diff --git a/MiniC/README-codegen.md b/MiniC/README-codegen.md index e6923a0..e9d29bd 100644 --- a/MiniC/README-codegen.md +++ b/MiniC/README-codegen.md @@ -3,24 +3,19 @@ LAB4 (simple code generation), MIF08 / CAP 2022-23 # Authors -YOUR NAME HERE +Augustin LUCAS # Contents -TODO for STUDENTS : Say a bit about the code infrastructure ... - # Test design -TODO: explain your tests - # Design choices -TODO: explain your choices. How did you implement boolean not? Did you implement an extension? +Booleans are implemented as integers behind the scenes, but type-checking before compilation disables any casting mechanism. +As for the previous lab, the Fortran-like for-loop extension has been implemented. # Known bugs -TODO: Bugs and limitations. - # Checklists A check ([X]) means that the feature is implemented @@ -28,30 +23,30 @@ and *tested* with appropriate test cases. ## Code generation -- [ ] Number Atom -- [ ] Boolean Atom -- [ ] Id Atom -- [ ] Additive expression -- [ ] Multiplicative expression -- [ ] UnaryMinus expression -- [ ] Or expression -- [ ] And expression -- [ ] Equality expression -- [ ] Relational expression (! many cases -> many tests) -- [ ] Not expression +- [x] Number Atom +- [x] Boolean Atom +- [x] Id Atom +- [x] Additive expression +- [x] Multiplicative expression +- [x] UnaryMinus expression +- [x] Or expression +- [x] And expression +- [x] Equality expression +- [x] Relational expression (! many cases -> many tests) +- [x] Not expression ## Statements -- [ ] Prog, assignements -- [ ] While -- [ ] Cond Block -- [ ] If -- [ ] Nested ifs -- [ ] Nested whiles +- [x] Prog, assignements +- [x] While +- [x] Cond Block +- [x] If +- [x] Nested ifs +- [x] Nested whiles ## Allocation -- [ ] Naive allocation -- [ ] All in memory allocation +- [x] Naive allocation +- [x] All in memory allocation - [ ] Massive tests of memory allocation diff --git a/MiniC/TP04/AllInMemAllocator.py b/MiniC/TP04/AllInMemAllocator.py index 7b08b30..0873e24 100644 --- a/MiniC/TP04/AllInMemAllocator.py +++ b/MiniC/TP04/AllInMemAllocator.py @@ -15,19 +15,21 @@ class AllInMemAllocator(Allocator): after: List[Instruction] = [] new_args: List[Operand] = [] - s_index = 0 - for arg in old_instr.args(): + for arg in old_instr.defined(): if isinstance(arg, Temporary): - s_index += 1 - if arg in old_instr.used(): # needs to be read first - before.append(RiscV.ld( - S[s_index], arg.get_alloced_loc() - )) - if arg in old_instr.defined(): # needs to be stored after - after.append(RiscV.sd( - S[s_index], arg.get_alloced_loc() - )) - new_args.append(S[s_index]) + after.append(RiscV.sd( + S[3], arg.get_alloced_loc() + )) + new_args.append(S[3]) + else: + new_args.append(arg) + + for i, arg in enumerate(old_instr.used(), 1): + if isinstance(arg, Temporary): + before.append(RiscV.ld( + S[i], arg.get_alloced_loc() + )) + new_args.append(S[i]) else: new_args.append(arg) diff --git a/MiniC/TP04/MiniCCodeGen3AVisitor.py b/MiniC/TP04/MiniCCodeGen3AVisitor.py index e211d90..e2ca2f0 100644 --- a/MiniC/TP04/MiniCCodeGen3AVisitor.py +++ b/MiniC/TP04/MiniCCodeGen3AVisitor.py @@ -283,7 +283,7 @@ class MiniCCodeGen3AVisitor(MiniCVisitor): print(Trees.toStringTree(ctx.stat_block(), [], self._parser)) # ltest <- fresh_label() - loop_test = self._current_function.fdata.fresh_label("loop_test") + loop_test = self._current_function.fdata.fresh_label("while_test") # lendwhile <- fresh_label() end_while = self._current_function.fdata.fresh_label("end_while") # code.addLabel(ltest) @@ -329,3 +329,79 @@ class MiniCCodeGen3AVisitor(MiniCVisitor): for stat in ctx.stat(): self._current_function.add_comment(Trees.toStringTree(stat, [], self._parser)) self.visit(stat) + + def visitForStat(self, ctx) -> None: + def immediate_to_tmp(op): + if not isinstance(op, Operands.Immediate): + return op + new_op = self._current_function.fdata.fresh_tmp() + self._current_function.add_instruction( + RiscV.li(new_op, op)) + return new_op + + + from_t = immediate_to_tmp(self.visit(ctx.expr(0))) + to_t = immediate_to_tmp(self.visit(ctx.expr(1))) + + stride = Operands.Immediate(1) + if len(ctx.expr()) > 2: + stride = self.visit(ctx.expr(2)) + + stride = immediate_to_tmp(stride) + + name = ctx.ID().getText() + if name not in self._symbol_table: + raise MiniCInternalError( + "Variable {} has not been declared before for loop".format(name)) + + variable = self._symbol_table[name] # variable acting as counter + for_test = self._current_function.fdata.fresh_label("forF_test") + end_for = self._current_function.fdata.fresh_label("end_forF") + body_for = self._current_function.fdata.fresh_label("body_forF") + neg_stride = self._current_function.fdata.fresh_label("neg_stride_forF") + counter = self._current_function.fdata.fresh_tmp() # real counter not affected by var. changes + + # counter <- from + self._current_function.add_instruction( + RiscV.mv(counter, from_t)) + #* for_test: + # var <- counter + # bge 0 stride neg_stride + # (positive stride here) + # ble counter to end_for + # j body + self._current_function.add_label(for_test) + self._current_function.add_instruction( + RiscV.mv(variable, counter)) + self._current_function.add_instruction( + RiscV.conditional_jump( + neg_stride, Operands.ZERO, + Condition(MiniCParser.GTEQ), stride + )) + self._current_function.add_instruction( + RiscV.conditional_jump( + end_for, counter, + Condition(MiniCParser.GTEQ), to_t + )) + self._current_function.add_instruction( + RiscV.jump(body_for)) + #* neg_stride: + # bl to counter end_for + self._current_function.add_label(neg_stride) + self._current_function.add_instruction( + RiscV.conditional_jump( + end_for, to_t, + Condition(MiniCParser.GTEQ), counter + )) + #* body: + # + # counter <- counter + stride + # j for_test + self._current_function.add_label(body_for) + self.visit(ctx.stat_block()) + self._current_function.add_instruction( + RiscV.add(counter, counter, stride)) + self._current_function.add_instruction( + RiscV.jump(for_test)) + #* end_for: + self._current_function.add_label(end_for) diff --git a/MiniC/TP04/tests/students/base/test_add_boolean.c b/MiniC/TP04/tests/students/base/test_add_boolean.c new file mode 100644 index 0000000..ada0d2b --- /dev/null +++ b/MiniC/TP04/tests/students/base/test_add_boolean.c @@ -0,0 +1,10 @@ +#include "printlib.h" + +int main() { + println_bool(true + false); + return 0; +} + +// EXITCODE 2 +// EXPECTED +// In function main: Line 4 col 15: invalid type for additive operands: boolean and boolean diff --git a/MiniC/TP04/tests/students/base/test_comp_bool.c b/MiniC/TP04/tests/students/base/test_comp_bool.c new file mode 100644 index 0000000..e7f2214 --- /dev/null +++ b/MiniC/TP04/tests/students/base/test_comp_bool.c @@ -0,0 +1,16 @@ +#include "printlib.h" + +int main() { + bool x, y; + + if (x <= y) { + println_string("ok"); + } + + return 0; +} + +// SKIP TEST EXPECTED +// EXITCODE 2 +// EXPECTED +// In function main: Line 6 col 6: invalid type for non numeric type: boolean \ No newline at end of file diff --git a/MiniC/TP04/tests/students/base/test_div_0.c b/MiniC/TP04/tests/students/base/test_div_0.c new file mode 100644 index 0000000..fc1d200 --- /dev/null +++ b/MiniC/TP04/tests/students/base/test_div_0.c @@ -0,0 +1,14 @@ +#include "printlib.h" + +int main() { + int x, y; + x = 5; + y = 0; + println_int(x/0); + return 0; +} + +// SKIP TEST EXPECTED +// EXECCODE 1 +// EXPECTED +// Division by 0 diff --git a/MiniC/TP04/tests/students/base/test_else.c b/MiniC/TP04/tests/students/base/test_else.c new file mode 100644 index 0000000..eb23197 --- /dev/null +++ b/MiniC/TP04/tests/students/base/test_else.c @@ -0,0 +1,15 @@ +#include "printlib.h" + +int main() { + int x, y; + if (x != 0) { + y = 12; + } else { + y = -3; + } + println_int(y); + return 0; +} + +// EXPECTED +// -3 diff --git a/MiniC/TP04/tests/students/base/test_fibonacci.c b/MiniC/TP04/tests/students/base/test_fibonacci.c new file mode 100644 index 0000000..515f8b3 --- /dev/null +++ b/MiniC/TP04/tests/students/base/test_fibonacci.c @@ -0,0 +1,27 @@ +#include "printlib.h" + +int main() { + int num, result, i; + int prev1, prev2, tmp; + result = -1; + num = 15; + + if (num < 2) { + result = num; + } else { + prev1 = 1; + prev2 = 0; + for i=2 to num { + tmp = prev1; + prev1 = prev1 + prev2; + prev2 = tmp; + } + result = prev1+prev2; + } + println_int(result); + return 0; +} + +// SKIP TEST EXPECTED +// EXPECTED +// 610 diff --git a/MiniC/TP04/tests/students/base/test_if_nonbool.c b/MiniC/TP04/tests/students/base/test_if_nonbool.c new file mode 100644 index 0000000..3f9bde0 --- /dev/null +++ b/MiniC/TP04/tests/students/base/test_if_nonbool.c @@ -0,0 +1,16 @@ +#include "printlib.h" + +int main() { + int x, y; + + if (x) { + y = 5; + } + println_int(y); + return 0; +} + +// SKIP TEST EXPECTED +// EXITCODE 2 +// EXPECTED +// In function main: Line 6 col 2: invalid type for non boolean as condition: integer diff --git a/MiniC/TP04/tests/students/base/test_mem_alloc.c b/MiniC/TP04/tests/students/base/test_mem_alloc.c new file mode 100644 index 0000000..2d645b8 --- /dev/null +++ b/MiniC/TP04/tests/students/base/test_mem_alloc.c @@ -0,0 +1,15 @@ +#include "printlib.h" + +int main() { + int x; + int y; + while (x < 5000) { + y = x+1; + x = y+1; + } + println_int(x); + return 0; +} + +// EXPECTED +// 5000 diff --git a/MiniC/TP04/tests/students/base/test_mod.c b/MiniC/TP04/tests/students/base/test_mod.c new file mode 100644 index 0000000..a4b760f --- /dev/null +++ b/MiniC/TP04/tests/students/base/test_mod.c @@ -0,0 +1,19 @@ +#include "printlib.h" + +int main() { + int x, y; + x = 5; + y = 3; + println_int(x%y); + println_int((-x)%y); + y = 0; + println_int(x%y); + return 0; +} + +// SKIP TEST EXPECTED +// EXECCODE 1 +// EXPECTED +// 2 +// -2 +// Division by 0 diff --git a/MiniC/TP04/tests/students/base/test_mul.c b/MiniC/TP04/tests/students/base/test_mul.c new file mode 100644 index 0000000..d8c9c63 --- /dev/null +++ b/MiniC/TP04/tests/students/base/test_mul.c @@ -0,0 +1,12 @@ +#include "printlib.h" + +int main() { + int x, y; + x = 12; + y = 5; + println_int(x*y); + return 0; +} + +// EXPECTED +// 60 diff --git a/MiniC/TP04/tests/students/base/test_nested_if.c b/MiniC/TP04/tests/students/base/test_nested_if.c new file mode 100644 index 0000000..f5e865e --- /dev/null +++ b/MiniC/TP04/tests/students/base/test_nested_if.c @@ -0,0 +1,33 @@ +#include "printlib.h" + +int main() { + if (true) { + if (false) { + println_int(-1); + } else { + println_int(1); + } + } else { + println_int(-1); + } + + if (false) { + if (false) { + println_int(-1); + } else { + println_int(-1); + } + } else { + if (true) { + println_int(2); + } else { + println_int(-1); + } + + } + return 0; +} + +// EXPECTED +// 1 +// 2 diff --git a/MiniC/TP04/tests/students/base/test_nested_while.c b/MiniC/TP04/tests/students/base/test_nested_while.c new file mode 100644 index 0000000..91ca297 --- /dev/null +++ b/MiniC/TP04/tests/students/base/test_nested_while.c @@ -0,0 +1,25 @@ +#include "printlib.h" + +int main() { + int x, y, z; + while (x < 12) { + while (x < 25) { + x = x+2; + } + } + println_int(x); + x = 0; + while (x < 5) { + x = x+1; + y = y+x; + while (z < 3) { + z = z+y; + } + } + println_int(z); + return 0; +} + +// EXPECTED +// 26 +// 3 diff --git a/MiniC/TP04/tests/students/base/test_not.c b/MiniC/TP04/tests/students/base/test_not.c new file mode 100644 index 0000000..0ff0c82 --- /dev/null +++ b/MiniC/TP04/tests/students/base/test_not.c @@ -0,0 +1,14 @@ +#include "printlib.h" + +int main() { + bool x, y; + x = true; + y = false; + println_bool(!x); + println_bool(!y); + return 0; +} + +// EXPECTED +// 0 +// 1 diff --git a/MiniC/TP04/tests/students/base/test_not_int.c b/MiniC/TP04/tests/students/base/test_not_int.c new file mode 100644 index 0000000..277d6cf --- /dev/null +++ b/MiniC/TP04/tests/students/base/test_not_int.c @@ -0,0 +1,11 @@ +#include "printlib.h" + +int main() { + println_int(!(12+2)); + return 0; +} + +// SKIP TEST EXPECTED +// EXITCODE 2 +// EXPECTED +// In function main: Line 4 col 14: invalid type for NOT: only boolean allowed: integer diff --git a/MiniC/TP04/tests/students/base/test_or.c b/MiniC/TP04/tests/students/base/test_or.c new file mode 100644 index 0000000..5dee194 --- /dev/null +++ b/MiniC/TP04/tests/students/base/test_or.c @@ -0,0 +1,12 @@ +#include "printlib.h" + +int main() { + bool x, y; + x = true; + y = false; + println_bool(x || y); + return 0; +} + +// EXPECTED +// 1 diff --git a/MiniC/TP04/tests/students/base/test_println_bool.c b/MiniC/TP04/tests/students/base/test_println_bool.c new file mode 100644 index 0000000..1960ef7 --- /dev/null +++ b/MiniC/TP04/tests/students/base/test_println_bool.c @@ -0,0 +1,14 @@ +#include "printlib.h" + +int main() { + int x, y; + + println_bool(true); + println_bool(y+2); + return 0; +} + +// SKIP TEST EXPECTED +// EXITCODE 2 +// EXPECTED +// In function main: Line 7 col 2: invalid type for println_bool statement: integer diff --git a/MiniC/TP04/tests/students/base/test_println_float.c b/MiniC/TP04/tests/students/base/test_println_float.c new file mode 100644 index 0000000..946f84a --- /dev/null +++ b/MiniC/TP04/tests/students/base/test_println_float.c @@ -0,0 +1,14 @@ +#include "printlib.h" + +int main() { + int x, y; + + println_float(15.0); + println_float(y+2); + return 0; +} + +// SKIP TEST EXPECTED +// EXITCODE 2 +// EXPECTED +// In function main: Line 7 col 2: invalid type for println_float statement: integer diff --git a/MiniC/TP04/tests/students/base/test_relational.c b/MiniC/TP04/tests/students/base/test_relational.c new file mode 100644 index 0000000..170ec8a --- /dev/null +++ b/MiniC/TP04/tests/students/base/test_relational.c @@ -0,0 +1,35 @@ +#include "printlib.h" + +int main() { + println_bool(1 < 2); + println_bool(1 < 1); + println_bool(2 < 1); + + println_bool(1 <= 2); + println_bool(1 <= 1); + println_bool(2 <= 1); + + println_bool(1 > 2); + println_bool(1 > 1); + println_bool(2 > 1); + + println_bool(1 >= 2); + println_bool(1 >= 1); + println_bool(2 >= 1); + + return 0; +} + +// EXPECTED +// 1 +// 0 +// 0 +// 1 +// 1 +// 0 +// 0 +// 0 +// 1 +// 0 +// 1 +// 1 diff --git a/MiniC/TP04/tests/students/base/test_while.c b/MiniC/TP04/tests/students/base/test_while.c new file mode 100644 index 0000000..f8e80a2 --- /dev/null +++ b/MiniC/TP04/tests/students/base/test_while.c @@ -0,0 +1,13 @@ +#include "printlib.h" + +int main() { + int x; + while (x < 12) { + x = x+2; + } + println_int(x); + return 0; +} + +// EXPECTED +// 12 diff --git a/MiniC/TP04/tests/students/base/test_while_nonbool.c b/MiniC/TP04/tests/students/base/test_while_nonbool.c new file mode 100644 index 0000000..b65726a --- /dev/null +++ b/MiniC/TP04/tests/students/base/test_while_nonbool.c @@ -0,0 +1,17 @@ +#include "printlib.h" + +int main() { + int x, y; + + while (x) { + y = 5; + x = x+1; + } + println_int(y); + return 0; +} + +// SKIP TEST EXPECTED +// EXITCODE 2 +// EXPECTED +// In function main: Line 6 col 2: invalid type for non boolean as condition: integer diff --git a/MiniC/TP04/tests/students/ext-for-fortran/test_for.c b/MiniC/TP04/tests/students/ext-for-fortran/test_for.c new file mode 100644 index 0000000..2aa7fa2 --- /dev/null +++ b/MiniC/TP04/tests/students/ext-for-fortran/test_for.c @@ -0,0 +1,32 @@ +#include "printlib.h" + +int main() { + int x, y; + int zero, trois; + trois = 3; + + // simple loop + for x=zero to trois { + y = y+3; + } + println_int(y); + println_int(x); + + // inversed loop + for x=5 to 1 by -2 { + println_int(x); + } + + // empty loop + for x=5 to 0 { + println_int(-1); + } + return 0; +} + +// SKIP TEST EXPECTED +// EXPECTED +// 9 +// 3 +// 5 +// 3 diff --git a/MiniC/TP04/tests/students/ext-for-fortran/test_imbricated_for.c b/MiniC/TP04/tests/students/ext-for-fortran/test_imbricated_for.c new file mode 100644 index 0000000..e95ced6 --- /dev/null +++ b/MiniC/TP04/tests/students/ext-for-fortran/test_imbricated_for.c @@ -0,0 +1,18 @@ +#include "printlib.h" + +int main() { + int i, count; + + for i=0 to 6 { + for i=0 to 6 { + count = count + 1; + } + } + println_int(count); + + return 0; +} + +// SKIP TEST EXPECTED +// EXPECTED +// 36 diff --git a/MiniC/TP04/tests/students/ext-for-fortran/test_invalid_from.c b/MiniC/TP04/tests/students/ext-for-fortran/test_invalid_from.c new file mode 100644 index 0000000..7f34bfb --- /dev/null +++ b/MiniC/TP04/tests/students/ext-for-fortran/test_invalid_from.c @@ -0,0 +1,17 @@ +#include "printlib.h" + +int main() { + int x, y; + float fl; + fl = 12.0; + + for x=fl to 3 { + y = y+3; + } + return 0; +} + +// SKIP TEST EXPECTED +// EXITCODE 2 +// EXPECTED +// In function main: Line 8 col 2: invalid type for non-integer from value: float diff --git a/MiniC/TP04/tests/students/ext-for-fortran/test_invalid_id.c b/MiniC/TP04/tests/students/ext-for-fortran/test_invalid_id.c new file mode 100644 index 0000000..dfc5f42 --- /dev/null +++ b/MiniC/TP04/tests/students/ext-for-fortran/test_invalid_id.c @@ -0,0 +1,17 @@ +#include "printlib.h" + +int main() { + int x, y; + float fl; + fl = 12.0; + + for fl=0 to 3 { + y = y+3; + } + return 0; +} + +// SKIP TEST EXPECTED +// EXITCODE 2 +// EXPECTED +// In function main: Line 8 col 2: invalid type for non-integer for loop counter: float diff --git a/MiniC/TP04/tests/students/ext-for-fortran/test_invalid_stride.c b/MiniC/TP04/tests/students/ext-for-fortran/test_invalid_stride.c new file mode 100644 index 0000000..880c506 --- /dev/null +++ b/MiniC/TP04/tests/students/ext-for-fortran/test_invalid_stride.c @@ -0,0 +1,15 @@ +#include "printlib.h" + +int main() { + int x, y; + + for x=0 to 3 by 1.0 { + y = y+3; + } + return 0; +} + +// SKIP TEST EXPECTED +// EXITCODE 2 +// EXPECTED +// In function main: Line 6 col 2: invalid type for non-integer stride value: float diff --git a/MiniC/TP04/tests/students/ext-for-fortran/test_invalid_to.c b/MiniC/TP04/tests/students/ext-for-fortran/test_invalid_to.c new file mode 100644 index 0000000..05c910c --- /dev/null +++ b/MiniC/TP04/tests/students/ext-for-fortran/test_invalid_to.c @@ -0,0 +1,17 @@ +#include "printlib.h" + +int main() { + int x, y; + float fl; + fl = 12.0; + + for x=0 to fl { + y = y+3; + } + return 0; +} + +// SKIP TEST EXPECTED +// EXITCODE 2 +// EXPECTED +// In function main: Line 8 col 2: invalid type for non-integer to value: float diff --git a/MiniC/TP04/tests/students/ext-for-fortran/test_undefined_id.c b/MiniC/TP04/tests/students/ext-for-fortran/test_undefined_id.c new file mode 100644 index 0000000..722193d --- /dev/null +++ b/MiniC/TP04/tests/students/ext-for-fortran/test_undefined_id.c @@ -0,0 +1,15 @@ +#include "printlib.h" + +int main() { + int x, y; + + for undef=0 to 3 { + y = y+3; + } + return 0; +} + +// SKIP TEST EXPECTED +// EXITCODE 2 +// EXPECTED +// In function main: Line 6 col 2: Undefined variable undef