buggy buggy frontend
This commit is contained in:
parent
619145bf22
commit
dd48562daa
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
namespace antlrSysY {
|
||||
@ -69,6 +70,14 @@ public:
|
||||
ArrayType() : Type(TypeTag::ArrayType) {}
|
||||
ArrayType(TypePtr_t element_type, int element_count)
|
||||
: 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 {
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common.h"
|
||||
#include "llir_type.h"
|
||||
|
||||
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:
|
||||
int value;
|
||||
ConstantInt(const std::string &name, int value) : Value(name, TypeHelper::TYPE_I32), value(value) {}
|
||||
Constant(const std::string &name, TypePtr_t type) : Value(name, type) {}
|
||||
};
|
||||
|
||||
class ConstantArr : public Value {};
|
||||
|
||||
class GlobalVarInt : public Value {
|
||||
class ConstantInt : public Constant {
|
||||
public:
|
||||
int init_value;
|
||||
GlobalVarInt(const std::string &name, int init_value) : Value(name, TypeHelper::TYPE_I32), init_value(init_value) {}
|
||||
int 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 {
|
||||
@ -93,9 +122,6 @@ enum class InstTag {
|
||||
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 {
|
||||
public:
|
||||
InstTag tag;
|
||||
@ -107,9 +133,8 @@ public:
|
||||
|
||||
class InstAlloca : public Instruction {
|
||||
public:
|
||||
bool isInit = false;
|
||||
InstAlloca(TypePtr_t alloc_type, bool isInit, std::shared_ptr<BasicBlock> parent_bb)
|
||||
: Instruction(InstTag::Alloca, std::make_shared<PointerType>(alloc_type), parent_bb), isInit(isInit) {}
|
||||
InstAlloca(TypePtr_t alloc_type, std::shared_ptr<BasicBlock> parent_bb)
|
||||
: Instruction(InstTag::Alloca, std::make_shared<PointerType>(alloc_type), parent_bb) {}
|
||||
};
|
||||
|
||||
class InstStore : public Instruction {
|
||||
@ -177,8 +202,46 @@ public:
|
||||
InstCall(FunctionPtr_t func, const std::vector<ValuePtr_t> &args, BasicBlockPtr_t parent_bb)
|
||||
: Instruction(InstTag::Call, func->get_type()->return_type, parent_bb) {
|
||||
operand_list.push_back(func);
|
||||
for (auto arg : args) {
|
||||
operand_list.push_back(arg);
|
||||
operand_list.insert(operand_list.end(), args.begin(), args.end());
|
||||
}
|
||||
};
|
||||
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -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<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<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,
|
||||
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
|
||||
|
||||
class Visitor : public antlrSysY::SysyBaseVisitor {
|
||||
private:
|
||||
struct VisitorState {
|
||||
bool isGlobalInt = false;
|
||||
bool isGlobalIint = false;
|
||||
bool isConstInt = false;
|
||||
bool isRealParam = false;
|
||||
bool isCondExp = false;
|
||||
std::shared_ptr<Function> current_func = {};
|
||||
std::shared_ptr<BasicBlock> current_bb = {};
|
||||
|
||||
std::vector<int> *arr_dim_list = nullptr;
|
||||
int arr_dim_index = 0;
|
||||
struct loop_record {
|
||||
BasicBlockPtr_t cond, body, next;
|
||||
int id;
|
||||
|
||||
@ -19,6 +19,8 @@ class Compiler:
|
||||
self.bin_template = f"build/test_results/{{testcase}}/bin/{scheme}"
|
||||
self.compile_log = f"build/log/compile_log/{{testcase}}/{scheme}.log"
|
||||
|
||||
self.count_error = 0
|
||||
|
||||
for testcase in testcases:
|
||||
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)
|
||||
if completed.returncode != 0:
|
||||
Print_C.print_error(f"Generating {self.scheme}.ll failed! See {log}")
|
||||
self.count_error += 1
|
||||
log_file.close()
|
||||
|
||||
|
||||
@ -142,5 +145,8 @@ 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)
|
||||
if self.count_error >= 10:
|
||||
Print_C.print_error(f"Test script stopped due to too many errors")
|
||||
return
|
||||
|
||||
|
||||
@ -59,6 +59,9 @@ int main(int argc, const char **argv) {
|
||||
#pragma endregion
|
||||
|
||||
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);
|
||||
SysyLexer lexer(&input);
|
||||
CommonTokenStream tokens(&lexer);
|
||||
|
||||
@ -31,8 +31,8 @@ std::shared_ptr<InstStore> build_InstStore(std::shared_ptr<Value> value, std::sh
|
||||
return inst_store;
|
||||
}
|
||||
|
||||
std::shared_ptr<InstAlloca> build_InstAlloca(TypePtr_t type, bool isInit, std::shared_ptr<BasicBlock> parent_bb) {
|
||||
auto inst_alloca = std::make_shared<InstAlloca>(type, isInit, 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, parent_bb);
|
||||
parent_bb->inst_list.push_back(inst_alloca);
|
||||
return inst_alloca;
|
||||
}
|
||||
@ -91,4 +91,11 @@ std::shared_ptr<InstCall> build_InstCall(FunctionPtr_t func, const std::vector<V
|
||||
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
|
||||
445
src/visitor.cpp
445
src/visitor.cpp
@ -1,4 +1,5 @@
|
||||
#include "visitor.h"
|
||||
#include "3rdparty/easylogging++.h"
|
||||
#include "common.h"
|
||||
#include "llir_type.h"
|
||||
#include "llir_value.h"
|
||||
@ -19,7 +20,7 @@ namespace antlrSysY {
|
||||
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(User)
|
||||
ANY2VALUE(FParam)
|
||||
@ -27,7 +28,8 @@ ValuePtr_t any_to_Value(const std::any &fuck_any) {
|
||||
ANY2VALUE(BasicBlock)
|
||||
ANY2VALUE(ConstantInt)
|
||||
ANY2VALUE(ConstantArr)
|
||||
ANY2VALUE(GlobalVarInt)
|
||||
ANY2VALUE(Constant)
|
||||
ANY2VALUE(GlobalVar)
|
||||
ANY2VALUE(Instruction)
|
||||
ANY2VALUE(InstAlloca)
|
||||
ANY2VALUE(InstStore)
|
||||
@ -48,101 +50,273 @@ std::any Visitor::visitConstDecl(SysyParser::ConstDeclContext *ctx) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// constInitVal is compulsory
|
||||
// constDef : IDENT ('[' constExp ']')* '=' constInitVal ';'
|
||||
std::any Visitor::visitConstDef(SysyParser::ConstDefContext *ctx) {
|
||||
auto name = ctx->IDENT()->getText();
|
||||
LOG(DEBUG) << "Visiting ConstDef " << name;
|
||||
if (_scope_tab.get_name(name, _scope_tab.get_level()).has_value())
|
||||
const auto const_name = ctx->IDENT()->getText();
|
||||
LOG(DEBUG) << "Visiting ConstDef " << const_name;
|
||||
if (_scope_tab.get_name(const_name, _scope_tab.get_level()).has_value())
|
||||
throw GrammarException("Duplicate const def");
|
||||
|
||||
// not array
|
||||
if (ctx->constExp().empty()) {
|
||||
if (ctx->constInitVal() != nullptr) {
|
||||
auto result = std::any_cast<int>(visit(ctx->constInitVal()));
|
||||
auto constint = build_ConstantInt(name, result);
|
||||
_scope_tab.push_name(name, constint);
|
||||
auto result = std::any_cast<std::shared_ptr<ConstantInt>>(visitConstInitVal(ctx->constInitVal()));
|
||||
_scope_tab.push_name(const_name, result);
|
||||
}
|
||||
// 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 {};
|
||||
}
|
||||
|
||||
// initVal is optional
|
||||
// varDef: IDENT ('[' constExp ']')* ('=' initVal)?;
|
||||
std::any Visitor::visitVarDef(SysyParser::VarDefContext *ctx) {
|
||||
auto name = ctx->IDENT()->getText();
|
||||
LOG(DEBUG) << "Visiting VarDef " << name;
|
||||
if (_scope_tab.get_name(name, _scope_tab.get_level()).has_value())
|
||||
auto var_name = ctx->IDENT()->getText();
|
||||
LOG(DEBUG) << "Visiting VarDef " << var_name;
|
||||
if (_scope_tab.get_name(var_name, _scope_tab.get_level()).has_value())
|
||||
panic("Duplicate const def");
|
||||
// Not Array
|
||||
if (ctx->constExp().empty()) {
|
||||
// global variable
|
||||
if (_scope_tab.get_level() == 0) {
|
||||
// global variable must be initialized, either specified or zeroed
|
||||
int result = 0;
|
||||
if (ctx->initVal()) {
|
||||
_state.isGlobalInt = true;
|
||||
result = std::any_cast<int>(visit(ctx->initVal()));
|
||||
_state.isGlobalInt = false;
|
||||
_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);
|
||||
_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
|
||||
else {
|
||||
auto alloca = build_InstAlloca(TypeHelper::TYPE_I32, false, _state.current_bb);
|
||||
_scope_tab.push_name(name, alloca);
|
||||
auto alloca_ = build_InstAlloca(TypeHelper::TYPE_I32, _state.current_bb);
|
||||
_scope_tab.push_name(var_name, alloca_);
|
||||
if (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 {
|
||||
// Array
|
||||
panic("To be implemented");
|
||||
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);
|
||||
// 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 {};
|
||||
}
|
||||
|
||||
std::any Visitor::visitInitVal(SysyParser::InitValContext *ctx) {
|
||||
if (ctx->exp()) {
|
||||
if (_state.isGlobalInt)
|
||||
if (_state.isGlobalIint)
|
||||
_state.isConstInt = true;
|
||||
auto retval = visit(ctx->exp());
|
||||
if (_state.isGlobalInt)
|
||||
auto retval = visitExp(ctx->exp());
|
||||
if (_state.isGlobalIint)
|
||||
_state.isConstInt = false;
|
||||
return retval;
|
||||
}
|
||||
// Array
|
||||
panic("To be implemented");
|
||||
}
|
||||
|
||||
std::any Visitor::visitConstInitVal(SysyParser::ConstInitValContext *ctx) {
|
||||
if (ctx->constExp() != nullptr /*&& ctx->arrDim.size() == 0*/) {
|
||||
return visit(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->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) {
|
||||
if (ctx->addExp() == nullptr)
|
||||
panic("Unreachable");
|
||||
_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;
|
||||
LOG(DEBUG) << "ConstExp Eval to " << result;
|
||||
LOG(DEBUG) << "ConstExp Eval to " << result->value;
|
||||
return {result};
|
||||
}
|
||||
|
||||
// addExp: mulExp | addExp ('+' | '-') mulExp;
|
||||
std::any Visitor::visitAddExp(SysyParser::AddExpContext *ctx) {
|
||||
if (_state.isConstInt) {
|
||||
int result = std::any_cast<int>(visit(ctx->mulExp()));
|
||||
int add_result = 0;
|
||||
auto result = std::any_cast<std::shared_ptr<ConstantInt>>(visitMulExp(ctx->mulExp()));
|
||||
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())
|
||||
result = add_result + result;
|
||||
result->value = add_result->value + result->value;
|
||||
else if (ctx->SUB())
|
||||
result = add_result - result;
|
||||
result->value = add_result->value - result->value;
|
||||
else
|
||||
panic("missing operator");
|
||||
}
|
||||
@ -173,17 +347,17 @@ std::any Visitor::visitAddExp(SysyParser::AddExpContext *ctx) {
|
||||
|
||||
std::any Visitor::visitMulExp(SysyParser::MulExpContext *ctx) {
|
||||
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()) {
|
||||
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()) {
|
||||
result = mul_result * result;
|
||||
result->value = mul_result->value * result->value;
|
||||
}
|
||||
else if (ctx->DIV()) {
|
||||
result = mul_result / result;
|
||||
result->value = mul_result->value / result->value;
|
||||
}
|
||||
else if (ctx->MOD()) {
|
||||
result = mul_result % result;
|
||||
result->value = mul_result->value % result->value;
|
||||
}
|
||||
else
|
||||
panic("Unreachable");
|
||||
@ -299,13 +473,13 @@ std::any Visitor::visitLOrExp(SysyParser::LOrExpContext *ctx) {
|
||||
std::any Visitor::visitUnaryExp(SysyParser::UnaryExpContext *ctx) {
|
||||
if (_state.isConstInt) {
|
||||
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())
|
||||
result = +result;
|
||||
result->value = +result->value;
|
||||
else if (ctx->unaryOp()->SUB())
|
||||
result = -result;
|
||||
result->value = -result->value;
|
||||
else if (ctx->unaryOp()->NOT())
|
||||
result = !result;
|
||||
result->value = !result->value;
|
||||
else
|
||||
panic("Unreachable");
|
||||
return {result};
|
||||
@ -376,7 +550,7 @@ std::any Visitor::visitPrimaryExp(SysyParser::PrimaryExpContext *ctx) {
|
||||
return visitExp(ctx->exp());
|
||||
}
|
||||
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);
|
||||
// actually, it is only a type assertion
|
||||
return constint->value;
|
||||
@ -418,32 +592,26 @@ std::any Visitor::visitPrimaryExp(SysyParser::PrimaryExpContext *ctx) {
|
||||
}
|
||||
panic("Unreachable");
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
// @retval: int
|
||||
// @retval: ConstantInt
|
||||
std::any Visitor::visitNumber(SysyParser::NumberContext *ctx) {
|
||||
auto int_const = std::any_cast<int>(visit(ctx->intConst()));
|
||||
if (_state.isConstInt) {
|
||||
return int_const;
|
||||
}
|
||||
else {
|
||||
return std::dynamic_pointer_cast<Value>(build_ConstantInt("", int_const));
|
||||
}
|
||||
return visitIntConst(ctx->intConst());
|
||||
}
|
||||
|
||||
// @retval: int
|
||||
// @retval: ConstantInt
|
||||
std::any Visitor::visitIntConst(SysyParser::IntConstContext *ctx) {
|
||||
int const_int = 0;
|
||||
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()) {
|
||||
return std::stoi(ctx->HEXADECIMAL_CONST()->getText(), nullptr, 16);
|
||||
const_int = std::stoi(ctx->HEXADECIMAL_CONST()->getText(), nullptr, 16);
|
||||
}
|
||||
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 ']')*;
|
||||
@ -460,17 +628,107 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
|
||||
}
|
||||
if (lval->type->type_tag == Type::TypeTag::PointerType) {
|
||||
auto ptr_type = std::dynamic_pointer_cast<PointerType>(lval->type);
|
||||
if (ptr_type->pointed_type->type_tag == Type::TypeTag::IntegerType) {
|
||||
// @retval: InstAlloca
|
||||
switch (ptr_type->pointed_type->type_tag) {
|
||||
case Type::TypeTag::IntegerType: {
|
||||
// Int
|
||||
if (ctx->exp().empty()) {
|
||||
// int ref
|
||||
// @retval: InstAlloca
|
||||
return lval;
|
||||
}
|
||||
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 {
|
||||
panic("To be implemented");
|
||||
case Type::TypeTag::ArrayType: {
|
||||
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");
|
||||
@ -494,7 +752,7 @@ std::any Visitor::visitFuncDef(SysyParser::FuncDefContext *ctx) {
|
||||
if (ctx->funcFParams()) {
|
||||
visitFuncFParams(ctx->funcFParams());
|
||||
}
|
||||
visit(ctx->block());
|
||||
visitBlock(ctx->block());
|
||||
// add return
|
||||
// _scope_tab.leave_scope();
|
||||
// TODO: avoid duplicate ret
|
||||
@ -507,36 +765,47 @@ std::any Visitor::visitFuncDef(SysyParser::FuncDefContext *ctx) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// @retval: any
|
||||
// Directly add to function, rather than return something...
|
||||
std::any Visitor::visitFuncFParams(SysyParser::FuncFParamsContext *ctx) {
|
||||
for (auto fparam : ctx->funcFParam()) {
|
||||
auto fparam_type = std::any_cast<TypePtr_t>(visit(fparam));
|
||||
auto fparam_name = fparam->getText();
|
||||
auto fparam_ptr = std::make_shared<FParam>(fparam_name, fparam_type);
|
||||
_state.current_func->fparam_list.push_back(fparam_ptr);
|
||||
if (fparam->LBRACKET().empty()) {
|
||||
auto alloca = build_InstAlloca(TypeHelper::TYPE_I32, false, _state.current_bb);
|
||||
auto store = build_InstStore(fparam_ptr, alloca, _state.current_bb);
|
||||
_scope_tab.push_name(fparam_name, alloca);
|
||||
_state.current_func->fparam_list.push_back(fparam_ptr);
|
||||
}
|
||||
else {
|
||||
panic("To be implemented");
|
||||
}
|
||||
for (auto fparam_ctx : ctx->funcFParam()) {
|
||||
auto fparam_type = std::any_cast<TypePtr_t>(visitFuncFParam(fparam_ctx));
|
||||
auto fparam_name = fparam_ctx->getText();
|
||||
auto fparam = std::make_shared<FParam>(fparam_name, fparam_type);
|
||||
_state.current_func->fparam_list.push_back(fparam);
|
||||
auto alloca_ = build_InstAlloca(fparam_type, _state.current_bb);
|
||||
build_InstStore(fparam, alloca_, _state.current_bb);
|
||||
_scope_tab.push_name(fparam_name, alloca_);
|
||||
_state.current_func->fparam_list.push_back(fparam);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
// funcFParam: bType IDENT ('[' ']' ('[' exp ']')*)?;
|
||||
std::any Visitor::visitFuncFParam(SysyParser::FuncFParamContext *ctx) {
|
||||
if (ctx->LBRACKET().empty()) {
|
||||
// int type
|
||||
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) {
|
||||
_scope_tab.enter_scope();
|
||||
for (auto block_item : ctx->blockItem()) {
|
||||
visit(block_item);
|
||||
visitBlockItem(block_item);
|
||||
}
|
||||
_scope_tab.leave_scope();
|
||||
return {};
|
||||
@ -556,8 +825,8 @@ stmt: lVal '=' exp ';' # assignStmt
|
||||
*/
|
||||
|
||||
std::any Visitor::visitAssignStmt(SysyParser::AssignStmtContext *ctx) {
|
||||
auto lval = any_to_Value(visit(ctx->lVal()));
|
||||
auto rhs = any_to_Value(visit(ctx->exp()));
|
||||
auto lval = any_to_Value(visitLVal(ctx->lVal()));
|
||||
auto rhs = any_to_Value(visitExp(ctx->exp()));
|
||||
auto store = build_InstStore(rhs, lval, _state.current_bb);
|
||||
return {};
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user