Commit 7e736683 authored by lxq's avatar lxq

fix behaviour for PhiInst, now can pass functional test

parent 83f09476
......@@ -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 <map>
#include <ostream>
#include <vector>
#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 &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) {
return cur_func->get_name() + bb->get_name().substr(5);
......@@ -130,7 +142,8 @@ class CodeGen {
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 *, 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;
......
......@@ -6,6 +6,7 @@
#include "codegen.hpp"
#include "BasicBlock.h"
#include "Constant.h"
#include "Function.h"
#include "GlobalVariable.h"
......@@ -16,6 +17,7 @@
#include <cstdint>
#include <cstring>
#include <string>
#include <utility>
// $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<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
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);
}
......@@ -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")
......
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