./scripts/verify_ir.sh test/test_case/functional/09_func_defn.sy --run

[error] [ir] StoreInst 当前只支持写入 i32*还有个问题没解决
hp 3 days ago
parent 3ad2437169
commit 5ce6b687a3

@ -45,6 +45,7 @@ class Value;
class User;
class ConstantValue;
class ConstantInt;
class ConstantFloat;
class GlobalValue;
class Instruction;
class BasicBlock;
@ -129,6 +130,8 @@ class Value {
bool IsInt1() const;
bool IsInt32() const;
bool IsPtrInt32() const;
bool IsFloat() const;
bool IsPtrFloat() const;
bool IsConstant() const;
bool IsInstruction() const;
bool IsUser() const;

@ -60,11 +60,24 @@ class IRGenImpl final : public SysYBaseVisitor {
const SemanticContext& sema_;
ir::Function* func_;
ir::IRBuilder builder_;
// 名称绑定由 Sema 负责IRGen 只维护"变量名 -> 存储槽位"的代码生成状态。
std::unordered_map<std::string, ir::Value*> storage_map_;
// 考虑到嵌套作用域(全局、函数、语句块),使用 vector 模拟栈来管理 storage_map_ 和 const_values_
std::vector<std::unordered_map<std::string, ir::Value*>> storage_map_stack_;
std::vector<std::unordered_map<std::string, ir::ConstantValue*>> const_values_stack_;
// 用于在栈中查找变量
ir::Value* FindStorage(const std::string& name) const {
for (auto it = storage_map_stack_.rbegin(); it != storage_map_stack_.rend(); ++it) {
if (it->count(name)) return it->at(name);
}
return nullptr;
}
// 记录常量名到常量值的映射,用于后续生成指令时直接替换
std::unordered_map<std::string, ir::ConstantValue*> const_values_;
ir::ConstantValue* FindConst(const std::string& name) const {
for (auto it = const_values_stack_.rbegin(); it != const_values_stack_.rend(); ++it) {
if (it->count(name)) return it->at(name);
}
return nullptr;
}
// 用于 break 和 continue 跳转的目标位置
ir::BasicBlock* current_loop_cond_bb_ = nullptr;

@ -14,6 +14,7 @@ add_executable(compiler
)
target_link_libraries(compiler PRIVATE
frontend
ir
utils
)

@ -64,7 +64,8 @@ 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 val_ty = (ptr->GetType() && ptr->GetType()->IsPtrFloat()) ? Type::GetFloatType() : Type::GetInt32Type();
return insert_block_->Append<LoadInst>(val_ty, ptr, name);
}
StoreInst* IRBuilder::CreateStore(Value* val, Value* ptr) {
@ -108,7 +109,8 @@ UnaryInst* IRBuilder::CreateNeg(Value* operand, const std::string& name) {
if (!operand) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateNeg 缺少操作数"));
}
return insert_block_->Append<UnaryInst>(Opcode::Neg, Type::GetInt32Type(), operand, name);
auto val_ty = (operand->GetType() && operand->GetType()->IsFloat()) ? Type::GetFloatType() : Type::GetInt32Type();
return insert_block_->Append<UnaryInst>(Opcode::Neg, val_ty, operand, name);
}
CmpInst* IRBuilder::CreateCmp(CmpOp op, Value* lhs, Value* rhs, const std::string& name) {

@ -75,8 +75,8 @@ BinaryInst::BinaryInst(Opcode op, std::shared_ptr<Type> ty, Value* lhs,
type_->GetKind() != lhs->GetType()->GetKind()) {
throw std::runtime_error(FormatError("ir", "BinaryInst 类型不匹配"));
}
if (!type_->IsInt32()) {
throw std::runtime_error(FormatError("ir", "BinaryInst 当前只支持 i32"));
if (!type_->IsInt32() && !type_->IsFloat()) {
throw std::runtime_error(FormatError("ir", "BinaryInst 当前只支持 i32 或 float"));
}
AddOperand(lhs);
AddOperand(rhs);
@ -101,8 +101,8 @@ UnaryInst::UnaryInst(Opcode op, std::shared_ptr<Type> ty, Value* operand,
if (type_->GetKind() != operand->GetType()->GetKind()) {
throw std::runtime_error(FormatError("ir", "UnaryInst 类型不匹配"));
}
if (!type_->IsInt32()) {
throw std::runtime_error(FormatError("ir", "UnaryInst 当前只支持 i32"));
if (!type_->IsInt32() && !type_->IsFloat()) {
throw std::runtime_error(FormatError("ir", "UnaryInst 当前只支持 i32 或 float"));
}
AddOperand(operand);
}
@ -124,8 +124,8 @@ Value* ReturnInst::GetValue() const { 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())) {
throw std::runtime_error(FormatError("ir", "AllocaInst 当前只支持 i32* 或 float*"));
}
}
@ -134,12 +134,19 @@ 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())) {
throw std::runtime_error(FormatError("ir", "LoadInst 当前只支持加载 i32 或 float"));
}
if (!ptr->GetType() || !ptr->GetType()->IsPtrInt32()) {
throw std::runtime_error(
FormatError("ir", "LoadInst 当前只支持从 i32* 加载"));
if (type_->IsInt32()) {
if (!ptr->GetType() || !ptr->GetType()->IsPtrInt32()) {
throw std::runtime_error(
FormatError("ir", "LoadInst 当前只支持从 i32* 加载"));
}
} else if (type_->IsFloat()) {
if (!ptr->GetType() || !ptr->GetType()->IsPtrFloat()) {
throw std::runtime_error(
FormatError("ir", "LoadInst 当前只支持从 float* 加载"));
}
}
AddOperand(ptr);
}
@ -157,12 +164,19 @@ 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()) {
throw std::runtime_error(
FormatError("ir", "StoreInst 当前只支持写入 i32*"));
if (!val->GetType() || (!val->GetType()->IsInt32() && !val->GetType()->IsFloat())) {
throw std::runtime_error(FormatError("ir", "StoreInst 当前只支持存储 i32 或 float"));
}
if (val->GetType()->IsInt32()) {
if (!ptr->GetType() || !ptr->GetType()->IsPtrInt32()) {
throw std::runtime_error(
FormatError("ir", "StoreInst 当前只支持写入 i32*"));
}
} else if (val->GetType()->IsFloat()) {
if (!ptr->GetType() || !ptr->GetType()->IsPtrFloat()) {
throw std::runtime_error(
FormatError("ir", "StoreInst 当前只支持写入 float*"));
}
}
AddOperand(val);
AddOperand(ptr);

@ -25,6 +25,16 @@ const std::shared_ptr<Type>& Type::GetPtrInt32Type() {
return type;
}
const std::shared_ptr<Type>& Type::GetFloatType() {
static std::shared_ptr<Type> ty = std::make_shared<Type>(Kind::Float);
return ty;
}
const std::shared_ptr<Type>& Type::GetPtrFloatType() {
static std::shared_ptr<Type> ty = std::make_shared<Type>(Kind::PtrFloat);
return ty;
}
Type::Kind Type::GetKind() const { return kind_; }
bool Type::IsVoid() const { return kind_ == Kind::Void; }
@ -35,4 +45,8 @@ bool Type::IsInt32() const { return kind_ == Kind::Int32; }
bool Type::IsPtrInt32() const { return kind_ == Kind::PtrInt32; }
bool Type::IsFloat() const { return kind_ == Kind::Float; }
bool Type::IsPtrFloat() const { return kind_ == Kind::PtrFloat; }
} // namespace ir

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

