feat: 支持全局变量声明与初始化+修改了.gitignore

hp 4 days ago
parent fd4f3b5fa8
commit 6f63c4c7ba

1
.gitignore vendored

@ -52,6 +52,7 @@ compile_commands.json
.idea/
.fleet/
.vs/
.trae/
*.code-workspace
# CLion

@ -83,17 +83,19 @@ class Context {
~Context();
// 去重创建 i32 常量。
ConstantInt* GetConstInt(int v);
ConstantFloat* GetConstFloat(float v);
std::string NextTemp();
private:
std::unordered_map<int, std::unique_ptr<ConstantInt>> const_ints_;
std::unordered_map<float, std::unique_ptr<ConstantFloat>> const_floats_;
int temp_index_ = -1;
};
class Type {
public:
enum class Kind { Void, Int1, Int32, PtrInt32 };
enum class Kind { Void, Int1, Int32, PtrInt32, Float, PtrFloat };
explicit Type(Kind k);
// 使用静态共享对象获取类型。
// 同一类型可直接比较返回值是否相等,例如:
@ -102,11 +104,15 @@ class Type {
static const std::shared_ptr<Type>& GetInt1Type();
static const std::shared_ptr<Type>& GetInt32Type();
static const std::shared_ptr<Type>& GetPtrInt32Type();
static const std::shared_ptr<Type>& GetFloatType();
static const std::shared_ptr<Type>& GetPtrFloatType();
Kind GetKind() const;
bool IsVoid() const;
bool IsInt1() const;
bool IsInt32() const;
bool IsPtrInt32() const;
bool IsFloat() const;
bool IsPtrFloat() const;
private:
Kind kind_;
@ -154,6 +160,15 @@ class ConstantInt : public ConstantValue {
int value_{};
};
class ConstantFloat : public ConstantValue {
public:
ConstantFloat(std::shared_ptr<Type> ty, float v);
float GetValue() const { return value_; }
private:
float value_{};
};
// 后续还需要扩展更多指令类型。
// enum class Opcode { Add, Sub, Mul, Alloca, Load, Store, Ret };
enum class Opcode { Add, Sub, Mul, Div, Mod, Neg, Alloca, Load, Store, Ret, Cmp, Zext, Br, CondBr };
@ -177,13 +192,19 @@ class User : public Value {
std::vector<Value*> operands_;
};
// GlobalValue 是全局值/全局变量体系的空壳占位类。
// 当前只补齐类层次,具体初始化器、打印和链接语义后续再补。
class GlobalValue : public User {
public:
GlobalValue(std::shared_ptr<Type> ty, std::string name);
};
class GlobalVariable : public GlobalValue {
public:
GlobalVariable(std::string name, std::shared_ptr<Type> type, ConstantValue* init);
ConstantValue* GetInitializer() const { return init_; }
private:
ConstantValue* init_ = nullptr;
};
class Instruction : public User {
public:
Instruction(Opcode op, std::shared_ptr<Type> ty, std::string name = "");
@ -327,10 +348,14 @@ class Module {
Function* CreateFunction(const std::string& name,
std::shared_ptr<Type> ret_type);
const std::vector<std::unique_ptr<Function>>& GetFunctions() const;
GlobalVariable* CreateGlobalVariable(const std::string& name, std::shared_ptr<Type> type, ConstantValue* init);
const std::vector<std::unique_ptr<GlobalVariable>>& GetGlobalVariables() const;
private:
Context context_;
std::vector<std::unique_ptr<Function>> functions_;
std::vector<std::unique_ptr<GlobalVariable>> global_variables_;
};
class IRBuilder {
@ -348,6 +373,7 @@ class IRBuilder {
BinaryInst* CreateMul(Value* lhs, Value* rhs, const std::string& name);
UnaryInst* CreateNeg(Value* operand, const std::string& name);
AllocaInst* CreateAllocaI32(const std::string& name);
AllocaInst* CreateAllocaFloat(const std::string& name);
LoadInst* CreateLoad(Value* ptr, const std::string& name);
StoreInst* CreateStore(Value* val, Value* ptr);
ReturnInst* CreateRet(Value* v);

@ -15,6 +15,14 @@ ConstantInt* Context::GetConstInt(int v) {
return inserted->second.get();
}
ConstantFloat* Context::GetConstFloat(float v) {
auto it = const_floats_.find(v);
if (it != const_floats_.end()) return it->second.get();
auto inserted =
const_floats_.emplace(v, std::make_unique<ConstantFloat>(Type::GetFloatType(), v)).first;
return inserted->second.get();
}
std::string Context::NextTemp() {
std::ostringstream oss;
oss << "%t" << ++temp_index_;

@ -49,6 +49,13 @@ AllocaInst* IRBuilder::CreateAllocaI32(const std::string& name) {
return insert_block_->Append<AllocaInst>(Type::GetPtrInt32Type(), name);
}
AllocaInst* IRBuilder::CreateAllocaFloat(const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
return insert_block_->Append<AllocaInst>(Type::GetPtrFloatType(), name);
}
LoadInst* IRBuilder::CreateLoad(Value* ptr, const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));

@ -18,4 +18,13 @@ const std::vector<std::unique_ptr<Function>>& Module::GetFunctions() const {
return functions_;
}
GlobalVariable* Module::CreateGlobalVariable(const std::string& name, std::shared_ptr<Type> type, ConstantValue* init) {
global_variables_.push_back(std::make_unique<GlobalVariable>(name, std::move(type), init));
return global_variables_.back().get();
}
const std::vector<std::unique_ptr<GlobalVariable>>& Module::GetGlobalVariables() const {
return global_variables_;
}
} // namespace ir

@ -24,6 +24,10 @@ bool Value::IsInt32() const { return type_ && type_->IsInt32(); }
bool Value::IsPtrInt32() const { return type_ && type_->IsPtrInt32(); }
bool Value::IsFloat() const { return type_ && type_->IsFloat(); }
bool Value::IsPtrFloat() const { return type_ && type_->IsPtrFloat(); }
bool Value::IsConstant() const {
return dynamic_cast<const ConstantValue*>(this) != nullptr;
}
@ -76,10 +80,97 @@ void Value::ReplaceAllUsesWith(Value* new_value) {
}
}
User::User(std::shared_ptr<Type> ty, std::string name)
: Value(std::move(ty), std::move(name)) {}
size_t User::GetNumOperands() const { return operands_.size(); }
Value* User::GetOperand(size_t index) const {
if (index >= operands_.size()) {
throw std::out_of_range("Operand index out of range");
}
return operands_[index];
}
void User::SetOperand(size_t index, Value* value) {
if (index >= operands_.size()) {
throw std::out_of_range("Operand index out of range");
}
if (operands_[index]) {
operands_[index]->RemoveUse(this, index);
}
operands_[index] = value;
if (value) {
value->AddUse(this, index);
}
}
void User::AddOperand(Value* value) {
operands_.push_back(value);
if (value) {
value->AddUse(this, operands_.size() - 1);
}
}
ConstantValue::ConstantValue(std::shared_ptr<Type> ty, std::string name)
: Value(std::move(ty), std::move(name)) {}
ConstantInt::ConstantInt(std::shared_ptr<Type> ty, int v)
: ConstantValue(std::move(ty), ""), value_(v) {}
ConstantFloat::ConstantFloat(std::shared_ptr<Type> ty, float v)
: ConstantValue(std::move(ty), ""), value_(v) {}
GlobalValue::GlobalValue(std::shared_ptr<Type> ty, std::string name)
: User(std::move(ty), std::move(name)) {}
GlobalVariable::GlobalVariable(std::string name, std::shared_ptr<Type> type, ConstantValue* init)
: GlobalValue(std::move(type), std::move(name)), init_(init) {}
Type::Type(Kind k) : kind_(k) {}
const std::shared_ptr<Type>& Type::GetVoidType() {
static std::shared_ptr<Type> ty = std::make_shared<Type>(Kind::Void);
return ty;
}
const std::shared_ptr<Type>& Type::GetInt1Type() {
static std::shared_ptr<Type> ty = std::make_shared<Type>(Kind::Int1);
return ty;
}
const std::shared_ptr<Type>& Type::GetInt32Type() {
static std::shared_ptr<Type> ty = std::make_shared<Type>(Kind::Int32);
return ty;
}
const std::shared_ptr<Type>& Type::GetPtrInt32Type() {
static std::shared_ptr<Type> ty = std::make_shared<Type>(Kind::PtrInt32);
return ty;
}
const std::shared_ptr<Type>& Type::GetFloatType() {
static std::shared_ptr<Type> ty = std::make_shared<Type>(Kind::Float);
return ty;
}
const std::shared_ptr<Type>& Type::GetPtrFloatType() {
static std::shared_ptr<Type> ty = std::make_shared<Type>(Kind::PtrFloat);
return ty;
}
Type::Kind Type::GetKind() const { return kind_; }
bool Type::IsVoid() const { return kind_ == Kind::Void; }
bool Type::IsInt1() const { return kind_ == Kind::Int1; }
bool Type::IsInt32() const { return kind_ == Kind::Int32; }
bool Type::IsPtrInt32() const { return kind_ == Kind::PtrInt32; }
bool Type::IsFloat() const { return kind_ == Kind::Float; }
bool Type::IsPtrFloat() const { return kind_ == Kind::PtrFloat; }
} // namespace ir

@ -42,30 +42,34 @@ std::any IRGenImpl::visitBlockItem(SysYParser::BlockItemContext* ctx) {
}
// 变量声明的 IR 生成目前也是最小实现:
// - 先检查声明的基础类型,当前仅支持局部 int
// - 先检查声明的基础类型,支持 int 和 float
// - 再把 Decl 中的变量定义交给 visitVarDef 继续处理。
//
// 和更完整的版本相比,这里还没有:
// - 一个 Decl 中多个变量定义的顺序处理;
// - const、数组、全局变量等不同声明形态
// - 更丰富的类型系统。
std::any IRGenImpl::visitDecl(SysYParser::DeclContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少变量声明"));
}
// 当前语法中 decl 包含 constDecl 或 varDecl这里只支持 varDecl
auto* var_decl = ctx->varDecl();
if (!var_decl) {
throw std::runtime_error(FormatError("irgen", "当前仅支持变量声明"));
}
if (!var_decl->bType() || !var_decl->bType()->INT()) {
throw std::runtime_error(FormatError("irgen", "当前仅支持局部 int 变量声明"));
}
// 遍历所有 varDef
for (auto* var_def : var_decl->varDef()) {
if (var_def) {
var_def->accept(this);
// 当前语法中 decl 包含 constDecl 或 varDecl
if (auto* var_decl = ctx->varDecl()) {
if (!var_decl->bType() || (!var_decl->bType()->INT() && !var_decl->bType()->FLOAT())) {
throw std::runtime_error(FormatError("irgen", "当前仅支持 int/float 变量声明"));
}
for (auto* var_def : var_decl->varDef()) {
if (var_def) {
var_def->accept(this);
}
}
} else if (auto* const_decl = ctx->constDecl()) {
// 稍后实现 constDecl
if (!const_decl->bType() || (!const_decl->bType()->INT() && !const_decl->bType()->FLOAT())) {
throw std::runtime_error(FormatError("irgen", "当前仅支持 int/float 常量声明"));
}
for (auto* const_def : const_decl->constDef()) {
if (const_def) {
const_def->accept(this);
}
}
} else {
throw std::runtime_error(FormatError("irgen", "当前仅支持变量声明"));
}
return BlockFlow::Continue;
}
@ -90,18 +94,68 @@ std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) {
if (storage_map_.find(var_name) != storage_map_.end()) {
throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位"));
}
auto* slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp());
storage_map_[var_name] = slot;
ir::Value* init = nullptr;
if (auto* init_val = ctx->initVal()) {
if (!init_val->exp()) {
throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化"));
// Determine base type from parent varDecl or constDecl
bool is_float = false;
auto* parent_decl = dynamic_cast<SysYParser::VarDeclContext*>(ctx->parent);
if (parent_decl && parent_decl->bType() && parent_decl->bType()->FLOAT()) {
is_float = true;
}
auto base_ty = is_float ? ir::Type::GetFloatType() : ir::Type::GetInt32Type();
if (func_ == nullptr) {
// 全局作用域
ir::ConstantValue* init_const = nullptr;
if (auto* init_val = ctx->initVal()) {
if (!init_val->exp()) {
throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化"));
}
auto* val = EvalExpr(*init_val->exp());
init_const = dynamic_cast<ir::ConstantValue*>(val);
if (!init_const) {
throw std::runtime_error(FormatError("irgen", "全局变量初始化必须是常量"));
}
} else {
if (is_float) {
init_const = module_.GetContext().GetConstFloat(0.0f);
} else {
init_const = module_.GetContext().GetConstInt(0);
}
}
init = EvalExpr(*init_val->exp());
auto* gv = module_.CreateGlobalVariable(var_name, base_ty, init_const);
storage_map_[var_name] = gv;
} else {
init = builder_.CreateConstInt(0);
// 局部作用域
auto* ptr_ty = is_float ? ir::Type::GetPtrFloatType() : ir::Type::GetPtrInt32Type();
// 简化处理,暂用 builder 创建 alloca
// 需要在 builder 中扩展 CreateAllocaFloat此处简化直接按 I32 Alloca 的名称调用,或添加新接口
// 为了不大幅改动 Builder我们复用 AllocaInst或者添加 CreateAlloca
ir::Value* slot = nullptr;
if (is_float) {
slot = builder_.CreateAllocaFloat(module_.GetContext().NextTemp());
} else {
slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp());
}
storage_map_[var_name] = slot;
ir::Value* init = nullptr;
if (auto* init_val = ctx->initVal()) {
if (!init_val->exp()) {
throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化"));
}
init = EvalExpr(*init_val->exp());
} else {
if (is_float) {
init = module_.GetContext().GetConstFloat(0.0f);
} else {
init = module_.GetContext().GetConstInt(0);
}
}
builder_.CreateStore(init, slot);
}
builder_.CreateStore(init, slot);
return BlockFlow::Continue;
}

@ -38,15 +38,16 @@ std::any IRGenImpl::visitCompUnit(SysYParser::CompUnitContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少编译单元"));
}
// 遍历所有 topLevelItem,找到 funcDef
// 遍历所有 topLevelItem
for (auto* item : ctx->topLevelItem()) {
if (item && item->funcDef()) {
if (!item) continue;
if (item->funcDef()) {
item->funcDef()->accept(this);
// 当前只支持单个函数,找到第一个后就返回
return {};
} else if (item->decl()) {
item->decl()->accept(this);
}
}
throw std::runtime_error(FormatError("irgen", "缺少函数定义"));
return {};
}
// 函数 IR 生成当前实现了:

Loading…
Cancel
Save