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/include/irgen/IRGen.h

101 lines
4.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.

// 将语法树翻译为 IR。
// 实现拆分在 IRGenFunc/IRGenStmt/IRGenExp/IRGenDecl。
#pragma once
#include <any>
#include <memory>
#include <string>
#include <vector>
#include <unordered_map>
#include "antlr4/SysYBaseVisitor.h"
#include "antlr4/SysYParser.h"
#include "ir/IR.h"
#include "sem/Sema.h"
// 前向声明:语义层可能在未来提供更明确的符号类型,用于把符号唯一标识映射到 IR 对象。
struct SemanticVarSymbol;
struct SemanticFuncSymbol;
namespace ir {
class Module;
class Function;
class IRBuilder;
class Value;
}
class IRGenImpl final : public SysYBaseVisitor {
public:
IRGenImpl(ir::Module& module, const SemanticContext& sema);
std::any visitCompUnit(SysYParser::CompUnitContext* ctx) override;
std::any visitFuncDef(SysYParser::FuncDefContext* ctx) override;
std::any visitBlockStmt(SysYParser::BlockStmtContext* ctx) override;
std::any visitBlockItem(SysYParser::BlockItemContext* ctx) override;
std::any visitDecl(SysYParser::DeclContext* ctx) override;
std::any visitVarDecl(SysYParser::VarDeclContext* ctx) override;
std::any visitStmt(SysYParser::StmtContext* ctx) override;
std::any visitVarDef(SysYParser::VarDefContext* ctx) override;
std::any visitReturnStmt(SysYParser::ReturnStmtContext* ctx) override;
std::any visitExp(SysYParser::ExpContext* ctx) override;
std::any visitCond(SysYParser::CondContext* ctx) override;
std::any visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) override;
std::any visitNumber(SysYParser::NumberContext* ctx) override;
std::any visitLValue(SysYParser::LValueContext* ctx) override;
std::any visitUnaryExp(SysYParser::UnaryExpContext* ctx) override;
std::any visitMulExp(SysYParser::MulExpContext* ctx) override;
std::any visitAddExp(SysYParser::AddExpContext* ctx) override;
std::any visitRelExp(SysYParser::RelExpContext* ctx) override;
std::any visitEqExp(SysYParser::EqExpContext* ctx) override;
std::any visitLAndExp(SysYParser::LAndExpContext* ctx) override;
std::any visitLOrExp(SysYParser::LOrExpContext* ctx) override;
// 辅助接口:数组下标地址计算与全局变量生成
ir::Value* EmitArrayIndex(ir::Value* base_ptr, SysYParser::ExpContext* idx_expr);
void EmitGlobalVariable(SysYParser::VarDefContext* ctx);
private:
enum class BlockFlow {
Continue,
Terminated,
};
struct LoopTargets {
ir::BasicBlock* continue_target;
ir::BasicBlock* break_target;
};
BlockFlow VisitBlockItemResult(SysYParser::BlockItemContext& item);
ir::Value* EvalExpr(SysYParser::ExpContext& expr);
ir::Value* EvalCond(SysYParser::CondContext& cond);
ir::Value* ToBoolValue(ir::Value* v);
ir::Value* FindInScope(const std::string& name);
std::string NextBlockName();
ir::Function* FindFunctionByName(const std::string& name);
ir::Value* ResolveLValueAddress(SysYParser::LValueContext* ctx);
ir::Module& module_;
const SemanticContext& sema_;
ir::Function* func_;
ir::IRBuilder builder_;
bool in_function_ = false;
// 当前函数的参数对应的栈槽位(在函数入口处为每个形参分配的 alloca
std::vector<ir::Value*> param_slots_;
// 将 Sema 提供的变量符号映射到对应的存储槽位(避免仅按名字查找)
std::unordered_map<const SemanticVarSymbol*, ir::Value*> symbol_storage_map_;
// 将 Sema 提供的函数符号映射到已创建的 IR 函数对象
std::unordered_map<const SemanticFuncSymbol*, ir::Function*> func_symbol_map_;
// 作用域栈:每个作用域维护一个从名称到存储槽位的映射
std::vector<std::unordered_map<std::string, ir::Value*>> scope_storage_;
// 名称绑定由 Sema 负责IRGen 只维护“声明 -> 存储槽位”的代码生成状态。
std::unordered_map<SysYParser::VarDefContext*, ir::Value*> storage_map_;
// 保留按名字的映射以兼容现有代码路径,但优先使用 symbol_storage_map_
std::unordered_map<std::string, ir::Value*> named_storage_;
std::vector<LoopTargets> loop_stack_;
};
std::unique_ptr<ir::Module> GenerateIR(SysYParser::CompUnitContext& tree,
const SemanticContext& sema);