Commit 83f09476 authored by lxq's avatar lxq

should pass the functional test

parent 33502fa9
...@@ -43,18 +43,17 @@ class CodeGen { ...@@ -43,18 +43,17 @@ class CodeGen {
void IR2assem(GetElementPtrInst *); void IR2assem(GetElementPtrInst *);
void IR2assem(CallInst *); void IR2assem(CallInst *);
void IR2assem(BranchInst *); void IR2assem(BranchInst *);
void IR2assem(BinaryInst *);
void IR2assem(FpToSiInst *);
void IR2assem(SiToFpInst *);
// The Instructions below will do nothing // The Instructions below will do nothing
void IR2assem(AllocaInst *) {} void IR2assem(AllocaInst *) {}
// integration with BranchInst // integration with BranchInst
void IR2assem(CmpInst *) {} void IR2assem(CmpInst *) {}
void IR2assem(FCmpInst *) {}
void IR2assem(ZextInst *) {} void IR2assem(ZextInst *) {}
void IR2assem(BinaryInst *);
void IR2assem(PhiInst *) {} void IR2assem(PhiInst *) {}
void IR2assem(FCmpInst *) {}
void IR2assem(FpToSiInst *) {}
void IR2assem(SiToFpInst *) {}
void stackMemAlloc(); void stackMemAlloc();
void stackMemDealloc(); void stackMemDealloc();
...@@ -63,7 +62,7 @@ class CodeGen { ...@@ -63,7 +62,7 @@ class CodeGen {
// - for global variables and pointers from alloca and GEP, read through // - for global variables and pointers from alloca and GEP, read through
// address // address
// only use register a_id and t_ // 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. // load the content in ptr to specified register.
// only use register a_id and t_ // only use register a_id and t_
void ptrContent2reg(Value *, int id = 0); void ptrContent2reg(Value *, int id = 0);
...@@ -92,21 +91,27 @@ class CodeGen { ...@@ -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; // 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]); 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) { switch (len) {
case 1: case 1:
return ".b"; return ".b";
case 2: case 2:
return ".h"; return ".h";
case 4: case 4:
return ".w"; return type->is_float_type() ? ".s" : ".w";
case 8: case 8:
return ".d"; return ".d";
} }
...@@ -116,16 +121,16 @@ class CodeGen { ...@@ -116,16 +121,16 @@ class CodeGen {
bool no_stack_alloca(Instruction *instr) { bool no_stack_alloca(Instruction *instr) {
if (instr->is_void()) if (instr->is_void())
return true; 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 true;
return false; 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 *, std::map<int, int>> func_arg_off; // to $sp
std::map<Function *, int> func_arg_N; std::map<Function *, int> func_arg_N; // total space for args
unsigned int stackN; unsigned int stackN; // function local vars and so on
Function *cur_func; Function *cur_func;
......
...@@ -17,13 +17,16 @@ ...@@ -17,13 +17,16 @@
using namespace std::literals::string_literals; 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 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; << std::endl;
} }
int main(int argc, char **argv) { int
main(int argc, char **argv) {
std::string target_path; std::string target_path;
std::string input_path; std::string input_path;
...@@ -36,9 +39,11 @@ int main(int argc, char **argv) { ...@@ -36,9 +39,11 @@ int main(int argc, char **argv) {
if (argv[i] == "-h"s || argv[i] == "--help"s) { if (argv[i] == "-h"s || argv[i] == "--help"s) {
print_help(argv[0]); print_help(argv[0]);
return 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) { if (target_path.empty() && i + 1 < argc) {
target_path = argv[i + 1]; target_path = argv[i + 1];
if (target_path.rfind(".") != std::string::npos)
target_path = target_path.substr(0, target_path.rfind("."));
i += 1; i += 1;
} else { } else {
print_help(argv[0]); print_help(argv[0]);
...@@ -71,12 +76,13 @@ int main(int argc, char **argv) { ...@@ -71,12 +76,13 @@ int main(int argc, char **argv) {
if (target_path.empty()) { if (target_path.empty()) {
auto pos = input_path.rfind('.'); auto pos = input_path.rfind('.');
if (pos == std::string::npos) { 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; return -1;
} else { } else {
// if (input_path.substr(pos) != ".cminus") { // if (input_path.substr(pos) != ".cminus") {
// std::cerr << argv[0] << ": input file " << input_path << " has unknown filetype!" << std::endl; // std::cerr << argv[0] << ": input file " << input_path << "
// return -1; // has unknown filetype!" << std::endl; return -1;
// } // }
target_path = input_path.substr(0, pos); target_path = input_path.substr(0, pos);
} }
...@@ -89,7 +95,8 @@ int main(int argc, char **argv) { ...@@ -89,7 +95,8 @@ int main(int argc, char **argv) {
a.run_visitor(builder); a.run_visitor(builder);
} catch (std::exception e) { } catch (std::exception e) {
std::cout << "Exception catched:\n\t" << e.what() << std::endl; 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; return -1;
} }
...@@ -104,7 +111,8 @@ int main(int argc, char **argv) { ...@@ -104,7 +111,8 @@ int main(int argc, char **argv) {
if (gvn) { if (gvn) {
PM.add_pass<DeadCode>(false); // remove some undef PM.add_pass<DeadCode>(false); // remove some undef
PM.add_pass<GVN>(emit, dump_json); 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(); PM.run();
...@@ -132,7 +140,8 @@ int main(int argc, char **argv) { ...@@ -132,7 +140,8 @@ int main(int argc, char **argv) {
lib_path.erase(lib_path.rfind('/')); lib_path.erase(lib_path.rfind('/'));
else else
lib_path.clear(); 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()); int re_code0 = std::system(cmd_str.c_str());
cmd_str = "rm "s + target_path + ".ll"; cmd_str = "rm "s + target_path + ".ll";
int re_code1 = std::system(cmd_str.c_str()); int re_code1 = std::system(cmd_str.c_str());
......
This diff is collapsed.
...@@ -6,7 +6,7 @@ import argparse ...@@ -6,7 +6,7 @@ import argparse
import subprocess import subprocess
test_dir = os.path.dirname(os.path.abspath(__file__)) # 当前文件夹路径 tests/5-bonus 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') testfile_dir = os.path.join(test_dir, './testcases')
output_file_name = os.path.join(test_dir, './test_result') output_file_name = os.path.join(test_dir, './test_result')
io = os.path.join(test_dir, '../../src/io/io.c') 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): ...@@ -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: 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 continue
# 未超时 # 未超时
output_file.write(f"[{count+1}/{test_count}] " + file_name + ': ') 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): ...@@ -75,8 +76,9 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
output_file.write('compile-1 timeout\n') output_file.write('compile-1 timeout\n')
failed_count += 1 failed_count += 1
continue continue
except Exception: except Exception as e:
output_file.write("compile-1 failed with an unexcept error\n") output_file.write("compile-1 failed with an unexcept error\n")
output_file.write(str(e))
failed_count += 1 failed_count += 1
continue continue
...@@ -107,8 +109,9 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False): ...@@ -107,8 +109,9 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
output_file.write('compile timeout\n') output_file.write('compile timeout\n')
failed_count += 1 failed_count += 1
continue continue
except Exception: except Exception as e:
output_file.write("compile failed with an unexcept error\n") output_file.write("compile failed with an unexcept error\n")
output_file.write(e)
failed_count += 1 failed_count += 1
continue continue
...@@ -135,8 +138,9 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False): ...@@ -135,8 +138,9 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
output_file.write("executable time limit exceeded\n") output_file.write("executable time limit exceeded\n")
failed_count += 1 failed_count += 1
continue continue
except Exception as _: except Exception as e:
output_file.write('executable runtime error\n') output_file.write('executable runtime error\n')
output_file.write(str(e))
failed_count += 1 failed_count += 1
continue continue
...@@ -159,8 +163,11 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False): ...@@ -159,8 +163,11 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
succ_count += 1 succ_count += 1
testtime[count] = time testtime[count] = time
else: 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 failed_count += 1
output_file.write(f"{failed_count} tests failed\n") output_file.write(f"{failed_count} tests failed\n")
...@@ -172,9 +179,11 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False): ...@@ -172,9 +179,11 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
output_file.write('\t\t\tyour_cminus') output_file.write('\t\t\tyour_cminus')
for count, file_name in enumerate(testfiles): for count, file_name in enumerate(testfiles):
output_file.write('{:<20}'.format(file_name)) 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__": if __name__ == "__main__":
...@@ -182,8 +191,10 @@ if __name__ == "__main__": ...@@ -182,8 +191,10 @@ if __name__ == "__main__":
parser = argparse.ArgumentParser(description="functional test") 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("--console", action="store_true",
parser.add_argument("--clang", action="store_true", help="estimate runtime when compile with clang") 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() args = parser.parse_args()
eval(args.console, testfile_dir, use_clang=args.clang) 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