functional all pass

This commit is contained in:
ridethepig 2023-05-16 00:41:02 +08:00
parent 0bc5ea8f10
commit 57094c9afe
8 changed files with 63 additions and 30 deletions

3
.gitignore vendored
View File

@ -2,4 +2,5 @@ build/
.antlr/ .antlr/
*.log *.log
__pycache__/ __pycache__/
*.o *.o
testcases/

View File

@ -219,7 +219,7 @@ public:
if (pointed_type->type_tag == Type::TypeTag::IntegerType) { if (pointed_type->type_tag == Type::TypeTag::IntegerType) {
return pointed_type; return pointed_type;
} }
else if (Type::isType<ArrayType>(pointed_type)){ else if (Type::isType<ArrayType>(pointed_type)) {
for (int i = 1; i < indices.size(); ++i) { for (int i = 1; i < indices.size(); ++i) {
pointed_type = std::dynamic_pointer_cast<ArrayType>(pointed_type)->element_type; pointed_type = std::dynamic_pointer_cast<ArrayType>(pointed_type)->element_type;
} }

View File

@ -167,8 +167,13 @@ public:
bool is_const; bool is_const;
GlobalVar(const std::string &name, TypePtr_t type, ConstantPtr_t init_value, bool is_const) GlobalVar(const std::string &name, TypePtr_t type, ConstantPtr_t init_value, bool is_const)
: Value(name, PointerType::make_shared(type)), init_value(init_value), is_const(is_const) {} : Value(name, PointerType::make_shared(type)), init_value(init_value), is_const(is_const) {}
static std::shared_ptr<GlobalVar> make_shared(const std::string &name, TypePtr_t type, ConstantPtr_t init_value, bool is_const) { static std::shared_ptr<GlobalVar> make_shared(
return std::make_shared<GlobalVar>(name, type ,init_value, is_const); const std::string &name,
TypePtr_t type,
ConstantPtr_t init_value,
bool is_const
) {
return std::make_shared<GlobalVar>(name, type, init_value, is_const);
} }
virtual std::string to_IR_string() override { virtual std::string to_IR_string() override {
std::string str = type->to_IR_string() + " @" + name; std::string str = type->to_IR_string() + " @" + name;

View File

@ -41,7 +41,11 @@ std::shared_ptr<InstStore> build_InstStore(
std::shared_ptr<BasicBlock> parent_bb std::shared_ptr<BasicBlock> parent_bb
); );
std::shared_ptr<InstAlloca> build_InstAlloca(const std::string &str, TypePtr_t type, std::shared_ptr<BasicBlock> parent_bb); std::shared_ptr<InstAlloca> build_InstAlloca(
const std::string &str,
TypePtr_t type,
std::shared_ptr<BasicBlock> parent_bb
);
std::shared_ptr<InstBinary> build_InstBinary( std::shared_ptr<InstBinary> build_InstBinary(
InstTag inst_tag, InstTag inst_tag,

View File

@ -193,6 +193,7 @@ class BatTest:
self.diffout_template = f"{compiler.target_dir}/{{testcase}}/{self.label}.diff" self.diffout_template = f"{compiler.target_dir}/{{testcase}}/{self.label}.diff"
def bat_case(self, testcase, compile=False): def bat_case(self, testcase, compile=False):
Print_C.print_subheader(f"Diff test {self.label} on {testcase}")
if compile: if compile:
self.compiler.clean_case(testcase) self.compiler.clean_case(testcase)
self.compiler_rf.clean_case(testcase) self.compiler_rf.clean_case(testcase)
@ -212,6 +213,7 @@ class BatTest:
return True return True
def bat_all_tests(self, compile=False): def bat_all_tests(self, compile=False):
for testcase in self.testcases: for testcase in self.testcases:
if not self.bat_case(testcase, compile): break if not self.bat_case(testcase, compile): break
@ -254,7 +256,7 @@ if __name__ == "__main__":
args = parser.parse_args() args = parser.parse_args()
print(args) print(args)
testcases = case_collector(args.case_selector, args.case_prefix) testcases = case_collector(args.case_selector, args.case_prefix)
target_dir = os.path.join(BUILD_DIR, args.case_prefix) target_dir = os.path.join(BUILD_DIR, args.case_prefix.replace("../", "").replace("./", ""))
if args.clean: if args.clean:
os.system(f"rm -rfI {target_dir}") os.system(f"rm -rfI {target_dir}")
if not os.path.exists(target_dir): if not os.path.exists(target_dir):

View File

@ -95,7 +95,7 @@ Visitor::Visitor(SysyLexer &) {
_func_tab.push_name("putch", func_putch); _func_tab.push_name("putch", func_putch);
auto func_putarray = std::make_shared<Function>("putarray", TypeHelper::TYPE_VOID); auto func_putarray = std::make_shared<Function>("putarray", TypeHelper::TYPE_VOID);
func_putarray->fparam_list = {fparam_ptr_i32, fparam_i32}; func_putarray->fparam_list = {fparam_i32, fparam_ptr_i32};
_func_tab.push_name("putarray", func_putarray); _func_tab.push_name("putarray", func_putarray);
// auto func_putf = std::make_shared<Function>("putf", TypeHelper::TYPE_VOID); // auto func_putf = std::make_shared<Function>("putf", TypeHelper::TYPE_VOID);
@ -152,7 +152,7 @@ std::any Visitor::visitConstDef(SysyParser::ConstDefContext *ctx) {
if (_scope_tab.get_level()) { if (_scope_tab.get_level()) {
// local const array // local const array
// Keep a pointer to the base address, alloca_ = &array, *alloca_ = &array[0] // Keep a pointer to the base address, alloca_ = &array, *alloca_ = &array[0]
auto alloca_ = build_InstAlloca(const_name , array_type, _state.current_bb); auto alloca_ = build_InstAlloca(const_name, array_type, _state.current_bb);
_scope_tab.push_name(const_name, alloca_); _scope_tab.push_name(const_name, alloca_);
// first dim base, ptr = *alloca_ = &array[0] // first dim base, ptr = *alloca_ = &array[0]
auto base_ptr = build_InstGEP(alloca_, {CONST0, CONST0}, _state.current_bb); auto base_ptr = build_InstGEP(alloca_, {CONST0, CONST0}, _state.current_bb);
@ -193,12 +193,12 @@ std::any Visitor::visitVarDef(SysyParser::VarDefContext *ctx) {
_state.isGlobalIint = true; _state.isGlobalIint = true;
auto result = std::any_cast<std::shared_ptr<ConstantInt>>(visitInitVal(ctx->initVal())); auto result = std::any_cast<std::shared_ptr<ConstantInt>>(visitInitVal(ctx->initVal()));
_state.isGlobalIint = false; _state.isGlobalIint = false;
auto global_var_int = GlobalVar::make_shared(var_name, result->type,result, false); auto global_var_int = GlobalVar::make_shared(var_name, result->type, result, false);
module.global_var_list.push_back(global_var_int); module.global_var_list.push_back(global_var_int);
_scope_tab.push_name(var_name, global_var_int); _scope_tab.push_name(var_name, global_var_int);
} }
else { else {
auto global_var_int = GlobalVar::make_shared(var_name, CONST0->type,CONST0, false); auto global_var_int = GlobalVar::make_shared(var_name, CONST0->type, CONST0, false);
module.global_var_list.push_back(global_var_int); module.global_var_list.push_back(global_var_int);
_scope_tab.push_name(var_name, global_var_int); _scope_tab.push_name(var_name, global_var_int);
} }
@ -393,9 +393,9 @@ std::any Visitor::visitAddExp(SysyParser::AddExpContext *ctx) {
return {result}; return {result};
} }
else { else {
auto mul_exp = any_to_Value(visitMulExp(ctx->mulExp()));
if (ctx->addExp()) { if (ctx->addExp()) {
auto add_exp = any_to_Value(visitAddExp(ctx->addExp())); auto add_exp = any_to_Value(visitAddExp(ctx->addExp()));
auto mul_exp = any_to_Value(visitMulExp(ctx->mulExp()));
if (std::dynamic_pointer_cast<IntegerType>(add_exp->type)->isI1()) { if (std::dynamic_pointer_cast<IntegerType>(add_exp->type)->isI1()) {
add_exp = build_InstZext(add_exp, _state.current_bb); add_exp = build_InstZext(add_exp, _state.current_bb);
} }
@ -410,8 +410,11 @@ std::any Visitor::visitAddExp(SysyParser::AddExpContext *ctx) {
} }
else else
panic("Unreachable"); panic("Unreachable");
return mul_exp;
}
else {
return visitMulExp(ctx->mulExp());
} }
return mul_exp;
} }
} }
@ -435,9 +438,9 @@ std::any Visitor::visitMulExp(SysyParser::MulExpContext *ctx) {
return {result}; return {result};
} }
else { else {
auto unary_exp = any_to_Value(visitUnaryExp(ctx->unaryExp()));
if (ctx->mulExp()) { if (ctx->mulExp()) {
auto mul_exp = any_to_Value(visitMulExp(ctx->mulExp())); auto mul_exp = any_to_Value(visitMulExp(ctx->mulExp()));
auto unary_exp = any_to_Value(visitUnaryExp(ctx->unaryExp()));
if (std::dynamic_pointer_cast<IntegerType>(unary_exp->type)->isI1()) { if (std::dynamic_pointer_cast<IntegerType>(unary_exp->type)->isI1()) {
unary_exp = build_InstZext(unary_exp, _state.current_bb); unary_exp = build_InstZext(unary_exp, _state.current_bb);
} }
@ -455,15 +458,18 @@ std::any Visitor::visitMulExp(SysyParser::MulExpContext *ctx) {
} }
else else
panic("Unreachable"); panic("Unreachable");
return {unary_exp};
}
else {
return visitUnaryExp(ctx->unaryExp());
} }
return {unary_exp};
} }
} }
// relExp: addExp | relExp ('<' | '>' | '<=' | '>=') addExp; // relExp: addExp | relExp ('<' | '>' | '<=' | '>=') addExp;
std::any Visitor::visitRelExp(SysyParser::RelExpContext *ctx) { std::any Visitor::visitRelExp(SysyParser::RelExpContext *ctx) {
auto add_exp = any_to_Value(visitAddExp(ctx->addExp()));
if (ctx->relExp()) { if (ctx->relExp()) {
auto rel_exp = any_to_Value(visitRelExp(ctx->relExp())); auto rel_exp = any_to_Value(visitRelExp(ctx->relExp()));
auto add_exp = any_to_Value(visitAddExp(ctx->addExp()));
sysy_assert(TypeHelper::isIntegerTypeI32(rel_exp->type)); sysy_assert(TypeHelper::isIntegerTypeI32(rel_exp->type));
if (ctx->LE()) { if (ctx->LE()) {
add_exp = build_InstBinary(InstTag::Le, rel_exp, add_exp, _state.current_bb); add_exp = build_InstBinary(InstTag::Le, rel_exp, add_exp, _state.current_bb);
@ -481,16 +487,19 @@ std::any Visitor::visitRelExp(SysyParser::RelExpContext *ctx) {
LOG(ERROR) << ctx->relExp()->getStart()->getLine() << ":" << ctx->relExp()->getText(); LOG(ERROR) << ctx->relExp()->getStart()->getLine() << ":" << ctx->relExp()->getText();
panic("Unreachable"); panic("Unreachable");
} }
return add_exp;
}
else {
return visitAddExp(ctx->addExp());
} }
return add_exp;
} }
// eqExp: relExp | eqExp ('==' | '!=') relExp; // eqExp: relExp | eqExp ('==' | '!=') relExp;
std::any Visitor::visitEqExp(SysyParser::EqExpContext *ctx) { std::any Visitor::visitEqExp(SysyParser::EqExpContext *ctx) {
auto rel_exp = any_to_Value(visitRelExp(ctx->relExp()));
bool need_zext = false;
if (ctx->eqExp()) { if (ctx->eqExp()) {
auto eq_exp = any_to_Value(visitEqExp(ctx->eqExp())); bool need_zext = false;
auto eq_exp = any_to_Value(visitEqExp(ctx->eqExp()));
auto rel_exp = any_to_Value(visitRelExp(ctx->relExp()));
if (TypeHelper::isIntegerTypeI32(eq_exp->type) || TypeHelper::isIntegerTypeI32(rel_exp->type)) { if (TypeHelper::isIntegerTypeI32(eq_exp->type) || TypeHelper::isIntegerTypeI32(rel_exp->type)) {
need_zext = true; need_zext = true;
} }
@ -508,12 +517,16 @@ std::any Visitor::visitEqExp(SysyParser::EqExpContext *ctx) {
} }
else else
panic("Unreachable"); panic("Unreachable");
return rel_exp;
}
else {
return visitRelExp(ctx->relExp());
} }
return rel_exp;
} }
// Notes about SideEffect: except for || and &&, other sub-expression evaluations are unsequenced // Notes about SideEffect: except for || and &&, other sub-expression evaluations are unsequenced
// as long as they are calculated before the operator // as long as they are calculated before the operator
// BUT, in sysy test, it seems that, it is a must ti compute from left to right
// lAndExp: eqExp | lAndExp '&&' eqExp; // lAndExp: eqExp | lAndExp '&&' eqExp;
// Luckily, there is only one path to lOrExp, which is `stmt` -> `cond` -> `lOrExp` // Luckily, there is only one path to lOrExp, which is `stmt` -> `cond` -> `lOrExp`
// Thus, there is no need to care about what if it appears in a arithmetic expression // Thus, there is no need to care about what if it appears in a arithmetic expression
@ -729,8 +742,7 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
return lval; return lval;
} }
else { else {
LOG(WARNING) << "Unexpected array referece" << lval->to_string() LOG(WARNING) << "Unexpected array referece" << lval->to_string() << " : " << ctx->getStart()->getLine();
<< " : "<< ctx->getStart()->getLine();
// array index, perhaps // array index, perhaps
// @retval: InstGEP // @retval: InstGEP
auto gep = lval; auto gep = lval;
@ -793,7 +805,9 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
return arr_elem_ptr; return arr_elem_ptr;
} }
else { else {
panic("Should be int"); LOG(WARNING) << "Should be int";
auto arr_ptr = build_InstGEP(ptr, {CONST0, offset}, _state.current_bb);
return arr_ptr;
} }
} }
} }
@ -833,7 +847,7 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
// return the address of an sub array // return the address of an sub array
auto array_type = std::dynamic_pointer_cast<ArrayType>(pointed_type); auto array_type = std::dynamic_pointer_cast<ArrayType>(pointed_type);
auto dim_size = ConstantInt::make_shared(array_type->element_count); auto dim_size = ConstantInt::make_shared(array_type->element_count);
auto inst_mul = build_InstBinary(InstTag::Mul, offset, dim_size, _state.current_bb); offset = build_InstBinary(InstTag::Mul, offset, dim_size, _state.current_bb);
auto arr_elem_ptr = build_InstGEP(ptr, {CONST0, offset}, _state.current_bb); auto arr_elem_ptr = build_InstGEP(ptr, {CONST0, offset}, _state.current_bb);
return arr_elem_ptr; return arr_elem_ptr;
} }