@ -10,6 +10,11 @@ std::any IRGenImpl::visitBlock(SysYParser::BlockContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少语句块"));
}
// 压入局部作用域
storage_map_stack_.push_back({});
const_values_stack_.push_back({});
bool terminated = false;
for (auto* item : ctx->blockItem()) {
if (item) {
@ -19,6 +24,11 @@ std::any IRGenImpl::visitBlock(SysYParser::BlockContext* ctx) {
}
}
}
// 弹出局部作用域
storage_map_stack_.pop_back();
const_values_stack_.pop_back();
return terminated ? BlockFlow::Terminated : BlockFlow::Continue;
}
@ -87,15 +97,21 @@ std::any IRGenImpl::visitConstDef(SysYParser::ConstDefContext* ctx) {
}
// 记录常量值供后续直接使用
const_values_[var_name] = init_const;
if (!const_values_stack_.empty()) {
const_values_stack_.back()[var_name] = init_const;
}
if (func_ == nullptr) {
auto* gv = module_.CreateGlobalVariable(var_name, base_ty, init_const);
storage_map_[var_name] = gv;
if (!storage_map_stack_.empty()) {
storage_map_stack_.back()[var_name] = gv;
}
} else {
ir::Value* slot = is_float ? builder_.CreateAllocaFloat(module_.GetContext().NextTemp())
: builder_.CreateAllocaI32(module_.GetContext().NextTemp());
storage_map_[var_name] = slot;
if (!storage_map_stack_.empty()) {
storage_map_stack_.back()[var_name] = slot;
}
builder_.CreateStore(init_const, slot);
}
@ -144,7 +160,7 @@ std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) {
throw std::runtime_error(FormatError("irgen", "暂不支持数组声明"));
}
std::string var_name = ctx->ID()->getText();
if (storage_map_.find(var_name) != storage_map_.end()) {
if (!storage_map_stack_.empty() && storage_map_stack_.back().find(var_name) != storage_map_stack_.back().end()) {
throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位"));
}
@ -177,11 +193,13 @@ std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) {
}
auto* gv = module_.CreateGlobalVariable(var_name, base_ty, init_const);
storage_map_[var_name] = gv;
if (!storage_map_stack_.empty()) {
storage_map_stack_.back()[var_name] = gv;
}
} else {
// 局部作用域
auto* ptr_ty = is_float ? ir::Type::GetPtrFloatType() : ir::Type::GetPtrInt32Type();
auto ptr_ty = is_float ? ir::Type::GetPtrFloatType() : ir::Type::GetPtrInt32Type();
// 简化处理,暂用 builder 创建 alloca
// 需要在 builder 中扩展 CreateAllocaFloat此处简化直接按 I32 Alloca 的名称调用,或添加新接口
// 为了不大幅改动 Builder我们复用 AllocaInst或者添加 CreateAlloca
@ -192,7 +210,9 @@ std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) {
slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp());
}
storage_map_[var_name] = slot;
if (!storage_map_stack_.empty()) {
storage_map_stack_.back()[var_name] = slot;
}
ir::Value* init = nullptr;
if (auto* init_val = ctx->initVal()) {

@ -47,14 +47,14 @@ std::any IRGenImpl::visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) {
"变量使用缺少语义绑定:" + lval_ctx->ID()->getText()));
}
std::string var_name = lval_ctx->ID()->getText();
auto it = storage_map_.find(var_name);
if (it == storage_map_.end()) {
ir::Value* slot = FindStorage(var_name);
if (!slot) {
throw std::runtime_error(
FormatError("irgen",
"变量声明缺少存储槽位:" + var_name));
}
return static_cast<ir::Value*>(
builder_.CreateLoad(it->second, module_.GetContext().NextTemp()));
builder_.CreateLoad(slot, module_.GetContext().NextTemp()));
}
// 处理 number
if (ctx->number()) {
@ -65,11 +65,21 @@ std::any IRGenImpl::visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) {
std::any IRGenImpl::visitNumber(SysYParser::NumberContext* ctx) {
if (!ctx || !ctx->intConst()) {
throw std::runtime_error(FormatError("irgen", "当前仅支持整数字面量"));
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少字面量节点"));
}
return static_cast<ir::Value*>(
builder_.CreateConstInt(std::stoi(ctx->intConst()->getText())));
if (ctx->intConst()) {
// 可能是 0x, 0X, 0 开头的八进制等,目前 std::stoi 会处理十进制,
// 为了支持 16 进制/8 进制建议使用 std::stoi(str, nullptr, 0)
std::string text = ctx->intConst()->getText();
return static_cast<ir::Value*>(
builder_.CreateConstInt(std::stoi(text, nullptr, 0)));
} else if (ctx->floatConst()) {
std::string text = ctx->floatConst()->getText();
return static_cast<ir::Value*>(
module_.GetContext().GetConstFloat(std::stof(text)));
}
throw std::runtime_error(FormatError("irgen", "不支持的字面量"));
}
// 变量使用的处理流程:
@ -86,9 +96,9 @@ std::any IRGenImpl::visitLVal(SysYParser::LValContext* ctx) {
std::string var_name = ctx->ID()->getText();
// 优先检查是否为已记录的常量,如果是则直接返回常量值,不再生成 Load 指令
auto it_const = const_values_.find(var_name);
if (it_const != const_values_.end()) {
return static_cast<ir::Value*>(it_const->second);
ir::ConstantValue* const_val = FindConst(var_name);
if (const_val) {
return static_cast<ir::Value*>(const_val);
}
const auto* decl = sema_.ResolveObjectUse(ctx);
@ -98,14 +108,14 @@ std::any IRGenImpl::visitLVal(SysYParser::LValContext* ctx) {
"变量使用缺少语义绑定:" + ctx->ID()->getText()));
}
// 使用变量名查找存储槽位
auto it = storage_map_.find(var_name);
if (it == storage_map_.end()) {
ir::Value* slot = FindStorage(var_name);
if (!slot) {
throw std::runtime_error(
FormatError("irgen",
"变量声明缺少存储槽位:" + var_name));
}
return static_cast<ir::Value*>(
builder_.CreateLoad(it->second, module_.GetContext().NextTemp()));
builder_.CreateLoad(slot, module_.GetContext().NextTemp()));
}
@ -158,7 +168,7 @@ std::any IRGenImpl::visitUnaryExp(SysYParser::UnaryExpContext* ctx) {
// 从 Sema 或 Module 中查找函数
// 目前简化处理,直接从 Module 中查找(如果是当前文件内定义的)
// 或者依赖 Sema 给出解析结果
const sem::FunctionBinding* func_binding = sema_.ResolveFunctionCall(ctx);
const FunctionBinding* func_binding = sema_.ResolveFunctionCall(ctx);
if (!func_binding) {
throw std::runtime_error(FormatError("irgen", "未找到函数声明:" + func_name));
}
@ -177,9 +187,9 @@ std::any IRGenImpl::visitUnaryExp(SysYParser::UnaryExpContext* ctx) {
// 可能是外部函数如 putint, getint 等
// 如果没有在 module_ 中,则需要创建一个只有声明的 Function
std::shared_ptr<ir::Type> ret_ty;
if (func_binding->GetReturnType()->IsInt()) {
if (func_binding->return_type == SemanticType::Int) {
ret_ty = ir::Type::GetInt32Type();
} else if (func_binding->GetReturnType()->IsFloat()) {
} else if (func_binding->return_type == SemanticType::Float) {
ret_ty = ir::Type::GetFloatType();
} else {
ret_ty = ir::Type::GetVoidType();
@ -202,10 +212,17 @@ std::any IRGenImpl::visitUnaryExp(SysYParser::UnaryExpContext* ctx) {
// 判断是正号还是负号
if (ctx->addUnaryOp()->SUB()) {
// 负号:生成 sub 0, operandLLVM IR 中没有 neg 指令)
ir::Value* zero = builder_.CreateConstInt(0);
return static_cast<ir::Value*>(
builder_.CreateSub(zero, operand, module_.GetContext().NextTemp()));
// 负号:如果是整数生成 sub 0, operand浮点数生成 fsub 0.0, operand
if (operand->GetType()->IsFloat()) {
ir::Value* zero = module_.GetContext().GetConstFloat(0.0f);
// 此处暂且假设 CreateSub 可以处理浮点数(如果底层有 fsub 则更好)
return static_cast<ir::Value*>(
builder_.CreateSub(zero, operand, module_.GetContext().NextTemp()));
} else {
ir::Value* zero = builder_.CreateConstInt(0);
return static_cast<ir::Value*>(
builder_.CreateSub(zero, operand, module_.GetContext().NextTemp()));
}
} else if (ctx->addUnaryOp()->ADD()) {
// 正号:直接返回操作数(+x 等价于 x
return operand;

@ -38,6 +38,10 @@ std::any IRGenImpl::visitCompUnit(SysYParser::CompUnitContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少编译单元"));
}
// 初始化全局作用域
storage_map_stack_.push_back({});
const_values_stack_.push_back({});
// 遍历所有 topLevelItem
for (auto* item : ctx->topLevelItem()) {
if (!item) continue;
@ -47,6 +51,11 @@ std::any IRGenImpl::visitCompUnit(SysYParser::CompUnitContext* ctx) {
item->decl()->accept(this);
}
}
// 退出全局作用域
storage_map_stack_.pop_back();
const_values_stack_.pop_back();
return {};
}
@ -69,7 +78,7 @@ std::any IRGenImpl::visitFuncDef(SysYParser::FuncDefContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少函数定义"));
}
if (!ctx->blockStmt()) {
if (!ctx->block()) {
throw std::runtime_error(FormatError("irgen", "函数体为空"));
}
if (!ctx->ID()) {
@ -89,7 +98,10 @@ std::any IRGenImpl::visitFuncDef(SysYParser::FuncDefContext* ctx) {
func_ = module_.CreateFunction(ctx->ID()->getText(), ret_type);
builder_.SetInsertPoint(func_->GetEntry());
storage_map_.clear();
// 进入函数作用域,压入一个新的 map
storage_map_stack_.push_back({});
const_values_stack_.push_back({});
if (ctx->funcFParams()) {
for (auto* paramCtx : ctx->funcFParams()->funcFParam()) {
@ -115,13 +127,18 @@ std::any IRGenImpl::visitFuncDef(SysYParser::FuncDefContext* ctx) {
}
builder_.CreateStore(arg, alloca_inst);
storage_map_[arg_name] = alloca_inst;
storage_map_stack_.back()[arg_name] = alloca_inst;
}
}
ctx->blockStmt()->accept(this);
ctx->block()->accept(this);
VerifyFunctionStructure(*func_);
func_ = nullptr;
// 退出函数作用域,弹出 map
storage_map_stack_.pop_back();
const_values_stack_.pop_back();
return {};
}

@ -35,12 +35,19 @@ std::any IRGenImpl::visitStmt(SysYParser::StmtContext* ctx) {
FormatError("irgen", "变量使用缺少语义绑定:" + lval_ctx->ID()->getText()));
}
std::string var_name = lval_ctx->ID()->getText();
auto it = storage_map_.find(var_name);
if (it == storage_map_.end()) {
ir::Value* slot = FindStorage(var_name);
if (!slot) {
throw std::runtime_error(
FormatError("irgen", "变量声明缺少存储槽位:" + var_name));
}
builder_.CreateStore(rhs, it->second);
// 如果 rhs 和 slot 的基类型不匹配,需要在这里做类型转换
// 为了简化并能通过当前测试,如果底层没有 float/int 转换指令
// 如果真的遇到 float 赋值给 int或者 int 赋值给 float并且这里直接抛异常
// 说明我们需要补齐类型转换指令(但当前没有),先忽略隐式转换或让 StoreInst 自行报错。
// 但是这里最可能的原因是 rhs 在经过表达式求值后,类型丢失了 float 的标志。
builder_.CreateStore(rhs, slot);
return BlockFlow::Continue;
}

@ -0,0 +1,19 @@
(base) root@HP:/home/hp/nudt-compiler-cpp/build# make -j$(nproc)
[ 2%] Built target utils
[ 2%] Building CXX object src/ir/CMakeFiles/ir_core.dir/Type.cpp.o
[ 3%] Building CXX object src/ir/CMakeFiles/ir_core.dir/Value.cpp.o
[ 73%] Built target antlr4_runtime
[ 75%] Built target sem
[ 79%] Built target frontend
[ 80%] Linking CXX static library libir_core.a
[ 84%] Built target ir_core
[ 85%] Built target ir_analysis
[ 89%] Built target ir_passes
[ 94%] Built target mir_core
[ 97%] Built target irgen
[ 99%] Built target mir_passes
[ 99%] Linking CXX executable ../bin/compiler
[100%] Built target compiler
(base) root@HP:/home/hp/nudt-compiler-cpp/build# cd ..
(base) root@HP:/home/hp/nudt-compiler-cpp# ./scripts/verify_ir.sh test/test_case/functional/09_func_defn.sy --run
[error] [irgen] 变量声明缺少存储槽位a
Loading…
Cancel
Save