You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nudt-compiler-cpp/src/irgen/IRGenDecl.cpp

573 lines
20 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "irgen/IRGen.h"
#include <cstdint>
#include <cstring>
#include <stdexcept>
#include "SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"
std::any IRGenImpl::visitBlockStmt(SysYParser::BlockStmtContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少语句块"));
}
const auto saved_const_env = const_env_;
const auto saved_const_float_env = const_float_env_;
for (auto* item : ctx->blockItem()) {
if (item) {
if (VisitBlockItemResult(*item) == BlockFlow::Terminated) {
break;
}
}
}
const_env_ = saved_const_env;
const_float_env_ = saved_const_float_env;
return {};
}
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", "暂不支持的语句或声明"));
}
std::any IRGenImpl::visitDecl(SysYParser::DeclContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少变量声明"));
}
if (ctx->constDecl()) {
return ctx->constDecl()->accept(this);
}
if (ctx->varDecl()) {
return ctx->varDecl()->accept(this);
}
return {};
}
// ─── 工具:扁平化 constInitValue ──────────────────────────────────────────
// 将嵌套的 const 初始化列表展开为长度 total 的整数数组。
// 遵循 C99 数组初始化规则:
// - 标量直接填一格
// - 大括号子列表对齐到 sub_size 边界,填满后补零
void IRGenImpl::FlattenConstInit(SysYParser::ConstInitValueContext* ctx,
const std::vector<int>& dims, int dim_idx,
std::vector<int>& out, int& pos) {
if (!ctx) return;
if (ctx->constExp()) {
// 标量叶节点
out[pos++] = EvalConstExpr(ctx->constExp());
return;
}
// 大括号列表
int sub_size = 1;
for (int i = dim_idx + 1; i < (int)dims.size(); i++) sub_size *= dims[i];
int agg_size = (dim_idx < (int)dims.size()) ? dims[dim_idx] * sub_size : 1;
int start = pos;
for (auto* item : ctx->constInitValue()) {
if (!item || pos >= start + agg_size) break;
if (item->constExp()) {
// 标量:直接填当前位置
out[pos++] = EvalConstExpr(item->constExp());
} else {
// 嵌套大括号:对齐到 sub_size 边界
if (sub_size > 1) {
int offset = pos - start;
int rem = offset % sub_size;
if (rem != 0) pos += sub_size - rem;
}
int sub_start = pos;
FlattenConstInit(item, dims, dim_idx + 1, out, pos);
// 补零到子聚合末尾
int sub_end = sub_start + sub_size;
while (pos < sub_end && pos < start + agg_size) out[pos++] = 0;
}
}
// 剩余补零
while (pos < start + agg_size) out[pos++] = 0;
}
void IRGenImpl::FlattenConstInitFloat(SysYParser::ConstInitValueContext* ctx,
const std::vector<int>& dims, int dim_idx,
std::vector<float>& out, int& pos) {
if (!ctx) return;
if (ctx->constExp()) {
out[pos++] = EvalConstExprAsFloat(ctx->constExp());
return;
}
int sub_size = 1;
for (int i = dim_idx + 1; i < (int)dims.size(); i++) sub_size *= dims[i];
int agg_size = (dim_idx < (int)dims.size()) ? dims[dim_idx] * sub_size : 1;
int start = pos;
for (auto* item : ctx->constInitValue()) {
if (!item || pos >= start + agg_size) break;
if (item->constExp()) {
out[pos++] = EvalConstExprAsFloat(item->constExp());
} else {
if (sub_size > 1) {
int offset = pos - start;
int rem = offset % sub_size;
if (rem != 0) pos += sub_size - rem;
}
int sub_start = pos;
FlattenConstInitFloat(item, dims, dim_idx + 1, out, pos);
int sub_end = sub_start + sub_size;
while (pos < sub_end && pos < start + agg_size) out[pos++] = 0.0f;
}
}
while (pos < start + agg_size) out[pos++] = 0.0f;
}
// ─── 工具:扁平化 initValue ───────────────────────────────────────────────
void IRGenImpl::FlattenInit(SysYParser::InitValueContext* ctx,
const std::vector<int>& dims, int dim_idx,
std::vector<ir::Value*>& out, int& pos) {
if (!ctx) return;
if (ctx->exp()) {
out[pos++] = EvalExpr(*ctx->exp());
return;
}
int sub_size = 1;
for (int i = dim_idx + 1; i < (int)dims.size(); i++) sub_size *= dims[i];
int agg_size = (dim_idx < (int)dims.size()) ? dims[dim_idx] * sub_size : 1;
int start = pos;
for (auto* item : ctx->initValue()) {
if (!item || pos >= start + agg_size) break;
if (item->exp()) {
out[pos++] = EvalExpr(*item->exp());
} else {
if (sub_size > 1) {
int offset = pos - start;
int rem = offset % sub_size;
if (rem != 0) pos += sub_size - rem; // zeros already in out
}
int sub_start = pos;
FlattenInit(item, dims, dim_idx + 1, out, pos);
int sub_end = sub_start + sub_size;
while (pos < sub_end && pos < start + agg_size) pos++; // zeros
}
}
while (pos < start + agg_size) pos++; // zeros
}
void IRGenImpl::FlattenGlobalInitInt(SysYParser::InitValueContext* ctx,
const std::vector<int>& dims, int dim_idx,
std::vector<int>& out, int& pos) {
if (!ctx) return;
if (ctx->exp()) {
out[pos++] = EvalExpAsConst(ctx->exp());
return;
}
int sub_size = 1;
for (int i = dim_idx + 1; i < (int)dims.size(); i++) sub_size *= dims[i];
int agg_size = (dim_idx < (int)dims.size()) ? dims[dim_idx] * sub_size : 1;
int start = pos;
for (auto* item : ctx->initValue()) {
if (!item || pos >= start + agg_size) break;
if (item->exp()) {
out[pos++] = EvalExpAsConst(item->exp());
} else {
if (sub_size > 1) {
int offset = pos - start;
int rem = offset % sub_size;
if (rem != 0) pos += sub_size - rem;
}
int sub_start = pos;
FlattenGlobalInitInt(item, dims, dim_idx + 1, out, pos);
int sub_end = sub_start + sub_size;
while (pos < sub_end && pos < start + agg_size) out[pos++] = 0;
}
}
while (pos < start + agg_size) out[pos++] = 0;
}
void IRGenImpl::FlattenGlobalInitFloat(SysYParser::InitValueContext* ctx,
const std::vector<int>& dims,
int dim_idx, std::vector<float>& out,
int& pos) {
if (!ctx) return;
if (ctx->exp()) {
out[pos++] = EvalExpAsConstFloat(ctx->exp());
return;
}
int sub_size = 1;
for (int i = dim_idx + 1; i < (int)dims.size(); i++) sub_size *= dims[i];
int agg_size = (dim_idx < (int)dims.size()) ? dims[dim_idx] * sub_size : 1;
int start = pos;
for (auto* item : ctx->initValue()) {
if (!item || pos >= start + agg_size) break;
if (item->exp()) {
out[pos++] = EvalExpAsConstFloat(item->exp());
} else {
if (sub_size > 1) {
int offset = pos - start;
int rem = offset % sub_size;
if (rem != 0) pos += sub_size - rem;
}
int sub_start = pos;
FlattenGlobalInitFloat(item, dims, dim_idx + 1, out, pos);
int sub_end = sub_start + sub_size;
while (pos < sub_end && pos < start + agg_size) out[pos++] = 0.0f;
}
}
while (pos < start + agg_size) out[pos++] = 0.0f;
}
// ─── const 声明 ───────────────────────────────────────────────────────────
std::any IRGenImpl::visitConstDecl(SysYParser::ConstDeclContext* ctx) {
if (!ctx) return {};
if (!ctx->btype()) {
throw std::runtime_error(FormatError("irgen", "缺少类型声明"));
}
if (ctx->btype()->INT()) {
current_decl_type_ = ir::Type::GetInt32Type();
} else if (ctx->btype()->FLOAT()) {
current_decl_type_ = ir::Type::GetFloat32Type();
} else {
throw std::runtime_error(FormatError("irgen", "当前仅支持 int/float const 声明"));
}
for (auto* def : ctx->constDef()) {
if (def) def->accept(this);
}
current_decl_type_ = nullptr;
return {};
}
std::any IRGenImpl::visitConstDef(SysYParser::ConstDefContext* ctx) {
if (!ctx || !ctx->ID()) return {};
const std::string name = ctx->ID()->getText();
// ── 标量 const ────────────────────────────────────────────────────────
if (ctx->LBRACK().empty()) {
if (!ctx->constInitValue() || !ctx->constInitValue()->constExp()) {
throw std::runtime_error(FormatError("irgen", "const 标量声明缺少初始值"));
}
const bool is_float_const = current_decl_type_ && current_decl_type_->IsFloat32();
if (is_float_const) {
float fval = EvalConstExprAsFloat(ctx->constInitValue()->constExp());
const_float_env_[name] = fval;
if (IsGlobalScope()) {
std::int32_t bits = 0;
std::memcpy(&bits, &fval, sizeof(bits));
auto* gv = module_.CreateGlobalVar(
name, static_cast<int>(bits), 1, ir::Type::GetPtrFloat32Type());
global_storage_[name] = gv;
} else {
auto* slot = CreateEntryAllocaF32(module_.GetContext().NextTemp());
named_storage_[name] = slot;
builder_.CreateStore(module_.GetContext().GetConstFloat(fval), slot);
}
} else {
int ival = EvalConstExpr(ctx->constInitValue()->constExp());
const_env_[name] = ival; // 存入编译期环境
if (IsGlobalScope()) {
auto* gv = module_.CreateGlobalVar(name, ival);
global_storage_[name] = gv;
} else {
auto* slot = CreateEntryAllocaI32(module_.GetContext().NextTemp());
named_storage_[name] = slot;
builder_.CreateStore(builder_.CreateConstInt(ival), slot);
}
}
return {};
}
// ── 数组 const ────────────────────────────────────────────────────────
std::vector<int> dims;
for (auto* ce : ctx->constExp()) {
dims.push_back(EvalConstExpr(ce));
}
int total = 1;
for (int d : dims) total *= d;
const bool is_float_const = current_decl_type_ && current_decl_type_->IsFloat32();
if (is_float_const) {
std::vector<float> flat(total, 0.0f);
if (ctx->constInitValue()) {
int pos = 0;
FlattenConstInitFloat(ctx->constInitValue(), dims, 0, flat, pos);
}
std::vector<int> init_bits;
init_bits.reserve(flat.size());
for (float v : flat) {
std::int32_t bits = 0;
std::memcpy(&bits, &v, sizeof(bits));
init_bits.push_back(static_cast<int>(bits));
}
if (IsGlobalScope()) {
auto* gv = module_.CreateGlobalVar(
name, 0, total, ir::Type::GetPtrFloat32Type(), std::move(init_bits));
global_storage_[name] = gv;
global_array_dims_[name] = dims;
} else {
auto* slot = CreateEntryAllocaF32Array(total, module_.GetContext().NextTemp());
named_storage_[name] = slot;
local_array_dims_[name] = dims;
for (int i = 0; i < total; i++) {
auto* idx = builder_.CreateConstInt(i);
auto* ptr = builder_.CreateGep(slot, idx, module_.GetContext().NextTemp());
builder_.CreateStore(module_.GetContext().GetConstFloat(flat[i]), ptr);
}
}
return {};
}
// 扁平化初始化值
std::vector<int> flat(total, 0);
if (ctx->constInitValue()) {
int pos = 0;
FlattenConstInit(ctx->constInitValue(), dims, 0, flat, pos);
}
if (IsGlobalScope()) {
auto* gv = module_.CreateGlobalVar(name, 0, total,
ir::Type::GetPtrInt32Type(),
std::move(flat));
global_storage_[name] = gv;
global_array_dims_[name] = dims;
} else {
// 局部 const 数组alloca + 逐元素 store
auto* slot = CreateEntryAllocaArray(total, module_.GetContext().NextTemp());
named_storage_[name] = slot;
local_array_dims_[name] = dims;
for (int i = 0; i < total; i++) {
auto* idx = builder_.CreateConstInt(i);
auto* ptr = builder_.CreateGep(slot, idx, module_.GetContext().NextTemp());
builder_.CreateStore(builder_.CreateConstInt(flat[i]), ptr);
}
}
return {};
}
// ─── var 声明 ─────────────────────────────────────────────────────────────
std::any IRGenImpl::visitVarDecl(SysYParser::VarDeclContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少变量声明"));
}
if (!ctx->btype()) {
throw std::runtime_error(FormatError("irgen", "缺少类型声明"));
}
// 设置当前声明类型
if (ctx->btype()->INT()) {
current_decl_type_ = ir::Type::GetInt32Type();
} else if (ctx->btype()->FLOAT()) {
current_decl_type_ = ir::Type::GetFloat32Type();
} else {
throw std::runtime_error(FormatError("irgen", "当前仅支持 int/float 变量声明"));
}
for (auto* var_def : ctx->varDef()) {
if (!var_def) {
throw std::runtime_error(FormatError("irgen", "非法变量声明"));
}
var_def->accept(this);
}
current_decl_type_ = nullptr; // 清理
return {};
}
std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) {
if (!ctx || !ctx->ID()) {
throw std::runtime_error(FormatError("irgen", "变量定义缺少名称"));
}
const std::string name = ctx->ID()->getText();
// ── 数组变量 ──────────────────────────────────────────────────────────
if (!ctx->LBRACK().empty()) {
std::vector<int> dims;
for (auto* ce : ctx->constExp()) {
dims.push_back(EvalConstExpr(ce));
}
int total = 1;
for (int d : dims) total *= d;
if (IsGlobalScope()) {
std::vector<int> init_elems;
if (auto* init_val = ctx->initValue()) {
if (current_decl_type_->IsFloat32()) {
std::vector<float> flat(total, 0.0f);
int pos = 0;
FlattenGlobalInitFloat(init_val, dims, 0, flat, pos);
init_elems.reserve(flat.size());
for (float v : flat) {
std::int32_t bits = 0;
std::memcpy(&bits, &v, sizeof(bits));
init_elems.push_back(static_cast<int>(bits));
}
} else {
init_elems.assign(total, 0);
int pos = 0;
FlattenGlobalInitInt(init_val, dims, 0, init_elems, pos);
}
}
auto* gv = module_.CreateGlobalVar(
name, 0, total,
current_decl_type_->IsFloat32() ? ir::Type::GetPtrFloat32Type()
: ir::Type::GetPtrInt32Type(),
std::move(init_elems));
storage_map_[ctx] = gv;
global_storage_[name] = gv;
global_array_dims_[name] = dims;
} else {
// 根据当前声明类型创建数组alloca
ir::AllocaInst* slot;
if (current_decl_type_->IsFloat32()) {
slot = CreateEntryAllocaF32Array(total, module_.GetContext().NextTemp());
} else {
slot = CreateEntryAllocaArray(total, module_.GetContext().NextTemp());
}
storage_map_[ctx] = slot;
named_storage_[name] = slot;
local_array_dims_[name] = dims;
// 先零初始化float 数组走 memsetint 数组维持逐元素 store。
if (current_decl_type_->IsFloat32()) {
if (total > 0) {
auto* memset_fn = module_.FindFunction("memset");
if (!memset_fn) {
memset_fn = module_.CreateFunction(
"memset", ir::Type::GetVoidType(),
{ir::Type::GetPtrFloat32Type(), ir::Type::GetInt32Type(),
ir::Type::GetInt32Type()});
memset_fn->SetExternal(true);
}
builder_.CreateCall(
memset_fn,
{slot, builder_.CreateConstInt(0), builder_.CreateConstInt(total * 4)},
module_.GetContext().NextTemp());
}
} else {
for (int i = 0; i < total; i++) {
auto* idx = builder_.CreateConstInt(i);
auto* ptr = builder_.CreateGep(slot, idx, module_.GetContext().NextTemp());
builder_.CreateStore(builder_.CreateConstInt(0), ptr);
}
}
// 如果有初始化列表,覆盖零
if (auto* init_val = ctx->initValue()) {
std::vector<ir::Value*> flat(total, nullptr);
int pos = 0;
FlattenInit(init_val, dims, 0, flat, pos);
for (int i = 0; i < total; i++) {
if (flat[i] != nullptr) {
auto* idx = builder_.CreateConstInt(i);
auto* ptr = builder_.CreateGep(slot, idx, module_.GetContext().NextTemp());
ir::Value* val = flat[i];
if (ptr->GetType()->IsPtrFloat32()) {
val = CastToFloat(val);
} else {
val = CastToInt(val);
}
builder_.CreateStore(val, ptr);
}
}
}
}
return {};
}
// ── 标量变量 ──────────────────────────────────────────────────────────
if (IsGlobalScope()) {
int init_bits_or_int = 0;
if (current_decl_type_->IsFloat32()) {
float fval = 0.0f;
if (auto* init_value = ctx->initValue()) {
if (!init_value->exp()) {
throw std::runtime_error(
FormatError("irgen", "全局标量变量仅支持表达式初始化"));
}
fval = EvalExpAsConstFloat(init_value->exp());
}
std::int32_t bits = 0;
std::memcpy(&bits, &fval, sizeof(bits));
init_bits_or_int = static_cast<int>(bits);
} else {
if (auto* init_value = ctx->initValue()) {
if (!init_value->exp()) {
throw std::runtime_error(
FormatError("irgen", "全局标量变量仅支持表达式初始化"));
}
init_bits_or_int = EvalExpAsConst(init_value->exp());
}
}
auto* gv = module_.CreateGlobalVar(
name, init_bits_or_int, 1,
current_decl_type_->IsFloat32() ? ir::Type::GetPtrFloat32Type()
: ir::Type::GetPtrInt32Type());
storage_map_[ctx] = gv;
global_storage_[name] = gv;
return {};
}
// 局部标量
if (storage_map_.find(ctx) != storage_map_.end()) {
throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位"));
}
// 根据当前声明类型创建alloca
ir::AllocaInst* slot;
if (current_decl_type_->IsFloat32()) {
slot = CreateEntryAllocaF32(module_.GetContext().NextTemp());
} else {
slot = CreateEntryAllocaI32(module_.GetContext().NextTemp());
}
storage_map_[ctx] = slot;
named_storage_[name] = slot;
ir::Value* init = nullptr;
if (auto* init_value = ctx->initValue()) {
if (!init_value->exp()) {
throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化到标量"));
}
init = EvalExpr(*init_value->exp());
} else {
if (current_decl_type_->IsFloat32()) {
init = module_.GetContext().GetConstFloat(0.0f);
} else {
init = builder_.CreateConstInt(0);
}
}
if (current_decl_type_->IsFloat32()) {
init = CastToFloat(init);
} else {
init = CastToInt(init);
}
builder_.CreateStore(init, slot);
return {};
}