From 5e7e8a6ff292393c187f19d9db9fd6b192615a8a Mon Sep 17 00:00:00 2001 From: potapo <2720187907@qq.com> Date: Fri, 27 Mar 2026 16:16:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B0=E7=BB=84=E6=9C=AA=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ir/IRBuilder.cpp | 57 +++++++++++++++++- src/ir/Instruction.cpp | 65 +++++++++++++++++--- src/irgen/IRGenDecl.cpp | 103 ++++++++++++++++++++++++++++++-- src/irgen/IRGenExp.cpp | 129 +++++++++++++++++++++++++++++++--------- 4 files changed, 313 insertions(+), 41 deletions(-) diff --git a/src/ir/IRBuilder.cpp b/src/ir/IRBuilder.cpp index 950a1aa..0bddcd9 100644 --- a/src/ir/IRBuilder.cpp +++ b/src/ir/IRBuilder.cpp @@ -34,7 +34,62 @@ BinaryInst* IRBuilder::CreateBinary(Opcode op, Value* lhs, Value* rhs, throw std::runtime_error( FormatError("ir", "IRBuilder::CreateBinary 缺少 rhs")); } - return insert_block_->Append(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::ICmpEQ: + case Opcode::ICmpNE: + case Opcode::ICmpSLT: + case Opcode::ICmpSLE: + case Opcode::ICmpSGT: + case Opcode::ICmpSGE: + case Opcode::And: + case Opcode::Or: + // 有效的二元操作符 + break; + case Opcode::Not: + // Not是一元操作符,不应该在BinaryInst中 + throw std::runtime_error(FormatError("ir", "Not是一元操作符,应使用其他指令")); + default: + throw std::runtime_error(FormatError("ir", "BinaryInst 不支持的操作码")); + } + + // 确定结果类型 + std::shared_ptr result_type; + + // 检查操作数类型是否相同 + if (lhs->GetType()->GetKind() != rhs->GetType()->GetKind()) { + throw std::runtime_error( + FormatError("ir", "CreateBinary 操作数类型不匹配")); + } + + // 根据操作符确定结果类型 + bool is_compare = (op == Opcode::ICmpEQ || op == Opcode::ICmpNE || + op == Opcode::ICmpSLT || op == Opcode::ICmpSLE || + op == Opcode::ICmpSGT || op == Opcode::ICmpSGE); + + bool is_logical = (op == Opcode::And || op == Opcode::Or); + + if (is_compare || 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(op, result_type, lhs, rhs, name); } BinaryInst* IRBuilder::CreateAdd(Value* lhs, Value* rhs, diff --git a/src/ir/Instruction.cpp b/src/ir/Instruction.cpp index 351b6fb..a84e0c3 100644 --- a/src/ir/Instruction.cpp +++ b/src/ir/Instruction.cpp @@ -61,22 +61,73 @@ void Instruction::SetParent(BasicBlock* parent) { parent_ = parent; } BinaryInst::BinaryInst(Opcode op, std::shared_ptr 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")); + // 检查操作码是否为有效的二元操作符 + switch (op) { + case Opcode::Add: + case Opcode::Sub: + case Opcode::Mul: + case Opcode::Div: + case Opcode::Mod: + case Opcode::ICmpEQ: + case Opcode::ICmpNE: + case Opcode::ICmpSLT: + case Opcode::ICmpSLE: + case Opcode::ICmpSGT: + case Opcode::ICmpSGE: + case Opcode::And: + case Opcode::Or: + // 有效的二元操作符 + break; + case Opcode::Not: + // Not是一元操作符,不应该在BinaryInst中 + throw std::runtime_error(FormatError("ir", "Not是一元操作符,应使用其他指令")); + default: + throw std::runtime_error(FormatError("ir", "BinaryInst 不支持的操作码")); } + if (!lhs || !rhs) { throw std::runtime_error(FormatError("ir", "BinaryInst 缺少操作数")); } + 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 (!lhs->GetType()->IsInt32() && !lhs->GetType()->IsFloat()) { + throw std::runtime_error( + FormatError("ir", "BinaryInst 只支持 int32 和 float 类型")); } - if (!type_->IsInt32()) { - throw std::runtime_error(FormatError("ir", "BinaryInst 当前只支持 i32")); + + // 对于算术运算,结果类型应与操作数类型相同 + // 对于比较运算,结果类型是int32(布尔值) + bool is_compare = (op == Opcode::ICmpEQ || op == Opcode::ICmpNE || + op == Opcode::ICmpSLT || op == Opcode::ICmpSLE || + op == Opcode::ICmpSGT || op == Opcode::ICmpSGE); + + bool is_logical = (op == Opcode::And || op == Opcode::Or); + + if (is_compare || is_logical) { + // 比较和逻辑运算的结果应该是整数类型 + if (!type_->IsInt32()) { + throw std::runtime_error( + FormatError("ir", "比较和逻辑运算的结果类型必须是 int32")); + } + } else { + // 算术运算的结果类型应与操作数类型相同 + if (type_->GetKind() != lhs->GetType()->GetKind()) { + throw std::runtime_error( + FormatError("ir", "BinaryInst 结果类型与操作数类型不匹配")); + } } + AddOperand(lhs); AddOperand(rhs); } diff --git a/src/irgen/IRGenDecl.cpp b/src/irgen/IRGenDecl.cpp index 34428c3..12dce7b 100644 --- a/src/irgen/IRGenDecl.cpp +++ b/src/irgen/IRGenDecl.cpp @@ -16,6 +16,15 @@ std::string GetLValueName(SysYParser::LValContext& lvalue) { return lvalue.Ident()->getText(); } +int TryGetConstInt(SysYParser::ConstExpContext* ctx) { + // 这里是一个简化的版本,实际上应该调用语义分析的常量求值 + // 暂时假设所有常量表达式都是整数常量 + // 实际实现需要更复杂的逻辑 + + // 简化为返回10 + return 10; +} + } // namespace // 注意:visitBlock 已经在 IRGenFunc.cpp 中实现,这里不要重复定义 @@ -89,6 +98,7 @@ std::any IRGenImpl::visitConstDef(SysYParser::ConstDefContext* ctx) { return {}; } +// 修改 visitVarDef 以支持简单的聚合初始化 std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少变量定义")); @@ -116,6 +126,10 @@ std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) { // 尝试获取数组大小(需要常量表达式求值) // 简化:假设第一个维度为10 array_size = 10; + + // 尝试从常量表达式获取大小 + // TODO: 这里需要常量表达式求值的支持 + // 暂时使用简化处理 } // 分配数组存储(简化:为每个元素分配独立存储) @@ -128,6 +142,7 @@ std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) { auto* slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp() + "_" + std::to_string(i)); element_slots.push_back(slot); } + // 处理初始化 if (auto* initVal = ctx->initVal()) { if (initVal->exp()) { @@ -140,10 +155,43 @@ std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) { builder_.CreateStore(builder_.CreateConstInt(0), element_slots[i]); } } else { - // 聚合初始化 - throw std::runtime_error(FormatError("irgen", "数组聚合初始化暂未实现")); + // 聚合初始化 - 现在实现简单的聚合初始化 + auto initVals = initVal->initVal(); + + if (initVals.empty()) { + // 空初始化列表,全部初始化为0 + for (int i = 0; i < array_size; i++) { + builder_.CreateStore(builder_.CreateConstInt(0), element_slots[i]); + } + } else { + // 有初始化值列表 + int init_index = 0; + for (auto* init_val : initVals) { + if (init_index >= array_size) { + throw std::runtime_error( + FormatError("irgen", "初始化值太多,数组大小为" + std::to_string(array_size))); + } + + if (init_val->exp()) { + // 简单表达式初始化 + ir::Value* val = EvalExpr(*init_val->exp()); + builder_.CreateStore(val, element_slots[init_index]); + } else { + // 嵌套的聚合初始化(暂不支持) + throw std::runtime_error( + FormatError("irgen", "嵌套聚合初始化暂未实现")); + } + + init_index++; + } + + // 剩余元素初始化为0 + for (int i = init_index; i < array_size; i++) { + builder_.CreateStore(builder_.CreateConstInt(0), element_slots[i]); + } + } } - }else { + } else { // 无初始化,所有元素初始化为0 for (int i = 0; i < array_size; i++) { builder_.CreateStore(builder_.CreateConstInt(0), element_slots[i]); @@ -173,7 +221,15 @@ std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) { if (initVals.empty()) { init = builder_.CreateConstInt(0); } else if (initVals.size() == 1) { - init = std::any_cast(initVals[0]->accept(this)); + // 递归处理嵌套的初始化值 + auto* inner_init_val = initVals[0]; + if (inner_init_val->exp()) { + init = EvalExpr(*inner_init_val->exp()); + } else { + // 多层嵌套暂不支持 + throw std::runtime_error( + FormatError("irgen", "标量变量的多层嵌套初始化暂不支持")); + } } else { throw std::runtime_error( FormatError("irgen", "标量变量聚合初始化只能有一个值")); @@ -189,3 +245,42 @@ std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) { return {}; } +// 修改后的 visitInitVal,支持简单的聚合初始化 +std::any IRGenImpl::visitInitVal(SysYParser::InitValContext* ctx) { + if (!ctx) { + throw std::runtime_error(FormatError("irgen", "非法初始化值")); + } + + // 如果是单个表达式 + if (ctx->exp()) { + return EvalExpr(*ctx->exp()); + } + // 如果是聚合初始化(花括号列表) + else if (!ctx->initVal().empty()) { + // 返回一个 vector,包含所有初始化值 + std::vector initValues; + + for (auto* initVal : ctx->initVal()) { + // 递归处理每个初始化值 + auto result = initVal->accept(this); + if (result.has_value()) { + try { + ir::Value* value = std::any_cast(result); + initValues.push_back(value); + } catch (const std::bad_any_cast&) { + // 可能返回的是 vector,对于嵌套数组初始化 + // 简化:我们暂时只支持一维数组 + throw std::runtime_error( + FormatError("irgen", "暂不支持多维数组初始化")); + } + } + } + + // 返回初始化值列表 + return initValues; + } + + throw std::runtime_error(FormatError("irgen", "不支持的初始化值形式")); +} + + diff --git a/src/irgen/IRGenExp.cpp b/src/irgen/IRGenExp.cpp index ccc7413..b0cb31f 100644 --- a/src/irgen/IRGenExp.cpp +++ b/src/irgen/IRGenExp.cpp @@ -111,6 +111,7 @@ std::any IRGenImpl::visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) { } // visitLVal +// 修改 visitLVal 以支持数组访问 std::any IRGenImpl::visitLVal(SysYParser::LValContext* ctx) { if (!ctx || !ctx->Ident()) { throw std::runtime_error(FormatError("irgen", "非法左值")); @@ -135,13 +136,43 @@ std::any IRGenImpl::visitLVal(SysYParser::LValContext* ctx) { "变量声明缺少存储槽位: " + varName)); } - ir::Value* load_result = builder_.CreateLoad(it->second, module_.GetContext().NextTemp()); - std::cerr << "[DEBUG] visitLVal: created load, result = " << (void*)load_result << std::endl; + ir::Value* base_ptr = it->second; - return static_cast(load_result); + // 检查是否有数组下标(是否是数组访问) + auto exp_list = ctx->exp(); + if (!exp_list.empty()) { + // 这是数组访问,需要生成GEP指令 + std::vector indices; + + // 第一个索引是0(假设一维数组) + indices.push_back(builder_.CreateConstInt(0)); + + // 添加用户提供的下标 + for (auto* exp : exp_list) { + ir::Value* index = EvalExpr(*exp); + indices.push_back(index); + } + + // 生成GEP指令获取元素地址 + ir::Value* elem_ptr = builder_.CreateGEP( + base_ptr, indices, module_.GetContext().NextTemp()); + + // 加载值 + ir::Value* load_result = builder_.CreateLoad( + elem_ptr, module_.GetContext().NextTemp()); + std::cerr << "[DEBUG] visitLVal: array access, result = " << (void*)load_result << std::endl; + + return static_cast(load_result); + } else { + // 普通标量变量访问 + ir::Value* load_result = builder_.CreateLoad( + base_ptr, module_.GetContext().NextTemp()); + std::cerr << "[DEBUG] visitLVal: scalar load, result = " << (void*)load_result << std::endl; + + return static_cast(load_result); + } } - // 加法表达式 std::any IRGenImpl::visitAddExp(SysYParser::AddExpContext* ctx) { if (!ctx) { @@ -386,16 +417,6 @@ std::any IRGenImpl::visitConstInitVal(SysYParser::ConstInitValContext* ctx) { } } -std::any IRGenImpl::visitInitVal(SysYParser::InitValContext* ctx) { - // 返回初始化的值(可能是单个表达式或聚合列表) - if (ctx->exp()) { - return EvalExpr(*ctx->exp()); - } else { - // 聚合初始化:需要返回一个列表,暂未实现 - throw std::runtime_error(FormatError("irgen", "聚合初始化暂未实现")); - } -} - std::any IRGenImpl::visitConstExp(SysYParser::ConstExpContext* ctx) { // 消除未使用参数警告 (void)ctx; // 明确表示参数未使用 @@ -415,7 +436,7 @@ std::any IRGenImpl::visitRelExp(SysYParser::RelExpContext* ctx) { throw std::runtime_error(FormatError("irgen", "非法关系表达式")); } - // 如果是基本形式 AddExp + // 如果是基本形式 AddExp(没有关系操作符) if (!ctx->relExp()) { return ctx->addExp()->accept(this); } @@ -434,27 +455,52 @@ std::any IRGenImpl::visitRelExp(SysYParser::RelExpContext* ctx) { } ir::Value* right = std::any_cast(right_any); - // 根据操作符生成相应的比较指令 - std::string op = ctx->relExp()->getText(); + // 通过操作符文本来判断,这样更通用 + // 获取操作符文本(这需要查看具体的语法定义) + // 由于不知道具体的方法名,我们采用更通用的方法 + + // 方法1:尝试通过relOp()获取操作符 + if (auto relOp = ctx->relExp()) { + std::string op = relOp->getText(); + + if (op == "<" || op == "Lt") { + return static_cast( + builder_.CreateICmpSLT(left, right, module_.GetContext().NextTemp())); + } else if (op == ">" || op == "Gt") { + return static_cast( + builder_.CreateICmpSGT(left, right, module_.GetContext().NextTemp())); + } else if (op == "<=" || op == "Le") { + return static_cast( + builder_.CreateICmpSLE(left, right, module_.GetContext().NextTemp())); + } else if (op == ">=" || op == "Ge") { + return static_cast( + builder_.CreateICmpSGE(left, right, module_.GetContext().NextTemp())); + } + } - if (op == "<") { + // 方法2:检查是否有特定的操作符方法 + // 根据错误信息,可能是LOp和GOp + if (ctx->LOp()) { // "<" return static_cast( builder_.CreateICmpSLT(left, right, module_.GetContext().NextTemp())); - } else if (op == ">") { + } else if (ctx->GOp()) { // ">" return static_cast( builder_.CreateICmpSGT(left, right, module_.GetContext().NextTemp())); - } else if (op == "<=") { + } + + // 方法3:检查Le和Ge + if (ctx->LeOp()) { // "<=" return static_cast( builder_.CreateICmpSLE(left, right, module_.GetContext().NextTemp())); - } else if (op == ">=") { + } else if (ctx->GeOp()) { // ">=" return static_cast( builder_.CreateICmpSGE(left, right, module_.GetContext().NextTemp())); } - throw std::runtime_error(FormatError("irgen", "未知的关系操作符: " + op)); + throw std::runtime_error(FormatError("irgen", "未知的关系操作符")); } -//赋值 +// 修改 EvalAssign 以支持数组赋值 ir::Value* IRGenImpl::EvalAssign(SysYParser::StmtContext* ctx) { if (!ctx || !ctx->lVal() || !ctx->exp()) { throw std::runtime_error(FormatError("irgen", "非法赋值语句")); @@ -463,11 +509,11 @@ ir::Value* IRGenImpl::EvalAssign(SysYParser::StmtContext* ctx) { // 计算右值 ir::Value* rhs = EvalExpr(*ctx->exp()); - // 获取左值地址 - std::string varName = ctx->lVal()->Ident()->getText(); + auto* lval = ctx->lVal(); + std::string varName = lval->Ident()->getText(); // 从语义分析获取变量定义 - auto* decl = sema_.ResolveVarUse(ctx->lVal()); + auto* decl = sema_.ResolveVarUse(lval); if (!decl) { throw std::runtime_error( FormatError("irgen", "变量使用缺少语义绑定: " + varName)); @@ -480,8 +526,33 @@ ir::Value* IRGenImpl::EvalAssign(SysYParser::StmtContext* ctx) { FormatError("irgen", "变量声明缺少存储槽位: " + varName)); } - // 生成store指令 - builder_.CreateStore(rhs, it->second); + ir::Value* base_ptr = it->second; + + // 检查是否有数组下标 + auto exp_list = lval->exp(); + if (!exp_list.empty()) { + // 这是数组元素赋值,需要生成GEP指令 + std::vector indices; + + // 第一个索引是0(假设一维数组) + indices.push_back(builder_.CreateConstInt(0)); + + // 添加用户提供的下标 + for (auto* exp : exp_list) { + ir::Value* index = EvalExpr(*exp); + indices.push_back(index); + } + + // 生成GEP指令获取元素地址 + ir::Value* elem_ptr = builder_.CreateGEP( + base_ptr, indices, module_.GetContext().NextTemp()); + + // 生成store指令 + builder_.CreateStore(rhs, elem_ptr); + } else { + // 普通标量赋值 + builder_.CreateStore(rhs, base_ptr); + } return rhs; -} \ No newline at end of file +}