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/IRGenStmt.cpp

192 lines
6.1 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 <stdexcept>
#include "antlr4/SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"
static std::string FormatErrorCtx(antlr4::ParserRuleContext* ctx,
const std::string& msg) {
if (ctx && ctx->getStart()) {
return FormatErrorAt("irgen", ctx->getStart()->getLine(),
ctx->getStart()->getCharPositionInLine() + 1, msg);
}
return FormatError("irgen", msg);
}
// 语句生成当前只实现了最小子集。
// 目前支持:
// - return <exp>;
//
// 还未支持:
// - 赋值语句
// - if / while 等控制流
// - 空语句、块语句嵌套分发之外的更多语句形态
std::any IRGenImpl::visitStmt(SysYParser::StmtContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少语句"));
}
if (ctx->lValue() && ctx->ASSIGN() && ctx->exp()) {
if (!ctx->lValue()->ID()) {
throw std::runtime_error(FormatError("irgen", "赋值语句左值非法"));
}
ir::Value* dest = ResolveLValueAddress(ctx->lValue());
if (!dest) {
throw std::runtime_error(
FormatError("irgen", "赋值目标地址解析失败"));
}
ir::Value* rhs = EvalExpr(*ctx->exp());
builder_.CreateStore(rhs, dest);
return BlockFlow::Continue;
}
if (ctx->blockStmt()) {
ctx->blockStmt()->accept(this);
return builder_.GetInsertBlock() && builder_.GetInsertBlock()->HasTerminator()
? BlockFlow::Terminated
: BlockFlow::Continue;
}
if (ctx->IF()) {
if (!ctx->cond() || ctx->stmt().empty()) {
throw std::runtime_error(FormatError("irgen", "if 语句不完整"));
}
auto* then_bb = func_->CreateBlock(NextBlockName());
auto* merge_bb = func_->CreateBlock(NextBlockName());
auto* else_bb = ctx->ELSE() ? func_->CreateBlock(NextBlockName()) : merge_bb;
ir::Value* cond = ToBoolValue(EvalCond(*ctx->cond()));
builder_.CreateCondBr(cond, then_bb, else_bb);
builder_.SetInsertPoint(then_bb);
auto then_flow = std::any_cast<BlockFlow>(ctx->stmt(0)->accept(this));
if (then_flow != BlockFlow::Terminated) {
builder_.CreateBr(merge_bb);
}
if (ctx->ELSE()) {
builder_.SetInsertPoint(else_bb);
auto else_flow = std::any_cast<BlockFlow>(ctx->stmt(1)->accept(this));
if (else_flow != BlockFlow::Terminated) {
builder_.CreateBr(merge_bb);
}
}
builder_.SetInsertPoint(merge_bb);
return BlockFlow::Continue;
}
if (ctx->WHILE()) {
if (!ctx->cond() || ctx->stmt().empty()) {
throw std::runtime_error(FormatError("irgen", "while 语句不完整"));
}
auto* cond_bb = func_->CreateBlock(NextBlockName());
auto* body_bb = func_->CreateBlock(NextBlockName());
auto* exit_bb = func_->CreateBlock(NextBlockName());
builder_.CreateBr(cond_bb);
builder_.SetInsertPoint(cond_bb);
ir::Value* cond = ToBoolValue(EvalCond(*ctx->cond()));
builder_.CreateCondBr(cond, body_bb, exit_bb);
loop_stack_.push_back({cond_bb, exit_bb});
builder_.SetInsertPoint(body_bb);
auto body_flow = std::any_cast<BlockFlow>(ctx->stmt(0)->accept(this));
if (body_flow != BlockFlow::Terminated) {
builder_.CreateBr(cond_bb);
}
loop_stack_.pop_back();
builder_.SetInsertPoint(exit_bb);
return BlockFlow::Continue;
}
if (ctx->BREAK()) {
if (loop_stack_.empty()) {
throw std::runtime_error(FormatError("irgen", "break 不在循环中"));
}
builder_.CreateBr(loop_stack_.back().break_target);
return BlockFlow::Terminated;
}
if (ctx->CONTINUE()) {
if (loop_stack_.empty()) {
throw std::runtime_error(FormatError("irgen", "continue 不在循环中"));
}
builder_.CreateBr(loop_stack_.back().continue_target);
return BlockFlow::Terminated;
}
if (ctx->returnStmt()) {
return ctx->returnStmt()->accept(this);
}
if (ctx->exp()) {
EvalExpr(*ctx->exp());
return BlockFlow::Continue;
}
if (ctx->SEMICOLON()) {
return BlockFlow::Continue;
}
throw std::runtime_error(FormatError("irgen", "暂不支持的语句类型"));
}
ir::Value* IRGenImpl::ResolveLValueAddress(SysYParser::LValueContext* ctx) {
if (!ctx || !ctx->ID()) {
throw std::runtime_error(FormatError("irgen", "非法左值"));
}
const std::string name = ctx->ID()->getText();
ir::Value* base = FindInScope(name);
if (!base) {
throw std::runtime_error(FormatError("irgen", "变量未声明: " + name));
}
if (ctx->LBRACK().empty()) {
return base;
}
// 到目前为止只支持一维数组,占位实现
if (ctx->exp().empty()) {
throw std::runtime_error(FormatError("irgen", "数组下标缺失"));
}
return EmitArrayIndex(base, ctx->exp(0));
}
std::any IRGenImpl::visitReturnStmt(SysYParser::ReturnStmtContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少 return 语句"));
}
if (!ctx->exp()) {
throw std::runtime_error(FormatError("irgen", "return 缺少表达式"));
}
ir::Value* v = EvalExpr(*ctx->exp());
builder_.CreateRet(v);
return BlockFlow::Terminated;
}
ir::Value* IRGenImpl::EmitArrayIndex(ir::Value* base_ptr,
SysYParser::ExpContext* idx_expr) {
if (!base_ptr) {
throw std::runtime_error(FormatError("irgen", "数组基址为空"));
}
if (!idx_expr) {
throw std::runtime_error(FormatError("irgen", "缺少数组下标表达式"));
}
ir::Value* idx = EvalExpr(*idx_expr);
if (!idx) {
throw std::runtime_error(FormatError("irgen", "数组下标计算失败"));
}
// 当前 IR 仍只支持 i32 / i32*,还未实现真正的 GEP。
// 这里提供一个占位:直接将基址作为元素地址返回(仅用于结构化接口),
// 具体语义需在后续 IR 指令集扩展后完成。
// TODO: 实现指针加法/GEP以支持数组下标访问
(void)idx;
return base_ptr;
}
void IRGenImpl::EmitGlobalVariable(SysYParser::VarDefContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少全局变量定义"));
}
// GlobalValue 还未完成,暂时抛异常以提醒后续实现。
throw std::runtime_error(FormatError("irgen", "全局变量生成未实现"));
}