数组未实现

feature/sem
potapo 2 weeks ago
parent 9c7095bba7
commit 5e7e8a6ff2

@ -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<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::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<Type> 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<BinaryInst>(op, result_type, lhs, rhs, name);
}
BinaryInst* IRBuilder::CreateAdd(Value* lhs, Value* rhs,

@ -61,22 +61,73 @@ 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"));
// 检查操作码是否为有效的二元操作符
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);
}

@ -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<ir::Value*>(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<ir::Value*> initValues;
for (auto* initVal : ctx->initVal()) {
// 递归处理每个初始化值
auto result = initVal->accept(this);
if (result.has_value()) {
try {
ir::Value* value = std::any_cast<ir::Value*>(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", "不支持的初始化值形式"));
}

@ -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<ir::Value*>(load_result);
// 检查是否有数组下标(是否是数组访问)
auto exp_list = ctx->exp();
if (!exp_list.empty()) {
// 这是数组访问需要生成GEP指令
std::vector<ir::Value*> 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<ir::Value*>(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<ir::Value*>(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<ir::Value*>(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<ir::Value*>(
builder_.CreateICmpSLT(left, right, module_.GetContext().NextTemp()));
} else if (op == ">" || op == "Gt") {
return static_cast<ir::Value*>(
builder_.CreateICmpSGT(left, right, module_.GetContext().NextTemp()));
} else if (op == "<=" || op == "Le") {
return static_cast<ir::Value*>(
builder_.CreateICmpSLE(left, right, module_.GetContext().NextTemp()));
} else if (op == ">=" || op == "Ge") {
return static_cast<ir::Value*>(
builder_.CreateICmpSGE(left, right, module_.GetContext().NextTemp()));
}
}
if (op == "<") {
// 方法2检查是否有特定的操作符方法
// 根据错误信息可能是LOp和GOp
if (ctx->LOp()) { // "<"
return static_cast<ir::Value*>(
builder_.CreateICmpSLT(left, right, module_.GetContext().NextTemp()));
} else if (op == ">") {
} else if (ctx->GOp()) { // ">"
return static_cast<ir::Value*>(
builder_.CreateICmpSGT(left, right, module_.GetContext().NextTemp()));
} else if (op == "<=") {
}
// 方法3检查Le和Ge
if (ctx->LeOp()) { // "<="
return static_cast<ir::Value*>(
builder_.CreateICmpSLE(left, right, module_.GetContext().NextTemp()));
} else if (op == ">=") {
} else if (ctx->GeOp()) { // ">="
return static_cast<ir::Value*>(
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<ir::Value*> 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;
}
}

Loading…
Cancel
Save