style(ir): 纠正代码位置

master
jing 1 week ago
parent 62dde8d7ab
commit fab6983d40

@ -3,3 +3,22 @@
// - 维护或可计算前驱/后继关系,用于 CFG 分析与优化
#include "ir/IR.h"
#include <utility>
namespace ir {
BasicBlock::BasicBlock(std::string name) : name_(std::move(name)) {}
const std::string& BasicBlock::name() const { return name_; }
bool BasicBlock::HasTerminator() const {
return !instructions_.empty() && instructions_.back()->IsTerminator();
}
const std::vector<std::unique_ptr<Instruction>>& BasicBlock::instructions()
const {
return instructions_;
}
} // namespace ir

@ -20,4 +20,12 @@ BasicBlock* Function::CreateBlock(const std::string& name) {
return ptr;
}
BasicBlock* Function::entry() { return entry_; }
const BasicBlock* Function::entry() const { return entry_; }
const std::vector<std::unique_ptr<BasicBlock>>& Function::blocks() const {
return blocks_;
}
} // namespace ir

@ -41,8 +41,8 @@ Context& DefaultContext();
class Type {
public:
enum class Kind { Void, Int32, PtrInt32 };
explicit Type(Kind k) : kind_(k) {}
Kind kind() const { return kind_; }
explicit Type(Kind k);
Kind kind() const;
static std::shared_ptr<Type> Void();
static std::shared_ptr<Type> Int32();
static std::shared_ptr<Type> PtrInt32();
@ -53,14 +53,13 @@ class Type {
class Value {
public:
Value(std::shared_ptr<Type> ty, std::string name)
: type_(std::move(ty)), name_(std::move(name)) {}
Value(std::shared_ptr<Type> ty, std::string name);
virtual ~Value() = default;
const std::shared_ptr<Type>& type() const { return type_; }
const std::string& name() const { return name_; }
void set_name(std::string n) { name_ = std::move(n); }
void AddUser(Instruction* user) { users_.push_back(user); }
const std::vector<Instruction*>& users() const { return users_; }
const std::shared_ptr<Type>& type() const;
const std::string& name() const;
void set_name(std::string n);
void AddUser(Instruction* user);
const std::vector<Instruction*>& users() const;
protected:
std::shared_ptr<Type> type_;
@ -77,16 +76,16 @@ class ConstantInt : public Value {
int value_{};
};
// 后续还需要扩展更多指令类型。
enum class Opcode { Add, Sub, Mul, Alloca, Load, Store, Ret };
class Instruction : public Value {
public:
Instruction(Opcode op, std::shared_ptr<Type> ty, std::string name = "")
: Value(std::move(ty), std::move(name)), opcode_(op) {}
Opcode opcode() const { return opcode_; }
bool IsTerminator() const { return opcode_ == Opcode::Ret; }
BasicBlock* parent() const { return parent_; }
void set_parent(BasicBlock* parent) { parent_ = parent; }
Instruction(Opcode op, std::shared_ptr<Type> ty, std::string name = "");
Opcode opcode() const;
bool IsTerminator() const;
BasicBlock* parent() const;
void set_parent(BasicBlock* parent);
private:
Opcode opcode_;
@ -97,8 +96,8 @@ class BinaryInst : public Instruction {
public:
BinaryInst(Opcode op, std::shared_ptr<Type> ty, Value* lhs, Value* rhs,
std::string name);
Value* lhs() const { return lhs_; }
Value* rhs() const { return rhs_; }
Value* lhs() const;
Value* rhs() const;
private:
Value* lhs_;
@ -108,7 +107,7 @@ class BinaryInst : public Instruction {
class ReturnInst : public Instruction {
public:
explicit ReturnInst(Value* val);
Value* value() const { return value_; }
Value* value() const;
private:
Value* value_;
@ -122,7 +121,7 @@ class AllocaInst : public Instruction {
class LoadInst : public Instruction {
public:
LoadInst(Value* ptr, std::string name);
Value* ptr() const { return ptr_; }
Value* ptr() const;
private:
Value* ptr_;
@ -131,8 +130,8 @@ class LoadInst : public Instruction {
class StoreInst : public Instruction {
public:
StoreInst(Value* val, Value* ptr);
Value* value() const { return value_; }
Value* ptr() const { return ptr_; }
Value* value() const;
Value* ptr() const;
private:
Value* value_;
@ -141,14 +140,10 @@ class StoreInst : public Instruction {
class BasicBlock {
public:
explicit BasicBlock(std::string name) : name_(std::move(name)) {}
const std::string& name() const { return name_; }
bool HasTerminator() const {
return !instructions_.empty() && instructions_.back()->IsTerminator();
}
const std::vector<std::unique_ptr<Instruction>>& instructions() const {
return instructions_;
}
explicit BasicBlock(std::string name);
const std::string& name() const;
bool HasTerminator() const;
const std::vector<std::unique_ptr<Instruction>>& instructions() const;
template <typename T, typename... Args>
T* Append(Args&&... args) {
if (HasTerminator()) {
@ -172,11 +167,9 @@ class Function : public Value {
// 允许显式指定返回类型,便于后续扩展多种函数签名。
Function(std::string name, std::shared_ptr<Type> ret_type);
BasicBlock* CreateBlock(const std::string& name);
BasicBlock* entry() { return entry_; }
const BasicBlock* entry() const { return entry_; }
const std::vector<std::unique_ptr<BasicBlock>>& blocks() const {
return blocks_;
}
BasicBlock* entry();
const BasicBlock* entry() const;
const std::vector<std::unique_ptr<BasicBlock>>& blocks() const;
private:
BasicBlock* entry_ = nullptr;
@ -188,9 +181,7 @@ class Module {
// 创建函数时显式传入返回类型,便于在 IRGen 中根据语法树信息选择类型。
Function* CreateFunction(const std::string& name,
std::shared_ptr<Type> ret_type);
const std::vector<std::unique_ptr<Function>>& functions() const {
return functions_;
}
const std::vector<std::unique_ptr<Function>>& functions() const;
private:
std::vector<std::unique_ptr<Function>> functions_;
@ -198,17 +189,15 @@ class Module {
class IRBuilder {
public:
explicit IRBuilder(BasicBlock* bb) : insertBlock_(bb) {}
void SetInsertPoint(BasicBlock* bb) { insertBlock_ = bb; }
BasicBlock* GetInsertBlock() const { return insertBlock_; }
explicit IRBuilder(BasicBlock* bb);
void SetInsertPoint(BasicBlock* bb);
BasicBlock* GetInsertBlock() const;
// 构造常量、二元运算、返回指令的最小集合。
ConstantInt* CreateConstInt(int v);
BinaryInst* CreateBinary(Opcode op, Value* lhs, Value* rhs,
const std::string& name);
BinaryInst* CreateAdd(Value* lhs, Value* rhs, const std::string& name) {
return CreateBinary(Opcode::Add, lhs, rhs, name);
}
BinaryInst* CreateAdd(Value* lhs, Value* rhs, const std::string& name);
AllocaInst* CreateAllocaI32(const std::string& name);
LoadInst* CreateLoad(Value* ptr, const std::string& name);
StoreInst* CreateStore(Value* val, Value* ptr);

@ -18,6 +18,12 @@ bool IsPtrInt32Type(const std::shared_ptr<Type>& ty) {
} // namespace
IRBuilder::IRBuilder(BasicBlock* bb) : insertBlock_(bb) {}
void IRBuilder::SetInsertPoint(BasicBlock* bb) { insertBlock_ = bb; }
BasicBlock* IRBuilder::GetInsertBlock() const { return insertBlock_; }
ConstantInt* IRBuilder::CreateConstInt(int v) {
// 常量不需要挂在基本块里,由 Context 负责去重与生命周期。
return DefaultContext().GetConstInt(v);
@ -47,6 +53,11 @@ BinaryInst* IRBuilder::CreateBinary(Opcode op, Value* lhs, Value* rhs,
return insertBlock_->Append<BinaryInst>(op, lhs->type(), lhs, rhs, name);
}
BinaryInst* IRBuilder::CreateAdd(Value* lhs, Value* rhs,
const std::string& name) {
return CreateBinary(Opcode::Add, lhs, rhs, name);
}
AllocaInst* IRBuilder::CreateAllocaI32(const std::string& name) {
if (!insertBlock_) {
throw std::runtime_error("IRBuilder 未设置插入点");

@ -18,6 +18,17 @@ bool IsPtrInt32Type(const std::shared_ptr<Type>& ty) {
} // namespace
Instruction::Instruction(Opcode op, std::shared_ptr<Type> ty, std::string name)
: Value(std::move(ty), std::move(name)), opcode_(op) {}
Opcode Instruction::opcode() const { return opcode_; }
bool Instruction::IsTerminator() const { return opcode_ == Opcode::Ret; }
BasicBlock* Instruction::parent() const { return parent_; }
void Instruction::set_parent(BasicBlock* parent) { parent_ = parent; }
BinaryInst::BinaryInst(Opcode op, std::shared_ptr<Type> ty, Value* lhs,
Value* rhs, std::string name)
: Instruction(op, std::move(ty), std::move(name)), lhs_(lhs), rhs_(rhs) {
@ -45,6 +56,10 @@ BinaryInst::BinaryInst(Opcode op, std::shared_ptr<Type> ty, Value* lhs,
}
}
Value* BinaryInst::lhs() const { return lhs_; }
Value* BinaryInst::rhs() const { return rhs_; }
ReturnInst::ReturnInst(Value* val)
: Instruction(Opcode::Ret, Type::Void(), ""), value_(val) {
if (!value_) {
@ -53,6 +68,8 @@ ReturnInst::ReturnInst(Value* val)
value_->AddUser(this);
}
Value* ReturnInst::value() const { return value_; }
AllocaInst::AllocaInst(std::string name)
: Instruction(Opcode::Alloca, Type::PtrInt32(), std::move(name)) {}
@ -67,6 +84,8 @@ LoadInst::LoadInst(Value* ptr, std::string name)
ptr_->AddUser(this);
}
Value* LoadInst::ptr() const { return ptr_; }
StoreInst::StoreInst(Value* val, Value* ptr)
: Instruction(Opcode::Store, Type::Void(), ""), value_(val), ptr_(ptr) {
if (!value_) {
@ -85,4 +104,8 @@ StoreInst::StoreInst(Value* val, Value* ptr)
ptr_->AddUser(this);
}
Value* StoreInst::value() const { return value_; }
Value* StoreInst::ptr() const { return ptr_; }
} // namespace ir

@ -12,4 +12,8 @@ Function* Module::CreateFunction(const std::string& name,
return functions_.back().get();
}
const std::vector<std::unique_ptr<Function>>& Module::functions() const {
return functions_;
}
} // namespace ir

@ -6,6 +6,10 @@
namespace ir {
Type::Type(Kind k) : kind_(k) {}
Type::Kind Type::kind() const { return kind_; }
std::shared_ptr<Type> Type::Void() { return DefaultContext().Void(); }
std::shared_ptr<Type> Type::Int32() { return DefaultContext().Int32(); }

@ -5,6 +5,19 @@
namespace ir {
Value::Value(std::shared_ptr<Type> ty, std::string name)
: type_(std::move(ty)), name_(std::move(name)) {}
const std::shared_ptr<Type>& Value::type() const { return type_; }
const std::string& Value::name() const { return name_; }
void Value::set_name(std::string n) { name_ = std::move(n); }
void Value::AddUser(Instruction* user) { users_.push_back(user); }
const std::vector<Instruction*>& Value::users() const { return users_; }
ConstantInt::ConstantInt(int v) : Value(Type::Int32(), ""), value_(v) {}
} // namespace ir

@ -9,6 +9,7 @@
#include "SysYParser.h"
#include "ir/IR.h"
#include "sem/Sema.h"
namespace antlr4 {
namespace tree {
@ -25,7 +26,7 @@ class Value;
class IRGenImpl {
public:
explicit IRGenImpl(ir::Module& module);
IRGenImpl(ir::Module& module, const SemanticContext& sema);
void Gen(SysYParser::CompUnitContext& cu);
@ -43,10 +44,12 @@ class IRGenImpl {
ir::Value* GenPrimary(SysYParser::PrimaryContext& primary);
ir::Module& module_;
const SemanticContext& sema_;
ir::Function* func_;
ir::IRBuilder builder_;
// 当前只维护函数级局部变量表;若后续引入嵌套块作用域,需要改成作用域栈
std::unordered_map<std::string, ir::Value*> locals_;
// 名称绑定由 Sema 负责IRGen 只维护“声明 -> 存储槽位”的代码生成状态
std::unordered_map<SysYParser::VarDeclContext*, ir::Value*> storage_map_;
};
std::unique_ptr<ir::Module> GenerateIR(antlr4::tree::ParseTree* tree);
std::unique_ptr<ir::Module> GenerateIR(SysYParser::CompUnitContext& tree,
const SemanticContext& sema);

@ -36,12 +36,11 @@ void IRGenImpl::GenDecl(SysYParser::DeclContext& decl) {
}
void IRGenImpl::GenVarDecl(SysYParser::VarDeclContext& decl) {
const std::string name = decl.Ident()->getText();
if (locals_.find(name) != locals_.end()) {
throw std::runtime_error("[irgen] 重复定义变量: " + name);
if (storage_map_.find(&decl) != storage_map_.end()) {
throw std::runtime_error("[irgen] 声明重复生成存储槽位");
}
auto* slot = builder_.CreateAllocaI32(ir::DefaultContext().NextTemp());
locals_[name] = slot;
storage_map_[&decl] = slot;
ir::Value* init = nullptr;
if (decl.exp()) {

@ -4,21 +4,12 @@
#include <stdexcept>
#include "SysYParser.h"
#include "antlr4-runtime.h"
#include "ir/IR.h"
std::unique_ptr<ir::Module> GenerateIR(antlr4::tree::ParseTree* tree) {
if (!tree) {
throw std::runtime_error("[irgen] 语法树为空");
}
auto* cu = dynamic_cast<SysYParser::CompUnitContext*>(tree);
if (!cu) {
throw std::runtime_error("[irgen] 语法树根节点不是 compUnit");
}
std::unique_ptr<ir::Module> GenerateIR(SysYParser::CompUnitContext& tree,
const SemanticContext& sema) {
auto module = std::make_unique<ir::Module>();
IRGenImpl gen(*module);
gen.Gen(*cu);
IRGenImpl gen(*module, sema);
gen.Gen(tree);
return module;
}

@ -33,10 +33,15 @@ ir::Value* IRGenImpl::GenPrimary(SysYParser::PrimaryContext& primary) {
return ir::DefaultContext().GetConstInt(std::stoi(primary.Number()->getText()));
}
if (primary.Ident()) {
const std::string name = primary.Ident()->getText();
auto it = locals_.find(name);
if (it == locals_.end()) {
throw std::runtime_error("[irgen] 变量未找到: " + name);
auto* decl = sema_.ResolveVarUse(&primary);
if (!decl) {
throw std::runtime_error("[irgen] 变量使用缺少语义绑定: " +
primary.Ident()->getText());
}
auto it = storage_map_.find(decl);
if (it == storage_map_.end()) {
throw std::runtime_error("[irgen] 变量声明缺少存储槽位: " +
primary.Ident()->getText());
}
return builder_.CreateLoad(it->second, ir::DefaultContext().NextTemp());
}

@ -19,8 +19,8 @@ void VerifyFunctionStructure(const ir::Function& func) {
} // namespace
IRGenImpl::IRGenImpl(ir::Module& module)
: module_(module), func_(nullptr), builder_(nullptr) {}
IRGenImpl::IRGenImpl(ir::Module& module, const SemanticContext& sema)
: module_(module), sema_(sema), func_(nullptr), builder_(nullptr) {}
void IRGenImpl::Gen(SysYParser::CompUnitContext& cu) {
if (!cu.funcDef()) {
@ -39,7 +39,7 @@ void IRGenImpl::GenFuncDef(SysYParser::FuncDefContext& func) {
func_ = module_.CreateFunction(func.Ident()->getText(), ir::Type::Int32());
builder_.SetInsertPoint(func_->entry());
locals_.clear();
storage_map_.clear();
GenBlock(*func.block());
// 语义正确性主要由 sema 保证,这里只兜底检查 IR 结构是否合法。

@ -30,9 +30,9 @@ int main(int argc, char** argv) {
if (!comp_unit) {
throw std::runtime_error("[main] 语法树根节点不是 compUnit");
}
RunSema(*comp_unit);
auto sema = RunSema(*comp_unit);
auto module = GenerateIR(antlr.tree);
auto module = GenerateIR(*comp_unit, sema);
if (opts.emit_ir) {
ir::IRPrinter printer;
if (need_blank_line) {

@ -7,43 +7,47 @@
namespace {
void CheckExpr(SysYParser::ExpContext& exp, const SymbolTable& table);
void CheckExpr(SysYParser::ExpContext& exp, const SymbolTable& table,
SemanticContext& sema);
void CheckPrimary(SysYParser::PrimaryContext& primary,
const SymbolTable& table) {
const SymbolTable& table, SemanticContext& sema) {
if (primary.Number()) {
return;
}
if (primary.Ident()) {
const std::string name = primary.Ident()->getText();
if (!table.Contains(name)) {
auto* decl = table.Lookup(name);
if (!decl) {
throw std::runtime_error("[sema] 使用了未定义的变量: " + name);
}
sema.BindVarUse(&primary, decl);
return;
}
if (primary.exp()) {
CheckExpr(*primary.exp(), table);
CheckExpr(*primary.exp(), table, sema);
return;
}
throw std::runtime_error("[sema] 暂不支持的 primary 形式");
}
void CheckExpr(SysYParser::ExpContext& exp, const SymbolTable& table) {
void CheckExpr(SysYParser::ExpContext& exp, const SymbolTable& table,
SemanticContext& sema) {
if (!exp.addExp()) {
throw std::runtime_error("[sema] 非法表达式");
}
const auto& terms = exp.addExp()->primary();
for (auto* term : terms) {
CheckPrimary(*term, table);
CheckPrimary(*term, table, sema);
}
}
} // namespace
void RunSema(SysYParser::CompUnitContext& comp_unit) {
SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit) {
auto* func = comp_unit.funcDef();
if (!func || !func->block()) {
throw std::runtime_error("[sema] 缺少 main 函数定义");
@ -53,6 +57,7 @@ void RunSema(SysYParser::CompUnitContext& comp_unit) {
}
SymbolTable table;
SemanticContext sema;
bool seen_return = false;
const auto& items = func->block()->blockItem();
@ -74,14 +79,14 @@ void RunSema(SysYParser::CompUnitContext& comp_unit) {
throw std::runtime_error("[sema] 重复定义变量: " + name);
}
if (decl->exp()) {
CheckExpr(*decl->exp(), table);
CheckExpr(*decl->exp(), table, sema);
}
table.Add(name);
table.Add(name, decl);
continue;
}
if (auto* stmt = item->stmt(); stmt && stmt->returnStmt()) {
auto* ret = stmt->returnStmt();
CheckExpr(*ret->exp(), table);
CheckExpr(*ret->exp(), table, sema);
seen_return = true;
if (i + 1 != items.size()) {
throw std::runtime_error("[sema] return 必须是 main 函数中的最后一条语句");
@ -94,4 +99,6 @@ void RunSema(SysYParser::CompUnitContext& comp_unit) {
if (!seen_return) {
throw std::runtime_error("[sema] main 函数必须包含 return 语句");
}
return sema;
}

@ -1,9 +1,30 @@
// 基于语法树的极简语义检查
// 基于语法树的极简语义检查与名称绑定
#pragma once
#include <unordered_map>
#include "SysYParser.h"
class SemanticContext {
public:
void BindVarUse(SysYParser::PrimaryContext* use,
SysYParser::VarDeclContext* decl) {
var_uses_[use] = decl;
}
SysYParser::VarDeclContext* ResolveVarUse(
const SysYParser::PrimaryContext* use) const {
auto it = var_uses_.find(use);
return it == var_uses_.end() ? nullptr : it->second;
}
private:
std::unordered_map<const SysYParser::PrimaryContext*,
SysYParser::VarDeclContext*>
var_uses_;
};
// 目前仅检查:
// - 变量先声明后使用
// - 局部变量不允许重复定义
void RunSema(SysYParser::CompUnitContext& comp_unit);
SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit);

@ -1,16 +1,24 @@
// 极简符号表:记录局部变量是否定义。
// 极简符号表:记录局部变量定义
#pragma once
#include <string>
#include <unordered_map>
#include "SysYParser.h"
class SymbolTable {
public:
void Add(const std::string& name) { table_[name] = true; }
void Add(const std::string& name, SysYParser::VarDeclContext* decl) {
table_[name] = decl;
}
bool Contains(const std::string& name) const {
return table_.find(name) != table_.end();
}
SysYParser::VarDeclContext* Lookup(const std::string& name) const {
auto it = table_.find(name);
return it == table_.end() ? nullptr : it->second;
}
private:
std::unordered_map<std::string, bool> table_;
std::unordered_map<std::string, SysYParser::VarDeclContext*> table_;
};

Loading…
Cancel
Save