This commit is contained in:
ridethepig 2023-05-08 19:41:14 +08:00
parent dd48562daa
commit 1bbad18f52
7 changed files with 257 additions and 40 deletions

16
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,16 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug",
"program": "${workspaceFolder}/build/sysy",
"args": ["testcases/functional/55_sort_test1.sy", "-S", "-o", "sss"],
"cwd": "${workspaceFolder}"
}
]
}

View File

@ -20,6 +20,11 @@
namespace antlrSysY { namespace antlrSysY {
template <typename T>
std::ostream &operator<<(typename std::enable_if<std::is_enum<T>::value, std::ostream>::type &stream, const T &e) {
return stream << static_cast<typename std::underlying_type<T>::type>(e);
}
class GrammarException : public std::exception { class GrammarException : public std::exception {
public: public:
GrammarException() : message("Unknown Grammar Exception") {} GrammarException() : message("Unknown Grammar Exception") {}

View File

@ -2,6 +2,7 @@
#include "common.h" #include "common.h"
#include <memory> #include <memory>
#include <string>
#include <vector> #include <vector>
namespace antlrSysY { namespace antlrSysY {
@ -19,6 +20,24 @@ public:
TypeTag type_tag; TypeTag type_tag;
Type(TypeTag type_tag) : type_tag(type_tag) {} Type(TypeTag type_tag) : type_tag(type_tag) {}
virtual ~Type() = default; virtual ~Type() = default;
virtual std::string to_string() {
switch (type_tag) {
case TypeTag::IntegerType:
return "IntegerType";
case TypeTag::FunctionType:
return "FunctionType";
case TypeTag::ArrayType:
return "ArrayType";
case TypeTag::PointerType:
return "PointerType";
case TypeTag::VectorType:
return "VectorType";
case TypeTag::VoidType:
return "VoidType";
case TypeTag::LabelType:
return "LabelType";
}
}
}; };
class IntegerType : public Type { class IntegerType : public Type {
@ -78,6 +97,9 @@ public:
} }
return std::dynamic_pointer_cast<ArrayType>(array_type); return std::dynamic_pointer_cast<ArrayType>(array_type);
} }
virtual std::string to_string() override {
return "Array[" + std::to_string(element_count) + " x " + element_type->to_string() + "]";
}
}; };
class PointerType : public Type { class PointerType : public Type {
@ -85,6 +107,12 @@ public:
TypePtr_t pointed_type = TypeHelper::TYPE_I32; TypePtr_t pointed_type = TypeHelper::TYPE_I32;
PointerType() : Type(TypeTag::PointerType) {} PointerType() : Type(TypeTag::PointerType) {}
PointerType(TypePtr_t pointed_type) : Type(TypeTag::PointerType), pointed_type(pointed_type) {} PointerType(TypePtr_t pointed_type) : Type(TypeTag::PointerType), pointed_type(pointed_type) {}
static auto make_shared(TypePtr_t pointed_type) {
return std::make_shared<PointerType>(pointed_type);
}
virtual std::string to_string() override {
return "Pointer->" + pointed_type->to_string();
}
}; };
class FunctionType : public Type { class FunctionType : public Type {

View File

@ -5,6 +5,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "3rdparty/easylogging++.h"
#include "common.h" #include "common.h"
#include "llir_type.h" #include "llir_type.h"
@ -16,6 +17,17 @@ public:
TypePtr_t type; TypePtr_t type;
Value(const std::string &name, TypePtr_t type) : name(name), type(type) {} Value(const std::string &name, TypePtr_t type) : name(name), type(type) {}
virtual ~Value() = default; virtual ~Value() = default;
template <typename TT> static bool isType(std::shared_ptr<Value> ptr) {
if (ptr.get()) {
auto &r = *ptr.get();
return typeid(r) == typeid(TT);
}
LOG(WARNING) << "Comparing with nullptr";
return false;
}
virtual std::string to_string() {
return name + ": " + type->to_string();
}
}; };
class User : public Value { class User : public Value {
@ -34,10 +46,21 @@ class Function : public Value {
public: public:
std::vector<std::shared_ptr<FParam>> fparam_list; std::vector<std::shared_ptr<FParam>> fparam_list;
std::vector<std::shared_ptr<BasicBlock>> bb_list; std::vector<std::shared_ptr<BasicBlock>> bb_list;
// we use empty basic_block to represent lib function
Function(const std::string &name, TypePtr_t ret_type) : Value(name, std::make_shared<FunctionType>(ret_type)) {} Function(const std::string &name, TypePtr_t ret_type) : Value(name, std::make_shared<FunctionType>(ret_type)) {}
std::shared_ptr<FunctionType> get_type() { std::shared_ptr<FunctionType> get_type() {
return std::dynamic_pointer_cast<FunctionType>(type); return std::dynamic_pointer_cast<FunctionType>(type);
} }
bool is_libfunc() {
return bb_list.size() == 0;
}
virtual std::string to_string() override {
std::string params_str;
for (auto fparam : fparam_list) {
params_str += fparam->to_string() + ",";
}
return name + "(" + params_str + ") -> " + type->to_string();
}
}; };
class BasicBlock : public Value { class BasicBlock : public Value {
@ -82,12 +105,13 @@ public:
typedef std::shared_ptr<Constant> ConstantPtr_t; typedef std::shared_ptr<Constant> ConstantPtr_t;
// emmm, actually it is more of a Instruction type
class GlobalVar : public Value { class GlobalVar : public Value {
public: public:
ConstantPtr_t init_value; ConstantPtr_t init_value;
bool is_const; bool is_const;
GlobalVar(const std::string &name, 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) {} : 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) { 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); return std::make_shared<GlobalVar>(name, init_value, is_const);
} }
@ -129,6 +153,62 @@ public:
std::vector<std::shared_ptr<Value>> operand_list; std::vector<std::shared_ptr<Value>> operand_list;
Instruction(InstTag inst_tag, TypePtr_t type, std::shared_ptr<BasicBlock> parent_bb) Instruction(InstTag inst_tag, TypePtr_t type, std::shared_ptr<BasicBlock> parent_bb)
: Value("", type), tag(inst_tag), parent_bb(parent_bb) {} : Value("", type), tag(inst_tag), parent_bb(parent_bb) {}
virtual std::string to_string() override {
switch (tag) {
case InstTag::Add:
return "Add";
case InstTag::Sub:
return "Sub";
case InstTag::Mod:
return "Mod";
case InstTag::Mul:
return "Mul";
case InstTag::Div:
return "Div";
case InstTag::Lt:
return "Lt";
case InstTag::Le:
return "Le";
case InstTag::Ge:
return "Ge";
case InstTag::Gt:
return "Gt";
case InstTag::Eq:
return "Eq";
case InstTag::Ne:
return "Ne";
case InstTag::And:
return "And";
case InstTag::Or:
return "Or";
case InstTag::Br:
return "Br";
case InstTag::Call:
return "Call";
case InstTag::Ret:
return "Ret";
case InstTag::Alloca:
return "Alloca";
case InstTag::Load:
return "Load";
case InstTag::Store:
return "Store";
case InstTag::GEP:
return "GEP";
case InstTag::Zext:
return "Zext";
case InstTag::Phi:
return "Phi";
case InstTag::MemPhi:
return "MemPhi";
case InstTag::LoadDep:
return "LoadDep";
case InstTag::InsertEle:
return "InsertEle";
case InstTag::ExtractEle:
return "ExtractEle";
}
}
}; };
class InstAlloca : public Instruction { class InstAlloca : public Instruction {
@ -215,14 +295,17 @@ public:
TypePtr_t element_type; TypePtr_t element_type;
InstGEP(ValuePtr_t pointer, const std::vector<ValuePtr_t> &indices, BasicBlockPtr_t parent_bb) 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) { : Instruction(InstTag::GEP, std::make_shared<PointerType>(extract_type(pointer, indices)), parent_bb) {
if (typeid(pointer) == typeid(std::shared_ptr<InstGEP>)) { if (Value::isType<InstGEP>(pointer)) {
aim_to = std::dynamic_pointer_cast<InstGEP>(pointer)->aim_to; aim_to = std::dynamic_pointer_cast<InstGEP>(pointer)->aim_to;
} }
else { else if (Value::isType<InstAlloca>(pointer) || Value::isType<GlobalVar>(pointer)){
sysy_assert(typeid(pointer) == typeid(std::shared_ptr<InstAlloca>) ||
typeid(pointer) == typeid(std::shared_ptr<GlobalVar>));
aim_to = pointer; aim_to = pointer;
} }
else {
LOG(WARNING) << "Unexpected pointer type" << pointer->to_string();
aim_to = pointer;
panic("message");
}
element_type = extract_type(pointer, indices); element_type = extract_type(pointer, indices);
operand_list.push_back(pointer); operand_list.push_back(pointer);
operand_list.insert(operand_list.end(), indices.begin(), indices.end()); operand_list.insert(operand_list.end(), indices.begin(), indices.end());
@ -232,8 +315,9 @@ public:
static TypePtr_t extract_type(ValuePtr_t pointer, const std::vector<ValuePtr_t> &indices) { 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 pointer_type = std::dynamic_pointer_cast<PointerType>(pointer->type);
auto pointed_type = pointer_type->pointed_type; auto pointed_type = pointer_type->pointed_type;
// ptr->array
if (pointed_type->type_tag == Type::TypeTag::ArrayType) { if (pointed_type->type_tag == Type::TypeTag::ArrayType) {
for (int i = 1; i < indices.size() - 1; ++i) { for (int i = 1; i < indices.size(); ++i) {
pointed_type = std::dynamic_pointer_cast<ArrayType>(pointed_type)->element_type; pointed_type = std::dynamic_pointer_cast<ArrayType>(pointed_type)->element_type;
} }
} }
@ -241,7 +325,8 @@ public:
return pointed_type; return pointed_type;
} }
else { else {
panic("Unmatch indices and array pointer"); LOG(WARNING) << "not returning an int-type";
return pointed_type;
} }
} }
}; };

