Commit 83f09476 authored by lxq's avatar lxq

should pass the functional test

parent 33502fa9
......@@ -43,18 +43,17 @@ class CodeGen {
void IR2assem(GetElementPtrInst *);
void IR2assem(CallInst *);
void IR2assem(BranchInst *);
void IR2assem(BinaryInst *);
void IR2assem(FpToSiInst *);
void IR2assem(SiToFpInst *);
// The Instructions below will do nothing
void IR2assem(AllocaInst *) {}
// integration with BranchInst
void IR2assem(CmpInst *) {}
void IR2assem(FCmpInst *) {}
void IR2assem(ZextInst *) {}
void IR2assem(BinaryInst *);
void IR2assem(PhiInst *) {}
void IR2assem(FCmpInst *) {}
void IR2assem(FpToSiInst *) {}
void IR2assem(SiToFpInst *) {}
void stackMemAlloc();
void stackMemDealloc();
......@@ -63,7 +62,7 @@ class CodeGen {
// - for global variables and pointers from alloca and GEP, read through
// address
// only use register a_id and t_
void value2reg(Value *, int id = 0, bool is_float = false);
void value2reg(Value *, int id = 0);
// load the content in ptr to specified register.
// only use register a_id and t_
void ptrContent2reg(Value *, int id = 0);
......@@ -92,21 +91,27 @@ class CodeGen {
}
}
void back2stack(Instruction *instr, string reg = "$a0") {
// assert the value needed to store back is in $a0 or $f0, according to the
// value type
void back2stack(Instruction *instr) {
// std::cerr << instr->print() << std::endl;
string suff = suffix(typeLen(instr->get_type()));
auto type = instr->get_type();
string instr_ir = type->is_float_type() ? "fst" : "st";
string suff = suffix(type);
string reg = type->is_float_type() ? "$fa0" : "$a0";
string addr = "$fp, -" + std::to_string(off[instr]);
output.push_back("st" + suff + " " + reg + " " + addr);
output.push_back(instr_ir + suff + " " + reg + ", " + addr);
}
string suffix(int len) {
string suffix(Type *type) {
int len = typeLen(type);
switch (len) {
case 1:
return ".b";
case 2:
return ".h";
case 4:
return ".w";
return type->is_float_type() ? ".s" : ".w";
case 8:
return ".d";
}
......@@ -116,16 +121,16 @@ class CodeGen {
bool no_stack_alloca(Instruction *instr) {
if (instr->is_void())
return true;
if (instr->is_cmp() or instr->is_zext())
if (instr->is_fcmp() or instr->is_cmp() or instr->is_zext())
return true;
return false;
}
std::map<Value *, unsigned int> off; // 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 *, int> func_arg_N;
unsigned int stackN;
std::map<Function *, int> func_arg_N; // total space for args
unsigned int stackN; // function local vars and so on
Function *cur_func;
......
......@@ -17,13 +17,16 @@
using namespace std::literals::string_literals;
void print_help(std::string exe_name) {
void
print_help(std::string exe_name) {
std::cout << "Usage: " << exe_name
<< " [ -h | --help ] [ -o <target-file> ] [ -emit-llvm ] [-mem2reg] [-gvn] [-dump-json] <input-file>"
<< " [ -h | --help ] [ -o <target-file> ] [ -emit-llvm ] "
"[-mem2reg] [-gvn] [-dump-json] <input-file>"
<< std::endl;
}
int main(int argc, char **argv) {
int
main(int argc, char **argv) {
std::string target_path;
std::string input_path;
......@@ -36,9 +39,11 @@ int main(int argc, char **argv) {
if (argv[i] == "-h"s || argv[i] == "--help"s) {
print_help(argv[0]);
return 0;
} else if (argv[i] == "-o"s) {
} else if (argv[i] == "-o"s || argv[i] == "-S"s) {
if (target_path.empty() && i + 1 < argc) {
target_path = argv[i + 1];
if (target_path.rfind(".") != std::string::npos)
target_path = target_path.substr(0, target_path.rfind("."));
i += 1;
} else {
print_help(argv[0]);
......@@ -71,12 +76,13 @@ int main(int argc, char **argv) {
if (target_path.empty()) {
auto pos = input_path.rfind('.');
if (pos == std::string::npos) {
std::cerr << argv[0] << ": input file " << input_path << " has unknown filetype!" << std::endl;
std::cerr << argv[0] << ": input file " << input_path
<< " has unknown filetype!" << std::endl;
return -1;
} else {
// if (input_path.substr(pos) != ".cminus") {
// std::cerr << argv[0] << ": input file " << input_path << " has unknown filetype!" << std::endl;
// return -1;
// std::cerr << argv[0] << ": input file " << input_path << "
// has unknown filetype!" << std::endl; return -1;
// }
target_path = input_path.substr(0, pos);
}
......@@ -89,7 +95,8 @@ int main(int argc, char **argv) {
a.run_visitor(builder);
} catch (std::exception e) {
std::cout << "Exception catched:\n\t" << e.what() << std::endl;
std::cout << "Already generated IR code:\n" << builder.getModule()->print();
std::cout << "Already generated IR code:\n"
<< builder.getModule()->print();
return -1;
}
......@@ -104,7 +111,8 @@ int main(int argc, char **argv) {
if (gvn) {
PM.add_pass<DeadCode>(false); // remove some undef
PM.add_pass<GVN>(emit, dump_json);
PM.add_pass<DeadCode>(false); // delete unused instructions created by GVN
PM.add_pass<DeadCode>(
false); // delete unused instructions created by GVN
}
PM.run();
......@@ -132,7 +140,8 @@ int main(int argc, char **argv) {
lib_path.erase(lib_path.rfind('/'));
else
lib_path.clear();
auto cmd_str = "clang -O0 -w -no-pie "s + target_path + ".ll -o " + target_path + lib_path + " -lcminus_io";
auto cmd_str = "clang -O0 -w -no-pie "s + target_path + ".ll -o " +
target_path + lib_path + " -lcminus_io";
int re_code0 = std::system(cmd_str.c_str());
cmd_str = "rm "s + target_path + ".ll";
int re_code1 = std::system(cmd_str.c_str());
......
This diff is collapsed.
......@@ -6,7 +6,7 @@ import argparse
import subprocess
test_dir = os.path.dirname(os.path.abspath(__file__)) # 当前文件夹路径 tests/5-bonus
cminus = os.path.join(test_dir, '../../build/cminus') # ===可修改===
cminus = os.path.join(test_dir, '../../build/cminusfc') # ===可修改===
testfile_dir = os.path.join(test_dir, './testcases')
output_file_name = os.path.join(test_dir, './test_result')
io = os.path.join(test_dir, '../../src/io/io.c')
......@@ -56,7 +56,8 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
# 超时,跳过
if start_time - total_start > 30 * 60 or start_time - single_begin > 30 * 60:
output_file.write(f"[{count+1}/{test_count}] " + file_name + ': skipped due to exceeded total time limit\n')
output_file.write(f"[{count+1}/{test_count}] " + file_name +
': skipped due to exceeded total time limit\n')
continue
# 未超时
output_file.write(f"[{count+1}/{test_count}] " + file_name + ': ')
......@@ -75,8 +76,9 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
output_file.write('compile-1 timeout\n')
failed_count += 1
continue
except Exception:
except Exception as e:
output_file.write("compile-1 failed with an unexcept error\n")
output_file.write(str(e))
failed_count += 1
continue
......@@ -107,8 +109,9 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
output_file.write('compile timeout\n')
failed_count += 1
continue
except Exception:
except Exception as e:
output_file.write("compile failed with an unexcept error\n")
output_file.write(e)
failed_count += 1
continue
......@@ -135,8 +138,9 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
output_file.write("executable time limit exceeded\n")
failed_count += 1
continue
except Exception as _:
except Exception as e:
output_file.write('executable runtime error\n')
output_file.write(str(e))
failed_count += 1
continue
......@@ -159,8 +163,11 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
succ_count += 1
testtime[count] = time
else:
output_file.write('output is different from standard answer, this may be caused by wrong return code\n'
) # 因为退出码也会作为输出的一部分,因此输出和答案不同可能是程序崩溃造成的
# 因为退出码也会作为输出的一部分,因此输出和答案不同可能是程序崩溃造成的
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=}")
failed_count += 1
output_file.write(f"{failed_count} tests failed\n")
......@@ -172,9 +179,11 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
output_file.write('\t\t\tyour_cminus')
for count, file_name in enumerate(testfiles):
output_file.write('{:<20}'.format(file_name))
output_file.write('\t\t %.6f' % testtime[count] if testtime[count] != -1 else '\t\t None ')
output_file.write(
'\t\t %.6f' % testtime[count] if testtime[count] != -1 else '\t\t None ')
output_file.write("===================================================================\n")
output_file.write(
"===================================================================\n")
if __name__ == "__main__":
......@@ -182,8 +191,10 @@ if __name__ == "__main__":
parser = argparse.ArgumentParser(description="functional test")
parser.add_argument("--console", action="store_true", help="specify whether to output the result to console")
parser.add_argument("--clang", action="store_true", help="estimate runtime when compile with clang")
parser.add_argument("--console", action="store_true",
help="specify whether to output the result to console")
parser.add_argument("--clang", action="store_true",
help="estimate runtime when compile with clang")
args = parser.parse_args()
eval(args.console, testfile_dir, use_clang=args.clang)
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