You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

227 lines
7.4 KiB

1 year ago
#ifndef _SYSYF_IR_BUILDER_H_
#define _SYSYF_IR_BUILDER_H_
#include "BasicBlock.h"
#include "Constant.h"
#include "Function.h"
#include "IRStmtBuilder.h"
#include "Module.h"
#include "Type.h"
#include <map>
#include "SyntaxTree.h"
namespace SysYF
{
namespace IR
{
class Scope {
public:
// enter a new scope
void enter() {
name2var.push_back({});
name2func.push_back({});
}
// exit a scope
void exit() {
name2var.pop_back();
name2func.pop_back();
}
bool in_global() {
return name2var.size() == 1;
}
// push a name to scope
// return true if successful
// return false if this name already exits
// but func name could be same with variable name
bool push(std::string name, Ptr<Value> val) {
bool result;
if (dynamic_pointer_cast<Function>(val)){
result = (name2func[name2func.size() - 1].insert({name, val})).second;
}
else{
result = (name2var[name2var.size() - 1].insert({name, val})).second;
}
return result;
}
Ptr<Value> find(std::string name, bool isfunc) {
if (isfunc){
for (auto s = name2func.rbegin(); s!= name2func.rend();s++) {
auto iter = s->find(name);
if (iter != s->end()) {
return iter->second;
}
}
}
else{
for (auto s = name2var.rbegin(); s!= name2var.rend();s++) {
auto iter = s->find(name);
if (iter != s->end()) {
return iter->second;
}
}
}
return nullptr;
}
private:
std::vector<std::map<std::string, Ptr<Value> >> name2var;
std::vector<std::map<std::string, Ptr<Value> >> name2func;
};
class IRBuilder: public SyntaxTree::Visitor
{
private:
virtual void visit(SyntaxTree::InitVal &) override final;
virtual void visit(SyntaxTree::Assembly &) override final;
virtual void visit(SyntaxTree::FuncDef &) override final;
virtual void visit(SyntaxTree::VarDef &) override final;
virtual void visit(SyntaxTree::AssignStmt &) override final;
virtual void visit(SyntaxTree::ReturnStmt &) override final;
virtual void visit(SyntaxTree::BlockStmt &) override final;
virtual void visit(SyntaxTree::EmptyStmt &) override final;
virtual void visit(SyntaxTree::ExprStmt &) override final;
virtual void visit(SyntaxTree::UnaryCondExpr &) override final;
virtual void visit(SyntaxTree::BinaryCondExpr &) override final;
virtual void visit(SyntaxTree::BinaryExpr &) override final;
virtual void visit(SyntaxTree::UnaryExpr &) override final;
virtual void visit(SyntaxTree::LVal &) override final;
virtual void visit(SyntaxTree::Literal &) override final;
virtual void visit(SyntaxTree::FuncCallStmt &) override final;
virtual void visit(SyntaxTree::FuncParam &) override final;
virtual void visit(SyntaxTree::FuncFParamList &) override final;
virtual void visit(SyntaxTree::IfStmt &) override final;
virtual void visit(SyntaxTree::WhileStmt &) override final;
virtual void visit(SyntaxTree::BreakStmt &) override final;
virtual void visit(SyntaxTree::ContinueStmt &) override final;
Ptr<IRStmtBuilder> builder;
Scope scope;
Ptr<Module> module;
IRBuilder() {
module = Module::create("SysYF code");
builder = IRStmtBuilder::create(nullptr, module);
auto TyVoid = Type::get_void_type(module);
auto TyInt32 = Type::get_int32_type(module);
auto TyInt32Ptr = Type::get_int32_ptr_type(module);
auto TyFloat = Type::get_float_type(module);
auto TyFloatPtr = Type::get_float_ptr_type(module);
auto input_type = FunctionType::create(TyInt32, {});
auto get_int =
Function::create(
input_type,
"get_int",
module);
input_type = FunctionType::create(TyFloat, {});
auto get_float =
Function::create(
input_type,
"get_float",
module);
input_type = FunctionType::create(TyInt32, {});
auto get_char =
Function::create(
input_type,
"get_char",
module);
PtrVec<Type> input_params;
PtrVec<Type> ().swap(input_params);
input_params.push_back(TyInt32Ptr);
input_type = FunctionType::create(TyInt32, input_params);
auto get_int_array =
Function::create(
input_type,
"get_int_array",
module);
PtrVec<Type> ().swap(input_params);
input_params.push_back(TyFloatPtr);
input_type = FunctionType::create(TyInt32, input_params);
auto get_float_array =
Function::create(
input_type,
"get_float_array",
module);
PtrVec<Type> output_params;
PtrVec<Type> ().swap(output_params);
output_params.push_back(TyInt32);
auto output_type = FunctionType::create(TyVoid, output_params);
auto put_int =
Function::create(
output_type,
"put_int",
module);
PtrVec<Type> ().swap(output_params);
output_params.push_back(TyFloat);
output_type = FunctionType::create(TyVoid, output_params);
auto put_float =
Function::create(
output_type,
"put_float",
module);
PtrVec<Type> ().swap(output_params);
output_params.push_back(TyInt32);
output_type = FunctionType::create(TyVoid, output_params);
auto put_char =
Function::create(
output_type,
"put_char",
module);
PtrVec<Type> ().swap(output_params);
output_params.push_back(TyInt32);
output_params.push_back(TyInt32Ptr);
output_type = FunctionType::create(TyVoid, output_params);
auto put_int_array =
Function::create(
output_type,
"put_int_array",
module);
PtrVec<Type> ().swap(output_params);
output_params.push_back(TyInt32);
output_params.push_back(TyFloatPtr);
output_type = FunctionType::create(TyVoid, output_params);
auto put_float_array =
Function::create(
output_type,
"put_float_array",
module);
scope.enter();
scope.push("getint", get_int);
scope.push("getfloat", get_float);
scope.push("getch", get_char);
scope.push("getarray", get_int_array);
scope.push("get_float_array", get_float_array);
scope.push("putint", put_int);
scope.push("putfloat", put_float);
scope.push("putch", put_char);
scope.push("putarray", put_int_array);
scope.push("putfloatarray", put_float_array);
}
public:
static Ptr<IRBuilder> create() {
return Ptr<IRBuilder>(new IRBuilder());
}
Ptr<Module> getModule() {
return module;
}
};
}
}
#endif // _SYSYF_IR_BUILDER_H_