Compare commits

...

75 Commits

Author SHA1 Message Date
mxr 35885f3eba (mir)修正编译程序死循环问题
2 weeks ago
mxr fdeb3fc66e (mir)修复寄存器重用冲突错误和浮点比较逻辑
3 weeks ago
mxr d0ecc5c2e9 (mir)修复传递参数是指针时存在的问题
3 weeks ago
mxr 1cf6ed53f1 (test)输出文件格式不匹配
3 weeks ago
compile b9151b866e 修复GEP中32位整型索引变量误用问题
3 weeks ago
mxr 34d483ed47 feat(mir)本地编译SysY静态库
3 weeks ago
mxr bbfb8f2c69 feat(mir)链接完整的 SysY 运行时库
3 weeks ago
ftt 966b5b9c7f 修改多维数组索引
3 weeks ago
mxr d5a8affe83 feat(mir)修正栈帧分配错误
3 weeks ago
ftt 0fd3f4b841 解决对应值栈槽问题
3 weeks ago
mxr 7438c366fd feat(mir)修正全局变量地址计算和数据段生成
3 weeks ago
mxr 5e492f531b feat(mir)处理指令立即数超出范围
4 weeks ago
mxr c9f73980ea feat(mir)修改数组分配逻辑
4 weeks ago
mxr 596b0ee334 feat(mir)添加Movk指令加载大立即数
4 weeks ago
mxr 4132f0b5ca feat(mir)实现多条指令访问栈帧
4 weeks ago
mxr 4f00d05c86 fix(mir)修复Ret返回void问题
4 weeks ago
ftt 8b4ffdde44 修改condbr
4 weeks ago
ftt 7d8ee45a42 值对应栈槽问题
4 weeks ago
ftt 288d0ec3b0 Merge remote-tracking branch 'refs/remotes/origin/feature/mir' into feature/mir
4 weeks ago
ftt bf21e9c437 处理浮点常量
4 weeks ago
mxr 9c9f5a2013 feat(mir)调试控制流生成
4 weeks ago
mxr 4f4842ae3a feat(mir)修复函数序言插入问题
4 weeks ago
mxr f0706adcc0 feat(mir)修改基本块名
4 weeks ago
mxr 34ec79c399 feat(mir)修复栈帧指令遍历处理
4 weeks ago
ftt c24a078bf5 补充寄存器
4 weeks ago
ftt 653c091993 完成二三四阶段,解决支持多函数问题等
4 weeks ago
mxr 6e804e2091 test(test)更新测试脚本并统一输出目录
4 weeks ago
mxr f966869fb1 feat(mir)扩展汇编指令生成
4 weeks ago
ftt 1a48e369e7 第一阶段:扩展 MIR 指令集
4 weeks ago
mxr 1c7cc33e4b chore(test)修改调试输出
1 month ago
pw6fhtz7q 6f649c0ad5 Merge pull request '语义分析与ir生成' (#5) from feature/ir-final into feature/lab2
1 month ago
LuoHello ec56841167 <feature/ir:语义分析模块修改,实现符号表与IR生成板块信息互通。常量,浮点,数组支持。大数组堆分配,alloca栈分配提到入口块以提升性能避免栈溢出,all passed。测试脚本见/script/test_compiler.sh,由/script/verify_ir.sh衍生而来.可改进:可删除很多为了便于调试而插入的print语句>
1 month ago
potapo c8f40ea09a 浮点实现,常量存在问题以及存储
1 month ago
potapo d9201de428 函数调用
1 month ago
LuoHello 700bbb4e3b <feature/ir>全局变量及局部变量区分,支持整型常量
1 month ago
LuoHello 728de089ff 控制流if,break,while,continue实现,条件跳转,无条件跳转实现,函数参数,函数类型系
1 month ago
LuoHello bc4400c1c7 控制流if,break,while,continue实现,条件跳转,无条件跳转实现,函数参数,函数类型系统完善
1 month ago
mxr c945a61f90 fix(sem)解决数组变量绑定缺失问题
1 month ago
potapo 0826c86772 嵌套初始化实现,库函数未增加
1 month ago
potapo ce25b612bf 数组基本实现成功,嵌套聚合初始化暂未实现
1 month ago
potapo fa76f0fbfc 数组基本实现成功,嵌套聚合初始化暂未实现
1 month ago
mxr 6e129b3a56 fix(sem)fix merge problem
1 month ago
potapo 5e7e8a6ff2 数组未实现
1 month ago
potapo 9c7095bba7 实现赋值
1 month ago
potapo 97c01debbd 基本测试通过但有函数没有实现
1 month ago
potapo f53f7ec82c 函数返回错误类型
1 month ago
LuoHello affccfb27c 完善 FunctionType 支持:扩展 CreateFunction 以支持 FunctionType,更新 IR 生成和打印
1 month ago
mxr b93d769576 feat(sem)增添常量绑定
1 month ago
mxr 9efcdde353 feat(sem)修改变量绑定
1 month ago
mxr 74f325c6fd feat(sem)常量浮点类型隐式转换为整型
1 month ago
mxr 8477ab4aca fix(sem)修正常量表达式求值问题
1 month ago
ftt 8e42c77caf 继续修改数组下标问题
1 month ago
mxr bff9a5d296 fix(sem)修正标量常量当作数组处理的问题
1 month ago
mxr 6cc1908515 chore(sem)合并ir分支到sem
1 month ago
ftt e0c8898dae 继续修改数组下标问题
1 month ago
LuoHello 310c93feac IRGen,IR fit our antrl4,full make passed
1 month ago
mxr 066db23e40 chore(sem)删除错误上传的文件
1 month ago
mxr 40403e955d feat(sem)补充常量求值
1 month ago
ftt 7eed5fe6f6 [sema] 数组下标个数不匹配
1 month ago
mxr 4098545062 feat(sem)补充符号表对库函数stoptime的支持
1 month ago
mxr f6773274dd feat(sem)补充符号表对库函数starttime的支持
1 month ago
mxr e1a4f30488 test(test)修改测试脚本run.sh用于批量测试语义分析结果
1 month ago
ftt f3fe34801e feat(sem)提交语义分析B部分
1 month ago
mxr d175189193 fix(sem)修正上一次提交的语法错误
1 month ago
mxr d1f2efa4ae feat(sem)补充符号表对库函数的支持
1 month ago
mxr a015a4bc30 fix(sem)修正符号表部分的编译错误
1 month ago
mxr c4479eaa1e fix(sem)修正符号表的语法错误
1 month ago
mxr a0d5288351 feat(sem)补充符号表对浮点类型的支持
1 month ago
mxr 5d4bb511d1 feat(sem)补充符号表实现
1 month ago
mxr c450277c83 feat(sem)补充类型系统Label类型
1 month ago
mxr c21c066e4d feat(sem)补充类型系统浮点类型
1 month ago
mxr 2070193fcd feat(sem)补充类型系统
1 month ago
mxr a1ba450950 chore(git)修改.gitignore文件
1 month ago
LuoHello 56753bc842 feat:SysY.g4删除Number,使用进制及数据类型区分常量,本地测试通过
2 months ago
mxr 43e257368f fix(frontend): 修改SysY.g4语法规则,通过前端编译,不能通过全量编译
2 months ago

7
.gitignore vendored

@ -68,3 +68,10 @@ Thumbs.db
# Project outputs
# =========================
test/test_result/
# =========================
# mxr
# =========================
result.txt
build.sh
gdb.sh

@ -41,10 +41,16 @@
namespace ir {
class Type;
class ArrayType;
class FunctionType;
class Value;
class User;
class ConstantValue;
class ConstantInt;
class ConstantFloat;
class ConstantArray;
class ConstantZero;
class ConstantAggregateZero;
class GlobalValue;
class Instruction;
class BasicBlock;
@ -77,39 +83,141 @@ class Use {
};
// IR 上下文:集中管理类型、常量等共享资源,便于复用与扩展。
// ir/IR.h - 修改 Context 类定义
class Context {
public:
Context() = default;
~Context();
// 去重创建 i32 常量。
// 去重创建 i32 常量
ConstantInt* GetConstInt(int v);
// 去重创建浮点常量
ConstantFloat* GetConstFloat(float v);
// 创建数组常量(不去重,因为数组常量通常比较复杂且组合多样)
ConstantArray* GetConstArray(std::shared_ptr<ArrayType> ty,
std::vector<ConstantValue*> elements);
// 获取零常量(按类型缓存)
ConstantZero* GetZeroConstant(std::shared_ptr<Type> ty);
// 获取聚合类型的零常量
ConstantAggregateZero* GetAggregateZero(std::shared_ptr<Type> ty);
std::string NextTemp();
private:
// 数组常量缓存需要添加到类中
struct ArrayKey {
std::shared_ptr<ArrayType> type;
std::vector<ConstantValue*> elements;
bool operator==(const ArrayKey& other) const;
};
struct ArrayKeyHash {
size_t operator()(const ArrayKey& key) const;
};
std::unordered_map<ArrayKey, std::unique_ptr<ConstantArray>, ArrayKeyHash> array_cache_;
// 其他现有成员...
std::unordered_map<int, std::unique_ptr<ConstantInt>> const_ints_;
std::unordered_map<uint32_t, std::unique_ptr<ConstantFloat>> const_floats_;
std::unordered_map<Type*, std::unique_ptr<ConstantZero>> zero_constants_;
std::unordered_map<Type*, std::unique_ptr<ConstantAggregateZero>> aggregate_zeros_;
int temp_index_ = -1;
};
class Type {
public:
enum class Kind { Void, Int32, PtrInt32 };
explicit Type(Kind k);
enum class Kind { Void, Int32, Float, PtrInt32, PtrFloat, Label, Array, Function,
Int1, PtrInt1};
virtual ~Type() = default;
// 使用静态共享对象获取类型。
// 同一类型可直接比较返回值是否相等,例如:
// Type::GetInt32Type() == Type::GetInt32Type()
static const std::shared_ptr<Type>& GetVoidType();
static const std::shared_ptr<Type>& GetInt32Type();
static const std::shared_ptr<Type>& GetFloatType();
static const std::shared_ptr<Type>& GetPtrInt32Type();
Kind GetKind() const;
bool IsVoid() const;
bool IsInt32() const;
bool IsPtrInt32() const;
static const std::shared_ptr<Type>& GetPtrFloatType();
static const std::shared_ptr<Type>& GetLabelType();
static std::shared_ptr<ArrayType> GetArrayType(std::shared_ptr<Type> elem, std::vector<int> dims);
static std::shared_ptr<FunctionType> GetFunctionType(std::shared_ptr<Type> ret, std::vector<std::shared_ptr<Type>> params);
static const std::shared_ptr<Type>& GetInt1Type();
static const std::shared_ptr<Type>& GetPtrInt1Type();
// 类型判断
Kind GetKind() const { return kind_; }
bool IsVoid() const { return kind_ == Kind::Void; }
bool IsInt32() const { return kind_ == Kind::Int32; }
bool IsFloat() const { return kind_ == Kind::Float; }
bool IsPtrInt32() const { return kind_ == Kind::PtrInt32; }
bool IsPtrFloat() const { return kind_ == Kind::PtrFloat; }
bool IsLabel() const { return kind_ == Kind::Label; }
bool IsArray() const { return kind_ == Kind::Array; }
bool IsFunction() const { return kind_ == Kind::Function; }
bool IsInt1() const { return kind_ == Kind::Int1; }
bool IsPtrInt1() const { return kind_ == Kind::PtrInt1; }
// 类型属性
virtual size_t Size() const; // 字节大小
virtual size_t Alignment() const; // 对齐要求
virtual bool IsComplete() const; // 是否为完整类型(非 void数组维度已知等
protected:
explicit Type(Kind k); // 构造函数 protected只能由工厂和派生类调用
private:
Kind kind_;
};
// 数组类型
class ArrayType : public Type {
public:
// 获取元素类型和维度
const std::shared_ptr<Type>& GetElementType() const { return elem_type_; }
const std::vector<int>& GetDimensions() const { return dims_; }
size_t GetElementCount() const; // 总元素个数
size_t Size() const override;
size_t Alignment() const override;
bool IsComplete() const override;
protected:
ArrayType(std::shared_ptr<Type> elem, std::vector<int> dims);
friend class Type; // 允许 Type::GetArrayType 构造
private:
std::shared_ptr<Type> elem_type_;
std::vector<int> dims_;
};
// 函数类型
class FunctionType : public Type {
public:
const std::shared_ptr<Type>& GetReturnType() const { return return_type_; }
const std::vector<std::shared_ptr<Type>>& GetParamTypes() const { return param_types_; }
size_t Size() const override; // 函数类型没有大小,通常返回 0
size_t Alignment() const override; // 无对齐要求
bool IsComplete() const override; // 函数类型视为完整
protected:
FunctionType(std::shared_ptr<Type> ret, std::vector<std::shared_ptr<Type>> params);
friend class Type;
private:
std::shared_ptr<Type> return_type_;
std::vector<std::shared_ptr<Type>> param_types_;
};
class Value {
public:
Value(std::shared_ptr<Type> ty, std::string name);
@ -151,8 +259,82 @@ class ConstantInt : public ConstantValue {
int value_{};
};
// 后续还需要扩展更多指令类型。
enum class Opcode { Add, Sub, Mul, Alloca, Load, Store, Ret };
// 在 ConstantInt 类之后添加以下类
// ConstantFloat - 浮点常量
class ConstantFloat : public ConstantValue {
public:
ConstantFloat(std::shared_ptr<Type> ty, float v);
float GetValue() const { return value_; }
private:
float value_{};
};
// ConstantArray - 数组常量
class ConstantArray : public ConstantValue {
public:
// 构造函数:接收数组类型和常量元素列表
ConstantArray(std::shared_ptr<ArrayType> ty, std::vector<ConstantValue*> elements);
// 获取元素数量
size_t GetNumElements() const { return elements_.size(); }
// 获取指定索引的元素
ConstantValue* GetElement(size_t index) const { return elements_[index]; }
// 获取所有元素
const std::vector<ConstantValue*>& GetElements() const { return elements_; }
// 验证常量数组的类型是否正确
bool IsValid() const;
private:
std::vector<ConstantValue*> elements_;
};
// ConstantZero - 零常量(用于零初始化)
class ConstantZero : public ConstantValue {
public:
explicit ConstantZero(std::shared_ptr<Type> ty);
// 工厂方法:创建特定类型的零常量
static std::unique_ptr<ConstantZero> GetZero(std::shared_ptr<Type> ty);
};
// ConstantAggregateZero - 聚合类型的零常量(数组、结构体等)
class ConstantAggregateZero : public ConstantValue {
public:
explicit ConstantAggregateZero(std::shared_ptr<Type> ty);
// 获取聚合类型
std::shared_ptr<Type> GetAggregateType() const { return GetType(); }
// 工厂方法:创建聚合类型的零常量
static std::unique_ptr<ConstantAggregateZero> GetZero(std::shared_ptr<Type> ty);
};
//function 参数占位类,目前仅保存类型和名字,后续可扩展更多属性(例如是否为数组参数、数组维度等)。
class Argument : public Value {
public:
Argument(std::shared_ptr<Type> ty, std::string name);
};
// 后续还需要扩展更多指令类型。add call instruction 只是最小占位,后续可以继续补 sub/mul/div/rem、br/condbr、phi、gep 等指令。
enum class Opcode {
Add, Sub, Mul,
Alloca, Load, Store, Ret, Call,
Br, CondBr, Icmp, ZExt, Trunc,
Div, Mod,
And, Or, Not,
GEP,
FAdd, FSub, FMul, FDiv,
FCmp,
SIToFP, // 整数转浮点
FPToSI, // 浮点转整数
FPExt, // 浮点扩展
FPTrunc, // 浮点截断
};
// ZExt 和 Trunc 是零扩展和截断指令,SysY 的 int (i32) vs LLVM IR 的比较结果 (i1)。
// User 是所有“会使用其他 Value 作为输入”的 IR 对象的抽象基类。
// 当前实现中只有 Instruction 继承自 User。
@ -162,7 +344,16 @@ class User : public Value {
size_t GetNumOperands() const;
Value* GetOperand(size_t index) const;
void SetOperand(size_t index, Value* value);
// 添加模板方法,支持派生类自动转换
template<typename T>
void SetOperand(size_t index, T* value) {
SetOperand(index, static_cast<Value*>(value));
}
template<typename T>
void AddOperand(T* value) {
AddOperand(static_cast<Value*>(value));
}
protected:
// 统一的 operand 入口。
void AddOperand(Value* value);
@ -173,9 +364,53 @@ class User : public Value {
// GlobalValue 是全局值/全局变量体系的空壳占位类。
// 当前只补齐类层次,具体初始化器、打印和链接语义后续再补。
// ir/IR.h - GlobalValue 类定义需要添加这些方法
class GlobalValue : public User {
public:
private:
std::vector<ConstantValue*> initializer_;
bool is_constant_ = false;
bool is_extern_ = false;
public:
GlobalValue(std::shared_ptr<Type> ty, std::string name);
// 初始化器相关
void SetInitializer(ConstantValue* init);
void SetInitializer(const std::vector<ConstantValue*>& init);
const std::vector<ConstantValue*>& GetInitializer() const { return initializer_; }
bool HasInitializer() const { return !initializer_.empty(); }
// 常量属性
void SetConstant(bool is_const) { is_constant_ = is_const; }
bool IsConstant() const { return is_constant_; }
// 外部声明
void SetExtern(bool is_extern) { is_extern_ = is_extern; }
bool IsExtern() const { return is_extern_; }
// 类型判断
bool IsArray() const { return GetType()->IsArray(); }
bool IsScalar() const { return GetType()->IsInt32() || GetType()->IsFloat(); }
// 数组常量相关方法
bool IsArrayConstant() const;
ConstantValue* GetArrayElement(size_t index) const;
size_t GetArraySize() const;
// 获取数组大小(如果是数组类型)
int GetArraySizeInElements() const {
if (auto* array_ty = dynamic_cast<ArrayType*>(GetType().get())) {
return array_ty->GetElementCount();
}
return 0;
}
private:
// 辅助方法
std::shared_ptr<Type> GetValueType() const;
bool CheckTypeCompatibility(std::shared_ptr<Type> value_type,
ConstantValue* init) const;
};
class Instruction : public User {
@ -223,6 +458,284 @@ class StoreInst : public Instruction {
Value* GetPtr() const;
};
// 在 IR.h 中修改 BranchInst 类定义
class BranchInst : public Instruction {
public:
// 无条件跳转构造函数
BranchInst(std::shared_ptr<Type> void_ty, BasicBlock* target)
: Instruction(Opcode::Br, void_ty, ""),
is_conditional_(false),
cond_(nullptr),
target_(target),
true_target_(nullptr),
false_target_(nullptr) {}
// 条件跳转构造函数
BranchInst(std::shared_ptr<Type> void_ty, Value* cond,
BasicBlock* true_target, BasicBlock* false_target)
: Instruction(Opcode::CondBr, void_ty, ""),
is_conditional_(true),
cond_(cond),
target_(nullptr),
true_target_(true_target),
false_target_(false_target) {
// 添加操作数以便维护 def-use 关系
AddOperand(cond);
// 注意BasicBlock 也是 Value也需要添加到操作数中
// 但 BasicBlock 继承自 Value所以可以添加
AddOperand(true_target);
AddOperand(false_target);
}
// 判断是否为条件跳转
bool IsConditional() const { return is_conditional_; }
// 获取无条件跳转的目标(仅适用于无条件跳转)
BasicBlock* GetTarget() const {
if (is_conditional_) {
throw std::runtime_error("GetTarget called on conditional branch");
}
return target_;
}
// 获取条件值(仅适用于条件跳转)
Value* GetCondition() const {
if (!is_conditional_) {
throw std::runtime_error("GetCondition called on unconditional branch");
}
return cond_;
}
// 获取真分支目标(仅适用于条件跳转)
BasicBlock* GetTrueTarget() const {
if (!is_conditional_) {
throw std::runtime_error("GetTrueTarget called on unconditional branch");
}
return true_target_;
}
// 获取假分支目标(仅适用于条件跳转)
BasicBlock* GetFalseTarget() const {
if (!is_conditional_) {
throw std::runtime_error("GetFalseTarget called on unconditional branch");
}
return false_target_;
}
// 设置无条件跳转目标
void SetTarget(BasicBlock* target) {
if (is_conditional_) {
throw std::runtime_error("SetTarget called on conditional branch");
}
target_ = target;
}
// 设置条件跳转的分支目标
void SetTrueTarget(BasicBlock* target) {
if (!is_conditional_) {
throw std::runtime_error("SetTrueTarget called on unconditional branch");
}
true_target_ = target;
// 更新操作数
SetOperand(1, target);
}
void SetFalseTarget(BasicBlock* target) {
if (!is_conditional_) {
throw std::runtime_error("SetFalseTarget called on unconditional branch");
}
false_target_ = target;
// 更新操作数
SetOperand(2, target);
}
void SetCondition(Value* cond) {
if (!is_conditional_) {
throw std::runtime_error("SetCondition called on unconditional branch");
}
cond_ = cond;
// 更新操作数
SetOperand(0, cond);
}
private:
bool is_conditional_;
Value* cond_; // 条件值(条件跳转使用)
BasicBlock* target_; // 无条件跳转目标
BasicBlock* true_target_; // 真分支目标(条件跳转使用)
BasicBlock* false_target_; // 假分支目标(条件跳转使用)
};
// 创建整数比较指令
class IcmpInst : public Instruction {
public:
enum class Predicate {
EQ, // equal
NE, // not equal
LT, // less than
LE, // less than or equal
GT, // greater than
GE // greater than or equal
};
IcmpInst(Predicate pred, Value* lhs, Value* rhs, std::shared_ptr<Type> i1_ty, std::string name)
: Instruction(Opcode::Icmp, i1_ty, name), pred_(pred) {
AddOperand(lhs);
AddOperand(rhs);
}
Predicate GetPredicate() const { return pred_; }
Value* GetLhs() const { return GetOperand(0); }
Value* GetRhs() const { return GetOperand(1); }
private:
Predicate pred_;
};
class FcmpInst : public Instruction {
public:
enum class Predicate {
FALSE, // Always false
OEQ, // Ordered and equal
OGT, // Ordered and greater than
OGE, // Ordered and greater than or equal
OLT, // Ordered and less than
OLE, // Ordered and less than or equal
ONE, // Ordered and not equal
ORD, // Ordered (no nans)
UNO, // Unordered (isnan(x) || isnan(y))
UEQ, // Unordered or equal
UGT, // Unordered or greater than
UGE, // Unordered or greater than or equal
ULT, // Unordered or less than
ULE, // Unordered or less than or equal
UNE, // Unordered or not equal
TRUE // Always true
};
FcmpInst(Predicate pred, Value* lhs, Value* rhs,
std::shared_ptr<Type> i1_ty, std::string name)
: Instruction(Opcode::FCmp, i1_ty, name), pred_(pred) {
AddOperand(lhs);
AddOperand(rhs);
}
Predicate GetPredicate() const { return pred_; }
Value* GetLhs() const { return GetOperand(0); }
Value* GetRhs() const { return GetOperand(1); }
private:
Predicate pred_;
};
// ZExtInst - 零扩展指令
class ZExtInst : public Instruction {
public:
ZExtInst(Value* value, std::shared_ptr<Type> target_ty, std::string name = "")
: Instruction(Opcode::ZExt, target_ty, name) {
AddOperand(value);
}
// 获取被扩展的值
Value* GetValue() const {
return GetOperand(0);
}
// 获取源类型
std::shared_ptr<Type> GetSourceType() const {
return GetValue()->GetType();
}
// 获取目标类型
std::shared_ptr<Type> GetTargetType() const {
return GetType();
}
// 设置被扩展的值
void SetValue(Value* value) {
SetOperand(0, value);
}
};
// TruncInst - 截断指令
class TruncInst : public Instruction {
public:
TruncInst(Value* value, std::shared_ptr<Type> target_ty, std::string name = "")
: Instruction(Opcode::Trunc, target_ty, name) {
AddOperand(value);
}
// 获取被截断的值
Value* GetValue() const {
return GetOperand(0);
}
// 获取源类型
std::shared_ptr<Type> GetSourceType() const {
return GetValue()->GetType();
}
// 获取目标类型
std::shared_ptr<Type> GetTargetType() const {
return GetType();
}
// 设置被截断的值
void SetValue(Value* value) {
SetOperand(0, value);
}
};
class GEPInst : public Instruction {
public:
GEPInst(std::shared_ptr<Type> ptr_ty,
Value* base,
const std::vector<Value*>& indices,
const std::string& name);
Value* GetBase() const;
const std::vector<Value*>& GetIndices() const;
};
// Function 当前也采用了最小实现。
// 需要特别注意:由于项目里还没有单独的 FunctionType
// Function 继承自 Value 后,其 type_ 目前只保存“返回类型”,
// 并不能完整表达“返回类型 + 形参列表”这一整套函数签名。
// 这对当前只支持 int main() 的最小 IR 足够,但后续若补普通函数、
// 形参和调用,通常需要引入专门的函数类型表示。
class Function : public Value {
public:
// 当前构造函数接收完整的 FunctionType。
Function(std::string name, std::shared_ptr<FunctionType> func_type);
BasicBlock* CreateBlock(const std::string& name);
BasicBlock* GetEntry();
const BasicBlock* GetEntry() const;
const std::vector<std::unique_ptr<BasicBlock>>& GetBlocks() const;
// 函数增加参数的接口,目前仅保存参数类型和名字,后续可扩展更多属性(例如是否为数组参数、数组维度等)。注意这里是直接在 Function 上管理参数列表,而不是通过一个单独的 FunctionType 来表达完整函数签名,这也是当前最小实现的一个简化点。
Argument* AddArgument(std::unique_ptr<Argument> arg);
const std::vector<std::unique_ptr<Argument>>& GetArguments() const;
private:
BasicBlock* entry_ = nullptr;
std::vector<std::unique_ptr<BasicBlock>> blocks_;
std::vector<std::unique_ptr<Argument>> arguments_;
};
class CallInst : public Instruction {
public:
CallInst(std::shared_ptr<Type> ret_ty,
Function* callee,
const std::vector<Value*>& args,
const std::string& name);
Function* GetCallee() const;
const std::vector<Value*>& GetArgs() const;
private:
Function* callee_;
std::vector<Value*> args_;
};
// BasicBlock 已纳入 Value 体系,便于后续向更完整 IR 类图靠拢。
// 当前其类型仍使用 void 作为占位,后续可替换为专门的 label type。
class BasicBlock : public Value {
@ -247,6 +760,20 @@ class BasicBlock : public Value {
return ptr;
}
template <typename T, typename... Args>
T* InsertBeforeTerminator(Args&&... args) {
auto inst = std::make_unique<T>(std::forward<Args>(args)...);
auto* ptr = inst.get();
ptr->SetParent(this);
auto pos = instructions_.end();
if (HasTerminator()) {
pos = instructions_.end() - 1;
}
instructions_.insert(pos, std::move(inst));
return ptr;
}
private:
Function* parent_ = nullptr;
std::vector<std::unique_ptr<Instruction>> instructions_;
@ -254,39 +781,51 @@ class BasicBlock : public Value {
std::vector<BasicBlock*> successors_;
};
// Function 当前也采用了最小实现。
// 需要特别注意:由于项目里还没有单独的 FunctionType
// Function 继承自 Value 后,其 type_ 目前只保存“返回类型”,
// 并不能完整表达“返回类型 + 形参列表”这一整套函数签名。
// 这对当前只支持 int main() 的最小 IR 足够,但后续若补普通函数、
// 形参和调用,通常需要引入专门的函数类型表示。
class Function : public Value {
public:
// 当前构造函数接收的也是返回类型,而不是完整函数类型。
Function(std::string name, std::shared_ptr<Type> ret_type);
BasicBlock* CreateBlock(const std::string& name);
BasicBlock* GetEntry();
const BasicBlock* GetEntry() const;
const std::vector<std::unique_ptr<BasicBlock>>& GetBlocks() const;
private:
BasicBlock* entry_ = nullptr;
std::vector<std::unique_ptr<BasicBlock>> blocks_;
};
class Module {
public:
Module() = default;
Context& GetContext();
const Context& GetContext() const;
// 创建函数时当前只显式入返回类型,尚未接入完整的 FunctionType。
// 创建函数时传入完整的 FunctionType。
Function* CreateFunction(const std::string& name,
std::shared_ptr<Type> ret_type);
std::shared_ptr<FunctionType> func_type);
GlobalValue* CreateGlobal(const std::string& name,
std::shared_ptr<Type> ty);
Function* FindFunction(const std::string& name) const;
const std::vector<std::unique_ptr<Function>>& GetFunctions() const;
const std::vector<std::unique_ptr<GlobalValue>>& GetGlobals() const;
private:
Context context_;
std::vector<std::unique_ptr<Function>> functions_;
std::vector<std::unique_ptr<GlobalValue>> globals_;
};
// SIToFP - 整数转浮点
class SIToFPInst : public Instruction {
public:
SIToFPInst(Value* value, std::shared_ptr<Type> target_ty, std::string name = "")
: Instruction(Opcode::SIToFP, target_ty, name) {
AddOperand(value);
}
Value* GetValue() const {
return GetOperand(0);
}
};
// FPToSI - 浮点转整数
class FPToSIInst : public Instruction {
public:
FPToSIInst(Value* value, std::shared_ptr<Type> target_ty, std::string name = "")
: Instruction(Opcode::FPToSI, target_ty, name) {
AddOperand(value);
}
Value* GetValue() const {
return GetOperand(0);
}
};
class IRBuilder {
@ -297,14 +836,81 @@ class IRBuilder {
// 构造常量、二元运算、返回指令的最小集合。
ConstantInt* CreateConstInt(int v);
ConstantFloat* CreateConstFloat(float v); // 新增
ConstantArray* CreateConstArray(std::shared_ptr<ArrayType> ty,
std::vector<ConstantValue*> elements); // 新增
ConstantZero* CreateZeroConstant(std::shared_ptr<Type> ty); // 新增
BinaryInst* CreateBinary(Opcode op, Value* lhs, Value* rhs,
const std::string& name);
BinaryInst* CreateAdd(Value* lhs, Value* rhs, const std::string& name);
AllocaInst* CreateAlloca(std::shared_ptr<Type> ty, 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);
CallInst* CreateCall(Function* callee, const std::vector<Value*>& args,
const std::string& name);
// 创建无条件跳转
BranchInst* CreateBr(BasicBlock* target);
// 创建条件跳转
BranchInst* CreateCondBr(Value* cond, BasicBlock* true_target,
BasicBlock* false_target);
// 创建整数比较指令
IcmpInst* CreateICmpEQ(Value* lhs, Value* rhs, const std::string& name);
IcmpInst* CreateICmpNE(Value* lhs, Value* rhs, const std::string& name);
IcmpInst* CreateICmpLT(Value* lhs, Value* rhs, const std::string& name);
IcmpInst* CreateICmpLE(Value* lhs, Value* rhs, const std::string& name);
IcmpInst* CreateICmpGT(Value* lhs, Value* rhs, const std::string& name);
IcmpInst* CreateICmpGE(Value* lhs, Value* rhs, const std::string& name);
// 创建类型转换指令
ZExtInst* CreateZExt(Value* value, std::shared_ptr<Type> target_ty,
const std::string& name = "");
TruncInst* CreateTrunc(Value* value, std::shared_ptr<Type> target_ty,
const std::string& name = "");
// 便捷方法
ZExtInst* CreateZExtI1ToI32(Value* value, const std::string& name = "zext");
TruncInst* CreateTruncI32ToI1(Value* value, const std::string& name = "trunc");
BinaryInst* CreateDiv(Value* lhs, Value* rhs, const std::string& name);
BinaryInst* CreateMod(Value* lhs, Value* rhs, const std::string& name);
BinaryInst* CreateMul(Value* lhs, Value* rhs, const std::string& name);
BinaryInst* CreateSub(Value* lhs, Value* rhs, const std::string& name);
// 比较运算接口
BinaryInst* CreateAnd(Value* lhs, Value* rhs, const std::string& name);
BinaryInst* CreateOr(Value* lhs, Value* rhs, const std::string& name);
IcmpInst* CreateNot(Value* val, const std::string& name);
GEPInst* CreateGEP(Value* base, const std::vector<Value*>& indices, const std::string& name);
// 浮点运算
BinaryInst* CreateFAdd(Value* lhs, Value* rhs, const std::string& name);
BinaryInst* CreateFSub(Value* lhs, Value* rhs, const std::string& name);
BinaryInst* CreateFMul(Value* lhs, Value* rhs, const std::string& name);
BinaryInst* CreateFDiv(Value* lhs, Value* rhs, const std::string& name);
// 浮点比较
FcmpInst* CreateFCmpOEQ(Value* lhs, Value* rhs, const std::string& name);
FcmpInst* CreateFCmpONE(Value* lhs, Value* rhs, const std::string& name);
FcmpInst* CreateFCmpOLT(Value* lhs, Value* rhs, const std::string& name);
FcmpInst* CreateFCmpOLE(Value* lhs, Value* rhs, const std::string& name);
FcmpInst* CreateFCmpOGT(Value* lhs, Value* rhs, const std::string& name);
FcmpInst* CreateFCmpOGE(Value* lhs, Value* rhs, const std::string& name);
// 类型转换
SIToFPInst* CreateSIToFP(Value* value, std::shared_ptr<Type> target_ty,
const std::string& name = "");
FPToSIInst* CreateFPToSI(Value* value, std::shared_ptr<Type> target_ty,
const std::string& name = "");
private:
Context& ctx_;
BasicBlock* insert_block_;
@ -313,6 +919,9 @@ class IRBuilder {
class IRPrinter {
public:
void Print(const Module& module, std::ostream& os);
private:
void PrintConstant(const ConstantValue* constant, std::ostream& os);
};
} // namespace ir

@ -7,12 +7,23 @@
#include <memory>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <iostream>
#include "SysYBaseVisitor.h"
#include "SysYParser.h"
#include "ir/IR.h"
#include "sem/Sema.h"
//#define DEBUG_IRGen
#ifdef DEBUG_IRGen
#include <iostream>
#define DEBUG_MSG(msg) std::cerr << "[IRGen Debug] " << msg << std::endl
#else
#define DEBUG_MSG(msg)
#endif
namespace ir {
class Module;
class Function;
@ -21,38 +32,151 @@ class Value;
}
class IRGenImpl final : public SysYBaseVisitor {
public:
IRGenImpl(ir::Module& module, const SemanticContext& sema);
public:
// 修改构造函数,添加 SymbolTable 参数
IRGenImpl(ir::Module& module,
const SemanticContext& sema,
const SymbolTable& sym_table); // 新增
// 顶层
std::any visitCompUnit(SysYParser::CompUnitContext* ctx) override;
std::any visitFuncDef(SysYParser::FuncDefContext* ctx) override;
std::any visitBlockStmt(SysYParser::BlockStmtContext* ctx) override;
// 块
std::any visitBlock(SysYParser::BlockContext* ctx) override; // 注意:规则名为 Block
std::any visitBlockItem(SysYParser::BlockItemContext* ctx) override;
// 声明
std::any visitDecl(SysYParser::DeclContext* ctx) override;
std::any visitStmt(SysYParser::StmtContext* ctx) override;
std::any visitVarDef(SysYParser::VarDefContext* ctx) override;
std::any visitReturnStmt(SysYParser::ReturnStmtContext* ctx) override;
std::any visitParenExp(SysYParser::ParenExpContext* ctx) override;
std::any visitNumberExp(SysYParser::NumberExpContext* ctx) override;
std::any visitVarExp(SysYParser::VarExpContext* ctx) override;
std::any visitAdditiveExp(SysYParser::AdditiveExpContext* ctx) override;
private:
enum class BlockFlow {
std::any visitConstDecl(SysYParser::ConstDeclContext* ctx) override;
std::any visitConstDef(SysYParser::ConstDefContext* ctx) override;
std::any visitInitVal(SysYParser::InitValContext* ctx) override;
std::any visitConstInitVal(SysYParser::ConstInitValContext* ctx) override;
// 语句
std::any visitStmt(SysYParser::StmtContext* ctx) override;
// 表达式
// 基本表达式(变量、常量、括号表达式)直接翻译为 IR 中的值;函数调用和一元运算需要特殊处理。
std::any visitExp(SysYParser::ExpContext* ctx) override;
std::any visitCond(SysYParser::CondContext* ctx) override;
std::any visitLVal(SysYParser::LValContext* ctx) override;
std::any visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) override;
std::any visitUnaryExp(SysYParser::UnaryExpContext* ctx) override;
std::any visitFuncRParams(SysYParser::FuncRParamsContext* ctx) override;
std::any visitMulExp(SysYParser::MulExpContext* ctx) override;
// 加法表达式、乘法表达式、关系表达式、相等表达式、条件表达式分别对应不同的访问函数,按照优先级分层访问,最终调用 visitLVal 来处理变量访问
std::any visitAddExp(SysYParser::AddExpContext* ctx) override;
std::any visitRelExp(SysYParser::RelExpContext* ctx) override;
std::any visitEqExp(SysYParser::EqExpContext* ctx) override;
std::any visitLAndExp(SysYParser::LAndExpContext* ctx) override;
std::any visitLOrExp(SysYParser::LOrExpContext* ctx) override;
std::any visitConstExp(SysYParser::ConstExpContext* ctx) override;
// 辅助函数
ir::Value* EvalExpr(SysYParser::ExpContext& expr); // 只保留一处
ir::Value* EvalCond(SysYParser::CondContext& cond);
std::any visitCallExp(SysYParser::UnaryExpContext* ctx);
std::vector<ir::Value*> ProcessNestedInitVals(SysYParser::InitValContext* ctx);
// 带维度感知的展平:按 C 语言花括号对齐规则填充 total_size 个槽位
// dims[0] 是最外层维度dims.back() 是最内层维度(元素层)
// 返回已展平并补零的 total_size 大小的向量
std::vector<ir::Value*> FlattenInitVal(SysYParser::InitValContext* ctx,
const std::vector<int>& dims,
bool is_float);
int TryEvaluateConstInt(SysYParser::ConstExpContext* ctx);
void AddRuntimeFunctions();
ir::Function* CreateRuntimeFunctionDecl(const std::string& funcName);
ir::BasicBlock* EnsureCleanupBlock();
void RegisterCleanup(ir::Function* free_func, ir::Value* ptr);
ir::AllocaInst* CreateEntryAlloca(std::shared_ptr<ir::Type> ty,
const std::string& name);
ir::AllocaInst* CreateEntryAllocaI32(const std::string& name);
ir::AllocaInst* CreateEntryAllocaFloat(const std::string& name);
private:
// 辅助函数声明
enum class BlockFlow{
Continue,
Terminated,
};
BlockFlow VisitBlockItemResult(SysYParser::BlockItemContext& item);
ir::Value* EvalExpr(SysYParser::ExpContext& expr);
BlockFlow HandleReturnStmt(SysYParser::StmtContext* ctx);
BlockFlow HandleIfStmt(SysYParser::StmtContext* ctx);
BlockFlow HandleWhileStmt(SysYParser::StmtContext* ctx);
BlockFlow HandleBreakStmt(SysYParser::StmtContext* ctx);
BlockFlow HandleContinueStmt(SysYParser::StmtContext* ctx);
BlockFlow HandleAssignStmt(SysYParser::StmtContext* ctx);
// 完全正确的左值判断函数
bool IsLValueExpression(SysYParser::ExpContext* ctx);
bool IsLValueInAddExp(SysYParser::AddExpContext* ctx);
bool IsLValueInMulExp(SysYParser::MulExpContext* ctx);
bool IsLValueInUnaryExp(SysYParser::UnaryExpContext* ctx);
bool IsLValueInPrimaryExp(SysYParser::PrimaryExpContext* ctx);
// 循环上下文结构
struct LoopContext {
ir::BasicBlock* condBlock;
ir::BasicBlock* bodyBlock;
ir::BasicBlock* exitBlock;
};
struct ArrayInfo {
std::vector<ir::Value*> elements;
std::vector<int> dimensions;
};
std::vector<LoopContext> loopStack_;
ir::Module& module_;
const SemanticContext& sema_;
const SymbolTable& symbol_table_; // 新增成员
ir::Function* func_;
ir::IRBuilder builder_;
// 名称绑定由 Sema 负责IRGen 只维护“声明 -> 存储槽位”的代码生成状态。
ir::Value* EvalAssign(SysYParser::StmtContext* ctx);
// 按 VarDefContext 查找存储位置(用于数组访问等场景)
std::unordered_map<SysYParser::VarDefContext*, ir::Value*> storage_map_;
// 按变量名快速查找(用于 LVal 等场景)
std::unordered_map<std::string, ir::Value*> local_var_map_; // 局部变量
std::unordered_map<std::string, ir::GlobalValue*> global_map_; // 全局变量
std::unordered_map<std::string, ir::Value*> param_map_; // 函数参数
std::unordered_set<std::string> pointer_param_names_; // 指针/数组形参名
std::unordered_set<std::string> heap_local_array_names_; // 堆分配的局部数组名
// 常量映射:常量名 -> 常量值(标量常量)
std::unordered_map<std::string, ir::ConstantValue*> const_value_map_;
// 全局常量映射:常量名 -> 全局变量(数组常量)
std::unordered_map<std::string, ir::GlobalValue*> const_global_map_;
// 原有的常量存储映射(用于兼容)
std::unordered_map<antlr4::ParserRuleContext*, ir::Value*> const_storage_map_;
std::unordered_map<SysYParser::VarDefContext*, ArrayInfo> array_info_map_;
std::string current_function_name_;
bool current_function_is_recursive_ = false;
ir::AllocaInst* function_return_slot_ = nullptr;
ir::BasicBlock* function_cleanup_block_ = nullptr;
std::vector<std::pair<ir::Function*, ir::Value*>> function_cleanup_actions_;
// 新增:处理全局和局部变量的辅助函数
// 修改处理函数的签名,使用 Symbol* 参数
std::any HandleGlobalVariable(SysYParser::VarDefContext* ctx,
const std::string& varName,
const Symbol* sym);
std::any HandleLocalVariable(SysYParser::VarDefContext* ctx,
const std::string& varName,
const Symbol* sym);
};
// 修改 GenerateIR 函数签名
std::unique_ptr<ir::Module> GenerateIR(SysYParser::CompUnitContext& tree,
const SemanticContext& sema);
const SemaResult& sema_result);

@ -19,41 +19,161 @@ class MIRContext {
MIRContext& DefaultContext();
enum class PhysReg { W0, W8, W9, X29, X30, SP };
enum class PhysReg {
//W0, W8, W9, X29, X30, SP
// 32位通用寄存器
W0, W1, W2, W3, W4, W5, W6, W7, // 参数传递/临时
W8, W9, // 临时寄存器(当前主要使用)
W10, W11, W12, W13, W14, W15, // 临时寄存器(扩展)
W16, W17, // intra-procedure-call 临时
W18, // 平台预留
W19, W20, W21, W22, W23, W24, // 被调用者保存(扩展用)
W25, W26, W27, W28, // 被调用者保存
W29, // 帧指针 (FP)
W30, // 链接寄存器 (LR)
// 64位版本
X0, X1, X2, X3, X4, X5, X6, X7,
X8, X9, X10, X11, X12, X13, X14, X15,
X16, X17, X18,
X19, X20, X21, X22, X23, X24, X25, X26, X27, X28,
X29, // FP
X30, // LR
// 浮点寄存器 (32位)
S0, S1, S2, S3, S4, S5, S6, S7,
S8, S9, S10, S11, S12, S13, S14, S15,
S16, S17, S18, S19, S20, S21, S22, S23,
S24, S25, S26, S27, S28, S29, S30, S31,
// 特殊寄存器
SP, // 栈指针
ZR, // 零寄存器
};
const char* PhysRegName(PhysReg reg);
// ========== 条件码枚举(用于 BCond 指令)==========
enum class CondCode {
EQ, // 相等 (equal)
NE, // 不等 (not equal)
CS, // 进位设置 (carry set) / 无符号大于等于
CC, // 进位清除 (carry clear) / 无符号小于
MI, // 负数 (minus)
PL, // 非负数 (plus)
VS, // 溢出 (overflow set)
VC, // 无溢出 (overflow clear)
HI, // 无符号大于 (higher)
LS, // 无符号小于等于 (lower or same)
GE, // 有符号大于等于 (greater or equal)
LT, // 有符号小于 (less than)
GT, // 有符号大于 (greater than)
LE, // 有符号小于等于 (less or equal)
AL, // 总是 (always)
};
const char* CondCodeName(CondCode cc);
// ========== MIR 指令操作码枚举 ==========
enum class Opcode {
Prologue,
Epilogue,
MovImm,
LoadStack,
StoreStack,
AddRR,
Ret,
// ---------- 栈帧相关 ----------
Prologue, // 函数序言(伪指令)
Epilogue, // 函数尾声(伪指令)
// ---------- 数据传输 ----------
MovImm, // 立即数移动到寄存器: MOV w8, #imm
MovReg, // 寄存器之间移动: MOV w8, w9
LoadStack, // 从栈槽加载: LDR w8, [sp, #offset]
StoreStack, // 存储到栈槽: STR w8, [sp, #offset]
LoadStackPair,// 成对加载: LDP x29, x30, [sp], #16
StoreStackPair,// 成对存储: STP x29, x30, [sp, #-16]!
// ---------- 整数算术运算 ----------
AddRR, // 加法: ADD w8, w8, w9
AddRI, // 加法(立即数): ADD w8, w8, #imm
SubRR, // 减法: SUB w8, w8, w9
SubRI, // 减法(立即数): SUB w8, w8, #imm
MulRR, // 乘法: MUL w8, w8, w9
SDivRR, // 有符号除法: SDIV w8, w8, w9
UDivRR, // 无符号除法: UDIV w8, w8, w9
// ---------- 浮点算术运算 ----------
FAddRR, // 浮点加法: FADD s0, s0, s1
FSubRR, // 浮点减法: FSUB s0, s0, s1
FMulRR, // 浮点乘法: FMUL s0, s0, s1
FDivRR, // 浮点除法: FDIV s0, s0, s1
// ---------- 比较运算 ----------
CmpRR, // 比较(寄存器): CMP w8, w9
CmpRI, // 比较(立即数): CMP w8, #imm
FCmpRR, // 浮点比较: FCMP s0, s1
// ---------- 类型转换 ----------
SIToFP, // 有符号整数转浮点: SCVTF s0, w0
FPToSI, // 浮点转有符号整数: FCVTZS w0, s0
ZExt, // 零扩展i1 -> i32: AND w8, w8, #1
// ---------- 控制流 ----------
B, // 无条件跳转: B label
BCond, // 条件跳转: B.EQ label, B.NE label, B.GT label 等
Call, // 函数调用: BL target
Ret, // 函数返回: RET
// ---------- 逻辑运算 ----------
AndRR, // 按位与: AND w8, w8, w9
OrRR, // 按位或: ORR w8, w8, w9
EorRR, // 按位异或: EOR w8, w8, w9
LslRR, // 逻辑左移: LSL w8, w8, w9
LsrRR, // 逻辑右移: LSR w8, w8, w9
AsrRR, // 算术右移: ASR w8, w8, w9
// ---------- 特殊 ----------
Nop, // 空操作: NOP
Label, // 内联标签,不生成实际指令,仅输出标签名
// 添加
Movk, // movk Rd, #imm16, lsl #shift
// 添加
LoadStackAddr, // 将栈帧地址加载到寄存器 (add xd, sp, #offset)
// 用于全局变量地址计算
Adrp, // ADRP Xd, label
AddLabel, // ADD Xd, Xn, :lo12:label
// 新增
Sxtw, // 符号扩展字到双字sxtw Xd, Wn
};
// ========== 操作数类 ==========
class Operand {
public:
enum class Kind { Reg, Imm, FrameIndex };
enum class Kind { Reg, Imm, FrameIndex, Cond, Label };
static Operand Reg(PhysReg reg);
static Operand Imm(int value);
static Operand FrameIndex(int index);
static Operand Cond(CondCode cc);
static Operand Label(const std::string& label);
Kind GetKind() const { return kind_; }
PhysReg GetReg() const { return reg_; }
int GetImm() const { return imm_; }
int GetFrameIndex() const { return imm_; }
CondCode GetCondCode() const { return cc_; }
const std::string& GetLabel() const { return label_; }
private:
Operand(Kind kind, PhysReg reg, int imm);
Operand(Kind kind, PhysReg reg, int imm, CondCode cc, const std::string& label);
Kind kind_;
PhysReg reg_;
int imm_;
CondCode cc_;
std::string label_;
};
// ========== MIR 指令类 ==========
class MachineInstr {
public:
MachineInstr(Opcode opcode, std::vector<Operand> operands = {});
@ -66,12 +186,14 @@ class MachineInstr {
std::vector<Operand> operands_;
};
// ========== 栈槽结构 ==========
struct FrameSlot {
int index = 0;
int size = 4;
int offset = 0;
};
// ========== MIR 基本块 ==========
class MachineBasicBlock {
public:
explicit MachineBasicBlock(std::string name);
@ -82,38 +204,133 @@ class MachineBasicBlock {
MachineInstr& Append(Opcode opcode,
std::initializer_list<Operand> operands = {});
MachineInstr& Append(Opcode opcode, std::vector<Operand> operands);
// 控制流信息
std::vector<MachineBasicBlock*>& GetSuccessors() { return successors_; }
const std::vector<MachineBasicBlock*>& GetSuccessors() const { return successors_; }
void AddSuccessor(MachineBasicBlock* succ) { successors_.push_back(succ); }
private:
std::string name_;
std::vector<MachineInstr> instructions_;
std::vector<MachineBasicBlock*> successors_;
};
// ========== MIR 函数 ==========
class MachineFunction {
public:
explicit MachineFunction(std::string name);
const std::string& GetName() const { return name_; }
// 基本块管理
MachineBasicBlock& GetEntry() { return entry_; }
const MachineBasicBlock& GetEntry() const { return entry_; }
std::vector<std::unique_ptr<MachineBasicBlock>>& GetBasicBlocks() {
return basic_blocks_;
}
const std::vector<std::unique_ptr<MachineBasicBlock>>& GetBasicBlocks() const {
return basic_blocks_;
}
void AddBasicBlock(std::unique_ptr<MachineBasicBlock> bb) {
basic_blocks_.push_back(std::move(bb));
}
// 栈槽管理
int CreateFrameIndex(int size = 4);
FrameSlot& GetFrameSlot(int index);
const FrameSlot& GetFrameSlot(int index) const;
std::vector<FrameSlot>& GetFrameSlots() { return frame_slots_; }
const std::vector<FrameSlot>& GetFrameSlots() const { return frame_slots_; }
// 栈帧大小
int GetFrameSize() const { return frame_size_; }
void SetFrameSize(int size) { frame_size_ = size; }
private:
std::string name_;
MachineBasicBlock entry_;
std::vector<std::unique_ptr<MachineBasicBlock>> basic_blocks_;
std::vector<FrameSlot> frame_slots_;
int frame_size_ = 0;
};
std::unique_ptr<MachineFunction> LowerToMIR(const ir::Module& module);
// ========== MIR 模块 ==========
class MachineModule {
public:
MachineModule() = default;
// 添加 MachineFunction
void AddFunction(std::unique_ptr<MachineFunction> func) {
functions_.push_back(std::move(func));
}
// 获取所有函数
const std::vector<std::unique_ptr<MachineFunction>>& GetFunctions() const {
return functions_;
}
std::vector<std::unique_ptr<MachineFunction>>& GetFunctions() {
return functions_;
}
// 根据名称查找函数
MachineFunction* GetFunction(const std::string& name) {
for (auto& func : functions_) {
if (func->GetName() == name) {
return func.get();
}
}
return nullptr;
}
const MachineFunction* GetFunction(const std::string& name) const {
for (const auto& func : functions_) {
if (func->GetName() == name) {
return func.get();
}
}
return nullptr;
}
struct GlobalDecl {
std::string name;
int size; // 字节大小
int alignment; // 对齐要求(通常为 4 或 8
bool is_zero_init; // 是否为零初始化
bool has_init_data; // 是否包含初始化数据(用于标量常量)
uint64_t init_data; // 初始化数据≤8字节
// 构造函数,默认零初始化
GlobalDecl(const std::string& n, int sz, int align, bool zero = true,
bool has_data = false, uint64_t data = 0)
: name(n), size(sz), alignment(align), is_zero_init(zero),
has_init_data(has_data), init_data(data) {}
};
void AddGlobal(const std::string& name, int size, int alignment,
bool is_zero_init = true,
bool has_init_data = false, uint64_t init_data = 0) {
globals_.emplace_back(name, size, alignment, is_zero_init,
has_init_data, init_data);
}
const std::vector<GlobalDecl>& GetGlobals() const { return globals_; }
private:
std::vector<std::unique_ptr<MachineFunction>> functions_;
std::vector<GlobalDecl> globals_;
};
// ========== 后端流程函数 ==========
/* std::unique_ptr<MachineFunction> LowerToMIR(const ir::Module& module);
void RunRegAlloc(MachineFunction& function);
void RunFrameLowering(MachineFunction& function);
void PrintAsm(const MachineFunction& function, std::ostream& os);
void PrintAsm(const MachineFunction& function, std::ostream& os); */
std::unique_ptr<MachineModule> LowerToMIR(const ir::Module& module);
void RunRegAlloc(MachineModule& module);
void RunFrameLowering(MachineModule& module);
void PrintAsm(const MachineModule& module, std::ostream& os);
} // namespace mir

@ -2,29 +2,101 @@
#pragma once
#include <unordered_map>
#include <vector>
#include <memory>
#include "SysYParser.h"
#include "ir/IR.h"
#include "sem/SymbolTable.h"
// 表达式信息结构
struct ExprInfo {
std::shared_ptr<ir::Type> type = nullptr;
bool is_lvalue = false;
bool is_const = false;
bool is_const_int = false; // 是否是整型常量
int const_int_value = 0;
float const_float_value = 0.0f;
antlr4::ParserRuleContext* node = nullptr; // 对应的语法树节点
};
// 语义分析上下文:存储分析过程中产生的信息
class SemanticContext {
public:
void BindVarUse(SysYParser::VarContext* use,
SysYParser::VarDefContext* decl) {
var_uses_[use] = decl;
}
SysYParser::VarDefContext* ResolveVarUse(
const SysYParser::VarContext* use) const {
auto it = var_uses_.find(use);
return it == var_uses_.end() ? nullptr : it->second;
}
private:
std::unordered_map<const SysYParser::VarContext*,
SysYParser::VarDefContext*>
var_uses_;
public:
// ----- 变量使用绑定(使用 LValContext 而不是 VarContext-----
void BindVarUse(SysYParser::LValContext* use,
SysYParser::VarDefContext* decl) {
var_uses_[use] = decl;
}
SysYParser::VarDefContext* ResolveVarUse(
const SysYParser::LValContext* use) const {
auto it = var_uses_.find(use);
return it == var_uses_.end() ? nullptr : it->second;
}
void BindConstUse(SysYParser::LValContext* use, SysYParser::ConstDefContext* decl) {
const_uses_[use] = decl;
}
SysYParser::ConstDefContext* ResolveConstUse(const SysYParser::LValContext* use) const {
auto it = const_uses_.find(use);
return it == const_uses_.end() ? nullptr : it->second;
}
// ----- 表达式类型信息存储 -----
void SetExprType(antlr4::ParserRuleContext* node, const ExprInfo& info) {
ExprInfo copy = info;
copy.node = node;
expr_types_[node] = copy;
}
ExprInfo* GetExprType(antlr4::ParserRuleContext* node) {
auto it = expr_types_.find(node);
return it == expr_types_.end() ? nullptr : &it->second;
}
const ExprInfo* GetExprType(antlr4::ParserRuleContext* node) const {
auto it = expr_types_.find(node);
return it == expr_types_.end() ? nullptr : &it->second;
}
// ----- 隐式转换标记(供 IR 生成使用)-----
struct ConversionInfo {
antlr4::ParserRuleContext* node;
std::shared_ptr<ir::Type> from_type;
std::shared_ptr<ir::Type> to_type;
};
void AddConversion(antlr4::ParserRuleContext* node,
std::shared_ptr<ir::Type> from,
std::shared_ptr<ir::Type> to) {
conversions_.push_back({node, from, to});
}
const std::vector<ConversionInfo>& GetConversions() const { return conversions_; }
private:
// 变量使用映射 - 使用 LValContext 作为键
std::unordered_map<const SysYParser::LValContext*,
SysYParser::VarDefContext*> var_uses_;
// 表达式类型映射
std::unordered_map<antlr4::ParserRuleContext*, ExprInfo> expr_types_;
// 隐式转换列表
std::vector<ConversionInfo> conversions_;
std::unordered_map<const SysYParser::LValContext*, SysYParser::ConstDefContext*> const_uses_;
};
// 目前仅检查:
// - 变量先声明后使用
// - 局部变量不允许重复定义
SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit);
// SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit);
// 新增:语义分析结果结构体
struct SemaResult {
SemanticContext context;
SymbolTable symbol_table;
};
// 修改 RunSema 的返回类型
SemaResult RunSema(SysYParser::CompUnitContext& comp_unit);

@ -1,17 +1,187 @@
// 极简符号表:记录局部变量定义点。
#pragma once
#include <algorithm>
#include <string>
#include <unordered_map>
#include <vector>
#include <memory>
#include "SysYParser.h"
#include "ir/IR.h"
// 符号种类
enum class SymbolKind {
Variable,
Function,
Parameter,
Constant
};
// 符号条目
// 符号条目
struct Symbol {
// 基本信息
std::string name;
SymbolKind kind;
std::shared_ptr<ir::Type> type;
int scope_level = 0;
int stack_offset = -1;
bool is_initialized = false;
bool is_builtin = false;
// 数组参数相关
std::vector<int> array_dims;
bool is_array_param = false;
// 函数相关
std::vector<std::shared_ptr<ir::Type>> param_types;
// 常量值存储
union ConstantValue {
int i32;
float f32;
};
// 标量常量
bool is_int_const = true;
ConstantValue const_value;
// 数组常量(扁平化存储)
bool is_array_const = false;
std::vector<ConstantValue> array_const_values;
// 语法树节点
SysYParser::VarDefContext* var_def_ctx = nullptr;
SysYParser::ConstDefContext* const_def_ctx = nullptr;
SysYParser::FuncFParamContext* param_def_ctx = nullptr;
SysYParser::FuncDefContext* func_def_ctx = nullptr;
// 辅助方法
bool IsScalarConstant() const {
return kind == SymbolKind::Constant && !type->IsArray();
}
bool IsArrayConstant() const {
return kind == SymbolKind::Constant && type->IsArray();
}
int GetIntConstant() const {
if (!IsScalarConstant()) {
throw std::runtime_error("不是标量常量");
}
if (!is_int_const) {
throw std::runtime_error("不是整型常量");
}
return const_value.i32;
}
float GetFloatConstant() const {
if (!IsScalarConstant()) {
throw std::runtime_error("不是标量常量");
}
if (is_int_const) {
return static_cast<float>(const_value.i32);
}
return const_value.f32;
}
ConstantValue GetArrayElement(size_t index) const {
if (!IsArrayConstant()) {
throw std::runtime_error("不是数组常量");
}
if (index >= array_const_values.size()) {
throw std::runtime_error("数组下标越界");
}
return array_const_values[index];
}
size_t GetArraySize() const {
if (!IsArrayConstant()) return 0;
return array_const_values.size();
}
};
class SymbolTable {
public:
void Add(const std::string& name, SysYParser::VarDefContext* decl);
bool Contains(const std::string& name) const;
SysYParser::VarDefContext* Lookup(const std::string& name) const;
public:
SymbolTable();
~SymbolTable() = default;
// 添加调试方法
size_t getScopeCount() const { return active_scope_stack_.size(); }
void dump() const {
std::cerr << "=== SymbolTable Dump ===" << std::endl;
for (size_t i = 0; i < scopes_.size(); ++i) {
std::cerr << "Scope " << i << " (depth=" << i << ")";
bool active = std::find(active_scope_stack_.begin(), active_scope_stack_.end(), i) != active_scope_stack_.end();
std::cerr << (active ? " [active]" : " [inactive]") << std::endl;
for (const auto& [name, sym] : scopes_[i]) {
std::cerr << " " << name
<< " (kind=" << (int)sym.kind
<< ", level=" << sym.scope_level << ")" << std::endl;
}
}
}
// ----- 作用域管理 -----
void enterScope(); // 进入新作用域
void exitScope(); // 退出当前作用域
int currentScopeLevel() const { return static_cast<int>(active_scope_stack_.size()) - 1; }
// ----- 符号操作(推荐使用)-----
bool addSymbol(const Symbol& sym); // 添加符号到当前作用域
Symbol* lookup(const std::string& name); // 从当前作用域向外查找
Symbol* lookupCurrent(const std::string& name); // 仅在当前作用域查找
const Symbol* lookup(const std::string& name) const;
const Symbol* lookupCurrent(const std::string& name) const;
const Symbol* lookupAll(const std::string& name) const; // 所有作用域查找,包括已结束的作用域
const Symbol* lookupByVarDef(const SysYParser::VarDefContext* decl) const; // 通过定义节点查找符号
const Symbol* lookupByConstDef(const SysYParser::ConstDefContext* decl) const; // 通过常量定义节点查找符号
// ----- 与原接口兼容(保留原有功能)-----
void Add(const std::string& name, SysYParser::VarDefContext* decl);
bool Contains(const std::string& name) const;
SysYParser::VarDefContext* Lookup(const std::string& name) const;
// ----- 辅助函数:从语法树节点构造 Type -----
static std::shared_ptr<ir::Type> getTypeFromFuncDef(SysYParser::FuncDefContext* ctx);
void registerBuiltinFunctions();
// 对常量表达式求值(返回整数值,用于数组维度等)
int EvaluateConstExp(SysYParser::ConstExpContext* ctx) const;
// 对常量表达式求值(返回浮点值,用于全局初始化)
float EvaluateConstExpFloat(SysYParser::ConstExpContext* ctx) const;
// 对常量初始化列表求值,返回一系列常量值(扁平化)
struct ConstValue {
enum Kind { INT, FLOAT };
Kind kind;
union {
int int_val;
float float_val;
};
};
void flattenInit(SysYParser::ConstInitValContext* ctx,
std::vector<ConstValue>& out,
std::shared_ptr<ir::Type> base_type) const;
std::vector<ConstValue> EvaluateConstInitVal(
SysYParser::ConstInitValContext* ctx,
const std::vector<int>& dims,
std::shared_ptr<ir::Type> base_type) const;
int EvaluateConstExpression(SysYParser::ExpContext* ctx) const;
private:
// 作用域栈:每个元素是一个从名字到符号的映射
std::vector<std::unordered_map<std::string, Symbol>> scopes_;
std::vector<size_t> active_scope_stack_;
static constexpr int GLOBAL_SCOPE = 0; // 全局作用域索引
ConstValue EvaluateAddExp(SysYParser::AddExpContext* ctx) const;
ConstValue EvaluateMulExp(SysYParser::MulExpContext* ctx) const;
ConstValue EvaluateUnaryExp(SysYParser::UnaryExpContext* ctx) const;
ConstValue EvaluatePrimaryExp(SysYParser::PrimaryExpContext* ctx) const;
private:
std::unordered_map<std::string, SysYParser::VarDefContext*> table_;
std::shared_ptr<ir::Type> getTypeFromVarDef(SysYParser::VarDefContext* ctx) const;
};

Binary file not shown.

@ -0,0 +1,492 @@
; ModuleID = 'optimized.bc'
source_filename = "./build/test_compiler/performance/03_sort1.ll"
@a = global [30000010 x i32] zeroinitializer
@ans = local_unnamed_addr global i32 0
declare i32 @getarray(ptr) local_unnamed_addr
declare void @putint(i32) local_unnamed_addr
declare void @putch(i32) local_unnamed_addr
declare void @starttime() local_unnamed_addr
declare void @stoptime() local_unnamed_addr
declare ptr @sysy_alloc_i32(i32) local_unnamed_addr
declare void @sysy_free_i32(ptr) local_unnamed_addr
declare void @sysy_zero_i32(ptr, i32) local_unnamed_addr
; Function Attrs: nofree norecurse nosync nounwind memory(argmem: read)
define i32 @getMaxNum(i32 %n, ptr nocapture readonly %arr) local_unnamed_addr #0 {
entry:
%t95 = icmp sgt i32 %n, 0
br i1 %t95, label %while.body.t5, label %while.exit.t6
while.body.t5: ; preds = %entry, %while.body.t5
%t3_i.07 = phi i32 [ %t21, %while.body.t5 ], [ 0, %entry ]
%t2_ret.06 = phi i32 [ %spec.select, %while.body.t5 ], [ 0, %entry ]
%0 = zext nneg i32 %t3_i.07 to i64
%t13 = getelementptr i32, ptr %arr, i64 %0
%t14 = load i32, ptr %t13, align 4
%spec.select = tail call i32 @llvm.smax.i32(i32 %t14, i32 %t2_ret.06)
%t21 = add nuw nsw i32 %t3_i.07, 1
%t9 = icmp slt i32 %t21, %n
br i1 %t9, label %while.body.t5, label %while.exit.t6
while.exit.t6: ; preds = %while.body.t5, %entry
%t2_ret.0.lcssa = phi i32 [ 0, %entry ], [ %spec.select, %while.body.t5 ]
ret i32 %t2_ret.0.lcssa
}
; Function Attrs: nofree norecurse nosync nounwind memory(none)
define i32 @getNumPos(i32 %num, i32 %pos) local_unnamed_addr #1 {
entry:
%t333 = icmp sgt i32 %pos, 0
br i1 %t333, label %while.body.t29, label %while.exit.t30
while.body.t29: ; preds = %entry, %while.body.t29
%t27_i.05 = phi i32 [ %t37, %while.body.t29 ], [ 0, %entry ]
%t24.04 = phi i32 [ %t35, %while.body.t29 ], [ %num, %entry ]
%t35 = sdiv i32 %t24.04, 16
%t37 = add nuw nsw i32 %t27_i.05, 1
%t33 = icmp slt i32 %t37, %pos
br i1 %t33, label %while.body.t29, label %while.exit.t30
while.exit.t30: ; preds = %while.body.t29, %entry
%t24.0.lcssa = phi i32 [ %num, %entry ], [ %t35, %while.body.t29 ]
%t39 = srem i32 %t24.0.lcssa, 16
ret i32 %t39
}
define void @radixSort(i32 %bitround, ptr nocapture %a, i32 %l, i32 %r) local_unnamed_addr {
entry:
%t43 = tail call ptr @sysy_alloc_i32(i32 16)
tail call void @sysy_zero_i32(ptr %t43, i32 16)
%t46 = tail call ptr @sysy_alloc_i32(i32 16)
tail call void @sysy_zero_i32(ptr %t46, i32 16)
%t48 = tail call ptr @sysy_alloc_i32(i32 16)
tail call void @sysy_zero_i32(ptr %t48, i32 16)
%t54 = icmp eq i32 %bitround, -1
%t56 = add i32 %l, 1
%t58 = icmp sge i32 %t56, %r
%t59 = or i1 %t54, %t58
br i1 %t59, label %cleanup.t44, label %while.cond.t62.preheader
while.cond.t62.preheader: ; preds = %entry
%t6796 = icmp slt i32 %l, %r
br i1 %t6796, label %while.body.t63.lr.ph, label %while.exit.t64
while.body.t63.lr.ph: ; preds = %while.cond.t62.preheader
%t333.i = icmp sgt i32 %bitround, 0
br label %while.body.t63
cleanup.t44: ; preds = %merge.t196, %entry
tail call void @sysy_free_i32(ptr %t48)
tail call void @sysy_free_i32(ptr %t46)
tail call void @sysy_free_i32(ptr %t43)
ret void
while.body.t63: ; preds = %while.body.t63.lr.ph, %getNumPos.exit28
%storemerge97 = phi i32 [ %l, %while.body.t63.lr.ph ], [ %t83, %getNumPos.exit28 ]
%0 = sext i32 %storemerge97 to i64
%t69 = getelementptr i32, ptr %a, i64 %0
%t70 = load i32, ptr %t69, align 4
br i1 %t333.i, label %while.body.t29.i, label %getNumPos.exit.thread
getNumPos.exit.thread: ; preds = %while.body.t63
%t39.i80 = srem i32 %t70, 16
%1 = sext i32 %t39.i80 to i64
%t7381 = getelementptr i32, ptr %t48, i64 %1
%t7482 = load i32, ptr %t7381, align 4
br label %getNumPos.exit28
while.body.t29.i: ; preds = %while.body.t63, %while.body.t29.i
%t27_i.05.i = phi i32 [ %t37.i, %while.body.t29.i ], [ 0, %while.body.t63 ]
%t24.04.i = phi i32 [ %t35.i, %while.body.t29.i ], [ %t70, %while.body.t63 ]
%t35.i = sdiv i32 %t24.04.i, 16
%t37.i = add nuw nsw i32 %t27_i.05.i, 1
%t33.i = icmp slt i32 %t37.i, %bitround
br i1 %t33.i, label %while.body.t29.i, label %getNumPos.exit
getNumPos.exit: ; preds = %while.body.t29.i
%t39.i = srem i32 %t35.i, 16
%2 = sext i32 %t39.i to i64
%t73 = getelementptr i32, ptr %t48, i64 %2
%t74 = load i32, ptr %t73, align 4
br label %while.body.t29.i22
while.body.t29.i22: ; preds = %getNumPos.exit, %while.body.t29.i22
%t27_i.05.i23 = phi i32 [ %t37.i26, %while.body.t29.i22 ], [ 0, %getNumPos.exit ]
%t24.04.i24 = phi i32 [ %t35.i25, %while.body.t29.i22 ], [ %t70, %getNumPos.exit ]
%t35.i25 = sdiv i32 %t24.04.i24, 16
%t37.i26 = add nuw nsw i32 %t27_i.05.i23, 1
%t33.i27 = icmp slt i32 %t37.i26, %bitround
br i1 %t33.i27, label %while.body.t29.i22, label %getNumPos.exit28.loopexit
getNumPos.exit28.loopexit: ; preds = %while.body.t29.i22
%.pre114 = srem i32 %t35.i25, 16
%.pre115 = sext i32 %.pre114 to i64
br label %getNumPos.exit28
getNumPos.exit28: ; preds = %getNumPos.exit28.loopexit, %getNumPos.exit.thread
%.pre-phi116 = phi i64 [ %.pre115, %getNumPos.exit28.loopexit ], [ %1, %getNumPos.exit.thread ]
%t7584.in = phi i32 [ %t74, %getNumPos.exit28.loopexit ], [ %t7482, %getNumPos.exit.thread ]
%t7584 = add i32 %t7584.in, 1
%t81 = getelementptr i32, ptr %t48, i64 %.pre-phi116
store i32 %t7584, ptr %t81, align 4
%t83 = add nsw i32 %storemerge97, 1
%t67 = icmp slt i32 %t83, %r
br i1 %t67, label %while.body.t63, label %while.exit.t64
while.exit.t64: ; preds = %getNumPos.exit28, %while.cond.t62.preheader
store i32 %l, ptr %t43, align 4
%t88 = load i32, ptr %t48, align 4
%t89 = add i32 %t88, %l
store i32 %t89, ptr %t46, align 4
%invariant.gep = getelementptr i32, ptr %t46, i64 -1
%t101 = getelementptr i32, ptr %t43, i64 1
store i32 %t89, ptr %t101, align 4
%t106 = getelementptr i32, ptr %t48, i64 1
%t107 = load i32, ptr %t106, align 4
%t108 = add i32 %t107, %t89
%t110 = getelementptr i32, ptr %t46, i64 1
store i32 %t108, ptr %t110, align 4
%t101.1 = getelementptr i32, ptr %t43, i64 2
store i32 %t108, ptr %t101.1, align 4
%t106.1 = getelementptr i32, ptr %t48, i64 2
%t107.1 = load i32, ptr %t106.1, align 4
%t108.1 = add i32 %t107.1, %t108
%t110.1 = getelementptr i32, ptr %t46, i64 2
store i32 %t108.1, ptr %t110.1, align 4
%t101.2 = getelementptr i32, ptr %t43, i64 3
store i32 %t108.1, ptr %t101.2, align 4
%t106.2 = getelementptr i32, ptr %t48, i64 3
%t107.2 = load i32, ptr %t106.2, align 4
%t108.2 = add i32 %t107.2, %t108.1
%t110.2 = getelementptr i32, ptr %t46, i64 3
store i32 %t108.2, ptr %t110.2, align 4
%t101.3 = getelementptr i32, ptr %t43, i64 4
store i32 %t108.2, ptr %t101.3, align 4
%t106.3 = getelementptr i32, ptr %t48, i64 4
%t107.3 = load i32, ptr %t106.3, align 4
%t108.3 = add i32 %t107.3, %t108.2
%t110.3 = getelementptr i32, ptr %t46, i64 4
store i32 %t108.3, ptr %t110.3, align 4
%t101.4 = getelementptr i32, ptr %t43, i64 5
store i32 %t108.3, ptr %t101.4, align 4
%t106.4 = getelementptr i32, ptr %t48, i64 5
%t107.4 = load i32, ptr %t106.4, align 4
%t108.4 = add i32 %t107.4, %t108.3
%t110.4 = getelementptr i32, ptr %t46, i64 5
store i32 %t108.4, ptr %t110.4, align 4
%t101.5 = getelementptr i32, ptr %t43, i64 6
store i32 %t108.4, ptr %t101.5, align 4
%t106.5 = getelementptr i32, ptr %t48, i64 6
%t107.5 = load i32, ptr %t106.5, align 4
%t108.5 = add i32 %t107.5, %t108.4
%t110.5 = getelementptr i32, ptr %t46, i64 6
store i32 %t108.5, ptr %t110.5, align 4
%t101.6 = getelementptr i32, ptr %t43, i64 7
store i32 %t108.5, ptr %t101.6, align 4
%t106.6 = getelementptr i32, ptr %t48, i64 7
%t107.6 = load i32, ptr %t106.6, align 4
%t108.6 = add i32 %t107.6, %t108.5
%t110.6 = getelementptr i32, ptr %t46, i64 7
store i32 %t108.6, ptr %t110.6, align 4
%t101.7 = getelementptr i32, ptr %t43, i64 8
store i32 %t108.6, ptr %t101.7, align 4
%t106.7 = getelementptr i32, ptr %t48, i64 8
%t107.7 = load i32, ptr %t106.7, align 4
%t108.7 = add i32 %t107.7, %t108.6
%t110.7 = getelementptr i32, ptr %t46, i64 8
store i32 %t108.7, ptr %t110.7, align 4
%t101.8 = getelementptr i32, ptr %t43, i64 9
store i32 %t108.7, ptr %t101.8, align 4
%t106.8 = getelementptr i32, ptr %t48, i64 9
%t107.8 = load i32, ptr %t106.8, align 4
%t108.8 = add i32 %t107.8, %t108.7
%t110.8 = getelementptr i32, ptr %t46, i64 9
store i32 %t108.8, ptr %t110.8, align 4
%t101.9 = getelementptr i32, ptr %t43, i64 10
store i32 %t108.8, ptr %t101.9, align 4
%t106.9 = getelementptr i32, ptr %t48, i64 10
%t107.9 = load i32, ptr %t106.9, align 4
%t108.9 = add i32 %t107.9, %t108.8
%t110.9 = getelementptr i32, ptr %t46, i64 10
store i32 %t108.9, ptr %t110.9, align 4
%t101.10 = getelementptr i32, ptr %t43, i64 11
store i32 %t108.9, ptr %t101.10, align 4
%t106.10 = getelementptr i32, ptr %t48, i64 11
%t107.10 = load i32, ptr %t106.10, align 4
%t108.10 = add i32 %t107.10, %t108.9
%t110.10 = getelementptr i32, ptr %t46, i64 11
store i32 %t108.10, ptr %t110.10, align 4
%t101.11 = getelementptr i32, ptr %t43, i64 12
store i32 %t108.10, ptr %t101.11, align 4
%t106.11 = getelementptr i32, ptr %t48, i64 12
%t107.11 = load i32, ptr %t106.11, align 4
%t108.11 = add i32 %t107.11, %t108.10
%t110.11 = getelementptr i32, ptr %t46, i64 12
store i32 %t108.11, ptr %t110.11, align 4
%t101.12 = getelementptr i32, ptr %t43, i64 13
store i32 %t108.11, ptr %t101.12, align 4
%t106.12 = getelementptr i32, ptr %t48, i64 13
%t107.12 = load i32, ptr %t106.12, align 4
%t108.12 = add i32 %t107.12, %t108.11
%t110.12 = getelementptr i32, ptr %t46, i64 13
store i32 %t108.12, ptr %t110.12, align 4
%t101.13 = getelementptr i32, ptr %t43, i64 14
store i32 %t108.12, ptr %t101.13, align 4
%t106.13 = getelementptr i32, ptr %t48, i64 14
%t107.13 = load i32, ptr %t106.13, align 4
%t108.13 = add i32 %t107.13, %t108.12
%t110.13 = getelementptr i32, ptr %t46, i64 14
store i32 %t108.13, ptr %t110.13, align 4
%t101.14 = getelementptr i32, ptr %t43, i64 15
store i32 %t108.13, ptr %t101.14, align 4
%t106.14 = getelementptr i32, ptr %t48, i64 15
%t107.14 = load i32, ptr %t106.14, align 4
%t108.14 = add i32 %t107.14, %t108.13
%t110.14 = getelementptr i32, ptr %t46, i64 15
store i32 %t108.14, ptr %t110.14, align 4
%t333.i29 = icmp sgt i32 %bitround, 0
br label %while.cond.t118.preheader
while.cond.t118.preheader: ; preds = %while.exit.t64, %while.exit.t120
%storemerge17104 = phi i32 [ 0, %while.exit.t64 ], [ %t180, %while.exit.t120 ]
%3 = zext nneg i32 %storemerge17104 to i64
%t122 = getelementptr i32, ptr %t43, i64 %3
%t125 = getelementptr i32, ptr %t46, i64 %3
%t123100 = load i32, ptr %t122, align 4
%t126101 = load i32, ptr %t125, align 4
%t127102 = icmp slt i32 %t123100, %t126101
br i1 %t127102, label %while.body.t119, label %while.exit.t120
while.body.t191.peel.next: ; preds = %while.exit.t120
store i32 %l, ptr %t43, align 4
%t187 = load i32, ptr %t48, align 4
%t188 = add i32 %t187, %l
store i32 %t188, ptr %t46, align 4
%t215 = add i32 %bitround, -1
%t218.peel.pre = load i32, ptr %t43, align 4
tail call void @radixSort(i32 %t215, ptr %a, i32 %t218.peel.pre, i32 %t188)
br label %merge.t196
while.body.t119: ; preds = %while.cond.t118.preheader, %while.exit.t136
%t123103 = phi i32 [ %t176, %while.exit.t136 ], [ %t123100, %while.cond.t118.preheader ]
%4 = sext i32 %t123103 to i64
%t132 = getelementptr i32, ptr %a, i64 %4
%t133 = load i32, ptr %t132, align 4
br label %while.cond.t134
while.exit.t120: ; preds = %while.exit.t136, %while.cond.t118.preheader
%t180 = add nuw nsw i32 %storemerge17104, 1
%t117 = icmp ult i32 %storemerge17104, 15
br i1 %t117, label %while.cond.t118.preheader, label %while.body.t191.peel.next
while.cond.t134: ; preds = %getNumPos.exit78, %while.body.t119
%t15099 = phi i32 [ %t150129, %getNumPos.exit78 ], [ %t133, %while.body.t119 ]
br i1 %t333.i29, label %while.body.t29.i32, label %getNumPos.exit38.thread
while.body.t29.i32: ; preds = %while.cond.t134, %while.body.t29.i32
%t27_i.05.i33 = phi i32 [ %t37.i36, %while.body.t29.i32 ], [ 0, %while.cond.t134 ]
%t24.04.i34 = phi i32 [ %t35.i35, %while.body.t29.i32 ], [ %t15099, %while.cond.t134 ]
%t35.i35 = sdiv i32 %t24.04.i34, 16
%t37.i36 = add nuw nsw i32 %t27_i.05.i33, 1
%t33.i37 = icmp slt i32 %t37.i36, %bitround
br i1 %t33.i37, label %while.body.t29.i32, label %getNumPos.exit38
getNumPos.exit38: ; preds = %while.body.t29.i32
%t39.i31 = srem i32 %t35.i35, 16
%t141.not = icmp eq i32 %t39.i31, %storemerge17104
br i1 %t141.not, label %while.exit.t136, label %while.body.t29.i42
getNumPos.exit38.thread: ; preds = %while.cond.t134
%t39.i3186 = srem i32 %t15099, 16
%t141.not87 = icmp eq i32 %t39.i3186, %storemerge17104
br i1 %t141.not87, label %while.exit.t136, label %getNumPos.exit48.thread
getNumPos.exit48.thread: ; preds = %getNumPos.exit38.thread
%5 = sext i32 %t39.i3186 to i64
%t147125 = getelementptr i32, ptr %t43, i64 %5
%t148126 = load i32, ptr %t147125, align 4
%6 = sext i32 %t148126 to i64
%t149127 = getelementptr i32, ptr %a, i64 %6
%t150128 = load i32, ptr %t149127, align 4
br label %getNumPos.exit68.thread
while.body.t29.i42: ; preds = %getNumPos.exit38, %while.body.t29.i42
%t27_i.05.i43 = phi i32 [ %t37.i46, %while.body.t29.i42 ], [ 0, %getNumPos.exit38 ]
%t24.04.i44 = phi i32 [ %t35.i45, %while.body.t29.i42 ], [ %t15099, %getNumPos.exit38 ]
%t35.i45 = sdiv i32 %t24.04.i44, 16
%t37.i46 = add nuw nsw i32 %t27_i.05.i43, 1
%t33.i47 = icmp slt i32 %t37.i46, %bitround
br i1 %t33.i47, label %while.body.t29.i42, label %getNumPos.exit48
getNumPos.exit48: ; preds = %while.body.t29.i42
%.pre117 = srem i32 %t35.i45, 16
%7 = sext i32 %.pre117 to i64
%t147 = getelementptr i32, ptr %t43, i64 %7
%t148 = load i32, ptr %t147, align 4
%8 = sext i32 %t148 to i64
%t149 = getelementptr i32, ptr %a, i64 %8
%t150 = load i32, ptr %t149, align 4
br i1 %t333.i29, label %while.body.t29.i52, label %getNumPos.exit68.thread
while.body.t29.i52: ; preds = %getNumPos.exit48, %while.body.t29.i52
%t27_i.05.i53 = phi i32 [ %t37.i56, %while.body.t29.i52 ], [ 0, %getNumPos.exit48 ]
%t24.04.i54 = phi i32 [ %t35.i55, %while.body.t29.i52 ], [ %t15099, %getNumPos.exit48 ]
%t35.i55 = sdiv i32 %t24.04.i54, 16
%t37.i56 = add nuw nsw i32 %t27_i.05.i53, 1
%t33.i57 = icmp slt i32 %t37.i56, %bitround
br i1 %t33.i57, label %while.body.t29.i52, label %while.body.t29.i62.preheader
while.body.t29.i62.preheader: ; preds = %while.body.t29.i52
%t39.i51 = srem i32 %t35.i55, 16
%9 = sext i32 %t39.i51 to i64
%t155 = getelementptr i32, ptr %t43, i64 %9
%t156 = load i32, ptr %t155, align 4
%10 = sext i32 %t156 to i64
%t157 = getelementptr i32, ptr %a, i64 %10
store i32 %t15099, ptr %t157, align 4
br label %while.body.t29.i62
getNumPos.exit68.thread: ; preds = %getNumPos.exit48, %getNumPos.exit48.thread
%t150130 = phi i32 [ %t150128, %getNumPos.exit48.thread ], [ %t150, %getNumPos.exit48 ]
%t39.i51.c = srem i32 %t15099, 16
%11 = sext i32 %t39.i51.c to i64
%t155.c = getelementptr i32, ptr %t43, i64 %11
%t156.c = load i32, ptr %t155.c, align 4
%12 = sext i32 %t156.c to i64
%t157.c = getelementptr i32, ptr %a, i64 %12
store i32 %t15099, ptr %t157.c, align 4
%t16191 = getelementptr i32, ptr %t43, i64 %11
%t16292 = load i32, ptr %t16191, align 4
br label %getNumPos.exit78
while.body.t29.i62: ; preds = %while.body.t29.i62.preheader, %while.body.t29.i62
%t27_i.05.i63 = phi i32 [ %t37.i66, %while.body.t29.i62 ], [ 0, %while.body.t29.i62.preheader ]
%t24.04.i64 = phi i32 [ %t35.i65, %while.body.t29.i62 ], [ %t15099, %while.body.t29.i62.preheader ]
%t35.i65 = sdiv i32 %t24.04.i64, 16
%t37.i66 = add nuw nsw i32 %t27_i.05.i63, 1
%t33.i67 = icmp slt i32 %t37.i66, %bitround
br i1 %t33.i67, label %while.body.t29.i62, label %getNumPos.exit68
getNumPos.exit68: ; preds = %while.body.t29.i62
%t39.i61 = srem i32 %t35.i65, 16
%13 = sext i32 %t39.i61 to i64
%t161 = getelementptr i32, ptr %t43, i64 %13
%t162 = load i32, ptr %t161, align 4
br label %while.body.t29.i72
while.body.t29.i72: ; preds = %getNumPos.exit68, %while.body.t29.i72
%t27_i.05.i73 = phi i32 [ %t37.i76, %while.body.t29.i72 ], [ 0, %getNumPos.exit68 ]
%t24.04.i74 = phi i32 [ %t35.i75, %while.body.t29.i72 ], [ %t15099, %getNumPos.exit68 ]
%t35.i75 = sdiv i32 %t24.04.i74, 16
%t37.i76 = add nuw nsw i32 %t27_i.05.i73, 1
%t33.i77 = icmp slt i32 %t37.i76, %bitround
br i1 %t33.i77, label %while.body.t29.i72, label %getNumPos.exit78.loopexit
getNumPos.exit78.loopexit: ; preds = %while.body.t29.i72
%.pre118 = srem i32 %t35.i75, 16
%.pre119 = sext i32 %.pre118 to i64
br label %getNumPos.exit78
getNumPos.exit78: ; preds = %getNumPos.exit78.loopexit, %getNumPos.exit68.thread
%t150129 = phi i32 [ %t150, %getNumPos.exit78.loopexit ], [ %t150130, %getNumPos.exit68.thread ]
%.pre-phi120 = phi i64 [ %.pre119, %getNumPos.exit78.loopexit ], [ %11, %getNumPos.exit68.thread ]
%t16394.in = phi i32 [ %t162, %getNumPos.exit78.loopexit ], [ %t16292, %getNumPos.exit68.thread ]
%t16394 = add i32 %t16394.in, 1
%t167 = getelementptr i32, ptr %t43, i64 %.pre-phi120
store i32 %t16394, ptr %t167, align 4
br label %while.cond.t134
while.exit.t136: ; preds = %getNumPos.exit38.thread, %getNumPos.exit38
%t171 = load i32, ptr %t122, align 4
%14 = sext i32 %t171 to i64
%t172 = getelementptr i32, ptr %a, i64 %14
store i32 %t15099, ptr %t172, align 4
%t175 = load i32, ptr %t122, align 4
%t176 = add i32 %t175, 1
store i32 %t176, ptr %t122, align 4
%t126 = load i32, ptr %t125, align 4
%t127 = icmp slt i32 %t176, %t126
br i1 %t127, label %while.body.t119, label %while.exit.t120
merge.t196: ; preds = %while.body.t191.peel.next, %merge.t196
%storemerge18107 = phi i32 [ 1, %while.body.t191.peel.next ], [ %t224, %merge.t196 ]
%15 = zext nneg i32 %storemerge18107 to i64
%gep106 = getelementptr i32, ptr %invariant.gep, i64 %15
%t202 = load i32, ptr %gep106, align 4
%t204 = getelementptr i32, ptr %t43, i64 %15
store i32 %t202, ptr %t204, align 4
%t209 = getelementptr i32, ptr %t48, i64 %15
%t210 = load i32, ptr %t209, align 4
%t211 = add i32 %t210, %t202
%t213 = getelementptr i32, ptr %t46, i64 %15
store i32 %t211, ptr %t213, align 4
%t218.pre = load i32, ptr %t204, align 4
tail call void @radixSort(i32 %t215, ptr %a, i32 %t218.pre, i32 %t211)
%t224 = add nuw nsw i32 %storemerge18107, 1
%t194 = icmp ult i32 %storemerge18107, 15
br i1 %t194, label %merge.t196, label %cleanup.t44, !llvm.loop !0
}
define noundef i32 @main() local_unnamed_addr {
entry:
%t231 = tail call i32 @getarray(ptr nonnull @a)
tail call void @starttime()
tail call void @radixSort(i32 8, ptr nonnull @a, i32 0, i32 %t231)
%ans.promoted = load i32, ptr @ans, align 4
%t2427 = icmp sgt i32 %t231, 0
br i1 %t2427, label %while.body.t238, label %while.exit.t239
while.body.t238: ; preds = %entry, %while.body.t238
%t236_i.09 = phi i32 [ %t254, %while.body.t238 ], [ 0, %entry ]
%t25268 = phi i32 [ %t252, %while.body.t238 ], [ %ans.promoted, %entry ]
%0 = zext nneg i32 %t236_i.09 to i64
%t246 = getelementptr [30000010 x i32], ptr @a, i64 0, i64 %0
%t247 = load i32, ptr %t246, align 4
%t249 = add nuw i32 %t236_i.09, 2
%t250 = srem i32 %t247, %t249
%t251 = mul i32 %t250, %t236_i.09
%t252 = add i32 %t251, %t25268
%t254 = add nuw nsw i32 %t236_i.09, 1
%t242 = icmp slt i32 %t254, %t231
br i1 %t242, label %while.body.t238, label %while.cond.t237.while.exit.t239_crit_edge
while.cond.t237.while.exit.t239_crit_edge: ; preds = %while.body.t238
store i32 %t252, ptr @ans, align 4
br label %while.exit.t239
while.exit.t239: ; preds = %while.cond.t237.while.exit.t239_crit_edge, %entry
%t257 = phi i32 [ %t252, %while.cond.t237.while.exit.t239_crit_edge ], [ %ans.promoted, %entry ]
%t258 = icmp slt i32 %t257, 0
br i1 %t258, label %then.t255, label %merge.t256
then.t255: ; preds = %while.exit.t239
%t260 = sub i32 0, %t257
store i32 %t260, ptr @ans, align 4
br label %merge.t256
merge.t256: ; preds = %then.t255, %while.exit.t239
tail call void @stoptime()
%t262 = load i32, ptr @ans, align 4
tail call void @putint(i32 %t262)
tail call void @putch(i32 10)
ret i32 0
}
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.smax.i32(i32, i32) #2
attributes #0 = { nofree norecurse nosync nounwind memory(argmem: read) }
attributes #1 = { nofree norecurse nosync nounwind memory(none) }
attributes #2 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
!0 = distinct !{!0, !1}
!1 = !{!"llvm.loop.peeled.count", i32 1}

@ -35,7 +35,7 @@ total=0
passed=0
failed=0
echo "开始测试 SysY 解析..."
echo "开始测试 ir out 解析..."
echo "输出将保存到 $RESULT_FILE"
echo "------------------------"
@ -59,10 +59,12 @@ for file in "${TEST_FILES[@]}"; do
echo "========== $file ==========" >> "$RESULT_FILE"
if [ $VERBOSE -eq 1 ]; then
"$COMPILER" --emit-parse-tree "$file" 2>&1 | tee -a "$RESULT_FILE"
# "$COMPILER" --emit-parse-tree "$file" 2>&1 | tee -a "$RESULT_FILE"
"$COMPILER" --emit-ir "$file" 2>&1 | tee -a "$RESULT_FILE"
result=${PIPESTATUS[0]}
else
"$COMPILER" --emit-parse-tree "$file" >> "$RESULT_FILE" 2>&1
# "$COMPILER" --emit-parse-tree "$file" >> "$RESULT_FILE" 2>&1
"$COMPILER" --emit-ir "$file" >> "$RESULT_FILE" 2>&1
result=$?
fi

@ -0,0 +1,233 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
COMPILER="$ROOT_DIR/build/bin/compiler"
TMP_DIR="$ROOT_DIR/build/test_compiler"
RESULT_BASE_DIR="$ROOT_DIR/test/test_result"
TEST_DIRS=("$ROOT_DIR/test/test_case/functional" "$ROOT_DIR/test/test_case/performance")
CC_BIN="${CC:-cc}"
RUNTIME_SRC="$ROOT_DIR/sylib/sylib.c"
RUNTIME_OBJ="$TMP_DIR/sylib.o"
LLC_BIN="${LLC:-llc}"
CLANG_BIN="${CLANG:-clang}"
if [[ ! -x "$COMPILER" ]]; then
echo "未找到编译器: $COMPILER"
echo "请先构建编译器,例如: mkdir -p build && cd build && cmake .. && make -j"
exit 1
fi
mkdir -p "$TMP_DIR"
if ! command -v "$LLC_BIN" >/dev/null 2>&1; then
echo "未找到 llc: $LLC_BIN"
echo "请安装 LLVM或通过 LLC 环境变量指定 llc 路径"
exit 1
fi
if ! command -v "$CLANG_BIN" >/dev/null 2>&1; then
echo "未找到 clang: $CLANG_BIN"
echo "请安装 Clang或通过 CLANG 环境变量指定 clang 路径"
exit 1
fi
# 编译运行库(供链接生成的可执行文件)
runtime_ready=0
if [[ -f "$RUNTIME_SRC" ]]; then
if "$CC_BIN" -c "$RUNTIME_SRC" -o "$RUNTIME_OBJ" >/dev/null 2>&1; then
runtime_ready=1
else
echo "[WARN] 运行库编译失败,生成的可执行文件将不链接 sylib: $RUNTIME_SRC"
fi
else
echo "[WARN] 未找到运行库源码: $RUNTIME_SRC"
fi
ir_total=0
ir_pass=0
result_total=0
result_pass=0
ir_failures=()
result_failures=()
function normalize_file() {
sed 's/\r$//' "$1"
}
for test_dir in "${TEST_DIRS[@]}"; do
if [[ ! -d "$test_dir" ]]; then
echo "跳过不存在的测试目录: $test_dir"
continue
fi
shopt -s nullglob
for input in "$test_dir"/*.sy; do
ir_total=$((ir_total+1))
base=$(basename "$input")
stem=${base%.sy}
case "$(basename "$test_dir")" in
functional)
out_dir="$RESULT_BASE_DIR/functional/ir"
;;
performance)
out_dir="$RESULT_BASE_DIR/performance/ir"
;;
*)
out_dir="$RESULT_BASE_DIR/$(basename "$test_dir")"
;;
esac
mkdir -p "$out_dir"
ll_file="$out_dir/$stem.ll"
stdout_file="$out_dir/$stem.stdout"
expected_file="$test_dir/$stem.out"
stdin_file="$test_dir/$stem.in"
echo "[TEST] $input"
# 编译并捕获所有输出
compiler_status=0
compiler_output=""
compiler_output=$("$COMPILER" --emit-ir "$input" 2>&1) || compiler_status=$?
# 临时文件存储原始输出
raw_ll="$out_dir/$stem.raw.ll"
printf '%s\n' "$compiler_output" > "$raw_ll"
# 检查编译是否成功
if [[ $compiler_status -ne 0 ]]; then
echo " [IR] 编译失败: 返回码 $compiler_status"
ir_failures+=("$input: compiler failed ($compiler_status)")
# 失败:保留原始输出(包含所有调试信息)
cp "$raw_ll" "$ll_file"
rm -f "$raw_ll"
continue
fi
# 从混杂输出中提取 IR
# - 顶层实体define/declare/@global
# - 基本块标签
# - 缩进的指令行
# - 函数结束花括号
grep -E '^(define |declare |@|[[:space:]]|})|^[A-Za-z_.$%][A-Za-z0-9_.$%]*:$' "$raw_ll" > "$ll_file"
# 检查是否生成了有效函数定义
if ! grep -qE '^define ' "$ll_file"; then
echo " [IR] 失败: 未生成有效函数定义"
ir_failures+=("$input: invalid IR output")
# 失败:保留原始输出
cp "$raw_ll" "$ll_file"
rm -f "$raw_ll"
continue
fi
# 可选:删除多余的空行
sed -i '/^$/N;/\n$/D' "$ll_file"
rm -f "$raw_ll"
ir_pass=$((ir_pass+1))
echo " [IR] 生成成功 (IR已保存到: $ll_file)"
# 运行测试
# 运行测试部分
if [[ -f "$expected_file" ]]; then
result_total=$((result_total+1))
# 运行生成的可执行文件(优先链接运行库)
run_status=0
obj_file="$out_dir/$stem.o"
exe_file="$out_dir/$stem"
if ! "$LLC_BIN" -filetype=obj "$ll_file" -o "$obj_file" > "$stdout_file" 2>&1; then
echo " [RUN] llc 失败"
result_failures+=("$input: llc failed")
continue
fi
if [[ $runtime_ready -eq 1 ]]; then
if ! "$CLANG_BIN" "$obj_file" "$RUNTIME_OBJ" -o "$exe_file" >> "$stdout_file" 2>&1; then
echo " [RUN] clang 链接失败"
result_failures+=("$input: clang link failed")
continue
fi
else
if ! "$CLANG_BIN" "$obj_file" -o "$exe_file" >> "$stdout_file" 2>&1; then
echo " [RUN] clang 链接失败"
result_failures+=("$input: clang link failed")
continue
fi
fi
if [[ -f "$stdin_file" ]]; then
"$exe_file" < "$stdin_file" > "$stdout_file" 2>&1 || run_status=$?
else
"$exe_file" > "$stdout_file" 2>&1 || run_status=$?
fi
# 读取预期文件内容
expected_content=$(normalize_file "$expected_file")
# 判断预期文件是只包含退出码,还是包含输出+退出码
if [[ "$expected_content" =~ ^[0-9]+$ ]]; then
# 只包含退出码
expected=$expected_content
if [[ "$run_status" -eq "$expected" ]]; then
result_pass=$((result_pass+1))
echo " [RUN] 返回值匹配: $run_status"
rm -f "$stdout_file"
else
echo " [RUN] 返回值不匹配: got $run_status, expected $expected"
result_failures+=("$input: exit code mismatch (got $run_status, expected $expected)")
fi
else
# 包含输出和退出码(最后一行是退出码)
expected_output=$(head -n -1 <<< "$expected_content")
expected_exit=$(tail -n 1 <<< "$expected_content")
actual_output=$(cat "$stdout_file")
if [[ "$run_status" -eq "$expected_exit" ]] && [[ "$actual_output" == "$expected_output" ]]; then
result_pass=$((result_pass+1))
echo " [RUN] 成功: 退出码和输出都匹配"
rm -f "$stdout_file"
else
echo " [RUN] 不匹配: 退出码 got $run_status, expected $expected_exit"
if [[ "$actual_output" != "$expected_output" ]]; then
echo " 输出不匹配"
fi
result_failures+=("$input: mismatch")
fi
fi
else
echo " [RUN] 未找到预期返回值文件 $expected_file,跳过结果验证"
fi
done
shopt -u nullglob
done
# 输出统计
cat <<EOF
测试完成。
IR 生成: $ir_pass / $ir_total
结果匹配: $result_pass / $result_total
EOF
# 输出失败列表
if [[ ${#ir_failures[@]} -gt 0 ]]; then
echo ""
echo "IR 失败列表:"
for item in "${ir_failures[@]}"; do
echo " $item"
done
fi
if [[ ${#result_failures[@]} -gt 0 ]]; then
echo ""
echo "结果失败列表:"
for item in "${result_failures[@]}"; do
echo " $item"
done
echo ""
echo "失败的测试文件已保留在: $TMP_DIR"
echo "可以查看对应的.ll文件进行调试"
fi

@ -0,0 +1,167 @@
#!/bin/bash
# 测试脚本(支持动态输出目录)
# 用法: ./run_tests.sh [--verbose] [--mode <模式>] [<单个测试文件>]
# 模式: parse-tree, ir, asm, run (默认 run)
COMPILER="./build/bin/compiler"
TEST_SCRIPT="./scripts/verify_asm.sh"
TEST_DIR="test/test_case"
RESULT_FILE="result.txt"
VERBOSE=0
MODE="run" # 默认模式为完整测试
# 解析参数
while [[ $# -gt 0 ]]; do
case "$1" in
--verbose|-v)
VERBOSE=1
shift
;;
--mode)
MODE="$2"
shift 2
;;
--emit-parse-tree)
MODE="parse-tree"
shift
;;
--emit-ir)
MODE="ir"
shift
;;
--emit-asm)
MODE="asm"
shift
;;
--run)
MODE="run"
shift
;;
-*)
echo "未知选项: $1"
exit 1
;;
*)
# 非选项参数视为测试文件
SINGLE_FILE="$1"
shift
;;
esac
done
# 检查编译器是否存在
if [ ! -f "$COMPILER" ]; then
echo "错误: 编译器未找到于 $COMPILER"
echo "请先完成项目构建 (cmake 和 make)"
exit 1
fi
# 如果是 run 模式,检查测试脚本是否存在
if [ "$MODE" = "run" ] && [ ! -f "$TEST_SCRIPT" ]; then
echo "错误: 测试脚本未找到于 $TEST_SCRIPT"
exit 1
fi
# 如果指定了单个文件,检查文件是否存在
if [ -n "$SINGLE_FILE" ] && [ ! -f "$SINGLE_FILE" ]; then
echo "错误: 文件 $SINGLE_FILE 不存在"
exit 1
fi
# 清空(或创建)结果文件
> "$RESULT_FILE"
# 计数器
total=0
passed=0
failed=0
echo "开始测试 (模式: $MODE)..."
echo "输出将保存到 $RESULT_FILE"
echo "------------------------"
# 确定测试文件列表
if [ -n "$SINGLE_FILE" ]; then
TEST_FILES=("$SINGLE_FILE")
else
mapfile -t TEST_FILES < <(find "$TEST_DIR" -type f -name "*.sy" | sort)
fi
# 根据模式执行测试
for file in "${TEST_FILES[@]}"; do
((total++))
if [ $VERBOSE -eq 1 ]; then
echo "测试文件: $file"
else
echo -n "测试 $file ... "
fi
echo "========== $file ==========" >> "$RESULT_FILE"
# 根据模式构建命令
case "$MODE" in
parse-tree)
cmd="$COMPILER --emit-parse-tree \"$file\""
;;
ir)
cmd="$COMPILER --emit-ir \"$file\""
;;
asm)
cmd="$COMPILER --emit-asm \"$file\""
;;
run)
# 根据输入文件所在子目录确定输出目录
# 提取 test/test_case/ 之后的子目录名functional 或 performance
rel_path="${file#$TEST_DIR/}"
subdir=$(echo "$rel_path" | cut -d'/' -f1)
if [[ "$subdir" != "functional" && "$subdir" != "performance" ]]; then
echo "警告: 未知子目录 $subdir,使用默认输出目录" >> "$RESULT_FILE"
out_dir="test/test_result/asm"
else
out_dir="test/test_result/$subdir/asm"
fi
cmd="$TEST_SCRIPT \"$file\" \"$out_dir\" --run"
;;
*)
echo "未知模式: $MODE" >&2
exit 1
;;
esac
if [ $VERBOSE -eq 1 ]; then
eval "$cmd" 2>&1 | tee -a "$RESULT_FILE"
result=${PIPESTATUS[0]}
else
eval "$cmd" >> "$RESULT_FILE" 2>&1
result=$?
fi
echo "" >> "$RESULT_FILE"
if [ $result -eq 0 ]; then
if [ $VERBOSE -eq 0 ]; then
echo "通过"
fi
((passed++))
else
if [ $VERBOSE -eq 0 ]; then
echo "失败"
else
echo ">>> 测试失败: $file"
fi
((failed++))
fi
done
echo "------------------------"
echo "总计: $total"
echo "通过: $passed"
echo "失败: $failed"
echo "详细输出已保存至 $RESULT_FILE"
if [ $failed -gt 0 ]; then
exit 1
else
exit 0
fi

@ -52,7 +52,8 @@ expected_file="$input_dir/$stem.out"
"$compiler" --emit-asm "$input" > "$asm_file"
echo "汇编已生成: $asm_file"
aarch64-linux-gnu-gcc "$asm_file" -o "$exe"
# 静态链接
aarch64-linux-gnu-gcc -no-pie "$asm_file" -L./sylib -lsysy -static -o "$exe"
echo "可执行文件已生成: $exe"
if [[ "$run_exec" == true ]]; then

@ -43,9 +43,6 @@ R_BRACK : ']';
L_BRACE : '{';
R_BRACE : '}';
//const numeric classes
//Number... change
// float first
// 16进制float first
HEX_FLOAT
: '0' [xX](
@ -72,18 +69,8 @@ HEX_INT: '0' [xX] [0-9a-fA-F]+; //16进制
OCTAL_INT: '0' [0-7]*; //8进制
DECIMAL_INT: [1-9][0-9]*; //10进制
ZERO: '0'; //单独0
// TODO: 后续完善IR后移除Number兼容规则
Number
: HEX_FLOAT
| DEC_FLOAT
| HEX_INT
| OCTAL_INT
| DECIMAL_INT
| ZERO
;
// 标识符(放最后)
// 标识符
Ident
: [a-zA-Z_][a-zA-Z_0-9]*
;
@ -103,11 +90,7 @@ BLOCK_COMMENT
//----语法规则----//
compUnit
: (funcDef|decl|program) EOF
;
program
: (decl|funcDef)+
: (funcDef|decl)+ EOF
;
decl
@ -135,7 +118,6 @@ constInitVal
varDecl
: bType varDef (Comma varDef)* Semi
| Int Ident (Assign exp)? Semi
;
varDef
@ -182,11 +164,7 @@ stmt
| While L_PAREN cond R_PAREN stmt
| Break Semi
| Continue Semi
| returnStmt
;
returnStmt
: Return (exp)? Semi
| Return (exp)? Semi
;
exp
@ -201,21 +179,19 @@ lVal
: Ident (L_BRACK exp R_BRACK)*
;
primary
primaryExp
: L_PAREN exp R_PAREN
| lVal
| Number // 让旧代码能用
| HEX_FLOAT
| DEC_FLOAT
| HEX_INT
| OCTAL_INT
| DECIMAL_INT
| ZERO
| Ident
;
unaryExp
: primary
: primaryExp
| Ident L_PAREN (funcRParams)? R_PAREN
| unaryOp unaryExp
;
@ -238,7 +214,6 @@ mulExp
addExp
: mulExp
| addExp (AddOp|SubOp) mulExp
| primary (AddOp primary)*
;
relExp
@ -263,4 +238,4 @@ lOrExp
constExp
: addExp
;
;

@ -1,7 +1,8 @@
// 管理基础类型、整型常量池和临时名生成。
// ir/IR.cpp
#include "ir/IR.h"
#include <cstring>
#include <sstream>
#include <functional>
namespace ir {
@ -15,10 +16,112 @@ ConstantInt* Context::GetConstInt(int v) {
return inserted->second.get();
}
ConstantFloat* Context::GetConstFloat(float v) {
uint32_t key;
std::memcpy(&key, &v, sizeof(float));
auto it = const_floats_.find(key);
if (it != const_floats_.end()) {
return it->second.get();
}
auto float_ty = Type::GetFloatType();
auto constant = std::make_unique<ConstantFloat>(float_ty, v);
auto* ptr = constant.get();
const_floats_[key] = std::move(constant);
return ptr;
}
ConstantArray* Context::GetConstArray(std::shared_ptr<ArrayType> ty,
std::vector<ConstantValue*> elements) {
// 验证数组常量
size_t expected_size = ty->GetElementCount();
if (elements.size() != expected_size) {
// 如果元素数量不匹配,可能需要补零或报错
// 这里根据需求处理
if (elements.size() < expected_size) {
// 补零
auto elem_type = ty->GetElementType();
while (elements.size() < expected_size) {
if (elem_type->IsInt32()) {
elements.push_back(GetConstInt(0));
} else if (elem_type->IsFloat()) {
elements.push_back(GetConstFloat(0.0f));
}
}
} else {
throw std::runtime_error("Array constant size mismatch");
}
}
// 构建缓存键
struct ArrayKey {
std::shared_ptr<ArrayType> type;
std::vector<ConstantValue*> elements;
bool operator==(const ArrayKey& other) const {
if (type != other.type) return false;
if (elements.size() != other.elements.size()) return false;
for (size_t i = 0; i < elements.size(); ++i) {
if (elements[i] != other.elements[i]) return false;
}
return true;
}
};
struct ArrayKeyHash {
size_t operator()(const ArrayKey& key) const {
size_t hash = std::hash<Type*>{}(key.type.get());
for (auto* elem : key.elements) {
hash ^= std::hash<ConstantValue*>{}(elem) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
}
return hash;
}
};
// 使用静态缓存(需要作为成员变量)
static std::unordered_map<ArrayKey, std::unique_ptr<ConstantArray>, ArrayKeyHash> cache;
ArrayKey key{ty, elements};
auto it = cache.find(key);
if (it != cache.end()) {
return it->second.get();
}
auto constant = std::make_unique<ConstantArray>(ty, std::move(elements));
auto* ptr = constant.get();
cache[std::move(key)] = std::move(constant);
return ptr;
}
ConstantZero* Context::GetZeroConstant(std::shared_ptr<Type> ty) {
auto it = zero_constants_.find(ty.get());
if (it != zero_constants_.end()) {
return it->second.get();
}
auto constant = std::make_unique<ConstantZero>(ty);
auto* ptr = constant.get();
zero_constants_[ty.get()] = std::move(constant);
return ptr;
}
ConstantAggregateZero* Context::GetAggregateZero(std::shared_ptr<Type> ty) {
auto it = aggregate_zeros_.find(ty.get());
if (it != aggregate_zeros_.end()) {
return it->second.get();
}
auto constant = std::make_unique<ConstantAggregateZero>(ty);
auto* ptr = constant.get();
aggregate_zeros_[ty.get()] = std::move(constant);
return ptr;
}
std::string Context::NextTemp() {
std::ostringstream oss;
oss << "%" << ++temp_index_;
oss << "%t" << ++temp_index_;
return oss.str();
}
} // namespace ir
} // namespace ir

@ -5,10 +5,21 @@
namespace ir {
Function::Function(std::string name, std::shared_ptr<Type> ret_type)
: Value(std::move(ret_type), std::move(name)) {
Function::Function(std::string name, std::shared_ptr<FunctionType> func_type)
: Value(std::move(func_type), std::move(name)) {
entry_ = CreateBlock("entry");
}
// 向函数添加参数的实现。
Argument* Function::AddArgument(std::unique_ptr<Argument> arg) {// 独占所有权,自动释放内存
if (!arg) return nullptr; // 1. 检查参数是否为空
auto* ptr = arg.get(); // 2. 获取原始指针(用于返回)
arguments_.push_back(std::move(arg)); // 3. 将参数所有权转移到函数的参数列表中,arg已经是空指针了不能再使用arg了
return ptr; // 4. 返回参数指针,方便调用者使用
}
// 获取函数参数列表的实现。
const std::vector<std::unique_ptr<Argument>>& Function::GetArguments() const {
return arguments_;
}
BasicBlock* Function::CreateBlock(const std::string& name) {
auto block = std::make_unique<BasicBlock>(name);

@ -1,11 +1,195 @@
// GlobalValue 占位实现:
// - 具体的全局初始化器、打印和链接语义需要自行补全
// ir/GlobalValue.cpp
#include "ir/IR.h"
#include <stdexcept>
namespace ir {
namespace {
ConstantValue* GetScalarZeroConstant(const Type& type) {
if (type.IsInt32()) {
static ConstantInt* zero_i32 = new ConstantInt(Type::GetInt32Type(), 0);
return zero_i32;
}
if (type.IsFloat()) {
static ConstantFloat* zero_f32 = new ConstantFloat(Type::GetFloatType(), 0.0f);
return zero_f32;
}
if (type.IsInt1()) {
static ConstantInt* zero_i1 = new ConstantInt(Type::GetInt1Type(), 0);
return zero_i1;
}
return nullptr;
}
} // namespace
GlobalValue::GlobalValue(std::shared_ptr<Type> ty, std::string name)
: User(std::move(ty), std::move(name)) {}
} // namespace ir
void GlobalValue::SetInitializer(ConstantValue* init) {
if (!init) {
throw std::runtime_error("GlobalValue::SetInitializer: init is null");
}
// 获取实际的值类型(用于类型检查)
std::shared_ptr<Type> value_type = GetValueType();
// 类型检查
bool type_match = CheckTypeCompatibility(value_type, init);
if (!type_match) {
throw std::runtime_error("GlobalValue::SetInitializer: type mismatch");
}
initializer_.clear();
initializer_.push_back(init);
}
void GlobalValue::SetInitializer(const std::vector<ConstantValue*>& init) {
if (init.empty()) {
initializer_.clear();
return;
}
// 获取实际的值类型
std::shared_ptr<Type> value_type = GetValueType();
// 类型检查
if (value_type->IsArray()) {
auto* array_ty = static_cast<ArrayType*>(value_type.get());
size_t array_size = array_ty->GetElementCount();
if (init.size() > array_size) {
throw std::runtime_error("GlobalValue::SetInitializer: too many initializers");
}
// 检查每个初始化值的类型
auto* elem_type = array_ty->GetElementType().get();
for (size_t i = 0; i < init.size(); ++i) {
auto* elem = init[i];
if (!elem) {
throw std::runtime_error("GlobalValue::SetInitializer: null initializer at index " + std::to_string(i));
}
bool elem_match = false;
if (elem_type->IsInt32() && elem->GetType()->IsInt32()) {
elem_match = true;
} else if (elem_type->IsFloat() && elem->GetType()->IsFloat()) {
elem_match = true;
} else if (elem_type->IsInt1() && elem->GetType()->IsInt1()) {
elem_match = true;
}
if (!elem_match) {
throw std::runtime_error("GlobalValue::SetInitializer: element type mismatch at index " + std::to_string(i));
}
}
}
else if (value_type->IsInt32() || value_type->IsFloat() || value_type->IsInt1()) {
if (init.size() != 1) {
throw std::runtime_error("GlobalValue::SetInitializer: scalar requires exactly one initializer");
}
if (!init[0]) {
throw std::runtime_error("GlobalValue::SetInitializer: null initializer");
}
if ((value_type->IsInt32() && !init[0]->GetType()->IsInt32()) ||
(value_type->IsFloat() && !init[0]->GetType()->IsFloat()) ||
(value_type->IsInt1() && !init[0]->GetType()->IsInt1())) {
throw std::runtime_error("GlobalValue::SetInitializer: type mismatch");
}
}
else {
throw std::runtime_error("GlobalValue::SetInitializer: unsupported type");
}
initializer_ = init;
}
// 辅助方法:获取实际的值类型(处理指针包装)
std::shared_ptr<Type> GlobalValue::GetValueType() const {
if (GetType()->IsPtrInt32()) {
return Type::GetInt32Type();
} else if (GetType()->IsPtrFloat()) {
return Type::GetFloatType();
} else if (GetType()->IsPtrInt1()) {
return Type::GetInt1Type();
}
return GetType();
}
// 辅助方法:检查类型兼容性
bool GlobalValue::CheckTypeCompatibility(std::shared_ptr<Type> value_type,
ConstantValue* init) const {
// 检查标量类型
if (value_type->IsInt32() && init->GetType()->IsInt32()) {
return true;
} else if (value_type->IsFloat() && init->GetType()->IsFloat()) {
return true;
} else if (value_type->IsInt1() && init->GetType()->IsInt1()) {
return true;
}
// 检查数组类型:允许用单个标量初始化整个数组
else if (value_type->IsArray()) {
auto* array_ty = static_cast<ArrayType*>(value_type.get());
auto* elem_type = array_ty->GetElementType().get();
if (elem_type->IsInt32() && init->GetType()->IsInt32()) {
return true;
} else if (elem_type->IsFloat() && init->GetType()->IsFloat()) {
return true;
} else if (elem_type->IsInt1() && init->GetType()->IsInt1()) {
return true;
}
// 也可以允许 ConstantArray 作为初始化器
else if (init->GetType()->IsArray()) {
auto* init_array = static_cast<ConstantArray*>(init);
return init_array->IsValid();
}
}
// 检查指针类型(用于数组参数)
else if (value_type->IsPtrInt32() && init->GetType()->IsInt32()) {
return true;
} else if (value_type->IsPtrFloat() && init->GetType()->IsFloat()) {
return true;
}
return false;
}
// 添加获取数组元素的便捷方法
ConstantValue* GlobalValue::GetArrayElement(size_t index) const {
if (!GetType()->IsArray()) {
return nullptr;
}
auto* array_ty = dynamic_cast<ArrayType*>(GetType().get());
if (!array_ty) {
return nullptr;
}
if (index >= static_cast<size_t>(array_ty->GetElementCount())) {
return nullptr;
}
if (index >= initializer_.size()) {
return GetScalarZeroConstant(*array_ty->GetElementType());
}
return initializer_[index];
}
// 添加获取数组元素数量的方法
size_t GlobalValue::GetArraySize() const {
if (!IsArrayConstant()) {
return 0;
}
return initializer_.size();
}
// 添加判断是否为数组常量的方法
bool GlobalValue::IsArrayConstant() const {
return GetType()->IsArray() && !initializer_.empty();
}
} // namespace ir

@ -5,7 +5,7 @@
#include "ir/IR.h"
#include <stdexcept>
#include <cstring>
#include "utils/Log.h"
namespace ir {
@ -21,6 +21,21 @@ ConstantInt* IRBuilder::CreateConstInt(int v) {
return ctx_.GetConstInt(v);
}
// IRBuilder 方法实现
ConstantFloat* IRBuilder::CreateConstFloat(float v) {
return ctx_.GetConstFloat(v);
}
ConstantArray* IRBuilder::CreateConstArray(std::shared_ptr<ArrayType> ty,
std::vector<ConstantValue*> elements) {
return ctx_.GetConstArray(ty, std::move(elements));
}
ConstantZero* IRBuilder::CreateZeroConstant(std::shared_ptr<Type> ty) {
return ctx_.GetZeroConstant(ty);
}
BinaryInst* IRBuilder::CreateBinary(Opcode op, Value* lhs, Value* rhs,
const std::string& name) {
if (!insert_block_) {
@ -34,7 +49,69 @@ BinaryInst* IRBuilder::CreateBinary(Opcode op, Value* lhs, Value* rhs,
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateBinary 缺少 rhs"));
}
return insert_block_->Append<BinaryInst>(op, lhs->GetType(), lhs, rhs, name);
// 检查操作码是否为有效的二元操作符
switch (op) {
case Opcode::Add:
case Opcode::Sub:
case Opcode::Mul:
case Opcode::Div:
case Opcode::Mod:
case Opcode::And:
case Opcode::Or:
// 添加浮点操作码
case Opcode::FAdd:
case Opcode::FSub:
case Opcode::FMul:
case Opcode::FDiv:
// 有效的二元操作符
break;
case Opcode::Not:
// Not是一元操作符不应该在BinaryInst中
throw std::runtime_error(FormatError("ir", "Not是一元操作符应使用其他指令"));
default:
throw std::runtime_error(FormatError("ir", "BinaryInst 不支持的操作码"));
}
// 确定结果类型
std::shared_ptr<Type> result_type;
// 检查操作数类型是否相同
if (lhs->GetType()->GetKind() != rhs->GetType()->GetKind()) {
throw std::runtime_error(
FormatError("ir", "CreateBinary 操作数类型不匹配"));
}
// 检查是否为浮点操作
bool is_float_op = (op == Opcode::FAdd || op == Opcode::FSub ||
op == Opcode::FMul || op == Opcode::FDiv);
if (is_float_op) {
// 浮点操作要求操作数是浮点类型
if (!lhs->GetType()->IsFloat()) {
throw std::runtime_error(
FormatError("ir", "浮点运算要求操作数为浮点类型"));
}
result_type = lhs->GetType();
} else {
bool is_logical = (op == Opcode::And || op == Opcode::Or);
if (is_logical) {
// 逻辑运算的结果是 int32布尔值
result_type = Type::GetInt32Type();
} else {
// 算术运算的结果类型与操作数相同
result_type = lhs->GetType();
}
// 检查操作数类型是否支持
if (!lhs->GetType()->IsInt32() && !lhs->GetType()->IsFloat()) {
throw std::runtime_error(
FormatError("ir", "CreateBinary 只支持 int32 和 float 类型"));
}
}
return insert_block_->Append<BinaryInst>(op, result_type, lhs, rhs, name);
}
BinaryInst* IRBuilder::CreateAdd(Value* lhs, Value* rhs,
@ -42,6 +119,17 @@ BinaryInst* IRBuilder::CreateAdd(Value* lhs, Value* rhs,
return CreateBinary(Opcode::Add, lhs, rhs, name);
}
AllocaInst* IRBuilder::CreateAlloca(std::shared_ptr<Type> ty,
const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!ty) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateAlloca 缺少类型"));
}
return insert_block_->Append<AllocaInst>(ty, name);
}
AllocaInst* IRBuilder::CreateAllocaI32(const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
@ -49,6 +137,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 未设置插入点"));
@ -57,9 +152,32 @@ LoadInst* IRBuilder::CreateLoad(Value* ptr, const std::string& name) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateLoad 缺少 ptr"));
}
return insert_block_->Append<LoadInst>(Type::GetInt32Type(), ptr, name);
auto ptr_ty = ptr->GetType();
std::shared_ptr<Type> elem_ty;
if (ptr_ty->IsPtrInt32()) {
elem_ty = Type::GetInt32Type();
} else if (ptr_ty->IsPtrFloat()) {
elem_ty = Type::GetFloatType();
} else if (ptr_ty->IsPtrInt1()) {
elem_ty = Type::GetInt1Type();
} else if (ptr_ty->IsArray()) {
// 数组类型的指针,元素类型是数组元素类型
auto* array_ty = dynamic_cast<ArrayType*>(ptr_ty.get());
if (array_ty) {
elem_ty = array_ty->GetElementType();
} else {
throw std::runtime_error(FormatError("ir", "不支持的指针类型"));
}
} else {
// 尝试其他指针类型
throw std::runtime_error(FormatError("ir", "不支持的指针类型"));
}
return insert_block_->Append<LoadInst>(elem_ty, ptr, name);
}
StoreInst* IRBuilder::CreateStore(Value* val, Value* ptr) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
@ -72,6 +190,35 @@ StoreInst* IRBuilder::CreateStore(Value* val, Value* ptr) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateStore 缺少 ptr"));
}
// 检查类型兼容性
auto ptr_ty = ptr->GetType();
auto val_ty = val->GetType();
if (ptr_ty->IsPtrInt32()) {
if (!val_ty->IsInt32()) {
throw std::runtime_error(FormatError("ir", "存储类型不匹配:期望 int32"));
}
} else if (ptr_ty->IsPtrFloat()) {
if (!val_ty->IsFloat()) {
throw std::runtime_error(
FormatError("ir", "存储类型不匹配:期望 float, 实际 kind=" +
std::to_string(static_cast<int>(val_ty->GetKind()))));
}
} else if (ptr_ty->IsArray()) {
// 数组存储支持两种形式:
// 1. 标量元素写入(通常配合 GEP 后落到元素指针,不会走到这里)
// 2. 聚合数组整体写入,例如 `store [16 x i32] zeroinitializer, [16 x i32]* %arr`
if (!val_ty->IsArray()) {
throw std::runtime_error(
FormatError("ir", "数组地址仅支持聚合数组整体存储"));
}
if (val_ty->GetKind() != ptr_ty->GetKind()) {
throw std::runtime_error(
FormatError("ir", "聚合数组存储类型不匹配"));
}
}
return insert_block_->Append<StoreInst>(Type::GetVoidType(), val, ptr);
}
@ -79,11 +226,445 @@ ReturnInst* IRBuilder::CreateRet(Value* v) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!v) {
return insert_block_->Append<ReturnInst>(Type::GetVoidType(), v);
}
BranchInst* IRBuilder::CreateBr(BasicBlock* target) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!target) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateRet 缺少返回值"));
FormatError("ir", "IRBuilder::CreateBr 缺少 target"));
}
return insert_block_->Append<ReturnInst>(Type::GetVoidType(), v);
return insert_block_->Append<BranchInst>(Type::GetVoidType(), target);
}
BranchInst* IRBuilder::CreateCondBr(Value* cond, BasicBlock* true_target,
BasicBlock* false_target) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!cond) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateCondBr 缺少 cond"));
}
if (!true_target) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateCondBr 缺少 true_target"));
}
if (!false_target) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateCondBr 缺少 false_target"));
}
return insert_block_->Append<BranchInst>(Type::GetVoidType(), cond, true_target, false_target);
}
// 创建整数相等比较
IcmpInst* IRBuilder::CreateICmpEQ(Value* lhs, Value* rhs,
const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!lhs || !rhs) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateICmpEQ 缺少操作数"));
}
// 检查类型必须一致
if (lhs->GetType() != rhs->GetType()) {
throw std::runtime_error(
FormatError("ir", "比较操作数类型不匹配"));
}
return insert_block_->Append<IcmpInst>(IcmpInst::Predicate::EQ, lhs, rhs,
Type::GetInt1Type(), name);
}
// 创建整数不等比较
IcmpInst* IRBuilder::CreateICmpNE(Value* lhs, Value* rhs,
const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!lhs || !rhs) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateICmpNE 缺少操作数"));
}
if (lhs->GetType() != rhs->GetType()) {
throw std::runtime_error(
FormatError("ir", "比较操作数类型不匹配"));
}
return insert_block_->Append<IcmpInst>(IcmpInst::Predicate::NE, lhs, rhs,
Type::GetInt1Type(), name);
}
// 创建整数小于比较
IcmpInst* IRBuilder::CreateICmpLT(Value* lhs, Value* rhs,
const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!lhs || !rhs) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateICmpLT 缺少操作数"));
}
if (lhs->GetType() != rhs->GetType()) {
throw std::runtime_error(
FormatError("ir", "比较操作数类型不匹配"));
}
return insert_block_->Append<IcmpInst>(IcmpInst::Predicate::LT, lhs, rhs,
Type::GetInt1Type(), name);
}
// 创建整数小于等于比较
IcmpInst* IRBuilder::CreateICmpLE(Value* lhs, Value* rhs,
const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!lhs || !rhs) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateICmpLE 缺少操作数"));
}
if (lhs->GetType() != rhs->GetType()) {
throw std::runtime_error(
FormatError("ir", "比较操作数类型不匹配"));
}
return insert_block_->Append<IcmpInst>(IcmpInst::Predicate::LE, lhs, rhs,
Type::GetInt1Type(), name);
}
// 创建整数大于比较
IcmpInst* IRBuilder::CreateICmpGT(Value* lhs, Value* rhs,
const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!lhs || !rhs) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateICmpGT 缺少操作数"));
}
if (lhs->GetType() != rhs->GetType()) {
throw std::runtime_error(
FormatError("ir", "比较操作数类型不匹配"));
}
return insert_block_->Append<IcmpInst>(IcmpInst::Predicate::GT, lhs, rhs,
Type::GetInt1Type(), name);
}
// 创建整数大于等于比较
IcmpInst* IRBuilder::CreateICmpGE(Value* lhs, Value* rhs,
const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!lhs || !rhs) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateICmpGE 缺少操作数"));
}
if (lhs->GetType() != rhs->GetType()) {
throw std::runtime_error(
FormatError("ir", "比较操作数类型不匹配"));
}
return insert_block_->Append<IcmpInst>(IcmpInst::Predicate::GE, lhs, rhs,
Type::GetInt1Type(), name);
}
// 创建零扩展指令
ZExtInst* IRBuilder::CreateZExt(Value* value, std::shared_ptr<Type> target_ty,
const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!value) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateZExt 缺少 value"));
}
if (!target_ty) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateZExt 缺少 target_ty"));
}
auto src_ty = value->GetType();
// 类型检查:源类型应该是较小的整数类型
if (!src_ty->IsInt1() && !src_ty->IsInt32()) {
throw std::runtime_error(
FormatError("ir", "ZExt 源类型必须是整数类型"));
}
// 目标类型应该是较大的整数类型
if (!target_ty->IsInt32()) {
throw std::runtime_error(
FormatError("ir", "ZExt 目标类型必须是整数类型"));
}
const std::string inst_name = name.empty() ? ctx_.NextTemp() : name;
return insert_block_->Append<ZExtInst>(value, target_ty, inst_name);
}
// 创建截断指令
TruncInst* IRBuilder::CreateTrunc(Value* value, std::shared_ptr<Type> target_ty,
const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!value) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateTrunc 缺少 value"));
}
if (!target_ty) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateTrunc 缺少 target_ty"));
}
auto src_ty = value->GetType();
// 类型检查:源类型应该是较大的整数类型
if (!src_ty->IsInt32()) {
throw std::runtime_error(
FormatError("ir", "Trunc 源类型必须是整数类型"));
}
// 目标类型应该是较小的整数类型
if (!target_ty->IsInt1() && !target_ty->IsInt32()) {
throw std::runtime_error(
FormatError("ir", "Trunc 目标类型必须是整数类型"));
}
const std::string inst_name = name.empty() ? ctx_.NextTemp() : name;
return insert_block_->Append<TruncInst>(value, target_ty, inst_name);
}
// 便捷方法i1 转 i32
ZExtInst* IRBuilder::CreateZExtI1ToI32(Value* value, const std::string& name) {
return CreateZExt(value, Type::GetInt32Type(), name);
}
// 便捷方法i32 转 i1
TruncInst* IRBuilder::CreateTruncI32ToI1(Value* value, const std::string& name) {
return CreateTrunc(value, Type::GetInt1Type(), name);
}
BinaryInst* IRBuilder::CreateDiv(Value* lhs, Value* rhs, const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!lhs) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateDiv 缺少 lhs"));
}
if (!rhs) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateDiv 缺少 rhs"));
}
return insert_block_->Append<BinaryInst>(Opcode::Div, lhs->GetType(), lhs, rhs, name);
}
BinaryInst* IRBuilder::CreateMod(Value* lhs, Value* rhs, const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!lhs) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateMod 缺少 lhs"));
}
if (!rhs) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateMod 缺少 rhs"));
}
return insert_block_->Append<BinaryInst>(Opcode::Mod, lhs->GetType(), lhs, rhs, name);
}
BinaryInst* IRBuilder::CreateAnd(Value* lhs, Value* rhs, const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!lhs) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateAnd 缺少 lhs"));
}
if (!rhs) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateAnd 缺少 rhs"));
}
auto result_ty = lhs->GetType()->IsInt1() ? Type::GetInt1Type()
: Type::GetInt32Type();
return insert_block_->Append<BinaryInst>(Opcode::And, result_ty, lhs, rhs, name);
}
BinaryInst* IRBuilder::CreateOr(Value* lhs, Value* rhs, const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!lhs) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateOr 缺少 lhs"));
}
if (!rhs) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateOr 缺少 rhs"));
}
auto result_ty = lhs->GetType()->IsInt1() ? Type::GetInt1Type()
: Type::GetInt32Type();
return insert_block_->Append<BinaryInst>(Opcode::Or, result_ty, lhs, rhs, name);
}
IcmpInst* IRBuilder::CreateNot(Value* val, const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!val) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateNot 缺少 operand"));
}
if (val->GetType()->IsInt1()) {
auto* ext = CreateZExtI1ToI32(val, "");
auto* zero = CreateConstInt(0);
return CreateICmpEQ(ext, zero, name);
}
auto* zero = CreateConstInt(0);
return CreateICmpEQ(val, zero, name);
}
GEPInst* IRBuilder::CreateGEP(Value* base,
const std::vector<Value*>& indices,
const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!base) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateGEP 缺少 base"));
}
// 检查所有索引
for (size_t i = 0; i < indices.size(); ++i) {
if (!indices[i]) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateGEP 索引 " + std::to_string(i) + " 为空"));
}
}
// 结果类型推断:
// - 对 i32*/float* 基址,结果仍分别为 i32*/float*
// - 对数组基址,按多索引向下剥离元素类型;若到达标量则返回对应标量指针
// (本项目没有“指向数组的指针类型”,未完全剥离时退回数组类型)
std::shared_ptr<Type> result_ty = base->GetType();
if (base->GetType()->IsPtrInt32()) {
result_ty = Type::GetPtrInt32Type();
} else if (base->GetType()->IsPtrFloat()) {
result_ty = Type::GetPtrFloatType();
} else if (base->GetType()->IsArray()) {
std::shared_ptr<Type> cur = base->GetType();
for (size_t i = 1; i < indices.size(); ++i) {
auto* at = dynamic_cast<ArrayType*>(cur.get());
if (!at) break;
cur = at->GetElementType();
}
if (cur->IsInt32()) result_ty = Type::GetPtrInt32Type();
else if (cur->IsFloat()) result_ty = Type::GetPtrFloatType();
else result_ty = cur;
}
return insert_block_->Append<GEPInst>(result_ty, base, indices, name);
}
BinaryInst* IRBuilder::CreateMul(Value* lhs, Value* rhs, const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!lhs) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateMul 缺少 lhs"));
}
if (!rhs) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateMul 缺少 rhs"));
}
return CreateBinary(Opcode::Mul, lhs, rhs, name);
}
BinaryInst* IRBuilder::CreateSub(Value* lhs, Value* rhs, const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!lhs) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateSub 缺少 lhs"));
}
if (!rhs) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateSub 缺少 rhs"));
}
return CreateBinary(Opcode::Sub, lhs, rhs, name);
}
// 注意:当前 CreateCall 仅支持直接调用 Function且不支持变长参数列表等复杂特性。
// 创建函数调用指令的实现,被调用的函数,参数列表,返回值临时变量名
CallInst* IRBuilder::CreateCall(Function* callee,
const std::vector<Value*>& args,
const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!callee) { //被调用的函数不能为空
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateCall 缺少 callee"));
}
auto func_ty = std::static_pointer_cast<FunctionType>(callee->GetType());
auto ret_ty = func_ty->GetReturnType();
return insert_block_->Append<CallInst>(ret_ty, callee, args, name);
}
BinaryInst* IRBuilder::CreateFAdd(Value* lhs, Value* rhs, const std::string& name) {
return insert_block_->Append<BinaryInst>(Opcode::FAdd, lhs->GetType(), lhs, rhs, name);
}
BinaryInst* IRBuilder::CreateFSub(Value* lhs, Value* rhs, const std::string& name) {
return insert_block_->Append<BinaryInst>(Opcode::FSub, lhs->GetType(), lhs, rhs, name);
}
BinaryInst* IRBuilder::CreateFMul(Value* lhs, Value* rhs, const std::string& name) {
return insert_block_->Append<BinaryInst>(Opcode::FMul, lhs->GetType(), lhs, rhs, name);
}
BinaryInst* IRBuilder::CreateFDiv(Value* lhs, Value* rhs, const std::string& name) {
return insert_block_->Append<BinaryInst>(Opcode::FDiv, lhs->GetType(), lhs, rhs, name);
}
// 浮点比较
FcmpInst* IRBuilder::CreateFCmpOEQ(Value* lhs, Value* rhs, const std::string& name) {
return insert_block_->Append<FcmpInst>(
FcmpInst::Predicate::OEQ, lhs, rhs, Type::GetInt1Type(), name);
}
FcmpInst* IRBuilder::CreateFCmpONE(Value* lhs, Value* rhs, const std::string& name) {
return insert_block_->Append<FcmpInst>(
FcmpInst::Predicate::ONE, lhs, rhs, Type::GetInt1Type(), name);
}
FcmpInst* IRBuilder::CreateFCmpOLT(Value* lhs, Value* rhs, const std::string& name) {
return insert_block_->Append<FcmpInst>(
FcmpInst::Predicate::OLT, lhs, rhs, Type::GetInt1Type(), name);
}
FcmpInst* IRBuilder::CreateFCmpOLE(Value* lhs, Value* rhs, const std::string& name) {
return insert_block_->Append<FcmpInst>(
FcmpInst::Predicate::OLE, lhs, rhs, Type::GetInt1Type(), name);
}
FcmpInst* IRBuilder::CreateFCmpOGT(Value* lhs, Value* rhs, const std::string& name) {
return insert_block_->Append<FcmpInst>(
FcmpInst::Predicate::OGT, lhs, rhs, Type::GetInt1Type(), name);
}
FcmpInst* IRBuilder::CreateFCmpOGE(Value* lhs, Value* rhs, const std::string& name) {
return insert_block_->Append<FcmpInst>(
FcmpInst::Predicate::OGE, lhs, rhs, Type::GetInt1Type(), name);
}
// 类型转换
SIToFPInst* IRBuilder::CreateSIToFP(Value* value, std::shared_ptr<Type> target_ty,
const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
const std::string inst_name = name.empty() ? ctx_.NextTemp() : name;
return insert_block_->Append<SIToFPInst>(value, target_ty, inst_name);
}
FPToSIInst* IRBuilder::CreateFPToSI(Value* value, std::shared_ptr<Type> target_ty,
const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
const std::string inst_name = name.empty() ? ctx_.NextTemp() : name;
return insert_block_->Append<FPToSIInst>(value, target_ty, inst_name);
}
} // namespace ir