View File

@ -90,10 +90,7 @@ public:
} }
CONST0 = std::make_shared<ConstantInt>("CONST0", 0); CONST0 = std::make_shared<ConstantInt>("CONST0", 0);
} }
std::any visitProgram(SysyParser::ProgramContext *ctx) override { std::any visitProgram(SysyParser::ProgramContext *ctx) override;
// before visiting, we add some lib functions
return this->SysyBaseVisitor::visitProgram(ctx);
}
// std::any visitCompUnit(SysyParser::CompUnitContext *ctx) override; // std::any visitCompUnit(SysyParser::CompUnitContext *ctx) override;
@ -158,7 +155,7 @@ public:
std::any visitReturnStmt(SysyParser::ReturnStmtContext *ctx) override; std::any visitReturnStmt(SysyParser::ReturnStmtContext *ctx) override;
// std::any visitCond(SysyParser::CondContext *ctx) override; std::any visitCond(SysyParser::CondContext *ctx) override;
// std::any visitFuncRParams(SysyParser::FuncRParamsContext *ctx) override; // std::any visitFuncRParams(SysyParser::FuncRParamsContext *ctx) override;

View File

@ -145,7 +145,7 @@ 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: if self.count_error >= 5:
Print_C.print_error(f"Test script stopped due to too many errors") Print_C.print_error(f"Test script stopped due to too many errors")
return return

