fix(ir): 修改了一下context的管理
This commit is contained in:
@@ -12,6 +12,10 @@ BasicBlock::BasicBlock(std::string name) : name_(std::move(name)) {}
|
|||||||
|
|
||||||
const std::string& BasicBlock::name() const { return name_; }
|
const std::string& BasicBlock::name() const { return name_; }
|
||||||
|
|
||||||
|
Function* BasicBlock::parent() const { return parent_; }
|
||||||
|
|
||||||
|
void BasicBlock::set_parent(Function* parent) { parent_ = parent; }
|
||||||
|
|
||||||
bool BasicBlock::HasTerminator() const {
|
bool BasicBlock::HasTerminator() const {
|
||||||
return !instructions_.empty() && instructions_.back()->IsTerminator();
|
return !instructions_.empty() && instructions_.back()->IsTerminator();
|
||||||
}
|
}
|
||||||
@@ -21,4 +25,12 @@ const std::vector<std::unique_ptr<Instruction>>& BasicBlock::instructions()
|
|||||||
return instructions_;
|
return instructions_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<BasicBlock*>& BasicBlock::predecessors() const {
|
||||||
|
return predecessors_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<BasicBlock*>& BasicBlock::successors() const {
|
||||||
|
return successors_;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ir
|
} // namespace ir
|
||||||
|
|||||||
@@ -7,11 +7,6 @@
|
|||||||
|
|
||||||
namespace ir {
|
namespace ir {
|
||||||
|
|
||||||
Context& DefaultContext() {
|
|
||||||
static Context ctx;
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
Context::~Context() = default;
|
Context::~Context() = default;
|
||||||
|
|
||||||
const std::shared_ptr<Type>& Context::Void() {
|
const std::shared_ptr<Type>& Context::Void() {
|
||||||
@@ -39,7 +34,7 @@ ConstantInt* Context::GetConstInt(int v) {
|
|||||||
auto it = const_ints_.find(v);
|
auto it = const_ints_.find(v);
|
||||||
if (it != const_ints_.end()) return it->second.get();
|
if (it != const_ints_.end()) return it->second.get();
|
||||||
auto inserted =
|
auto inserted =
|
||||||
const_ints_.emplace(v, std::make_unique<ConstantInt>(v)).first;
|
const_ints_.emplace(v, std::make_unique<ConstantInt>(Int32(), v)).first;
|
||||||
return inserted->second.get();
|
return inserted->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ Function::Function(std::string name, std::shared_ptr<Type> ret_type)
|
|||||||
BasicBlock* Function::CreateBlock(const std::string& name) {
|
BasicBlock* Function::CreateBlock(const std::string& name) {
|
||||||
auto block = std::make_unique<BasicBlock>(name);
|
auto block = std::make_unique<BasicBlock>(name);
|
||||||
auto* ptr = block.get();
|
auto* ptr = block.get();
|
||||||
|
ptr->set_parent(this);
|
||||||
blocks_.push_back(std::move(block));
|
blocks_.push_back(std::move(block));
|
||||||
if (!entry_) {
|
if (!entry_) {
|
||||||
entry_ = ptr;
|
entry_ = ptr;
|
||||||
|
|||||||
37
src/ir/IR.h
37
src/ir/IR.h
@@ -2,6 +2,7 @@
|
|||||||
// 可在此基础上扩展更多类型/指令
|
// 可在此基础上扩展更多类型/指令
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <iosfwd>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -15,10 +16,12 @@ class Type;
|
|||||||
class ConstantInt;
|
class ConstantInt;
|
||||||
class Instruction;
|
class Instruction;
|
||||||
class BasicBlock;
|
class BasicBlock;
|
||||||
|
class Function;
|
||||||
|
|
||||||
// IR 上下文:集中管理类型、常量等共享资源,便于复用与扩展。
|
// IR 上下文:集中管理类型、常量等共享资源,便于复用与扩展。
|
||||||
class Context {
|
class Context {
|
||||||
public:
|
public:
|
||||||
|
Context() = default;
|
||||||
~Context();
|
~Context();
|
||||||
const std::shared_ptr<Type>& Void();
|
const std::shared_ptr<Type>& Void();
|
||||||
const std::shared_ptr<Type>& Int32();
|
const std::shared_ptr<Type>& Int32();
|
||||||
@@ -36,16 +39,14 @@ class Context {
|
|||||||
int temp_index_ = -1;
|
int temp_index_ = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
Context& DefaultContext();
|
|
||||||
|
|
||||||
class Type {
|
class Type {
|
||||||
public:
|
public:
|
||||||
enum class Kind { Void, Int32, PtrInt32 };
|
enum class Kind { Void, Int32, PtrInt32 };
|
||||||
explicit Type(Kind k);
|
explicit Type(Kind k);
|
||||||
Kind kind() const;
|
Kind kind() const;
|
||||||
static std::shared_ptr<Type> Void();
|
bool IsVoid() const;
|
||||||
static std::shared_ptr<Type> Int32();
|
bool IsInt32() const;
|
||||||
static std::shared_ptr<Type> PtrInt32();
|
bool IsPtrInt32() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Kind kind_;
|
Kind kind_;
|
||||||
@@ -69,7 +70,7 @@ class Value {
|
|||||||
|
|
||||||
class ConstantInt : public Value {
|
class ConstantInt : public Value {
|
||||||
public:
|
public:
|
||||||
explicit ConstantInt(int v);
|
ConstantInt(std::shared_ptr<Type> ty, int v);
|
||||||
int value() const { return value_; }
|
int value() const { return value_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -106,7 +107,7 @@ class BinaryInst : public Instruction {
|
|||||||
|
|
||||||
class ReturnInst : public Instruction {
|
class ReturnInst : public Instruction {
|
||||||
public:
|
public:
|
||||||
explicit ReturnInst(Value* val);
|
ReturnInst(std::shared_ptr<Type> void_ty, Value* val);
|
||||||
Value* value() const;
|
Value* value() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -115,12 +116,12 @@ class ReturnInst : public Instruction {
|
|||||||
|
|
||||||
class AllocaInst : public Instruction {
|
class AllocaInst : public Instruction {
|
||||||
public:
|
public:
|
||||||
explicit AllocaInst(std::string name);
|
AllocaInst(std::shared_ptr<Type> ptr_ty, std::string name);
|
||||||
};
|
};
|
||||||
|
|
||||||
class LoadInst : public Instruction {
|
class LoadInst : public Instruction {
|
||||||
public:
|
public:
|
||||||
LoadInst(Value* ptr, std::string name);
|
LoadInst(std::shared_ptr<Type> val_ty, Value* ptr, std::string name);
|
||||||
Value* ptr() const;
|
Value* ptr() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -129,7 +130,7 @@ class LoadInst : public Instruction {
|
|||||||
|
|
||||||
class StoreInst : public Instruction {
|
class StoreInst : public Instruction {
|
||||||
public:
|
public:
|
||||||
StoreInst(Value* val, Value* ptr);
|
StoreInst(std::shared_ptr<Type> void_ty, Value* val, Value* ptr);
|
||||||
Value* value() const;
|
Value* value() const;
|
||||||
Value* ptr() const;
|
Value* ptr() const;
|
||||||
|
|
||||||
@@ -142,8 +143,12 @@ class BasicBlock {
|
|||||||
public:
|
public:
|
||||||
explicit BasicBlock(std::string name);
|
explicit BasicBlock(std::string name);
|
||||||
const std::string& name() const;
|
const std::string& name() const;
|
||||||
|
Function* parent() const;
|
||||||
|
void set_parent(Function* parent);
|
||||||
bool HasTerminator() const;
|
bool HasTerminator() const;
|
||||||
const std::vector<std::unique_ptr<Instruction>>& instructions() const;
|
const std::vector<std::unique_ptr<Instruction>>& instructions() const;
|
||||||
|
const std::vector<BasicBlock*>& predecessors() const;
|
||||||
|
const std::vector<BasicBlock*>& successors() const;
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
T* Append(Args&&... args) {
|
T* Append(Args&&... args) {
|
||||||
if (HasTerminator()) {
|
if (HasTerminator()) {
|
||||||
@@ -159,7 +164,10 @@ class BasicBlock {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::string name_;
|
std::string name_;
|
||||||
|
Function* parent_ = nullptr;
|
||||||
std::vector<std::unique_ptr<Instruction>> instructions_;
|
std::vector<std::unique_ptr<Instruction>> instructions_;
|
||||||
|
std::vector<BasicBlock*> predecessors_;
|
||||||
|
std::vector<BasicBlock*> successors_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Function : public Value {
|
class Function : public Value {
|
||||||
@@ -178,18 +186,22 @@ class Function : public Value {
|
|||||||
|
|
||||||
class Module {
|
class Module {
|
||||||
public:
|
public:
|
||||||
|
Module() = default;
|
||||||
|
Context& context();
|
||||||
|
const Context& context() const;
|
||||||
// 创建函数时显式传入返回类型,便于在 IRGen 中根据语法树信息选择类型。
|
// 创建函数时显式传入返回类型,便于在 IRGen 中根据语法树信息选择类型。
|
||||||
Function* CreateFunction(const std::string& name,
|
Function* CreateFunction(const std::string& name,
|
||||||
std::shared_ptr<Type> ret_type);
|
std::shared_ptr<Type> ret_type);
|
||||||
const std::vector<std::unique_ptr<Function>>& functions() const;
|
const std::vector<std::unique_ptr<Function>>& functions() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Context context_;
|
||||||
std::vector<std::unique_ptr<Function>> functions_;
|
std::vector<std::unique_ptr<Function>> functions_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IRBuilder {
|
class IRBuilder {
|
||||||
public:
|
public:
|
||||||
explicit IRBuilder(BasicBlock* bb);
|
IRBuilder(Context& ctx, BasicBlock* bb);
|
||||||
void SetInsertPoint(BasicBlock* bb);
|
void SetInsertPoint(BasicBlock* bb);
|
||||||
BasicBlock* GetInsertBlock() const;
|
BasicBlock* GetInsertBlock() const;
|
||||||
|
|
||||||
@@ -204,12 +216,13 @@ class IRBuilder {
|
|||||||
ReturnInst* CreateRet(Value* v);
|
ReturnInst* CreateRet(Value* v);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Context& ctx_;
|
||||||
BasicBlock* insertBlock_;
|
BasicBlock* insertBlock_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IRPrinter {
|
class IRPrinter {
|
||||||
public:
|
public:
|
||||||
void Print(const Module& module);
|
void Print(const Module& module, std::ostream& os);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ir
|
} // namespace ir
|
||||||
|
|||||||
@@ -6,19 +6,8 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace ir {
|
namespace ir {
|
||||||
namespace {
|
IRBuilder::IRBuilder(Context& ctx, BasicBlock* bb)
|
||||||
|
: ctx_(ctx), insertBlock_(bb) {}
|
||||||
bool IsArithmeticType(const std::shared_ptr<Type>& ty) {
|
|
||||||
return ty && ty->kind() == Type::Kind::Int32;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsPtrInt32Type(const std::shared_ptr<Type>& ty) {
|
|
||||||
return ty && ty->kind() == Type::Kind::PtrInt32;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
IRBuilder::IRBuilder(BasicBlock* bb) : insertBlock_(bb) {}
|
|
||||||
|
|
||||||
void IRBuilder::SetInsertPoint(BasicBlock* bb) { insertBlock_ = bb; }
|
void IRBuilder::SetInsertPoint(BasicBlock* bb) { insertBlock_ = bb; }
|
||||||
|
|
||||||
@@ -26,7 +15,7 @@ BasicBlock* IRBuilder::GetInsertBlock() const { return insertBlock_; }
|
|||||||
|
|
||||||
ConstantInt* IRBuilder::CreateConstInt(int v) {
|
ConstantInt* IRBuilder::CreateConstInt(int v) {
|
||||||
// 常量不需要挂在基本块里,由 Context 负责去重与生命周期。
|
// 常量不需要挂在基本块里,由 Context 负责去重与生命周期。
|
||||||
return DefaultContext().GetConstInt(v);
|
return ctx_.GetConstInt(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
BinaryInst* IRBuilder::CreateBinary(Opcode op, Value* lhs, Value* rhs,
|
BinaryInst* IRBuilder::CreateBinary(Opcode op, Value* lhs, Value* rhs,
|
||||||
@@ -40,16 +29,6 @@ BinaryInst* IRBuilder::CreateBinary(Opcode op, Value* lhs, Value* rhs,
|
|||||||
if (!rhs) {
|
if (!rhs) {
|
||||||
throw std::runtime_error("IRBuilder::CreateBinary 缺少 rhs");
|
throw std::runtime_error("IRBuilder::CreateBinary 缺少 rhs");
|
||||||
}
|
}
|
||||||
if (op != Opcode::Add) {
|
|
||||||
throw std::runtime_error("IRBuilder::CreateBinary 当前只支持 Add");
|
|
||||||
}
|
|
||||||
if (!lhs->type() || !rhs->type() ||
|
|
||||||
lhs->type()->kind() != rhs->type()->kind()) {
|
|
||||||
throw std::runtime_error("IRBuilder::CreateBinary 操作数类型不匹配");
|
|
||||||
}
|
|
||||||
if (!IsArithmeticType(lhs->type())) {
|
|
||||||
throw std::runtime_error("IRBuilder::CreateBinary 当前只支持 i32 二元运算");
|
|
||||||
}
|
|
||||||
return insertBlock_->Append<BinaryInst>(op, lhs->type(), lhs, rhs, name);
|
return insertBlock_->Append<BinaryInst>(op, lhs->type(), lhs, rhs, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +41,7 @@ AllocaInst* IRBuilder::CreateAllocaI32(const std::string& name) {
|
|||||||
if (!insertBlock_) {
|
if (!insertBlock_) {
|
||||||
throw std::runtime_error("IRBuilder 未设置插入点");
|
throw std::runtime_error("IRBuilder 未设置插入点");
|
||||||
}
|
}
|
||||||
return insertBlock_->Append<AllocaInst>(name);
|
return insertBlock_->Append<AllocaInst>(ctx_.PtrInt32(), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadInst* IRBuilder::CreateLoad(Value* ptr, const std::string& name) {
|
LoadInst* IRBuilder::CreateLoad(Value* ptr, const std::string& name) {
|
||||||
@@ -72,10 +51,7 @@ LoadInst* IRBuilder::CreateLoad(Value* ptr, const std::string& name) {
|
|||||||
if (!ptr) {
|
if (!ptr) {
|
||||||
throw std::runtime_error("IRBuilder::CreateLoad 缺少 ptr");
|
throw std::runtime_error("IRBuilder::CreateLoad 缺少 ptr");
|
||||||
}
|
}
|
||||||
if (!IsPtrInt32Type(ptr->type())) {
|
return insertBlock_->Append<LoadInst>(ctx_.Int32(), ptr, name);
|
||||||
throw std::runtime_error("IRBuilder::CreateLoad 当前只支持从 i32* 加载");
|
|
||||||
}
|
|
||||||
return insertBlock_->Append<LoadInst>(ptr, name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StoreInst* IRBuilder::CreateStore(Value* val, Value* ptr) {
|
StoreInst* IRBuilder::CreateStore(Value* val, Value* ptr) {
|
||||||
@@ -88,13 +64,7 @@ StoreInst* IRBuilder::CreateStore(Value* val, Value* ptr) {
|
|||||||
if (!ptr) {
|
if (!ptr) {
|
||||||
throw std::runtime_error("IRBuilder::CreateStore 缺少 ptr");
|
throw std::runtime_error("IRBuilder::CreateStore 缺少 ptr");
|
||||||
}
|
}
|
||||||
if (!IsArithmeticType(val->type())) {
|
return insertBlock_->Append<StoreInst>(ctx_.Void(), val, ptr);
|
||||||
throw std::runtime_error("IRBuilder::CreateStore 当前只支持存储 i32");
|
|
||||||
}
|
|
||||||
if (!IsPtrInt32Type(ptr->type())) {
|
|
||||||
throw std::runtime_error("IRBuilder::CreateStore 当前只支持写入 i32*");
|
|
||||||
}
|
|
||||||
return insertBlock_->Append<StoreInst>(val, ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnInst* IRBuilder::CreateRet(Value* v) {
|
ReturnInst* IRBuilder::CreateRet(Value* v) {
|
||||||
@@ -104,7 +74,7 @@ ReturnInst* IRBuilder::CreateRet(Value* v) {
|
|||||||
if (!v) {
|
if (!v) {
|
||||||
throw std::runtime_error("IRBuilder::CreateRet 缺少返回值");
|
throw std::runtime_error("IRBuilder::CreateRet 缺少返回值");
|
||||||
}
|
}
|
||||||
return insertBlock_->Append<ReturnInst>(v);
|
return insertBlock_->Append<ReturnInst>(ctx_.Void(), v);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ir
|
} // namespace ir
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
#include "ir/IR.h"
|
#include "ir/IR.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <ostream>
|
||||||
#include <string>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace ir {
|
namespace ir {
|
||||||
|
|
||||||
@@ -49,15 +49,15 @@ static std::string ValueToString(const Value* v) {
|
|||||||
return v ? v->name() : "<null>";
|
return v ? v->name() : "<null>";
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRPrinter::Print(const Module& module) {
|
void IRPrinter::Print(const Module& module, std::ostream& os) {
|
||||||
for (const auto& func : module.functions()) {
|
for (const auto& func : module.functions()) {
|
||||||
std::cout << "define " << TypeToString(*func->type()) << " @"
|
os << "define " << TypeToString(*func->type()) << " @" << func->name()
|
||||||
<< func->name() << "() {\n";
|
<< "() {\n";
|
||||||
for (const auto& bb : func->blocks()) {
|
for (const auto& bb : func->blocks()) {
|
||||||
if (!bb) {
|
if (!bb) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::cout << bb->name() << ":\n";
|
os << bb->name() << ":\n";
|
||||||
for (const auto& instPtr : bb->instructions()) {
|
for (const auto& instPtr : bb->instructions()) {
|
||||||
const auto* inst = instPtr.get();
|
const auto* inst = instPtr.get();
|
||||||
switch (inst->opcode()) {
|
switch (inst->opcode()) {
|
||||||
@@ -65,39 +65,39 @@ void IRPrinter::Print(const Module& module) {
|
|||||||
case Opcode::Sub:
|
case Opcode::Sub:
|
||||||
case Opcode::Mul: {
|
case Opcode::Mul: {
|
||||||
auto* bin = static_cast<const BinaryInst*>(inst);
|
auto* bin = static_cast<const BinaryInst*>(inst);
|
||||||
std::cout << " " << bin->name() << " = " << OpcodeToString(bin->opcode())
|
os << " " << bin->name() << " = " << OpcodeToString(bin->opcode())
|
||||||
<< " " << TypeToString(*bin->lhs()->type()) << " "
|
<< " " << TypeToString(*bin->lhs()->type()) << " "
|
||||||
<< ValueToString(bin->lhs()) << ", "
|
<< ValueToString(bin->lhs()) << ", "
|
||||||
<< ValueToString(bin->rhs()) << "\n";
|
<< ValueToString(bin->rhs()) << "\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Opcode::Alloca: {
|
case Opcode::Alloca: {
|
||||||
auto* alloca = static_cast<const AllocaInst*>(inst);
|
auto* alloca = static_cast<const AllocaInst*>(inst);
|
||||||
std::cout << " " << alloca->name() << " = alloca i32\n";
|
os << " " << alloca->name() << " = alloca i32\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Opcode::Load: {
|
case Opcode::Load: {
|
||||||
auto* load = static_cast<const LoadInst*>(inst);
|
auto* load = static_cast<const LoadInst*>(inst);
|
||||||
std::cout << " " << load->name() << " = load i32, i32* "
|
os << " " << load->name() << " = load i32, i32* "
|
||||||
<< ValueToString(load->ptr()) << "\n";
|
<< ValueToString(load->ptr()) << "\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Opcode::Store: {
|
case Opcode::Store: {
|
||||||
auto* store = static_cast<const StoreInst*>(inst);
|
auto* store = static_cast<const StoreInst*>(inst);
|
||||||
std::cout << " store i32 " << ValueToString(store->value()) << ", i32* "
|
os << " store i32 " << ValueToString(store->value()) << ", i32* "
|
||||||
<< ValueToString(store->ptr()) << "\n";
|
<< ValueToString(store->ptr()) << "\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Opcode::Ret: {
|
case Opcode::Ret: {
|
||||||
auto* ret = static_cast<const ReturnInst*>(inst);
|
auto* ret = static_cast<const ReturnInst*>(inst);
|
||||||
std::cout << " ret " << TypeToString(*ret->value()->type()) << " "
|
os << " ret " << TypeToString(*ret->value()->type()) << " "
|
||||||
<< ValueToString(ret->value()) << "\n";
|
<< ValueToString(ret->value()) << "\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout << "}\n";
|
os << "}\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,18 +6,6 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace ir {
|
namespace ir {
|
||||||
namespace {
|
|
||||||
|
|
||||||
bool IsArithmeticType(const std::shared_ptr<Type>& ty) {
|
|
||||||
return ty && ty->kind() == Type::Kind::Int32;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsPtrInt32Type(const std::shared_ptr<Type>& ty) {
|
|
||||||
return ty && ty->kind() == Type::Kind::PtrInt32;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
Instruction::Instruction(Opcode op, std::shared_ptr<Type> ty, std::string name)
|
Instruction::Instruction(Opcode op, std::shared_ptr<Type> ty, std::string name)
|
||||||
: Value(std::move(ty), std::move(name)), opcode_(op) {}
|
: Value(std::move(ty), std::move(name)), opcode_(op) {}
|
||||||
|
|
||||||
@@ -45,7 +33,7 @@ BinaryInst::BinaryInst(Opcode op, std::shared_ptr<Type> ty, Value* lhs,
|
|||||||
type_->kind() != lhs_->type()->kind()) {
|
type_->kind() != lhs_->type()->kind()) {
|
||||||
throw std::runtime_error("BinaryInst 类型不匹配");
|
throw std::runtime_error("BinaryInst 类型不匹配");
|
||||||
}
|
}
|
||||||
if (!IsArithmeticType(type_)) {
|
if (!type_->IsInt32()) {
|
||||||
throw std::runtime_error("BinaryInst 当前只支持 i32");
|
throw std::runtime_error("BinaryInst 当前只支持 i32");
|
||||||
}
|
}
|
||||||
if (lhs_) {
|
if (lhs_) {
|
||||||
@@ -60,25 +48,37 @@ Value* BinaryInst::lhs() const { return lhs_; }
|
|||||||
|
|
||||||
Value* BinaryInst::rhs() const { return rhs_; }
|
Value* BinaryInst::rhs() const { return rhs_; }
|
||||||
|
|
||||||
ReturnInst::ReturnInst(Value* val)
|
ReturnInst::ReturnInst(std::shared_ptr<Type> void_ty, Value* val)
|
||||||
: Instruction(Opcode::Ret, Type::Void(), ""), value_(val) {
|
: Instruction(Opcode::Ret, std::move(void_ty), ""),
|
||||||
|
value_(val) {
|
||||||
if (!value_) {
|
if (!value_) {
|
||||||
throw std::runtime_error("ReturnInst 缺少返回值");
|
throw std::runtime_error("ReturnInst 缺少返回值");
|
||||||
}
|
}
|
||||||
|
if (!type_ || !type_->IsVoid()) {
|
||||||
|
throw std::runtime_error("ReturnInst 返回类型必须为 void");
|
||||||
|
}
|
||||||
value_->AddUser(this);
|
value_->AddUser(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* ReturnInst::value() const { return value_; }
|
Value* ReturnInst::value() const { return value_; }
|
||||||
|
|
||||||
AllocaInst::AllocaInst(std::string name)
|
AllocaInst::AllocaInst(std::shared_ptr<Type> ptr_ty, std::string name)
|
||||||
: Instruction(Opcode::Alloca, Type::PtrInt32(), std::move(name)) {}
|
: Instruction(Opcode::Alloca, std::move(ptr_ty), std::move(name)) {
|
||||||
|
if (!type_ || !type_->IsPtrInt32()) {
|
||||||
|
throw std::runtime_error("AllocaInst 当前只支持 i32*");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LoadInst::LoadInst(Value* ptr, std::string name)
|
LoadInst::LoadInst(std::shared_ptr<Type> val_ty, Value* ptr, std::string name)
|
||||||
: Instruction(Opcode::Load, Type::Int32(), std::move(name)), ptr_(ptr) {
|
: Instruction(Opcode::Load, std::move(val_ty), std::move(name)),
|
||||||
|
ptr_(ptr) {
|
||||||
if (!ptr_) {
|
if (!ptr_) {
|
||||||
throw std::runtime_error("LoadInst 缺少 ptr");
|
throw std::runtime_error("LoadInst 缺少 ptr");
|
||||||
}
|
}
|
||||||
if (!IsPtrInt32Type(ptr_->type())) {
|
if (!type_ || !type_->IsInt32()) {
|
||||||
|
throw std::runtime_error("LoadInst 当前只支持加载 i32");
|
||||||
|
}
|
||||||
|
if (!ptr_->type() || !ptr_->type()->IsPtrInt32()) {
|
||||||
throw std::runtime_error("LoadInst 当前只支持从 i32* 加载");
|
throw std::runtime_error("LoadInst 当前只支持从 i32* 加载");
|
||||||
}
|
}
|
||||||
ptr_->AddUser(this);
|
ptr_->AddUser(this);
|
||||||
@@ -86,18 +86,23 @@ LoadInst::LoadInst(Value* ptr, std::string name)
|
|||||||
|
|
||||||
Value* LoadInst::ptr() const { return ptr_; }
|
Value* LoadInst::ptr() const { return ptr_; }
|
||||||
|
|
||||||
StoreInst::StoreInst(Value* val, Value* ptr)
|
StoreInst::StoreInst(std::shared_ptr<Type> void_ty, Value* val, Value* ptr)
|
||||||
: Instruction(Opcode::Store, Type::Void(), ""), value_(val), ptr_(ptr) {
|
: Instruction(Opcode::Store, std::move(void_ty), ""),
|
||||||
|
value_(val),
|
||||||
|
ptr_(ptr) {
|
||||||
if (!value_) {
|
if (!value_) {
|
||||||
throw std::runtime_error("StoreInst 缺少 value");
|
throw std::runtime_error("StoreInst 缺少 value");
|
||||||
}
|
}
|
||||||
if (!ptr_) {
|
if (!ptr_) {
|
||||||
throw std::runtime_error("StoreInst 缺少 ptr");
|
throw std::runtime_error("StoreInst 缺少 ptr");
|
||||||
}
|
}
|
||||||
if (!IsArithmeticType(value_->type())) {
|
if (!type_ || !type_->IsVoid()) {
|
||||||
|
throw std::runtime_error("StoreInst 返回类型必须为 void");
|
||||||
|
}
|
||||||
|
if (!value_->type() || !value_->type()->IsInt32()) {
|
||||||
throw std::runtime_error("StoreInst 当前只支持存储 i32");
|
throw std::runtime_error("StoreInst 当前只支持存储 i32");
|
||||||
}
|
}
|
||||||
if (!IsPtrInt32Type(ptr_->type())) {
|
if (!ptr_->type() || !ptr_->type()->IsPtrInt32()) {
|
||||||
throw std::runtime_error("StoreInst 当前只支持写入 i32*");
|
throw std::runtime_error("StoreInst 当前只支持写入 i32*");
|
||||||
}
|
}
|
||||||
value_->AddUser(this);
|
value_->AddUser(this);
|
||||||
|
|||||||
@@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
namespace ir {
|
namespace ir {
|
||||||
|
|
||||||
|
Context& Module::context() { return context_; }
|
||||||
|
|
||||||
|
const Context& Module::context() const { return context_; }
|
||||||
|
|
||||||
Function* Module::CreateFunction(const std::string& name,
|
Function* Module::CreateFunction(const std::string& name,
|
||||||
std::shared_ptr<Type> ret_type) {
|
std::shared_ptr<Type> ret_type) {
|
||||||
functions_.push_back(std::make_unique<Function>(name, std::move(ret_type)));
|
functions_.push_back(std::make_unique<Function>(name, std::move(ret_type)));
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ Type::Type(Kind k) : kind_(k) {}
|
|||||||
|
|
||||||
Type::Kind Type::kind() const { return kind_; }
|
Type::Kind Type::kind() const { return kind_; }
|
||||||
|
|
||||||
std::shared_ptr<Type> Type::Void() { return DefaultContext().Void(); }
|
bool Type::IsVoid() const { return kind_ == Kind::Void; }
|
||||||
|
|
||||||
std::shared_ptr<Type> Type::Int32() { return DefaultContext().Int32(); }
|
bool Type::IsInt32() const { return kind_ == Kind::Int32; }
|
||||||
|
|
||||||
std::shared_ptr<Type> Type::PtrInt32() { return DefaultContext().PtrInt32(); }
|
bool Type::IsPtrInt32() const { return kind_ == Kind::PtrInt32; }
|
||||||
|
|
||||||
} // namespace ir
|
} // namespace ir
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ void Value::AddUser(Instruction* user) { users_.push_back(user); }
|
|||||||
|
|
||||||
const std::vector<Instruction*>& Value::users() const { return users_; }
|
const std::vector<Instruction*>& Value::users() const { return users_; }
|
||||||
|
|
||||||
ConstantInt::ConstantInt(int v) : Value(Type::Int32(), ""), value_(v) {}
|
ConstantInt::ConstantInt(std::shared_ptr<Type> ty, int v)
|
||||||
|
: Value(std::move(ty), ""), value_(v) {}
|
||||||
|
|
||||||
} // namespace ir
|
} // namespace ir
|
||||||
|
|||||||
@@ -39,14 +39,14 @@ void IRGenImpl::GenVarDecl(SysYParser::VarDeclContext& decl) {
|
|||||||
if (storage_map_.find(&decl) != storage_map_.end()) {
|
if (storage_map_.find(&decl) != storage_map_.end()) {
|
||||||
throw std::runtime_error("[irgen] 声明重复生成存储槽位");
|
throw std::runtime_error("[irgen] 声明重复生成存储槽位");
|
||||||
}
|
}
|
||||||
auto* slot = builder_.CreateAllocaI32(ir::DefaultContext().NextTemp());
|
auto* slot = builder_.CreateAllocaI32(module_.context().NextTemp());
|
||||||
storage_map_[&decl] = slot;
|
storage_map_[&decl] = slot;
|
||||||
|
|
||||||
ir::Value* init = nullptr;
|
ir::Value* init = nullptr;
|
||||||
if (decl.exp()) {
|
if (decl.exp()) {
|
||||||
init = GenExpr(*decl.exp());
|
init = GenExpr(*decl.exp());
|
||||||
} else {
|
} else {
|
||||||
init = ir::DefaultContext().GetConstInt(0);
|
init = builder_.CreateConstInt(0);
|
||||||
}
|
}
|
||||||
builder_.CreateStore(init, slot);
|
builder_.CreateStore(init, slot);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,10 @@ void VerifyFunctionStructure(const ir::Function& func) {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
IRGenImpl::IRGenImpl(ir::Module& module, const SemanticContext& sema)
|
IRGenImpl::IRGenImpl(ir::Module& module, const SemanticContext& sema)
|
||||||
: module_(module), sema_(sema), func_(nullptr), builder_(nullptr) {}
|
: module_(module),
|
||||||
|
sema_(sema),
|
||||||
|
func_(nullptr),
|
||||||
|
builder_(module.context(), nullptr) {}
|
||||||
|
|
||||||
void IRGenImpl::Gen(SysYParser::CompUnitContext& cu) {
|
void IRGenImpl::Gen(SysYParser::CompUnitContext& cu) {
|
||||||
if (!cu.funcDef()) {
|
if (!cu.funcDef()) {
|
||||||
@@ -37,7 +40,9 @@ void IRGenImpl::GenFuncDef(SysYParser::FuncDefContext& func) {
|
|||||||
throw std::runtime_error("[irgen] 缺少函数名");
|
throw std::runtime_error("[irgen] 缺少函数名");
|
||||||
}
|
}
|
||||||
|
|
||||||
func_ = module_.CreateFunction(func.Ident()->getText(), ir::Type::Int32());
|
func_ = module_.CreateFunction(
|
||||||
|
func.Ident()->getText(),
|
||||||
|
std::make_shared<ir::Type>(ir::Type::Kind::Int32));
|
||||||
builder_.SetInsertPoint(func_->entry());
|
builder_.SetInsertPoint(func_->entry());
|
||||||
storage_map_.clear();
|
storage_map_.clear();
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ int main(int argc, char** argv) {
|
|||||||
if (need_blank_line) {
|
if (need_blank_line) {
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
printer.Print(*module);
|
printer.Print(*module, std::cout);
|
||||||
need_blank_line = true;
|
need_blank_line = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user