forked from ppxf25tqu/nudt-compiler-cpp
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.
242 lines
9.7 KiB
242 lines
9.7 KiB
#include "irgen/IRGen.h"
|
|
|
|
#include <stdexcept>
|
|
#include <string>
|
|
|
|
#include "SysYParser.h"
|
|
#include "ir/IR.h"
|
|
#include "utils/Log.h"
|
|
|
|
// ─── visitStmt ────────────────────────────────────────────────────────────────
|
|
std::any IRGenImpl::visitStmt(SysYParser::StmtContext* ctx) {
|
|
return VisitStmt(*ctx);
|
|
}
|
|
|
|
IRGenImpl::BlockFlow IRGenImpl::VisitStmt(SysYParser::StmtContext& s) {
|
|
auto* ctx = &s;
|
|
|
|
// 若当前块已经终结,跳过死代码
|
|
{
|
|
auto* cur = builder_.GetInsertBlock();
|
|
if (cur && cur->HasTerminator()) return BlockFlow::Terminated;
|
|
}
|
|
|
|
// ── return ──────────────────────────────────────────────────────────────────
|
|
if (ctx->Return()) {
|
|
if (ctx->exp()) {
|
|
ir::Value* v = EvalExpr(*ctx->exp());
|
|
// Coerce return value to function return type
|
|
if (func_->GetType()->IsInt32() && v->IsFloat32()) {
|
|
v = ToInt(v);
|
|
} else if (func_->GetType()->IsFloat32() && v->IsInt32()) {
|
|
v = ToFloat(v);
|
|
} else if (func_->GetType()->IsInt32() && v->IsInt1()) {
|
|
v = ToI32(v);
|
|
}
|
|
if (func_->GetName() == "main" && !func_->GetType()->IsVoid()) {
|
|
auto* nl = builder_.CreateConstInt(10);
|
|
// ((v % 256) + 256) % 256
|
|
auto* mod256 = builder_.CreateMod(v, builder_.CreateConstInt(256),
|
|
module_.GetContext().NextTemp());
|
|
auto* add256 = builder_.CreateAdd(mod256, builder_.CreateConstInt(256),
|
|
module_.GetContext().NextTemp());
|
|
auto* masked = builder_.CreateMod(add256, builder_.CreateConstInt(256),
|
|
module_.GetContext().NextTemp());
|
|
|
|
std::vector<ir::Value*> args1 = {masked};
|
|
builder_.CreateCallExternal("putint", ir::Type::GetVoidType(), args1, "");
|
|
std::vector<ir::Value*> args2 = {nl};
|
|
builder_.CreateCallExternal("putch", ir::Type::GetVoidType(), args2, "");
|
|
}
|
|
builder_.CreateRet(v);
|
|
} else {
|
|
builder_.CreateRetVoid();
|
|
}
|
|
return BlockFlow::Terminated;
|
|
}
|
|
|
|
// ── break ────────────────────────────────────────────────────────────────────
|
|
if (ctx->Break()) {
|
|
if (loop_stack_.empty()) {
|
|
throw std::runtime_error(FormatError("irgen", "break 在循环外"));
|
|
}
|
|
builder_.CreateBr(loop_stack_.back().after_bb);
|
|
return BlockFlow::Terminated;
|
|
}
|
|
|
|
// ── continue ─────────────────────────────────────────────────────────────────
|
|
if (ctx->Continue()) {
|
|
if (loop_stack_.empty()) {
|
|
throw std::runtime_error(FormatError("irgen", "continue 在循环外"));
|
|
}
|
|
builder_.CreateBr(loop_stack_.back().cond_bb);
|
|
return BlockFlow::Terminated;
|
|
}
|
|
|
|
// ── 赋值 lVar = exp ──────────────────────────────────────────────────────────
|
|
if (ctx->lVar() && ctx->Assign()) {
|
|
ir::Value* rhs = EvalExpr(*ctx->exp());
|
|
ir::Value* addr = EvalLVarAddr(ctx->lVar());
|
|
// Coerce rhs to match slot type
|
|
if (addr->IsPtrInt32() && rhs->IsFloat32()) {
|
|
rhs = ToInt(rhs);
|
|
} else if (addr->IsPtrFloat32() && rhs->IsInt32()) {
|
|
rhs = ToFloat(rhs);
|
|
} else if (addr->IsPtrInt32() && rhs->IsInt1()) {
|
|
rhs = ToI32(rhs);
|
|
}
|
|
builder_.CreateStore(rhs, addr);
|
|
return BlockFlow::Continue;
|
|
}
|
|
|
|
// ── 纯表达式语句 (exp)? ; ────────────────────────────────────────────────────
|
|
if (ctx->Semi() && !ctx->Return() && !ctx->If() && !ctx->While() &&
|
|
!ctx->Break() && !ctx->Continue() && !ctx->Assign()) {
|
|
if (ctx->exp()) {
|
|
EvalExpr(*ctx->exp());
|
|
}
|
|
return BlockFlow::Continue;
|
|
}
|
|
|
|
// ── if ───────────────────────────────────────────────────────────────────────
|
|
if (ctx->If()) {
|
|
if (!ctx->cond()) {
|
|
throw std::runtime_error(FormatError("irgen", "if 缺少条件"));
|
|
}
|
|
|
|
auto stmts = ctx->stmt();
|
|
|
|
// Step 1: evaluate condition (may create short-circuit blocks with lower
|
|
// SSA numbers — must happen before any branch-target blocks are created).
|
|
ir::Value* cond_val = EvalCond(*ctx->cond());
|
|
|
|
// Step 2: create then_bb now (its label number will be >= all short-circuit
|
|
// block numbers allocated during EvalCond).
|
|
ir::BasicBlock* then_bb = func_->CreateBlock(
|
|
module_.GetContext().NextLabel() + ".if.then");
|
|
|
|
// Step 3: create else_bb/merge_bb as placeholders. They will be moved to
|
|
// the end of the block list after their predecessors are filled in, so the
|
|
// block ordering in the output will be correct even though their label
|
|
// numbers are allocated here (before then-body sub-blocks are created).
|
|
ir::BasicBlock* else_bb = nullptr;
|
|
ir::BasicBlock* merge_bb = nullptr;
|
|
|
|
if (stmts.size() >= 2) {
|
|
else_bb = func_->CreateBlock(module_.GetContext().NextLabel() + ".if.else");
|
|
merge_bb = func_->CreateBlock(module_.GetContext().NextLabel() + ".if.end");
|
|
} else {
|
|
merge_bb = func_->CreateBlock(module_.GetContext().NextLabel() + ".if.end");
|
|
}
|
|
|
|
// Check if current block already terminated (short-circuit may do this)
|
|
if (builder_.GetInsertBlock() && builder_.GetInsertBlock()->HasTerminator()) {
|
|
func_->MoveBlockToEnd(then_bb);
|
|
if (else_bb) func_->MoveBlockToEnd(else_bb);
|
|
func_->MoveBlockToEnd(merge_bb);
|
|
builder_.SetInsertPoint(merge_bb);
|
|
return BlockFlow::Continue;
|
|
}
|
|
|
|
if (stmts.size() >= 2) {
|
|
builder_.CreateCondBr(cond_val, then_bb, else_bb);
|
|
} else {
|
|
builder_.CreateCondBr(cond_val, then_bb, merge_bb);
|
|
}
|
|
|
|
// then 分支 — visit body (may create many sub-blocks with higher numbers)
|
|
func_->MoveBlockToEnd(then_bb);
|
|
builder_.SetInsertPoint(then_bb);
|
|
auto then_flow = VisitStmt(*stmts[0]);
|
|
if (then_flow != BlockFlow::Terminated) {
|
|
builder_.CreateBr(merge_bb);
|
|
}
|
|
|
|
// else 分支
|
|
if (else_bb) {
|
|
func_->MoveBlockToEnd(else_bb);
|
|
builder_.SetInsertPoint(else_bb);
|
|
auto else_flow = VisitStmt(*stmts[1]);
|
|
if (else_flow != BlockFlow::Terminated) {
|
|
builder_.CreateBr(merge_bb);
|
|
}
|
|
}
|
|
|
|
func_->MoveBlockToEnd(merge_bb);
|
|
builder_.SetInsertPoint(merge_bb);
|
|
return BlockFlow::Continue;
|
|
}
|
|
|
|
// ── while ────────────────────────────────────────────────────────────────────
|
|
if (ctx->While()) {
|
|
if (!ctx->cond()) {
|
|
throw std::runtime_error(FormatError("irgen", "while 缺少条件"));
|
|
}
|
|
|
|
ir::BasicBlock* cond_bb = func_->CreateBlock(
|
|
module_.GetContext().NextLabel() + ".while.cond");
|
|
|
|
// 跳转到条件块
|
|
if (!builder_.GetInsertBlock()->HasTerminator()) {
|
|
builder_.CreateBr(cond_bb);
|
|
}
|
|
|
|
// EvalCond MUST come before creating body_bb/after_bb so that
|
|
// short-circuit blocks get lower SSA numbers than the loop body blocks.
|
|
builder_.SetInsertPoint(cond_bb);
|
|
ir::Value* cond_val = EvalCond(*ctx->cond());
|
|
|
|
ir::BasicBlock* body_bb = func_->CreateBlock(
|
|
module_.GetContext().NextLabel() + ".while.body");
|
|
ir::BasicBlock* after_bb = func_->CreateBlock(
|
|
module_.GetContext().NextLabel() + ".while.end");
|
|
|
|
// 检查条件求值后是否已终结
|
|
if (!builder_.GetInsertBlock()->HasTerminator()) {
|
|
builder_.CreateCondBr(cond_val, body_bb, after_bb);
|
|
}
|
|
|
|
// 循环体(压入循环栈)
|
|
func_->MoveBlockToEnd(body_bb);
|
|
loop_stack_.push_back({cond_bb, after_bb});
|
|
builder_.SetInsertPoint(body_bb);
|
|
auto stmts = ctx->stmt();
|
|
if (!stmts.empty()) {
|
|
auto body_flow = VisitStmt(*stmts[0]);
|
|
if (body_flow != BlockFlow::Terminated) {
|
|
builder_.CreateBr(cond_bb); // 循环回跳
|
|
}
|
|
} else {
|
|
builder_.CreateBr(cond_bb);
|
|
}
|
|
loop_stack_.pop_back();
|
|
|
|
func_->MoveBlockToEnd(after_bb);
|
|
builder_.SetInsertPoint(after_bb);
|
|
return BlockFlow::Continue;
|
|
}
|
|
|
|
// ── 块语句 ───────────────────────────────────────────────────────────────────
|
|
if (ctx->block()) {
|
|
auto result = ctx->block()->accept(this);
|
|
if (result.has_value()) {
|
|
try {
|
|
auto flow = std::any_cast<BlockFlow>(result);
|
|
if (flow == BlockFlow::Terminated) return BlockFlow::Terminated;
|
|
} catch (...) {}
|
|
}
|
|
// 检查 builder 的实际状态
|
|
if (builder_.GetInsertBlock() && builder_.GetInsertBlock()->HasTerminator()) {
|
|
return BlockFlow::Terminated;
|
|
}
|
|
return BlockFlow::Continue;
|
|
}
|
|
|
|
// ── 空语句 ; ─────────────────────────────────────────────────────────────────
|
|
if (ctx->Semi()) {
|
|
return BlockFlow::Continue;
|
|
}
|
|
|
|
throw std::runtime_error(FormatError("irgen", "不支持的语句类型"));
|
|
}
|