View File

@ -39,10 +39,80 @@ static ValuePtr_t any_to_Value(const std::any &fuck_any) {
ANY2VALUE(InstBranch) ANY2VALUE(InstBranch)
ANY2VALUE(InstReturn) ANY2VALUE(InstReturn)
ANY2VALUE(InstCall) ANY2VALUE(InstCall)
ANY2VALUE(InstGEP)
LOG(ERROR) << fuck_any.type().name(); LOG(ERROR) << fuck_any.type().name();
panic("Unreachable"); panic("Unreachable");
} }
static TypePtr_t any_to_Type(const std::any &fuck_any) {
ANY2VALUE(Type)
ANY2VALUE(ArrayType)
ANY2VALUE(FunctionType)
ANY2VALUE(IntegerType)
ANY2VALUE(PointerType)
LOG(ERROR) << fuck_any.type().name();
panic("Unreachable");
}
/*
int getint(),getch(),getarray(int a[]);
void putint(int a),putch(int a),putarray(int n,int a[]);
#define starttime() _sysy_starttime(__LINE__)
#define stoptime() _sysy_stoptime(__LINE__)
__attribute((constructor)) void before_main();
__attribute((destructor)) void after_main();
void _sysy_starttime(int lineno);
void _sysy_stoptime(int lineno);
*/
std::any Visitor::visitProgram(SysyParser::ProgramContext *ctx) {
#pragma region RegisterLibFunc
auto fparam_i32 = std::make_shared<FParam>("", TypeHelper::TYPE_I32);
auto pointer_type = std::make_shared<PointerType>(TypeHelper::TYPE_I32);
auto fparam_ptr_i32 = std::make_shared<FParam>("", pointer_type);
auto func_getint = std::make_shared<Function>("getint", TypeHelper::TYPE_I32);
// void param
_func_tab.push_name("getint", func_getint);
auto func_getch = std::make_shared<Function>("getch", TypeHelper::TYPE_I32);
// void param
_func_tab.push_name("getch", func_getch);
auto func_getarray = std::make_shared<Function>("getarray", TypeHelper::TYPE_I32);
func_getarray->fparam_list.push_back(fparam_ptr_i32);
_func_tab.push_name("getarray", func_getarray);
auto func_putint = std::make_shared<Function>("putint", TypeHelper::TYPE_VOID);
func_putint->fparam_list.push_back(fparam_i32);
_func_tab.push_name("putint", func_putint);
auto func_putch = std::make_shared<Function>("putch", TypeHelper::TYPE_VOID);
func_putch->fparam_list = {fparam_i32};
_func_tab.push_name("putch", func_putch);
auto func_putarray = std::make_shared<Function>("putarray", TypeHelper::TYPE_VOID);
func_putarray->fparam_list = {fparam_ptr_i32, fparam_i32};
_func_tab.push_name("putarray", func_putarray);
// auto func_putf = std::make_shared<Function>("putf", TypeHelper::TYPE_VOID);
// should not be used
auto func_starttime = std::make_shared<Function>("_sysy_starttime", TypeHelper::TYPE_VOID);
func_starttime->fparam_list = {fparam_i32};
_func_tab.push_name("starttime", func_starttime);
auto func_stoptime = std::make_shared<Function>("_sysy_stoptime", TypeHelper::TYPE_VOID);
func_stoptime->fparam_list = {fparam_i32};
_func_tab.push_name("stoptime", func_stoptime);
#pragma endregion
SysyBaseVisitor::visitProgram(ctx);
return {};
}
std::any Visitor::visitConstDecl(SysyParser::ConstDeclContext *ctx) { std::any Visitor::visitConstDecl(SysyParser::ConstDeclContext *ctx) {
for (auto constDef : ctx->constDef()) { for (auto constDef : ctx->constDef()) {
visitConstDef(constDef); visitConstDef(constDef);
@ -222,7 +292,7 @@ std::any Visitor::visitInitVal(SysyParser::InitValContext *ctx) {
if (_state.isGlobalIint) { if (_state.isGlobalIint) {
auto const_value = any_to_Value(visitInitVal(init_val)); auto const_value = any_to_Value(visitInitVal(init_val));
// should evaluate to const int // should evaluate to const int
sysy_assert(typeid(const_value) == typeid(std::shared_ptr<ConstantInt>)); sysy_assert(Value::isType<ConstantInt>(const_value));
cur_arr.push_back(const_value); cur_arr.push_back(const_value);
} }
else { else {
@ -347,9 +417,9 @@ 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) {
auto result = std::any_cast<std::shared_ptr<ConstantInt>>(visitUnaryExp(ctx->unaryExp())); auto result = std::dynamic_pointer_cast<ConstantInt>(any_to_Value(visitUnaryExp(ctx->unaryExp())));
if (ctx->mulExp()) { if (ctx->mulExp()) {
auto mul_result = std::any_cast<std::shared_ptr<ConstantInt>>(visitMulExp(ctx->mulExp())); auto mul_result = std::dynamic_pointer_cast<ConstantInt>(any_to_Value(visitMulExp(ctx->mulExp())));
if (ctx->MUL()) { if (ctx->MUL()) {
result->value = mul_result->value * result->value; result->value = mul_result->value * result->value;
} }
@ -392,36 +462,36 @@ std::any Visitor::visitMulExp(SysyParser::MulExpContext *ctx) {
// relExp: addExp | relExp ('<' | '>' | '<=' | '>=') addExp; // relExp: addExp | relExp ('<' | '>' | '<=' | '>=') addExp;
std::any Visitor::visitRelExp(SysyParser::RelExpContext *ctx) { std::any Visitor::visitRelExp(SysyParser::RelExpContext *ctx) {
auto add_exp = any_to_Value(visitAddExp(ctx->addExp())); auto add_exp = any_to_Value(visitAddExp(ctx->addExp()));
// should always has type I32
sysy_assert(TypeHelper::isIntegerTypeI32(add_exp->type));
if (ctx->relExp()) { if (ctx->relExp()) {
auto rel_exp = any_to_Value(visitRelExp(ctx->relExp())); auto rel_exp = any_to_Value(visitRelExp(ctx->relExp()));
sysy_assert(TypeHelper::isIntegerTypeI32(rel_exp->type)); sysy_assert(TypeHelper::isIntegerTypeI32(rel_exp->type));
if (ctx->relExp()->LE()) { if (ctx->LE()) {
add_exp = build_InstBinary(InstTag::Le, rel_exp, add_exp, _state.current_bb); add_exp = build_InstBinary(InstTag::Le, rel_exp, add_exp, _state.current_bb);
} }
else if (ctx->relExp()->LT()) { else if (ctx->LT()) {
add_exp = build_InstBinary(InstTag::Lt, rel_exp, add_exp, _state.current_bb); add_exp = build_InstBinary(InstTag::Lt, rel_exp, add_exp, _state.current_bb);
} }
else if (ctx->relExp()->GE()) { else if (ctx->GE()) {
add_exp = build_InstBinary(InstTag::Ge, rel_exp, add_exp, _state.current_bb); add_exp = build_InstBinary(InstTag::Ge, rel_exp, add_exp, _state.current_bb);
} }
else if (ctx->relExp()->GT()) { else if (ctx->GT()) {
add_exp = build_InstBinary(InstTag::Gt, rel_exp, add_exp, _state.current_bb); add_exp = build_InstBinary(InstTag::Gt, rel_exp, add_exp, _state.current_bb);
} }
else else {
LOG(ERROR) << ctx->relExp()->getStart()->getLine() << ":" << ctx->relExp()->getText();
panic("Unreachable"); panic("Unreachable");
} }
}
return add_exp; return add_exp;
} }
// eqExp: relExp | eqExp ('==' | '!=') relExp; // eqExp: relExp | eqExp ('==' | '!=') relExp;
std::any Visitor::visitEqExp(SysyParser::EqExpContext *ctx) { std::any Visitor::visitEqExp(SysyParser::EqExpContext *ctx) {
auto rel_exp = any_to_Value(visitRelExp(ctx->relExp())); auto rel_exp = any_to_Value(visitRelExp(ctx->relExp()));
sysy_assert(TypeHelper::isIntegerTypeI1(rel_exp->type)); // sysy_assert(TypeHelper::isIntegerTypeI1(rel_exp->type));
if (ctx->eqExp()) { if (ctx->eqExp()) {
auto eq_exp = any_to_Value(visitEqExp(ctx->eqExp())); auto eq_exp = any_to_Value(visitEqExp(ctx->eqExp()));
sysy_assert(TypeHelper::isIntegerTypeI1(eq_exp->type)); // sysy_assert(TypeHelper::isIntegerTypeI1(eq_exp->type));
if (ctx->EQ()) { if (ctx->EQ()) {
rel_exp = build_InstBinary(InstTag::Eq, eq_exp, rel_exp, _state.current_bb); rel_exp = build_InstBinary(InstTag::Eq, eq_exp, rel_exp, _state.current_bb);
} }
@ -444,7 +514,6 @@ std::any Visitor::visitLAndExp(SysyParser::LAndExpContext *ctx) {
for (int i = 0; i < eq_exp_list.size(); ++i) { for (int i = 0; i < eq_exp_list.size(); ++i) {
auto next_block = build_BasicBlock("", _state.current_func); auto next_block = build_BasicBlock("", _state.current_func);
auto eq_exp = any_to_Value(visitEqExp(eq_exp_list[i])); auto eq_exp = any_to_Value(visitEqExp(eq_exp_list[i]));
sysy_assert(TypeHelper::isIntegerTypeI1(eq_exp->type)); // expect a boolean
auto condition = build_InstBinary(InstTag::Ne, eq_exp, CONST0, _state.current_bb); auto condition = build_InstBinary(InstTag::Ne, eq_exp, CONST0, _state.current_bb);
build_InstBranch(condition, next_block, ctx->false_block, _state.current_bb); build_InstBranch(condition, next_block, ctx->false_block, _state.current_bb);
_state.current_bb = next_block; _state.current_bb = next_block;
@ -456,16 +525,26 @@ std::any Visitor::visitLAndExp(SysyParser::LAndExpContext *ctx) {
// @retval: Bool // @retval: Bool
// lOrExp: lAndExp ('||' lAndExp)*; // lOrExp: lAndExp ('||' lAndExp)*;
std::any Visitor::visitLOrExp(SysyParser::LOrExpContext *ctx) { std::any Visitor::visitLOrExp(SysyParser::LOrExpContext *ctx) {
auto n_and_exp = ctx->lAndExp().size(); LOG(DEBUG) << "Eval to Cond(lOrExp); lineno=" << ctx->getStart()->getLine();
auto and_exp_list = ctx->lAndExp();
auto n_and_exp = and_exp_list.size();
for (int i = 0; i < n_and_exp - 1; ++i) { for (int i = 0; i < n_and_exp - 1; ++i) {
auto next_block = build_BasicBlock("", _state.current_func); auto next_block = build_BasicBlock("", _state.current_func);
ctx->lAndExp(i)->true_block = ctx->true_block; ctx->lAndExp(i)->true_block = ctx->true_block;
ctx->lAndExp(i)->false_block = next_block; ctx->lAndExp(i)->false_block = next_block;
visitLAndExp(ctx->lAndExp(i)); visitLAndExp(and_exp_list[i]);
_state.current_bb = next_block; _state.current_bb = next_block;
} }
ctx->lAndExp(n_and_exp - 1)->true_block = ctx->true_block; ctx->lAndExp(n_and_exp - 1)->true_block = ctx->true_block;
ctx->lAndExp(n_and_exp - 1)->false_block = ctx->false_block; ctx->lAndExp(n_and_exp - 1)->false_block = ctx->false_block;
visitLAndExp(ctx->lAndExp(n_and_exp-1));
return {};
}
std::any Visitor::visitCond(SysyParser::CondContext *ctx) {
_state.isCondExp = true;
visitLOrExp(ctx->lOrExp());
_state.isCondExp = false;
return {}; return {};
} }
@ -551,9 +630,10 @@ std::any Visitor::visitPrimaryExp(SysyParser::PrimaryExpContext *ctx) {
} }
else if (ctx->lVal()) { else if (ctx->lVal()) {
auto value = any_to_Value(visitLVal(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;
return value;
} }
else if (ctx->number()) { else if (ctx->number()) {
return visitNumber(ctx->number()); return visitNumber(ctx->number());
@ -579,7 +659,7 @@ std::any Visitor::visitPrimaryExp(SysyParser::PrimaryExpContext *ctx) {
} }
// @retval: InstLoad // @retval: InstLoad
else { else {
LOG(WARNING) << "lval type is pointer"; LOG(WARNING) << "lval type is pointer: " << lval->type->type_tag;
// should be InstAlloca // should be InstAlloca
auto ptr_type = std::dynamic_pointer_cast<PointerType>(lval->type); auto ptr_type = std::dynamic_pointer_cast<PointerType>(lval->type);
return build_InstLoad(lval, ptr_type->pointed_type, _state.current_bb); return build_InstLoad(lval, ptr_type->pointed_type, _state.current_bb);
@ -618,10 +698,11 @@ std::any Visitor::visitIntConst(SysyParser::IntConstContext *ctx) {
std::any Visitor::visitLVal(SysyParser::LValContext *ctx) { std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
auto name = ctx->IDENT()->getText(); auto name = ctx->IDENT()->getText();
LOG(DEBUG) << "Eval to lVal " << name; LOG(DEBUG) << "Eval to lVal " << name << "; lineno=" << ctx->getStart()->getLine();
auto _lval = _scope_tab.get_name(name); auto _lval = _scope_tab.get_name(name);
sysy_assert(_lval.has_value()); sysy_assert(_lval.has_value());
auto lval = _lval.value(); auto lval = _lval.value();
LOG(DEBUG) << "lVal found: " << lval->to_string();
// @retval: ConstantInt // @retval: ConstantInt
if (lval->type->type_tag == Type::TypeTag::IntegerType) { if (lval->type->type_tag == Type::TypeTag::IntegerType) {
return {lval}; return {lval};
@ -653,18 +734,19 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
// ??? Pointer // ??? Pointer
// @retval: InstLoad // @retval: InstLoad
LOG(WARNING) << "Unexpected pointer"; LOG(WARNING) << "Unexpected pointer";
auto pointed_type = std::dynamic_pointer_cast<PointerType>(lval)->pointed_type; auto pointed_type = std::dynamic_pointer_cast<PointerType>(lval->type)->pointed_type;
auto inst_load = build_InstLoad(lval, pointed_type, _state.current_bb); auto inst_load = build_InstLoad(lval, pointed_type, _state.current_bb);
return inst_load; return inst_load;
} }
else { else {
// fparam array, whose first dim is represented by a pointer // fparam array, whose first dim is represented by a pointer
auto pointed_type = std::dynamic_pointer_cast<PointerType>(lval)->pointed_type; auto pointed_type = std::dynamic_pointer_cast<PointerType>(lval->type)->pointed_type;
sysy_assert(pointed_type->type_tag == Type::TypeTag::ArrayType);
auto inst_load = build_InstLoad(lval, pointed_type, _state.current_bb); auto inst_load = build_InstLoad(lval, pointed_type, _state.current_bb);
auto ptr = build_InstGEP(inst_load, {CONST0}, _state.current_bb); auto ptr = build_InstGEP(inst_load, {CONST0}, _state.current_bb);
pointed_type = std::dynamic_pointer_cast<PointerType>(ptr->type)->pointed_type; 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); ValuePtr_t offset = ConstantInt::make_shared(0);
auto exp_list = ctx->exp(); auto exp_list = ctx->exp();
// calculate offset by hand: offset = (offset + exp[i]) * dim_size[i] // calculate offset by hand: offset = (offset + exp[i]) * dim_size[i]
@ -704,7 +786,7 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
auto exp_list = ctx->exp(); auto exp_list = ctx->exp();
// calculate offset by hand: offset = (offset + exp[i]) * dim_size[i] // calculate offset by hand: offset = (offset + exp[i]) * dim_size[i]
for (int i = 0; i < exp_list.size() - 1; ++i) { for (int i = 0; i < exp_list.size() - 1; ++i) {
sysy_assert(typeid(pointed_type) == typeid(std::shared_ptr<ArrayType>)); sysy_assert(pointed_type->type_tag == Type::TypeTag::ArrayType);
auto array_type = std::dynamic_pointer_cast<ArrayType>(pointed_type); auto array_type = std::dynamic_pointer_cast<ArrayType>(pointed_type);
auto exp_val = any_to_Value(visitExp(exp_list[i])); auto exp_val = any_to_Value(visitExp(exp_list[i]));
auto dim_size = ConstantInt::make_shared(array_type->element_count); auto dim_size = ConstantInt::make_shared(array_type->element_count);
@ -752,6 +834,7 @@ std::any Visitor::visitFuncDef(SysyParser::FuncDefContext *ctx) {
if (ctx->funcFParams()) { if (ctx->funcFParams()) {
visitFuncFParams(ctx->funcFParams()); visitFuncFParams(ctx->funcFParams());
} }
LOG(DEBUG) << func_obj->to_string();
visitBlock(ctx->block()); visitBlock(ctx->block());
// add return // add return
// _scope_tab.leave_scope(); // _scope_tab.leave_scope();
@ -769,10 +852,9 @@ std::any Visitor::visitFuncDef(SysyParser::FuncDefContext *ctx) {
// Directly add to function, rather than return something... // 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 : ctx->funcFParam()) { for (auto fparam_ctx : ctx->funcFParam()) {
auto fparam_type = std::any_cast<TypePtr_t>(visitFuncFParam(fparam_ctx)); auto fparam_type = any_to_Type(visitFuncFParam(fparam_ctx));
auto fparam_name = fparam_ctx->getText(); auto fparam_name = fparam_ctx->IDENT()->getText();
auto fparam = 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);
auto alloca_ = build_InstAlloca(fparam_type, _state.current_bb); auto alloca_ = build_InstAlloca(fparam_type, _state.current_bb);
build_InstStore(fparam, alloca_, _state.current_bb); build_InstStore(fparam, alloca_, _state.current_bb);
_scope_tab.push_name(fparam_name, alloca_); _scope_tab.push_name(fparam_name, alloca_);
@ -789,7 +871,7 @@ std::any Visitor::visitFuncFParam(SysyParser::FuncFParamContext *ctx) {
} }
else { else {
// array type // array type
std::vector<int> dim_list; // the first dim must be empty, though std::vector<int> dim_list = {0}; // the first dim must be empty, though
for (auto exp_ctx : ctx->exp()) { for (auto exp_ctx : ctx->exp()) {
_state.isConstInt = true; _state.isConstInt = true;
auto exp_val = std::dynamic_pointer_cast<ConstantInt>(any_to_Value(visitExp(exp_ctx))); auto exp_val = std::dynamic_pointer_cast<ConstantInt>(any_to_Value(visitExp(exp_ctx)));
@ -833,6 +915,8 @@ std::any Visitor::visitAssignStmt(SysyParser::AssignStmtContext *ctx) {
// TODO: Remove RETURN in else stmt // TODO: Remove RETURN in else stmt
std::any Visitor::visitIfStmt(SysyParser::IfStmtContext *ctx) { std::any Visitor::visitIfStmt(SysyParser::IfStmtContext *ctx) {
LOG(DEBUG) << "Visiting IfStmt "
<< "; lineno=" << ctx->getStart()->getLine();
auto true_block = build_BasicBlock("_then", _state.current_func); auto true_block = build_BasicBlock("_then", _state.current_func);
auto next_block = build_BasicBlock("_next", _state.current_func); auto next_block = build_BasicBlock("_next", _state.current_func);
auto false_block = next_block; auto false_block = next_block;
@ -857,6 +941,8 @@ std::any Visitor::visitIfStmt(SysyParser::IfStmtContext *ctx) {
// TODO: backpatching? I am not sure whether it is necessary // TODO: backpatching? I am not sure whether it is necessary
std::any Visitor::visitWhileStmt(SysyParser::WhileStmtContext *ctx) { std::any Visitor::visitWhileStmt(SysyParser::WhileStmtContext *ctx) {
LOG(DEBUG) << "Visiting WhileStmt "
<< "; lineno=" << ctx->getStart()->getLine();
auto while_id = std::to_string(_state.loop_stmt_count); auto while_id = std::to_string(_state.loop_stmt_count);
auto cond_block = build_BasicBlock("_loop_cond_" + while_id, _state.current_func); auto cond_block = build_BasicBlock("_loop_cond_" + while_id, _state.current_func);
auto body_block = build_BasicBlock("_loop_body_" + while_id, _state.current_func); auto body_block = build_BasicBlock("_loop_body_" + while_id, _state.current_func);