|
|
#include "irgen/IRGen.h"
|
|
|
|
|
|
#include <cmath>
|
|
|
#include <limits>
|
|
|
#include <stdexcept>
|
|
|
|
|
|
#include "SysYParser.h"
|
|
|
#include "ir/IR.h"
|
|
|
#include "utils/Log.h"
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
int ParseIntLiteral(const std::string& text) {
|
|
|
size_t parsed = 0;
|
|
|
long long value = std::stoll(text, &parsed, 0);
|
|
|
if (parsed != text.size()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法整数字面量: " + text));
|
|
|
}
|
|
|
if (value < std::numeric_limits<int>::min() ||
|
|
|
value > std::numeric_limits<int>::max()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "整数字面量越界: " + text));
|
|
|
}
|
|
|
return static_cast<int>(value);
|
|
|
}
|
|
|
|
|
|
double ParseFloatLiteral(const std::string& text) {
|
|
|
if (text.find("0x") == 0 || text.find("0X") == 0) {
|
|
|
// 手动解析十六进制浮点数常量
|
|
|
// 格式: 0x[hex_digits][.[hex_digits]][p|P[+|-][decimal_digits]]
|
|
|
std::string hex_part;
|
|
|
std::string exp_part;
|
|
|
size_t p_pos = text.find_first_of("pP");
|
|
|
|
|
|
if (p_pos != std::string::npos) {
|
|
|
hex_part = text.substr(0, p_pos);
|
|
|
exp_part = text.substr(p_pos + 1);
|
|
|
} else {
|
|
|
hex_part = text;
|
|
|
exp_part = "0";
|
|
|
}
|
|
|
|
|
|
// 解析十六进制部分
|
|
|
double mantissa = 0.0;
|
|
|
double frac = 0.0;
|
|
|
double frac_divisor = 1.0;
|
|
|
bool in_frac = false;
|
|
|
|
|
|
for (size_t i = 2; i < hex_part.size(); i++) {
|
|
|
char c = hex_part[i];
|
|
|
if (c == '.') {
|
|
|
in_frac = true;
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
int digit;
|
|
|
if (c >= '0' && c <= '9') {
|
|
|
digit = c - '0';
|
|
|
} else if (c >= 'a' && c <= 'f') {
|
|
|
digit = 10 + (c - 'a');
|
|
|
} else if (c >= 'A' && c <= 'F') {
|
|
|
digit = 10 + (c - 'A');
|
|
|
} else {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法浮点字面量: " + text));
|
|
|
}
|
|
|
|
|
|
if (in_frac) {
|
|
|
frac_divisor *= 16.0;
|
|
|
frac += digit / frac_divisor;
|
|
|
} else {
|
|
|
mantissa = mantissa * 16.0 + digit;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
mantissa += frac;
|
|
|
|
|
|
// 解析指数部分
|
|
|
int exponent = 0;
|
|
|
if (!exp_part.empty()) {
|
|
|
try {
|
|
|
exponent = std::stoi(exp_part);
|
|
|
} catch (...) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法浮点字面量: " + text));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return mantissa * std::pow(2.0, exponent);
|
|
|
} else {
|
|
|
// 解析十进制浮点数常量
|
|
|
char* end = nullptr;
|
|
|
double value = std::strtod(text.c_str(), &end);
|
|
|
if (end == text.c_str()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法浮点字面量: " + text));
|
|
|
}
|
|
|
if (static_cast<size_t>(end - text.c_str()) != text.size()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法浮点字面量: " + text));
|
|
|
}
|
|
|
return value;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void CollectInitExprs(SysYParser::InitValContext* init,
|
|
|
std::vector<SysYParser::ExpContext*>& out,
|
|
|
const std::vector<int>& dims,
|
|
|
size_t dim_idx = 0) {
|
|
|
if (!init) {
|
|
|
return;
|
|
|
}
|
|
|
if (init->exp()) {
|
|
|
out.push_back(init->exp());
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 计算当前维度的大小
|
|
|
size_t current_dim_size = 1;
|
|
|
for (size_t i = dim_idx; i < dims.size(); ++i) {
|
|
|
current_dim_size *= dims[i];
|
|
|
}
|
|
|
|
|
|
size_t start_pos = out.size();
|
|
|
auto nested_inits = init->initVal();
|
|
|
|
|
|
if (dims.empty()) {
|
|
|
// 标量,直接处理
|
|
|
for (auto* nested : nested_inits) {
|
|
|
CollectInitExprs(nested, out, dims, dim_idx);
|
|
|
}
|
|
|
} else if (dim_idx < dims.size() - 1) {
|
|
|
// 多维数组,递归处理每个子数组
|
|
|
size_t sub_dim_size = 1;
|
|
|
for (size_t i = dim_idx + 1; i < dims.size(); ++i) {
|
|
|
sub_dim_size *= dims[i];
|
|
|
}
|
|
|
|
|
|
for (auto* nested : nested_inits) {
|
|
|
if (out.size() >= start_pos + current_dim_size) {
|
|
|
break;
|
|
|
}
|
|
|
CollectInitExprs(nested, out, dims, dim_idx + 1);
|
|
|
}
|
|
|
} else {
|
|
|
// 一维数组,直接展平所有初始化表达式
|
|
|
for (auto* nested : nested_inits) {
|
|
|
if (out.size() >= start_pos + current_dim_size) {
|
|
|
break;
|
|
|
}
|
|
|
CollectInitExprs(nested, out, dims, dim_idx);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 确保不超过当前维度的大小
|
|
|
if (out.size() > start_pos + current_dim_size) {
|
|
|
// 截断超出的部分
|
|
|
out.resize(start_pos + current_dim_size);
|
|
|
}
|
|
|
|
|
|
// 补齐到当前维度大小
|
|
|
while (out.size() < start_pos + current_dim_size) {
|
|
|
out.push_back(nullptr);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void CollectConstInitExprs(SysYParser::ConstInitValContext* init,
|
|
|
std::vector<SysYParser::ConstExpContext*>& out,
|
|
|
const std::vector<int>& dims,
|
|
|
size_t dim_idx = 0) {
|
|
|
if (!init) {
|
|
|
return;
|
|
|
}
|
|
|
if (init->constExp()) {
|
|
|
out.push_back(init->constExp());
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 计算当前维度的大小
|
|
|
size_t current_dim_size = 1;
|
|
|
for (size_t i = dim_idx; i < dims.size(); ++i) {
|
|
|
current_dim_size *= dims[i];
|
|
|
}
|
|
|
|
|
|
size_t start_pos = out.size();
|
|
|
auto nested_inits = init->constInitVal();
|
|
|
|
|
|
if (dims.empty()) {
|
|
|
// 标量,直接处理
|
|
|
for (auto* nested : nested_inits) {
|
|
|
CollectConstInitExprs(nested, out, dims, dim_idx);
|
|
|
}
|
|
|
} else if (dim_idx < dims.size() - 1) {
|
|
|
// 多维数组,递归处理每个子数组
|
|
|
size_t sub_dim_size = 1;
|
|
|
for (size_t i = dim_idx + 1; i < dims.size(); ++i) {
|
|
|
sub_dim_size *= dims[i];
|
|
|
}
|
|
|
|
|
|
for (auto* nested : nested_inits) {
|
|
|
if (out.size() >= start_pos + current_dim_size) {
|
|
|
break;
|
|
|
}
|
|
|
CollectConstInitExprs(nested, out, dims, dim_idx + 1);
|
|
|
}
|
|
|
} else {
|
|
|
// 一维数组,直接展平所有初始化表达式
|
|
|
for (auto* nested : nested_inits) {
|
|
|
if (out.size() >= start_pos + current_dim_size) {
|
|
|
break;
|
|
|
}
|
|
|
CollectConstInitExprs(nested, out, dims, dim_idx);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 确保不超过当前维度的大小
|
|
|
if (out.size() > start_pos + current_dim_size) {
|
|
|
// 截断超出的部分
|
|
|
out.resize(start_pos + current_dim_size);
|
|
|
}
|
|
|
|
|
|
// 补齐到当前维度大小
|
|
|
while (out.size() < start_pos + current_dim_size) {
|
|
|
out.push_back(nullptr);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
ir::AllocaInst* IRGenImpl::CreateEntryBlockAlloca(std::shared_ptr<ir::Type> elem_ty,
|
|
|
const std::string& name,
|
|
|
ir::Value* count) {
|
|
|
if (!func_ || func_->GetBlocks().empty()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "无法在入口块分配栈空间:函数未定义或无基本块"));
|
|
|
}
|
|
|
|
|
|
auto* entry_block = func_->GetBlocks().front().get();
|
|
|
|
|
|
auto* alloca = entry_block->InsertAlloca<ir::AllocaInst>(elem_ty, name, count);
|
|
|
|
|
|
return alloca;
|
|
|
}
|
|
|
|
|
|
std::shared_ptr<ir::Type> IRGenImpl::ResolveBType(
|
|
|
SysYParser::BTypeContext* btype) const {
|
|
|
if (!btype) {
|
|
|
throw std::runtime_error(FormatError("irgen", "缺少基础类型"));
|
|
|
}
|
|
|
if (btype->Int()) {
|
|
|
return ir::Type::GetInt32Type();
|
|
|
}
|
|
|
if (btype->Float()) {
|
|
|
return ir::Type::GetFloat32Type();
|
|
|
}
|
|
|
throw std::runtime_error(FormatError("irgen", "当前仅支持 int/float 类型"));
|
|
|
}
|
|
|
|
|
|
std::any IRGenImpl::visitBlock(SysYParser::BlockContext* ctx) {
|
|
|
if (!ctx) {
|
|
|
throw std::runtime_error(FormatError("irgen", "缺少语句块"));
|
|
|
}
|
|
|
|
|
|
// 进入新的作用域,保存当前常量映射状态
|
|
|
const_value_history_.push_back(const_value_map_);
|
|
|
local_const_stack_.emplace_back();
|
|
|
|
|
|
bool terminated = false;
|
|
|
for (auto* item : ctx->blockItem()) {
|
|
|
if (item) {
|
|
|
if (VisitBlockItemResult(*item) == BlockFlow::Terminated) {
|
|
|
// 当前语法要求 return 为块内最后一条语句;命中后可停止生成。
|
|
|
terminated = true;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 退出作用域,恢复常量映射状态
|
|
|
const_value_map_ = const_value_history_.back();
|
|
|
const_value_history_.pop_back();
|
|
|
local_const_stack_.pop_back();
|
|
|
|
|
|
return terminated ? BlockFlow::Terminated : BlockFlow::Continue;
|
|
|
}
|
|
|
|
|
|
IRGenImpl::BlockFlow IRGenImpl::VisitBlockItemResult(
|
|
|
SysYParser::BlockItemContext& item) {
|
|
|
return std::any_cast<BlockFlow>(item.accept(this));
|
|
|
}
|
|
|
|
|
|
std::any IRGenImpl::visitBlockItem(SysYParser::BlockItemContext* ctx) {
|
|
|
if (!ctx) {
|
|
|
throw std::runtime_error(FormatError("irgen", "缺少块内项"));
|
|
|
}
|
|
|
if (ctx->decl()) {
|
|
|
ctx->decl()->accept(this);
|
|
|
return BlockFlow::Continue;
|
|
|
}
|
|
|
if (ctx->stmt()) {
|
|
|
return ctx->stmt()->accept(this);
|
|
|
}
|
|
|
throw std::runtime_error(FormatError("irgen", "暂不支持的语句或声明"));
|
|
|
}
|
|
|
|
|
|
// 变量声明的 IR 生成目前也是最小实现:
|
|
|
// - 先检查声明的基础类型,当前仅支持局部 int;
|
|
|
// - 再把 Decl 中的变量定义交给 visitVarDef 继续处理。
|
|
|
//
|
|
|
// 和更完整的版本相比,这里还没有:
|
|
|
// - 一个 Decl 中多个变量定义的顺序处理;
|
|
|
// - const、数组、全局变量等不同声明形态;
|
|
|
// - 更丰富的类型系统。
|
|
|
std::any IRGenImpl::visitDecl(SysYParser::DeclContext* ctx) {
|
|
|
if (!ctx) {
|
|
|
throw std::runtime_error(FormatError("irgen", "缺少变量声明"));
|
|
|
}
|
|
|
if (ctx->constDecl()) {
|
|
|
auto* const_decl = ctx->constDecl();
|
|
|
if (!const_decl || !const_decl->bType()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法常量声明"));
|
|
|
}
|
|
|
auto elem_ty = ResolveBType(const_decl->bType());
|
|
|
const bool is_float = elem_ty->IsFloat32();
|
|
|
for (auto* def : const_decl->constDef()) {
|
|
|
if (!def || !def->Ident()) {
|
|
|
continue;
|
|
|
}
|
|
|
const std::string name = def->Ident()->getText();
|
|
|
if (def->constExp().empty()) {
|
|
|
if (!is_float && def->constInitVal() && def->constInitVal()->constExp()) {
|
|
|
int const_value = EvalConstIntExpr(*def->constInitVal()->constExp());
|
|
|
if (!func_) {
|
|
|
// 只对全局整型常量进行常量折叠
|
|
|
const_value_map_[name] = const_value;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (func_) {
|
|
|
// 局部常量:分配栈空间
|
|
|
auto* slot = builder_.CreateAlloca(elem_ty, module_.GetContext().NextTemp());
|
|
|
const_storage_map_[def] = slot;
|
|
|
ir::Value* init_elem = nullptr;
|
|
|
if (def->constInitVal() && def->constInitVal()->constExp()) {
|
|
|
init_elem = CastValueTo(
|
|
|
std::any_cast<ir::Value*>(def->constInitVal()->constExp()->accept(this)),
|
|
|
elem_ty);
|
|
|
} else {
|
|
|
init_elem = is_float ? static_cast<ir::Value*>(builder_.CreateConstFloat(0.0))
|
|
|
: static_cast<ir::Value*>(builder_.CreateConstInt(0));
|
|
|
}
|
|
|
builder_.CreateStore(init_elem, slot);
|
|
|
} else {
|
|
|
// 全局常量:创建全局变量
|
|
|
if (is_float) {
|
|
|
double init_value = 0.0;
|
|
|
if (def->constInitVal() && def->constInitVal()->constExp()) {
|
|
|
init_value = EvalConstFloatExpr(*def->constInitVal()->constExp());
|
|
|
}
|
|
|
auto* global = module_.CreateGlobalF32(name, init_value);
|
|
|
const_global_storage_map_[def] = global;
|
|
|
} else {
|
|
|
int init_value = 0;
|
|
|
if (def->constInitVal() && def->constInitVal()->constExp()) {
|
|
|
init_value = EvalConstIntExpr(*def->constInitVal()->constExp());
|
|
|
}
|
|
|
auto* global = module_.CreateGlobalI32(name, init_value);
|
|
|
const_global_storage_map_[def] = global;
|
|
|
}
|
|
|
}
|
|
|
continue;
|
|
|
}
|
|
|
auto extents = EvalArrayExtents(def->constExp());
|
|
|
size_t total_extent = 1;
|
|
|
for (int extent : extents) {
|
|
|
total_extent *= static_cast<size_t>(extent);
|
|
|
}
|
|
|
const_array_extents_map_[def] = extents;
|
|
|
|
|
|
if (!func_) {
|
|
|
std::vector<SysYParser::ConstExpContext*> init_exprs;
|
|
|
bool has_init = false;
|
|
|
if (def->constInitVal()) {
|
|
|
has_init = true;
|
|
|
CollectConstInitExprs(def->constInitVal(), init_exprs, extents);
|
|
|
if (init_exprs.size() > total_extent) {
|
|
|
throw std::runtime_error(FormatError("irgen", "数组初始化元素过多"));
|
|
|
}
|
|
|
}
|
|
|
std::vector<int> init_values;
|
|
|
std::vector<double> init_float_values;
|
|
|
if (is_float) {
|
|
|
if (has_init) {
|
|
|
init_float_values.reserve(total_extent);
|
|
|
for (size_t index = 0; index < total_extent; ++index) {
|
|
|
if (index < init_exprs.size() && init_exprs[index] && init_exprs[index]->addExp()) {
|
|
|
double value = 0.0;
|
|
|
auto* cf = dynamic_cast<ir::ConstantFloat*>(CastValueTo(
|
|
|
std::any_cast<ir::Value*>(init_exprs[index]->addExp()->accept(this)),
|
|
|
ir::Type::GetFloat32Type()));
|
|
|
if (cf) {
|
|
|
value = cf->GetValue();
|
|
|
}
|
|
|
init_float_values.push_back(value);
|
|
|
} else {
|
|
|
init_float_values.push_back(0.0);
|
|
|
}
|
|
|
}
|
|
|
size_t trailing_zeros = 0;
|
|
|
while (trailing_zeros < init_float_values.size() && init_float_values[init_float_values.size() - 1 - trailing_zeros] == 0.0) {
|
|
|
trailing_zeros++;
|
|
|
}
|
|
|
if (trailing_zeros > 0) {
|
|
|
init_float_values.resize(init_float_values.size() - trailing_zeros);
|
|
|
}
|
|
|
auto* global = module_.CreateGlobalArrayF32(name, total_extent, init_float_values);
|
|
|
const_global_storage_map_[def] = global;
|
|
|
} else {
|
|
|
auto* global = module_.CreateGlobalArrayF32(name, total_extent, {});
|
|
|
const_global_storage_map_[def] = global;
|
|
|
}
|
|
|
} else {
|
|
|
if (has_init) {
|
|
|
init_values.reserve(total_extent);
|
|
|
for (size_t index = 0; index < total_extent; ++index) {
|
|
|
if (index < init_exprs.size() && init_exprs[index] && init_exprs[index]->addExp()) {
|
|
|
int value = 0;
|
|
|
auto* ci = dynamic_cast<ir::ConstantInt*>(CastValueTo(
|
|
|
std::any_cast<ir::Value*>(init_exprs[index]->addExp()->accept(this)),
|
|
|
ir::Type::GetInt32Type()));
|
|
|
if (ci) {
|
|
|
value = ci->GetValue();
|
|
|
}
|
|
|
init_values.push_back(value);
|
|
|
} else {
|
|
|
init_values.push_back(0);
|
|
|
}
|
|
|
}
|
|
|
size_t trailing_zeros = 0;
|
|
|
while (trailing_zeros < init_values.size() && init_values[init_values.size() - 1 - trailing_zeros] == 0) {
|
|
|
trailing_zeros++;
|
|
|
}
|
|
|
if (trailing_zeros > 0) {
|
|
|
init_values.resize(init_values.size() - trailing_zeros);
|
|
|
}
|
|
|
auto* global = module_.CreateGlobalArrayI32(name, total_extent, init_values);
|
|
|
const_global_storage_map_[def] = global;
|
|
|
} else {
|
|
|
auto* global = module_.CreateGlobalArrayI32(name, total_extent, {});
|
|
|
const_global_storage_map_[def] = global;
|
|
|
}
|
|
|
}
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
auto* slot =
|
|
|
builder_.CreateAlloca(elem_ty, module_.GetContext().NextTemp(),
|
|
|
builder_.CreateConstInt(static_cast<int>(total_extent)));
|
|
|
const_storage_map_[def] = slot;
|
|
|
|
|
|
std::vector<SysYParser::ConstExpContext*> init_exprs;
|
|
|
CollectConstInitExprs(def->constInitVal(), init_exprs, extents);
|
|
|
if (init_exprs.size() > total_extent) {
|
|
|
throw std::runtime_error(FormatError("irgen", "数组初始化元素过多"));
|
|
|
}
|
|
|
for (size_t index = 0; index < total_extent; ++index) {
|
|
|
auto* idx = builder_.CreateConstInt(static_cast<int>(index));
|
|
|
auto* ptr = builder_.CreateGEP(slot, idx, module_.GetContext().NextTemp());
|
|
|
ir::Value* init_elem = nullptr;
|
|
|
if (index < init_exprs.size() && init_exprs[index] && init_exprs[index]->addExp()) {
|
|
|
init_elem = CastValueTo(
|
|
|
std::any_cast<ir::Value*>(init_exprs[index]->addExp()->accept(this)),
|
|
|
elem_ty);
|
|
|
} else {
|
|
|
init_elem = is_float ? static_cast<ir::Value*>(builder_.CreateConstFloat(0.0))
|
|
|
: static_cast<ir::Value*>(builder_.CreateConstInt(0));
|
|
|
}
|
|
|
builder_.CreateStore(init_elem, ptr);
|
|
|
}
|
|
|
}
|
|
|
return {};
|
|
|
}
|
|
|
if (!ctx->varDecl()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "当前不支持 const 声明"));
|
|
|
}
|
|
|
ctx->varDecl()->accept(this);
|
|
|
return {};
|
|
|
}
|
|
|
|
|
|
std::any IRGenImpl::visitVarDecl(SysYParser::VarDeclContext* ctx) {
|
|
|
if (!ctx) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法变量声明"));
|
|
|
}
|
|
|
if (!ctx->bType() || (!ctx->bType()->Int() && !ctx->bType()->Float())) {
|
|
|
throw std::runtime_error(
|
|
|
FormatError("irgen", "当前仅支持局部 int/float 变量声明"));
|
|
|
}
|
|
|
const auto& defs = ctx->varDef();
|
|
|
if (defs.empty()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法变量声明"));
|
|
|
}
|
|
|
for (auto* def : defs) {
|
|
|
if (!def) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法变量声明"));
|
|
|
}
|
|
|
def->accept(this);
|
|
|
}
|
|
|
return {};
|
|
|
}
|
|
|
|
|
|
|
|
|
// 当前仍是教学用的最小版本,因此这里只支持:
|
|
|
// - 局部 int 变量;
|
|
|
// - 标量初始化;
|
|
|
// - 一个 VarDef 对应一个槽位。
|
|
|
std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) {
|
|
|
if (!ctx) {
|
|
|
throw std::runtime_error(FormatError("irgen", "缺少变量定义"));
|
|
|
}
|
|
|
if (!ctx->Ident()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "变量声明缺少名称"));
|
|
|
}
|
|
|
const std::string name = ctx->Ident()->getText();
|
|
|
auto* var_decl = dynamic_cast<SysYParser::VarDeclContext*>(ctx->parent);
|
|
|
auto elem_ty = ResolveBType(var_decl ? var_decl->bType() : nullptr);
|
|
|
const bool is_float = elem_ty->IsFloat32();
|
|
|
|
|
|
if (name.empty()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "变量声明缺少名称"));
|
|
|
}
|
|
|
|
|
|
const bool is_array = !ctx->constExp().empty();
|
|
|
std::vector<int> extents;
|
|
|
size_t total_extent = 1;
|
|
|
if (is_array) {
|
|
|
extents = EvalArrayExtents(ctx->constExp());
|
|
|
for (int extent : extents) {
|
|
|
total_extent *= static_cast<size_t>(extent);
|
|
|
}
|
|
|
array_extents_map_[ctx] = extents;
|
|
|
}
|
|
|
|
|
|
if (!func_) {
|
|
|
if (global_storage_map_.find(ctx) != global_storage_map_.end()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "声明重复生成全局变量"));
|
|
|
}
|
|
|
if (is_array) {
|
|
|
std::vector<SysYParser::ExpContext*> init_exprs;
|
|
|
bool has_init = false;
|
|
|
if (auto* init_value = ctx->initVal()) {
|
|
|
has_init = true;
|
|
|
CollectInitExprs(init_value, init_exprs, extents);
|
|
|
if (init_exprs.size() > total_extent) {
|
|
|
throw std::runtime_error(FormatError("irgen", "数组初始化元素过多"));
|
|
|
}
|
|
|
}
|
|
|
std::vector<int> init_values;
|
|
|
std::vector<double> init_float_values;
|
|
|
if (is_float) {
|
|
|
if (has_init) {
|
|
|
init_float_values.reserve(total_extent);
|
|
|
for (size_t index = 0; index < total_extent; ++index) {
|
|
|
if (index < init_exprs.size() && init_exprs[index]) {
|
|
|
double value = 0.0;
|
|
|
auto* folded = EvalExpr(*init_exprs[index]);
|
|
|
auto* cf = dynamic_cast<ir::ConstantFloat*>(CastValueTo(folded, ir::Type::GetFloat32Type()));
|
|
|
if (cf) {
|
|
|
value = cf->GetValue();
|
|
|
}
|
|
|
init_float_values.push_back(value);
|
|
|
} else {
|
|
|
init_float_values.push_back(0.0);
|
|
|
}
|
|
|
}
|
|
|
size_t trailing_zeros = 0;
|
|
|
while (trailing_zeros < init_float_values.size() && init_float_values[init_float_values.size() - 1 - trailing_zeros] == 0.0) {
|
|
|
trailing_zeros++;
|
|
|
}
|
|
|
if (trailing_zeros > 0) {
|
|
|
init_float_values.resize(init_float_values.size() - trailing_zeros);
|
|
|
}
|
|
|
auto* global = module_.CreateGlobalArrayF32(name, total_extent, init_float_values);
|
|
|
global_storage_map_[ctx] = global;
|
|
|
} else {
|
|
|
auto* global = module_.CreateGlobalArrayF32(name, total_extent, {});
|
|
|
global_storage_map_[ctx] = global;
|
|
|
}
|
|
|
} else {
|
|
|
if (has_init) {
|
|
|
init_values.reserve(total_extent);
|
|
|
for (size_t index = 0; index < total_extent; ++index) {
|
|
|
if (index < init_exprs.size() && init_exprs[index]) {
|
|
|
int value = 0;
|
|
|
auto* folded = EvalExpr(*init_exprs[index]);
|
|
|
auto* ci = dynamic_cast<ir::ConstantInt*>(CastValueTo(folded, ir::Type::GetInt32Type()));
|
|
|
if (ci) {
|
|
|
value = ci->GetValue();
|
|
|
}
|
|
|
init_values.push_back(value);
|
|
|
} else {
|
|
|
init_values.push_back(0);
|
|
|
}
|
|
|
}
|
|
|
size_t trailing_zeros = 0;
|
|
|
while (trailing_zeros < init_values.size() && init_values[init_values.size() - 1 - trailing_zeros] == 0) {
|
|
|
trailing_zeros++;
|
|
|
}
|
|
|
if (trailing_zeros > 0) {
|
|
|
init_values.resize(init_values.size() - trailing_zeros);
|
|
|
}
|
|
|
auto* global = module_.CreateGlobalArrayI32(name, total_extent, init_values);
|
|
|
global_storage_map_[ctx] = global;
|
|
|
} else {
|
|
|
auto* global = module_.CreateGlobalArrayI32(name, total_extent, {});
|
|
|
global_storage_map_[ctx] = global;
|
|
|
}
|
|
|
}
|
|
|
return {};
|
|
|
}
|
|
|
|
|
|
int init = 0;
|
|
|
double init_float = 0.0;
|
|
|
if (auto* init_value = ctx->initVal()) {
|
|
|
if (!init_value->exp()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化"));
|
|
|
}
|
|
|
auto* folded = EvalExpr(*init_value->exp());
|
|
|
if (is_float) {
|
|
|
auto* cf = dynamic_cast<ir::ConstantFloat*>(CastValueTo(folded, ir::Type::GetFloat32Type()));
|
|
|
if (!cf) {
|
|
|
throw std::runtime_error(
|
|
|
FormatError("irgen", "全局浮点初始化必须是常量表达式"));
|
|
|
}
|
|
|
init_float = cf->GetValue();
|
|
|
} else {
|
|
|
auto* ci = dynamic_cast<ir::ConstantInt*>(CastValueTo(folded, ir::Type::GetInt32Type()));
|
|
|
if (!ci) {
|
|
|
throw std::runtime_error(
|
|
|
FormatError("irgen", "全局整型初始化必须是常量表达式"));
|
|
|
}
|
|
|
init = ci->GetValue();
|
|
|
}
|
|
|
}
|
|
|
auto* global =
|
|
|
is_float ? module_.CreateGlobalF32(name, init_float)
|
|
|
: module_.CreateGlobalI32(name, init);
|
|
|
global_storage_map_[ctx] = global;
|
|
|
return {};
|
|
|
}
|
|
|
|
|
|
// 检查是否已经在当前作用域中声明
|
|
|
if (storage_map_.find(ctx) != storage_map_.end()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位"));
|
|
|
}
|
|
|
ir::Value* count = nullptr;
|
|
|
if (is_array) {
|
|
|
count = builder_.CreateConstInt(static_cast<int>(total_extent));
|
|
|
}
|
|
|
auto* slot = CreateEntryBlockAlloca(elem_ty, module_.GetContext().NextTemp(), count);
|
|
|
storage_map_[ctx] = slot;
|
|
|
|
|
|
if (is_array) {
|
|
|
std::vector<SysYParser::ExpContext*> init_exprs;
|
|
|
if (auto* init_value = ctx->initVal()) {
|
|
|
CollectInitExprs(init_value, init_exprs, extents);
|
|
|
if (init_exprs.size() > total_extent) {
|
|
|
throw std::runtime_error(FormatError("irgen", "数组初始化元素过多"));
|
|
|
}
|
|
|
|
|
|
// 对于小数组(<=10000元素),直接生成完整初始化
|
|
|
if (total_extent <= 10000) {
|
|
|
for (size_t index = 0; index < total_extent; ++index) {
|
|
|
auto* idx = builder_.CreateConstInt(static_cast<int>(index));
|
|
|
auto* ptr = builder_.CreateGEP(slot, idx, module_.GetContext().NextTemp());
|
|
|
ir::Value* init_elem = nullptr;
|
|
|
if (index < init_exprs.size() && init_exprs[index]) {
|
|
|
init_elem = CastValueTo(EvalExpr(*init_exprs[index]), elem_ty);
|
|
|
} else {
|
|
|
init_elem = is_float ? static_cast<ir::Value*>(builder_.CreateConstFloat(0.0))
|
|
|
: static_cast<ir::Value*>(builder_.CreateConstInt(0));
|
|
|
}
|
|
|
builder_.CreateStore(init_elem, ptr);
|
|
|
}
|
|
|
} else {
|
|
|
// 对于大数组,生成循环初始化零,然后初始化非零元素
|
|
|
auto* func = builder_.GetInsertBlock()->GetParent();
|
|
|
auto* loop_cond = func->CreateBlock("zero.init.cond");
|
|
|
auto* loop_body = func->CreateBlock("zero.init.body");
|
|
|
auto* loop_end = func->CreateBlock("zero.init.end");
|
|
|
|
|
|
auto* counter = builder_.CreateAlloca(ir::Type::GetInt32Type(), module_.GetContext().NextTemp());
|
|
|
builder_.CreateStore(builder_.CreateConstInt(0), counter);
|
|
|
|
|
|
builder_.CreateBr(loop_cond);
|
|
|
|
|
|
builder_.SetInsertPoint(loop_cond);
|
|
|
auto* counter_val = builder_.CreateLoad(counter, module_.GetContext().NextTemp());
|
|
|
auto* cond = builder_.CreateICmp(ir::Opcode::Lt, counter_val,
|
|
|
builder_.CreateConstInt(static_cast<int>(total_extent)),
|
|
|
module_.GetContext().NextTemp());
|
|
|
builder_.CreateCondBr(cond, loop_body, loop_end);
|
|
|
|
|
|
builder_.SetInsertPoint(loop_body);
|
|
|
auto* idx = builder_.CreateLoad(counter, module_.GetContext().NextTemp());
|
|
|
auto* ptr = builder_.CreateGEP(slot, idx, module_.GetContext().NextTemp());
|
|
|
auto* zero = is_float ? static_cast<ir::Value*>(builder_.CreateConstFloat(0.0))
|
|
|
: static_cast<ir::Value*>(builder_.CreateConstInt(0));
|
|
|
builder_.CreateStore(zero, ptr);
|
|
|
|
|
|
auto* new_counter = builder_.CreateAdd(builder_.CreateLoad(counter, module_.GetContext().NextTemp()),
|
|
|
builder_.CreateConstInt(1),
|
|
|
module_.GetContext().NextTemp());
|
|
|
builder_.CreateStore(new_counter, counter);
|
|
|
builder_.CreateBr(loop_cond);
|
|
|
|
|
|
builder_.SetInsertPoint(loop_end);
|
|
|
|
|
|
// 初始化非零元素
|
|
|
for (size_t index = 0; index < init_exprs.size(); ++index) {
|
|
|
if (init_exprs[index]) {
|
|
|
auto* idx = builder_.CreateConstInt(static_cast<int>(index));
|
|
|
auto* ptr = builder_.CreateGEP(slot, idx, module_.GetContext().NextTemp());
|
|
|
ir::Value* init_elem = CastValueTo(EvalExpr(*init_exprs[index]), elem_ty);
|
|
|
builder_.CreateStore(init_elem, ptr);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
// 如果没有初始化列表,不生成任何初始化代码(局部变量默认不初始化)
|
|
|
return {};
|
|
|
}
|
|
|
|
|
|
ir::Value* init = nullptr;
|
|
|
if (auto* init_value = ctx->initVal()) {
|
|
|
if (!init_value->exp()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化"));
|
|
|
}
|
|
|
init = CastValueTo(EvalExpr(*init_value->exp()), elem_ty);
|
|
|
} else {
|
|
|
init = is_float ? static_cast<ir::Value*>(builder_.CreateConstFloat(0.0))
|
|
|
: static_cast<ir::Value*>(builder_.CreateConstInt(0));
|
|
|
}
|
|
|
builder_.CreateStore(init, slot);
|
|
|
return {};
|
|
|
} |