Commit 7e736683 authored by lxq's avatar lxq

fix behaviour for PhiInst, now can pass functional test

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