|
|
|
|
@ -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, operand(LLVM 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;
|
|
|
|
|
|