Rename API, Make emit IR optional

This commit is contained in:
ridethepig 2023-05-17 00:25:13 +08:00
parent 57094c9afe
commit a9a340f482
8 changed files with 101 additions and 88 deletions

View File

@ -20,7 +20,7 @@ file(GLOB MY_HEADERS "include/*.h")
include(formatting.cmake)
clang_format(format ${MY_SOURCES} ${MY_HEADERS})
clang_format_check(format_check ${MY_SOURCES} ${MY_HEADERS})
# clang_format_check(format_check ${MY_SOURCES} ${MY_HEADERS})
add_executable(sysy ${SOURCES})
# message(STATUS "${SOURCES}")

View File

@ -192,10 +192,10 @@ public:
TypePtr_t element_type;
InstGEP(ValuePtr_t pointer, const std::vector<ValuePtr_t> &indices, BasicBlockPtr_t parent_bb)
: Instruction(InstTag::GEP, std::make_shared<PointerType>(extract_type(pointer, indices)), parent_bb) {
if (Value::isValueType<InstGEP>(pointer)) {
if (Value::is<InstGEP>(pointer)) {
aim_to = std::dynamic_pointer_cast<InstGEP>(pointer)->aim_to;
}
else if (Value::isValueType<InstAlloca>(pointer) || Value::isValueType<GlobalVar>(pointer)) {
else if (Value::is<InstAlloca>(pointer) || Value::is<GlobalVar>(pointer)) {
aim_to = pointer;
}
else {

View File

@ -20,7 +20,7 @@ public:
virtual ~Value() = default;
template <typename TT>
static bool isValueType(std::shared_ptr<Value> ptr) {
static bool is(std::shared_ptr<Value> ptr) {
if (ptr.get()) {
// auto &r = *ptr.get();
// return typeid(r) == typeid(TT);
@ -33,7 +33,7 @@ public:
// it is caller's duty to check before use `asType`
template <typename TT>
static std::shared_ptr<TT> asValueType(std::shared_ptr<Value> ptr) {
static std::shared_ptr<TT> as(std::shared_ptr<Value> ptr) {
return std::dynamic_pointer_cast<TT>(ptr);
}
@ -94,8 +94,8 @@ public:
std::vector<std::shared_ptr<Instruction>> inst_list;
std::shared_ptr<Function> parent;
BasicBlockListNode_t itr;
std::vector<std::shared_ptr<BasicBlock>> successors;
std::vector<std::shared_ptr<BasicBlock>> predecessors;
std::list<std::shared_ptr<BasicBlock>> successors;
std::list<std::shared_ptr<BasicBlock>> predecessors;
BasicBlock(const std::string &name, std::shared_ptr<Function> parent) : Value(name, TypeHelper::TYPE_LABEL) {
this->parent = parent;
}

View File

@ -228,7 +228,7 @@ scheme_ref = {
scheme_my = {
"name": "my",
"sy_ir": f"build/sysy -S {{sy}} -o {{ir}}",
"sy_ir": f"build/sysy -S {{sy}} -o {{ir}} -emit-llvm",
"ir_asm": "llc --march=x86 --relocation-model=pic {ir} -o {asm}",
"asm_obj": "as --32 {asm} -o {obj}",
"obj_bin": f"clang -m32 -Ofast -fPIE {{obj}} {LIB_PATH} -o {{bin}}",

View File

@ -39,6 +39,7 @@ int main(int argc, const char **argv) {
arg_parser.add_argument("-S").implicit_value(true).help("Useless but required by the contest").required();
arg_parser.add_argument("-o").help("Output file name").required();
arg_parser.add_argument("-O1").implicit_value(true).default_value(false).help("Performance mode");
arg_parser.add_argument("-emit-llvm").implicit_value(true).default_value(false).help("Generate llvm ir");
arg_parser.add_argument("--v").default_value(0);
try {
arg_parser.parse_args(argc, argv);
@ -50,6 +51,7 @@ int main(int argc, const char **argv) {
auto source_file = arg_parser.get<std::string>("source");
auto output_file = arg_parser.get<std::string>("-o");
auto flg_O1 = arg_parser["-O1"] == true;
auto emit_llvm = arg_parser["-emit-llvm"] == true;
// std::cout << source_file << " " << output_file << " " << flg_O1 <<
// std::endl;
#pragma endregion
@ -86,13 +88,15 @@ int main(int argc, const char **argv) {
auto tree = parser.program();
Visitor visitor(lexer);
visitor.visitProgram(tree);
auto llir_file = output_file.substr(0, output_file.rfind(".")) + ".ll";
std::ofstream ofs_llir_file(llir_file);
if (!ofs_llir_file.good()) {
LOG(ERROR) << "Failed to create/overwrite LLIR output file " << llir_file;
return 1;
if (emit_llvm) {
auto llir_file = output_file.substr(0, output_file.rfind(".")) + ".ll";
std::ofstream ofs_llir_file(llir_file);
if (!ofs_llir_file.good()) {
LOG(ERROR) << "Failed to create/overwrite LLIR output file " << llir_file;
return 1;
}
visitor.llir_gen(ofs_llir_file);
}
visitor.llir_gen(ofs_llir_file);
#if 0
std::cout << tree->toStringTree(&parser) << std::endl << std::endl;
#endif

View File

@ -293,7 +293,7 @@ std::any Visitor::visitInitVal(SysyParser::InitValContext *ctx) {
if (_state.isGlobalIint) {
auto const_value = any_to_Value(visitInitVal(init_val));
// should evaluate to const int
sysy_assert(Value::isValueType<ConstantInt>(const_value));
sysy_assert(Value::is<ConstantInt>(const_value));
cur_arr.push_back(const_value);
}
else {
@ -834,6 +834,15 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
pointed_type = array_type->element_type;
ptr = build_InstGEP(ptr, {CONST0, CONST0}, _state.current_bb);
}
// for (int i = 0; i < exp_list.size() - 1; ++ i) {
// sysy_assert(pointed_type->type_tag == Type::TypeTag::ArrayType);
// auto array_type = std::dynamic_pointer_cast<ArrayType>(pointed_type);
// auto exp_val = any_to_Value(visitExp(exp_list[i]));
// if (Value::isValueType<PointerType>(exp_val)){
// exp_val = build_InstLoad(exp_val, pointed_type, _state.current_bb);
// }
// ptr = build_InstGEP(ptr, {CONST0, exp_val}, _state.current_bb);
// }
auto exp_val = any_to_Value(visitExp(exp_list.back()));
auto inst_add = build_InstBinary(InstTag::Add, offset, exp_val, _state.current_bb);
offset = inst_add; // finally, we get the offset
@ -887,7 +896,7 @@ std::any Visitor::visitFuncDef(SysyParser::FuncDefContext *ctx) {
func_obj->bb_list.pop_back();
}
if (func_obj->bb_list.back()->inst_list.size()==0
|| !Value::isValueType<InstReturn>(func_obj->bb_list.back()->inst_list.back())){
|| !Value::is<InstReturn>(func_obj->bb_list.back()->inst_list.back())){
if (func_ret_type->type_tag == Type::TypeTag::VoidType) {
build_InstReturn(_state.current_bb);
}

View File

@ -75,8 +75,8 @@ std::shared_ptr<InstBinary> build_InstBinary(
assert(Type::isType<IntegerType>(op1->type));
assert(Type::isType<IntegerType>(op2->type));
if (!(Type::asType<IntegerType>(op1->type)->int_type == Type::asType<IntegerType>(op2->type)->int_type)) {
if (!(Value::isValueType<ConstantInt>(op1) && Value::asValueType<ConstantInt>(op1)->value == 0)
&& !(Value::isValueType<ConstantInt>(op2) && Value::asValueType<ConstantInt>(op2)->value == 0)) {
if (!(Value::is<ConstantInt>(op1) && Value::as<ConstantInt>(op1)->value == 0)
&& !(Value::is<ConstantInt>(op2) && Value::as<ConstantInt>(op2)->value == 0)) {
LOG(ERROR) << op1->to_string() << ",\t" << op2->to_string();
assert(0);
}

View File

@ -158,21 +158,21 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
VLOG(5) << "Build inst" << _inst->ir_seqno << ": " << _inst->to_string();
switch (_inst->tag) {
case InstTag::Br: {
auto inst = Value::asValueType<InstBranch>(_inst);
auto inst = Value::as<InstBranch>(_inst);
assert(inst->ir_seqno == -1);
ostr << "br ";
if (inst->operand_list.size() == 1) {
assert(Value::isValueType<BasicBlock>(inst->operand_list[0]));
auto bb_dest = Value::asValueType<BasicBlock>(inst->operand_list[0]);
assert(Value::is<BasicBlock>(inst->operand_list[0]));
auto bb_dest = Value::as<BasicBlock>(inst->operand_list[0]);
assert(bb_dest->ir_seqno >= 0);
ostr << "label %" << bb_dest->ir_seqno;
}
else {
assert(Value::isValueType<Instruction>(inst->operand_list[0]));
assert(Value::is<Instruction>(inst->operand_list[0]));
assert(Type::isType<IntegerType>(inst->operand_list[0]->type));
auto cond = Value::asValueType<Instruction>(inst->operand_list[0]);
auto bb_true = Value::asValueType<BasicBlock>(inst->operand_list[1]);
auto bb_false = Value::asValueType<BasicBlock>(inst->operand_list[2]);
auto cond = Value::as<Instruction>(inst->operand_list[0]);
auto bb_true = Value::as<BasicBlock>(inst->operand_list[1]);
auto bb_false = Value::as<BasicBlock>(inst->operand_list[2]);
if (!Type::asType<IntegerType>(cond->type)->isI1()) {
LOG(ERROR) << "Expect cond evals to i1: " << cond->to_string();
panic("Grammar check");
@ -185,7 +185,7 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
break;
}
case InstTag::Ret: {
auto inst = Value::asValueType<InstReturn>(_inst);
auto inst = Value::as<InstReturn>(_inst);
assert(inst->ir_seqno == -1);
ostr << "ret ";
if (inst->operand_list.size() == 0) {
@ -193,17 +193,17 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
ostr << "void";
}
else {
if (Value::isValueType<Instruction>(inst->operand_list[0])) {
auto op0 = Value::asValueType<Instruction>(inst->operand_list[0]);
if (Value::is<Instruction>(inst->operand_list[0])) {
auto op0 = Value::as<Instruction>(inst->operand_list[0]);
assert(op0->ir_seqno >= 0);
ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno;
}
else if (Value::isValueType<ConstantInt>(inst->operand_list[0])) {
auto op0 = Value::asValueType<ConstantInt>(inst->operand_list[0]);
else if (Value::is<ConstantInt>(inst->operand_list[0])) {
auto op0 = Value::as<ConstantInt>(inst->operand_list[0]);
ostr << op0->to_IR_string();
}
else if (Value::isValueType<FParam>(inst->operand_list[0])) {
auto op0 = Value::asValueType<FParam>(inst->operand_list[0]);
else if (Value::is<FParam>(inst->operand_list[0])) {
auto op0 = Value::as<FParam>(inst->operand_list[0]);
ostr << op0->to_IR_string();
}
else {
@ -214,38 +214,38 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
break;
}
case InstTag::Store: {
auto inst = Value::asValueType<InstStore>(_inst);
auto inst = Value::as<InstStore>(_inst);
assert(inst->ir_seqno == -1);
ostr << "store ";
if (Value::isValueType<Instruction>(inst->operand_list[0])) {
auto op0 = Value::asValueType<Instruction>(inst->operand_list[0]);
if (Value::is<Instruction>(inst->operand_list[0])) {
auto op0 = Value::as<Instruction>(inst->operand_list[0]);
assert(op0->ir_seqno >= 0);
ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno << ", ";
}
else if (Value::isValueType<ConstantInt>(inst->operand_list[0])) {
auto op0 = Value::asValueType<ConstantInt>(inst->operand_list[0]);
else if (Value::is<ConstantInt>(inst->operand_list[0])) {
auto op0 = Value::as<ConstantInt>(inst->operand_list[0]);
ostr << op0->to_IR_string() << ", ";
}
else if (Value::isValueType<FParam>(inst->operand_list[0])) {
auto op0 = Value::asValueType<FParam>(inst->operand_list[0]);
else if (Value::is<FParam>(inst->operand_list[0])) {
auto op0 = Value::as<FParam>(inst->operand_list[0]);
ostr << op0->to_IR_string() << ", ";
}
else {
LOG(ERROR) << "Unexpected type of op0: " << inst->operand_list[0]->to_string();
assert(0);
}
if (Value::isValueType<GlobalVar>(inst->operand_list[1])) {
auto op1 = Value::asValueType<GlobalVar>(inst->operand_list[1]);
if (Value::is<GlobalVar>(inst->operand_list[1])) {
auto op1 = Value::as<GlobalVar>(inst->operand_list[1]);
ostr << op1->type->to_IR_string() << " @" << op1->name;
}
else if (Value::isValueType<Instruction>(inst->operand_list[1])) {
auto op1 = Value::asValueType<Instruction>(inst->operand_list[1]);
else if (Value::is<Instruction>(inst->operand_list[1])) {
auto op1 = Value::as<Instruction>(inst->operand_list[1]);
assert(op1->ir_seqno >= 0);
ostr << op1->type->to_IR_string() << " %" << op1->ir_seqno;
}
else if (Value::isValueType<FParam>(inst->operand_list[0])) {
auto op0 = Value::asValueType<FParam>(inst->operand_list[0]);
else if (Value::is<FParam>(inst->operand_list[0])) {
auto op0 = Value::as<FParam>(inst->operand_list[0]);
ostr << op0->to_IR_string();
}
else {
@ -257,9 +257,9 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
}
// Call's seqno is dependent on its return type
case InstTag::Call: {
auto inst = Value::asValueType<InstCall>(_inst);
auto inst = Value::as<InstCall>(_inst);
LOG(DEBUG) << inst->operand_list[0]->to_string();
auto func = Value::asValueType<Function>(inst->operand_list[0]);
auto func = Value::as<Function>(inst->operand_list[0]);
auto func_type = Type::asType<FunctionType>(func->type);
if (Type::isType<VoidType>(func_type->return_type)) {
assert(inst->ir_seqno == -1);
@ -272,17 +272,17 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
ostr << func->name << "(";
if (inst->operand_list.size() > 1) {
for (int i = 1; i < inst->operand_list.size(); ++i) {
if (Value::isValueType<Instruction>(inst->operand_list[i])) {
auto op0 = Value::asValueType<Instruction>(inst->operand_list[i]);
if (Value::is<Instruction>(inst->operand_list[i])) {
auto op0 = Value::as<Instruction>(inst->operand_list[i]);
assert(op0->ir_seqno >= 0);
ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno;
}
else if (Value::isValueType<ConstantInt>(inst->operand_list[i])) {
auto op0 = Value::asValueType<ConstantInt>(inst->operand_list[i]);
else if (Value::is<ConstantInt>(inst->operand_list[i])) {
auto op0 = Value::as<ConstantInt>(inst->operand_list[i]);
ostr << op0->to_IR_string();
}
else if (Value::isValueType<FParam>(inst->operand_list[i])) {
auto op0 = Value::asValueType<FParam>(inst->operand_list[i]);
else if (Value::is<FParam>(inst->operand_list[i])) {
auto op0 = Value::as<FParam>(inst->operand_list[i]);
ostr << op0->to_IR_string() << ", ";
}
else {
@ -309,36 +309,36 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
case InstTag::Ne:
case InstTag::And:
case InstTag::Or: {
auto inst = Value::asValueType<InstBinary>(_inst);
auto inst = Value::as<InstBinary>(_inst);
ostr << "%" << inst->ir_seqno << " = " << inst->to_string() << " ";
if (Value::isValueType<Instruction>(inst->operand_list[0])) {
auto op0 = Value::asValueType<Instruction>(inst->operand_list[0]);
if (Value::is<Instruction>(inst->operand_list[0])) {
auto op0 = Value::as<Instruction>(inst->operand_list[0]);
assert(op0->ir_seqno >= 0);
ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno << ", ";
}
else if (Value::isValueType<ConstantInt>(inst->operand_list[0])) {
auto op0 = Value::asValueType<ConstantInt>(inst->operand_list[0]);
else if (Value::is<ConstantInt>(inst->operand_list[0])) {
auto op0 = Value::as<ConstantInt>(inst->operand_list[0]);
ostr << op0->to_IR_string() << ", ";
}
else if (Value::isValueType<FParam>(inst->operand_list[0])) {
auto op0 = Value::asValueType<FParam>(inst->operand_list[0]);
else if (Value::is<FParam>(inst->operand_list[0])) {
auto op0 = Value::as<FParam>(inst->operand_list[0]);
ostr << op0->to_IR_string() << ", ";
}
else {
LOG(ERROR) << "Unexpected type of op0: " << inst->operand_list[0]->to_string();
assert(0);
}
if (Value::isValueType<Instruction>(inst->operand_list[1])) {
auto op1 = Value::asValueType<Instruction>(inst->operand_list[1]);
if (Value::is<Instruction>(inst->operand_list[1])) {
auto op1 = Value::as<Instruction>(inst->operand_list[1]);
assert(op1->ir_seqno >= 0);
ostr << "%" << op1->ir_seqno;
}
else if (Value::isValueType<ConstantInt>(inst->operand_list[1])) {
auto op1 = Value::asValueType<ConstantInt>(inst->operand_list[1]);
else if (Value::is<ConstantInt>(inst->operand_list[1])) {
auto op1 = Value::as<ConstantInt>(inst->operand_list[1]);
ostr << op1->value;
}
else if (Value::isValueType<FParam>(inst->operand_list[1])) {
auto op1 = Value::asValueType<FParam>(inst->operand_list[1]);
else if (Value::is<FParam>(inst->operand_list[1])) {
auto op1 = Value::as<FParam>(inst->operand_list[1]);
ostr << "%" << op1->ir_seqno;
}
else {
@ -348,21 +348,21 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
break;
}
case InstTag::Load: {
auto inst = Value::asValueType<InstLoad>(_inst);
auto inst = Value::as<InstLoad>(_inst);
assert(inst->ir_seqno != -1);
assert(Type::isType<PointerType>(inst->operand_list[0]->type));
ostr << "%" << inst->ir_seqno << " = load " << inst->type->to_IR_string() << ", ";
if (Value::isValueType<GlobalVar>(inst->operand_list[0])) {
auto op1 = Value::asValueType<GlobalVar>(inst->operand_list[0]);
if (Value::is<GlobalVar>(inst->operand_list[0])) {
auto op1 = Value::as<GlobalVar>(inst->operand_list[0]);
ostr << op1->type->to_IR_string() << " @" << op1->name;
}
else if (Value::isValueType<Instruction>(inst->operand_list[0])) {
auto op1 = Value::asValueType<Instruction>(inst->operand_list[0]);
else if (Value::is<Instruction>(inst->operand_list[0])) {
auto op1 = Value::as<Instruction>(inst->operand_list[0]);
assert(op1->ir_seqno >= 0);
ostr << op1->type->to_IR_string() << " %" << op1->ir_seqno;
}
else if (Value::isValueType<FParam>(inst->operand_list[0])) {
auto op0 = Value::asValueType<FParam>(inst->operand_list[0]);
else if (Value::is<FParam>(inst->operand_list[0])) {
auto op0 = Value::as<FParam>(inst->operand_list[0]);
ostr << op0->to_IR_string();
}
else {
@ -372,21 +372,21 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
break;
}
case InstTag::GEP: {
auto inst = Value::asValueType<InstGEP>(_inst);
auto inst = Value::as<InstGEP>(_inst);
assert(inst->ir_seqno >= 0);
auto pointer_type = Type::asType<PointerType>(inst->operand_list[0]->type);
ostr << "%" << inst->ir_seqno << " = getelementptr " << pointer_type->pointed_type->to_IR_string() << ", ";
if (Value::isValueType<GlobalVar>(inst->operand_list[0])) {
auto op0 = Value::asValueType<GlobalVar>(inst->operand_list[0]);
if (Value::is<GlobalVar>(inst->operand_list[0])) {
auto op0 = Value::as<GlobalVar>(inst->operand_list[0]);
ostr << op0->to_IR_string();
}
else if (Value::isValueType<Instruction>(inst->operand_list[0])) {
auto op0 = Value::asValueType<Instruction>(inst->operand_list[0]);
else if (Value::is<Instruction>(inst->operand_list[0])) {
auto op0 = Value::as<Instruction>(inst->operand_list[0]);
ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno;
}
else if (Value::isValueType<FParam>(inst->operand_list[0])) {
auto op0 = Value::asValueType<FParam>(inst->operand_list[0]);
else if (Value::is<FParam>(inst->operand_list[0])) {
auto op0 = Value::as<FParam>(inst->operand_list[0]);
ostr << op0->to_IR_string();
}
else {
@ -399,7 +399,7 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
break;
}
case InstTag::Alloca: {
auto inst = Value::asValueType<InstAlloca>(_inst);
auto inst = Value::as<InstAlloca>(_inst);
assert(inst->ir_seqno != -1);
auto pointer_type = Type::asType<PointerType>(inst->type);
ostr << "%" << inst->ir_seqno << " = alloca " << pointer_type->pointed_type->to_IR_string() << ", align 4";
@ -407,20 +407,20 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
break;
}
case InstTag::Zext: {
auto inst = Value::asValueType<InstZext>(_inst);
auto inst = Value::as<InstZext>(_inst);
assert(inst->ir_seqno >= 0);
ostr << "%" << inst->ir_seqno << " = zext ";
if (Value::isValueType<Instruction>(inst->operand_list[0])) {
auto op0 = Value::asValueType<Instruction>(inst->operand_list[0]);
if (Value::is<Instruction>(inst->operand_list[0])) {
auto op0 = Value::as<Instruction>(inst->operand_list[0]);
assert(op0->ir_seqno >= 0);
ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno << "to ";
}
else if (Value::isValueType<ConstantInt>(inst->operand_list[0])) {
auto op0 = Value::asValueType<ConstantInt>(inst->operand_list[0]);
else if (Value::is<ConstantInt>(inst->operand_list[0])) {
auto op0 = Value::as<ConstantInt>(inst->operand_list[0]);
ostr << op0->to_IR_string() << "to ";
}
else if (Value::isValueType<FParam>(inst->operand_list[0])) {
auto op0 = Value::asValueType<FParam>(inst->operand_list[0]);
else if (Value::is<FParam>(inst->operand_list[0])) {
auto op0 = Value::as<FParam>(inst->operand_list[0]);
ostr << op0->to_IR_string() << "to ";
}
else {