@ -4,6 +4,9 @@
#include "ir/IR.h"
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <ostream>
#include <stdexcept>
#include <string>
@ -12,14 +15,134 @@
namespace ir {
static const char* TypeToString(const Type& ty) {
static std::string TypeToString(const Type& ty);
static std::string ArrayTypeToStringFrom(const Type& base_ty,
const std::vector<int>& dims,
size_t begin) {
std::string s = TypeToString(base_ty);
for (size_t i = dims.size(); i-- > begin;) {
s = "[" + std::to_string(dims[i]) + " x " + s + "]";
}
return s;
}
static bool IsZeroConstant(const ConstantValue* value) {
if (!value) {
return true;
}
if (auto* ci = dynamic_cast<const ConstantInt*>(value)) {
return ci->GetValue() == 0;
}
if (auto* cf = dynamic_cast<const ConstantFloat*>(value)) {
return cf->GetValue() == 0.0f;
}
if (dynamic_cast<const ConstantZero*>(value) ||
dynamic_cast<const ConstantAggregateZero*>(value)) {
return true;
}
if (auto* arr = dynamic_cast<const ConstantArray*>(value)) {
for (auto* elem : arr->GetElements()) {
if (!IsZeroConstant(elem)) {
return false;
}
}
return true;
}
return false;
}
static size_t AggregateSpan(const std::vector<int>& dims, size_t level) {
size_t span = 1;
for (size_t i = level; i < dims.size(); ++i) {
span *= static_cast<size_t>(dims[i]);
}
return span;
}
static bool IsZeroRange(const std::vector<ConstantValue*>& init,
size_t begin,
size_t count) {
for (size_t i = 0; i < count; ++i) {
const size_t index = begin + i;
if (index >= init.size()) {
continue;
}
if (!IsZeroConstant(init[index])) {
return false;
}
}
return true;
}
static void PrintFlatArrayBody(std::ostream& os,
const Type& base_ty,
const std::vector<int>& dims,
size_t level,
const std::vector<ConstantValue*>& init,
size_t& flat_index) {
const size_t span = AggregateSpan(dims, level);
if (IsZeroRange(init, flat_index, span)) {
os << "zeroinitializer";
flat_index += span;
return;
}
os << "[";
for (int i = 0; i < dims[level]; ++i) {
if (i > 0) os << ", ";
if (level + 1 < dims.size()) {
os << ArrayTypeToStringFrom(base_ty, dims, level + 1) << " ";
PrintFlatArrayBody(os, base_ty, dims, level + 1, init, flat_index);
continue;
}
os << TypeToString(base_ty) << " ";
if (flat_index < init.size() && init[flat_index]) {
if (auto* ci = dynamic_cast<const ConstantInt*>(init[flat_index])) {
os << ci->GetValue();
} else if (auto* cf = dynamic_cast<const ConstantFloat*>(init[flat_index])) {
os << cf->GetValue();
} else if (IsZeroConstant(init[flat_index])) {
os << "0";
} else {
os << "0";
}
} else {
os << "0";
}
++flat_index;
}
os << "]";
}
static std::string TypeToString(const Type& ty) {
switch (ty.GetKind()) {
case Type::Kind::Void:
return "void";
case Type::Kind::Int32:
return "i32";
case Type::Kind::PtrInt32:
return "i32*";
case Type::Kind::Void: return "void";
case Type::Kind::Int32: return "i32";
case Type::Kind::Float: return "float";
case Type::Kind::PtrInt32: return "i32*";
case Type::Kind::PtrFloat: return "float*";
case Type::Kind::Label: return "label";
case Type::Kind::Function: return "function";
case Type::Kind::Int1: return "i1";
case Type::Kind::PtrInt1: return "i1*";
case Type::Kind::Array: {
// 打印数组类型为 LLVM 风格,如 [4 x [2 x i32]]
auto* at = dynamic_cast<const ArrayType*>(&ty);
if (!at) return "array";
// 递归构建类型字符串
std::string elem = TypeToString(*at->GetElementType());
const auto& dims = at->GetDimensions();
// 从外到内构建
std::string s = elem;
for (auto it = dims.rbegin(); it != dims.rend(); ++it) {
s = "[" + std::to_string(*it) + " x " + s + "]";
}
return s;
}
default: return "unknown";
}
throw std::runtime_error(FormatError("ir", "未知类型"));
}
@ -40,21 +163,182 @@ static const char* OpcodeToString(Opcode op) {
return "store";
case Opcode::Ret:
return "ret";
case Opcode::Call:
return "call";
case Opcode::Br:
return "br";
case Opcode::CondBr:
return "condbr";
case Opcode::Icmp:
return "icmp";
case Opcode::Div:
return "sdiv";
case Opcode::Mod:
return "srem";
case Opcode::ZExt:
return "zext";
case Opcode::Trunc:
return "trunc";
case Opcode::And:
return "and";
case Opcode::Or:
return "or";
case Opcode::Not:
return "not";
case Opcode::GEP:
return "getelementptr";
case Opcode::FAdd: return "fadd";
case Opcode::FSub: return "fsub";
case Opcode::FMul: return "fmul";
case Opcode::FDiv: return "fdiv";
case Opcode::FCmp: return "fcmp";
case Opcode::SIToFP: return "sitofp";
case Opcode::FPToSI: return "fptosi";
case Opcode::FPExt: return "fpext";
case Opcode::FPTrunc: return "fptrunc";
}
return "?";
}
// 将 float 值转为 LLVM IR 接受的 64-bit 十六进制浮点格式
static std::string FloatToLLVMHex(float f) {
double d = static_cast<double>(f);
uint64_t bits;
memcpy(&bits, &d, sizeof(bits));
char buf[20];
snprintf(buf, sizeof(buf), "0x%016llX", (unsigned long long)bits);
return buf;
}
static std::string ValueToString(const Value* v) {
if (!v) {
return "<null>";
}
if (dynamic_cast<const ConstantZero*>(v) ||
dynamic_cast<const ConstantAggregateZero*>(v)) {
return "zeroinitializer";
}
if (auto* ci = dynamic_cast<const ConstantInt*>(v)) {
return std::to_string(ci->GetValue());
}
return v ? v->GetName() : "<null>";
if (auto* cf = dynamic_cast<const ConstantFloat*>(v)) {
return FloatToLLVMHex(cf->GetValue());
}
const auto& name = v->GetName();
if (name.empty()) {
return "<unnamed>";
}
if (name[0] == '%' || name[0] == '@') {
return name;
}
if (dynamic_cast<const GlobalValue*>(v)) {
return "@" + name;
}
return "%" + name;
}
static std::string MemoryTypeToString(const Type& ty) {
std::string text = TypeToString(ty);
if (ty.IsArray()) {
text += "*";
}
return text;
}
void IRPrinter::Print(const Module& module, std::ostream& os) {
for (const auto& global : module.GetGlobals()) {
if (!global) continue;
os << "@" << global->GetName() << " = "
<< (global->IsConstant() ? "constant " : "global ");
if (global->GetType()->IsPtrInt32()) {
os << "i32 ";
if (global->HasInitializer()) {
auto* ci = dynamic_cast<const ConstantInt*>(global->GetInitializer().front());
os << (ci ? ci->GetValue() : 0);
} else {
os << "0";
}
os << "\n";
continue;
}
if (global->GetType()->IsPtrFloat()) {
os << "float ";
if (global->HasInitializer()) {
auto* cf = dynamic_cast<const ConstantFloat*>(global->GetInitializer().front());
os << (cf ? ValueToString(cf) : FloatToLLVMHex(0.0f));
} else {
os << FloatToLLVMHex(0.0f);
}
os << "\n";
continue;
}
if (global->GetType()->IsArray()) {
auto* at = dynamic_cast<const ArrayType*>(global->GetType().get());
os << TypeToString(*global->GetType()) << " ";
if (!at || !global->HasInitializer() ||
IsZeroRange(global->GetInitializer(), 0, AggregateSpan(at->GetDimensions(), 0))) {
os << "zeroinitializer\n";
continue;
}
size_t flat_index = 0;
PrintFlatArrayBody(os,
*at->GetElementType(),
at->GetDimensions(),
0,
global->GetInitializer(),
flat_index);
os << "\n";
continue;
}
os << TypeToString(*global->GetType()) << " zeroinitializer\n";
}
auto print_func_params = [&](const Function* func,
const FunctionType* func_ty) {
bool first = true;
if (!func->GetArguments().empty()) {
for (const auto& arg : func->GetArguments()) {
if (!first) os << ", ";
first = false;
os << TypeToString(*arg->GetType()) << " %" << arg->GetName();
}
return;
}
for (const auto& pty : func_ty->GetParamTypes()) {
if (!first) os << ", ";
first = false;
os << TypeToString(*pty);
}
};
auto is_declaration_only = [](const Function* func) {
const auto& blocks = func->GetBlocks();
if (blocks.size() != 1) return false;
const auto& only = blocks.front();
if (!only) return false;
return only->GetInstructions().empty();
};
for (const auto& func : module.GetFunctions()) {
os << "define " << TypeToString(*func->GetType()) << " @" << func->GetName()
<< "() {\n";
auto* func_ty = static_cast<const FunctionType*>(func->GetType().get());
if (is_declaration_only(func.get())) {
os << "declare " << TypeToString(*func_ty->GetReturnType()) << " @"
<< func->GetName() << "(";
print_func_params(func.get(), func_ty);
os << ")\n";
continue;
}
os << "define " << TypeToString(*func_ty->GetReturnType()) << " @"
<< func->GetName() << "(";
print_func_params(func.get(), func_ty);
os << ") {\n";
for (const auto& bb : func->GetBlocks()) {
if (!bb) {
continue;
@ -65,7 +349,17 @@ void IRPrinter::Print(const Module& module, std::ostream& os) {
switch (inst->GetOpcode()) {
case Opcode::Add:
case Opcode::Sub:
case Opcode::Mul: {
case Opcode::Mul:
case Opcode::Div:
case Opcode::Mod:
case Opcode::And:
case Opcode::Not:
case Opcode::Or:
case Opcode::FAdd:
case Opcode::FSub:
case Opcode::FMul:
case Opcode::FDiv:
{
auto* bin = static_cast<const BinaryInst*>(inst);
os << " " << bin->GetName() << " = "
<< OpcodeToString(bin->GetOpcode()) << " "
@ -76,25 +370,189 @@ void IRPrinter::Print(const Module& module, std::ostream& os) {
}
case Opcode::Alloca: {
auto* alloca = static_cast<const AllocaInst*>(inst);
os << " " << alloca->GetName() << " = alloca i32\n";
std::string elem_ty_str;
if (alloca->GetType()->IsPtrInt32()) {
elem_ty_str = "i32";
} else if (alloca->GetType()->IsPtrFloat()) {
elem_ty_str = "float";
} else {
elem_ty_str = TypeToString(*alloca->GetType());
}
os << " " << alloca->GetName() << " = alloca " << elem_ty_str << "\n";
break;
}
case Opcode::Load: {
auto* load = static_cast<const LoadInst*>(inst);
os << " " << load->GetName() << " = load i32, i32* "
os << " " << load->GetName() << " = load "
<< TypeToString(*load->GetType()) << ", "
<< MemoryTypeToString(*load->GetPtr()->GetType()) << " "
<< ValueToString(load->GetPtr()) << "\n";
break;
}
case Opcode::Store: {
auto* store = static_cast<const StoreInst*>(inst);
os << " store i32 " << ValueToString(store->GetValue())
<< ", i32* " << ValueToString(store->GetPtr()) << "\n";
os << " store " << TypeToString(*store->GetValue()->GetType()) << " "
<< ValueToString(store->GetValue())
<< ", " << MemoryTypeToString(*store->GetPtr()->GetType()) << " "
<< ValueToString(store->GetPtr()) << "\n";
break;
}
case Opcode::Ret: {
auto* ret = static_cast<const ReturnInst*>(inst);
os << " ret " << TypeToString(*ret->GetValue()->GetType()) << " "
<< ValueToString(ret->GetValue()) << "\n";
if (!ret->GetValue()) {
os << " ret void\n";
} else {
os << " ret " << TypeToString(*ret->GetValue()->GetType()) << " "
<< ValueToString(ret->GetValue()) << "\n";
}
break;
}
// CallInst类在 include/ir/IR.h 中定义
case Opcode::Call: {
auto* call = static_cast<const CallInst*>(inst);
os << " ";
if (!call->GetType()->IsVoid()) {
os << call->GetName() << " = ";
}
os << "call " << TypeToString(*call->GetType()) << " @"
<< call->GetCallee()->GetName() << "(";
bool first = true;
for (auto* arg : call->GetArgs()) {
if (!first) os << ", ";
first = false;
os << TypeToString(*arg->GetType()) << " " << ValueToString(arg);
}
os << ")\n";
break;
}
// 在 IRPrinter.cpp 的 switch 语句中添加
case Opcode::Br:
case Opcode::CondBr: {
auto* br = static_cast<const BranchInst*>(inst);
if (!br->IsConditional()) {
os << " br label %" << br->GetTarget()->GetName() << "\n";
} else {
os << " br i1 " << ValueToString(br->GetCondition())
<< ", label %" << br->GetTrueTarget()->GetName()
<< ", label %" << br->GetFalseTarget()->GetName() << "\n";
}
break;
}
case Opcode::Icmp: {
auto* icmp = static_cast<const IcmpInst*>(inst);
os << " " << icmp->GetName() << " = icmp ";
switch (icmp->GetPredicate()) {
case IcmpInst::Predicate::EQ: os << "eq"; break;
case IcmpInst::Predicate::NE: os << "ne"; break;
case IcmpInst::Predicate::LT: os << "slt"; break;
case IcmpInst::Predicate::LE: os << "sle"; break;
case IcmpInst::Predicate::GT: os << "sgt"; break;
case IcmpInst::Predicate::GE: os << "sge"; break;
}
os << " " << TypeToString(*icmp->GetLhs()->GetType())
<< " " << ValueToString(icmp->GetLhs())
<< ", " << ValueToString(icmp->GetRhs()) << "\n";
break;
}
case Opcode::ZExt: {
auto* zext = static_cast<const ZExtInst*>(inst);
os << " " << zext->GetName() << " = zext "
<< TypeToString(*zext->GetSourceType()) << " "
<< ValueToString(zext->GetValue()) << " to "
<< TypeToString(*zext->GetTargetType()) << "\n";
break;
}
case Opcode::Trunc: {
auto* trunc = static_cast<const TruncInst*>(inst);
os << " " << trunc->GetName() << " = trunc "
<< TypeToString(*trunc->GetSourceType()) << " "
<< ValueToString(trunc->GetValue()) << " to "
<< TypeToString(*trunc->GetTargetType()) << "\n";
break;
}
case Opcode::GEP:{
// 打印为类似 LLVM 的 getelementptr 形式:
// getelementptr <elem_ty>, <base_ty> <base>, i32 <idx0>, i32 <idx1>, ...
os << " " << inst->GetName() << " = getelementptr ";
// 基地址类型使用第一个操作数的类型
Value* base = inst->GetOperand(0);
// GEP 的第一个类型参数应是基址指向的元素类型pointee
std::string elem_ty;
if (base->GetType()->IsPtrInt32()) elem_ty = "i32";
else if (base->GetType()->IsPtrFloat()) elem_ty = "float";
else if (base->GetType()->IsArray()) elem_ty = TypeToString(*base->GetType());
else elem_ty = TypeToString(*inst->GetType());
std::string base_ty = TypeToString(*base->GetType());
if (base->GetType()->IsArray()) {
base_ty += "*";
}
os << elem_ty << ", " << base_ty << " " << ValueToString(base);
// 后续操作数为索引,按照 i32 打印
// 特殊处理:如果 base 是标量指针i32*/float*)且第一个索引是常量 0
// 且后续还有索引,则丢弃第一个 0对 T* 来说多余且会导致无效 IR
size_t start_idx = 1;
if ((base->GetType()->IsPtrInt32() || base->GetType()->IsPtrFloat()) &&
inst->GetNumOperands() >= 3) {
// 检查第一个索引是否为常量 0
auto* first_idx = inst->GetOperand(1);
if (auto* ci = dynamic_cast<const ConstantInt*>(first_idx)) {
if (ci->GetValue() == 0) {
start_idx = 2; // 跳过第一个 0
}
}
}
for (size_t i = start_idx; i < inst->GetNumOperands(); ++i) {
os << ", i32 " << ValueToString(inst->GetOperand(i));
}
os << "\n";
break;
}
case Opcode::FCmp: {
auto* fcmp = static_cast<const FcmpInst*>(inst);
os << " " << fcmp->GetName() << " = fcmp ";
switch (fcmp->GetPredicate()) {
case FcmpInst::Predicate::OEQ: os << "oeq"; break;
case FcmpInst::Predicate::ONE: os << "one"; break;
case FcmpInst::Predicate::OLT: os << "olt"; break;
case FcmpInst::Predicate::OLE: os << "ole"; break;
case FcmpInst::Predicate::OGT: os << "ogt"; break;
case FcmpInst::Predicate::OGE: os << "oge"; break;
default: os << "oeq"; break;
}
os << " " << TypeToString(*fcmp->GetLhs()->GetType())
<< " " << ValueToString(fcmp->GetLhs())
<< ", " << ValueToString(fcmp->GetRhs()) << "\n";
break;
}
case Opcode::SIToFP: {
auto* sitofp = static_cast<const SIToFPInst*>(inst);
os << " " << sitofp->GetName() << " = sitofp "
<< TypeToString(*sitofp->GetValue()->GetType()) << " "
<< ValueToString(sitofp->GetValue()) << " to "
<< TypeToString(*sitofp->GetType()) << "\n";
break;
}
case Opcode::FPToSI: {
auto* fptosi = static_cast<const FPToSIInst*>(inst);
os << " " << fptosi->GetName() << " = fptosi "
<< TypeToString(*fptosi->GetValue()->GetType()) << " "
<< ValueToString(fptosi->GetValue()) << " to "
<< TypeToString(*fptosi->GetType()) << "\n";
break;
}
default: {
// 处理未知操作码
os << " ; 未知指令: " << OpcodeToString(inst->GetOpcode()) << "\n";
break;
}
}
@ -104,4 +562,28 @@ void IRPrinter::Print(const Module& module, std::ostream& os) {
}
}
void IRPrinter::PrintConstant(const ConstantValue* constant, std::ostream& os) {
if (auto* const_int = dynamic_cast<const ConstantInt*>(constant)) {
os << const_int->GetValue();
}
else if (auto* const_float = dynamic_cast<const ConstantFloat*>(constant)) {
os << const_float->GetValue();
}
else if (auto* const_array = dynamic_cast<const ConstantArray*>(constant)) {
os << "[";
auto& elements = const_array->GetElements();
for (size_t i = 0; i < elements.size(); ++i) {
if (i > 0) os << ", ";
PrintConstant(elements[i], os);
}
os << "]";
}
else if (dynamic_cast<const ConstantZero*>(constant)) {
os << "zero";
}
else if (dynamic_cast<const ConstantAggregateZero*>(constant)) {
os << "zeroinitializer";
}
}
} // namespace ir

@ -52,7 +52,10 @@ Instruction::Instruction(Opcode op, std::shared_ptr<Type> ty, std::string name)
Opcode Instruction::GetOpcode() const { return opcode_; }
bool Instruction::IsTerminator() const { return opcode_ == Opcode::Ret; }
bool Instruction::IsTerminator() const {
return opcode_ == Opcode::Ret || opcode_ == Opcode::Br ||
opcode_ == Opcode::CondBr;
}
BasicBlock* Instruction::GetParent() const { return parent_; }
@ -61,22 +64,71 @@ void Instruction::SetParent(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)) {
if (op != Opcode::Add) {
throw std::runtime_error(FormatError("ir", "BinaryInst 当前只支持 Add"));
}
if (!lhs || !rhs) {
throw std::runtime_error(FormatError("ir", "BinaryInst 缺少操作数"));
// 检查操作码是否为有效的二元操作符
switch (op) {
case Opcode::Add:
case Opcode::Sub:
case Opcode::Mul:
case Opcode::Div:
case Opcode::Mod:
case Opcode::And:
case Opcode::Or:
case Opcode::FAdd:
case Opcode::FSub:
case Opcode::FMul:
case Opcode::FDiv:
// 有效的二元操作符
break;
case Opcode::Not:
// Not是一元操作符不应该在BinaryInst中
throw std::runtime_error(FormatError("ir", "Not是一元操作符应使用其他指令"));
default:
throw std::runtime_error(FormatError("ir", "BinaryInst 不支持的操作码"));
}
// 当前 BinaryInst 仅支持 Add/Sub/Mul且操作数和结果必须都是 i32。
if (op != Opcode::Add && op != Opcode::Sub && op != Opcode::Mul) {
}
if (!type_ || !lhs->GetType() || !rhs->GetType()) {
throw std::runtime_error(FormatError("ir", "BinaryInst 缺少类型信息"));
}
if (lhs->GetType()->GetKind() != rhs->GetType()->GetKind() ||
type_->GetKind() != lhs->GetType()->GetKind()) {
throw std::runtime_error(FormatError("ir", "BinaryInst 类型不匹配"));
// 对于比较操作结果类型是i1但我们的类型系统可能还没有i1
// 暂时简化所有操作都返回i32比较操作返回0或1
// 检查操作数类型是否匹配
if (lhs->GetType()->GetKind() != rhs->GetType()->GetKind()) {
throw std::runtime_error(FormatError("ir", "BinaryInst 操作数类型不匹配"));
}
if (!type_->IsInt32()) {
throw std::runtime_error(FormatError("ir", "BinaryInst 当前只支持 i32"));
bool is_logical = (op == Opcode::And || op == Opcode::Or);
// 检查操作数类型是否支持
if (is_logical) {
if (!lhs->GetType()->IsInt32() && !lhs->GetType()->IsInt1()) {
throw std::runtime_error(
FormatError("ir", "逻辑运算仅支持 i32/i1"));
}
} else {
if (!lhs->GetType()->IsInt32() && !lhs->GetType()->IsFloat()) {
throw std::runtime_error(
FormatError("ir", "BinaryInst 只支持 int32 和 float 类型"));
}
}
if (is_logical) {
// 逻辑运算结果类型应与操作数一致i1 或 i32
if (type_->GetKind() != lhs->GetType()->GetKind()) {
throw std::runtime_error(
FormatError("ir", "逻辑运算结果类型与操作数类型不匹配"));
}
} else {
// 算术运算的结果类型应与操作数类型相同
if (type_->GetKind() != lhs->GetType()->GetKind()) {
throw std::runtime_error(
FormatError("ir", "BinaryInst 结果类型与操作数类型不匹配"));
}
}
AddOperand(lhs);
AddOperand(rhs);
}
@ -87,21 +139,27 @@ Value* BinaryInst::GetRhs() const { return GetOperand(1); }
ReturnInst::ReturnInst(std::shared_ptr<Type> void_ty, Value* val)
: Instruction(Opcode::Ret, std::move(void_ty), "") {
if (!val) {
throw std::runtime_error(FormatError("ir", "ReturnInst 缺少返回值"));
}
if (!type_ || !type_->IsVoid()) {
throw std::runtime_error(FormatError("ir", "ReturnInst 返回类型必须为 void"));
}
AddOperand(val);
if (val) {
AddOperand(val);
}
}
Value* ReturnInst::GetValue() const { return GetOperand(0); }
Value* ReturnInst::GetValue() const {
if (GetNumOperands() == 0) {
return nullptr;
}
return GetOperand(0);
}
AllocaInst::AllocaInst(std::shared_ptr<Type> ptr_ty, std::string name)
: Instruction(Opcode::Alloca, std::move(ptr_ty), std::move(name)) {
if (!type_ || !type_->IsPtrInt32()) {
throw std::runtime_error(FormatError("ir", "AllocaInst 当前只支持 i32*"));
if (!type_ ||
(!type_->IsPtrInt32() && !type_->IsPtrFloat() && !type_->IsArray())) {
throw std::runtime_error(
FormatError("ir", "AllocaInst 仅支持 i32* / float* / array"));
}
}
@ -110,12 +168,15 @@ LoadInst::LoadInst(std::shared_ptr<Type> val_ty, Value* ptr, std::string name)
if (!ptr) {
throw std::runtime_error(FormatError("ir", "LoadInst 缺少 ptr"));
}
if (!type_ || !type_->IsInt32()) {
throw std::runtime_error(FormatError("ir", "LoadInst 当前只支持加载 i32"));
if (!type_ || (!type_->IsInt32() && !type_->IsFloat() && !type_->IsInt1())) {
throw std::runtime_error(
FormatError("ir", "LoadInst 仅支持加载 i32/float/i1"));
}
if (!ptr->GetType() || !ptr->GetType()->IsPtrInt32()) {
if (!ptr->GetType() ||
(!ptr->GetType()->IsPtrInt32() && !ptr->GetType()->IsPtrFloat() &&
!ptr->GetType()->IsArray() && !ptr->GetType()->IsPtrInt1())) {
throw std::runtime_error(
FormatError("ir", "LoadInst 当前只支持从 i32* 加载"));
FormatError("ir", "LoadInst 仅支持从指针或数组地址加载"));
}
AddOperand(ptr);
}
@ -133,13 +194,25 @@ StoreInst::StoreInst(std::shared_ptr<Type> void_ty, Value* val, Value* ptr)
if (!type_ || !type_->IsVoid()) {
throw std::runtime_error(FormatError("ir", "StoreInst 返回类型必须为 void"));
}
if (!val->GetType() || !val->GetType()->IsInt32()) {
throw std::runtime_error(FormatError("ir", "StoreInst 当前只支持存储 i32"));
}
if (!ptr->GetType() || !ptr->GetType()->IsPtrInt32()) {
if (!val->GetType() ||
(!val->GetType()->IsInt32() && !val->GetType()->IsFloat() &&
!val->GetType()->IsInt1() && !val->GetType()->IsArray())) {
throw std::runtime_error(
FormatError("ir", "StoreInst 当前只支持写入 i32*"));
FormatError("ir", "StoreInst 仅支持存储 i32/float/i1/array"));
}
if (!ptr->GetType() ||
(!ptr->GetType()->IsPtrInt32() && !ptr->GetType()->IsPtrFloat() &&
!ptr->GetType()->IsArray() && !ptr->GetType()->IsPtrInt1())) {
throw std::runtime_error(FormatError("ir", "StoreInst 仅支持写入指针或数组地址"));
}
if (ptr->GetType()->IsArray()) {
if (!val->GetType()->IsArray() ||
val->GetType()->GetKind() != ptr->GetType()->GetKind()) {
throw std::runtime_error(
FormatError("ir", "StoreInst 聚合存储要求 value/ptr 具有相同数组类型"));
}
}
AddOperand(val);
AddOperand(ptr);
}
@ -148,4 +221,61 @@ Value* StoreInst::GetValue() const { return GetOperand(0); }
Value* StoreInst::GetPtr() const { return GetOperand(1); }
Function* CallInst::GetCallee() const { return callee_; }
const std::vector<Value*>& CallInst::GetArgs() const { return args_; }
GEPInst::GEPInst(std::shared_ptr<Type> ptr_ty,
Value* base,
const std::vector<Value*>& indices,
const std::string& name)
: Instruction(Opcode::GEP, ptr_ty, name) {
// 添加base作为第一个操作数
AddOperand(base);
// 添加所有索引作为后续操作数
for (auto* index : indices) {
AddOperand(index);
}
}
Value* GEPInst::GetBase() const {
// 第一个操作数是base
return GetOperand(0);
}
const std::vector<Value*>& GEPInst::GetIndices() const {
// 需要返回索引列表但Instruction只存储操作数
// 这是一个设计问题:要么修改架构,要么提供辅助方法
// 简化实现返回空vector或创建临时vector
static std::vector<Value*> indices;
indices.clear();
// 索引从操作数1开始
for (size_t i = 1; i < GetNumOperands(); ++i) {
indices.push_back(GetOperand(i));
}
return indices;
}
CallInst::CallInst(std::shared_ptr<Type> ret_ty, Function* callee,
const std::vector<Value*>& args, const std::string& name)
: Instruction(Opcode::Call, std::move(ret_ty), name), // name 是 const&,这里会复制
callee_(callee), args_(args) {
if (!callee_) {
throw std::runtime_error(FormatError("ir", "CallInst 缺少被调用函数"));
}
for (auto* arg : args_) {
if (!arg) {
throw std::runtime_error(FormatError("ir", "CallInst 参数不能为 null"));
}
AddOperand(arg);
}
}
} // namespace ir

@ -9,13 +9,46 @@ Context& Module::GetContext() { return context_; }
const Context& Module::GetContext() const { return context_; }
Function* Module::CreateFunction(const std::string& name,
std::shared_ptr<Type> ret_type) {
functions_.push_back(std::make_unique<Function>(name, std::move(ret_type)));
std::shared_ptr<FunctionType> func_type) {
functions_.push_back(std::make_unique<Function>(name, std::move(func_type)));
return functions_.back().get();
}
Function* Module::FindFunction(const std::string& name) const {
for (const auto& func : functions_) {
if (func->GetName() == name) {
return func.get();
}
}
return nullptr;
}
const std::vector<std::unique_ptr<Function>>& Module::GetFunctions() const {
return functions_;
}
GlobalValue* Module::CreateGlobal(const std::string& name,
std::shared_ptr<Type> ty) {
// 对于标量类型,自动转换为指针类型
std::shared_ptr<Type> global_ty;
if (ty->IsInt32()) {
global_ty = Type::GetPtrInt32Type(); // i32 -> i32*
} else if (ty->IsFloat()) {
global_ty = Type::GetPtrFloatType(); // float -> float*
} else if (ty->IsInt1()) {
global_ty = Type::GetPtrInt1Type(); // i1 -> i1*
} else {
// 数组等类型保持不变
global_ty = ty;
}
globals_.push_back(std::make_unique<GlobalValue>(global_ty, name));
return globals_.back().get();
}
const std::vector<std::unique_ptr<GlobalValue>>& Module::GetGlobals() const {
return globals_;
}
} // namespace ir

@ -1,31 +1,220 @@
// 当前仅支持 void、i32 和 i32*。
#include "ir/IR.h"
#include <cassert>
namespace ir {
Type::Type(Kind k) : kind_(k) {}
size_t Type::Size() const {
switch (kind_) {
case Kind::Void: return 0;
case Kind::Int32: return 4;
case Kind::Float: return 4; // 单精度浮点 4 字节
case Kind::PtrInt32: return 8; // 假设 64 位指针
case Kind::PtrFloat: return 8;
case Kind::Label: return 8; // 标签地址大小(指针大小)
case Kind::PtrInt1: return 8; // 指向 i1 的指针大小
default: return 0; // 派生类应重写
}
}
size_t Type::Alignment() const {
switch (kind_) {
case Kind::Int32: return 4;
case Kind::Float: return 4;
case Kind::PtrInt32: return 8;
case Kind::PtrFloat: return 8;
case Kind::Label: return 8; // 与指针相同
default: return 1;
}
}
bool Type::IsComplete() const {
return kind_ != Kind::Void;
}
const std::shared_ptr<Type>& Type::GetVoidType() {
static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::Void);
static const std::shared_ptr<Type> type = std::shared_ptr<Type>(new Type(Kind::Void));
return type;
}
const std::shared_ptr<Type>& Type::GetInt32Type() {
static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::Int32);
static const std::shared_ptr<Type> type = std::shared_ptr<Type>(new Type(Kind::Int32));
return type;
}
const std::shared_ptr<Type>& Type::GetFloatType() {
static const std::shared_ptr<Type> type(new Type(Kind::Float));
return type;
}
const std::shared_ptr<Type>& Type::GetPtrInt32Type() {
static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::PtrInt32);
static const std::shared_ptr<Type> type = std::shared_ptr<Type>(new Type(Kind::PtrInt32));
return type;
}
Type::Kind Type::GetKind() const { return kind_; }
const std::shared_ptr<Type>& Type::GetPtrFloatType() {
static const std::shared_ptr<Type> type(new Type(Kind::PtrFloat));
return type;
}
const std::shared_ptr<Type>& Type::GetLabelType() {
static const std::shared_ptr<Type> type(new Type(Kind::Label));
return type;
}
// Int1 类型表示布尔值,通常用于比较指令的结果
const std::shared_ptr<Type>& Type::GetInt1Type() {
static const std::shared_ptr<Type> type = std::shared_ptr<Type>(new Type(Kind::Int1));
return type;
}
// PtrInt1 类型表示指向 Int1 的指针,主要用于条件跳转等场景
const std::shared_ptr<Type>& Type::GetPtrInt1Type() {
static const std::shared_ptr<Type> type = std::shared_ptr<Type>(new Type(Kind::PtrInt1));
return type;
}
bool Type::IsVoid() const { return kind_ == Kind::Void; }
// ---------- 数组类型缓存 ----------
// 使用自定义键类型保证唯一性:元素类型指针 + 维度向量
struct ArrayKey {
const Type* elem_type;
std::vector<int> dims;
bool Type::IsInt32() const { return kind_ == Kind::Int32; }
bool operator==(const ArrayKey& other) const {
return elem_type == other.elem_type && dims == other.dims;
}
};
bool Type::IsPtrInt32() const { return kind_ == Kind::PtrInt32; }
struct ArrayKeyHash {
std::size_t operator()(const ArrayKey& key) const {
std::size_t h = std::hash<const Type*>{}(key.elem_type);
for (int d : key.dims) {
h ^= std::hash<int>{}(d) + 0x9e3779b9 + (h << 6) + (h >> 2);
}
return h;
}
};
static std::unordered_map<ArrayKey, std::weak_ptr<ArrayType>, ArrayKeyHash>& GetArrayCache() {
static std::unordered_map<ArrayKey, std::weak_ptr<ArrayType>, ArrayKeyHash> cache;
return cache;
}
std::shared_ptr<ArrayType> Type::GetArrayType(std::shared_ptr<Type> elem,
std::vector<int> dims) {
// 检查维度合法性
for (int d : dims) {
if (d <= 0) {
// SysY 数组维度必须为正整数常量表达式,这里假设已检查
return nullptr;
}
}
ArrayKey key{elem.get(), dims};
auto& cache = GetArrayCache();
auto it = cache.find(key);
if (it != cache.end()) {
auto ptr = it->second.lock();
if (ptr) return ptr;
}
auto arr = std::shared_ptr<ArrayType>(new ArrayType(std::move(elem), std::move(dims)));
cache[key] = arr;
return arr;
}
// ---------- 函数类型缓存 ----------
struct FunctionKey {
const Type* return_type;
std::vector<const Type*> param_types;
bool operator==(const FunctionKey& other) const {
return return_type == other.return_type && param_types == other.param_types;
}
};
struct FunctionKeyHash {
std::size_t operator()(const FunctionKey& key) const {
std::size_t h = std::hash<const Type*>{}(key.return_type);
for (const Type* t : key.param_types) {
h ^= std::hash<const Type*>{}(t) + 0x9e3779b9 + (h << 6) + (h >> 2);
}
return h;
}
};
static std::unordered_map<FunctionKey, std::weak_ptr<FunctionType>, FunctionKeyHash>& GetFunctionCache() {
static std::unordered_map<FunctionKey, std::weak_ptr<FunctionType>, FunctionKeyHash> cache;
return cache;
}
std::shared_ptr<FunctionType> Type::GetFunctionType(std::shared_ptr<Type> ret,
std::vector<std::shared_ptr<Type>> params) {
// 提取裸指针用于键(保证唯一性,因为 shared_ptr 指向同一对象)
std::vector<const Type*> param_ptrs;
param_ptrs.reserve(params.size());
for (const auto& p : params) {
param_ptrs.push_back(p.get());
}
FunctionKey key{ret.get(), std::move(param_ptrs)};
auto& cache = GetFunctionCache();
auto it = cache.find(key);
if (it != cache.end()) {
auto ptr = it->second.lock();
if (ptr) return ptr;
}
auto func = std::shared_ptr<FunctionType>(new FunctionType(std::move(ret), std::move(params)));
cache[key] = func;
return func;
}
// ---------- ArrayType 实现 ----------
ArrayType::ArrayType(std::shared_ptr<Type> elem, std::vector<int> dims)
: Type(Kind::Array), elem_type_(std::move(elem)), dims_(std::move(dims)) {
// 数组元素类型必须是完整类型
assert(elem_type_ && elem_type_->IsComplete());
}
size_t ArrayType::GetElementCount() const {
size_t count = 1;
for (int d : dims_) count *= d;
return count;
}
size_t ArrayType::Size() const {
return GetElementCount() * elem_type_->Size();
}
size_t ArrayType::Alignment() const {
// 数组对齐等于其元素对齐
return elem_type_->Alignment();
}
bool ArrayType::IsComplete() const {
// 维度已确定且元素类型完整,则数组完整
return !dims_.empty() && elem_type_->IsComplete();
}
// ---------- FunctionType 实现 ----------
FunctionType::FunctionType(std::shared_ptr<Type> ret,
std::vector<std::shared_ptr<Type>> params)
: Type(Kind::Function), return_type_(std::move(ret)), param_types_(std::move(params)) {}
size_t FunctionType::Size() const {
// 函数类型没有运行时大小,通常用于类型检查,返回 0
return 0;
}
size_t FunctionType::Alignment() const {
// 不对齐
return 1;
}
bool FunctionType::IsComplete() const {
// 函数类型总是完整的(只要返回类型完整,但 SysY 中 void 也视为完整)
return true;
}
} // namespace ir

@ -76,8 +76,65 @@ void Value::ReplaceAllUsesWith(Value* new_value) {
ConstantValue::ConstantValue(std::shared_ptr<Type> ty, std::string name)
: Value(std::move(ty), std::move(name)) {}
// 建一个 Argument 对象,用给定的类型和名称初始化它,并继承 Value 的所有属性和方法。
Argument::Argument(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::ConstantFloat(std::shared_ptr<Type> ty, float v)
: ConstantValue(ty, ""), value_(v) {
if (!ty->IsFloat()) {
throw std::runtime_error("ConstantFloat requires Float type");
}
}
// ConstantArray 实现
ConstantArray::ConstantArray(std::shared_ptr<ArrayType> ty,
std::vector<ConstantValue*> elements)
: ConstantValue(ty, ""), elements_(std::move(elements)) {
if (!IsValid()) {
throw std::runtime_error("Invalid constant array initialization");
}
}
bool ConstantArray::IsValid() const {
auto* array_ty = dynamic_cast<ArrayType*>(GetType().get());
if (!array_ty) return false;
// 检查元素数量是否匹配
if (elements_.size() != array_ty->GetElementCount()) return false;
// 检查每个元素的类型是否匹配数组元素类型
auto& elem_ty = array_ty->GetElementType();
for (auto* elem : elements_) {
if (elem->GetType() != elem_ty) return false;
}
return true;
}
// ConstantZero 实现
ConstantZero::ConstantZero(std::shared_ptr<Type> ty)
: ConstantValue(ty, "zero") {
// 零常量可以用于任何类型
}
std::unique_ptr<ConstantZero> ConstantZero::GetZero(std::shared_ptr<Type> ty) {
return std::make_unique<ConstantZero>(ty);
}
// ConstantAggregateZero 实现
ConstantAggregateZero::ConstantAggregateZero(std::shared_ptr<Type> ty)
: ConstantValue(ty, "zero") {
if (!ty->IsArray()) {
throw std::runtime_error("ConstantAggregateZero requires aggregate type");
}
}
std::unique_ptr<ConstantAggregateZero> ConstantAggregateZero::GetZero(std::shared_ptr<Type> ty) {
return std::make_unique<ConstantAggregateZero>(ty);
}
} // namespace ir

@ -10,4 +10,4 @@ target_link_libraries(irgen PUBLIC
build_options
${ANTLR4_RUNTIME_TARGET}
ir
)
)

@ -1,5 +1,7 @@
// IRGenDecl.cpp
#include "irgen/IRGen.h"
#include <functional>
#include <stdexcept>
#include "SysYParser.h"
@ -8,100 +10,758 @@
namespace {
std::string GetLValueName(SysYParser::LValueContext& lvalue) {
if (!lvalue.ID()) {
throw std::runtime_error(FormatError("irgen", "非法左值"));
constexpr size_t kLocalArrayHeapThresholdBytes = 1024 * 1024;
size_t GetArrayElementByteWidth(const ir::ArrayType& array_ty) {
auto* elem_ty = array_ty.GetElementType().get();
if (elem_ty->IsInt1()) {
return 1;
}
return lvalue.ID()->getText();
return 4;
}
} // namespace
size_t GetArrayStorageBytes(const ir::ArrayType& array_ty) {
return static_cast<size_t>(array_ty.GetElementCount()) *
GetArrayElementByteWidth(array_ty);
}
std::any IRGenImpl::visitBlockStmt(SysYParser::BlockStmtContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少语句块"));
bool IsZeroIRValue(const ir::Value* value) {
if (!value) {
return true;
}
for (auto* item : ctx->blockItem()) {
if (item) {
if (VisitBlockItemResult(*item) == BlockFlow::Terminated) {
// 当前语法要求 return 为块内最后一条语句;命中后可停止生成。
break;
}
}
if (auto* ci = dynamic_cast<const ir::ConstantInt*>(value)) {
return ci->GetValue() == 0;
}
return {};
if (auto* cf = dynamic_cast<const ir::ConstantFloat*>(value)) {
return cf->GetValue() == 0.0f;
}
if (dynamic_cast<const ir::ConstantZero*>(value) ||
dynamic_cast<const ir::ConstantAggregateZero*>(value)) {
return true;
}
return false;
}
IRGenImpl::BlockFlow IRGenImpl::VisitBlockItemResult(
SysYParser::BlockItemContext& item) {
return std::any_cast<BlockFlow>(item.accept(this));
bool IsZeroConstantValue(const ir::ConstantValue* value) {
return IsZeroIRValue(value);
}
std::any IRGenImpl::visitBlockItem(SysYParser::BlockItemContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少块内项"));
std::vector<ir::ConstantValue*> TrimTrailingZeroConstants(
std::vector<ir::ConstantValue*> values) {
while (!values.empty() && IsZeroConstantValue(values.back())) {
values.pop_back();
}
if (ctx->decl()) {
ctx->decl()->accept(this);
return BlockFlow::Continue;
return values;
}
std::vector<ir::Value*> BuildArrayIndices(ir::IRBuilder& builder,
const std::vector<int>& dims,
size_t flat_idx) {
std::vector<ir::Value*> indices;
indices.reserve(dims.size() + 1);
indices.push_back(builder.CreateConstInt(0));
size_t rem = flat_idx;
for (size_t i = 0; i < dims.size(); ++i) {
size_t stride = 1;
for (size_t j = i + 1; j < dims.size(); ++j) {
stride *= static_cast<size_t>(dims[j]);
}
const int idx = static_cast<int>(rem / stride);
rem %= stride;
indices.push_back(builder.CreateConstInt(idx));
}
if (ctx->stmt()) {
return ctx->stmt()->accept(this);
return indices;
}
std::vector<ir::Value*> BuildZeroIndices(ir::IRBuilder& builder,
size_t dims_count) {
std::vector<ir::Value*> indices;
indices.reserve(dims_count + 1);
for (size_t i = 0; i <= dims_count; ++i) {
indices.push_back(builder.CreateConstInt(0));
}
throw std::runtime_error(FormatError("irgen", "暂不支持的语句或声明"));
return indices;
}
// 变量声明的 IR 生成目前也是最小实现:
// - 先检查声明的基础类型,当前仅支持局部 int
// - 再把 Decl 中的变量定义交给 visitVarDef 继续处理。
//
// 和更完整的版本相比,这里还没有:
// - 一个 Decl 中多个变量定义的顺序处理;
// - const、数组、全局变量等不同声明形态
// - 更丰富的类型系统。
std::string MakeStaticArrayName(const ir::Function& func,
const std::string& var_name,
std::string suffix) {
for (char& ch : suffix) {
if (ch == '%') {
ch = '_';
}
}
return "__static_array." + func.GetName() + "." + var_name + "." + suffix;
}
} // namespace
// visitDecl: 处理声明
std::any IRGenImpl::visitDecl(SysYParser::DeclContext* ctx) {
DEBUG_MSG("[DEBUG] visitDecl: 开始处理声明");
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少变量声明"));
}
if (!ctx->btype() || !ctx->btype()->INT()) {
throw std::runtime_error(FormatError("irgen", "当前仅支持局部 int 变量声明"));
// 处理 varDecl
if (auto* varDecl = ctx->varDecl()) {
DEBUG_MSG("[DEBUG] visitDecl: 处理变量声明");
for (auto* varDef : varDecl->varDef()) {
varDef->accept(this);
}
}
auto* var_def = ctx->varDef();
if (!var_def) {
throw std::runtime_error(FormatError("irgen", "非法变量声明"));
// 处理 constDecl
if (ctx->constDecl()) {
DEBUG_MSG("[DEBUG] visitDecl: 处理常量声明");
auto* constDecl = ctx->constDecl();
for (auto* constDef : constDecl->constDef()) {
constDef->accept(this);
}
}
var_def->accept(this);
DEBUG_MSG("[DEBUG] visitDecl: 声明处理完成");
return {};
}
// 当前仍是教学用的最小版本,因此这里只支持:
// - 局部 int 变量;
// - 标量初始化;
// - 一个 VarDef 对应一个槽位。
std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) {
// visitConstDecl: 处理常量声明
std::any IRGenImpl::visitConstDecl(SysYParser::ConstDeclContext* ctx) {
DEBUG_MSG("[DEBUG] visitConstDecl: 开始处理常量声明");
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少变量定义"));
throw std::runtime_error(FormatError("irgen", "非法常量声明"));
}
for (auto* constDef : ctx->constDef()) {
if (constDef) {
constDef->accept(this);
}
}
DEBUG_MSG("[DEBUG] visitConstDecl: 常量声明处理完成");
return {};
}
// visitConstDef: 处理常量定义 - 从符号表获取常量值
std::any IRGenImpl::visitConstDef(SysYParser::ConstDefContext* ctx) {
DEBUG_MSG("[DEBUG] visitConstDef: 开始处理常量定义");
if (!ctx || !ctx->Ident()) {
throw std::runtime_error(FormatError("irgen", "非法常量定义"));
}
if (!ctx->lValue()) {
throw std::runtime_error(FormatError("irgen", "变量声明缺少名称"));
std::string const_name = ctx->Ident()->getText();
// 从符号表获取常量符号
const Symbol* sym = symbol_table_.lookupByConstDef(ctx);
if (!sym || sym->kind != SymbolKind::Constant) {
throw std::runtime_error(FormatError("irgen", "常量符号未找到: " + const_name));
}
GetLValueName(*ctx->lValue());
DEBUG_MSG("[DEBUG] visitConstDef: 从符号表获取常量 " << const_name
<< ", is_array_const: " << sym->IsArrayConstant());
// 根据符号表中的常量值创建 IR 常量
if (sym->IsArrayConstant()) {
auto* array_ty = dynamic_cast<ir::ArrayType*>(sym->type.get());
if (!array_ty) {
throw std::runtime_error(FormatError("irgen", "数组类型转换失败"));
}
const bool is_global_scope = (func_ == nullptr) || (sym->scope_level == 0);
const bool use_heap_storage = !is_global_scope &&
(current_function_is_recursive_ ||
GetArrayStorageBytes(*array_ty) > kLocalArrayHeapThresholdBytes);
// 先把符号表中的扁平初始化值转换为 IR 常量值
std::vector<ir::ConstantValue*> init_consts;
init_consts.reserve(sym->GetArraySize());
for (size_t i = 0; i < sym->GetArraySize(); ++i) {
auto elem = sym->GetArrayElement(i);
if (array_ty->GetElementType()->IsInt32()) {
init_consts.push_back(builder_.CreateConstInt(elem.i32));
} else if (array_ty->GetElementType()->IsFloat()) {
init_consts.push_back(builder_.CreateConstFloat(elem.f32));
}
}
init_consts = TrimTrailingZeroConstants(std::move(init_consts));
if (is_global_scope) {
// 全局 const 数组:全局存储,并标记为 constant
ir::GlobalValue* global_array = module_.CreateGlobal(const_name, sym->type);
if (!init_consts.empty()) {
global_array->SetInitializer(init_consts);
}
global_array->SetConstant(true);
const_global_map_[const_name] = global_array;
const_storage_map_[ctx] = global_array;
} else {
ir::Value* array_slot = nullptr;
if (use_heap_storage) {
const bool is_float_array = array_ty->GetElementType()->IsFloat();
const std::string alloc_name = is_float_array ? "sysy_alloc_f32" : "sysy_alloc_i32";
const std::string free_name = is_float_array ? "sysy_free_f32" : "sysy_free_i32";
ir::Function* alloc_func = module_.FindFunction(alloc_name);
if (!alloc_func) alloc_func = CreateRuntimeFunctionDecl(alloc_name);
ir::Function* free_func = module_.FindFunction(free_name);
if (!free_func) free_func = CreateRuntimeFunctionDecl(free_name);
array_slot = builder_.CreateCall(
alloc_func,
{builder_.CreateConstInt(static_cast<int>(array_ty->GetElementCount()))},
module_.GetContext().NextTemp());
heap_local_array_names_.insert(const_name);
RegisterCleanup(free_func, array_slot);
} else {
array_slot = CreateEntryAlloca(sym->type,
module_.GetContext().NextTemp() + "_" + const_name);
}
const auto& dims = array_ty->GetDimensions();
const size_t total_size = array_ty->GetElementCount();
if (init_consts.empty()) {
if (use_heap_storage) {
const std::string zero_name = array_ty->GetElementType()->IsFloat()
? "sysy_zero_f32"
: "sysy_zero_i32";
ir::Function* zero_func = module_.FindFunction(zero_name);
if (!zero_func) zero_func = CreateRuntimeFunctionDecl(zero_name);
builder_.CreateCall(zero_func,
{array_slot, builder_.CreateConstInt(static_cast<int>(total_size))},
module_.GetContext().NextTemp());
} else {
builder_.CreateStore(module_.GetContext().GetAggregateZero(sym->type), array_slot);
}
}
for (size_t i = 0; i < total_size; ++i) {
ir::Value* init = nullptr;
if (i < init_consts.size()) {
init = init_consts[i];
} else if (array_ty->GetElementType()->IsFloat()) {
init = builder_.CreateConstFloat(0.0f);
} else {
init = builder_.CreateConstInt(0);
}
ir::Value* elem_ptr = nullptr;
if (use_heap_storage) {
if (IsZeroIRValue(init)) {
continue;
}
elem_ptr = builder_.CreateGEP(
array_slot, {builder_.CreateConstInt(static_cast<int>(i))},
module_.GetContext().NextTemp());
} else {
elem_ptr = builder_.CreateGEP(
array_slot, BuildArrayIndices(builder_, dims, i),
module_.GetContext().NextTemp());
}
builder_.CreateStore(init, elem_ptr);
}
local_var_map_[const_name] = array_slot;
const_storage_map_[ctx] = array_slot;
}
} else if (sym->IsScalarConstant()) {
// 标量常量:存储常量值
ir::ConstantValue* const_value = nullptr;
if (sym->type->IsInt32()) {
const_value = builder_.CreateConstInt(sym->GetIntConstant());
DEBUG_MSG("[DEBUG] visitConstDef: 整型常量 " << const_name
<< " = " << sym->GetIntConstant());
} else if (sym->type->IsFloat()) {
const_value = builder_.CreateConstFloat(sym->GetFloatConstant());
DEBUG_MSG("[DEBUG] visitConstDef: 浮点常量 " << const_name
<< " = " << sym->GetFloatConstant());
}
const_value_map_[const_name] = const_value;
const_storage_map_[ctx] = const_value;
}
return {};
}
// visitVarDef: 处理变量定义 - 从符号表获取类型信息
std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) {
DEBUG_MSG("[DEBUG] visitVarDef: 开始处理变量定义");
if (!ctx || !ctx->Ident()) {
throw std::runtime_error(FormatError("irgen", "非法变量定义"));
}
std::string varName = ctx->Ident()->getText();
DEBUG_MSG("[DEBUG] visitVarDef: 变量名称: " << varName);
// 防止重复分配
if (storage_map_.find(ctx) != storage_map_.end()) {
throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位"));
throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位: " + varName));
}
// 从符号表获取变量信息
const Symbol* sym = symbol_table_.lookupByVarDef(ctx);
if (!sym) {
throw std::runtime_error(FormatError("irgen", "变量符号未找到: " + varName));
}
DEBUG_MSG("[DEBUG] visitVarDef: 变量类型: "
<< (sym->type->IsInt32() ? "int" :
sym->type->IsFloat() ? "float" :
sym->type->IsArray() ? "array" : "unknown"));
// 根据作用域处理
if (func_ == nullptr) {
DEBUG_MSG("[DEBUG] visitVarDef: 处理全局变量");
return HandleGlobalVariable(ctx, varName, sym);
} else {
DEBUG_MSG("[DEBUG] visitVarDef: 处理局部变量");
return HandleLocalVariable(ctx, varName, sym);
}
}
// HandleGlobalVariable: 处理全局变量
std::any IRGenImpl::HandleGlobalVariable(SysYParser::VarDefContext* ctx,
const std::string& varName,
const Symbol* sym) {
DEBUG_MSG("[DEBUG] HandleGlobalVariable: 开始处理全局变量 " << varName);
if (!sym) {
throw std::runtime_error(FormatError("irgen", "符号表信息缺失: " + varName));
}
bool is_array = sym->type->IsArray();
bool is_float = sym->type->IsFloat();
if (is_array) {
if (auto* array_ty = dynamic_cast<ir::ArrayType*>(sym->type.get())) {
is_float = array_ty->GetElementType()->IsFloat();
}
}
auto* slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp());
storage_map_[ctx] = slot;
if (is_array) {
// 从符号表获取数组类型和维度
auto* array_ty = dynamic_cast<ir::ArrayType*>(sym->type.get());
if (!array_ty) {
throw std::runtime_error(FormatError("irgen", "数组类型转换失败"));
}
const auto& dimensions = array_ty->GetDimensions();
size_t total_size = array_ty->GetElementCount();
DEBUG_MSG("[DEBUG] HandleGlobalVariable: 全局数组 " << varName << " 维度: ");
for (int d : dimensions) DEBUG_MSG(d << " ");
DEBUG_MSG(", 总大小: " << total_size);
// 创建全局数组
ir::GlobalValue* global_array = module_.CreateGlobal(varName, sym->type);
// 处理初始化值(使用带维度感知的展平)
std::vector<ir::ConstantValue*> init_consts;
if (auto* initVal = ctx->initVal()) {
DEBUG_MSG("[DEBUG] HandleGlobalVariable: 处理初始化值");
// 全局变量的初始化必须是常量表达式(语义检查已保证)
std::vector<ir::Value*> flat_vals = FlattenInitVal(
initVal, dimensions, is_float);
for (auto* val : flat_vals) {
if (is_float) {
if (auto* cf = dynamic_cast<ir::ConstantFloat*>(val)) {
init_consts.push_back(cf);
} else if (auto* ci = dynamic_cast<ir::ConstantInt*>(val)) {
init_consts.push_back(builder_.CreateConstFloat(static_cast<float>(ci->GetValue())));
} else {
init_consts.push_back(builder_.CreateConstFloat(0.0f));
}
} else {
if (auto* ci = dynamic_cast<ir::ConstantInt*>(val)) {
init_consts.push_back(ci);
} else if (auto* cf = dynamic_cast<ir::ConstantFloat*>(val)) {
init_consts.push_back(builder_.CreateConstInt(static_cast<int>(cf->GetValue())));
} else {
init_consts.push_back(builder_.CreateConstInt(0));
}
}
}
}
ir::Value* init = nullptr;
if (auto* init_value = ctx->initValue()) {
if (!init_value->exp()) {
throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化"));
init_consts = TrimTrailingZeroConstants(std::move(init_consts));
// 设置初始化器
if (!init_consts.empty()) {
global_array->SetInitializer(init_consts);
}
init = EvalExpr(*init_value->exp());
storage_map_[ctx] = global_array;
global_map_[varName] = global_array;
} else {
init = builder_.CreateConstInt(0);
// 全局标量变量
std::shared_ptr<ir::Type> var_type = sym->type;
ir::GlobalValue* global_var = module_.CreateGlobal(varName, var_type);
// 处理初始化值
ir::ConstantValue* init_value = nullptr;
if (auto* initVal = ctx->initVal()) {
auto result = initVal->accept(this);
if (result.has_value()) {
try {
ir::Value* val = std::any_cast<ir::Value*>(result);
if (is_float) {
if (auto* const_float = dynamic_cast<ir::ConstantFloat*>(val)) {
init_value = const_float;
} else if (auto* const_int = dynamic_cast<ir::ConstantInt*>(val)) {
init_value = builder_.CreateConstFloat(static_cast<float>(const_int->GetValue()));
}
} else {
if (auto* const_int = dynamic_cast<ir::ConstantInt*>(val)) {
init_value = const_int;
} else if (auto* const_float = dynamic_cast<ir::ConstantFloat*>(val)) {
init_value = builder_.CreateConstInt(static_cast<int>(const_float->GetValue()));
}
}
} catch (const std::bad_any_cast&) {
// 使用默认值
}
}
}
//正确:只在没有初始化值时才设置默认值
if (!init_value) {
if (is_float) {
init_value = builder_.CreateConstFloat(0.0f);
} else {
init_value = builder_.CreateConstInt(0);
}
}
global_var->SetInitializer(init_value);
storage_map_[ctx] = global_var;
global_map_[varName] = global_var;
}
DEBUG_MSG("[DEBUG] HandleGlobalVariable: 全局变量处理完成");
return {};
}
// HandleLocalVariable: 处理局部变量
std::any IRGenImpl::HandleLocalVariable(SysYParser::VarDefContext* ctx,
const std::string& varName,
const Symbol* sym) {
DEBUG_MSG("[DEBUG] HandleLocalVariable: 开始处理局部变量 " << varName);
if (!sym) {
throw std::runtime_error(FormatError("irgen", "符号表信息缺失: " + varName));
}
bool is_array = sym->type->IsArray();
bool is_float = sym->type->IsFloat();
if (is_array) {
if (auto* array_ty = dynamic_cast<ir::ArrayType*>(sym->type.get())) {
is_float = array_ty->GetElementType()->IsFloat();
}
}
if (is_array) {
// 从符号表获取数组信息
auto* array_ty = dynamic_cast<ir::ArrayType*>(sym->type.get());
if (!array_ty) {
throw std::runtime_error(FormatError("irgen", "数组类型转换失败"));
}
size_t total_size = array_ty->GetElementCount();
const size_t total_bytes = GetArrayStorageBytes(*array_ty);
const bool use_heap_storage =
current_function_is_recursive_ || total_bytes > kLocalArrayHeapThresholdBytes;
DEBUG_MSG("[DEBUG] HandleLocalVariable: 局部数组 " << varName
<< " 总大小: " << total_size);
ir::Value* array_slot = nullptr;
if (use_heap_storage) {
const std::string alloc_name = is_float ? "sysy_alloc_f32" : "sysy_alloc_i32";
const std::string free_name = is_float ? "sysy_free_f32" : "sysy_free_i32";
ir::Function* alloc_func = module_.FindFunction(alloc_name);
if (!alloc_func) {
alloc_func = CreateRuntimeFunctionDecl(alloc_name);
}
ir::Function* free_func = module_.FindFunction(free_name);
if (!free_func) {
free_func = CreateRuntimeFunctionDecl(free_name);
}
array_slot = builder_.CreateCall(
alloc_func,
{builder_.CreateConstInt(static_cast<int>(total_size))},
module_.GetContext().NextTemp());
heap_local_array_names_.insert(varName);
RegisterCleanup(free_func, array_slot);
} else {
array_slot = CreateEntryAlloca(
sym->type, module_.GetContext().NextTemp() + "_" + varName);
}
const auto& dims = array_ty->GetDimensions();
storage_map_[ctx] = array_slot;
local_var_map_[varName] = array_slot;
// 处理初始化
if (auto* initVal = ctx->initVal()) {
std::vector<ir::Value*> init_values = FlattenInitVal(
initVal, array_ty->GetDimensions(), is_float);
bool is_all_zero_init = true;
for (auto* value : init_values) {
if (!IsZeroIRValue(value)) {
is_all_zero_init = false;
break;
}
}
if (is_all_zero_init && !use_heap_storage) {
builder_.CreateStore(module_.GetContext().GetAggregateZero(sym->type),
array_slot);
DEBUG_MSG("[DEBUG] HandleLocalVariable: aggregate zeroinitializer store for "
<< varName);
return {};
}
if (use_heap_storage) {
const std::string zero_name = is_float ? "sysy_zero_f32" : "sysy_zero_i32";
ir::Function* zero_func = module_.FindFunction(zero_name);
if (!zero_func) {
zero_func = CreateRuntimeFunctionDecl(zero_name);
}
builder_.CreateCall(zero_func,
{array_slot, builder_.CreateConstInt(static_cast<int>(total_size))},
module_.GetContext().NextTemp());
if (is_all_zero_init) {
return {};
}
}
for (size_t i = 0; i < total_size; i++) {
ir::Value* val = (i < init_values.size() && init_values[i])
? init_values[i]
: (is_float ? static_cast<ir::Value*>(builder_.CreateConstFloat(0.0f))
: static_cast<ir::Value*>(builder_.CreateConstInt(0)));
if (use_heap_storage && IsZeroIRValue(val)) {
continue;
}
if (is_float && val->GetType()->IsInt32()) {
val = builder_.CreateSIToFP(val, ir::Type::GetFloatType(),
module_.GetContext().NextTemp());
} else if (!is_float && val->GetType()->IsFloat()) {
val = builder_.CreateFPToSI(val, ir::Type::GetInt32Type(),
module_.GetContext().NextTemp());
}
ir::Value* elem_ptr = nullptr;
if (use_heap_storage) {
elem_ptr = builder_.CreateGEP(
array_slot, {builder_.CreateConstInt(static_cast<int>(i))},
module_.GetContext().NextTemp());
} else {
elem_ptr = builder_.CreateGEP(
array_slot, BuildArrayIndices(builder_, dims, i),
module_.GetContext().NextTemp());
}
builder_.CreateStore(val, elem_ptr);
}
}
} else {
// 局部标量变量
ir::AllocaInst* slot;
if (is_float) {
slot = CreateEntryAllocaFloat(module_.GetContext().NextTemp() + "_" + varName);
} else {
slot = CreateEntryAllocaI32(module_.GetContext().NextTemp() + "_" + varName);
}
storage_map_[ctx] = slot;
local_var_map_[varName] = slot;
// 处理初始化
ir::Value* init = nullptr;
if (auto* initVal = ctx->initVal()) {
auto result = initVal->accept(this);
if (result.has_value()) {
try {
init = std::any_cast<ir::Value*>(result);
} catch (const std::bad_any_cast&) {
try {
auto init_vec = std::any_cast<std::vector<ir::Value*>>(result);
if (!init_vec.empty()) {
init = init_vec[0];
}
} catch (const std::bad_any_cast&) {
// 使用默认值
}
}
}
}
if (!init) {
// SysY 局部变量未显式初始化时为未定义值:不生成默认 store。
return {};
}
// 标量初始化支持 int/float 隐式转换。
if (is_float && init->GetType()->IsInt32()) {
init = builder_.CreateSIToFP(init, ir::Type::GetFloatType(),
module_.GetContext().NextTemp());
} else if (!is_float && init->GetType()->IsFloat()) {
init = builder_.CreateFPToSI(init, ir::Type::GetInt32Type(),
module_.GetContext().NextTemp());
}
builder_.CreateStore(init, slot);
}
builder_.CreateStore(init, slot);
DEBUG_MSG("[DEBUG] HandleLocalVariable: 局部变量处理完成");
return {};
}
// visitInitVal: 处理初始化值
std::any IRGenImpl::visitInitVal(SysYParser::InitValContext* ctx) {
DEBUG_MSG("[DEBUG] visitInitVal: 开始处理初始化值");
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "非法初始化值"));
}
// 如果是单个表达式
if (ctx->exp()) {
DEBUG_MSG("[DEBUG] visitInitVal: 处理表达式初始化");
return EvalExpr(*ctx->exp());
}
// 如果是聚合初始化(花括号列表)
else if (!ctx->initVal().empty()) {
DEBUG_MSG("[DEBUG] visitInitVal: 处理聚合初始化");
return ProcessNestedInitVals(ctx);
}
DEBUG_MSG("[DEBUG] visitInitVal: 空初始化列表");
return std::vector<ir::Value*>{};
}
// ProcessNestedInitVals: 处理嵌套聚合初始化
std::vector<ir::Value*> IRGenImpl::ProcessNestedInitVals(SysYParser::InitValContext* ctx) {
DEBUG_MSG("[DEBUG] ProcessNestedInitVals: 开始处理嵌套初始化值");
std::vector<ir::Value*> all_values;
for (auto* init_val : ctx->initVal()) {
auto result = init_val->accept(this);
if (result.has_value()) {
try {
// 尝试获取单个值
ir::Value* value = std::any_cast<ir::Value*>(result);
all_values.push_back(value);
DEBUG_MSG("[DEBUG] ProcessNestedInitVals: 获取到单个值");
} catch (const std::bad_any_cast&) {
try {
// 尝试获取值列表(嵌套情况)
std::vector<ir::Value*> nested_values =
std::any_cast<std::vector<ir::Value*>>(result);
DEBUG_MSG("[DEBUG] ProcessNestedInitVals: 获取到嵌套值列表, 大小: "
<< nested_values.size());
all_values.insert(all_values.end(),
nested_values.begin(), nested_values.end());
} catch (const std::bad_any_cast&) {
DEBUG_MSG("[ERROR] ProcessNestedInitVals: 不支持的初始化值类型");
throw std::runtime_error(
FormatError("irgen", "不支持的初始化值类型"));
}
}
}
}
DEBUG_MSG("[DEBUG] ProcessNestedInitVals: 共获取 " << all_values.size()
<< " 个初始化值");
return all_values;
}
// FlattenInitVal按 C 语言花括号对齐规则展平初始化列表
// dims[0] 是最外层维度dims.back() 是最内层维度(元素层)
// 总元素数 = prod(dims),结果向量长度恰好为总元素数(不足处补零)
std::vector<ir::Value*> IRGenImpl::FlattenInitVal(
SysYParser::InitValContext* ctx,
const std::vector<int>& dims,
bool is_float) {
// 计算总元素数
size_t total = 1;
for (int d : dims) total *= static_cast<size_t>(d);
// 零值工厂
auto make_zero = [&]() -> ir::Value* {
if (is_float) return builder_.CreateConstFloat(0.0f);
return builder_.CreateConstInt(0);
};
// 先全部填零
std::vector<ir::Value*> flat(total, nullptr);
// 计算 depth 层从 begin 开始的子数组跨度
// depth=0 → 每个子聚合占 dims[1]*dims[2]*... 个元素
auto subspan = [&](size_t depth) -> size_t {
size_t span = 1;
for (size_t i = depth + 1; i < dims.size(); ++i)
span *= static_cast<size_t>(dims[i]);
return span;
};
// 递归 fill_impl将 node 的内容按 C 规则写入 flat[begin..end-1],返回填完后的光标
std::function<size_t(SysYParser::InitValContext*, size_t, size_t, size_t)> fill_impl;
fill_impl = [&](SysYParser::InitValContext* node,
size_t depth,
size_t begin,
size_t end) -> size_t {
if (!node || begin >= end) return begin;
// 单标量初始化项(叶节点)
if (node->exp()) {
ir::Value* v = EvalExpr(*node->exp());
if (begin < flat.size()) flat[begin] = v;
return std::min(begin + 1, end);
}
// 聚合初始化(花括号列表)
size_t cursor = begin;
for (auto* child : node->initVal()) {
if (cursor >= end) break;
if (child->exp()) {
// 标量子项
ir::Value* v = EvalExpr(*child->exp());
if (cursor < flat.size()) flat[cursor] = v;
++cursor;
continue;
}
// 花括号子列表
if (depth + 1 < dims.size()) {
// 对齐到下一个子聚合边界
const size_t span = subspan(depth);
const size_t rel = (cursor - begin) % span;
if (rel != 0) cursor += (span - rel);
if (cursor >= end) break;
const size_t sub_end = std::min(cursor + span, end);
fill_impl(child, depth + 1, cursor, sub_end);
cursor = sub_end; // 消耗一个子聚合
} else {
// 最内层遇到额外花括号,按顺序展开
cursor = fill_impl(child, depth, cursor, end);
}
}
return cursor;
};
fill_impl(ctx, 0, 0, total);
// 把 nullptr未显式初始化替换为零值
for (auto*& v : flat) {
if (!v) v = make_zero();
}
return flat;
}

@ -6,10 +6,11 @@
#include "ir/IR.h"
#include "utils/Log.h"
// 修改 GenerateIR 函数
std::unique_ptr<ir::Module> GenerateIR(SysYParser::CompUnitContext& tree,
const SemanticContext& sema) {
const SemaResult& sema_result) {
auto module = std::make_unique<ir::Module>();
IRGenImpl gen(*module, sema);
IRGenImpl gen(*module, sema_result.context, sema_result.symbol_table);
tree.accept(&gen);
return module;
}

File diff suppressed because it is too large Load Diff

@ -1,6 +1,8 @@
#include "irgen/IRGen.h"
#include <memory>
#include <stdexcept>
#include <vector>
#include "SysYParser.h"
#include "ir/IR.h"
@ -9,7 +11,6 @@
namespace {
void VerifyFunctionStructure(const ir::Function& func) {
// 当前 IRGen 仍是单入口、顺序生成;这里在生成结束后补一层块终结校验。
for (const auto& bb : func.GetBlocks()) {
if (!bb || !bb->HasTerminator()) {
throw std::runtime_error(
@ -19,69 +20,498 @@ void VerifyFunctionStructure(const ir::Function& func) {
}
}
bool HasDirectSelfCall(antlr4::ParserRuleContext* node,
const std::string& func_name) {
if (!node) {
return false;
}
if (auto* unary = dynamic_cast<SysYParser::UnaryExpContext*>(node)) {
if (unary->Ident() && unary->Ident()->getText() == func_name) {
return true;
}
}
for (auto* child : node->children) {
if (auto* rule = dynamic_cast<antlr4::ParserRuleContext*>(child)) {
if (HasDirectSelfCall(rule, func_name)) {
return true;
}
}
}
return false;
}
} // namespace
IRGenImpl::IRGenImpl(ir::Module& module, const SemanticContext& sema)
: module_(module),
sema_(sema),
func_(nullptr),
builder_(module.GetContext(), nullptr) {}
// 编译单元的 IR 生成当前只实现了最小功能:
// - Module 已在 GenerateIR 中创建,这里只负责继续生成其中的内容;
// - 当前会读取编译单元中的函数定义,并交给 visitFuncDef 生成函数 IR
//
// 当前还没有实现:
// - 多个函数定义的遍历与生成;
// - 全局变量、全局常量的 IR 生成。
// 实现新的构造函数
IRGenImpl::IRGenImpl(ir::Module& module,
const SemanticContext& sema,
const SymbolTable& sym_table)
: module_(module), sema_(sema), symbol_table_(sym_table),
builder_(module.GetContext(), nullptr), func_(nullptr) {
AddRuntimeFunctions();
}
void IRGenImpl::AddRuntimeFunctions() {
DEBUG_MSG("[DEBUG IRGEN] 添加运行时库函数声明");
// 输入函数(返回 int
module_.CreateFunction("getint",
ir::Type::GetFunctionType(ir::Type::GetInt32Type(), {}));
module_.CreateFunction("getch",
ir::Type::GetFunctionType(ir::Type::GetInt32Type(), {}));
// getarray(int* a, int n): int
module_.CreateFunction("getarray",
ir::Type::GetFunctionType(
ir::Type::GetInt32Type(),
{ir::Type::GetPtrInt32Type()}));
// 输出函数(返回 void
module_.CreateFunction("putint",
ir::Type::GetFunctionType(
ir::Type::GetVoidType(),
{ir::Type::GetInt32Type()}));
module_.CreateFunction("putch",
ir::Type::GetFunctionType(
ir::Type::GetVoidType(),
{ir::Type::GetInt32Type()}));
// putarray(int n, int* a): void
module_.CreateFunction("putarray",
ir::Type::GetFunctionType(
ir::Type::GetVoidType(),
{ir::Type::GetInt32Type(), ir::Type::GetPtrInt32Type()}));
// 字符串输出(暂时用 int* 替代 char*
module_.CreateFunction("puts",
ir::Type::GetFunctionType(
ir::Type::GetVoidType(),
{ir::Type::GetPtrInt32Type()}));
// 时间测量函数SysY 标准库)
module_.CreateFunction("_sysy_starttime",
ir::Type::GetFunctionType(
ir::Type::GetVoidType(),
{ir::Type::GetInt32Type()}));
module_.CreateFunction("_sysy_stoptime",
ir::Type::GetFunctionType(
ir::Type::GetVoidType(),
{ir::Type::GetInt32Type()}));
// 简化版本
module_.CreateFunction("starttime",
ir::Type::GetFunctionType(ir::Type::GetVoidType(), {}));
module_.CreateFunction("stoptime",
ir::Type::GetFunctionType(ir::Type::GetVoidType(), {}));
// 浮点 I/O
module_.CreateFunction("getfloat",
ir::Type::GetFunctionType(ir::Type::GetFloatType(), {}));
module_.CreateFunction("putfloat",
ir::Type::GetFunctionType(
ir::Type::GetVoidType(),
{ir::Type::GetFloatType()}));
module_.CreateFunction("getfarray",
ir::Type::GetFunctionType(
ir::Type::GetInt32Type(),
{ir::Type::GetPtrFloatType()}));
module_.CreateFunction("putfarray",
ir::Type::GetFunctionType(
ir::Type::GetVoidType(),
{ir::Type::GetInt32Type(), ir::Type::GetPtrFloatType()}));
// 内存操作函数
module_.CreateFunction("memset",
ir::Type::GetFunctionType(
ir::Type::GetPtrInt32Type(),
{ir::Type::GetPtrInt32Type(),
ir::Type::GetInt32Type(),
ir::Type::GetInt32Type()}));
module_.CreateFunction("sysy_alloc_i32",
ir::Type::GetFunctionType(
ir::Type::GetPtrInt32Type(),
{ir::Type::GetInt32Type()}));
module_.CreateFunction("sysy_alloc_f32",
ir::Type::GetFunctionType(
ir::Type::GetPtrFloatType(),
{ir::Type::GetInt32Type()}));
module_.CreateFunction("sysy_free_i32",
ir::Type::GetFunctionType(
ir::Type::GetVoidType(),
{ir::Type::GetPtrInt32Type()}));
module_.CreateFunction("sysy_free_f32",
ir::Type::GetFunctionType(
ir::Type::GetVoidType(),
{ir::Type::GetPtrFloatType()}));
module_.CreateFunction("sysy_zero_i32",
ir::Type::GetFunctionType(
ir::Type::GetVoidType(),
{ir::Type::GetPtrInt32Type(), ir::Type::GetInt32Type()}));
module_.CreateFunction("sysy_zero_f32",
ir::Type::GetFunctionType(
ir::Type::GetVoidType(),
{ir::Type::GetPtrFloatType(), ir::Type::GetInt32Type()}));
DEBUG_MSG("[DEBUG IRGEN] 运行时库函数声明完成");
}
// 修正:没有 mainFuncDef通过函数名找到 main
std::any IRGenImpl::visitCompUnit(SysYParser::CompUnitContext* ctx) {
DEBUG_MSG("[DEBUG IRGEN] visitCompUnit");
DEBUG_MSG("[DEBUG] IRGen: 符号表地址 = " << &symbol_table_);
DEBUG_MSG("[DEBUG] IRGen: 开始生成 IR");
// 尝试查找 main 函数
const Symbol* main_sym = symbol_table_.lookup("main");
if (main_sym) {
DEBUG_MSG("[DEBUG] IRGen: 找到 main 函数符号");
} else {
DEBUG_MSG("[DEBUG] IRGen: 未找到 main 函数符号");
}
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少编译单元"));
}
auto* func = ctx->funcDef();
if (!func) {
throw std::runtime_error(FormatError("irgen", "缺少函数定义"));
// 处理全局变量声明
for (auto* decl : ctx->decl()) {
if (decl) {
decl->accept(this);
}
}
// 处理所有函数定义
for (auto* funcDef : ctx->funcDef()) {
if (funcDef) {
funcDef->accept(this);
}
}
func->accept(this);
return {};
}
// 函数 IR 生成当前实现了:
// 1. 获取函数名;
// 2. 检查函数返回类型;
// 3. 在 Module 中创建 Function
// 4. 将 builder 插入点设置到入口基本块;
// 5. 继续生成函数体。
//
// 当前还没有实现:
// - 通用函数返回类型处理;
// - 形参列表遍历与参数类型收集;
// - FunctionType 这样的函数类型对象;
// - Argument/形式参数 IR 对象;
// - 入口块中的参数初始化逻辑。
// ...
// 因此这里目前只支持最小的“无参 int 函数”生成。
std::any IRGenImpl::visitFuncDef(SysYParser::FuncDefContext* ctx) {
DEBUG_MSG("[DEBUG IRGEN] visitFuncDef: " << (ctx && ctx->Ident() ? ctx->Ident()->getText() : "<null>"));
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少函数定义"));
}
if (!ctx->blockStmt()) {
if (!ctx->Ident()) {
throw std::runtime_error(FormatError("irgen", "缺少函数名"));
}
std::string funcName = ctx->Ident()->getText();
if (!ctx->block()) {
throw std::runtime_error(FormatError("irgen", "函数体为空"));
}
if (!ctx->ID()) {
throw std::runtime_error(FormatError("irgen", "缺少函数名"));
std::shared_ptr<ir::Type> ret_type = ir::Type::GetInt32Type();
if (ctx->funcType()) {
if (ctx->funcType()->Void()) {
ret_type = ir::Type::GetVoidType();
} else if (ctx->funcType()->Int()) {
ret_type = ir::Type::GetInt32Type();
} else if (ctx->funcType()->Float()) {
ret_type = ir::Type::GetFloatType();
}
}
if (!ctx->funcType() || !ctx->funcType()->INT()) {
throw std::runtime_error(FormatError("irgen", "当前仅支持无参 int 函数"));
std::vector<std::shared_ptr<ir::Type>> param_types;
if (ctx->funcFParams()) {
for (auto* param : ctx->funcFParams()->funcFParam()) {
if (!param || !param->Ident()) continue;
std::string name = param->Ident()->getText();
std::shared_ptr<ir::Type> param_ty;
// 检查 bType 是否存在
if (!param->bType()) {
throw std::runtime_error(FormatError("irgen", "函数参数缺少类型: " + name));
}
if (param->bType()->Int()) {
param_ty = ir::Type::GetInt32Type();
} else if (param->bType()->Float()) {
param_ty = ir::Type::GetFloatType();
} else {
param_ty = ir::Type::GetInt32Type(); // 默认值
}
if (!param->L_BRACK().empty()) {
if (param_ty->IsInt32()) {
param_ty = ir::Type::GetPtrInt32Type();
} else if (param_ty->IsFloat()) {
param_ty = ir::Type::GetPtrFloatType();
}
}
param_types.push_back(param_ty);
}
}
func_ = module_.CreateFunction(ctx->ID()->getText(), ir::Type::GetInt32Type());
builder_.SetInsertPoint(func_->GetEntry());
// 创建函数类型
auto func_type = ir::Type::GetFunctionType(ret_type, param_types);
// 调试输出
DEBUG_MSG("[DEBUG] visitFuncDef: 创建函数 " << funcName
<< ",返回类型: " << (ret_type->IsVoid() ? "void" : ret_type->IsFloat() ? "float" : "int")
<< ",参数数量: " << param_types.size());
// 创建函数对象
func_ = module_.CreateFunction(funcName, func_type);
// 检查函数是否成功创建
if (!func_) {
DEBUG_MSG("[ERROR] visitFuncDef: 创建函数失败func_ 为 nullptr!");
throw std::runtime_error(FormatError("irgen", "创建函数失败: " + funcName));
}
DEBUG_MSG("[DEBUG] visitFuncDef: 函数对象地址: " << (void*)func_);
// 设置插入点
auto* entry_block = func_->GetEntry();
if (!entry_block) {
DEBUG_MSG("[ERROR] visitFuncDef: 函数入口基本块为空!");
throw std::runtime_error(FormatError("irgen", "函数入口基本块为空: " + funcName));
}
builder_.SetInsertPoint(entry_block);
storage_map_.clear();
param_map_.clear();
pointer_param_names_.clear();
heap_local_array_names_.clear();
current_function_name_ = funcName;
current_function_is_recursive_ = HasDirectSelfCall(ctx->block(), funcName);
function_cleanup_block_ = nullptr;
function_cleanup_actions_.clear();
function_return_slot_ = nullptr;
if (ret_type->IsInt32()) {
function_return_slot_ = CreateEntryAllocaI32(module_.GetContext().NextTemp() + ".retval");
} else if (ret_type->IsFloat()) {
function_return_slot_ = CreateEntryAllocaFloat(module_.GetContext().NextTemp() + ".retval");
}
// 函数参数处理
if (ctx->funcFParams()) {
for (auto* param : ctx->funcFParams()->funcFParam()) {
if (!param || !param->Ident()) continue;
std::string name = param->Ident()->getText();
std::shared_ptr<ir::Type> param_ty;
// 再次检查 bType
if (!param->bType()) {
throw std::runtime_error(FormatError("irgen", "函数参数缺少类型: " + name));
}
if (param->bType()->Int()) {
param_ty = ir::Type::GetInt32Type();
} else if (param->bType()->Float()) {
param_ty = ir::Type::GetFloatType();
} else {
param_ty = ir::Type::GetInt32Type();
}
if (!param->L_BRACK().empty()) {
if (param_ty->IsInt32()) {
param_ty = ir::Type::GetPtrInt32Type();
} else if (param_ty->IsFloat()) {
param_ty = ir::Type::GetPtrFloatType();
}
}
// 检查函数对象是否有效
if (!func_) {
DEBUG_MSG("[ERROR] visitFuncDef: func_ 在添加参数时变为 nullptr!");
throw std::runtime_error(FormatError("irgen", "函数对象无效"));
}
DEBUG_MSG("[DEBUG] visitFuncDef: 为函数 " << funcName
<< " 添加参数 " << name << ",类型: "
<< (param_ty->IsInt32() ? "int32" : param_ty->IsFloat() ? "float" :
param_ty->IsPtrInt32() ? "ptr_int32" : param_ty->IsPtrFloat() ? "ptr_float" : "other")
);
// 创建参数并添加到函数
auto arg = std::make_unique<ir::Argument>(param_ty, name);
if (!arg) {
throw std::runtime_error(FormatError("irgen", "创建参数失败: " + name));
}
auto* arg_ptr = arg.get();
auto* added_arg = func_->AddArgument(std::move(arg));
if (!added_arg) {
DEBUG_MSG("[ERROR] visitFuncDef: AddArgument 返回 nullptr!");
throw std::runtime_error(FormatError("irgen", "添加参数失败: " + name));
}
// 标量参数:入栈到本地槽位;数组参数(指针)直接作为地址使用。
if (param_ty->IsPtrInt32() || param_ty->IsPtrFloat()) {
param_map_[name] = added_arg;
pointer_param_names_.insert(name);
} else {
ir::AllocaInst* slot = nullptr;
if (param_ty->IsInt32()) {
slot = CreateEntryAllocaI32(module_.GetContext().NextTemp());
} else if (param_ty->IsFloat()) {
slot = CreateEntryAllocaFloat(module_.GetContext().NextTemp());
} else {
throw std::runtime_error(FormatError("irgen", "不支持的参数类型"));
}
if (!slot) {
throw std::runtime_error(FormatError("irgen", "创建参数存储槽位失败: " + name));
}
builder_.CreateStore(added_arg, slot);
param_map_[name] = slot;
pointer_param_names_.erase(name);
}
DEBUG_MSG("[DEBUG] visitFuncDef: 参数 " << name << " 处理完成");
}
}
// 生成函数体
DEBUG_MSG("[DEBUG] visitFuncDef: 开始生成函数体");
ctx->block()->accept(this);
ctx->blockStmt()->accept(this);
// 语义正确性主要由 sema 保证,这里只兜底检查 IR 结构是否合法。
VerifyFunctionStructure(*func_);
// 如果当前插入块没有终止指令,添加默认返回
if (auto* cur = builder_.GetInsertBlock(); cur && !cur->HasTerminator()) {
DEBUG_MSG("[DEBUG] visitFuncDef: 函数体没有终止指令,添加默认返回");
if (function_cleanup_block_) {
if (ret_type->IsFloat()) {
builder_.CreateStore(builder_.CreateConstFloat(0.0f), function_return_slot_);
} else if (ret_type->IsInt32()) {
builder_.CreateStore(builder_.CreateConstInt(0), function_return_slot_);
}
builder_.CreateBr(function_cleanup_block_);
} else if (ret_type->IsVoid()) {
builder_.CreateRet(nullptr);
} else if (ret_type->IsFloat()) {
builder_.CreateRet(builder_.CreateConstFloat(0.0f));
} else {
builder_.CreateRet(builder_.CreateConstInt(0));
}
}
if (function_cleanup_block_ && !function_cleanup_block_->HasTerminator()) {
builder_.SetInsertPoint(function_cleanup_block_);
for (auto it = function_cleanup_actions_.rbegin();
it != function_cleanup_actions_.rend(); ++it) {
builder_.CreateCall(it->first, {it->second}, module_.GetContext().NextTemp());
}
if (ret_type->IsVoid()) {
builder_.CreateRet(nullptr);
} else {
builder_.CreateRet(builder_.CreateLoad(function_return_slot_, module_.GetContext().NextTemp()));
}
}
// 验证函数结构
try {
VerifyFunctionStructure(*func_);
} catch (const std::exception& e) {
DEBUG_MSG("[ERROR] visitFuncDef: 验证函数结构失败: " << e.what());
throw;
}
DEBUG_MSG("[DEBUG] visitFuncDef: 函数 " << funcName << " 生成完成");
func_ = nullptr;
current_function_name_.clear();
current_function_is_recursive_ = false;
function_return_slot_ = nullptr;
function_cleanup_block_ = nullptr;
function_cleanup_actions_.clear();
return {};
}
ir::BasicBlock* IRGenImpl::EnsureCleanupBlock() {
if (!function_cleanup_block_) {
std::string name = module_.GetContext().NextTemp();
if (!name.empty() && name[0] == '%') {
name.erase(0, 1);
}
function_cleanup_block_ = func_->CreateBlock("cleanup." + name);
}
return function_cleanup_block_;
}
void IRGenImpl::RegisterCleanup(ir::Function* free_func, ir::Value* ptr) {
if (!free_func || !ptr) {
return;
}
EnsureCleanupBlock();
function_cleanup_actions_.push_back({free_func, ptr});
}
ir::AllocaInst* IRGenImpl::CreateEntryAlloca(std::shared_ptr<ir::Type> ty,
const std::string& name) {
if (!func_ || !func_->GetEntry()) {
throw std::runtime_error(FormatError("irgen", "缺少函数入口块,无法创建入口栈槽位"));
}
return func_->GetEntry()->InsertBeforeTerminator<ir::AllocaInst>(ty, name);
}
ir::AllocaInst* IRGenImpl::CreateEntryAllocaI32(const std::string& name) {
return CreateEntryAlloca(ir::Type::GetPtrInt32Type(), name);
}
ir::AllocaInst* IRGenImpl::CreateEntryAllocaFloat(const std::string& name) {
return CreateEntryAlloca(ir::Type::GetPtrFloatType(), name);
}
std::any IRGenImpl::visitBlock(SysYParser::BlockContext* ctx) {
DEBUG_MSG("[DEBUG IRGEN] visitBlock: " << (ctx ? ctx->getText() : "<null>"));
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少语句块"));
}
BlockFlow flow = BlockFlow::Continue;
for (auto* item : ctx->blockItem()) {
if (!item) continue;
flow = VisitBlockItemResult(*item);
if (flow == BlockFlow::Terminated) {
break;
}
auto* cur = builder_.GetInsertBlock();
DEBUG_MSG("[DEBUG] current insert block: "
<< (cur ? cur->GetName() : "<null>"));
if (cur && cur->HasTerminator()) {
break;
}
}
return flow;
}
// 类型安全的包装器
IRGenImpl::BlockFlow IRGenImpl::VisitBlockItemResult(
SysYParser::BlockItemContext& item) {
auto result = item.accept(this);// 调用 visitBlockItem返回 std::any 包装的 BlockFlow
return std::any_cast<BlockFlow>(result); // 解包为 BlockFlow
}
// 用于遍历块内项,返回是否继续访问后续项(如遇到 return/break/continue 则终止访问)
std::any IRGenImpl::visitBlockItem(SysYParser::BlockItemContext* ctx) {
DEBUG_MSG("[DEBUG IRGEN] visitBlockItem: " << (ctx ? ctx->getText() : "<null>"));
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少块内项"));
}
// 块内项可以是语句或声明,优先处理语句(如 return/break/continue 可能终止块内执行)
if (ctx->stmt()) {
return ctx->stmt()->accept(this); // 语句访问返回 BlockFlow指示是否继续访问后续项
}
// 处理声明(如变量定义),继续访问后续项
if (ctx->decl()) {
ctx->decl()->accept(this);
return BlockFlow::Continue; // 声明不会终止块内执行,继续访问后续项
}
throw std::runtime_error(FormatError("irgen", "暂不支持的块内项"));
}

@ -16,24 +16,512 @@
// - 空语句、块语句嵌套分发之外的更多语句形态
std::any IRGenImpl::visitStmt(SysYParser::StmtContext* ctx) {
DEBUG_MSG("[DEBUG IRGEN] visitStmt: " << (ctx ? ctx->getText() : "<null>"));
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少语句"));
}
if (ctx->returnStmt()) {
return ctx->returnStmt()->accept(this);
// return 语句 - 通过 Return() 关键字判断
if (ctx->Return()) {
return HandleReturnStmt(ctx);
}
// 赋值语句
if (ctx->lVal() && ctx->Assign() && ctx->exp()) {
return HandleAssignStmt(ctx);
}
// if 语句
if (ctx->If()) {
return HandleIfStmt(ctx);
}
// while 语句
if (ctx->While()) {
return HandleWhileStmt(ctx);
}
// break 语句
if (ctx->Break()) {
return HandleBreakStmt(ctx);
}
// continue 语句
if (ctx->Continue()) {
return HandleContinueStmt(ctx);
}
// 块语句
if (ctx->block()) {
return ctx->block()->accept(this);
}
// 空语句或表达式语句(先计算表达式)
if (ctx->exp()) {
EvalExpr(*ctx->exp());
return BlockFlow::Continue;
}
throw std::runtime_error(FormatError("irgen", "暂不支持的语句类型"));
}
// 修改 HandleReturnStmt 函数
std::any IRGenImpl::visitReturnStmt(SysYParser::ReturnStmtContext* ctx) {
IRGenImpl::BlockFlow IRGenImpl::HandleReturnStmt(SysYParser::StmtContext* ctx) {
DEBUG_MSG("[DEBUG IRGEN] HandleReturnStmt: " << (ctx ? ctx->getText() : "<null>"));
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少 return 语句"));
}
if (!ctx->exp()) {
throw std::runtime_error(FormatError("irgen", "return 缺少表达式"));
// 检查函数是否存在
if (!func_) {
throw std::runtime_error(FormatError("irgen", "Return语句不在函数中"));
}
// 获取函数类型中的返回类型
auto func_type = std::dynamic_pointer_cast<ir::FunctionType>(func_->GetType());
if (!func_type) {
throw std::runtime_error(FormatError("irgen", "函数类型无效"));
}
auto ret_type = func_type->GetReturnType();
if (ret_type->IsVoid()) {
if (ctx->exp()) {
// 表达式被忽略(可计算但不使用)
EvalExpr(*ctx->exp());
}
if (function_cleanup_block_) {
builder_.CreateBr(function_cleanup_block_);
} else {
// 对于void函数创建返回指令不传参数
builder_.CreateRet(nullptr);
}
} else {
ir::Value* retValue = nullptr;
if (ctx->exp()) {
retValue = EvalExpr(*ctx->exp());
if (!retValue) {
throw std::runtime_error(FormatError("irgen", "返回值表达式求值失败"));
}
// 类型转换
if (retValue->GetType() != ret_type) {
if (ret_type->IsInt32() && retValue->GetType()->IsFloat()) {
retValue = builder_.CreateFPToSI(retValue, ir::Type::GetInt32Type());
} else if (ret_type->IsFloat() && retValue->GetType()->IsInt32()) {
retValue = builder_.CreateSIToFP(retValue, ir::Type::GetFloatType());
}
}
} else {
// 无表达式,返回默认值
if (ret_type->IsInt32()) {
retValue = builder_.CreateConstInt(0);
} else if (ret_type->IsFloat()) {
retValue = builder_.CreateConstFloat(0.0f);
} else {
retValue = builder_.CreateConstInt(0); // fallback
}
}
if (function_cleanup_block_) {
builder_.CreateStore(retValue, function_return_slot_);
builder_.CreateBr(function_cleanup_block_);
} else {
builder_.CreateRet(retValue);
}
}
ir::Value* v = EvalExpr(*ctx->exp());
builder_.CreateRet(v);
return BlockFlow::Terminated;
}
// if语句待实现
IRGenImpl::BlockFlow IRGenImpl::HandleIfStmt(SysYParser::StmtContext* ctx) {
DEBUG_MSG("[DEBUG IRGEN] HandleIfStmt: " << (ctx ? ctx->getText() : "<null>"));
auto* cond = ctx->cond();
auto* thenStmt = ctx->stmt(0);
auto* elseStmt = ctx->stmt(1);
// 创建基本块(使用唯一名称,避免同名标签)
auto uniq = [&](const std::string& prefix) {
std::string t = module_.GetContext().NextTemp();
if (!t.empty() && t[0] == '%') t.erase(0, 1);
return prefix + "." + t;
};
auto* thenBlock = func_->CreateBlock(uniq("then"));
auto* elseBlock = (ctx->Else() && elseStmt) ? func_->CreateBlock(uniq("else")) : nullptr;
auto* mergeBlock = func_->CreateBlock(uniq("merge"));
DEBUG_MSG("[DEBUG IF] thenBlock: " << thenBlock->GetName());
if (elseBlock) DEBUG_MSG("[DEBUG IF] elseBlock: " << elseBlock->GetName());
DEBUG_MSG("[DEBUG IF] mergeBlock: " << mergeBlock->GetName());
DEBUG_MSG("[DEBUG IF] current insert block before cond: "
<< builder_.GetInsertBlock()->GetName());
// 生成条件
auto* condValue = EvalCond(*cond);
if (!condValue->GetType()->IsInt1()) {
if (condValue->GetType()->IsFloat()) {
condValue = builder_.CreateFCmpONE(
condValue, builder_.CreateConstFloat(0.0f), module_.GetContext().NextTemp());
} else {
condValue = builder_.CreateICmpNE(
condValue, builder_.CreateConstInt(0), module_.GetContext().NextTemp());
}
}
// 创建条件跳转
if (elseBlock) {
DEBUG_MSG("[DEBUG IF] Creating condbr: " << condValue->GetName()
<< " -> " << thenBlock->GetName() << ", " << elseBlock->GetName());
builder_.CreateCondBr(condValue, thenBlock, elseBlock);
} else {
DEBUG_MSG("[DEBUG IF] Creating condbr: " << condValue->GetName()
<< " -> " << thenBlock->GetName() << ", " << mergeBlock->GetName());
builder_.CreateCondBr(condValue, thenBlock, mergeBlock);
}
// 生成 then 分支
DEBUG_MSG("[DEBUG IF] Generating then branch in block: " << thenBlock->GetName());
builder_.SetInsertPoint(thenBlock);
auto thenResult = thenStmt->accept(this);
bool thenTerminated = (std::any_cast<BlockFlow>(thenResult) == BlockFlow::Terminated);
DEBUG_MSG("[DEBUG IF] then branch terminated: " << thenTerminated);
if (!thenTerminated) {
DEBUG_MSG("[DEBUG IF] Adding br to merge block from then");
builder_.CreateBr(mergeBlock);
}
DEBUG_MSG("[DEBUG IF] then block has terminator: " << thenBlock->HasTerminator());
// 生成 else 分支
bool elseTerminated = false;
if (elseBlock) {
DEBUG_MSG("[DEBUG IF] Generating else branch in block: " << elseBlock->GetName());
builder_.SetInsertPoint(elseBlock);
auto elseResult = elseStmt->accept(this);
elseTerminated = (std::any_cast<BlockFlow>(elseResult) == BlockFlow::Terminated);
DEBUG_MSG("[DEBUG IF] else branch terminated: " << elseTerminated);
if (!elseTerminated) {
DEBUG_MSG("[DEBUG IF] Adding br to merge block from else");
builder_.CreateBr(mergeBlock);
}
DEBUG_MSG("[DEBUG IF] else block has terminator: " << elseBlock->HasTerminator());
}
// 决定后续插入点
DEBUG_MSG("[DEBUG IF] thenTerminated=" << thenTerminated
<< ", elseTerminated=" << elseTerminated);
if (elseBlock) {
DEBUG_MSG("[DEBUG IF] Setting insert point to merge block: "
<< mergeBlock->GetName());
builder_.SetInsertPoint(mergeBlock);
} else {
DEBUG_MSG("[DEBUG IF] No else, setting insert point to merge block: "
<< mergeBlock->GetName());
builder_.SetInsertPoint(mergeBlock);
}
DEBUG_MSG("[DEBUG IF] Final insert block: "
<< builder_.GetInsertBlock()->GetName());
return BlockFlow::Continue;
}
// while语句待实现IRGenImpl::BlockFlow IRGenImpl::HandleWhileStmt(SysYParser::StmtContext* ctx) {
IRGenImpl::BlockFlow IRGenImpl::HandleWhileStmt(SysYParser::StmtContext* ctx) {
DEBUG_MSG("[DEBUG IRGEN] HandleWhileStmt: " << (ctx ? ctx->getText() : "<null>"));
if (!ctx || !ctx->cond() || !ctx->stmt(0)) {
throw std::runtime_error(FormatError("irgen", "非法 while 语句"));
}
DEBUG_MSG("[DEBUG WHILE] Current insert block before while: "
<< builder_.GetInsertBlock()->GetName());
auto uniq = [&](const std::string& prefix) {
std::string t = module_.GetContext().NextTemp();
if (!t.empty() && t[0] == '%') t.erase(0, 1);
return prefix + "." + t;
};
auto* condBlock = func_->CreateBlock(uniq("while.cond"));
auto* bodyBlock = func_->CreateBlock(uniq("while.body"));
auto* exitBlock = func_->CreateBlock(uniq("while.exit"));
DEBUG_MSG("[DEBUG WHILE] condBlock: " << condBlock->GetName());
DEBUG_MSG("[DEBUG WHILE] bodyBlock: " << bodyBlock->GetName());
DEBUG_MSG("[DEBUG WHILE] exitBlock: " << exitBlock->GetName());
DEBUG_MSG("[DEBUG WHILE] Adding br to condBlock from current block");
builder_.CreateBr(condBlock);
loopStack_.push_back({condBlock, bodyBlock, exitBlock});
DEBUG_MSG("[DEBUG WHILE] loopStack size: " << loopStack_.size());
// 条件块
DEBUG_MSG("[DEBUG WHILE] Generating condition in block: " << condBlock->GetName());
builder_.SetInsertPoint(condBlock);
auto* condValue = EvalCond(*ctx->cond());
if (!condValue->GetType()->IsInt1()) {
if (condValue->GetType()->IsFloat()) {
condValue = builder_.CreateFCmpONE(
condValue, builder_.CreateConstFloat(0.0f), module_.GetContext().NextTemp());
} else {
condValue = builder_.CreateICmpNE(
condValue, builder_.CreateConstInt(0), module_.GetContext().NextTemp());
}
}
builder_.CreateCondBr(condValue, bodyBlock, exitBlock);
DEBUG_MSG("[DEBUG WHILE] condBlock has terminator: " << condBlock->HasTerminator());
// 循环体
DEBUG_MSG("[DEBUG WHILE] Generating body in block: " << bodyBlock->GetName());
builder_.SetInsertPoint(bodyBlock);
auto bodyResult = ctx->stmt(0)->accept(this);
bool bodyTerminated = (std::any_cast<BlockFlow>(bodyResult) == BlockFlow::Terminated);
DEBUG_MSG("[DEBUG WHILE] body terminated: " << bodyTerminated);
if (!bodyTerminated) {
DEBUG_MSG("[DEBUG WHILE] Adding br to condBlock from body");
builder_.CreateBr(condBlock);
}
DEBUG_MSG("[DEBUG WHILE] bodyBlock has terminator: " << bodyBlock->HasTerminator());
loopStack_.pop_back();
DEBUG_MSG("[DEBUG WHILE] loopStack size after pop: " << loopStack_.size());
// 设置插入点为 exitBlock
DEBUG_MSG("[DEBUG WHILE] Setting insert point to exitBlock: " << exitBlock->GetName());
builder_.SetInsertPoint(exitBlock);
DEBUG_MSG("[DEBUG WHILE] exitBlock has terminator before return: "
<< exitBlock->HasTerminator());
return BlockFlow::Continue;
}
// break语句待实现
IRGenImpl::BlockFlow IRGenImpl::HandleBreakStmt(SysYParser::StmtContext* ctx) {
DEBUG_MSG("[DEBUG IRGEN] HandleBreakStmt: " << (ctx ? ctx->getText() : "<null>"));
if (loopStack_.empty()) {
throw std::runtime_error(FormatError("irgen", "break 语句不在循环中"));
}
DEBUG_MSG("[DEBUG BREAK] Current insert block before break: "
<< builder_.GetInsertBlock()->GetName());
DEBUG_MSG("[DEBUG BREAK] Breaking to exitBlock: "
<< loopStack_.back().exitBlock->GetName());
// 跳转到循环退出块
builder_.CreateBr(loopStack_.back().exitBlock);
// break 本身就是终止当前路径,后续 unreachable 代码不需要继续生成。
return BlockFlow::Terminated;
}
IRGenImpl::BlockFlow IRGenImpl::HandleContinueStmt(SysYParser::StmtContext* ctx) {
DEBUG_MSG("[DEBUG IRGEN] HandleContinueStmt: " << (ctx ? ctx->getText() : "<null>"));
if (loopStack_.empty()) {
throw std::runtime_error(FormatError("irgen", "continue 语句不在循环中"));
}
DEBUG_MSG("[DEBUG CONTINUE] Current insert block before continue: "
<< builder_.GetInsertBlock()->GetName());
DEBUG_MSG("[DEBUG CONTINUE] Continuing to condBlock: "
<< loopStack_.back().condBlock->GetName());
// 跳转到循环条件块
builder_.CreateBr(loopStack_.back().condBlock);
// continue 本身就是终止当前路径,后续 unreachable 代码不需要继续生成。
return BlockFlow::Terminated;
}
// 赋值语句(待实现)
// 赋值语句
// 赋值语句
IRGenImpl::BlockFlow IRGenImpl::HandleAssignStmt(SysYParser::StmtContext* ctx) {
DEBUG_MSG("[DEBUG IRGEN] HandleAssignStmt: " << (ctx ? ctx->getText() : "<null>"));
if (!ctx || !ctx->lVal() || !ctx->exp()) {
throw std::runtime_error(FormatError("irgen", "非法赋值语句"));
}
// 计算右值
ir::Value* rhs = EvalExpr(*ctx->exp());
if (!rhs) {
throw std::runtime_error(FormatError("irgen", "赋值 RHS 计算失败"));
}
auto* lval = ctx->lVal();
std::string varName = lval->Ident()->getText();
DEBUG_MSG("[DEBUG] HandleAssignStmt: assigning to " << varName);
// 1. 检查是否为常量(不能给常量赋值)
auto* const_decl = sema_.ResolveConstUse(lval);
if (const_decl) {
throw std::runtime_error(
FormatError("irgen", "不能给常量赋值: " + varName));
}
// 2. 查找存储位置
ir::Value* base_ptr = nullptr;
// 2.1 尝试通过语义分析获取变量定义,并从 storage_map_ 查找
auto* var_decl = sema_.ResolveVarUse(lval);
if (var_decl) {
auto it = storage_map_.find(var_decl);
if (it != storage_map_.end()) {
base_ptr = it->second;
DEBUG_MSG("[DEBUG] HandleAssignStmt: found in storage_map_ for " << varName
<< ", ptr = " << (void*)base_ptr);
}
}
// 2.2 从参数映射查找(关键!)
if (!base_ptr) {
auto it2 = param_map_.find(varName);
if (it2 != param_map_.end()) {
base_ptr = it2->second;
DEBUG_MSG("[DEBUG] HandleAssignStmt: found in param_map_ for " << varName
<< ", ptr = " << (void*)base_ptr);
}
}
// 2.3 从全局变量映射查找
if (!base_ptr) {
auto it3 = global_map_.find(varName);
if (it3 != global_map_.end()) {
base_ptr = it3->second;
DEBUG_MSG("[DEBUG] HandleAssignStmt: found in global_map_ for " << varName
<< ", ptr = " << (void*)base_ptr);
}
}
// 2.4 从局部变量映射查找fallback
if (!base_ptr) {
auto it4 = local_var_map_.find(varName);
if (it4 != local_var_map_.end()) {
base_ptr = it4->second;
DEBUG_MSG("[DEBUG] HandleAssignStmt: found in local_var_map_ for " << varName
<< ", ptr = " << (void*)base_ptr);
}
}
// 如果还是找不到,才报错
if (!base_ptr) {
throw std::runtime_error(
FormatError("irgen", "变量声明缺少存储槽位: " + varName));
}
// 3. 检查是否有数组下标
auto exp_list = lval->exp();
if (!exp_list.empty()) {
// 数组元素赋值
std::vector<ir::Value*> idx_vals;
for (auto* exp : exp_list) {
ir::Value* index = EvalExpr(*exp);
idx_vals.push_back(index);
}
ir::Value* elem_ptr = nullptr;
// 扁平数组/数组参数T*)的多维访问:先线性化,再单索引 GEP。
if ((base_ptr->GetType()->IsPtrInt32() || base_ptr->GetType()->IsPtrFloat()) && idx_vals.size() > 1) {
const Symbol* var_sym = symbol_table_.lookup(varName);
if (!var_sym && var_decl) {
var_sym = symbol_table_.lookupByVarDef(var_decl);
}
if (!var_sym) {
var_sym = symbol_table_.lookupAll(varName);
}
std::vector<int> dims;
if (var_sym) {
if (var_sym->is_array_param && !var_sym->array_dims.empty()) {
dims = var_sym->array_dims;
} else if (var_sym->type && var_sym->type->IsArray()) {
auto* at = dynamic_cast<ir::ArrayType*>(var_sym->type.get());
if (at) dims = at->GetDimensions();
}
}
if (dims.empty() && var_decl) {
for (auto* cexp : var_decl->constExp()) {
dims.push_back(symbol_table_.EvaluateConstExp(cexp));
}
}
ir::Value* flat = nullptr;
for (size_t i = 0; i < idx_vals.size(); ++i) {
ir::Value* term = idx_vals[i];
if (!term) continue;
int mult = 1;
if (!dims.empty() && i + 1 < dims.size()) {
for (size_t j = i + 1; j < dims.size(); ++j) {
if (dims[j] > 0) mult *= dims[j];
}
}
if (mult != 1) {
auto* mval = builder_.CreateConstInt(mult);
term = builder_.CreateMul(term, mval, module_.GetContext().NextTemp());
}
if (!flat) flat = term;
else flat = builder_.CreateAdd(flat, term, module_.GetContext().NextTemp());
}
if (!flat) flat = builder_.CreateConstInt(0);
std::vector<ir::Value*> gep_indices = {flat};
elem_ptr = builder_.CreateGEP(base_ptr, gep_indices, module_.GetContext().NextTemp());
} else {
std::vector<ir::Value*> indices;
if (base_ptr->GetType()->IsPtrInt32() || base_ptr->GetType()->IsPtrFloat()) {
for (auto* v : idx_vals) indices.push_back(v);
} else {
indices.push_back(builder_.CreateConstInt(0));
for (auto* v : idx_vals) indices.push_back(v);
}
elem_ptr = builder_.CreateGEP(base_ptr, indices, module_.GetContext().NextTemp());
}
if (elem_ptr->GetType()->IsPtrFloat() && rhs->GetType()->IsInt32()) {
rhs = builder_.CreateSIToFP(rhs, ir::Type::GetFloatType(),
module_.GetContext().NextTemp());
} else if (elem_ptr->GetType()->IsPtrInt32() && rhs->GetType()->IsFloat()) {
rhs = builder_.CreateFPToSI(rhs, ir::Type::GetInt32Type(),
module_.GetContext().NextTemp());
}
builder_.CreateStore(rhs, elem_ptr);
} else {
// 普通标量赋值
DEBUG_MSG("[DEBUG] HandleAssignStmt: scalar assignment to " << varName
<< ", ptr = " << (void*)base_ptr
<< ", rhs = " << (void*)rhs);
// 在 HandleAssignStmt 中,存储前添加类型调试
if (base_ptr && base_ptr->GetType()) {
DEBUG_MSG("[DEBUG] Is int32: " << base_ptr->GetType()->IsInt32());
DEBUG_MSG("[DEBUG] Is float: " << base_ptr->GetType()->IsFloat());
DEBUG_MSG("[DEBUG] Is ptr int32: " << base_ptr->GetType()->IsPtrInt32());
DEBUG_MSG("[DEBUG] Is ptr float: " << base_ptr->GetType()->IsPtrFloat());
DEBUG_MSG("[DEBUG] Is array: " << base_ptr->GetType()->IsArray());
}
if (rhs && rhs->GetType()) {
DEBUG_MSG("[DEBUG] Value is int32: " << rhs->GetType()->IsInt32());
}
if (base_ptr->GetType()->IsPtrFloat() && rhs->GetType()->IsInt32()) {
rhs = builder_.CreateSIToFP(rhs, ir::Type::GetFloatType(),
module_.GetContext().NextTemp());
} else if (base_ptr->GetType()->IsPtrInt32() && rhs->GetType()->IsFloat()) {
rhs = builder_.CreateFPToSI(rhs, ir::Type::GetInt32Type(),
module_.GetContext().NextTemp());
}
builder_.CreateStore(rhs, base_ptr);
}
return BlockFlow::Continue;
}

@ -46,13 +46,17 @@ int main(int argc, char** argv) {
}
if (opts.emit_asm) {
auto machine_func = mir::LowerToMIR(*module);
mir::RunRegAlloc(*machine_func);
mir::RunFrameLowering(*machine_func);
//auto machine_func = mir::LowerToMIR(*module);
auto machine_module = mir::LowerToMIR(*module);
//mir::RunRegAlloc(*machine_func);
mir::RunRegAlloc(*machine_module);
//mir::RunFrameLowering(*machine_func);
mir::RunFrameLowering(*machine_module);
if (need_blank_line) {
std::cout << "\n";
}
mir::PrintAsm(*machine_func, std::cout);
//mir::PrintAsm(*machine_func, std::cout);
mir::PrintAsm(*machine_module, std::cout);
}
#else
if (opts.emit_ir || opts.emit_asm) {

@ -2,12 +2,24 @@
#include <ostream>
#include <stdexcept>
#include <set>
#include "utils/Log.h"
//#define DEBUG_Asm
#ifdef DEBUG_Asm
#include <iostream>
#define DEBUG_MSG(msg) std::cerr << "[Asm Debug] " << msg << std::endl
#else
#define DEBUG_MSG(msg)
#endif
namespace mir {
namespace {
static void PrintLoadImm64(std::ostream& os, PhysReg reg, uint64_t imm);
const FrameSlot& GetFrameSlot(const MachineFunction& function,
const Operand& operand) {
if (operand.GetKind() != Operand::Kind::FrameIndex) {
@ -16,63 +28,458 @@ const FrameSlot& GetFrameSlot(const MachineFunction& function,
return function.GetFrameSlot(operand.GetFrameIndex());
}
void PrintStackAccess(std::ostream& os, const char* mnemonic, PhysReg reg,
int offset) {
os << " " << mnemonic << " " << PhysRegName(reg) << ", [x29, #" << offset
<< "]\n";
void PrintStackAccess(std::ostream& os, const char* insn, PhysReg reg, int64_t offset) {
// offset 通常是负数,例如 -8, -24, -40 等
if (offset >= -256 && offset <= 255) {
os << " " << insn << " " << PhysRegName(reg) << ", [x29, #" << offset << "]\n";
return;
}
// 大偏移量:用 x16 计算 x29 + offset然后间接访问
os << " mov x16, x29\n";
int64_t abs_offset = (offset >= 0) ? offset : -offset;
if (abs_offset <= 4095) {
if (offset >= 0) {
os << " add x16, x16, #" << offset << "\n";
} else {
os << " sub x16, x16, #" << abs_offset << "\n";
}
} else {
// 分解大偏移量
PrintLoadImm64(os, PhysReg::X17, abs_offset);
if (offset >= 0) {
os << " add x16, x16, x17\n";
} else {
os << " sub x16, x16, x17\n";
}
}
os << " " << insn << " " << PhysRegName(reg) << ", [x16]\n";
}
} // namespace
// 打印单个操作数
void PrintOperand(std::ostream& os, const Operand& op) {
switch (op.GetKind()) {
case Operand::Kind::Reg:
os << PhysRegName(op.GetReg());
break;
case Operand::Kind::Imm:
os << "#" << op.GetImm();
break;
case Operand::Kind::FrameIndex:
os << "[sp, #" << op.GetFrameIndex() << "]";
break;
case Operand::Kind::Cond:
os << CondCodeName(op.GetCondCode());
break;
case Operand::Kind::Label:
DEBUG_MSG("label is" << op.GetLabel());
os << op.GetLabel();
break;
}
}
void PrintAsm(const MachineFunction& function, std::ostream& os) {
os << ".text\n";
os << ".global " << function.GetName() << "\n";
os << ".type " << function.GetName() << ", %function\n";
os << function.GetName() << ":\n";
// 判断立即数是否可作为 AArch64 ADD/SUB 指令的 12 位立即数(可左移 0 或 12 位)
static bool IsLegalAddSubImm(int64_t imm) {
if (imm < 0) imm = -imm; // 取绝对值,因为移位规则对称
if (imm <= 4095) return true; // 0-4095 直接合法
if ((imm & 0xFFF) == 0 && imm <= 4095 * 4096) return true; // 4096 的倍数且 ≤ 16773120
return false;
}
// 在匿名命名空间添加辅助函数
static void PrintLoadImm64(std::ostream& os, PhysReg reg, uint64_t imm) {
// 输出 movz + movk 序列
uint16_t part0 = imm & 0xFFFF;
uint16_t part1 = (imm >> 16) & 0xFFFF;
uint16_t part2 = (imm >> 32) & 0xFFFF;
uint16_t part3 = (imm >> 48) & 0xFFFF;
os << " movz " << PhysRegName(reg) << ", #" << part0;
if (part1 != 0 || part2 != 0 || part3 != 0) {
os << ", lsl #0";
}
os << "\n";
if (part1 != 0) {
os << " movk " << PhysRegName(reg) << ", #" << part1 << ", lsl #16\n";
}
if (part2 != 0) {
os << " movk " << PhysRegName(reg) << ", #" << part2 << ", lsl #32\n";
}
if (part3 != 0) {
os << " movk " << PhysRegName(reg) << ", #" << part3 << ", lsl #48\n";
}
}
for (const auto& inst : function.GetEntry().GetInstructions()) {
const auto& ops = inst.GetOperands();
switch (inst.GetOpcode()) {
case Opcode::Prologue:
os << " stp x29, x30, [sp, #-16]!\n";
os << " mov x29, sp\n";
if (function.GetFrameSize() > 0) {
os << " sub sp, sp, #" << function.GetFrameSize() << "\n";
// 打印单条指令
void PrintInstruction(std::ostream& os, const MachineInstr& instr,
const MachineFunction& function) {
const auto& ops = instr.GetOperands();
switch (instr.GetOpcode()) {
case Opcode::Prologue:
os << " stp x29, x30, [sp, #-16]!\n";
os << " mov x29, sp\n";
if (function.GetFrameSize() > 0) {
int64_t size = function.GetFrameSize();
if (IsLegalAddSubImm(size)) {
os << " sub sp, sp, #" << size << "\n";
} else {
PrintLoadImm64(os, PhysReg::X16, size);
os << " sub sp, sp, x16\n";
}
break;
case Opcode::Epilogue:
if (function.GetFrameSize() > 0) {
os << " add sp, sp, #" << function.GetFrameSize() << "\n";
}
break;
case Opcode::Epilogue:
if (function.GetFrameSize() > 0) {
int64_t size = function.GetFrameSize();
if (IsLegalAddSubImm(size)) {
os << " add sp, sp, #" << size << "\n";
} else {
PrintLoadImm64(os, PhysReg::X16, size);
os << " add sp, sp, x16\n";
}
os << " ldp x29, x30, [sp], #16\n";
break;
case Opcode::MovImm:
os << " mov " << PhysRegName(ops.at(0).GetReg()) << ", #"
<< ops.at(1).GetImm() << "\n";
break;
case Opcode::LoadStack: {
const auto& slot = GetFrameSlot(function, ops.at(1));
PrintStackAccess(os, "ldur", ops.at(0).GetReg(), slot.offset);
break;
}
case Opcode::StoreStack: {
os << " ldp x29, x30, [sp], #16\n";
break;
case Opcode::MovImm:
os << " mov " << PhysRegName(ops.at(0).GetReg()) << ", #"
<< ops.at(1).GetImm() << "\n";
break;
case Opcode::MovReg:
os << " mov " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << "\n";
break;
case Opcode::StoreStack: {
// 检查第二个操作数的类型
if (ops.size() >= 2 && ops.at(1).GetKind() == Operand::Kind::FrameIndex) {
// 存储到栈槽
const auto& slot = GetFrameSlot(function, ops.at(1));
PrintStackAccess(os, "stur", ops.at(0).GetReg(), slot.offset);
break;
} else if (ops.size() >= 2 && ops.at(1).GetKind() == Operand::Kind::Reg) {
// 间接存储:存储到寄存器指向的地址
// STR W9, [X8]
os << " str " << PhysRegName(ops.at(0).GetReg()) << ", ["
<< PhysRegName(ops.at(1).GetReg()) << "]\n";
} else {
throw std::runtime_error("StoreStack: 无效的操作数类型");
}
break;
}
case Opcode::LoadStack: {
// 检查第二个操作数的类型
if (ops.size() >= 2 && ops.at(1).GetKind() == Operand::Kind::FrameIndex) {
// 从栈槽加载
const auto& slot = GetFrameSlot(function, ops.at(1));
PrintStackAccess(os, "ldur", ops.at(0).GetReg(), slot.offset);
} else if (ops.size() >= 2 && ops.at(1).GetKind() == Operand::Kind::Reg) {
// 间接加载:从寄存器指向的地址加载
// LDR W9, [X8]
os << " ldr " << PhysRegName(ops.at(0).GetReg()) << ", ["
<< PhysRegName(ops.at(1).GetReg()) << "]\n";
} else {
throw std::runtime_error("LoadStack: 无效的操作数类型");
}
break;
}
case Opcode::StoreStackPair:
// stp x29, x30, [sp, #-16]!
os << " stp " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", [sp";
if (ops.size() > 2 && ops.at(2).GetKind() == Operand::Kind::Imm) {
int offset = ops.at(2).GetImm();
os << ", #" << offset;
}
case Opcode::AddRR:
os << "]!\n"; // 注意添加 ! 表示 pre-index
break;
case Opcode::LoadStackPair:
// ldp x29, x30, [sp], #16
os << " ldp " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", [sp]";
if (ops.size() > 2 && ops.at(2).GetKind() == Operand::Kind::Imm) {
int offset = ops.at(2).GetImm();
os << ", #" << offset;
}
os << "\n";
break;
case Opcode::AddRR:
os << " add " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::AddRI:
os << " add " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", #"
<< ops.at(2).GetImm() << "\n";
break;
case Opcode::SubRR:
os << " sub " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::SubRI:
os << " sub " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", #"
<< ops.at(2).GetImm() << "\n";
break;
case Opcode::MulRR:
os << " mul " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::SDivRR:
os << " sdiv " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::UDivRR:
os << " udiv " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::FAddRR:
os << " fadd " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::FSubRR:
os << " fsub " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::FMulRR:
os << " fmul " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::FDivRR:
os << " fdiv " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::CmpRR:
os << " cmp " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << "\n";
break;
case Opcode::CmpRI:
os << " cmp " << PhysRegName(ops.at(0).GetReg()) << ", #"
<< ops.at(1).GetImm() << "\n";
break;
case Opcode::FCmpRR:
os << " fcmp " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << "\n";
break;
case Opcode::SIToFP:
os << " scvtf " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << "\n";
break;
case Opcode::FPToSI:
os << " fcvtzs " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << "\n";
break;
case Opcode::ZExt:
os << " and " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", #1\n";
break;
case Opcode::AndRR:
os << " and " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::OrRR:
os << " orr " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::EorRR:
os << " eor " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::LslRR:
os << " lsl " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::LsrRR:
os << " lsr " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::AsrRR:
os << " asr " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::B:
os << " b ";
PrintOperand(os, ops.at(0));
os << "\n";
break;
case Opcode::BCond:
os << " b.";
PrintOperand(os, ops.at(0));
os << " ";
PrintOperand(os, ops.at(1));
os << "\n";
break;
case Opcode::Call:
os << " bl ";
PrintOperand(os, ops.at(0));
os << "\n";
break;
case Opcode::Ret:
os << " ret\n";
break;
case Opcode::Nop:
os << " nop\n";
break;
case Opcode::Label:
os << ops.at(0).GetLabel() << ":\n";
break;
case Opcode::Movk:
os << " movk " << PhysRegName(ops.at(0).GetReg()) << ", #"
<< ops.at(1).GetImm() << ", lsl #" << ops.at(2).GetImm() << "\n";
break;
case Opcode::LoadStackAddr: {
const FrameSlot& slot = GetFrameSlot(function, ops.at(1));
int64_t offset = slot.offset; // 负值,如 -8
PhysReg dst = ops.at(0).GetReg();
auto tryEmitSimple = [&]() -> bool {
if (offset >= 0 && offset <= 4095) {
os << " add " << PhysRegName(dst) << ", x29, #" << offset << "\n";
return true;
} else if (offset < 0 && offset >= -4095) {
os << " sub " << PhysRegName(dst) << ", x29, #" << (-offset) << "\n";
return true;
}
return false;
};
if (tryEmitSimple()) break;
// 复杂偏移
uint64_t absOffset = (offset >= 0) ? offset : -offset;
PrintLoadImm64(os, PhysReg::X16, absOffset);
if (offset >= 0) {
os << " add " << PhysRegName(dst) << ", x29, x16\n";
} else {
os << " sub " << PhysRegName(dst) << ", x29, x16\n";
}
break;
}
case Opcode::Adrp: {
// adrp Xd, label
os << " adrp " << PhysRegName(ops.at(0).GetReg()) << ", "
<< ops.at(1).GetLabel() << "\n";
break;
}
case Opcode::AddLabel: {
// add Xd, Xn, :lo12:label
os << " add " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
<< PhysRegName(ops.at(1).GetReg()) << ", :lo12:"
<< ops.at(2).GetLabel() << "\n";
break;
case Opcode::Ret:
os << " ret\n";
}
case Opcode::Sxtw:
os << " sxtw " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << "\n";
break;
default:
os << " // unknown instruction\n";
break;
}
}
// 打印单个函数(单函数版本)
void PrintAsm(const MachineFunction& function, std::ostream& os) {
// 输出函数标签
os << ".text\n";
os << ".global " << function.GetName() << "\n";
os << ".type " << function.GetName() << ", %function\n";
os << function.GetName() << ":\n";
// 计算栈帧大小
int frameSize = function.GetFrameSize();
// 输出每个基本块
const auto& blocks = function.GetBasicBlocks();
bool firstBlock = true;
for (const auto& bb : blocks) {
DEBUG_MSG("block");
// 输出基本块标签(非第一个基本块)
if (!firstBlock) {
os << bb->GetName() << ":\n";
}
firstBlock = false;
// 输出基本块中的指令
for (const auto& inst : bb->GetInstructions()) {
DEBUG_MSG("inst");
PrintInstruction(os, inst, function);
}
}
os << ".size " << function.GetName() << ", .-" << function.GetName() << "\n";
}
} // namespace
// 打印模块(模块版本)
void PrintAsm(const MachineModule& module, std::ostream& os) {
// 输出文件头
os << ".arch armv8-a\n";
// 输出数据段:全局变量
const auto& globals = module.GetGlobals();
if (!globals.empty()) {
os << "\n.data\n";
for (const auto& g : globals) {
os << ".global " << g.name << "\n";
os << ".type " << g.name << ", %object\n";
os << ".align " << g.alignment << "\n";
os << g.name << ":\n";
if (g.is_zero_init) {
os << " .zero " << g.size << "\n";
} else if (g.has_init_data) {
if (g.size == 4) {
os << " .word " << static_cast<uint32_t>(g.init_data) << "\n";
} else if (g.size == 8) {
os << " .quad " << g.init_data << "\n";
} else {
// 暂不支持的标量大小,回退为零初始化
os << " .zero " << g.size << " // unhandled init size\n";
}
} else {
// 有初始值但无法提取(例如数组、结构体)
os << " .zero " << g.size << " // unhandled initializer\n";
}
os << ".size " << g.name << ", " << g.size << "\n\n";
}
}
os << ".size " << function.GetName() << ", .-" << function.GetName()
<< "\n";
static const std::set<std::string> externalFuncs = {
"getint", "getch", "getarray", "putint", "putch", "putarray", "puts",
"_sysy_starttime", "_sysy_stoptime", "starttime", "stoptime",
"getfloat", "putfloat", "getfarray", "putfarray", "memset",
"sysy_alloc_i32", "sysy_alloc_f32", "sysy_free_i32", "sysy_free_f32",
"sysy_zero_i32", "sysy_zero_f32"
};
DEBUG_MSG("module");
// 遍历所有函数,输出汇编
for (const auto& func : module.GetFunctions()) {
if (externalFuncs.count(func->GetName())) {
continue; // 跳过库函数桩
}
DEBUG_MSG("func");
PrintAsm(*func, os);
os << "\n";
}
}
} // namespace mir
} // namespace mir

@ -5,6 +5,15 @@
#include "utils/Log.h"
//#define DEBUG_Frame
#ifdef DEBUG_Frame
#include <iostream>
#define DEBUG_MSG(msg) std::cerr << "[Frame Debug] " << msg << std::endl
#else
#define DEBUG_MSG(msg)
#endif
namespace mir {
namespace {
@ -15,31 +24,49 @@ int AlignTo(int value, int align) {
} // namespace
void RunFrameLowering(MachineFunction& function) {
DEBUG_MSG("function RunFrameLowering");
int cursor = 0;
for (const auto& slot : function.GetFrameSlots()) {
cursor += slot.size;
if (-cursor < -256) {
throw std::runtime_error(FormatError("mir", "暂不支持过大的栈帧"));
}
}
cursor = 0;
for (const auto& slot : function.GetFrameSlots()) {
cursor += slot.size;
function.GetFrameSlot(slot.index).offset = -cursor;
}
function.SetFrameSize(AlignTo(cursor, 16));
auto& insts = function.GetEntry().GetInstructions();
std::vector<MachineInstr> lowered;
lowered.emplace_back(Opcode::Prologue);
for (const auto& inst : insts) {
if (inst.GetOpcode() == Opcode::Ret) {
lowered.emplace_back(Opcode::Epilogue);
// 基本块
const auto& blocks = function.GetBasicBlocks();
bool firstBlock = true;
for (const auto& bb : blocks) {
DEBUG_MSG("block");
auto& insts = bb->GetInstructions();
std::vector<MachineInstr> lowered;
// 输出基本块标签(非第一个基本块)
if (firstBlock) {
DEBUG_MSG("empalace Prologue");
lowered.emplace_back(Opcode::Prologue);
}
firstBlock = false;
// 输出基本块中的指令
for (const auto& inst : insts) {
DEBUG_MSG("inst");
if (inst.GetOpcode() == Opcode::Ret) {
DEBUG_MSG("empalace Epilogue");
lowered.emplace_back(Opcode::Epilogue);
}
lowered.push_back(inst);
}
lowered.push_back(inst);
insts = std::move(lowered);
}
}
// 模块版本的栈帧布局
void RunFrameLowering(MachineModule& module) {
// 对模块中的每个函数执行栈帧布局
DEBUG_MSG("module RunFrameLowering");
for (auto& func : module.GetFunctions()) {
RunFrameLowering(*func);
}
insts = std::move(lowered);
}
} // namespace mir
} // namespace mir

File diff suppressed because it is too large Load Diff

@ -9,7 +9,8 @@ MachineBasicBlock::MachineBasicBlock(std::string name)
MachineInstr& MachineBasicBlock::Append(Opcode opcode,
std::initializer_list<Operand> operands) {
instructions_.emplace_back(opcode, std::vector<Operand>(operands));
//instructions_.emplace_back(opcode, std::vector<Operand>(operands));
instructions_.emplace_back(opcode, std::move(operands));
return instructions_.back();
}

@ -4,17 +4,25 @@
namespace mir {
Operand::Operand(Kind kind, PhysReg reg, int imm)
: kind_(kind), reg_(reg), imm_(imm) {}
Operand::Operand(Kind kind, PhysReg reg, int imm, CondCode cc, const std::string& label)
: kind_(kind), reg_(reg), imm_(imm), cc_(cc), label_(label) {}
Operand Operand::Reg(PhysReg reg) { return Operand(Kind::Reg, reg, 0); }
Operand Operand::Reg(PhysReg reg) { return Operand(Kind::Reg, reg, 0, CondCode::EQ, ""); }
Operand Operand::Imm(int value) {
return Operand(Kind::Imm, PhysReg::W0, value);
return Operand(Kind::Imm, PhysReg::W0, value, CondCode::EQ, "");
}
Operand Operand::FrameIndex(int index) {
return Operand(Kind::FrameIndex, PhysReg::W0, index);
return Operand(Kind::FrameIndex, PhysReg::W0, index, CondCode::EQ, "");
}
Operand Operand::Cond(CondCode cc) {
return Operand(Kind::Cond, PhysReg::W0, 0, cc, "");
}
Operand Operand::Label(const std::string& label) {
return Operand(Kind::Label, PhysReg::W0, 0, CondCode::EQ, label);
}
MachineInstr::MachineInstr(Opcode opcode, std::vector<Operand> operands)

@ -12,8 +12,8 @@ bool IsAllowedReg(PhysReg reg) {
case PhysReg::W0:
case PhysReg::W8:
case PhysReg::W9:
case PhysReg::X29:
case PhysReg::X30:
case PhysReg::X29: //FP = X29 帧指针
case PhysReg::X30: //LR = X30 链接寄存器
case PhysReg::SP:
return true;
}
@ -22,15 +22,61 @@ bool IsAllowedReg(PhysReg reg) {
} // namespace
//void RunRegAlloc(MachineFunction& function) {
// for (const auto& inst : function.GetEntry().GetInstructions()) {
// for (const auto& operand : inst.GetOperands()) {
// if (operand.GetKind() == Operand::Kind::Reg &&
// !IsAllowedReg(operand.GetReg())) {
// throw std::runtime_error(FormatError("mir", "寄存器分配失败"));
// }
// }
// }
//}
// 单函数版本的寄存器分配(原有逻辑)
void RunRegAlloc(MachineFunction& function) {
for (const auto& inst : function.GetEntry().GetInstructions()) {
for (const auto& operand : inst.GetOperands()) {
if (operand.GetKind() == Operand::Kind::Reg &&
!IsAllowedReg(operand.GetReg())) {
throw std::runtime_error(FormatError("mir", "寄存器分配失败"));
// 当前仅执行最小一致性检查,不实现真实寄存器分配
// Lab3 阶段保持栈槽模型,不需要真实寄存器分配
// 检查每个基本块中的指令
for (auto& bb : function.GetBasicBlocks()) {
for (auto& instr : bb->GetInstructions()) {
// 检查指令的操作数是否有效
for (const auto& operand : instr.GetOperands()) {
switch (operand.GetKind()) {
case Operand::Kind::Reg:
// 寄存器操作数:检查是否在允许的范围内
// 当前使用固定寄存器 w0, w8, w9, s0, s1 等
break;
case Operand::Kind::FrameIndex:
// 栈槽索引:检查是否有效
if (operand.GetFrameIndex() < 0 ||
operand.GetFrameIndex() >= static_cast<int>(function.GetFrameSlots().size())) {
throw std::runtime_error(
FormatError("regalloc", "无效的栈槽索引: " +
std::to_string(operand.GetFrameIndex())));
}
break;
case Operand::Kind::Imm:
case Operand::Kind::Cond:
case Operand::Kind::Label:
// 立即数、条件码、标签不需要检查
break;
}
}
}
}
// 注意Lab3 阶段不实现真实寄存器分配
// 所有值仍然使用栈槽模型,寄存器仅作为临时计算使用
}
// 模块版本的寄存器分配
void RunRegAlloc(MachineModule& module) {
// 对模块中的每个函数执行寄存器分配
for (auto& func : module.GetFunctions()) {
RunRegAlloc(*func);
}
}
} // namespace mir

@ -8,20 +8,111 @@ namespace mir {
const char* PhysRegName(PhysReg reg) {
switch (reg) {
case PhysReg::W0:
return "w0";
case PhysReg::W8:
return "w8";
case PhysReg::W9:
return "w9";
case PhysReg::X29:
return "x29";
case PhysReg::X30:
return "x30";
case PhysReg::SP:
return "sp";
// 32位寄存器
case PhysReg::W0: return "w0";
case PhysReg::W1: return "w1";
case PhysReg::W2: return "w2";
case PhysReg::W3: return "w3";
case PhysReg::W4: return "w4";
case PhysReg::W5: return "w5";
case PhysReg::W6: return "w6";
case PhysReg::W7: return "w7";
case PhysReg::W8: return "w8";
case PhysReg::W9: return "w9";
case PhysReg::W10: return "w10";
case PhysReg::W11: return "w11";
case PhysReg::W12: return "w12";
case PhysReg::W13: return "w13";
case PhysReg::W14: return "w14";
case PhysReg::W15: return "w15";
case PhysReg::W16: return "w16"; // 添加
case PhysReg::W17: return "w17"; // 添加
case PhysReg::W18: return "w18"; // 添加
case PhysReg::W19: return "w19"; // 添加
case PhysReg::W20: return "w20"; // 添加
case PhysReg::W21: return "w21"; // 添加
case PhysReg::W22: return "w22"; // 添加
case PhysReg::W23: return "w23"; // 添加
case PhysReg::W24: return "w24"; // 添加
case PhysReg::W25: return "w25"; // 添加
case PhysReg::W26: return "w26"; // 添加
case PhysReg::W27: return "w27"; // 添加
case PhysReg::W28: return "w28"; // 添加
case PhysReg::W29: return "w29";
case PhysReg::W30: return "w30";
// 64位寄存器
case PhysReg::X0: return "x0";
case PhysReg::X1: return "x1";
case PhysReg::X2: return "x2";
case PhysReg::X3: return "x3";
case PhysReg::X4: return "x4";
case PhysReg::X5: return "x5";
case PhysReg::X6: return "x6";
case PhysReg::X7: return "x7";
case PhysReg::X8: return "x8";
case PhysReg::X9: return "x9";
case PhysReg::X10: return "x10"; // 添加
case PhysReg::X11: return "x11"; // 添加
case PhysReg::X12: return "x12"; // 添加
case PhysReg::X13: return "x13"; // 添加
case PhysReg::X14: return "x14"; // 添加
case PhysReg::X15: return "x15"; // 添加
case PhysReg::X16: return "x16"; // 添加
case PhysReg::X17: return "x17"; // 添加
case PhysReg::X18: return "x18"; // 添加
case PhysReg::X19: return "x19"; // 添加
case PhysReg::X20: return "x20"; // 添加
case PhysReg::X21: return "x21"; // 添加
case PhysReg::X22: return "x22"; // 添加
case PhysReg::X23: return "x23"; // 添加
case PhysReg::X24: return "x24"; // 添加
case PhysReg::X25: return "x25"; // 添加
case PhysReg::X26: return "x26"; // 添加
case PhysReg::X27: return "x27"; // 添加
case PhysReg::X28: return "x28"; // 添加
case PhysReg::X29: return "x29";
case PhysReg::X30: return "x30";
// 浮点寄存器
case PhysReg::S0: return "s0";
case PhysReg::S1: return "s1";
case PhysReg::S2: return "s2";
case PhysReg::S3: return "s3";
case PhysReg::S4: return "s4";
case PhysReg::S5: return "s5";
case PhysReg::S6: return "s6";
case PhysReg::S7: return "s7";
// 特殊寄存器
case PhysReg::SP: return "sp";
case PhysReg::ZR: return "xzr";
default: return "unknown";
}
throw std::runtime_error(FormatError("mir", "未知物理寄存器"));
}
const char* CondCodeName(CondCode cc) {
switch (cc) {
case CondCode::EQ: return "eq";
case CondCode::NE: return "ne";
case CondCode::CS: return "cs";
case CondCode::CC: return "cc";
case CondCode::MI: return "mi";
case CondCode::PL: return "pl";
case CondCode::VS: return "vs";
case CondCode::VC: return "vc";
case CondCode::HI: return "hi";
case CondCode::LS: return "ls";
case CondCode::GE: return "ge";
case CondCode::LT: return "lt";
case CondCode::GT: return "gt";
case CondCode::LE: return "le";
case CondCode::AL: return "al";
default: return "unknown";
}
throw std::runtime_error(FormatError("mir", "未知条件码"));
}
} // namespace mir

File diff suppressed because it is too large Load Diff

@ -1,17 +1,789 @@
// 维护局部变量声明的注册与查找。
#include "sem/SymbolTable.h"
#include <antlr4-runtime.h> // 用于访问父节点
#include <cctype>
#include <stdexcept>
#include <string>
#include <cmath>
#include <functional>
//#define DEBUG_SYMBOL_TABLE
#ifdef DEBUG_SYMBOL_TABLE
#include <iostream>
#define DEBUG_MSG(msg) std::cerr << "[SymbolTable Debug] " << msg << std::endl
#else
#define DEBUG_MSG(msg)
#endif
// ---------- 构造函数 ----------
SymbolTable::SymbolTable() {
scopes_.emplace_back(); // 初始化全局作用域
active_scope_stack_.push_back(0);
registerBuiltinFunctions(); // 注册内置库函数
}
// ---------- 作用域管理 ----------
void SymbolTable::enterScope() {
scopes_.emplace_back();
active_scope_stack_.push_back(scopes_.size() - 1);
}
void SymbolTable::exitScope() {
if (active_scope_stack_.size() > 1) {
active_scope_stack_.pop_back();
}
// 不能退出全局作用域
}
// ---------- 符号添加与查找 ----------
bool SymbolTable::addSymbol(const Symbol& sym) {
auto& current_scope = scopes_[active_scope_stack_.back()];
if (current_scope.find(sym.name) != current_scope.end()) {
return false; // 重复定义
}
Symbol stored_sym = sym;
stored_sym.scope_level = currentScopeLevel();
current_scope[sym.name] = stored_sym;
// 立即验证存储的符号
const auto& stored = current_scope[sym.name];
DEBUG_MSG("SymbolTable::addSymbol: stored " << sym.name
<< " with kind=" << (int)stored.kind
<< ", const_def_ctx=" << stored.const_def_ctx);
return true;
}
Symbol* SymbolTable::lookup(const std::string& name) {
return const_cast<Symbol*>(static_cast<const SymbolTable*>(this)->lookup(name));
}
Symbol* SymbolTable::lookupCurrent(const std::string& name) {
return const_cast<Symbol*>(static_cast<const SymbolTable*>(this)->lookupCurrent(name));
}
const Symbol* SymbolTable::lookup(const std::string& name) const {
for (auto it = active_scope_stack_.rbegin(); it != active_scope_stack_.rend(); ++it) {
const auto& scope = scopes_[*it];
auto found = scope.find(name);
if (found != scope.end()) {
DEBUG_MSG("SymbolTable::lookup: found " << name
<< " in active scope index " << *it
<< ", kind=" << (int)found->second.kind
<< ", const_def_ctx=" << found->second.const_def_ctx);
return &found->second;
}
}
return nullptr;
}
const Symbol* SymbolTable::lookupCurrent(const std::string& name) const {
const auto& current_scope = scopes_[active_scope_stack_.back()];
auto it = current_scope.find(name);
if (it != current_scope.end()) {
return &it->second;
}
return nullptr;
}
const Symbol* SymbolTable::lookupAll(const std::string& name) const {
for (auto it = scopes_.rbegin(); it != scopes_.rend(); ++it) {
auto found = it->find(name);
if (found != it->end()) {
return &found->second;
}
}
return nullptr;
}
void SymbolTable::Add(const std::string& name,
SysYParser::VarDefContext* decl) {
table_[name] = decl;
const Symbol* SymbolTable::lookupByVarDef(const SysYParser::VarDefContext* decl) const {
if (!decl) return nullptr;
for (auto it = scopes_.rbegin(); it != scopes_.rend(); ++it) {
for (const auto& [name, sym] : *it) {
if (sym.var_def_ctx == decl) {
return &sym;
}
}
}
return nullptr;
}
const Symbol* SymbolTable::lookupByConstDef(const SysYParser::ConstDefContext* decl) const {
if (!decl) return nullptr;
for (auto it = scopes_.rbegin(); it != scopes_.rend(); ++it) {
for (const auto& [name, sym] : *it) {
if (sym.const_def_ctx == decl) {
return &sym;
}
}
}
return nullptr;
}
// ---------- 兼容原接口 ----------
void SymbolTable::Add(const std::string& name, SysYParser::VarDefContext* decl) {
Symbol sym;
sym.name = name;
sym.kind = SymbolKind::Variable;
sym.type = getTypeFromVarDef(decl);
sym.var_def_ctx = decl;
sym.scope_level = currentScopeLevel();
addSymbol(sym);
}
bool SymbolTable::Contains(const std::string& name) const {
return table_.find(name) != table_.end();
for (auto it = active_scope_stack_.rbegin(); it != active_scope_stack_.rend(); ++it) {
const auto& scope = scopes_[*it];
if (scope.find(name) != scope.end()) {
return true;
}
}
return false;
}
SysYParser::VarDefContext* SymbolTable::Lookup(const std::string& name) const {
auto it = table_.find(name);
return it == table_.end() ? nullptr : it->second;
for (auto it = active_scope_stack_.rbegin(); it != active_scope_stack_.rend(); ++it) {
const auto& scope = scopes_[*it];
auto found = scope.find(name);
if (found != scope.end()) {
// 只返回变量定义的上下文(函数等其他符号返回 nullptr
if (found->second.kind == SymbolKind::Variable) {
return found->second.var_def_ctx;
}
return nullptr;
}
}
return nullptr;
}
// ---------- 辅助函数:从 VarDefContext 获取外层 VarDeclContext ----------
static SysYParser::VarDeclContext* getOuterVarDecl(SysYParser::VarDefContext* varDef) {
auto parent = varDef->parent;
while (parent) {
if (auto varDecl = dynamic_cast<SysYParser::VarDeclContext*>(parent)) {
return varDecl;
}
parent = parent->parent;
}
return nullptr;
}
// ---------- 辅助函数:从 VarDefContext 获取外层 ConstDeclContext常量定义----------
static SysYParser::ConstDeclContext* getOuterConstDecl(SysYParser::VarDefContext* varDef) {
auto parent = varDef->parent;
while (parent) {
if (auto constDecl = dynamic_cast<SysYParser::ConstDeclContext*>(parent)) {
return constDecl;
}
parent = parent->parent;
}
return nullptr;
}
// 从 VarDefContext 构造类型
// 原静态函数改为成员函数,并调用成员 EvaluateConstExp
std::shared_ptr<ir::Type> SymbolTable::getTypeFromVarDef(SysYParser::VarDefContext* ctx) const {
// 获取基本类型(同原代码,但通过外层 Decl 确定)
std::shared_ptr<ir::Type> base_type = nullptr;
auto varDecl = getOuterVarDecl(ctx);
if (varDecl) {
auto bType = varDecl->bType();
if (bType->Int()) base_type = ir::Type::GetInt32Type();
else if (bType->Float()) base_type = ir::Type::GetFloatType();
} else {
auto constDecl = getOuterConstDecl(ctx);
if (constDecl) {
auto bType = constDecl->bType();
if (bType->Int()) base_type = ir::Type::GetInt32Type();
else if (bType->Float()) base_type = ir::Type::GetFloatType();
}
}
if (!base_type) base_type = ir::Type::GetInt32Type();
// 解析维度
std::vector<int> dims;
for (auto* dimExp : ctx->constExp()) {
int dim = EvaluateConstExp(dimExp); // 调用成员函数
if (dim <= 0) {
throw std::runtime_error("数组维度必须为正整数");
}
dims.push_back(dim);
}
if (!dims.empty()) {
return ir::Type::GetArrayType(base_type, dims);
}
return base_type;
}
// 从 FuncDefContext 构造函数类型
std::shared_ptr<ir::Type> SymbolTable::getTypeFromFuncDef(SysYParser::FuncDefContext* ctx) {
// 1. 返回类型
std::shared_ptr<ir::Type> ret_type;
auto funcType = ctx->funcType();
if (funcType->Void()) {
ret_type = ir::Type::GetVoidType();
} else if (funcType->Int()) {
ret_type = ir::Type::GetInt32Type();
} else if (funcType->Float()) {
ret_type = ir::Type::GetFloatType();
} else {
ret_type = ir::Type::GetInt32Type(); // fallback
}
// 2. 参数类型
std::vector<std::shared_ptr<ir::Type>> param_types;
auto fParams = ctx->funcFParams();
if (fParams) {
for (auto param : fParams->funcFParam()) {
std::shared_ptr<ir::Type> param_type;
auto bType = param->bType();
if (bType->Int()) {
param_type = ir::Type::GetInt32Type();
} else if (bType->Float()) {
param_type = ir::Type::GetFloatType();
} else {
param_type = ir::Type::GetInt32Type();
}
// 处理数组参数:如果存在 [ ] 或 [ exp ],退化为指针
if (param->L_BRACK().size() > 0) {
if (param_type->IsInt32()) {
param_type = ir::Type::GetPtrInt32Type();
} else if (param_type->IsFloat()) {
param_type = ir::Type::GetPtrFloatType();
}
}
param_types.push_back(param_type);
}
}
return ir::Type::GetFunctionType(ret_type, param_types);
}
// ----- 注册内置库函数-----
void SymbolTable::registerBuiltinFunctions() {
// 确保当前处于全局作用域scopes_ 只有一层)
// 1. getint: int getint()
Symbol getint;
getint.name = "getint";
getint.kind = SymbolKind::Function;
getint.type = ir::Type::GetFunctionType(ir::Type::GetInt32Type(), {}); // 无参数
getint.param_types = {};
getint.scope_level = 0;
getint.is_builtin = true;
addSymbol(getint);
// 2. getfloat: float getfloat()
Symbol getfloat;
getfloat.name = "getfloat";
getfloat.kind = SymbolKind::Function;
getfloat.type = ir::Type::GetFunctionType(ir::Type::GetFloatType(), {});
getfloat.param_types = {};
getfloat.scope_level = 0;
getfloat.is_builtin = true;
addSymbol(getfloat);
// 3. getch: int getch()
Symbol getch;
getch.name = "getch";
getch.kind = SymbolKind::Function;
getch.type = ir::Type::GetFunctionType(ir::Type::GetInt32Type(), {});
getch.param_types = {};
getch.scope_level = 0;
getch.is_builtin = true;
addSymbol(getch);
// 4. putint: void putint(int)
std::vector<std::shared_ptr<ir::Type>> putint_params = { ir::Type::GetInt32Type() };
Symbol putint;
putint.name = "putint";
putint.kind = SymbolKind::Function;
putint.type = ir::Type::GetFunctionType(ir::Type::GetVoidType(), putint_params);
putint.param_types = putint_params;
putint.scope_level = 0;
putint.is_builtin = true;
addSymbol(putint);
// 5. putfloat: void putfloat(float)
std::vector<std::shared_ptr<ir::Type>> putfloat_params = { ir::Type::GetFloatType() };
Symbol putfloat;
putfloat.name = "putfloat";
putfloat.kind = SymbolKind::Function;
putfloat.type = ir::Type::GetFunctionType(ir::Type::GetVoidType(), putfloat_params);
putfloat.param_types = putfloat_params;
putfloat.scope_level = 0;
putfloat.is_builtin = true;
addSymbol(putfloat);
// 6. putch: void putch(int)
std::vector<std::shared_ptr<ir::Type>> putch_params = { ir::Type::GetInt32Type() };
Symbol putch;
putch.name = "putch";
putch.kind = SymbolKind::Function;
putch.type = ir::Type::GetFunctionType(ir::Type::GetVoidType(), putch_params);
putch.param_types = putch_params;
putch.scope_level = 0;
putch.is_builtin = true;
addSymbol(putch);
// 7. getarray: int getarray(int a[])
// 参数类型: int a[] 退化为 int* 即 PtrInt32
std::vector<std::shared_ptr<ir::Type>> getarray_params = { ir::Type::GetPtrInt32Type() };
Symbol getarray;
getarray.name = "getarray";
getarray.kind = SymbolKind::Function;
getarray.type = ir::Type::GetFunctionType(ir::Type::GetInt32Type(), getarray_params);
getarray.param_types = getarray_params;
getarray.scope_level = 0;
getarray.is_builtin = true;
addSymbol(getarray);
// 8. putarray: void putarray(int n, int a[])
// 参数: int n, int a[] -> 实际类型: int, int*
std::vector<std::shared_ptr<ir::Type>> putarray_params = { ir::Type::GetInt32Type(), ir::Type::GetPtrInt32Type() };
Symbol putarray;
putarray.name = "putarray";
putarray.kind = SymbolKind::Function;
putarray.type = ir::Type::GetFunctionType(ir::Type::GetVoidType(), putarray_params);
putarray.param_types = putarray_params;
putarray.scope_level = 0;
putarray.is_builtin = true;
addSymbol(putarray);
// starttime: void starttime()
Symbol starttime;
starttime.name = "starttime";
starttime.kind = SymbolKind::Function;
starttime.type = ir::Type::GetFunctionType(ir::Type::GetVoidType(), {}); // 无参数,返回 void
starttime.param_types = {};
starttime.scope_level = 0;
starttime.is_builtin = true;
addSymbol(starttime);
// stoptime: void stoptime()
Symbol stoptime;
stoptime.name = "stoptime";
stoptime.kind = SymbolKind::Function;
stoptime.type = ir::Type::GetFunctionType(ir::Type::GetVoidType(), {}); // 无参数,返回 void
stoptime.param_types = {};
stoptime.scope_level = 0;
stoptime.is_builtin = true;
addSymbol(stoptime);
// getfarray: int getfarray(float arr[])
std::vector<std::shared_ptr<ir::Type>> getfarray_params = { ir::Type::GetPtrFloatType() };
Symbol getfarray;
getfarray.name = "getfarray";
getfarray.kind = SymbolKind::Function;
getfarray.type = ir::Type::GetFunctionType(ir::Type::GetInt32Type(), getfarray_params);
getfarray.param_types = getfarray_params;
getfarray.scope_level = 0;
getfarray.is_builtin = true;
addSymbol(getfarray);
// putfarray: void putfarray(int len, float arr[])
std::vector<std::shared_ptr<ir::Type>> putfarray_params = {
ir::Type::GetInt32Type(),
ir::Type::GetPtrFloatType()
};
Symbol putfarray;
putfarray.name = "putfarray";
putfarray.kind = SymbolKind::Function;
putfarray.type = ir::Type::GetFunctionType(ir::Type::GetVoidType(), putfarray_params);
putfarray.param_types = putfarray_params;
putfarray.scope_level = 0;
putfarray.is_builtin = true;
addSymbol(putfarray);
}
// ==================== 常量表达式求值实现 ====================
static long long ParseIntegerLiteral(const std::string& text) {
// 处理前缀0x/0X 十六进制0 八进制,否则十进制
if (text.size() > 2 && (text[0] == '0' && (text[1] == 'x' || text[1] == 'X'))) {
return std::stoll(text.substr(2), nullptr, 16);
} else if (text.size() > 1 && text[0] == '0') {
return std::stoll(text, nullptr, 8);
} else {
return std::stoll(text, nullptr, 10);
}
}
static float ParseFloatLiteral(const std::string& text) {
return std::stof(text);
}
SymbolTable::ConstValue SymbolTable::EvaluatePrimaryExp(SysYParser::PrimaryExpContext* ctx) const {
if (!ctx) throw std::runtime_error("常量表达式求值:无效 PrimaryExp");
if (ctx->lVal()) {
auto lval = ctx->lVal();
if (!lval->Ident()) throw std::runtime_error("常量表达式求值:无效左值");
std::string name = lval->Ident()->getText();
const Symbol* sym = lookup(name);
if (!sym) throw std::runtime_error("常量表达式求值:未定义的标识符 " + name);
if (sym->kind != SymbolKind::Constant)
throw std::runtime_error("常量表达式求值:标识符 " + name + " 不是常量");
ConstValue val;
if (sym->is_int_const) {
val.kind = ConstValue::INT;
val.int_val = sym->const_value.i32;
} else {
val.kind = ConstValue::FLOAT;
val.float_val = sym->const_value.f32;
}
return val;
}
else if (ctx->HEX_FLOAT() || ctx->DEC_FLOAT()) {
std::string text;
if (ctx->HEX_FLOAT()) text = ctx->HEX_FLOAT()->getText();
else text = ctx->DEC_FLOAT()->getText();
ConstValue val;
val.kind = ConstValue::FLOAT;
val.float_val = ParseFloatLiteral(text);
return val;
}
else if (ctx->HEX_INT() || ctx->OCTAL_INT() || ctx->DECIMAL_INT() || ctx->ZERO()) {
std::string text;
if (ctx->HEX_INT()) text = ctx->HEX_INT()->getText();
else if (ctx->OCTAL_INT()) text = ctx->OCTAL_INT()->getText();
else if (ctx->DECIMAL_INT()) text = ctx->DECIMAL_INT()->getText();
else text = ctx->ZERO()->getText();
ConstValue val;
val.kind = ConstValue::INT;
val.int_val = static_cast<int>(ParseIntegerLiteral(text));
return val;
}
else if (ctx->exp()) {
return EvaluateAddExp(ctx->exp()->addExp());
}
else {
throw std::runtime_error("常量表达式求值:不支持的 PrimaryExp 类型");
}
}
SymbolTable::ConstValue SymbolTable::EvaluateUnaryExp(SysYParser::UnaryExpContext* ctx) const {
if (!ctx) throw std::runtime_error("常量表达式求值:无效 UnaryExp");
if (ctx->primaryExp()) {
return EvaluatePrimaryExp(ctx->primaryExp());
}
else if (ctx->unaryOp()) {
ConstValue operand = EvaluateUnaryExp(ctx->unaryExp());
std::string op = ctx->unaryOp()->getText();
if (op == "+") {
return operand;
}
else if (op == "-") {
if (operand.kind == ConstValue::INT) {
operand.int_val = -operand.int_val;
} else {
operand.float_val = -operand.float_val;
}
return operand;
}
else if (op == "!") {
if (operand.kind != ConstValue::INT) {
throw std::runtime_error("常量表达式求值:逻辑非操作数必须是整数");
}
ConstValue res;
res.kind = ConstValue::INT;
res.int_val = (operand.int_val == 0) ? 1 : 0;
return res;
}
else {
throw std::runtime_error("常量表达式求值:未知一元运算符 " + op);
}
}
else {
// 函数调用在常量表达式中不允许
throw std::runtime_error("常量表达式求值:不允许函数调用");
}
}
SymbolTable::ConstValue SymbolTable::EvaluateMulExp(SysYParser::MulExpContext* ctx) const {
if (!ctx) throw std::runtime_error("常量表达式求值:无效 MulExp");
if (ctx->mulExp()) {
ConstValue left = EvaluateMulExp(ctx->mulExp());
ConstValue right = EvaluateUnaryExp(ctx->unaryExp());
std::string op;
if (ctx->MulOp()) op = "*";
else if (ctx->DivOp()) op = "/";
else if (ctx->QuoOp()) op = "%";
else throw std::runtime_error("常量表达式求值:未知乘法运算符");
bool is_float = (left.kind == ConstValue::FLOAT || right.kind == ConstValue::FLOAT);
if (is_float) {
float l = (left.kind == ConstValue::INT) ? static_cast<float>(left.int_val) : left.float_val;
float r = (right.kind == ConstValue::INT) ? static_cast<float>(right.int_val) : right.float_val;
ConstValue res;
res.kind = ConstValue::FLOAT;
if (op == "*") res.float_val = l * r;
else if (op == "/") res.float_val = l / r;
else if (op == "%") throw std::runtime_error("常量表达式求值:浮点数不支持取模运算");
return res;
} else {
int l = left.int_val;
int r = right.int_val;
ConstValue res;
res.kind = ConstValue::INT;
if (op == "*") res.int_val = l * r;
else if (op == "/") {
if (r == 0) throw std::runtime_error("常量表达式求值:除零错误");
res.int_val = l / r;
}
else if (op == "%") {
if (r == 0) throw std::runtime_error("常量表达式求值:模零错误");
res.int_val = l % r;
}
return res;
}
}
else {
return EvaluateUnaryExp(ctx->unaryExp());
}
}
SymbolTable::ConstValue SymbolTable::EvaluateAddExp(SysYParser::AddExpContext* ctx) const {
if (!ctx) throw std::runtime_error("常量表达式求值:无效 AddExp");
if (ctx->addExp()) {
ConstValue left = EvaluateAddExp(ctx->addExp());
ConstValue right = EvaluateMulExp(ctx->mulExp());
std::string op;
if (ctx->AddOp()) op = "+";
else if (ctx->SubOp()) op = "-";
else throw std::runtime_error("常量表达式求值:未知加法运算符");
bool is_float = (left.kind == ConstValue::FLOAT || right.kind == ConstValue::FLOAT);
if (is_float) {
float l = (left.kind == ConstValue::INT) ? static_cast<float>(left.int_val) : left.float_val;
float r = (right.kind == ConstValue::INT) ? static_cast<float>(right.int_val) : right.float_val;
ConstValue res;
res.kind = ConstValue::FLOAT;
if (op == "+") res.float_val = l + r;
else res.float_val = l - r;
return res;
} else {
int l = left.int_val;
int r = right.int_val;
ConstValue res;
res.kind = ConstValue::INT;
if (op == "+") res.int_val = l + r;
else res.int_val = l - r;
return res;
}
}
else {
return EvaluateMulExp(ctx->mulExp());
}
}
int SymbolTable::EvaluateConstExp(SysYParser::ConstExpContext* ctx) const {
if (!ctx || !ctx->addExp())
throw std::runtime_error("常量表达式求值:无效 ConstExp");
ConstValue val = EvaluateAddExp(ctx->addExp());
if (val.kind == ConstValue::INT) {
return val.int_val;
} else {
float f = val.float_val;
int i = static_cast<int>(f);
if (std::abs(f - i) > 1e-6) {
throw std::runtime_error("常量表达式求值:浮点常量不能隐式转换为整数");
}
return i;
}
}
float SymbolTable::EvaluateConstExpFloat(SysYParser::ConstExpContext* ctx) const {
if (!ctx || !ctx->addExp())
throw std::runtime_error("常量表达式求值:无效 ConstExp");
ConstValue val = EvaluateAddExp(ctx->addExp());
if (val.kind == ConstValue::INT) {
return static_cast<float>(val.int_val);
} else {
return val.float_val;
}
}
void SymbolTable::flattenInit(SysYParser::ConstInitValContext* ctx,
std::vector<ConstValue>& out,
std::shared_ptr<ir::Type> base_type) const {
if (!ctx) return;
// 获取当前初始化列表的文本(用于调试)
std::string ctxText;
if (ctx->constExp()) {
ctxText = ctx->constExp()->getText();
} else {
ctxText = "{ ... }";
}
if (ctx->constExp()) {
ConstValue val = EvaluateAddExp(ctx->constExp()->addExp());
DEBUG_MSG("处理常量表达式: " << ctxText
<< " 类型=" << (val.kind == ConstValue::INT ? "INT" : "FLOAT")
<< " 值=" << (val.kind == ConstValue::INT ? std::to_string(val.int_val) : std::to_string(val.float_val))
<< " 目标类型=" << (base_type->IsInt32() ? "Int32" : "Float"));
// 整型数组不能接受浮点常量
if (base_type->IsInt32() && val.kind == ConstValue::FLOAT) {
DEBUG_MSG("错误:整型数组遇到浮点常量,值=" << val.float_val);
throw std::runtime_error("常量初始化:整型数组不能使用浮点常量");
}
// 浮点数组接受整型常量,并隐式转换
if (base_type->IsFloat() && val.kind == ConstValue::INT) {
DEBUG_MSG("浮点数组接收整型常量,隐式转换为浮点: " << val.int_val);
val.kind = ConstValue::FLOAT;
val.float_val = static_cast<float>(val.int_val);
}
out.push_back(val);
} else {
DEBUG_MSG("进入花括号初始化列表: " << ctxText);
// 花括号初始化列表:递归展开所有子项
for (auto* sub : ctx->constInitVal()) {
flattenInit(sub, out, base_type);
}
DEBUG_MSG("退出花括号初始化列表");
}
}
std::vector<SymbolTable::ConstValue> SymbolTable::EvaluateConstInitVal(
SysYParser::ConstInitValContext* ctx,
const std::vector<int>& dims,
std::shared_ptr<ir::Type> base_type) const {
// ========== 1. 标量常量dims 为空)==========
if (dims.empty()) {
if (!ctx || !ctx->constExp()) {
throw std::runtime_error("标量常量初始化必须使用单个表达式");
}
ConstValue val = EvaluateAddExp(ctx->constExp()->addExp());
// 类型兼容性检查
/*
if (base_type->IsInt32() && val.kind == ConstValue::FLOAT) {
throw std::runtime_error("整型常量不能使用浮点常量初始化");
}
*/
// 隐式类型转换
if (base_type->IsInt32() && val.kind == ConstValue::FLOAT) {
val.kind = ConstValue::INT;
val.int_val = static_cast<int>(val.float_val);
}
if (base_type->IsFloat() && val.kind == ConstValue::INT) {
val.kind = ConstValue::FLOAT;
val.float_val = static_cast<float>(val.int_val);
}
return {val}; // 返回包含单个值的向量
}
// ========== 2. 数组常量dims 非空)==========
size_t total = 1;
for (int d : dims) total *= d;
ConstValue zero;
if (base_type->IsInt32()) {
zero.kind = ConstValue::INT;
zero.int_val = 0;
} else {
zero.kind = ConstValue::FLOAT;
zero.float_val = 0.0f;
}
// 先整体补零,再按 C 语言花括号规则覆盖显式初始化项。
std::vector<ConstValue> flat(total, zero);
auto convert_value = [&](ConstValue v) -> ConstValue {
if (base_type->IsInt32()) {
if (v.kind == ConstValue::FLOAT) {
throw std::runtime_error("常量初始化:整型数组不能使用浮点常量");
}
return v;
}
if (v.kind == ConstValue::INT) {
ConstValue t;
t.kind = ConstValue::FLOAT;
t.float_val = static_cast<float>(v.int_val);
return t;
}
return v;
};
auto subarray_span = [&](size_t depth) -> size_t {
size_t span = 1;
for (size_t i = depth + 1; i < dims.size(); ++i) span *= static_cast<size_t>(dims[i]);
return span;
};
std::function<size_t(SysYParser::ConstInitValContext*, size_t, size_t, size_t)> fill;
fill = [&](SysYParser::ConstInitValContext* node,
size_t depth,
size_t begin,
size_t end) -> size_t {
if (!node || begin >= end) return begin;
// 标量初始化项
if (node->constExp()) {
ConstValue v = convert_value(EvaluateAddExp(node->constExp()->addExp()));
if (begin < flat.size()) flat[begin] = v;
return std::min(begin + 1, end);
}
size_t cursor = begin;
for (auto* child : node->constInitVal()) {
if (cursor >= end) break;
if (child->constExp()) {
ConstValue v = convert_value(EvaluateAddExp(child->constExp()->addExp()));
if (cursor < flat.size()) flat[cursor] = v;
++cursor;
continue;
}
// 花括号子列表:在非最内层需要按子聚合边界对齐。
if (depth + 1 < dims.size()) {
const size_t span = subarray_span(depth);
const size_t rel = (cursor - begin) % span;
if (rel != 0) cursor += (span - rel);
if (cursor >= end) break;
const size_t sub_end = std::min(cursor + span, end);
fill(child, depth + 1, cursor, sub_end);
// 一个带花括号的子初始化器会消费当前层的一个子聚合。
cursor = sub_end;
} else {
// 最内层(标量数组)遇到额外花括号,按同层顺序展开。
cursor = fill(child, depth, cursor, end);
}
}
return cursor;
};
fill(ctx, 0, 0, total);
return flat;
}
int SymbolTable::EvaluateConstExpression(SysYParser::ExpContext* ctx) const {
if (!ctx || !ctx->addExp()) {
throw std::runtime_error("常量表达式求值:无效 ExpContext");
}
ConstValue val = EvaluateAddExp(ctx->addExp());
if (val.kind == ConstValue::INT) {
return val.int_val;
} else {
float f = val.float_val;
int i = static_cast<int>(f);
if (std::abs(f - i) > 1e-6) {
throw std::runtime_error("常量表达式求值:浮点常量不能隐式转换为整数");
}
return i;
}
}

@ -0,0 +1,5 @@
编译libsysy.a
```
aarch64-linux-gnu-gcc -c sylib.c -o sylib.o
aarch64-linux-gnu-ar rcs libsysy.a sylib.o
```

@ -1,4 +1,162 @@
// SysY 运行库实现:
// - 按实验/评测规范提供 I/O 等函数实现
// - 与编译器生成的目标代码链接,支撑运行时行为
#include "sylib.h"
#include <math.h>
#include <stdlib.h>
extern int scanf(const char* format, ...);
extern int printf(const char* format, ...);
extern int getchar(void);
extern int putchar(int c);
int getint(void) {
int x = 0;
scanf("%d", &x);
return x;
}
int getch(void) {
return getchar();
}
int getarray(int a[]) {
int n;
scanf("%d", &n);
int i = 0;
for (; i < n; ++i) {
scanf("%d", &a[i]);
}
return n;
}
float getfloat(void) {
float x = 0.0f;
scanf("%f", &x);
return x;
}
int getfarray(float a[]) {
int n = 0;
if (scanf("%d", &n) != 1) {
return 0;
}
int i = 0;
for (; i < n; ++i) {
if (scanf("%f", &a[i]) != 1) {
return i;
}
}
return n;
}
void putint(int x) {
printf("%d", x);
}
void putch(int x) {
putchar(x);
}
void putarray(int n, int a[]) {
int i = 0;
printf("%d:", n);
for (; i < n; ++i) {
printf(" %d", a[i]);
}
putchar('\n');
}
void putfloat(float x) {
printf("%a", x);
}
void putfarray(int n, float a[]) {
int i = 0;
printf("%d:", n);
for (; i < n; ++i) {
printf(" %a", a[i]);
}
putchar('\n');
}
void puts(int s[]) {
if (!s) return;
while (*s) {
putchar(*s);
++s;
}
}
void _sysy_starttime(int lineno) {
(void)lineno;
}
void _sysy_stoptime(int lineno) {
(void)lineno;
}
void starttime(void) {
_sysy_starttime(0);
}
void stoptime(void) {
_sysy_stoptime(0);
}
int* memset(int* ptr, int value, int count) {
unsigned char* p = (unsigned char*)ptr;
unsigned char byte = (unsigned char)(value & 0xFF);
int i = 0;
for (; i < count; ++i) {
p[i] = byte;
}
return ptr;
}
int* sysy_alloc_i32(int count) {
if (count <= 0) {
return 0;
}
return (int*)malloc((size_t)count * sizeof(int));
}
float* sysy_alloc_f32(int count) {
if (count <= 0) {
return 0;
}
return (float*)malloc((size_t)count * sizeof(float));
}
void sysy_free_i32(int* ptr) {
if (!ptr) {
return;
}
free(ptr);
}
void sysy_free_f32(float* ptr) {
if (!ptr) {
return;
}
free(ptr);
}
void sysy_zero_i32(int* ptr, int count) {
int i = 0;
if (!ptr || count <= 0) {
return;
}
for (; i < count; ++i) {
ptr[i] = 0;
}
}
void sysy_zero_f32(float* ptr, int count) {
int i = 0;
if (!ptr || count <= 0) {
return;
}
for (; i < count; ++i) {
ptr[i] = 0.0f;
}
}

@ -1,4 +1,29 @@
// SysY 运行库头文件:
// - 声明运行库函数原型(供编译器生成 call 或链接阶段引用)
// - 与 sylib.c 配套,按规范逐步补齐声明
#pragma once
int getint(void);
int getch(void);
int getarray(int a[]);
float getfloat(void);
int getfarray(float a[]);
void putint(int x);
void putch(int x);
void putarray(int n, int a[]);
void putfloat(float x);
void putfarray(int n, float a[]);
void puts(int s[]);
void _sysy_starttime(int lineno);
void _sysy_stoptime(int lineno);
void starttime(void);
void stoptime(void);
int read_map(void);
int* memset(int* ptr, int value, int count);
int* sysy_alloc_i32(int count);
float* sysy_alloc_f32(int count);
void sysy_free_i32(int* ptr);
void sysy_free_f32(float* ptr);
void sysy_zero_i32(int* ptr, int count);
void sysy_zero_f32(float* ptr, int count);

@ -0,0 +1 @@
int main() { return 0; }

@ -0,0 +1 @@
int main() { return 0; }

@ -0,0 +1 @@
int add(int a, int b) { return a + b; } int main() { return add(1, 2); }
Loading…
Cancel
Save