View File

@ -43,10 +43,15 @@ std::shared_ptr<InstStore> build_InstStore(
} }
// a little bit different, we put all alloca in the head of each basic block // a little bit different, we put all alloca in the head of each basic block
std::shared_ptr<InstAlloca> build_InstAlloca(const std::string & name, TypePtr_t type, std::shared_ptr<BasicBlock> parent_bb) { std::shared_ptr<InstAlloca> build_InstAlloca(
auto inst_alloca = std::make_shared<InstAlloca>(type, parent_bb); const std::string &name,
TypePtr_t type,
std::shared_ptr<BasicBlock> parent_bb
) {
auto inst_alloca = std::make_shared<InstAlloca>(type, parent_bb);
inst_alloca->name = name; inst_alloca->name = name;
parent_bb->inst_list.insert(parent_bb->inst_list.begin(), inst_alloca); auto func_head_bb = parent_bb->parent->bb_list.front();
func_head_bb->inst_list.insert(func_head_bb->inst_list.begin(), inst_alloca);
// parent_bb->inst_list.push_back(inst_alloca); // parent_bb->inst_list.push_back(inst_alloca);
return inst_alloca; return inst_alloca;
} }

View File

@ -153,6 +153,7 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
ostr << block->ir_seqno << ":" << std::endl; ostr << block->ir_seqno << ":" << std::endl;
} }
for (int j = 0; j < block->inst_list.size(); ++j) { for (int j = 0; j < block->inst_list.size(); ++j) {
ostr << " ";
auto _inst = block->inst_list[j]; auto _inst = block->inst_list[j];
VLOG(5) << "Build inst" << _inst->ir_seqno << ": " << _inst->to_string(); VLOG(5) << "Build inst" << _inst->ir_seqno << ": " << _inst->to_string();
switch (_inst->tag) { switch (_inst->tag) {
@ -251,6 +252,7 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
LOG(ERROR) << "Unexpected type of op1: " << inst->operand_list[1]->to_string(); LOG(ERROR) << "Unexpected type of op1: " << inst->operand_list[1]->to_string();
assert(0); assert(0);
} }
ostr << ", align 4";
break; break;
} }
// Call's seqno is dependent on its return type // Call's seqno is dependent on its return type
@ -470,8 +472,8 @@ void Visitor::llir_gen(std::ostream &ostr) {
} }
else if (global_var_type->pointed_type->type_tag == Type::TypeTag::ArrayType) { else if (global_var_type->pointed_type->type_tag == Type::TypeTag::ArrayType) {
// sysy_assert(global_var->) // sysy_assert(global_var->)
auto array_type = std::dynamic_pointer_cast<ArrayType>(global_var_type->pointed_type); auto array_type = std::dynamic_pointer_cast<ArrayType>(global_var_type->pointed_type);
auto init_value = std::dynamic_pointer_cast<ConstantArr>(global_var->init_value); auto init_value = std::dynamic_pointer_cast<ConstantArr>(global_var->init_value);
if (init_value != nullptr) { if (init_value != nullptr) {
auto hierarchy_array = gen_arr_hierarchy(array_type, init_value->value_list, 0, init_value->value_list.size()); auto hierarchy_array = gen_arr_hierarchy(array_type, init_value->value_list, 0, init_value->value_list.size());
if (hierarchy_array) { if (hierarchy_array) {