diff --git a/include/codegen.hpp b/include/codegen.hpp index caa442301e8fd664704c71d5b5f8b8dbe7f6d161..a78f5d47496564b40d3844104004ace997f1cf80 100644 --- a/include/codegen.hpp +++ b/include/codegen.hpp @@ -3,6 +3,7 @@ #include "BasicBlock.h" #include "Function.h" +#include "IRprinter.h" #include "Instruction.h" #include "Module.h" #include "Value.h" @@ -10,6 +11,7 @@ #include #include +#include #define ALIGN(x, align) (((x / align) + (x % align ? 1 : 0)) * align) // #define STACK_ALIGN(x) (((x / 16) + (x % 16 ? 1 : 0)) * 16) @@ -36,16 +38,17 @@ class CodeGen { void run(); private: + void IR2assem(Instruction &, BasicBlock &); void IR2assem(LoadInst *); void IR2assem(StoreInst *); void IR2assem(ReturnInst *); - void IR2assem(Instruction &); void IR2assem(GetElementPtrInst *); void IR2assem(CallInst *); void IR2assem(BranchInst *); void IR2assem(BinaryInst *); void IR2assem(FpToSiInst *); void IR2assem(SiToFpInst *); + void IR2assem(PhiInst *) {} // The Instructions below will do nothing void IR2assem(AllocaInst *) {} // integration with BranchInst @@ -53,8 +56,6 @@ class CodeGen { void IR2assem(FCmpInst *) {} void IR2assem(ZextInst *) {} - void IR2assem(PhiInst *) {} - void stackMemAlloc(); void stackMemDealloc(); // load value `opk` to the specified register @@ -68,6 +69,17 @@ class CodeGen { void ptrContent2reg(Value *, int id = 0); void compute_arg_info(Function *); string bool2branch(Instruction *); + void getPhiMap(); + void copystmt(BasicBlock *bb) { + // all the phi instruction is transformed to copy-stmt + for (auto © : phi_map[bb]) { + output.push_back("# " + print_as_op(copy.first, false) + " = " + + print_as_op(copy.second, false)); + auto lvalue = static_cast(copy.first); + value2reg(copy.second); + back2stack(lvalue); + } + } string label_in_assem(BasicBlock *bb) { return cur_func->get_name() + bb->get_name().substr(5); @@ -130,7 +142,8 @@ class CodeGen { std::map off; // stack offset to $fp std::map> func_arg_off; // to $sp std::map func_arg_N; // total space for args - unsigned int stackN; // function local vars and so on + std::map>> phi_map; + unsigned int stackN; // function local vars and so on Function *cur_func; diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp index af70028f65dce5f8f9770ba8e8f8e2b6b1532835..8e522752e5c66b631e2ffe7d0e66eb4a57b03b78 100644 --- a/src/codegen/codegen.cpp +++ b/src/codegen/codegen.cpp @@ -6,6 +6,7 @@ #include "codegen.hpp" +#include "BasicBlock.h" #include "Constant.h" #include "Function.h" #include "GlobalVariable.h" @@ -16,6 +17,7 @@ #include #include #include +#include // $r0 $zero constant 0 // $r1 $ra return address @@ -55,11 +57,29 @@ class Reg { } }; +void +CodeGen::getPhiMap() { + phi_map.clear(); + for (auto &func : m->get_functions()) + for (auto &bb : func.get_basic_blocks()) + for (auto &instr : bb.get_instructions()) { + if (not instr.is_phi()) + continue; + for (int i = 0; i < instr.get_num_operand() / 2; i++) { + auto key = + static_cast(instr.get_operand(2 * i + 1)); + auto value = + std::make_pair(&instr, instr.get_operand(2 * i)); + phi_map[key].push_back(value); + } + } +} + void CodeGen::run() { // TODO: implement // 以下内容生成 int main() { return 0; } 的汇编代码 - + getPhiMap(); output.push_back(".text"); // global variables for (auto &globl : m->get_global_variable()) { @@ -86,14 +106,11 @@ CodeGen::run() { for (auto &bb : func.get_basic_blocks()) { output.push_back(label_in_assem(&bb) + ":"); for (auto &instr : bb.get_instructions()) { - IR2assem(instr); + IR2assem(instr, bb); } } // restore the stack stackMemDealloc(); - } else { - /* output.push_back(".globl " + func.get_name()); - * output.push_back(".type " + func.get_name() + ", @function"); */ } } } @@ -429,7 +446,9 @@ CodeGen::IR2assem(ReturnInst *instr) { } void -CodeGen::IR2assem(Instruction &instr) { +CodeGen::IR2assem(Instruction &instr, BasicBlock &bb) { + if (instr.is_br() or instr.is_ret()) + copystmt(&bb); output.push_back("# " + instr.print()); switch (instr.get_instr_type()) { case Instruction::ret: @@ -488,6 +507,6 @@ CodeGen::IR2assem(Instruction &instr) { } // assert(false && "This ") if (not instr.is_void() and not no_stack_alloca(&instr) and - not instr.is_alloca()) + not instr.is_alloca() and not instr.is_phi()) back2stack(&instr); } diff --git a/tests/5-bonus/test_time.py b/tests/5-bonus/test_time.py index 7f8b062a84a7823d441b933ae9c3825c899cd549..de3cdd47012a6220b58312030caffb77ca333a7f 100644 --- a/tests/5-bonus/test_time.py +++ b/tests/5-bonus/test_time.py @@ -40,7 +40,7 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False): single_begin = timeit.default_timer() testfiles = os.listdir(testfile_dir) - testfiles.sort() + # testfiles.sort() # 过滤出以.cminus结尾的file testfiles = filter(lambda s: s.endswith('.cminus'), testfiles) testfiles = list(testfiles) @@ -68,7 +68,7 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False): if not use_clang: try: # ===可修改=== - compile_res = subprocess.run([cminus, filepath, '-mem2reg', '-S', 'a.s'], + compile_res = subprocess.run([cminus, filepath, '-S', 'a.s'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=300) @@ -126,7 +126,7 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False): # 记录运行时间 start = timeit.default_timer() - for i in range(10): + for _ in range(10): exe_res = subprocess.run(['./a.out'], input=input_option, stdout=subprocess.PIPE, @@ -140,7 +140,7 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False): continue except Exception as e: output_file.write('executable runtime error\n') - output_file.write(str(e)) + output_file.write(str(e) + '\n') failed_count += 1 continue @@ -166,8 +166,8 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False): # 因为退出码也会作为输出的一部分,因此输出和答案不同可能是程序崩溃造成的 output_file.write( 'output is different from standard answer, this may be caused by wrong return code\n') - output_file.write(f"\t{ref=}") - output_file.write(f"\t{actual=}") + output_file.write("\t" + ref + "\n") + output_file.write("\t" + actual + "\n") failed_count += 1 output_file.write(f"{failed_count} tests failed\n")