At least, they all compiles
This commit is contained in:
parent
53b6e3e33f
commit
391b529960
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -9,7 +9,7 @@
|
||||
"request": "launch",
|
||||
"name": "Debug",
|
||||
"program": "${workspaceFolder}/build/sysy",
|
||||
"args": ["build/ManualTest/a.c", "-S", "-o", "sss"],
|
||||
"args": ["testcases/functional/64_calculator.sy", "-S", "-o", "build/manual-test/21_my.ll"],
|
||||
"cwd": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
|
||||
@ -90,6 +90,7 @@ class InstStore : public Instruction {
|
||||
public:
|
||||
InstStore(std::shared_ptr<Value> value, std::shared_ptr<Value> pointer, std::shared_ptr<BasicBlock> parent_bb)
|
||||
: Instruction(InstTag::Store, TypeHelper::TYPE_VOID, parent_bb) {
|
||||
assert(value);
|
||||
operand_list.push_back(value);
|
||||
operand_list.push_back(pointer);
|
||||
}
|
||||
@ -198,7 +199,7 @@ public:
|
||||
aim_to = pointer;
|
||||
}
|
||||
else {
|
||||
LOG(WARNING) << "Unexpected pointer type" << pointer->to_string();
|
||||
// LOG(WARNING) << "Unexpected pointer type " << pointer->to_string();
|
||||
aim_to = nullptr;
|
||||
}
|
||||
element_type = extract_type(pointer, indices);
|
||||
@ -215,19 +216,19 @@ public:
|
||||
static TypePtr_t extract_type(ValuePtr_t pointer, const std::vector<ValuePtr_t> &indices) {
|
||||
auto pointer_type = std::dynamic_pointer_cast<PointerType>(pointer->type);
|
||||
auto pointed_type = pointer_type->pointed_type;
|
||||
// ptr->array
|
||||
if (pointed_type->type_tag == Type::TypeTag::ArrayType) {
|
||||
for (int i = 1; i < indices.size(); ++i) {
|
||||
pointed_type = std::dynamic_pointer_cast<ArrayType>(pointed_type)->element_type;
|
||||
}
|
||||
}
|
||||
if (pointed_type->type_tag == Type::TypeTag::IntegerType) {
|
||||
return pointed_type;
|
||||
}
|
||||
else {
|
||||
LOG(WARNING) << "not returning an int-type";
|
||||
else if (Type::isType<ArrayType>(pointed_type)){
|
||||
for (int i = 1; i < indices.size(); ++i) {
|
||||
pointed_type = std::dynamic_pointer_cast<ArrayType>(pointed_type)->element_type;
|
||||
}
|
||||
return pointed_type;
|
||||
}
|
||||
else {
|
||||
LOG(ERROR) << "unexpected type: " << pointer->to_string();
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@ public:
|
||||
template <typename TT>
|
||||
static bool isType(std::shared_ptr<Type> ptr) {
|
||||
if (ptr) {
|
||||
return dynamic_cast<TT*>(ptr.get()) != nullptr;
|
||||
return dynamic_cast<TT *>(ptr.get()) != nullptr;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
@ -136,10 +136,7 @@ public:
|
||||
return "Pointer->" + pointed_type->to_string();
|
||||
}
|
||||
virtual std::string to_IR_string() override {
|
||||
if (pointed_type->type_tag == TypeTag::IntegerType) {
|
||||
return "i32*";
|
||||
}
|
||||
panic("Unknown");
|
||||
return pointed_type->to_IR_string() + "*";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include "3rdparty/easylogging++.h"
|
||||
#include "common.h"
|
||||
#include "llir_type.h"
|
||||
#include <cassert>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <shared_mutex>
|
||||
@ -23,9 +24,10 @@ public:
|
||||
if (ptr.get()) {
|
||||
// auto &r = *ptr.get();
|
||||
// return typeid(r) == typeid(TT);
|
||||
return dynamic_cast<TT*>(ptr.get()) != nullptr;
|
||||
return dynamic_cast<TT *>(ptr.get()) != nullptr;
|
||||
}
|
||||
LOG(WARNING) << "Comparing with nullptr";
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -55,6 +57,12 @@ class FParam : public Value {
|
||||
public:
|
||||
int ir_seqno = -1;
|
||||
FParam(const std::string &name, TypePtr_t type) : Value(name, type) {}
|
||||
virtual std::string to_string() override {
|
||||
return type->to_string() + " @" + name + " %" + std::to_string(ir_seqno);
|
||||
}
|
||||
virtual std::string to_IR_string() override {
|
||||
return type->to_IR_string() + " %" + std::to_string(ir_seqno);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::list<std::shared_ptr<antlrSysY::BasicBlock>>::iterator BasicBlockListNode_t;
|
||||
@ -114,7 +122,7 @@ public:
|
||||
return str;
|
||||
}
|
||||
virtual std::string to_IR_string() override {
|
||||
return to_string();
|
||||
return type->to_IR_string() + " " + std::to_string(value);
|
||||
}
|
||||
};
|
||||
|
||||
@ -157,10 +165,10 @@ class GlobalVar : public Value {
|
||||
public:
|
||||
ConstantPtr_t init_value;
|
||||
bool is_const;
|
||||
GlobalVar(const std::string &name, ConstantPtr_t init_value, bool is_const)
|
||||
: Value(name, PointerType::make_shared(init_value->type)), init_value(init_value), is_const(is_const) {}
|
||||
static std::shared_ptr<GlobalVar> make_shared(const std::string &name, ConstantPtr_t init_value, bool is_const) {
|
||||
return std::make_shared<GlobalVar>(name, init_value, 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) {}
|
||||
static std::shared_ptr<GlobalVar> make_shared(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 {
|
||||
std::string str = type->to_IR_string() + " @" + name;
|
||||
|
||||
@ -79,7 +79,7 @@ class Compiler:
|
||||
|
||||
Print_C.print_procedure(f"Generating {self.scheme}.s")
|
||||
# subprocess.run(f"llc -O3 -march=arm -mcpu=cortex-a72 -float-abi=hard -filetype=asm {ir} -o {asm}".split(), stdout=log_file, stderr=log_file, bufsize=1)
|
||||
completed = subprocess.run(f"llc -O3 --relocation-model=pic {ir} -o {asm}".split(), stdout=log_file, stderr=log_file, bufsize=1)
|
||||
completed = subprocess.run(f"llc --march=x86 --relocation-model=pic {ir} -o {asm}".split(), stdout=log_file, stderr=log_file, bufsize=1)
|
||||
if completed.returncode != 0:
|
||||
Print_C.print_error(f"Generating {self.scheme}.s failed! See {log} | {ir}")
|
||||
self.count_error += 1
|
||||
@ -96,7 +96,7 @@ class Compiler:
|
||||
|
||||
Print_C.print_procedure(f"Generating {self.scheme}.o")
|
||||
# subprocess.run(f"as -march=armv7-a -mfloat-abi=hard {asm} -o {obj}".split(), stdout=log_file, stderr=log_file, bufsize=1)
|
||||
completed = subprocess.run(f"as {asm} -o {obj}".split(), stdout=log_file, stderr=log_file, bufsize=1)
|
||||
completed = subprocess.run(f"as --32 {asm} -o {obj}".split(), stdout=log_file, stderr=log_file, bufsize=1)
|
||||
if completed.returncode != 0:
|
||||
Print_C.print_error(f"Generating {self.scheme}.o failed! See {log}")
|
||||
self.count_error += 1
|
||||
@ -111,7 +111,7 @@ class Compiler:
|
||||
|
||||
Print_C.print_procedure(f"Generating {self.scheme}")
|
||||
# subprocess.run(f"clang -Ofast -marm -march=armv7-a -mfpu=neon -mfloat-abi=hard {obj} {lib} -o {bin}".split(), stdout=log_file, stderr=log_file, bufsize=1)
|
||||
completed = subprocess.run(f"clang -Ofast -fPIE {obj} {lib} -o {bin}".split(), stdout=log_file, stderr=log_file, bufsize=1)
|
||||
completed = subprocess.run(f"clang -m32 -Ofast -fPIE {obj} {lib} -o {bin}".split(), stdout=log_file, stderr=log_file, bufsize=1)
|
||||
if completed.returncode != 0:
|
||||
Print_C.print_error(f"Linking {self.scheme} failed! See {log}")
|
||||
self.count_error += 1
|
||||
@ -155,6 +155,9 @@ class Compiler:
|
||||
for testcase in self.testcases:
|
||||
Print_C.print_subheader(f"[Compiling {self.scheme} | {testcase}]")
|
||||
self.sy_to_ir(frontend_instr=frontend_instr, testcase=testcase, category=category)
|
||||
self.ir_to_asm(testcase=testcase)
|
||||
self.asm_to_obj(testcase=testcase)
|
||||
self.obj_to_bin(testcase=testcase)
|
||||
if self.count_error >= 1:
|
||||
Print_C.print_error(f"Test script stopped due to too many errors")
|
||||
return
|
||||
|
||||
@ -6,8 +6,15 @@ print("compile {}".format(sys.argv[1]))
|
||||
fullpath = sys.argv[1]
|
||||
libpath = sys.argv[2]
|
||||
(filename, extname) = os.path.splitext(sys.argv[1])
|
||||
|
||||
os.system(f"clang -emit-llvm -S {fullpath} -o {filename}.ll -O0 -fno-builtin")
|
||||
os.system(f"llc{filename}.ll -o {filename}.s")
|
||||
os.system(f"as {filename}.s -o {filename}.o")
|
||||
os.system(f"clang {filename}.o {libpath} -o {filename}")
|
||||
'''
|
||||
python3 scripts/manual-compile.py build/manual-test/55_sort_test1.sy tools/sylib/libsysy_x86.a
|
||||
'''
|
||||
# os.system(f"clang -emit-llvm -S {fullpath} -o {filename}.ll -O0 -fno-builtin")
|
||||
print(f"clang -x c -c -m32 -emit-llvm -S {fullpath} -o {filename}.ll -O0 -fno-builtin")
|
||||
os.system(f"clang -x c -c -m32 -emit-llvm -S {fullpath} -o {filename}.ll -O0 -fno-builtin")
|
||||
print(f"llc --march=x86 --relocation-model=pic {filename}.ll -o {filename}.s")
|
||||
os.system(f"llc --march=x86 --relocation-model=pic {filename}.ll -o {filename}.s")
|
||||
print(f"as --32 {filename}.s -o {filename}.o")
|
||||
os.system(f"as --32 {filename}.s -o {filename}.o")
|
||||
print(f"clang -m32 -fPIE {filename}.o {libpath} -o {filename}")
|
||||
os.system(f"clang -m32 -fPIE {filename}.o {libpath} -o {filename}")
|
||||
3
scripts/sylib-gen.sh
Normal file
3
scripts/sylib-gen.sh
Normal file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
clang -c -m32 -fPIC tools/sylib/sylib.c -include tools/sylib/sylib.h -o tools/sylib/sylib.o
|
||||
ar rcs tools/sylib/libsysy_x86.a tools/sylib/sylib.o
|
||||
@ -88,7 +88,7 @@ my_scheme = {"scheme": "my",
|
||||
"emit_llvm_ir": False}
|
||||
|
||||
llir_scheme = {"scheme": "llir",
|
||||
"frontend_instr": "clang -x c -c -fPIE -S -emit-llvm -include {header} {sy} -o {ir}",
|
||||
"frontend_instr": "clang -x c -c -fPIE -m32 -S -emit-llvm -include {header} {sy} -o {ir}",
|
||||
"emit_llvm_ir": True}
|
||||
|
||||
# gcc -c -fPIC -o sylib.o -include sylib.h sylib.c && ar rcs libsysy_x86.a sylib.o
|
||||
@ -123,8 +123,8 @@ if __name__ == '__main__':
|
||||
subprocess.run("rm -rf build/log/run_log".split())
|
||||
subprocess.run("rm -rf build/log/test_result.log".split())
|
||||
|
||||
# Tester(my_scheme, True, testcases).compile_rubbish(category=category)
|
||||
Tester(llir_scheme, True, testcases).compile_reference(category=category)
|
||||
Tester(my_scheme, True, testcases).compile_rubbish(category=category)
|
||||
# Tester(llir_scheme, True, testcases).compile_reference(category=category)
|
||||
|
||||
# for scheme in all_schemes:
|
||||
# tester = Tester(scheme, is_trivial=True)
|
||||
|
||||
@ -60,6 +60,7 @@ int main(int argc, const char **argv) {
|
||||
defaultConf.set(el::Level::Debug, el::ConfigurationType::Format, "%level %loc %msg");
|
||||
defaultConf.set(el::Level::Warning, el::ConfigurationType::Format, "%level %loc %msg");
|
||||
defaultConf.set(el::Level::Error, el::ConfigurationType::Format, "%level %loc %msg");
|
||||
defaultConf.set(el::Level::Info, el::ConfigurationType::Format, "%level %loc %msg");
|
||||
el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput);
|
||||
el::Loggers::reconfigureLogger("default", defaultConf);
|
||||
#pragma endregion
|
||||
@ -85,7 +86,7 @@ int main(int argc, const char **argv) {
|
||||
auto tree = parser.program();
|
||||
Visitor visitor(lexer);
|
||||
visitor.visitProgram(tree);
|
||||
auto llir_file = source_file + ".ll";
|
||||
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;
|
||||
|
||||
@ -2,9 +2,11 @@
|
||||
#include "3rdparty/easylogging++.h"
|
||||
#include "SysyLexer.h"
|
||||
#include "common.h"
|
||||
#include "llir_instruction.h"
|
||||
#include "llir_type.h"
|
||||
#include "llir_value.h"
|
||||
#include <any>
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -159,16 +161,16 @@ std::any Visitor::visitConstDef(SysyParser::ConstDefContext *ctx) {
|
||||
base_ptr = build_InstGEP(base_ptr, {CONST0, CONST0}, _state.current_bb);
|
||||
}
|
||||
// we store the elements in 1-dim shape
|
||||
build_InstStore(array_value[0], base_ptr, _state.current_bb);
|
||||
build_InstStore(array_value[0] ? array_value[0] : CONST0, base_ptr, _state.current_bb);
|
||||
for (int i = 1; i < array_value.size(); ++i) {
|
||||
auto ptr = build_InstGEP(base_ptr, {ConstantInt::make_shared(i)}, _state.current_bb);
|
||||
build_InstStore(array_value[i], ptr, _state.current_bb);
|
||||
build_InstStore(array_value[i] ? array_value[i] : CONST0, ptr, _state.current_bb);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// global const array
|
||||
auto const_arr = ConstantArr::make_shared("const_arr", array_value, array_type);
|
||||
auto global_var = GlobalVar::make_shared(const_name, const_arr, true);
|
||||
auto global_var = GlobalVar::make_shared(const_name, array_type, const_arr, true);
|
||||
module.global_var_list.push_back(global_var);
|
||||
_scope_tab.push_name(const_name, global_var);
|
||||
}
|
||||
@ -191,12 +193,12 @@ std::any Visitor::visitVarDef(SysyParser::VarDefContext *ctx) {
|
||||
_state.isGlobalIint = true;
|
||||
auto result = std::any_cast<std::shared_ptr<ConstantInt>>(visitInitVal(ctx->initVal()));
|
||||
_state.isGlobalIint = false;
|
||||
auto global_var_int = std::make_shared<GlobalVar>(var_name, result, false);
|
||||
auto global_var_int = GlobalVar::make_shared(var_name, result->type,result, false);
|
||||
module.global_var_list.push_back(global_var_int);
|
||||
_scope_tab.push_name(var_name, global_var_int);
|
||||
}
|
||||
else {
|
||||
auto global_var_int = std::make_shared<GlobalVar>(var_name, CONST0, false);
|
||||
auto global_var_int = GlobalVar::make_shared(var_name, CONST0->type,CONST0, false);
|
||||
module.global_var_list.push_back(global_var_int);
|
||||
_scope_tab.push_name(var_name, global_var_int);
|
||||
}
|
||||
@ -236,10 +238,10 @@ std::any Visitor::visitVarDef(SysyParser::VarDefContext *ctx) {
|
||||
base_ptr = build_InstGEP(base_ptr, {CONST0, CONST0}, _state.current_bb);
|
||||
}
|
||||
// TODO: BAAU-2021 calls memset in `libc` (not sysylib) to optimize this process
|
||||
build_InstStore(array_value[0], base_ptr, _state.current_bb);
|
||||
build_InstStore(array_value[0] ? array_value[0] : CONST0, base_ptr, _state.current_bb);
|
||||
for (int i = 1; i < array_value.size(); ++i) {
|
||||
auto ptr = build_InstGEP(base_ptr, {ConstantInt::make_shared(i)}, _state.current_bb);
|
||||
build_InstStore(array_value[i], ptr, _state.current_bb);
|
||||
build_InstStore(array_value[i] ? array_value[i] : CONST0, ptr, _state.current_bb);
|
||||
}
|
||||
}
|
||||
// If there is no init expr, let it be
|
||||
@ -256,12 +258,12 @@ std::any Visitor::visitVarDef(SysyParser::VarDefContext *ctx) {
|
||||
sysy_assert(_state.arr_dim_index == 0);
|
||||
_state.isGlobalIint = false;
|
||||
auto const_arr = ConstantArr::make_shared("var_arr", array_value, array_type);
|
||||
auto global_var = GlobalVar::make_shared(var_name, const_arr, false);
|
||||
auto global_var = GlobalVar::make_shared(var_name, const_arr->type, const_arr, false);
|
||||
module.global_var_list.push_back(global_var);
|
||||
_scope_tab.push_name(var_name, global_var);
|
||||
}
|
||||
else {
|
||||
auto global_var = GlobalVar::make_shared(var_name, CONST0, false);
|
||||
auto global_var = GlobalVar::make_shared(var_name, array_type, nullptr, false);
|
||||
module.global_var_list.push_back(global_var);
|
||||
_scope_tab.push_name(var_name, global_var);
|
||||
}
|
||||
@ -486,10 +488,18 @@ std::any Visitor::visitRelExp(SysyParser::RelExpContext *ctx) {
|
||||
// eqExp: relExp | eqExp ('==' | '!=') relExp;
|
||||
std::any Visitor::visitEqExp(SysyParser::EqExpContext *ctx) {
|
||||
auto rel_exp = any_to_Value(visitRelExp(ctx->relExp()));
|
||||
// sysy_assert(TypeHelper::isIntegerTypeI1(rel_exp->type));
|
||||
bool need_zext = false;
|
||||
if (ctx->eqExp()) {
|
||||
auto eq_exp = any_to_Value(visitEqExp(ctx->eqExp()));
|
||||
// sysy_assert(TypeHelper::isIntegerTypeI1(eq_exp->type));
|
||||
if (TypeHelper::isIntegerTypeI32(eq_exp->type) || TypeHelper::isIntegerTypeI32(rel_exp->type)) {
|
||||
need_zext = true;
|
||||
}
|
||||
if (need_zext && TypeHelper::isIntegerTypeI1(eq_exp->type)) {
|
||||
eq_exp = build_InstZext(eq_exp, _state.current_bb);
|
||||
}
|
||||
if (need_zext && TypeHelper::isIntegerTypeI1(rel_exp->type)) {
|
||||
rel_exp = build_InstZext(rel_exp, _state.current_bb);
|
||||
}
|
||||
if (ctx->EQ()) {
|
||||
rel_exp = build_InstBinary(InstTag::Eq, eq_exp, rel_exp, _state.current_bb);
|
||||
}
|
||||
@ -606,7 +616,10 @@ std::any Visitor::visitUnaryExp(SysyParser::UnaryExpContext *ctx) {
|
||||
for (int i = 0; i < rparams.size(); ++i) {
|
||||
auto rparam = rparams[i];
|
||||
auto fparam = fparams[i];
|
||||
_state.isRealParam = true;
|
||||
if (Type::isType<IntegerType>(fparam->type)) _state.isRealParam = false;
|
||||
auto exp = any_to_Value(visitExp(rparam->exp()));
|
||||
_state.isRealParam = false;
|
||||
args.push_back(exp);
|
||||
}
|
||||
}
|
||||
@ -645,7 +658,7 @@ std::any Visitor::visitPrimaryExp(SysyParser::PrimaryExpContext *ctx) {
|
||||
else if (ctx->lVal()) {
|
||||
if (_state.isRealParam) {
|
||||
_state.isRealParam = false;
|
||||
LOG(WARNING) << "isRealParam";
|
||||
VLOG(5) << "isRealParam:" << ctx->getStart()->getLine();
|
||||
return visitLVal(ctx->lVal());
|
||||
}
|
||||
else {
|
||||
@ -657,7 +670,7 @@ std::any Visitor::visitPrimaryExp(SysyParser::PrimaryExpContext *ctx) {
|
||||
}
|
||||
// @retval: InstLoad
|
||||
else {
|
||||
LOG(WARNING) << "lval type is pointer: " << lval->type->type_tag;
|
||||
// LOG(WARNING) << "lval type is pointer: " << lval->type->type_tag;
|
||||
// should be InstAlloca
|
||||
auto ptr_type = std::dynamic_pointer_cast<PointerType>(lval->type);
|
||||
return build_InstLoad(lval, ptr_type->pointed_type, _state.current_bb);
|
||||
@ -716,7 +729,8 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
|
||||
return lval;
|
||||
}
|
||||
else {
|
||||
LOG(WARNING) << "Unexpected array referece";
|
||||
LOG(WARNING) << "Unexpected array referece" << lval->to_string()
|
||||
<< " : "<< ctx->getStart()->getLine();
|
||||
// array index, perhaps
|
||||
// @retval: InstGEP
|
||||
auto gep = lval;
|
||||
@ -728,7 +742,6 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
|
||||
}
|
||||
};
|
||||
case Type::TypeTag::PointerType: {
|
||||
sysy_assert(0);
|
||||
if (ctx->exp().empty()) {
|
||||
// ??? Pointer
|
||||
// @retval: InstLoad
|
||||
@ -739,19 +752,26 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
|
||||
}
|
||||
else {
|
||||
// fparam array, whose first dim is represented by a pointer
|
||||
auto pointed_type = std::dynamic_pointer_cast<PointerType>(lval->type)->pointed_type;
|
||||
auto pointed_type = Type::asType<PointerType>(lval->type)->pointed_type;
|
||||
auto inst_load = build_InstLoad(lval, pointed_type, _state.current_bb);
|
||||
|
||||
LOG(INFO) << lval->to_string() << " " << lval->type->to_string();
|
||||
auto ptr = build_InstGEP(inst_load, {CONST0}, _state.current_bb);
|
||||
pointed_type = std::dynamic_pointer_cast<PointerType>(ptr->type)->pointed_type;
|
||||
LOG(INFO) << pointed_type->to_string();
|
||||
sysy_assert(pointed_type->type_tag == Type::TypeTag::ArrayType);
|
||||
ValuePtr_t offset = ConstantInt::make_shared(0);
|
||||
auto exp_list = ctx->exp();
|
||||
if (exp_list.size() == 1) {
|
||||
auto exp_val = any_to_Value(visitExp(exp_list[0]));
|
||||
auto ptr = build_InstGEP(inst_load, {exp_val}, _state.current_bb);
|
||||
pointed_type = Type::asType<PointerType>(ptr->type)->pointed_type;
|
||||
assert(Type::isType<IntegerType>(pointed_type));
|
||||
return ptr;
|
||||
}
|
||||
// LOG(INFO) << lval->to_string() << " " << lval->type->to_string();
|
||||
auto ptr = build_InstGEP(inst_load, {CONST0}, _state.current_bb);
|
||||
pointed_type = Type::asType<PointerType>(ptr->type)->pointed_type;
|
||||
ValuePtr_t offset = ConstantInt::make_shared(0);
|
||||
// LOG(INFO) << pointed_type->to_string();
|
||||
assert(Type::isType<ArrayType>(pointed_type));
|
||||
|
||||
// calculate offset by hand: offset = (offset + exp[i]) * dim_size[i]
|
||||
for (int i = 0; i < exp_list.size() - 1; ++i) {
|
||||
sysy_assert(typeid(pointed_type) == typeid(std::shared_ptr<ArrayType>));
|
||||
sysy_assert(Type::isType<ArrayType>(pointed_type));
|
||||
auto array_type = std::dynamic_pointer_cast<ArrayType>(pointed_type);
|
||||
auto exp_val = any_to_Value(visitExp(exp_list[i]));
|
||||
auto dim_size = ConstantInt::make_shared(array_type->element_count);
|
||||
@ -846,13 +866,21 @@ std::any Visitor::visitFuncDef(SysyParser::FuncDefContext *ctx) {
|
||||
visitBlock(ctx->block());
|
||||
// add return
|
||||
// _scope_tab.leave_scope();
|
||||
// TODO: avoid duplicate ret
|
||||
// there may be an empty bb in the end
|
||||
|
||||
// avoid duplicate ret
|
||||
if (func_obj->bb_list.back()->inst_list.size() == 0 && func_obj->bb_list.back()->name == "after_ret") {
|
||||
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())){
|
||||
if (func_ret_type->type_tag == Type::TypeTag::VoidType) {
|
||||
build_InstReturn(_state.current_bb);
|
||||
}
|
||||
else {
|
||||
build_InstReturn(CONST0, _state.current_bb);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -880,16 +908,18 @@ std::any Visitor::visitFuncFParam(SysyParser::FuncFParamContext *ctx) {
|
||||
else {
|
||||
// array type
|
||||
std::vector<int> dim_list = {0}; // the first dim must be empty, though
|
||||
TypePtr_t array_type = TypeHelper::TYPE_I32;
|
||||
for (auto exp_ctx : ctx->exp()) {
|
||||
_state.isConstInt = true;
|
||||
auto exp_val = std::dynamic_pointer_cast<ConstantInt>(any_to_Value(visitExp(exp_ctx)));
|
||||
_state.isConstInt = false;
|
||||
dim_list.push_back(exp_val->value);
|
||||
array_type = std::make_shared<ArrayType>(array_type, exp_val->value);
|
||||
}
|
||||
auto array_type = ArrayType::build_from_list(dim_list);
|
||||
// auto true_array_type = std::make_shared<PointerType>(array_type);
|
||||
// return {true_array_type};
|
||||
return {array_type};
|
||||
// auto array_type = ArrayType::build_from_list(dim_list);
|
||||
auto true_array_type = std::make_shared<PointerType>(array_type);
|
||||
return {true_array_type};
|
||||
// return {array_type};
|
||||
}
|
||||
}
|
||||
|
||||
@ -995,6 +1025,8 @@ std::any Visitor::visitReturnStmt(SysyParser::ReturnStmtContext *ctx) {
|
||||
else {
|
||||
build_InstReturn(_state.current_bb);
|
||||
}
|
||||
auto new_bb = build_BasicBlock("after_ret", _state.current_func, _state.current_bb->itr);
|
||||
_state.current_bb = new_bb;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include "llir_type.h"
|
||||
#include "llir_value.h"
|
||||
#include "visitor.h"
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
namespace antlrSysY {
|
||||
@ -65,6 +66,15 @@ std::shared_ptr<InstBinary> build_InstBinary(
|
||||
else {
|
||||
panic("Invalid Binary Operation");
|
||||
}
|
||||
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)) {
|
||||
LOG(ERROR) << op1->to_string() << ",\t" << op2->to_string();
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
parent_bb->inst_list.push_back(inst_binary);
|
||||
return inst_binary;
|
||||
}
|
||||
|
||||
@ -81,6 +81,7 @@ static void _build_arr_init_list(
|
||||
ostr << "]";
|
||||
}
|
||||
else {
|
||||
ostr << arr_type->to_IR_string() << " ";
|
||||
ostr << "[";
|
||||
for (int i = 0; i < arr->value_list.size(); ++i) {
|
||||
if (arr->value_list[i])
|
||||
@ -102,11 +103,12 @@ static void _build_arr_init_list(
|
||||
}
|
||||
}
|
||||
|
||||
static void _gen_blocks(const std::list<BasicBlockPtr_t> &block_list, int reg_count) {
|
||||
std::stringstream ostr;
|
||||
static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &block_list, int reg_count) {
|
||||
// first pass, allocate sequence number
|
||||
for (auto block_itr = block_list.begin(); block_itr != block_list.end(); ++block_itr) {
|
||||
auto block = *block_itr;
|
||||
sysy_assert(block->ir_seqno == -1); // multi-alloc is error
|
||||
block->ir_seqno = reg_count++;
|
||||
for (int j = 0; j < block->inst_list.size(); ++j) {
|
||||
auto inst = block->inst_list[j];
|
||||
sysy_assert(inst->ir_seqno == -1); // multi-alloc is error
|
||||
@ -143,10 +145,6 @@ static void _gen_blocks(const std::list<BasicBlockPtr_t> &block_list, int reg_co
|
||||
default: panic("Unexpected instruction");
|
||||
}
|
||||
}
|
||||
sysy_assert(block->ir_seqno == -1); // multi-alloc is error
|
||||
if (block_itr != block_list.begin()) {
|
||||
block->ir_seqno = reg_count++;
|
||||
}
|
||||
}
|
||||
// second pass, generate IR
|
||||
for (auto block_itr = block_list.begin(); block_itr != block_list.end(); ++block_itr) {
|
||||
@ -156,12 +154,11 @@ static void _gen_blocks(const std::list<BasicBlockPtr_t> &block_list, int reg_co
|
||||
}
|
||||
for (int j = 0; j < block->inst_list.size(); ++j) {
|
||||
auto _inst = block->inst_list[j];
|
||||
|
||||
VLOG(5) << "Build inst" << _inst->ir_seqno << ": " << _inst->to_string();
|
||||
switch (_inst->tag) {
|
||||
case InstTag::Br: {
|
||||
auto inst = Value::asValueType<InstBranch>(_inst);
|
||||
assert(inst->ir_seqno == -1);
|
||||
std::stringstream ostr;
|
||||
ostr << "br ";
|
||||
if (inst->operand_list.size() == 1) {
|
||||
assert(Value::isValueType<BasicBlock>(inst->operand_list[0]));
|
||||
@ -202,7 +199,11 @@ static void _gen_blocks(const std::list<BasicBlockPtr_t> &block_list, int reg_co
|
||||
}
|
||||
else if (Value::isValueType<ConstantInt>(inst->operand_list[0])) {
|
||||
auto op0 = Value::asValueType<ConstantInt>(inst->operand_list[0]);
|
||||
ostr << op0->to_string();
|
||||
ostr << op0->to_IR_string();
|
||||
}
|
||||
else if (Value::isValueType<FParam>(inst->operand_list[0])) {
|
||||
auto op0 = Value::asValueType<FParam>(inst->operand_list[0]);
|
||||
ostr << op0->to_IR_string();
|
||||
}
|
||||
else {
|
||||
LOG(ERROR) << "Unexpected type of op0: " << inst->operand_list[0]->to_string();
|
||||
@ -215,8 +216,7 @@ static void _gen_blocks(const std::list<BasicBlockPtr_t> &block_list, int reg_co
|
||||
auto inst = Value::asValueType<InstStore>(_inst);
|
||||
assert(inst->ir_seqno == -1);
|
||||
ostr << "store ";
|
||||
assert(Type::isType<IntegerType>(inst->operand_list[0]->type));
|
||||
assert(Type::isType<PointerType>(inst->operand_list[1]->type));
|
||||
|
||||
if (Value::isValueType<Instruction>(inst->operand_list[0])) {
|
||||
auto op0 = Value::asValueType<Instruction>(inst->operand_list[0]);
|
||||
assert(op0->ir_seqno >= 0);
|
||||
@ -224,7 +224,11 @@ static void _gen_blocks(const std::list<BasicBlockPtr_t> &block_list, int reg_co
|
||||
}
|
||||
else if (Value::isValueType<ConstantInt>(inst->operand_list[0])) {
|
||||
auto op0 = Value::asValueType<ConstantInt>(inst->operand_list[0]);
|
||||
ostr << "i32 " << op0->value << ", ";
|
||||
ostr << op0->to_IR_string() << ", ";
|
||||
}
|
||||
else if (Value::isValueType<FParam>(inst->operand_list[0])) {
|
||||
auto op0 = Value::asValueType<FParam>(inst->operand_list[0]);
|
||||
ostr << op0->to_IR_string() << ", ";
|
||||
}
|
||||
else {
|
||||
LOG(ERROR) << "Unexpected type of op0: " << inst->operand_list[0]->to_string();
|
||||
@ -239,6 +243,10 @@ static void _gen_blocks(const std::list<BasicBlockPtr_t> &block_list, int reg_co
|
||||
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]);
|
||||
ostr << op0->to_IR_string();
|
||||
}
|
||||
else {
|
||||
LOG(ERROR) << "Unexpected type of op1: " << inst->operand_list[1]->to_string();
|
||||
assert(0);
|
||||
@ -247,7 +255,8 @@ static void _gen_blocks(const std::list<BasicBlockPtr_t> &block_list, int reg_co
|
||||
}
|
||||
// Call's seqno is dependent on its return type
|
||||
case InstTag::Call: {
|
||||
auto inst = Value::asValueType<InstReturn>(_inst);
|
||||
auto inst = Value::asValueType<InstCall>(_inst);
|
||||
LOG(DEBUG) << inst->operand_list[0]->to_string();
|
||||
auto func = Value::asValueType<Function>(inst->operand_list[0]);
|
||||
auto func_type = Type::asType<FunctionType>(func->type);
|
||||
if (Type::isType<VoidType>(func_type->return_type)) {
|
||||
@ -268,7 +277,11 @@ static void _gen_blocks(const std::list<BasicBlockPtr_t> &block_list, int reg_co
|
||||
}
|
||||
else if (Value::isValueType<ConstantInt>(inst->operand_list[i])) {
|
||||
auto op0 = Value::asValueType<ConstantInt>(inst->operand_list[i]);
|
||||
ostr << op0->to_string();
|
||||
ostr << op0->to_IR_string();
|
||||
}
|
||||
else if (Value::isValueType<FParam>(inst->operand_list[i])) {
|
||||
auto op0 = Value::asValueType<FParam>(inst->operand_list[i]);
|
||||
ostr << op0->to_IR_string() << ", ";
|
||||
}
|
||||
else {
|
||||
LOG(ERROR) << "Unexpected type of op_i: " << inst->operand_list[i]->to_string();
|
||||
@ -295,7 +308,7 @@ static void _gen_blocks(const std::list<BasicBlockPtr_t> &block_list, int reg_co
|
||||
case InstTag::And:
|
||||
case InstTag::Or: {
|
||||
auto inst = Value::asValueType<InstBinary>(_inst);
|
||||
ostr << "%" << inst->ir_seqno << " = " << inst->to_string();
|
||||
ostr << "%" << inst->ir_seqno << " = " << inst->to_string() << " ";
|
||||
if (Value::isValueType<Instruction>(inst->operand_list[0])) {
|
||||
auto op0 = Value::asValueType<Instruction>(inst->operand_list[0]);
|
||||
assert(op0->ir_seqno >= 0);
|
||||
@ -303,7 +316,11 @@ static void _gen_blocks(const std::list<BasicBlockPtr_t> &block_list, int reg_co
|
||||
}
|
||||
else if (Value::isValueType<ConstantInt>(inst->operand_list[0])) {
|
||||
auto op0 = Value::asValueType<ConstantInt>(inst->operand_list[0]);
|
||||
ostr << op0->to_string() << ", ";
|
||||
ostr << op0->to_IR_string() << ", ";
|
||||
}
|
||||
else if (Value::isValueType<FParam>(inst->operand_list[0])) {
|
||||
auto op0 = Value::asValueType<FParam>(inst->operand_list[0]);
|
||||
ostr << op0->to_IR_string() << ", ";
|
||||
}
|
||||
else {
|
||||
LOG(ERROR) << "Unexpected type of op0: " << inst->operand_list[0]->to_string();
|
||||
@ -318,6 +335,10 @@ static void _gen_blocks(const std::list<BasicBlockPtr_t> &block_list, int reg_co
|
||||
auto op1 = Value::asValueType<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]);
|
||||
ostr << "%" << op1->ir_seqno;
|
||||
}
|
||||
else {
|
||||
LOG(ERROR) << "Unexpected type of op1: " << inst->operand_list[1]->to_string();
|
||||
assert(0);
|
||||
@ -338,6 +359,10 @@ static void _gen_blocks(const std::list<BasicBlockPtr_t> &block_list, int reg_co
|
||||
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]);
|
||||
ostr << op0->to_IR_string();
|
||||
}
|
||||
else {
|
||||
LOG(ERROR) << "Unexpected type of op0: " << inst->operand_list[1]->to_string();
|
||||
assert(0);
|
||||
@ -348,7 +373,6 @@ static void _gen_blocks(const std::list<BasicBlockPtr_t> &block_list, int reg_co
|
||||
auto inst = Value::asValueType<InstGEP>(_inst);
|
||||
|
||||
assert(inst->ir_seqno >= 0);
|
||||
std::stringstream ostr;
|
||||
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])) {
|
||||
@ -359,6 +383,10 @@ static void _gen_blocks(const std::list<BasicBlockPtr_t> &block_list, int reg_co
|
||||
auto op0 = Value::asValueType<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]);
|
||||
ostr << op0->to_IR_string();
|
||||
}
|
||||
else {
|
||||
LOG(WARNING) << "Unexpected type of op0: " << inst->operand_list[0]->to_string();
|
||||
assert(0);
|
||||
@ -371,22 +399,26 @@ static void _gen_blocks(const std::list<BasicBlockPtr_t> &block_list, int reg_co
|
||||
case InstTag::Alloca: {
|
||||
auto inst = Value::asValueType<InstAlloca>(_inst);
|
||||
assert(inst->ir_seqno != -1);
|
||||
ostr << "%" << inst->ir_seqno << " = alloca i32, align 4";
|
||||
auto pointer_type = Type::asType<PointerType>(inst->type);
|
||||
ostr << "%" << inst->ir_seqno << " = alloca " << pointer_type->pointed_type->to_IR_string() << ", align 4";
|
||||
break;
|
||||
}
|
||||
case InstTag::Zext: {
|
||||
auto inst = Value::asValueType<InstZext>(_inst);
|
||||
assert(inst->ir_seqno >= 0);
|
||||
std::stringstream ostr;
|
||||
ostr << "%" << inst->ir_seqno << " = zext ";
|
||||
if (Value::isValueType<Instruction>(inst->operand_list[0])) {
|
||||
auto op0 = Value::asValueType<Instruction>(inst->operand_list[0]);
|
||||
assert(op0->ir_seqno >= 0);
|
||||
ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno << ", ";
|
||||
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]);
|
||||
ostr << op0->to_string() << ", ";
|
||||
ostr << op0->to_IR_string() << "to ";
|
||||
}
|
||||
else if (Value::isValueType<FParam>(inst->operand_list[0])) {
|
||||
auto op0 = Value::asValueType<FParam>(inst->operand_list[0]);
|
||||
ostr << op0->to_IR_string() << "to ";
|
||||
}
|
||||
else {
|
||||
LOG(ERROR) << "Unexpected type of op0: " << inst->operand_list[0]->to_string();
|
||||
@ -398,6 +430,7 @@ static void _gen_blocks(const std::list<BasicBlockPtr_t> &block_list, int reg_co
|
||||
// These should not be generated in frontend stage
|
||||
default: panic("Unexpected instruction");
|
||||
}
|
||||
ostr << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -427,7 +460,7 @@ void Visitor::llir_gen(std::ostream &ostr) {
|
||||
LOG(DEBUG) << "Gen Global " << global_var->name;
|
||||
ostr << "@" << global_var->name << " = "
|
||||
<< "dso_local"
|
||||
<< " " << (global_var->is_const ? "const" : "global") << " ";
|
||||
<< " " << (global_var->is_const ? "constant" : "global") << " ";
|
||||
auto global_var_type = std::dynamic_pointer_cast<PointerType>(global_var->type);
|
||||
if (global_var_type->pointed_type->type_tag == Type::TypeTag::IntegerType) {
|
||||
auto init_value = std::dynamic_pointer_cast<ConstantInt>(global_var->init_value);
|
||||
@ -438,15 +471,19 @@ void Visitor::llir_gen(std::ostream &ostr) {
|
||||
// sysy_assert(global_var->)
|
||||
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);
|
||||
if (init_value != nullptr) {
|
||||
auto hierarchy_array = gen_arr_hierarchy(array_type, init_value->value_list, 0, init_value->value_list.size());
|
||||
if (hierarchy_array) {
|
||||
// LOG(DEBUG) << hierarchy_array->to_string();
|
||||
ostr << array_type->to_IR_string() << " ";
|
||||
_build_arr_init_list(ostr, hierarchy_array, array_type);
|
||||
}
|
||||
else {
|
||||
ostr << array_type->to_IR_string() << " zeroinitializer";
|
||||
}
|
||||
}
|
||||
else {
|
||||
ostr << array_type->to_IR_string() << " zeroinitializer";
|
||||
}
|
||||
ostr << ", align 4" << std::endl;
|
||||
}
|
||||
else {
|
||||
@ -468,11 +505,15 @@ void Visitor::llir_gen(std::ostream &ostr) {
|
||||
ostr << "(";
|
||||
auto ¶m_list = func->fparam_list;
|
||||
for (int i = 0; i < (int)param_list.size() - 1; ++i) {
|
||||
ostr << param_list[i]->type->to_IR_string() << " %" << reg_count++ << ", ";
|
||||
param_list[i]->ir_seqno = reg_count++;
|
||||
ostr << param_list[i]->to_IR_string() << ", ";
|
||||
}
|
||||
if (param_list.size()) {
|
||||
param_list.back()->ir_seqno = reg_count++;
|
||||
ostr << param_list.back()->to_IR_string();
|
||||
}
|
||||
if (param_list.size()) ostr << param_list.back()->type->to_IR_string();
|
||||
ostr << ") {" << std::endl;
|
||||
_gen_blocks(func->bb_list, reg_count);
|
||||
_gen_blocks(ostr, func->bb_list, reg_count);
|
||||
ostr << "}" << std::endl;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
BIN
tools/sylib/libsysy_x64.a
Normal file
BIN
tools/sylib/libsysy_x64.a
Normal file
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user