diff --git a/tests/fixtures/unsigned_calcs.c b/tests/fixtures/unsigned_calcs.c new file mode 100644 index 0000000..89b1735 --- /dev/null +++ b/tests/fixtures/unsigned_calcs.c @@ -0,0 +1,25 @@ +#include + +long foo(unsigned); +long foo(unsigned int a) { return a; } + +int main() { + printf("%ld\n", foo((unsigned short)-1)); + + unsigned int c = 2147483649; + int d = 2000; + int s = d + c; + printf("%d\n", c); + printf("%d\n", s); + + unsigned long i = 999999u * 9999999 * 999999; + unsigned long l = -9223372036854775808u + 1; + printf("%lu\n", i); + printf("%lu\n", l); + + int eq = 18446744073709551615u == 18446744073709551615ll; + printf("%d\n", eq); + + unsigned char n = 372897938; + printf("%ld\n", (long)n); +} diff --git a/tests/snapshots/success_unsigned_calcs b/tests/snapshots/success_unsigned_calcs new file mode 100644 index 0000000..8f74c1c --- /dev/null +++ b/tests/snapshots/success_unsigned_calcs @@ -0,0 +1,7 @@ +65535 +-2147483647 +-2147481647 +420793087 +9223372036854775809 +1 +146 diff --git a/wrecc_compiler/src/compiler/codegen/mod.rs b/wrecc_compiler/src/compiler/codegen/mod.rs index 98ee26c..67a9125 100644 --- a/wrecc_compiler/src/compiler/codegen/mod.rs +++ b/wrecc_compiler/src/compiler/codegen/mod.rs @@ -1023,6 +1023,16 @@ impl Compiler { if value_reg.get_type().size() < 4 { self.write_out(Lir::Movz(value_reg.clone(), dest_reg.clone())); } else { + // convert registers since otherwise will read memory that isnt + // that doesnt belong to value_reg: casting unsigned int to long + // int a: -4(%rbp), 4 bytes allocate + // `movq -4(%rbp), %r10`, would read 8 bytes + value_reg = convert_reg!( + self, + value_reg, + Register::Temp(..) | Register::Stack(..) | Register::Label(..) + ); + value_reg.set_type(new_type); self.write_out(Lir::Mov(value_reg.clone(), dest_reg.clone())) } diff --git a/wrecc_compiler/src/compiler/typechecker/fold.rs b/wrecc_compiler/src/compiler/typechecker/fold.rs index 17fc2a0..b5d9e39 100644 --- a/wrecc_compiler/src/compiler/typechecker/fold.rs +++ b/wrecc_compiler/src/compiler/typechecker/fold.rs @@ -722,6 +722,7 @@ mod tests { "(unsigned)420793087", "unsigned int", ); + assert_fold_type("999999u * 9999999 * 999999", "420793087u", "unsigned int"); assert_fold_error!( "999999 * 9999999 * 999999", ErrorKind::IntegerOverflow(QualType { @@ -787,5 +788,6 @@ mod tests { assert_fold("(short *)1 + -5", "(short*)-9"); assert_fold("(int*)1 + -9223372036854775807", "(int*)5"); assert_fold_error!("(int*)1 + -9223372036854775808", ErrorKind::ScaleOverflow); + assert_fold_error!("(int*)1 - 9223372036854775809ul", ErrorKind::ScaleOverflow); } } diff --git a/wrecc_compiler/src/compiler/typechecker/mod.rs b/wrecc_compiler/src/compiler/typechecker/mod.rs index 856f358..a0d4b86 100644 --- a/wrecc_compiler/src/compiler/typechecker/mod.rs +++ b/wrecc_compiler/src/compiler/typechecker/mod.rs @@ -2614,6 +2614,8 @@ mod tests { assert_type!("(void*)1 == a", "int", "long* a;"); assert_type!("0 == a", "int", "long* a;"); assert_type!("a == 0", "int", "int* a;"); + assert_type!("a == 2l", "int", "unsigned int a;"); + assert_type!("a == 2lu", "int", "int a;"); assert_type_err!("1 == a", ErrorKind::InvalidComp(..), "long *a;"); assert_type_err!("a == b", ErrorKind::InvalidComp(..), "int *a; long *b;");