|
|
#include "irgen/IRGen.h"
|
|
|
|
|
|
#include <stdexcept>
|
|
|
|
|
|
#include "SysYParser.h"
|
|
|
#include "ir/IR.h"
|
|
|
#include "utils/Log.h"
|
|
|
|
|
|
// 表达式生成当前也只实现了很小的一个子集。
|
|
|
// 目前支持:
|
|
|
// - 整数字面量
|
|
|
// - 普通局部变量读取
|
|
|
// - 括号表达式
|
|
|
// - 二元加法
|
|
|
//
|
|
|
// 还未支持:
|
|
|
// - 减乘除与一元运算
|
|
|
// - 赋值表达式
|
|
|
// - 函数调用
|
|
|
// - 数组、指针、下标访问
|
|
|
// - 条件与比较表达式
|
|
|
// - ...
|
|
|
|
|
|
// 表达式生成
|
|
|
ir::Value* IRGenImpl::EvalExpr(SysYParser::ExpContext& expr) {
|
|
|
std::cerr << "[DEBUG IRGEN] EvalExpr: 开始处理表达式 " << expr.getText() << std::endl;
|
|
|
try {
|
|
|
auto result_any = expr.accept(this);
|
|
|
|
|
|
if (!result_any.has_value()) {
|
|
|
std::cerr << "[ERROR] EvalExpr: result_any has no value" << std::endl;
|
|
|
throw std::runtime_error("表达式求值结果为空");
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
ir::Value* result = std::any_cast<ir::Value*>(result_any);
|
|
|
std::cerr << "[DEBUG] EvalExpr: success, result = " << (void*)result << std::endl;
|
|
|
return result;
|
|
|
} catch (const std::bad_any_cast& e) {
|
|
|
std::cerr << "[ERROR] EvalExpr: bad any_cast - " << e.what() << std::endl;
|
|
|
std::cerr << " Type info: " << result_any.type().name() << std::endl;
|
|
|
throw std::runtime_error(FormatError("irgen", "表达式求值返回了错误的类型"));
|
|
|
}
|
|
|
} catch (const std::exception& e) {
|
|
|
std::cerr << "[ERROR] Exception in EvalExpr: " << e.what() << std::endl;
|
|
|
throw;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
ir::Value* IRGenImpl::EvalCond(SysYParser::CondContext& cond) {
|
|
|
std::cerr << "[DEBUG IRGEN] EvalCond: 开始处理条件表达式 " << cond.getText() << std::endl;
|
|
|
return std::any_cast<ir::Value*>(cond.accept(this));
|
|
|
}
|
|
|
|
|
|
// 基本表达式:数字、变量、括号表达式
|
|
|
std::any IRGenImpl::visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) {
|
|
|
std::cerr << "[DEBUG IRGEN] visitPrimaryExp: 开始处理基本表达式 " << (ctx ? ctx->getText() : "<null>") << std::endl;
|
|
|
if (!ctx) {
|
|
|
throw std::runtime_error(FormatError("irgen", "缺少基本表达式"));
|
|
|
}
|
|
|
|
|
|
std::cerr << "[DEBUG] visitPrimaryExp" << std::endl;
|
|
|
|
|
|
// 处理数字字面量
|
|
|
if (ctx->DECIMAL_INT()) {
|
|
|
int value = std::stoi(ctx->DECIMAL_INT()->getText());
|
|
|
ir::Value* const_int = builder_.CreateConstInt(value);
|
|
|
std::cerr << "[DEBUG] visitPrimaryExp: constant int " << value
|
|
|
<< " created as " << (void*)const_int << std::endl;
|
|
|
return static_cast<ir::Value*>(const_int);
|
|
|
}
|
|
|
|
|
|
if (ctx->HEX_FLOAT()) {
|
|
|
std::string hex_float_str = ctx->HEX_FLOAT()->getText();
|
|
|
float value = 0.0f;
|
|
|
try {
|
|
|
value = std::stof(hex_float_str);
|
|
|
} catch (const std::exception& e) {
|
|
|
std::cerr << "[WARNING] 无法解析十六进制浮点数: " << hex_float_str
|
|
|
<< ",使用0.0代替" << std::endl;
|
|
|
value = 0.0f;
|
|
|
}
|
|
|
ir::Value* const_float = builder_.CreateConstFloat(value);
|
|
|
std::cerr << "[DEBUG] visitPrimaryExp: constant hex float " << value
|
|
|
<< " created as " << (void*)const_float << std::endl;
|
|
|
return static_cast<ir::Value*>(const_float);
|
|
|
}
|
|
|
|
|
|
if (ctx->DEC_FLOAT()) {
|
|
|
std::string dec_float_str = ctx->DEC_FLOAT()->getText();
|
|
|
float value = 0.0f;
|
|
|
try {
|
|
|
value = std::stof(dec_float_str);
|
|
|
} catch (const std::exception& e) {
|
|
|
std::cerr << "[WARNING] 无法解析十进制浮点数: " << dec_float_str
|
|
|
<< ",使用0.0代替" << std::endl;
|
|
|
value = 0.0f;
|
|
|
}
|
|
|
ir::Value* const_float = builder_.CreateConstFloat(value);
|
|
|
std::cerr << "[DEBUG] visitPrimaryExp: constant dec float " << value
|
|
|
<< " created as " << (void*)const_float << std::endl;
|
|
|
return static_cast<ir::Value*>(const_float);
|
|
|
}
|
|
|
|
|
|
if (ctx->HEX_INT()) {
|
|
|
std::string hex = ctx->HEX_INT()->getText();
|
|
|
int value = std::stoi(hex, nullptr, 16);
|
|
|
ir::Value* const_int = builder_.CreateConstInt(value);
|
|
|
std::cerr << "[DEBUG] visitPrimaryExp: constant hex int " << value
|
|
|
<< " created as " << (void*)const_int << std::endl;
|
|
|
return static_cast<ir::Value*>(const_int);
|
|
|
}
|
|
|
|
|
|
if (ctx->OCTAL_INT()) {
|
|
|
std::string oct = ctx->OCTAL_INT()->getText();
|
|
|
int value = std::stoi(oct, nullptr, 8);
|
|
|
ir::Value* const_int = builder_.CreateConstInt(value);
|
|
|
std::cerr << "[DEBUG] visitPrimaryExp: constant octal int " << value
|
|
|
<< " created as " << (void*)const_int << std::endl;
|
|
|
return static_cast<ir::Value*>(const_int);
|
|
|
}
|
|
|
|
|
|
if (ctx->ZERO()) {
|
|
|
ir::Value* const_int = builder_.CreateConstInt(0);
|
|
|
std::cerr << "[DEBUG] visitPrimaryExp: constant zero int created" << std::endl;
|
|
|
return static_cast<ir::Value*>(const_int);
|
|
|
}
|
|
|
|
|
|
// 处理变量
|
|
|
if (ctx->lVal()) {
|
|
|
std::cerr << "[DEBUG] visitPrimaryExp: visiting lVal" << std::endl;
|
|
|
return ctx->lVal()->accept(this);
|
|
|
}
|
|
|
|
|
|
// 处理括号表达式
|
|
|
if (ctx->L_PAREN() && ctx->exp()) {
|
|
|
std::cerr << "[DEBUG] visitPrimaryExp: visiting parenthesized expression" << std::endl;
|
|
|
return EvalExpr(*ctx->exp());
|
|
|
}
|
|
|
|
|
|
std::cerr << "[ERROR] visitPrimaryExp: unsupported primary expression type" << std::endl;
|
|
|
throw std::runtime_error(FormatError("irgen", "不支持的基本表达式类型"));
|
|
|
}
|
|
|
|
|
|
// 左值(变量)处理
|
|
|
std::any IRGenImpl::visitLVal(SysYParser::LValContext* ctx) {
|
|
|
std::cerr << "[DEBUG IRGEN] visitLVal: 开始处理左值 " << (ctx ? ctx->getText() : "<null>") << std::endl;
|
|
|
if (!ctx || !ctx->Ident()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法左值"));
|
|
|
}
|
|
|
|
|
|
std::string varName = ctx->Ident()->getText();
|
|
|
std::cerr << "[DEBUG] visitLVal: " << varName << std::endl;
|
|
|
|
|
|
// 先检查语义分析中常量绑定
|
|
|
const SysYParser::ConstDefContext* const_decl = sema_.ResolveConstUse(ctx);
|
|
|
const Symbol* sym = nullptr;
|
|
|
if (const_decl) {
|
|
|
sym = symbol_table_.lookupByConstDef(const_decl);
|
|
|
if (!sym) {
|
|
|
sym = symbol_table_.lookupAll(varName);
|
|
|
}
|
|
|
} else {
|
|
|
sym = symbol_table_.lookup(varName);
|
|
|
}
|
|
|
|
|
|
// 如果是常量,直接返回常量值
|
|
|
if (sym && sym->kind == SymbolKind::Constant) {
|
|
|
std::cerr << "[DEBUG] visitLVal: 找到常量 " << varName << std::endl;
|
|
|
|
|
|
if (sym->IsScalarConstant()) {
|
|
|
if (sym->type->IsInt32()) {
|
|
|
ir::ConstantValue* const_val = builder_.CreateConstInt(sym->GetIntConstant());
|
|
|
return static_cast<ir::Value*>(const_val);
|
|
|
} else if (sym->type->IsFloat()) {
|
|
|
ir::ConstantValue* const_val = builder_.CreateConstFloat(sym->GetFloatConstant());
|
|
|
return static_cast<ir::Value*>(const_val);
|
|
|
}
|
|
|
} else if (sym->IsArrayConstant()) {
|
|
|
auto it = const_global_map_.find(varName);
|
|
|
if (it != const_global_map_.end()) {
|
|
|
ir::GlobalValue* global_array = it->second;
|
|
|
|
|
|
// 尝试获取类型信息,用于维度判断与下标线性化
|
|
|
auto* array_ty = dynamic_cast<ir::ArrayType*>(sym->type.get());
|
|
|
if (!array_ty) {
|
|
|
// 无法获取数组类型,退回返回全局对象
|
|
|
return static_cast<ir::Value*>(global_array);
|
|
|
}
|
|
|
|
|
|
size_t ndims = array_ty->GetDimensions().size();
|
|
|
|
|
|
// 有下标访问
|
|
|
if (!ctx->exp().empty()) {
|
|
|
size_t provided = ctx->exp().size();
|
|
|
|
|
|
// 完全索引(所有维度都有下标)——直接返回常量元素,不生成 Load
|
|
|
if (provided == ndims) {
|
|
|
std::vector<int> idxs;
|
|
|
idxs.reserve(provided);
|
|
|
for (auto* exp : ctx->exp()) {
|
|
|
ir::Value* v = EvalExpr(*exp);
|
|
|
if (!v || !v->IsConstant()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "常量数组索引必须为常量整数: " + varName));
|
|
|
}
|
|
|
auto* ci = dynamic_cast<ir::ConstantInt*>(v);
|
|
|
if (!ci) {
|
|
|
throw std::runtime_error(FormatError("irgen", "常量数组索引非整型常量: " + varName));
|
|
|
}
|
|
|
idxs.push_back(ci->GetValue());
|
|
|
}
|
|
|
|
|
|
// 计算线性下标(行主序)
|
|
|
const auto& dims = array_ty->GetDimensions();
|
|
|
int flat = idxs[0];
|
|
|
for (size_t i = 1; i < ndims; ++i) {
|
|
|
flat = flat * dims[i] + idxs[i];
|
|
|
}
|
|
|
|
|
|
ir::ConstantValue* elem = global_array->GetArrayElement(static_cast<size_t>(flat));
|
|
|
return static_cast<ir::Value*>(elem);
|
|
|
}
|
|
|
|
|
|
// 部分索引:返回指针(不做 Load),由上层按需处理
|
|
|
std::vector<ir::Value*> indices;
|
|
|
indices.push_back(builder_.CreateConstInt(0));
|
|
|
for (auto* exp : ctx->exp()) {
|
|
|
indices.push_back(EvalExpr(*exp));
|
|
|
}
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateGEP(global_array, indices, module_.GetContext().NextTemp()));
|
|
|
} else {
|
|
|
// 无下标,直接返回全局常量对象
|
|
|
return static_cast<ir::Value*>(global_array);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 不是常量,按正常变量处理
|
|
|
auto* decl = sema_.ResolveVarUse(ctx);
|
|
|
ir::Value* ptr = nullptr;
|
|
|
|
|
|
if (decl) {
|
|
|
auto it = storage_map_.find(decl);
|
|
|
if (it != storage_map_.end()) {
|
|
|
ptr = it->second;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (!ptr) {
|
|
|
auto it2 = param_map_.find(varName);
|
|
|
if (it2 != param_map_.end()) {
|
|
|
ptr = it2->second;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (!ptr) {
|
|
|
auto it3 = global_map_.find(varName);
|
|
|
if (it3 != global_map_.end()) {
|
|
|
ptr = it3->second;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (!ptr) {
|
|
|
auto it4 = local_var_map_.find(varName);
|
|
|
if (it4 != local_var_map_.end()) {
|
|
|
ptr = it4->second;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (!ptr) {
|
|
|
throw std::runtime_error(
|
|
|
FormatError("irgen", "变量声明缺少存储槽位: " + varName));
|
|
|
}
|
|
|
|
|
|
// 检查是否有数组下标
|
|
|
bool is_array_access = !ctx->exp().empty();
|
|
|
if (is_array_access) {
|
|
|
// 收集下标表达式(不含前导0)
|
|
|
std::vector<ir::Value*> idx_vals;
|
|
|
for (auto* exp : ctx->exp()) {
|
|
|
ir::Value* index = EvalExpr(*exp);
|
|
|
idx_vals.push_back(index);
|
|
|
}
|
|
|
|
|
|
const Symbol* var_sym = sym;
|
|
|
if (!var_sym) {
|
|
|
var_sym = symbol_table_.lookup(varName);
|
|
|
}
|
|
|
if (!var_sym && decl) {
|
|
|
var_sym = symbol_table_.lookupByVarDef(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() && ptr->GetType()->IsArray()) {
|
|
|
if (auto* at = dynamic_cast<ir::ArrayType*>(ptr->GetType().get())) {
|
|
|
dims = at->GetDimensions();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 兜底:从语法树声明提取维度,避免作用域关闭后符号查询不完整。
|
|
|
if (dims.empty() && const_decl) {
|
|
|
auto* mutable_const_decl = const_cast<SysYParser::ConstDefContext*>(const_decl);
|
|
|
for (auto* cexp : mutable_const_decl->constExp()) {
|
|
|
dims.push_back(symbol_table_.EvaluateConstExp(cexp));
|
|
|
}
|
|
|
}
|
|
|
if (dims.empty() && decl) {
|
|
|
for (auto* cexp : decl->constExp()) {
|
|
|
dims.push_back(symbol_table_.EvaluateConstExp(cexp));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const bool is_partial_array_access =
|
|
|
!dims.empty() && idx_vals.size() < dims.size();
|
|
|
|
|
|
// 如果 base 是标量指针(例如局部扁平数组或数组参数),
|
|
|
// 需要把多维下标折合为单一线性下标,然后用一个索引进行 GEP。
|
|
|
if (ptr->GetType()->IsPtrInt32() || ptr->GetType()->IsPtrFloat()) {
|
|
|
// 如果没有维度信息,仍尝试用运行时算术合并下标(按后维乘积)
|
|
|
// flat = idx0 * (prod dims[1..]) + idx1 * (prod dims[2..]) + ...
|
|
|
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) {
|
|
|
// 数组参数首维可能是 0(表示省略),不参与乘数。
|
|
|
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);
|
|
|
|
|
|
// 使用单一索引创建 GEP
|
|
|
std::vector<ir::Value*> gep_indices = { flat };
|
|
|
ir::Value* elem_ptr = builder_.CreateGEP(ptr, gep_indices, module_.GetContext().NextTemp());
|
|
|
if (is_partial_array_access) {
|
|
|
return elem_ptr;
|
|
|
}
|
|
|
return static_cast<ir::Value*>(builder_.CreateLoad(elem_ptr, module_.GetContext().NextTemp()));
|
|
|
}
|
|
|
|
|
|
std::vector<ir::Value*> indices;
|
|
|
// 标量指针(T*)使用单索引;数组对象使用前导0进入首层。
|
|
|
if (ptr->GetType()->IsPtrInt32() || 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);
|
|
|
}
|
|
|
|
|
|
ir::Value* elem_ptr = builder_.CreateGEP(ptr, indices, module_.GetContext().NextTemp());
|
|
|
if (is_partial_array_access) {
|
|
|
return elem_ptr;
|
|
|
}
|
|
|
return static_cast<ir::Value*>(builder_.CreateLoad(elem_ptr, module_.GetContext().NextTemp()));
|
|
|
} else {
|
|
|
if ((sym && sym->is_array_param) ||
|
|
|
pointer_param_names_.find(varName) != pointer_param_names_.end() ||
|
|
|
heap_local_array_names_.find(varName) != heap_local_array_names_.end()) {
|
|
|
return ptr;
|
|
|
}
|
|
|
if (ptr->GetType()->IsArray()) {
|
|
|
return ptr;
|
|
|
}
|
|
|
return static_cast<ir::Value*>(builder_.CreateLoad(ptr, module_.GetContext().NextTemp()));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
std::any IRGenImpl::visitAddExp(SysYParser::AddExpContext* ctx) {
|
|
|
std::cerr << "[DEBUG IRGEN] visitAddExp: 开始处理加法表达式 " << (ctx ? ctx->getText() : "<null>") << std::endl;
|
|
|
if (!ctx) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法加法表达式"));
|
|
|
}
|
|
|
|
|
|
// 如果没有 addExp(),说明是单个 mulExp()
|
|
|
if (!ctx->addExp()) {
|
|
|
return ctx->mulExp()->accept(this);
|
|
|
}
|
|
|
|
|
|
// 正确提取左操作数
|
|
|
auto left_any = ctx->addExp()->accept(this);
|
|
|
if (!left_any.has_value()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "左操作数求值失败"));
|
|
|
}
|
|
|
ir::Value* left = std::any_cast<ir::Value*>(left_any);
|
|
|
|
|
|
// 正确提取右操作数
|
|
|
auto right_any = ctx->mulExp()->accept(this);
|
|
|
if (!right_any.has_value()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "右操作数求值失败"));
|
|
|
}
|
|
|
ir::Value* right = std::any_cast<ir::Value*>(right_any);
|
|
|
|
|
|
std::cerr << "[DEBUG] visitAddExp: left=" << (void*)left
|
|
|
<< ", type=" << (left->GetType()->IsFloat() ? "float" : "int")
|
|
|
<< ", right=" << (void*)right
|
|
|
<< ", type=" << (right->GetType()->IsFloat() ? "float" : "int") << std::endl;
|
|
|
|
|
|
// 处理类型转换:如果操作数类型不同,需要进行类型转换
|
|
|
if (left->GetType()->IsFloat() != right->GetType()->IsFloat()) {
|
|
|
if (left->GetType()->IsFloat()) {
|
|
|
// left是float,right是int,需要将right转换为float
|
|
|
right = builder_.CreateSIToFP(right, ir::Type::GetFloatType());
|
|
|
} else {
|
|
|
// right是float,left是int,需要将left转换为float
|
|
|
left = builder_.CreateSIToFP(left, ir::Type::GetFloatType());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 根据操作符生成相应的指令
|
|
|
if (ctx->AddOp()) {
|
|
|
if (left->GetType()->IsFloat()) {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateFAdd(left, right, module_.GetContext().NextTemp()));
|
|
|
} else {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateAdd(left, right, module_.GetContext().NextTemp()));
|
|
|
}
|
|
|
} else if (ctx->SubOp()) {
|
|
|
if (left->GetType()->IsFloat()) {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateFSub(left, right, module_.GetContext().NextTemp()));
|
|
|
} else {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateSub(left, right, module_.GetContext().NextTemp()));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "未知的加法操作符"));
|
|
|
}
|
|
|
|
|
|
|
|
|
std::any IRGenImpl::visitMulExp(SysYParser::MulExpContext* ctx) {
|
|
|
std::cerr << "[DEBUG IRGEN] visitMulExp: 开始处理乘法表达式 " << (ctx ? ctx->getText() : "<null>") << std::endl;
|
|
|
if (!ctx) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法乘法表达式"));
|
|
|
}
|
|
|
|
|
|
// 如果是基本形式 UnaryExp
|
|
|
if (!ctx->mulExp()) {
|
|
|
return ctx->unaryExp()->accept(this);
|
|
|
}
|
|
|
|
|
|
// 提取左操作数
|
|
|
auto left_any = ctx->mulExp()->accept(this);
|
|
|
if (!left_any.has_value()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "左操作数求值失败"));
|
|
|
}
|
|
|
ir::Value* left = std::any_cast<ir::Value*>(left_any);
|
|
|
|
|
|
// 提取右操作数
|
|
|
auto right_any = ctx->unaryExp()->accept(this);
|
|
|
if (!right_any.has_value()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "右操作数求值失败"));
|
|
|
}
|
|
|
ir::Value* right = std::any_cast<ir::Value*>(right_any);
|
|
|
|
|
|
std::cerr << "[DEBUG] visitMulExp: left=" << (void*)left
|
|
|
<< ", type=" << (left->GetType()->IsFloat() ? "float" : "int")
|
|
|
<< ", right=" << (void*)right
|
|
|
<< ", type=" << (right->GetType()->IsFloat() ? "float" : "int") << std::endl;
|
|
|
|
|
|
// 处理类型转换:如果操作数类型不同,需要进行类型转换
|
|
|
if (left->GetType()->IsFloat() != right->GetType()->IsFloat()) {
|
|
|
if (left->GetType()->IsFloat()) {
|
|
|
// left是float,right是int,需要将right转换为float
|
|
|
right = builder_.CreateSIToFP(right, ir::Type::GetFloatType());
|
|
|
} else {
|
|
|
// right是float,left是int,需要将left转换为float
|
|
|
left = builder_.CreateSIToFP(left, ir::Type::GetFloatType());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 根据操作符生成指令
|
|
|
if (ctx->MulOp()) {
|
|
|
if (left->GetType()->IsFloat()) {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateFMul(left, right, module_.GetContext().NextTemp()));
|
|
|
} else {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateMul(left, right, module_.GetContext().NextTemp()));
|
|
|
}
|
|
|
} else if (ctx->DivOp()) {
|
|
|
if (left->GetType()->IsFloat()) {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateFDiv(left, right, module_.GetContext().NextTemp()));
|
|
|
} else {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateDiv(left, right, module_.GetContext().NextTemp()));
|
|
|
}
|
|
|
} else if (ctx->QuoOp()) {
|
|
|
// 取模运算:浮点数不支持取模,只支持整数
|
|
|
if (left->GetType()->IsFloat() || right->GetType()->IsFloat()) {
|
|
|
throw std::runtime_error(
|
|
|
FormatError("irgen", "浮点数不支持取模运算"));
|
|
|
}
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateMod(left, right, module_.GetContext().NextTemp()));
|
|
|
}
|
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "未知的乘法操作符"));
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 逻辑与
|
|
|
std::any IRGenImpl::visitLAndExp(SysYParser::LAndExpContext* ctx) {
|
|
|
std::cerr << "[DEBUG IRGEN] visitLAndExp: 开始处理逻辑与表达式 " << (ctx ? ctx->getText() : "<null>") << std::endl;
|
|
|
if (!ctx) throw std::runtime_error(FormatError("irgen", "非法逻辑与表达式"));
|
|
|
|
|
|
if (!ctx->lAndExp()) {
|
|
|
return ctx->eqExp()->accept(this);
|
|
|
}
|
|
|
|
|
|
ir::Value* left = std::any_cast<ir::Value*>(ctx->lAndExp()->accept(this));
|
|
|
ir::Value* right = std::any_cast<ir::Value*>(ctx->eqExp()->accept(this));
|
|
|
|
|
|
auto to_bool = [&](ir::Value* v) -> ir::Value* {
|
|
|
if (v->GetType()->IsInt1()) {
|
|
|
return v;
|
|
|
}
|
|
|
if (v->GetType()->IsFloat()) {
|
|
|
return builder_.CreateFCmpONE(v, builder_.CreateConstFloat(0.0f),
|
|
|
module_.GetContext().NextTemp());
|
|
|
}
|
|
|
return builder_.CreateICmpNE(v, builder_.CreateConstInt(0),
|
|
|
module_.GetContext().NextTemp());
|
|
|
};
|
|
|
|
|
|
auto* left_bool = to_bool(left);
|
|
|
auto* right_bool = to_bool(right);
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateAnd(left_bool, right_bool, module_.GetContext().NextTemp()));
|
|
|
}
|
|
|
|
|
|
// 逻辑或
|
|
|
std::any IRGenImpl::visitLOrExp(SysYParser::LOrExpContext* ctx) {
|
|
|
std::cerr << "[DEBUG IRGEN] visitLOrExp: 开始处理逻辑或表达式 " << (ctx ? ctx->getText() : "<null>") << std::endl;
|
|
|
if (!ctx) throw std::runtime_error(FormatError("irgen", "非法逻辑或表达式"));
|
|
|
|
|
|
if (!ctx->lOrExp()) {
|
|
|
return ctx->lAndExp()->accept(this);
|
|
|
}
|
|
|
|
|
|
ir::Value* left = std::any_cast<ir::Value*>(ctx->lOrExp()->accept(this));
|
|
|
ir::Value* right = std::any_cast<ir::Value*>(ctx->lAndExp()->accept(this));
|
|
|
|
|
|
auto to_bool = [&](ir::Value* v) -> ir::Value* {
|
|
|
if (v->GetType()->IsInt1()) {
|
|
|
return v;
|
|
|
}
|
|
|
if (v->GetType()->IsFloat()) {
|
|
|
return builder_.CreateFCmpONE(v, builder_.CreateConstFloat(0.0f),
|
|
|
module_.GetContext().NextTemp());
|
|
|
}
|
|
|
return builder_.CreateICmpNE(v, builder_.CreateConstInt(0),
|
|
|
module_.GetContext().NextTemp());
|
|
|
};
|
|
|
|
|
|
auto* left_bool = to_bool(left);
|
|
|
auto* right_bool = to_bool(right);
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateOr(left_bool, right_bool, module_.GetContext().NextTemp()));
|
|
|
}
|
|
|
|
|
|
std::any IRGenImpl::visitExp(SysYParser::ExpContext* ctx) {
|
|
|
std::cerr << "[DEBUG IRGEN] visitExp: 开始处理表达式 " << (ctx ? ctx->getText() : "<null>") << std::endl;
|
|
|
if (!ctx) throw std::runtime_error(FormatError("irgen", "非法表达式"));
|
|
|
return ctx->addExp()->accept(this);
|
|
|
}
|
|
|
|
|
|
std::any IRGenImpl::visitCond(SysYParser::CondContext* ctx) {
|
|
|
std::cerr << "[DEBUG IRGEN] visitCond: 开始处理条件 " << (ctx ? ctx->getText() : "<null>") << std::endl;
|
|
|
if (!ctx) throw std::runtime_error(FormatError("irgen", "非法条件表达式"));
|
|
|
return ctx->lOrExp()->accept(this);
|
|
|
}
|
|
|
|
|
|
std::any IRGenImpl::visitCallExp(SysYParser::UnaryExpContext* ctx) {
|
|
|
std::cerr << "[DEBUG IRGEN] visitCallExp: 开始处理函数调用 " << (ctx ? ctx->getText() : "<null>") << std::endl;
|
|
|
if (!ctx || !ctx->Ident()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法函数调用"));
|
|
|
}
|
|
|
|
|
|
std::string funcName = ctx->Ident()->getText();
|
|
|
std::cout << "[DEBUG IRGEN] visitCallExp: 调用函数 " << funcName << std::endl;
|
|
|
|
|
|
// 查找函数对象
|
|
|
ir::Function* callee = module_.FindFunction(funcName);
|
|
|
|
|
|
// 如果没找到,可能是运行时函数还没声明,尝试动态声明
|
|
|
if (!callee) {
|
|
|
std::cout << "[DEBUG IRGEN] 函数 " << funcName << " 未找到,尝试动态声明" << std::endl;
|
|
|
|
|
|
// 根据函数名动态创建运行时函数声明
|
|
|
callee = CreateRuntimeFunctionDecl(funcName);
|
|
|
if (!callee) {
|
|
|
throw std::runtime_error(FormatError("irgen", "未找到函数: " + funcName));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 收集实参
|
|
|
std::vector<ir::Value*> args;
|
|
|
if (ctx->funcRParams()) {
|
|
|
auto argList = ctx->funcRParams()->accept(this);
|
|
|
try {
|
|
|
args = std::any_cast<std::vector<ir::Value*>>(argList);
|
|
|
std::cout << "[DEBUG IRGEN] visitCallExp: 收集到 " << args.size() << " 个参数" << std::endl;
|
|
|
} catch (const std::bad_any_cast& e) {
|
|
|
std::cerr << "[ERROR] visitCallExp: 函数调用参数类型错误: " << e.what() << std::endl;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 按形参类型修正实参(数组衰减为指针等)。
|
|
|
if (auto* fty = dynamic_cast<ir::FunctionType*>(callee->GetType().get())) {
|
|
|
const auto& param_tys = fty->GetParamTypes();
|
|
|
size_t n = std::min(param_tys.size(), args.size());
|
|
|
for (size_t i = 0; i < n; ++i) {
|
|
|
if (!args[i] || !param_tys[i]) continue;
|
|
|
|
|
|
// 数组实参传给指针形参时,执行数组到指针衰减。
|
|
|
if (args[i]->GetType()->IsArray() &&
|
|
|
(param_tys[i]->IsPtrInt32() || param_tys[i]->IsPtrFloat())) {
|
|
|
std::vector<ir::Value*> idx;
|
|
|
idx.push_back(builder_.CreateConstInt(0));
|
|
|
idx.push_back(builder_.CreateConstInt(0));
|
|
|
args[i] = builder_.CreateGEP(args[i], idx, module_.GetContext().NextTemp());
|
|
|
}
|
|
|
|
|
|
// 标量实参的隐式类型转换(int <-> float)。
|
|
|
if (param_tys[i]->IsFloat() && args[i]->GetType()->IsInt32()) {
|
|
|
args[i] = builder_.CreateSIToFP(args[i], ir::Type::GetFloatType(),
|
|
|
module_.GetContext().NextTemp());
|
|
|
} else if (param_tys[i]->IsInt32() && args[i]->GetType()->IsFloat()) {
|
|
|
args[i] = builder_.CreateFPToSI(args[i], ir::Type::GetInt32Type(),
|
|
|
module_.GetContext().NextTemp());
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 生成调用指令
|
|
|
ir::Value* callResult = builder_.CreateCall(callee, args, module_.GetContext().NextTemp());
|
|
|
|
|
|
// 如果函数返回 void,返回一个默认值(用于表达式上下文)
|
|
|
if (callResult->GetType()->IsVoid()) {
|
|
|
// void 函数调用不产生值,但我们返回一个 0 常量以保持类型一致性
|
|
|
return static_cast<ir::Value*>(builder_.CreateConstInt(0));
|
|
|
}
|
|
|
|
|
|
std::cout << "[DEBUG IRGEN] visitCallExp: 函数调用完成,返回值 " << (void*)callResult << std::endl;
|
|
|
return static_cast<ir::Value*>(callResult);
|
|
|
}
|
|
|
|
|
|
// 动态创建运行时函数声明的辅助函数
|
|
|
ir::Function* IRGenImpl::CreateRuntimeFunctionDecl(const std::string& funcName) {
|
|
|
std::cerr << "[DEBUG IRGEN] CreateRuntimeFunctionDecl: 开始创建运行时函数声明 " << funcName << std::endl;
|
|
|
|
|
|
// 根据常见运行时函数名创建对应的函数类型
|
|
|
if (funcName == "getint" || funcName == "getch") {
|
|
|
return module_.CreateFunction(funcName,
|
|
|
ir::Type::GetFunctionType(ir::Type::GetInt32Type(), {}));
|
|
|
}
|
|
|
else if (funcName == "putint" || funcName == "putch") {
|
|
|
return module_.CreateFunction(funcName,
|
|
|
ir::Type::GetFunctionType(
|
|
|
ir::Type::GetVoidType(),
|
|
|
{ir::Type::GetInt32Type()}));
|
|
|
}
|
|
|
else if (funcName == "getarray") {
|
|
|
return module_.CreateFunction(funcName,
|
|
|
ir::Type::GetFunctionType(
|
|
|
ir::Type::GetInt32Type(),
|
|
|
{ir::Type::GetPtrInt32Type()}));
|
|
|
}
|
|
|
else if (funcName == "putarray") {
|
|
|
return module_.CreateFunction(funcName,
|
|
|
ir::Type::GetFunctionType(
|
|
|
ir::Type::GetVoidType(),
|
|
|
{ir::Type::GetInt32Type(), ir::Type::GetPtrInt32Type()}));
|
|
|
}
|
|
|
else if (funcName == "puts") {
|
|
|
return module_.CreateFunction(funcName,
|
|
|
ir::Type::GetFunctionType(
|
|
|
ir::Type::GetVoidType(),
|
|
|
{ir::Type::GetPtrInt32Type()}));
|
|
|
}
|
|
|
else if (funcName == "starttime" || funcName == "stoptime") {
|
|
|
return module_.CreateFunction(funcName,
|
|
|
ir::Type::GetFunctionType(ir::Type::GetVoidType(), {}));
|
|
|
}
|
|
|
else if (funcName == "_sysy_starttime" || funcName == "_sysy_stoptime") {
|
|
|
return module_.CreateFunction(funcName,
|
|
|
ir::Type::GetFunctionType(
|
|
|
ir::Type::GetVoidType(),
|
|
|
{ir::Type::GetInt32Type()}));
|
|
|
}
|
|
|
else if (funcName == "getfloat") {
|
|
|
return module_.CreateFunction(funcName,
|
|
|
ir::Type::GetFunctionType(ir::Type::GetFloatType(), {}));
|
|
|
}
|
|
|
else if (funcName == "putfloat") {
|
|
|
return module_.CreateFunction(funcName,
|
|
|
ir::Type::GetFunctionType(
|
|
|
ir::Type::GetVoidType(),
|
|
|
{ir::Type::GetFloatType()}));
|
|
|
}
|
|
|
else if (funcName == "getfarray") {
|
|
|
return module_.CreateFunction(funcName,
|
|
|
ir::Type::GetFunctionType(
|
|
|
ir::Type::GetInt32Type(),
|
|
|
{ir::Type::GetPtrFloatType()}));
|
|
|
}
|
|
|
else if (funcName == "putfarray") {
|
|
|
return module_.CreateFunction(funcName,
|
|
|
ir::Type::GetFunctionType(
|
|
|
ir::Type::GetVoidType(),
|
|
|
{ir::Type::GetInt32Type(), ir::Type::GetPtrFloatType()}));
|
|
|
}
|
|
|
else if (funcName == "memset") {
|
|
|
return module_.CreateFunction(funcName,
|
|
|
ir::Type::GetFunctionType(
|
|
|
ir::Type::GetPtrInt32Type(),
|
|
|
{ir::Type::GetPtrInt32Type(),
|
|
|
ir::Type::GetInt32Type(),
|
|
|
ir::Type::GetInt32Type()}));
|
|
|
}
|
|
|
else if (funcName == "sysy_alloc_i32") {
|
|
|
return module_.CreateFunction(funcName,
|
|
|
ir::Type::GetFunctionType(
|
|
|
ir::Type::GetPtrInt32Type(),
|
|
|
{ir::Type::GetInt32Type()}));
|
|
|
}
|
|
|
else if (funcName == "sysy_alloc_f32") {
|
|
|
return module_.CreateFunction(funcName,
|
|
|
ir::Type::GetFunctionType(
|
|
|
ir::Type::GetPtrFloatType(),
|
|
|
{ir::Type::GetInt32Type()}));
|
|
|
}
|
|
|
else if (funcName == "sysy_free_i32") {
|
|
|
return module_.CreateFunction(funcName,
|
|
|
ir::Type::GetFunctionType(
|
|
|
ir::Type::GetVoidType(),
|
|
|
{ir::Type::GetPtrInt32Type()}));
|
|
|
}
|
|
|
else if (funcName == "sysy_free_f32") {
|
|
|
return module_.CreateFunction(funcName,
|
|
|
ir::Type::GetFunctionType(
|
|
|
ir::Type::GetVoidType(),
|
|
|
{ir::Type::GetPtrFloatType()}));
|
|
|
}
|
|
|
else if (funcName == "sysy_zero_i32") {
|
|
|
return module_.CreateFunction(funcName,
|
|
|
ir::Type::GetFunctionType(
|
|
|
ir::Type::GetVoidType(),
|
|
|
{ir::Type::GetPtrInt32Type(), ir::Type::GetInt32Type()}));
|
|
|
}
|
|
|
else if (funcName == "sysy_zero_f32") {
|
|
|
return module_.CreateFunction(funcName,
|
|
|
ir::Type::GetFunctionType(
|
|
|
ir::Type::GetVoidType(),
|
|
|
{ir::Type::GetPtrFloatType(), ir::Type::GetInt32Type()}));
|
|
|
}
|
|
|
|
|
|
// 其他函数不支持动态创建
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
std::any IRGenImpl::visitUnaryExp(SysYParser::UnaryExpContext* ctx) {
|
|
|
std::cerr << "[DEBUG IRGEN] visitUnaryExp: 开始处理一元表达式 " << (ctx ? ctx->getText() : "<null>") << std::endl;
|
|
|
if (!ctx) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法一元表达式"));
|
|
|
}
|
|
|
|
|
|
// 基本表达式
|
|
|
if (ctx->primaryExp()) {
|
|
|
return ctx->primaryExp()->accept(this);
|
|
|
}
|
|
|
|
|
|
// 函数调用
|
|
|
if (ctx->Ident()) {
|
|
|
return visitCallExp(ctx);
|
|
|
}
|
|
|
|
|
|
// 一元运算
|
|
|
if (ctx->unaryOp() && ctx->unaryExp()) {
|
|
|
auto* operand = std::any_cast<ir::Value*>(ctx->unaryExp()->accept(this));
|
|
|
std::string op = ctx->unaryOp()->getText();
|
|
|
|
|
|
if (op == "+") {
|
|
|
// +x 等价于 x
|
|
|
return operand;
|
|
|
} else if (op == "-") {
|
|
|
// -x 根据操作数类型选择整数或浮点减法
|
|
|
if (operand->GetType()->IsFloat()) {
|
|
|
// 浮点取负:0.0 - x
|
|
|
ir::Value* zero_float = builder_.CreateConstFloat(0.0f);
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateFSub(zero_float, operand, module_.GetContext().NextTemp()));
|
|
|
} else {
|
|
|
// 整数取负:0 - x
|
|
|
ir::Value* zero = builder_.CreateConstInt(0);
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateSub(zero, operand, module_.GetContext().NextTemp()));
|
|
|
}
|
|
|
} else if (op == "!") {
|
|
|
// 逻辑非运算
|
|
|
// 先将值转换为bool(与0比较)
|
|
|
ir::Value* zero;
|
|
|
if (operand->GetType()->IsFloat()) {
|
|
|
zero = builder_.CreateConstFloat(0.0f);
|
|
|
// 浮点逻辑非:x == 0.0
|
|
|
ir::Value* cmp = builder_.CreateFCmpOEQ(operand, zero, module_.GetContext().NextTemp());
|
|
|
// 将bool转换为int
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateZExt(cmp, ir::Type::GetInt32Type()));
|
|
|
} else {
|
|
|
zero = builder_.CreateConstInt(0);
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateNot(operand, module_.GetContext().NextTemp()));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "暂不支持的一元表达式形式"));
|
|
|
}
|
|
|
|
|
|
// 实现函数调用
|
|
|
std::any IRGenImpl::visitFuncRParams(SysYParser::FuncRParamsContext* ctx) {
|
|
|
std::cerr << "[DEBUG IRGEN] visitFuncRParams: 开始处理函数参数 " << (ctx ? ctx->getText() : "<null>") << std::endl;
|
|
|
if (!ctx) return std::vector<ir::Value*>{};
|
|
|
std::vector<ir::Value*> args;
|
|
|
for (auto* exp : ctx->exp()) {
|
|
|
args.push_back(EvalExpr(*exp));
|
|
|
}
|
|
|
return args;
|
|
|
}
|
|
|
|
|
|
// visitConstExp - 处理常量表达式
|
|
|
std::any IRGenImpl::visitConstExp(SysYParser::ConstExpContext* ctx) {
|
|
|
std::cerr << "[DEBUG IRGEN] visitConstExp: 开始处理常量表达式 " << (ctx ? ctx->getText() : "<null>") << std::endl;
|
|
|
if (!ctx || !ctx->addExp()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法常量表达式"));
|
|
|
}
|
|
|
|
|
|
auto result = ctx->addExp()->accept(this);
|
|
|
|
|
|
if (!result.has_value()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "常量表达式求值失败"));
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
return std::any_cast<ir::Value*>(result);
|
|
|
} catch (const std::bad_any_cast& e) {
|
|
|
throw std::runtime_error(FormatError("irgen",
|
|
|
"常量表达式返回类型错误: " + std::string(e.what())));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// visitConstInitVal - 处理常量初始化值
|
|
|
std::any IRGenImpl::visitConstInitVal(SysYParser::ConstInitValContext* ctx) {
|
|
|
std::cerr << "[DEBUG IRGEN] visitConstInitVal: 开始处理常量初始化值 " << (ctx ? ctx->getText() : "<null>") << std::endl;
|
|
|
if (!ctx) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法常量初始化值"));
|
|
|
}
|
|
|
|
|
|
// 如果是单个常量表达式
|
|
|
if (ctx->constExp()) {
|
|
|
return ctx->constExp()->accept(this);
|
|
|
}
|
|
|
// 如果是聚合初始化(花括号列表)
|
|
|
else if (!ctx->constInitVal().empty()) {
|
|
|
std::vector<ir::Value*> all_values;
|
|
|
|
|
|
for (auto* init_val : ctx->constInitVal()) {
|
|
|
auto result = init_val->accept(this);
|
|
|
if (!result.has_value()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "常量初始化值求值失败"));
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
// 尝试获取单个常量值
|
|
|
ir::Value* value = std::any_cast<ir::Value*>(result);
|
|
|
all_values.push_back(value);
|
|
|
} catch (const std::bad_any_cast&) {
|
|
|
try {
|
|
|
// 尝试获取值列表(嵌套情况)
|
|
|
std::vector<ir::Value*> nested_values =
|
|
|
std::any_cast<std::vector<ir::Value*>>(result);
|
|
|
all_values.insert(all_values.end(),
|
|
|
nested_values.begin(), nested_values.end());
|
|
|
} catch (const std::bad_any_cast& e) {
|
|
|
throw std::runtime_error(FormatError("irgen",
|
|
|
"不支持的常量初始化值类型: " + std::string(e.what())));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return all_values;
|
|
|
}
|
|
|
|
|
|
// 空初始化列表
|
|
|
return std::vector<ir::Value*>{};
|
|
|
}
|
|
|
|
|
|
std::any IRGenImpl::visitRelExp(SysYParser::RelExpContext* ctx) {
|
|
|
std::cerr << "[DEBUG IRGEN] visitRelExp: 开始处理关系表达式 " << (ctx ? ctx->getText() : "<null>") << std::endl;
|
|
|
if (!ctx) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法关系表达式"));
|
|
|
}
|
|
|
|
|
|
if (ctx->relExp() && ctx->addExp()) {
|
|
|
auto left_any = ctx->relExp()->accept(this);
|
|
|
auto right_any = ctx->addExp()->accept(this);
|
|
|
auto* lhs = std::any_cast<ir::Value*>(left_any);
|
|
|
auto* rhs = std::any_cast<ir::Value*>(right_any);
|
|
|
|
|
|
std::cerr << "[DEBUG] visitRelExp: left=" << (void*)lhs
|
|
|
<< ", type=" << (lhs->GetType()->IsFloat() ? "float" : "int")
|
|
|
<< ", right=" << (void*)rhs
|
|
|
<< ", type=" << (rhs->GetType()->IsFloat() ? "float" : "int") << std::endl;
|
|
|
|
|
|
// 处理类型转换:如果操作数类型不同,需要进行类型转换
|
|
|
if (lhs->GetType()->IsFloat() != rhs->GetType()->IsFloat()) {
|
|
|
if (lhs->GetType()->IsFloat()) {
|
|
|
// lhs是float,rhs是int,需要将rhs转换为float
|
|
|
rhs = builder_.CreateSIToFP(rhs, ir::Type::GetFloatType());
|
|
|
} else {
|
|
|
// rhs是float,lhs是int,需要将lhs转换为float
|
|
|
lhs = builder_.CreateSIToFP(lhs, ir::Type::GetFloatType());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 根据操作数和类型选择指令
|
|
|
if (ctx->LOp()) {
|
|
|
if (lhs->GetType()->IsFloat()) {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateFCmpOLT(lhs, rhs, module_.GetContext().NextTemp()));
|
|
|
} else {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateICmpLT(lhs, rhs, module_.GetContext().NextTemp()));
|
|
|
}
|
|
|
}
|
|
|
if (ctx->GOp()) {
|
|
|
if (lhs->GetType()->IsFloat()) {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateFCmpOGT(lhs, rhs, module_.GetContext().NextTemp()));
|
|
|
} else {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateICmpGT(lhs, rhs, module_.GetContext().NextTemp()));
|
|
|
}
|
|
|
}
|
|
|
if (ctx->LeOp()) {
|
|
|
if (lhs->GetType()->IsFloat()) {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateFCmpOLE(lhs, rhs, module_.GetContext().NextTemp()));
|
|
|
} else {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateICmpLE(lhs, rhs, module_.GetContext().NextTemp()));
|
|
|
}
|
|
|
}
|
|
|
if (ctx->GeOp()) {
|
|
|
if (lhs->GetType()->IsFloat()) {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateFCmpOGE(lhs, rhs, module_.GetContext().NextTemp()));
|
|
|
} else {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateICmpGE(lhs, rhs, module_.GetContext().NextTemp()));
|
|
|
}
|
|
|
}
|
|
|
throw std::runtime_error(FormatError("irgen", "未知关系运算符"));
|
|
|
}
|
|
|
|
|
|
if (ctx->addExp()) {
|
|
|
return ctx->addExp()->accept(this);
|
|
|
}
|
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "关系表达式暂未实现"));
|
|
|
}
|
|
|
|
|
|
std::any IRGenImpl::visitEqExp(SysYParser::EqExpContext* ctx) {
|
|
|
std::cerr << "[DEBUG IRGEN] visitEqExp: 开始处理相等表达式 " << (ctx ? ctx->getText() : "<null>") << std::endl;
|
|
|
if (!ctx) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法相等表达式"));
|
|
|
}
|
|
|
|
|
|
if (ctx->eqExp() && ctx->relExp()) {
|
|
|
auto left_any = ctx->eqExp()->accept(this);
|
|
|
auto right_any = ctx->relExp()->accept(this);
|
|
|
auto* lhs = std::any_cast<ir::Value*>(left_any);
|
|
|
auto* rhs = std::any_cast<ir::Value*>(right_any);
|
|
|
|
|
|
std::cerr << "[DEBUG] visitEqExp: left=" << (void*)lhs
|
|
|
<< ", type=" << (lhs->GetType()->IsFloat() ? "float" : "int")
|
|
|
<< ", right=" << (void*)rhs
|
|
|
<< ", type=" << (rhs->GetType()->IsFloat() ? "float" : "int") << std::endl;
|
|
|
|
|
|
// 处理类型转换:如果操作数类型不同,需要进行类型转换
|
|
|
if (lhs->GetType()->IsFloat() != rhs->GetType()->IsFloat()) {
|
|
|
if (lhs->GetType()->IsFloat()) {
|
|
|
// lhs是float,rhs是int,需要将rhs转换为float
|
|
|
rhs = builder_.CreateSIToFP(rhs, ir::Type::GetFloatType());
|
|
|
} else {
|
|
|
// rhs是float,lhs是int,需要将lhs转换为float
|
|
|
lhs = builder_.CreateSIToFP(lhs, ir::Type::GetFloatType());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 根据操作符和类型选择指令
|
|
|
if (ctx->EqOp()) {
|
|
|
if (lhs->GetType()->IsFloat()) {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateFCmpOEQ(lhs, rhs, module_.GetContext().NextTemp()));
|
|
|
} else {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateICmpEQ(lhs, rhs, module_.GetContext().NextTemp()));
|
|
|
}
|
|
|
}
|
|
|
if (ctx->NeOp()) {
|
|
|
if (lhs->GetType()->IsFloat()) {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateFCmpONE(lhs, rhs, module_.GetContext().NextTemp()));
|
|
|
} else {
|
|
|
return static_cast<ir::Value*>(
|
|
|
builder_.CreateICmpNE(lhs, rhs, module_.GetContext().NextTemp()));
|
|
|
}
|
|
|
}
|
|
|
throw std::runtime_error(FormatError("irgen", "未知相等运算符"));
|
|
|
}
|
|
|
|
|
|
if (ctx->relExp()) {
|
|
|
return ctx->relExp()->accept(this);
|
|
|
}
|
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "相等表达式暂未实现"));
|
|
|
}
|
|
|
|
|
|
|
|
|
ir::Value* IRGenImpl::EvalAssign(SysYParser::StmtContext* ctx) {
|
|
|
std::cerr << "[DEBUG IRGEN] EvalAssign: 开始处理赋值语句 " << (ctx ? ctx->getText() : "<null>") << std::endl;
|
|
|
std::cout << "[DEBUG IRGEN] visitCond: " << (ctx ? ctx->getText() : "<null>") << std::endl;
|
|
|
if (!ctx || !ctx->lVal() || !ctx->exp()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法赋值语句"));
|
|
|
}
|
|
|
|
|
|
// 计算右值
|
|
|
ir::Value* rhs = EvalExpr(*ctx->exp());
|
|
|
|
|
|
auto* lval = ctx->lVal();
|
|
|
std::string varName = lval->Ident()->getText();
|
|
|
|
|
|
// 首先尝试从语义分析获取变量定义
|
|
|
auto* var_decl = sema_.ResolveVarUse(lval);
|
|
|
|
|
|
if (var_decl) {
|
|
|
// 是变量赋值
|
|
|
// 从storage_map_获取存储位置
|
|
|
auto it = storage_map_.find(var_decl);
|
|
|
if (it == storage_map_.end()) {
|
|
|
throw std::runtime_error(
|
|
|
FormatError("irgen", "变量声明缺少存储槽位: " + varName));
|
|
|
}
|
|
|
|
|
|
ir::Value* base_ptr = it->second;
|
|
|
|
|
|
auto convert_for_store = [&](ir::Value* value, ir::Value* ptr) -> ir::Value* {
|
|
|
if (ptr->GetType()->IsPtrFloat() && value->GetType()->IsInt32()) {
|
|
|
return builder_.CreateSIToFP(value, ir::Type::GetFloatType(),
|
|
|
module_.GetContext().NextTemp());
|
|
|
}
|
|
|
if (ptr->GetType()->IsPtrInt32() && value->GetType()->IsFloat()) {
|
|
|
return builder_.CreateFPToSI(value, ir::Type::GetInt32Type(),
|
|
|
module_.GetContext().NextTemp());
|
|
|
}
|
|
|
return value;
|
|
|
};
|
|
|
|
|
|
// 检查是否有数组下标
|
|
|
auto exp_list = lval->exp();
|
|
|
if (!exp_list.empty()) {
|
|
|
// 这是数组元素赋值,需要生成GEP指令
|
|
|
std::vector<ir::Value*> indices;
|
|
|
|
|
|
// 标量指针参数(T*)不应添加前导0;数组对象需要前导0。
|
|
|
if (!(base_ptr->GetType()->IsPtrInt32() || base_ptr->GetType()->IsPtrFloat())) {
|
|
|
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指令
|
|
|
rhs = convert_for_store(rhs, elem_ptr);
|
|
|
builder_.CreateStore(rhs, elem_ptr);
|
|
|
} else {
|
|
|
// 普通标量赋值
|
|
|
// 调试输出指针类型
|
|
|
std::cerr << "[DEBUG] base_ptr type: " << base_ptr->GetType() << std::endl;
|
|
|
std::cerr << "[DEBUG] rhs type: " << rhs->GetType()<< std::endl;
|
|
|
|
|
|
// 如果 base_ptr 不是标量指针类型,可能需要特殊处理
|
|
|
if (!base_ptr->GetType()->IsPtrInt32() && !base_ptr->GetType()->IsPtrFloat()) {
|
|
|
std::cerr << "[ERROR] base_ptr is not a pointer type!" << std::endl;
|
|
|
throw std::runtime_error("尝试存储到非指针类型");
|
|
|
}
|
|
|
rhs = convert_for_store(rhs, base_ptr);
|
|
|
builder_.CreateStore(rhs, base_ptr);
|
|
|
}
|
|
|
} else {
|
|
|
// 尝试获取常量定义
|
|
|
auto* const_decl = sema_.ResolveConstUse(lval);
|
|
|
if (const_decl) {
|
|
|
// 尝试给常量赋值,这是错误的
|
|
|
throw std::runtime_error(
|
|
|
FormatError("irgen", "不能给常量赋值: " + varName));
|
|
|
} else {
|
|
|
throw std::runtime_error(
|
|
|
FormatError("irgen", "变量/常量使用缺少语义绑定: " + varName));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return rhs;
|
|
|
}
|