buggy buggy frontend

This commit is contained in:
ridethepig 2023-05-07 21:59:04 +08:00
parent 619145bf22
commit dd48562daa
7 changed files with 470 additions and 109 deletions

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "common.h"
#include <memory> #include <memory>
#include <vector> #include <vector>
namespace antlrSysY { namespace antlrSysY {
@ -69,6 +70,14 @@ public:
ArrayType() : Type(TypeTag::ArrayType) {} ArrayType() : Type(TypeTag::ArrayType) {}
ArrayType(TypePtr_t element_type, int element_count) ArrayType(TypePtr_t element_type, int element_count)
: Type(TypeTag::ArrayType), element_count(element_count), element_type(element_type) {} : Type(TypeTag::ArrayType), element_count(element_count), element_type(element_type) {}
static std::shared_ptr<ArrayType> build_from_list(const std::vector<int> &dim_list) {
TypePtr_t array_type = TypeHelper::TYPE_I32;
sysy_assert(dim_list.size() != 0);
for (auto itr = dim_list.rbegin(); itr != dim_list.rend(); ++itr) {
array_type = std::make_shared<ArrayType>(array_type, *itr);
}
return std::dynamic_pointer_cast<ArrayType>(array_type);
}
}; };
class PointerType : public Type { class PointerType : public Type {

View File

@ -5,6 +5,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "common.h"
#include "llir_type.h" #include "llir_type.h"
namespace antlrSysY { namespace antlrSysY {
@ -50,18 +51,46 @@ public:
} }
}; };
class ConstantInt : public Value { typedef std::shared_ptr<Value> ValuePtr_t;
typedef std::shared_ptr<BasicBlock> BasicBlockPtr_t;
typedef std::shared_ptr<Function> FunctionPtr_t;
class Constant : public Value {
public: public:
int value; Constant(const std::string &name, TypePtr_t type) : Value(name, type) {}
ConstantInt(const std::string &name, int value) : Value(name, TypeHelper::TYPE_I32), value(value) {}
}; };
class ConstantArr : public Value {}; class ConstantInt : public Constant {
class GlobalVarInt : public Value {
public: public:
int init_value; int value;
GlobalVarInt(const std::string &name, int init_value) : Value(name, TypeHelper::TYPE_I32), init_value(init_value) {} ConstantInt(const std::string &name, int value) : Constant(name, TypeHelper::TYPE_I32), value(value) {}
static std::shared_ptr<ConstantInt> make_shared(int value) {
return std::make_shared<ConstantInt>("", value);
}
};
class ConstantArr : public Constant {
public:
std::vector<ValuePtr_t> value_list;
ConstantArr(const std::string &name, const std::vector<ValuePtr_t> &value_list, std::shared_ptr<ArrayType> type)
: Constant(name, type), value_list(value_list) {}
static std::shared_ptr<ConstantArr> make_shared(const std::string &name, const std::vector<ValuePtr_t> &value_list,
std::shared_ptr<ArrayType> type) {
return std::make_shared<ConstantArr>(name, value_list, type);
}
};
typedef std::shared_ptr<Constant> ConstantPtr_t;
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, 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);
}
}; };
enum class InstTag { enum class InstTag {
@ -93,9 +122,6 @@ enum class InstTag {
ExtractEle ExtractEle
}; };
typedef std::shared_ptr<Value> ValuePtr_t;
typedef std::shared_ptr<BasicBlock> BasicBlockPtr_t;
typedef std::shared_ptr<Function> FunctionPtr_t;
class Instruction : public Value { class Instruction : public Value {
public: public:
InstTag tag; InstTag tag;
@ -107,9 +133,8 @@ public:
class InstAlloca : public Instruction { class InstAlloca : public Instruction {
public: public:
bool isInit = false; InstAlloca(TypePtr_t alloc_type, std::shared_ptr<BasicBlock> parent_bb)
InstAlloca(TypePtr_t alloc_type, bool isInit, std::shared_ptr<BasicBlock> parent_bb) : Instruction(InstTag::Alloca, std::make_shared<PointerType>(alloc_type), parent_bb) {}
: Instruction(InstTag::Alloca, std::make_shared<PointerType>(alloc_type), parent_bb), isInit(isInit) {}
}; };
class InstStore : public Instruction { class InstStore : public Instruction {
@ -177,8 +202,46 @@ public:
InstCall(FunctionPtr_t func, const std::vector<ValuePtr_t> &args, BasicBlockPtr_t parent_bb) InstCall(FunctionPtr_t func, const std::vector<ValuePtr_t> &args, BasicBlockPtr_t parent_bb)
: Instruction(InstTag::Call, func->get_type()->return_type, parent_bb) { : Instruction(InstTag::Call, func->get_type()->return_type, parent_bb) {
operand_list.push_back(func); operand_list.push_back(func);
for (auto arg : args) { operand_list.insert(operand_list.end(), args.begin(), args.end());
operand_list.push_back(arg); }
};
// getelementptr <ty>, ptr <ptrval>{, [inrange] <ty> <idx>}*
// Example: lea arr[2][3] from arr[5][4]:
// &arr[2][3] = GEP [5x[4xi32]], [5x[4xi32]]* arr, i32 0, i32 2, i32 3
class InstGEP : public Instruction {
public:
ValuePtr_t aim_to;
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 (typeid(pointer) == typeid(std::shared_ptr<InstGEP>)) {
aim_to = std::dynamic_pointer_cast<InstGEP>(pointer)->aim_to;
}
else {
sysy_assert(typeid(pointer) == typeid(std::shared_ptr<InstAlloca>) ||
typeid(pointer) == typeid(std::shared_ptr<GlobalVar>));
aim_to = pointer;
}
element_type = extract_type(pointer, indices);
operand_list.push_back(pointer);
operand_list.insert(operand_list.end(), indices.begin(), indices.end());
}
// get the inner
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;
if (pointed_type->type_tag == Type::TypeTag::ArrayType) {
for (int i = 1; i < indices.size() - 1; ++i) {
pointed_type = std::dynamic_pointer_cast<ArrayType>(pointed_type)->element_type;
}
}
if (pointed_type->type_tag == Type::TypeTag::IntegerType) {
return pointed_type;
}
else {
panic("Unmatch indices and array pointer");
} }
} }
}; };

View File

@ -29,7 +29,7 @@ std::shared_ptr<InstLoad> build_InstLoad(std::shared_ptr<Value> value, TypePtr_t
std::shared_ptr<InstStore> build_InstStore(std::shared_ptr<Value> value, std::shared_ptr<Value> pointer, std::shared_ptr<InstStore> build_InstStore(std::shared_ptr<Value> value, std::shared_ptr<Value> pointer,
std::shared_ptr<BasicBlock> parent_bb); std::shared_ptr<BasicBlock> parent_bb);
std::shared_ptr<InstAlloca> build_InstAlloca(TypePtr_t type, bool isInit, std::shared_ptr<BasicBlock> parent_bb); std::shared_ptr<InstAlloca> build_InstAlloca(TypePtr_t type, std::shared_ptr<BasicBlock> parent_bb);
std::shared_ptr<InstBinary> build_InstBinary(InstTag inst_tag, std::shared_ptr<Value> op1, std::shared_ptr<Value> op2, std::shared_ptr<InstBinary> build_InstBinary(InstTag inst_tag, std::shared_ptr<Value> op1, std::shared_ptr<Value> op2,
std::shared_ptr<BasicBlock> parent_bb); std::shared_ptr<BasicBlock> parent_bb);
@ -47,18 +47,22 @@ std::shared_ptr<InstReturn> build_InstReturn(BasicBlockPtr_t parent_bb);
std::shared_ptr<InstCall> build_InstCall(FunctionPtr_t func, const std::vector<ValuePtr_t> &args, std::shared_ptr<InstCall> build_InstCall(FunctionPtr_t func, const std::vector<ValuePtr_t> &args,
BasicBlockPtr_t parent_bb); BasicBlockPtr_t parent_bb);
std::shared_ptr<InstGEP> build_InstGEP(ValuePtr_t pointer, const std::vector<ValuePtr_t> &indices,
BasicBlockPtr_t parent_bb);
#pragma endregion #pragma endregion
class Visitor : public antlrSysY::SysyBaseVisitor { class Visitor : public antlrSysY::SysyBaseVisitor {
private: private:
struct VisitorState { struct VisitorState {
bool isGlobalInt = false; bool isGlobalIint = false;
bool isConstInt = false; bool isConstInt = false;
bool isRealParam = false; bool isRealParam = false;
bool isCondExp = false; bool isCondExp = false;
std::shared_ptr<Function> current_func = {}; std::shared_ptr<Function> current_func = {};
std::shared_ptr<BasicBlock> current_bb = {}; std::shared_ptr<BasicBlock> current_bb = {};
std::vector<int> *arr_dim_list = nullptr;
int arr_dim_index = 0;
struct loop_record { struct loop_record {
BasicBlockPtr_t cond, body, next; BasicBlockPtr_t cond, body, next;
int id; int id;

View File

@ -18,6 +18,8 @@ class Compiler:
self.obj_template = f"build/test_results/{{testcase}}/obj/{scheme}.o" self.obj_template = f"build/test_results/{{testcase}}/obj/{scheme}.o"
self.bin_template = f"build/test_results/{{testcase}}/bin/{scheme}" self.bin_template = f"build/test_results/{{testcase}}/bin/{scheme}"
self.compile_log = f"build/log/compile_log/{{testcase}}/{scheme}.log" self.compile_log = f"build/log/compile_log/{{testcase}}/{scheme}.log"
self.count_error = 0
for testcase in testcases: for testcase in testcases:
self.__generate_path(testcase) self.__generate_path(testcase)
@ -64,6 +66,7 @@ class Compiler:
completed = subprocess.run(frontend_instr.format(header=header, sy=sy, ir=ir).split(), stdout=log_file, stderr=log_file, bufsize=1) completed = subprocess.run(frontend_instr.format(header=header, sy=sy, ir=ir).split(), stdout=log_file, stderr=log_file, bufsize=1)
if completed.returncode != 0: if completed.returncode != 0:
Print_C.print_error(f"Generating {self.scheme}.ll failed! See {log}") Print_C.print_error(f"Generating {self.scheme}.ll failed! See {log}")
self.count_error += 1
log_file.close() log_file.close()
@ -142,5 +145,8 @@ class Compiler:
for testcase in self.testcases: for testcase in self.testcases:
Print_C.print_subheader(f"[Compiling {self.scheme} | {testcase}]") Print_C.print_subheader(f"[Compiling {self.scheme} | {testcase}]")
self.sy_to_ir(frontend_instr=frontend_instr, testcase=testcase, category=category) self.sy_to_ir(frontend_instr=frontend_instr, testcase=testcase, category=category)
if self.count_error >= 10:
Print_C.print_error(f"Test script stopped due to too many errors")
return

View File

@ -59,6 +59,9 @@ int main(int argc, const char **argv) {
#pragma endregion #pragma endregion
std::ifstream ifs_source_file(source_file); std::ifstream ifs_source_file(source_file);
if (!ifs_source_file.good()) {
LOG(ERROR) << "Source file " << source_file << " not found.";
}
ANTLRInputStream input(ifs_source_file); ANTLRInputStream input(ifs_source_file);
SysyLexer lexer(&input); SysyLexer lexer(&input);
CommonTokenStream tokens(&lexer); CommonTokenStream tokens(&lexer);

View File

@ -31,8 +31,8 @@ std::shared_ptr<InstStore> build_InstStore(std::shared_ptr<Value> value, std::sh
return inst_store; return inst_store;
} }
std::shared_ptr<InstAlloca> build_InstAlloca(TypePtr_t type, bool isInit, std::shared_ptr<BasicBlock> parent_bb) { std::shared_ptr<InstAlloca> build_InstAlloca(TypePtr_t type, std::shared_ptr<BasicBlock> parent_bb) {
auto inst_alloca = std::make_shared<InstAlloca>(type, isInit, parent_bb); auto inst_alloca = std::make_shared<InstAlloca>(type, parent_bb);
parent_bb->inst_list.push_back(inst_alloca); parent_bb->inst_list.push_back(inst_alloca);
return inst_alloca; return inst_alloca;
} }
@ -91,4 +91,11 @@ std::shared_ptr<InstCall> build_InstCall(FunctionPtr_t func, const std::vector<V
return inst; return inst;
} }
std::shared_ptr<InstGEP> build_InstGEP(ValuePtr_t pointer, const std::vector<ValuePtr_t> &indices,
BasicBlockPtr_t parent_bb) {
auto inst = std::make_shared<InstGEP>(pointer, indices, parent_bb);
parent_bb->inst_list.push_back(inst);
return inst;
}
} // namespace antlrSysY } // namespace antlrSysY

View File

@ -1,4 +1,5 @@
#include "visitor.h" #include "visitor.h"
#include "3rdparty/easylogging++.h"
#include "common.h" #include "common.h"
#include "llir_type.h" #include "llir_type.h"
#include "llir_value.h" #include "llir_value.h"
@ -19,7 +20,7 @@ namespace antlrSysY {
return value; \ return value; \
} }
ValuePtr_t any_to_Value(const std::any &fuck_any) { static ValuePtr_t any_to_Value(const std::any &fuck_any) {
ANY2VALUE(Value) ANY2VALUE(Value)
ANY2VALUE(User) ANY2VALUE(User)
ANY2VALUE(FParam) ANY2VALUE(FParam)
@ -27,7 +28,8 @@ ValuePtr_t any_to_Value(const std::any &fuck_any) {
ANY2VALUE(BasicBlock) ANY2VALUE(BasicBlock)
ANY2VALUE(ConstantInt) ANY2VALUE(ConstantInt)
ANY2VALUE(ConstantArr) ANY2VALUE(ConstantArr)
ANY2VALUE(GlobalVarInt) ANY2VALUE(Constant)
ANY2VALUE(GlobalVar)
ANY2VALUE(Instruction) ANY2VALUE(Instruction)
ANY2VALUE(InstAlloca) ANY2VALUE(InstAlloca)
ANY2VALUE(InstStore) ANY2VALUE(InstStore)
@ -48,101 +50,273 @@ std::any Visitor::visitConstDecl(SysyParser::ConstDeclContext *ctx) {
return {}; return {};
} }
// constInitVal is compulsory
// constDef : IDENT ('[' constExp ']')* '=' constInitVal ';' // constDef : IDENT ('[' constExp ']')* '=' constInitVal ';'
std::any Visitor::visitConstDef(SysyParser::ConstDefContext *ctx) { std::any Visitor::visitConstDef(SysyParser::ConstDefContext *ctx) {
auto name = ctx->IDENT()->getText(); const auto const_name = ctx->IDENT()->getText();
LOG(DEBUG) << "Visiting ConstDef " << name; LOG(DEBUG) << "Visiting ConstDef " << const_name;
if (_scope_tab.get_name(name, _scope_tab.get_level()).has_value()) if (_scope_tab.get_name(const_name, _scope_tab.get_level()).has_value())
throw GrammarException("Duplicate const def"); throw GrammarException("Duplicate const def");
// not array // not array
if (ctx->constExp().empty()) { if (ctx->constExp().empty()) {
if (ctx->constInitVal() != nullptr) { auto result = std::any_cast<std::shared_ptr<ConstantInt>>(visitConstInitVal(ctx->constInitVal()));
auto result = std::any_cast<int>(visit(ctx->constInitVal())); _scope_tab.push_name(const_name, result);
auto constint = build_ConstantInt(name, result); }
_scope_tab.push_name(name, constint); // const array
else {
std::vector<int> dim_list;
auto const_exp_list = ctx->constExp();
// collect size of each dimension
for (auto const_exp : const_exp_list) {
auto n_elem = std::any_cast<std::shared_ptr<ConstantInt>>(visitConstExp(const_exp));
dim_list.push_back(n_elem->value);
}
auto array_type = ArrayType::build_from_list(dim_list);
// anyways, first collect init value
_state.arr_dim_index = 0;
_state.arr_dim_list = &dim_list;
auto array_value = std::any_cast<std::vector<ValuePtr_t>>(visitConstInitVal(ctx->constInitVal()));
_state.arr_dim_list = nullptr;
sysy_assert(_state.arr_dim_index == 0);
if (_scope_tab.get_level()) {
// local const array
// Keep a pointer to the base address, alloca_ = &array, *alloca_ = &array[0]
auto alloca_ = build_InstAlloca(array_type, _state.current_bb);
_scope_tab.push_name(const_name, alloca_);
// first dim base, ptr = *alloca_ = &array[0]
auto base_ptr = build_InstGEP(alloca_, {CONST0, CONST0}, _state.current_bb);
// get the first element's base, final ptr = &a[0][0]...[0]
for (int i = 1; i < dim_list.size(); ++i) {
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);
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);
}
}
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);
_scope_tab.push_name(const_name, global_var);
} }
} }
return {}; return {};
} }
// initVal is optional
// varDef: IDENT ('[' constExp ']')* ('=' initVal)?;
std::any Visitor::visitVarDef(SysyParser::VarDefContext *ctx) { std::any Visitor::visitVarDef(SysyParser::VarDefContext *ctx) {
auto name = ctx->IDENT()->getText(); auto var_name = ctx->IDENT()->getText();
LOG(DEBUG) << "Visiting VarDef " << name; LOG(DEBUG) << "Visiting VarDef " << var_name;
if (_scope_tab.get_name(name, _scope_tab.get_level()).has_value()) if (_scope_tab.get_name(var_name, _scope_tab.get_level()).has_value())
panic("Duplicate const def"); panic("Duplicate const def");
// Not Array // Not Array
if (ctx->constExp().empty()) { if (ctx->constExp().empty()) {
// global variable // global variable
if (_scope_tab.get_level() == 0) { if (_scope_tab.get_level() == 0) {
// global variable must be initialized, either specified or zeroed // global variable must be initialized, either specified or zeroed
int result = 0;
if (ctx->initVal()) { if (ctx->initVal()) {
_state.isGlobalInt = true; _state.isGlobalIint = true;
result = std::any_cast<int>(visit(ctx->initVal())); auto result = std::any_cast<std::shared_ptr<ConstantInt>>(visitInitVal(ctx->initVal()));
_state.isGlobalInt = false; _state.isGlobalIint = false;
auto global_var_int = std::make_shared<GlobalVar>(var_name, result, false);
_scope_tab.push_name(var_name, global_var_int);
}
else {
auto global_var_int = std::make_shared<GlobalVar>(var_name, CONST0, false);
_scope_tab.push_name(var_name, global_var_int);
} }
auto global_var_int = std::make_shared<GlobalVarInt>(name, result);
_scope_tab.push_name(name, global_var_int);
} }
// local variable // local variable
else { else {
auto alloca = build_InstAlloca(TypeHelper::TYPE_I32, false, _state.current_bb); auto alloca_ = build_InstAlloca(TypeHelper::TYPE_I32, _state.current_bb);
_scope_tab.push_name(name, alloca); _scope_tab.push_name(var_name, alloca_);
if (ctx->initVal()) { if (ctx->initVal()) {
auto init_val = any_to_Value(visitInitVal(ctx->initVal())); auto init_val = any_to_Value(visitInitVal(ctx->initVal()));
build_InstStore(init_val, alloca, _state.current_bb); build_InstStore(init_val, alloca_, _state.current_bb);
} }
} }
} }
else { else {
// Array std::vector<int> dim_list;
panic("To be implemented"); auto const_exp_list = ctx->constExp();
// collect size of each dimension
for (auto const_exp : const_exp_list) {
auto n_elem = std::any_cast<std::shared_ptr<ConstantInt>>(visitConstExp(const_exp));
dim_list.push_back(n_elem->value);
}
auto array_type = ArrayType::build_from_list(dim_list);
// local array
if (_scope_tab.get_level()) {
auto alloca_ = build_InstAlloca(array_type, _state.current_bb);
_scope_tab.push_name(var_name, alloca_);
if (ctx->initVal()) {
_state.arr_dim_index = 0;
_state.arr_dim_list = &dim_list;
auto array_value = std::any_cast<std::vector<ValuePtr_t>>(visitInitVal(ctx->initVal()));
_state.arr_dim_list = nullptr;
sysy_assert(_state.arr_dim_index == 0);
// Build GEP
auto base_ptr = build_InstGEP(alloca_, {CONST0, CONST0}, _state.current_bb);
for (int i = 1; i < dim_list.size(); ++i) {
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);
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);
}
}
// If there is no init expr, let it be
}
// global array, generally the same as constant global array
else {
if (ctx->initVal()) {
// first collect init value
_state.isGlobalIint = true;
_state.arr_dim_index = 0;
_state.arr_dim_list = &dim_list;
auto array_value = std::any_cast<std::vector<ValuePtr_t>>(visitInitVal(ctx->initVal()));
_state.arr_dim_list = nullptr;
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);
_scope_tab.push_name(var_name, global_var);
}
else {
auto global_var = GlobalVar::make_shared(var_name, CONST0, false);
_scope_tab.push_name(var_name, global_var);
}
}
} }
return {}; return {};
} }
std::any Visitor::visitInitVal(SysyParser::InitValContext *ctx) { std::any Visitor::visitInitVal(SysyParser::InitValContext *ctx) {
if (ctx->exp()) { if (ctx->exp()) {
if (_state.isGlobalInt) if (_state.isGlobalIint)
_state.isConstInt = true; _state.isConstInt = true;
auto retval = visit(ctx->exp()); auto retval = visitExp(ctx->exp());
if (_state.isGlobalInt) if (_state.isGlobalIint)
_state.isConstInt = false; _state.isConstInt = false;
return retval; return retval;
} }
// Array // Array
panic("To be implemented"); else {
} sysy_assert(_state.arr_dim_list);
int cur_dim = _state.arr_dim_list->at(_state.arr_dim_index);
std::any Visitor::visitConstInitVal(SysyParser::ConstInitValContext *ctx) { int elem_size = 1;
if (ctx->constExp() != nullptr /*&& ctx->arrDim.size() == 0*/) { std::vector<ValuePtr_t> cur_arr;
return visit(ctx->constExp()); for (int i = _state.arr_dim_index + 1; i < _state.arr_dim_list->size(); ++i) {
elem_size *= _state.arr_dim_list->at(i);
}
for (auto init_val : ctx->initVal()) {
if (init_val->exp()) {
if (_state.isGlobalIint) {
auto const_value = any_to_Value(visitInitVal(init_val));
// should evaluate to const int
sysy_assert(typeid(const_value) == typeid(std::shared_ptr<ConstantInt>));
cur_arr.push_back(const_value);
}
else {
// God knows what it evaluates to
auto exp_value = any_to_Value(visitInitVal(init_val));
cur_arr.push_back(exp_value);
}
}
else {
// evaluate sub-array
// before evaluate the new sub-array, first fill up the last one
const int pos = cur_arr.size();
// the additional `%elem_size`: what if the last dim is {}?
for (int i = 0; i < (elem_size - (pos % elem_size)) % elem_size; ++i) {
cur_arr.push_back(CONST0);
}
_state.arr_dim_index++;
auto sub_array = std::any_cast<std::vector<ValuePtr_t>>(visitInitVal(init_val));
_state.arr_dim_index--;
cur_arr.insert(cur_arr.end(), sub_array.begin(), sub_array.end());
}
}
// fill up the rest
for (int i = cur_arr.size(); i < cur_dim * elem_size; ++i) {
cur_arr.push_back(CONST0);
}
return cur_arr;
} }
panic("To be implemented");
} }
// TODO: Replace all any<int> to ConstantInt
// constInitVal: constExp | ('{' (constInitVal (',' constInitVal)*)? '}');
std::any Visitor::visitConstInitVal(SysyParser::ConstInitValContext *ctx) {
if (ctx->constExp() != nullptr) {
return visitConstExp(ctx->constExp());
}
else {
sysy_assert(_state.arr_dim_list);
int cur_dim = _state.arr_dim_list->at(_state.arr_dim_index);
int elem_size = 1;
std::vector<ValuePtr_t> cur_arr;
for (int i = _state.arr_dim_index + 1; i < _state.arr_dim_list->size(); ++i) {
elem_size *= _state.arr_dim_list->at(i);
}
for (auto init_val : ctx->constInitVal()) {
if (init_val->constExp()) {
// evaluate to const int
auto const_value = any_to_Value(visitConstInitVal(init_val));
sysy_assert(TypeHelper::isIntegerType(const_value->type));
cur_arr.push_back(const_value);
}
else {
// evaluate to sub-array
// before evaluate the new sub-array, first fill up the last one
int pos = cur_arr.size();
// the additional `%elem_size`: what if the last dim is {}?
for (int i = 0; i < (elem_size - (pos % elem_size)) % elem_size; ++i) {
cur_arr.push_back(CONST0);
}
_state.arr_dim_index++;
auto sub_array = std::any_cast<std::vector<ValuePtr_t>>(visitConstInitVal(init_val));
_state.arr_dim_index--;
cur_arr.insert(cur_arr.end(), sub_array.begin(), sub_array.end());
}
}
// fill up the rest
for (int i = cur_arr.size(); i < cur_dim * elem_size; ++i) {
cur_arr.push_back(CONST0);
}
return cur_arr;
}
}
// @retval: int
std::any Visitor::visitConstExp(SysyParser::ConstExpContext *ctx) { std::any Visitor::visitConstExp(SysyParser::ConstExpContext *ctx) {
if (ctx->addExp() == nullptr) if (ctx->addExp() == nullptr)
panic("Unreachable"); panic("Unreachable");
_state.isConstInt = true; _state.isConstInt = true;
int result = std::any_cast<int>(visit(ctx->addExp())); auto result = std::any_cast<std::shared_ptr<ConstantInt>>(visitAddExp(ctx->addExp()));
_state.isConstInt = false; _state.isConstInt = false;
LOG(DEBUG) << "ConstExp Eval to " << result; LOG(DEBUG) << "ConstExp Eval to " << result->value;
return {result}; return {result};
} }
// addExp: mulExp | addExp ('+' | '-') mulExp; // addExp: mulExp | addExp ('+' | '-') mulExp;
std::any Visitor::visitAddExp(SysyParser::AddExpContext *ctx) { std::any Visitor::visitAddExp(SysyParser::AddExpContext *ctx) {
if (_state.isConstInt) { if (_state.isConstInt) {
int result = std::any_cast<int>(visit(ctx->mulExp())); auto result = std::any_cast<std::shared_ptr<ConstantInt>>(visitMulExp(ctx->mulExp()));
int add_result = 0;
if (ctx->addExp()) { if (ctx->addExp()) {
add_result = std::any_cast<int>(visit(ctx->addExp())); auto add_result = std::any_cast<std::shared_ptr<ConstantInt>>(visitAddExp(ctx->addExp()));
if (ctx->ADD()) if (ctx->ADD())
result = add_result + result; result->value = add_result->value + result->value;
else if (ctx->SUB()) else if (ctx->SUB())
result = add_result - result; result->value = add_result->value - result->value;
else else
panic("missing operator"); panic("missing operator");
} }
@ -173,17 +347,17 @@ std::any Visitor::visitAddExp(SysyParser::AddExpContext *ctx) {
std::any Visitor::visitMulExp(SysyParser::MulExpContext *ctx) { std::any Visitor::visitMulExp(SysyParser::MulExpContext *ctx) {
if (_state.isConstInt) { if (_state.isConstInt) {
int result = std::any_cast<int>(visitUnaryExp(ctx->unaryExp())); auto result = std::any_cast<std::shared_ptr<ConstantInt>>(visitUnaryExp(ctx->unaryExp()));
if (ctx->mulExp()) { if (ctx->mulExp()) {
int mul_result = std::any_cast<int>(visit(ctx->mulExp())); auto mul_result = std::any_cast<std::shared_ptr<ConstantInt>>(visitMulExp(ctx->mulExp()));
if (ctx->MUL()) { if (ctx->MUL()) {
result = mul_result * result; result->value = mul_result->value * result->value;
} }
else if (ctx->DIV()) { else if (ctx->DIV()) {
result = mul_result / result; result->value = mul_result->value / result->value;
} }
else if (ctx->MOD()) { else if (ctx->MOD()) {
result = mul_result % result; result->value = mul_result->value % result->value;
} }
else else
panic("Unreachable"); panic("Unreachable");
@ -299,13 +473,13 @@ std::any Visitor::visitLOrExp(SysyParser::LOrExpContext *ctx) {
std::any Visitor::visitUnaryExp(SysyParser::UnaryExpContext *ctx) { std::any Visitor::visitUnaryExp(SysyParser::UnaryExpContext *ctx) {
if (_state.isConstInt) { if (_state.isConstInt) {
if (ctx->unaryExp()) { if (ctx->unaryExp()) {
int result = std::any_cast<int>(visit(ctx->unaryExp())); auto result = std::any_cast<std::shared_ptr<ConstantInt>>(visitUnaryExp(ctx->unaryExp()));
if (ctx->unaryOp()->ADD()) if (ctx->unaryOp()->ADD())
result = +result; result->value = +result->value;
else if (ctx->unaryOp()->SUB()) else if (ctx->unaryOp()->SUB())
result = -result; result->value = -result->value;
else if (ctx->unaryOp()->NOT()) else if (ctx->unaryOp()->NOT())
result = !result; result->value = !result->value;
else else
panic("Unreachable"); panic("Unreachable");
return {result}; return {result};
@ -376,7 +550,7 @@ std::any Visitor::visitPrimaryExp(SysyParser::PrimaryExpContext *ctx) {
return visitExp(ctx->exp()); return visitExp(ctx->exp());
} }
else if (ctx->lVal()) { else if (ctx->lVal()) {
auto value = any_to_Value(visit(ctx->lVal())); auto value = any_to_Value(visitLVal(ctx->lVal()));
auto constint = std::dynamic_pointer_cast<ConstantInt>(value); auto constint = std::dynamic_pointer_cast<ConstantInt>(value);
// actually, it is only a type assertion // actually, it is only a type assertion
return constint->value; return constint->value;
@ -418,32 +592,26 @@ std::any Visitor::visitPrimaryExp(SysyParser::PrimaryExpContext *ctx) {
} }
panic("Unreachable"); panic("Unreachable");
} }
return {};
} }
// @retval: int // @retval: ConstantInt
std::any Visitor::visitNumber(SysyParser::NumberContext *ctx) { std::any Visitor::visitNumber(SysyParser::NumberContext *ctx) {
auto int_const = std::any_cast<int>(visit(ctx->intConst())); return visitIntConst(ctx->intConst());
if (_state.isConstInt) {
return int_const;
}
else {
return std::dynamic_pointer_cast<Value>(build_ConstantInt("", int_const));
}
} }
// @retval: int // @retval: ConstantInt
std::any Visitor::visitIntConst(SysyParser::IntConstContext *ctx) { std::any Visitor::visitIntConst(SysyParser::IntConstContext *ctx) {
int const_int = 0;
if (ctx->DECIMAL_CONST()) { if (ctx->DECIMAL_CONST()) {
return std::stoi(ctx->DECIMAL_CONST()->getText(), nullptr, 10); const_int = std::stoi(ctx->DECIMAL_CONST()->getText(), nullptr, 10);
} }
else if (ctx->HEXADECIMAL_CONST()) { else if (ctx->HEXADECIMAL_CONST()) {
return std::stoi(ctx->HEXADECIMAL_CONST()->getText(), nullptr, 16); const_int = std::stoi(ctx->HEXADECIMAL_CONST()->getText(), nullptr, 16);
} }
else if (ctx->OCTAL_CONST()) { else if (ctx->OCTAL_CONST()) {
return std::stoi(ctx->OCTAL_CONST()->getText(), nullptr, 8); const_int = std::stoi(ctx->OCTAL_CONST()->getText(), nullptr, 8);
} }
return {}; return build_ConstantInt("", const_int);
} }
// lVal: IDENT ('[' exp ']')*; // lVal: IDENT ('[' exp ']')*;
@ -460,17 +628,107 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
} }
if (lval->type->type_tag == Type::TypeTag::PointerType) { if (lval->type->type_tag == Type::TypeTag::PointerType) {
auto ptr_type = std::dynamic_pointer_cast<PointerType>(lval->type); auto ptr_type = std::dynamic_pointer_cast<PointerType>(lval->type);
if (ptr_type->pointed_type->type_tag == Type::TypeTag::IntegerType) { switch (ptr_type->pointed_type->type_tag) {
// @retval: InstAlloca case Type::TypeTag::IntegerType: {
// Int
if (ctx->exp().empty()) { if (ctx->exp().empty()) {
// int ref
// @retval: InstAlloca
return lval; return lval;
} }
else { else {
panic("To be implemented"); LOG(WARNING) << "Unexpected array referece";
// array index, perhaps
// @retval: InstGEP
auto gep = lval;
for (auto exp_ctx : ctx->exp()) {
auto exp = any_to_Value(visitExp(exp_ctx));
gep = build_InstGEP(gep, {exp}, _state.current_bb);
}
return gep;
}
};
case Type::TypeTag::PointerType: {
if (ctx->exp().empty()) {
// ??? Pointer
// @retval: InstLoad
LOG(WARNING) << "Unexpected pointer";
auto pointed_type = std::dynamic_pointer_cast<PointerType>(lval)->pointed_type;
auto inst_load = build_InstLoad(lval, pointed_type, _state.current_bb);
return inst_load;
}
else {
// fparam array, whose first dim is represented by a pointer
auto pointed_type = std::dynamic_pointer_cast<PointerType>(lval)->pointed_type;
sysy_assert(pointed_type->type_tag == Type::TypeTag::ArrayType);
auto inst_load = build_InstLoad(lval, pointed_type, _state.current_bb);
auto ptr = build_InstGEP(inst_load, {CONST0}, _state.current_bb);
pointed_type = std::dynamic_pointer_cast<PointerType>(ptr->type)->pointed_type;
ValuePtr_t offset = ConstantInt::make_shared(0);
auto exp_list = ctx->exp();
// 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>));
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);
auto inst_add = build_InstBinary(InstTag::Add, offset, exp_val, _state.current_bb);
auto inst_mul = build_InstBinary(InstTag::Mul, inst_add, dim_size, _state.current_bb);
offset = inst_mul;
pointed_type = array_type->element_type;
ptr = build_InstGEP(ptr, {CONST0, CONST0}, _state.current_bb);
}
// visit the last dimension, mul is not needed
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
pointed_type = std::dynamic_pointer_cast<PointerType>(ptr->type)->pointed_type;
if (TypeHelper::isIntegerType(pointed_type)) {
// return the address of the array element
auto arr_elem_ptr = build_InstGEP(ptr, {offset}, _state.current_bb);
return arr_elem_ptr;
}
else {
panic("Should be int");
}
} }
} }
else { case Type::TypeTag::ArrayType: {
panic("To be implemented"); sysy_assert(!ctx->exp().empty());
// get &array[0]
auto ptr = build_InstGEP(lval, {CONST0, CONST0}, _state.current_bb);
auto pointed_type = std::dynamic_pointer_cast<PointerType>(ptr->type)->pointed_type;
ValuePtr_t offset = ConstantInt::make_shared(0);
auto exp_list = ctx->exp();
// 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>));
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);
auto inst_add = build_InstBinary(InstTag::Add, offset, exp_val, _state.current_bb);
auto inst_mul = build_InstBinary(InstTag::Mul, inst_add, dim_size, _state.current_bb);
offset = inst_mul;
pointed_type = array_type->element_type;
ptr = build_InstGEP(ptr, {CONST0, CONST0}, _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
pointed_type = std::dynamic_pointer_cast<PointerType>(ptr->type)->pointed_type;
if (TypeHelper::isIntegerType(pointed_type)) {
// return the address of the array element
auto arr_elem_ptr = build_InstGEP(ptr, {offset}, _state.current_bb);
return arr_elem_ptr;
}
else {
panic("Should be int");
}
}
default:
panic("Unreachable");
} }
} }
panic("Unreachable"); panic("Unreachable");
@ -494,7 +752,7 @@ std::any Visitor::visitFuncDef(SysyParser::FuncDefContext *ctx) {
if (ctx->funcFParams()) { if (ctx->funcFParams()) {
visitFuncFParams(ctx->funcFParams()); visitFuncFParams(ctx->funcFParams());
} }
visit(ctx->block()); visitBlock(ctx->block());
// add return // add return
// _scope_tab.leave_scope(); // _scope_tab.leave_scope();
// TODO: avoid duplicate ret // TODO: avoid duplicate ret
@ -507,36 +765,47 @@ std::any Visitor::visitFuncDef(SysyParser::FuncDefContext *ctx) {
return {}; return {};
} }
// @retval: any
// Directly add to function, rather than return something...
std::any Visitor::visitFuncFParams(SysyParser::FuncFParamsContext *ctx) { std::any Visitor::visitFuncFParams(SysyParser::FuncFParamsContext *ctx) {
for (auto fparam : ctx->funcFParam()) { for (auto fparam_ctx : ctx->funcFParam()) {
auto fparam_type = std::any_cast<TypePtr_t>(visit(fparam)); auto fparam_type = std::any_cast<TypePtr_t>(visitFuncFParam(fparam_ctx));
auto fparam_name = fparam->getText(); auto fparam_name = fparam_ctx->getText();
auto fparam_ptr = std::make_shared<FParam>(fparam_name, fparam_type); auto fparam = std::make_shared<FParam>(fparam_name, fparam_type);
_state.current_func->fparam_list.push_back(fparam_ptr); _state.current_func->fparam_list.push_back(fparam);
if (fparam->LBRACKET().empty()) { auto alloca_ = build_InstAlloca(fparam_type, _state.current_bb);
auto alloca = build_InstAlloca(TypeHelper::TYPE_I32, false, _state.current_bb); build_InstStore(fparam, alloca_, _state.current_bb);
auto store = build_InstStore(fparam_ptr, alloca, _state.current_bb); _scope_tab.push_name(fparam_name, alloca_);
_scope_tab.push_name(fparam_name, alloca); _state.current_func->fparam_list.push_back(fparam);
_state.current_func->fparam_list.push_back(fparam_ptr);
}
else {
panic("To be implemented");
}
} }
return {}; return {};
} }
// funcFParam: bType IDENT ('[' ']' ('[' exp ']')*)?;
std::any Visitor::visitFuncFParam(SysyParser::FuncFParamContext *ctx) { std::any Visitor::visitFuncFParam(SysyParser::FuncFParamContext *ctx) {
if (ctx->LBRACKET().empty()) { if (ctx->LBRACKET().empty()) {
// int type
return {TypeHelper::TYPE_I32}; return {TypeHelper::TYPE_I32};
} }
panic("To be implemented"); else {
// array type
std::vector<int> dim_list; // the first dim must be empty, though
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);
}
auto array_type = ArrayType::build_from_list(dim_list);
auto true_array_type = std::make_shared<PointerType>(array_type);
return {true_array_type};
}
} }
std::any Visitor::visitBlock(SysyParser::BlockContext *ctx) { std::any Visitor::visitBlock(SysyParser::BlockContext *ctx) {
_scope_tab.enter_scope(); _scope_tab.enter_scope();
for (auto block_item : ctx->blockItem()) { for (auto block_item : ctx->blockItem()) {
visit(block_item); visitBlockItem(block_item);
} }
_scope_tab.leave_scope(); _scope_tab.leave_scope();
return {}; return {};
@ -556,8 +825,8 @@ stmt: lVal '=' exp ';' # assignStmt
*/ */
std::any Visitor::visitAssignStmt(SysyParser::AssignStmtContext *ctx) { std::any Visitor::visitAssignStmt(SysyParser::AssignStmtContext *ctx) {
auto lval = any_to_Value(visit(ctx->lVal())); auto lval = any_to_Value(visitLVal(ctx->lVal()));
auto rhs = any_to_Value(visit(ctx->exp())); auto rhs = any_to_Value(visitExp(ctx->exp()));
auto store = build_InstStore(rhs, lval, _state.current_bb); auto store = build_InstStore(rhs, lval, _state.current_bb);
return {}; return {};
} }