Skip to content

Commit

Permalink
implemented short type
Browse files Browse the repository at this point in the history
  • Loading branch information
PhilippRados committed Apr 20, 2024
1 parent b569edc commit c7035f8
Show file tree
Hide file tree
Showing 12 changed files with 71 additions and 25 deletions.
2 changes: 1 addition & 1 deletion fuzzer/inputs/expr.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
int a = 2147483649 * 3 << +2 + a % (2) + (int)'d';
short a = 217 - 3 & +2 % (2) + (short)'d';

int main() { return a; }
4 changes: 2 additions & 2 deletions fuzzer/inputs/header.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include <stdio.h>

int main() {
int a = 2;
printf("hello %d", a);
long a = 2;
printf("hello %ld", a);
}
9 changes: 8 additions & 1 deletion fuzzer/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
#[macro_use]
extern crate afl;
use std::collections::HashMap;
use std::path::Path;
use wrecc_compiler::*;

fn main() {
fuzz!(|data: &[u8]| {
if let Ok(s) = std::str::from_utf8(data) {
if let Ok(source) = preprocess(Path::new("./some.c"),&Vec::new(),&Vec::new(), s.to_string()) {
if let Ok(source) = preprocess(
Path::new("./some.c"),
&Vec::new(),
&Vec::new(),
&HashMap::new(),
s.to_string(),
) {
let _ = compile(source, false);
}
}
Expand Down
13 changes: 13 additions & 0 deletions tests/fixtures/short_type.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <stdio.h>

short int foo(int short s) { return 4 - s; }

int main() {
char c = sizeof((short int)5);
short int s = foo(9);
int short o = foo(3);
printf("%d", c);
printf("%d", s);
printf("%d", o);
printf("%ld", sizeof(s));
}
1 change: 1 addition & 0 deletions tests/snapshots/success_short_type
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2-512
19 changes: 10 additions & 9 deletions wrecc_compiler/src/compiler/codegen/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ use crate::compiler::typechecker::mir::expr::ValueKind;
use super::lir::maybe_prefix_underscore;

/// Registers used for passing arguments to functions
pub static ARG_REGS: &[[&str; 3]; 6] = &[
["%rdi", "%edi", "%dil"],
["%rsi", "%esi", "%sil"],
["%rdx", "%edx", "%dl"],
["%rcx", "%ecx", "%cl"],
["%r8", "%r8d", "%r8b"],
["%r9", "%r9d", "%r9b"],
pub static ARG_REGS: &[[&str; 4]; 6] = &[
["%rdi", "%edi", "%di", "%dil"],
["%rsi", "%esi", "%si", "%sil"],
["%rdx", "%edx", "%dx", "%dl"],
["%rcx", "%ecx", "%cx", "%cl"],
["%r8", "%r8d", "%r8w", "%r8b"],
["%r9", "%r9d", "%r9w", "%r9b"],
];

/// All possible operands to an instruction in [LIR](crate::compiler::codegen::lir)
Expand Down Expand Up @@ -376,7 +376,7 @@ impl ArgRegister {
#[derive(Debug, PartialEq, Clone)]
pub struct ArgRegisterKind {
in_use: bool,
names: [&'static str; 3],
names: [&'static str; 4],
}
impl ArgRegisterKind {
pub fn new(index: usize) -> Self {
Expand All @@ -389,7 +389,8 @@ impl ScratchRegister for ArgRegisterKind {
}
fn name(&self, type_decl: &Type) -> String {
match type_decl {
Type::Primitive(Primitive::Char) => self.names[2],
Type::Primitive(Primitive::Char) => self.names[3],
Type::Primitive(Primitive::Short) => self.names[2],
Type::Primitive(Primitive::Int) | Type::Enum(..) => self.names[1],
Type::Primitive(Primitive::Long) | Type::Pointer(_) | Type::Array { .. } => self.names[0],
_ => unimplemented!("aggregate types are not yet implemented as function args"),
Expand Down
8 changes: 6 additions & 2 deletions wrecc_compiler/src/compiler/common/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pub enum TokenKind {
Long,
Int,
Char,
Short,
Struct,
Union,
Enum,
Expand Down Expand Up @@ -196,6 +197,7 @@ impl Display for TokenKind {
TokenKind::Char => "'char'",
TokenKind::CharLit(_) => "'char'",
TokenKind::Int => "'int'",
TokenKind::Short => "'short'",
TokenKind::Long => "'long'",
TokenKind::Struct => "'struct'",
TokenKind::TypeDef => "'typedef'",
Expand Down Expand Up @@ -302,6 +304,7 @@ impl Token {
| TokenKind::Struct
| TokenKind::Void
| TokenKind::Char
| TokenKind::Short
| TokenKind::Int
| TokenKind::Long
)
Expand All @@ -328,9 +331,10 @@ impl PartialEq for Token {
impl Into<SpecifierKind> for Token {
fn into(self) -> SpecifierKind {
match self.kind {
TokenKind::Int => SpecifierKind::Int,
TokenKind::Char => SpecifierKind::Char,
TokenKind::Void => SpecifierKind::Void,
TokenKind::Char => SpecifierKind::Char,
TokenKind::Short => SpecifierKind::Short,
TokenKind::Int => SpecifierKind::Int,
TokenKind::Long => SpecifierKind::Long,
_ => unreachable!("token not specifier"),
}
Expand Down
19 changes: 14 additions & 5 deletions wrecc_compiler/src/compiler/common/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::compiler::parser::hir::expr::*;
use std::fmt::Display;
use std::rc::Rc;

static RETURN_REG: &[&str; 3] = &["%al", "%eax", "%rax"];
static RETURN_REG: &[&str; 4] = &["%al", "%ax", "%eax", "%rax"];

pub trait TypeInfo {
/// Returns size of type in bytes
Expand Down Expand Up @@ -248,6 +248,7 @@ impl Type {
pub fn maybe_wrap(&self, n: i64) -> Option<i64> {
match self {
Type::Primitive(Primitive::Char) => Some(n as i8 as i64),
Type::Primitive(Primitive::Short) => Some(n as i16 as i64),
Type::Primitive(Primitive::Int) | Type::Enum(..) => Some(n as i32 as i64),
Type::Pointer(_) | Type::Primitive(Primitive::Long) => Some(n),
_ => None,
Expand Down Expand Up @@ -282,6 +283,7 @@ pub struct FuncType {
pub enum Primitive {
Void,
Char,
Short,
Int,
Long,
}
Expand All @@ -292,6 +294,7 @@ impl TypeInfo for Primitive {
match self {
Primitive::Void => 0,
Primitive::Char => 1,
Primitive::Short => 2,
Primitive::Int => 4,
Primitive::Long => 8,
}
Expand All @@ -300,6 +303,7 @@ impl TypeInfo for Primitive {
String::from(match self {
Primitive::Void => unreachable!(),
Primitive::Char => "b",
Primitive::Short => "w",
Primitive::Int => "d",
Primitive::Long => "",
})
Expand All @@ -311,6 +315,7 @@ impl TypeInfo for Primitive {
String::from(match self {
Primitive::Void => "zero",
Primitive::Char => "byte",
Primitive::Short => "word",
Primitive::Int => "long",
Primitive::Long => "quad",
})
Expand All @@ -319,8 +324,9 @@ impl TypeInfo for Primitive {
String::from(match self {
Primitive::Void => unreachable!("doesnt have return register when returning void"),
Primitive::Char => RETURN_REG[0],
Primitive::Int => RETURN_REG[1],
Primitive::Long => RETURN_REG[2],
Primitive::Short => RETURN_REG[1],
Primitive::Int => RETURN_REG[2],
Primitive::Long => RETURN_REG[3],
})
}
}
Expand All @@ -329,6 +335,7 @@ impl Primitive {
match self {
Primitive::Void => "void",
Primitive::Char => "char",
Primitive::Short => "short",
Primitive::Int => "int",
Primitive::Long => "long",
}
Expand All @@ -338,6 +345,7 @@ impl Primitive {
match self {
Primitive::Void => unreachable!(),
Primitive::Char => i8::MAX as i64,
Primitive::Short => i16::MAX as i64,
Primitive::Int => i32::MAX as i64,
Primitive::Long => i64::MAX,
}
Expand All @@ -346,6 +354,7 @@ impl Primitive {
match self {
Primitive::Void => unreachable!(),
Primitive::Char => i8::MIN as i64,
Primitive::Short => i16::MIN as i64,
Primitive::Int => i32::MIN as i64,
Primitive::Long => i64::MIN,
}
Expand Down Expand Up @@ -623,7 +632,7 @@ pub mod tests {
assert_type_print("char *(**)", "char ***");

assert_type_print("char *(*)[3][4][2]", "char *(*)[3][4][2]");
assert_type_print("char (**[3][4])[2]", "char (**[3][4])[2]");
assert_type_print("short (**[3][4])[2]", "short (**[3][4])[2]");
assert_type_print("char (**(*)[4])[2]", "char (**(*)[4])[2]");
assert_type_print("char(**(*[3])[4])[2]", "char (**(*[3])[4])[2]");

Expand All @@ -645,6 +654,6 @@ pub mod tests {
"int (**(int *, char (*)()))[3]",
);

assert_type_print("int *(int**, ...)", "int *(int **, ...)");
assert_type_print("short *(short int**, ...)", "short *(short **, ...)");
}
}
2 changes: 2 additions & 0 deletions wrecc_compiler/src/compiler/parser/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,7 @@ mod tests {
assert_fold_type("2147483648 + (int*)1", "(int*)8589934593", "int*");

assert_fold_type("'a'", "'a'", "char");
assert_fold_type("'a' + (short)3", "100", "int");
assert_fold_type("-'a'", "-'a'", "int");
assert_fold_type("+'a'", "(int)'a'", "int");

Expand Down Expand Up @@ -685,6 +686,7 @@ mod tests {
);

assert_fold_type("(char)127 + 2", "129", "int");
assert_fold_type("(short)127 + 2", "129", "int");
assert_fold_type("2147483648 + 1", "2147483649", "long");
}

Expand Down
8 changes: 6 additions & 2 deletions wrecc_compiler/src/compiler/parser/hir/decl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ pub struct MemberDeclarator {
pub enum SpecifierKind {
Void,
Char,
Short,
Int,
Long,

Expand All @@ -75,9 +76,12 @@ impl SpecifierKind {
match self {
SpecifierKind::Void => 0,
SpecifierKind::Char => 1,
SpecifierKind::Int => 2,
SpecifierKind::Short => 2,
SpecifierKind::Long => 3,
_ => 4,
// int is last in specifier order because thats easier to read:
// eg: `short int` `long int`
SpecifierKind::Int => 4,
_ => 5,
}
}
}
Expand Down
1 change: 1 addition & 0 deletions wrecc_compiler/src/compiler/scanner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ impl<'a> Scanner<'a> {
("int", TokenKind::Int),
("long", TokenKind::Long),
("char", TokenKind::Char),
("short", TokenKind::Short),
("struct", TokenKind::Struct),
("union", TokenKind::Union),
("enum", TokenKind::Enum),
Expand Down
10 changes: 7 additions & 3 deletions wrecc_compiler/src/compiler/typechecker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ impl TypeChecker {
let mut specifier_kind_list: Vec<hir::decl::SpecifierKind> =
specifiers.into_iter().map(|spec| spec.kind).collect();

specifier_kind_list.sort_by_key(|spec| std::cmp::Reverse(spec.order()));
specifier_kind_list.sort_by_key(|spec| spec.order());

match specifier_kind_list.as_slice() {
[hir::decl::SpecifierKind::Struct(name, members)]
Expand All @@ -263,6 +263,10 @@ impl TypeChecker {

[hir::decl::SpecifierKind::Void] => Ok(Type::Primitive(Primitive::Void)),
[hir::decl::SpecifierKind::Char] => Ok(Type::Primitive(Primitive::Char)),
[hir::decl::SpecifierKind::Short]
| [hir::decl::SpecifierKind::Short, hir::decl::SpecifierKind::Int] => {
Ok(Type::Primitive(Primitive::Short))
}
[hir::decl::SpecifierKind::Int] => Ok(Type::Primitive(Primitive::Int)),
[hir::decl::SpecifierKind::Long]
| [hir::decl::SpecifierKind::Long, hir::decl::SpecifierKind::Int]
Expand Down Expand Up @@ -2559,8 +2563,8 @@ int a;";

#[test]
fn array_init_list() {
let actual = setup_init_list("int a[3] = {1,2};").unwrap();
let expected = vec![(0, "1", "int"), (4, "2", "int")];
let actual = setup_init_list("short a[3] = {1,2};").unwrap();
let expected = vec![(0, "1", "short"), (2, "2", "short")];

assert_init(actual, expected);
}
Expand Down

0 comments on commit c7035f8

Please sign in to comment.