refactor(dev): unify user-facing diagnostics

master
Lane0218 1 week ago
parent 9070775187
commit e9d7b4a058

@ -4,6 +4,7 @@
#include "SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"
void IRGenImpl::GenBlock(SysYParser::BlockContext& block) {
for (auto* item : block.blockItem()) {
@ -24,7 +25,7 @@ bool IRGenImpl::GenBlockItem(SysYParser::BlockItemContext& item) {
if (item.stmt()) {
return GenStmt(*item.stmt());
}
throw std::runtime_error("[irgen] 暂不支持的 blockItem 类型");
throw std::runtime_error(FormatError("irgen", "暂不支持的语句或声明"));
}
void IRGenImpl::GenDecl(SysYParser::DeclContext& decl) {
@ -32,13 +33,13 @@ void IRGenImpl::GenDecl(SysYParser::DeclContext& decl) {
GenVarDecl(*decl.varDecl());
return;
}
throw std::runtime_error("[irgen] 暂不支持的声明类型");
throw std::runtime_error(FormatError("irgen", "暂不支持的声明类型"));
}
void IRGenImpl::GenVarDecl(SysYParser::VarDeclContext& decl) {
const std::string name = decl.Ident()->getText();
if (locals_.find(name) != locals_.end()) {
throw std::runtime_error("[irgen] 重复定义变量: " + name);
throw std::runtime_error(FormatError("irgen", "重复定义变量: " + name));
}
auto* slot = builder_.CreateAllocaI32(ir::DefaultContext().NextTemp());
locals_[name] = slot;

@ -6,15 +6,16 @@
#include "SysYParser.h"
#include "antlr4-runtime.h"
#include "ir/IR.h"
#include "utils/Log.h"
std::unique_ptr<ir::Module> GenerateIR(antlr4::tree::ParseTree* tree) {
if (!tree) {
throw std::runtime_error("[irgen] 语法树为空");
throw std::runtime_error(FormatError("irgen", "语法树为空"));
}
auto* cu = dynamic_cast<SysYParser::CompUnitContext*>(tree);
if (!cu) {
throw std::runtime_error("[irgen] 语法树根节点不是 compUnit");
throw std::runtime_error(FormatError("irgen", "语法树根节点不是 compUnit"));
}
auto module = std::make_unique<ir::Module>();

@ -4,10 +4,11 @@
#include "SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"
ir::Value* IRGenImpl::GenExpr(SysYParser::ExpContext& expr) {
if (!expr.addExp()) {
throw std::runtime_error("[irgen] 非法表达式");
throw std::runtime_error(FormatError("irgen", "非法表达式"));
}
return GenAddExpr(*expr.addExp());
}
@ -16,7 +17,7 @@ ir::Value* IRGenImpl::GenAddExpr(SysYParser::AddExpContext& add) {
// 当前表达式层次仍是最小实现,直接贴合 addExp -> primary 的语法形状。
const auto& terms = add.primary();
if (terms.empty()) {
throw std::runtime_error("[irgen] 空加法表达式");
throw std::runtime_error(FormatError("irgen", "空加法表达式"));
}
ir::Value* acc = GenPrimary(*terms[0]);
@ -36,12 +37,12 @@ ir::Value* IRGenImpl::GenPrimary(SysYParser::PrimaryContext& primary) {
const std::string name = primary.Ident()->getText();
auto it = locals_.find(name);
if (it == locals_.end()) {
throw std::runtime_error("[irgen] 变量未找到: " + name);
throw std::runtime_error(FormatError("irgen", "变量未找到: " + name));
}
return builder_.CreateLoad(it->second, ir::DefaultContext().NextTemp());
}
if (primary.exp()) {
return GenExpr(*primary.exp());
}
throw std::runtime_error("[irgen] 暂不支持的 primary 形式");
throw std::runtime_error(FormatError("irgen", "暂不支持的表达式形式"));
}

@ -4,6 +4,7 @@
#include "SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"
namespace {
@ -11,8 +12,9 @@ void VerifyFunctionStructure(const ir::Function& func) {
// 当前 IRGen 仍是单入口、顺序生成;这里在生成结束后补一层块终结校验。
for (const auto& bb : func.blocks()) {
if (!bb || !bb->HasTerminator()) {
throw std::runtime_error("[irgen] 基本块未正确终结: " +
(bb ? bb->name() : std::string("<null>")));
throw std::runtime_error(
FormatError("irgen", "基本块未正确终结: " +
(bb ? bb->name() : std::string("<null>"))));
}
}
}
@ -24,17 +26,17 @@ IRGenImpl::IRGenImpl(ir::Module& module)
void IRGenImpl::Gen(SysYParser::CompUnitContext& cu) {
if (!cu.funcDef()) {
throw std::runtime_error("[irgen] 缺少 main 定义");
throw std::runtime_error(FormatError("irgen", "缺少 main 定义"));
}
GenFuncDef(*cu.funcDef());
}
void IRGenImpl::GenFuncDef(SysYParser::FuncDefContext& func) {
if (!func.block()) {
throw std::runtime_error("[irgen] 函数体为空");
throw std::runtime_error(FormatError("irgen", "函数体为空"));
}
if (!func.Ident()) {
throw std::runtime_error("[irgen] 缺少函数名");
throw std::runtime_error(FormatError("irgen", "缺少函数名"));
}
func_ = module_.CreateFunction(func.Ident()->getText(), ir::Type::Int32());

@ -4,18 +4,19 @@
#include "SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"
bool IRGenImpl::GenStmt(SysYParser::StmtContext& stmt) {
if (stmt.returnStmt()) {
GenReturnStmt(*stmt.returnStmt());
return true;
}
throw std::runtime_error("[irgen] 暂不支持的语句类型");
throw std::runtime_error(FormatError("irgen", "暂不支持的语句类型"));
}
void IRGenImpl::GenReturnStmt(SysYParser::ReturnStmtContext& ret) {
if (!ret.exp()) {
throw std::runtime_error("[irgen] return 缺少表达式");
throw std::runtime_error(FormatError("irgen", "return 缺少表达式"));
}
ir::Value* v = GenExpr(*ret.exp());
builder_.CreateRet(v);

@ -28,7 +28,7 @@ int main(int argc, char** argv) {
auto* comp_unit = dynamic_cast<SysYParser::CompUnitContext*>(antlr.tree);
if (!comp_unit) {
throw std::runtime_error("[main] 语法树根节点不是 compUnit");
throw std::runtime_error(FormatError("main", "语法树根节点不是 compUnit"));
}
RunSema(*comp_unit);

@ -3,6 +3,8 @@
#include <stdexcept>
#include <vector>
#include "utils/Log.h"
namespace mir {
namespace {
@ -17,8 +19,7 @@ void RunFrameLowering(MachineFunction& function) {
for (const auto& slot : function.frame_slots()) {
cursor += slot.size;
if (-cursor < -256) {
throw std::runtime_error(
"Lab3 MVP 后端暂不支持超过 64 个 i32 栈槽的函数");
throw std::runtime_error(FormatError("mir", "暂不支持过大的栈帧"));
}
}

@ -4,6 +4,7 @@
#include <unordered_map>
#include "ir/IR.h"
#include "utils/Log.h"
namespace mir {
namespace {
@ -20,8 +21,8 @@ void EmitValueToReg(const ir::Value* value, PhysReg target,
auto it = slots.find(value);
if (it == slots.end()) {
throw std::runtime_error("Lab3 MVP 后端找不到值对应的栈槽: " +
value->name());
throw std::runtime_error(
FormatError("mir", "找不到值对应的栈槽: " + value->name()));
}
block.Append(Opcode::LoadStack,
@ -41,7 +42,8 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
auto& store = static_cast<const ir::StoreInst&>(inst);
auto dst = slots.find(store.ptr());
if (dst == slots.end()) {
throw std::runtime_error("Lab3 MVP 后端要求 store 目标必须来自 alloca");
throw std::runtime_error(
FormatError("mir", "暂不支持对非栈变量地址进行写入"));
}
EmitValueToReg(store.value(), PhysReg::W8, slots, block);
block.Append(Opcode::StoreStack,
@ -52,7 +54,8 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
auto& load = static_cast<const ir::LoadInst&>(inst);
auto src = slots.find(load.ptr());
if (src == slots.end()) {
throw std::runtime_error("Lab3 MVP 后端要求 load 源必须来自 alloca");
throw std::runtime_error(
FormatError("mir", "暂不支持对非栈变量地址进行读取"));
}
int dst_slot = function.CreateFrameIndex();
block.Append(Opcode::LoadStack,
@ -83,10 +86,10 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
}
case ir::Opcode::Sub:
case ir::Opcode::Mul:
throw std::runtime_error("Lab3 MVP 后端暂不支持 add 以外的二元运算");
throw std::runtime_error(FormatError("mir", "暂不支持该二元运算"));
}
throw std::runtime_error("Lab3 MVP 后端遇到未知 IR 指令");
throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令"));
}
} // namespace
@ -95,19 +98,19 @@ std::unique_ptr<MachineFunction> LowerToMIR(const ir::Module& module) {
DefaultContext();
if (module.functions().size() != 1) {
throw std::runtime_error("Lab3 MVP 后端只支持单函数 main");
throw std::runtime_error(FormatError("mir", "暂不支持多个函数"));
}
const auto& func = *module.functions().front();
if (func.name() != "main") {
throw std::runtime_error("Lab3 MVP 后端只支持 main 函数");
throw std::runtime_error(FormatError("mir", "暂不支持非 main 函数"));
}
auto machine_func = std::make_unique<MachineFunction>(func.name());
ValueSlotMap slots;
const auto* entry = func.entry();
if (!entry) {
throw std::runtime_error("IR 函数缺少入口基本块");
throw std::runtime_error(FormatError("mir", "IR 函数缺少入口基本块"));
}
for (const auto& inst : entry->instructions()) {

@ -2,6 +2,8 @@
#include <stdexcept>
#include "utils/Log.h"
namespace mir {
namespace {
@ -24,7 +26,7 @@ void RunRegAlloc(MachineFunction& function) {
for (const auto& inst : function.entry().instructions()) {
for (const auto& operand : inst.operands()) {
if (operand.kind() == Operand::Kind::Reg && !IsAllowedReg(operand.reg())) {
throw std::runtime_error("Lab3 MVP 后端发现未预着色的寄存器");
throw std::runtime_error(FormatError("mir", "寄存器分配失败"));
}
}
}

@ -4,6 +4,7 @@
#include <string>
#include "sem/SymbolTable.h"
#include "utils/Log.h"
namespace {
@ -18,7 +19,7 @@ void CheckPrimary(SysYParser::PrimaryContext& primary,
if (primary.Ident()) {
const std::string name = primary.Ident()->getText();
if (!table.Contains(name)) {
throw std::runtime_error("[sema] 使用了未定义的变量: " + name);
throw std::runtime_error(FormatError("sema", "使用了未定义的变量: " + name));
}
return;
}
@ -28,12 +29,12 @@ void CheckPrimary(SysYParser::PrimaryContext& primary,
return;
}
throw std::runtime_error("[sema] 暂不支持的 primary 形式");
throw std::runtime_error(FormatError("sema", "暂不支持的表达式形式"));
}
void CheckExpr(SysYParser::ExpContext& exp, const SymbolTable& table) {
if (!exp.addExp()) {
throw std::runtime_error("[sema] 非法表达式");
throw std::runtime_error(FormatError("sema", "非法表达式"));
}
const auto& terms = exp.addExp()->primary();
for (auto* term : terms) {
@ -46,10 +47,10 @@ void CheckExpr(SysYParser::ExpContext& exp, const SymbolTable& table) {
void RunSema(SysYParser::CompUnitContext& comp_unit) {
auto* func = comp_unit.funcDef();
if (!func || !func->block()) {
throw std::runtime_error("[sema] 缺少 main 函数定义");
throw std::runtime_error(FormatError("sema", "缺少 main 函数定义"));
}
if (!func->Ident() || func->Ident()->getText() != "main") {
throw std::runtime_error("[sema] 入口函数必须命名为 main");
throw std::runtime_error(FormatError("sema", "入口函数必须命名为 main"));
}
SymbolTable table;
@ -57,7 +58,8 @@ void RunSema(SysYParser::CompUnitContext& comp_unit) {
const auto& items = func->block()->blockItem();
if (items.empty()) {
throw std::runtime_error("[sema] main 函数不能为空,且必须以 return 结束");
throw std::runtime_error(
FormatError("sema", "main 函数不能为空,且必须以 return 结束"));
}
for (size_t i = 0; i < items.size(); ++i) {
@ -66,12 +68,13 @@ void RunSema(SysYParser::CompUnitContext& comp_unit) {
continue;
}
if (seen_return) {
throw std::runtime_error("[sema] return 必须是 main 函数中的最后一条语句");
throw std::runtime_error(
FormatError("sema", "return 必须是 main 函数中的最后一条语句"));
}
if (auto* decl = item->decl() ? item->decl()->varDecl() : nullptr) {
const std::string name = decl->Ident()->getText();
if (table.Contains(name)) {
throw std::runtime_error("[sema] 重复定义变量: " + name);
throw std::runtime_error(FormatError("sema", "重复定义变量: " + name));
}
if (decl->exp()) {
CheckExpr(*decl->exp(), table);
@ -84,14 +87,15 @@ void RunSema(SysYParser::CompUnitContext& comp_unit) {
CheckExpr(*ret->exp(), table);
seen_return = true;
if (i + 1 != items.size()) {
throw std::runtime_error("[sema] return 必须是 main 函数中的最后一条语句");
throw std::runtime_error(
FormatError("sema", "return 必须是 main 函数中的最后一条语句"));
}
continue;
}
throw std::runtime_error("[sema] 暂不支持的 blockItem 类型");
throw std::runtime_error(FormatError("sema", "暂不支持的语句或声明"));
}
if (!seen_return) {
throw std::runtime_error("[sema] main 函数必须包含 return 语句");
throw std::runtime_error(FormatError("sema", "main 函数必须包含 return 语句"));
}
}

Loading…
Cancel
Save