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.

94 lines
3.4 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 <unordered_map>
#include "SysYBaseVisitor.h"
#include "SysYParser.h"
#include "ir/IR.h"
#include "sem/Sema.h"
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 visitBlock(SysYParser::BlockContext* ctx) override;
std::any visitBlockItem(SysYParser::BlockItemContext* ctx) override;
// 声明
std::any visitDecl(SysYParser::DeclContext* ctx) override;
std::any visitVarDef(SysYParser::VarDefContext* ctx) override;
// 语句
std::any visitStmt(SysYParser::StmtContext* ctx) override;
// 表达式
// 基本表达式(变量、常量、括号表达式)直接翻译为 IR 中的值;函数调用和一元运算需要特殊处理。
std::any visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) override;
// 一元表达式包括函数调用和一元运算,需要特殊处理
std::any visitUnaryExp(SysYParser::UnaryExpContext* ctx) override;
// 其他二元表达式按照优先级分层访问,最终调用 visitLVal 来处理变量访问。变量引用
std::any visitLVal(SysYParser::LValContext* ctx) override;
// 加法表达式、乘法表达式、关系表达式、相等表达式、条件表达式分别对应不同的访问函数,按照优先级分层访问,最终调用 visitLVal 来处理变量访问
std::any visitAddExp(SysYParser::AddExpContext* ctx) override;
std::any visitMulExp(SysYParser::MulExpContext* ctx) override;
std::any visitRelExp(SysYParser::RelExpContext* ctx) override;
std::any visitEqExp(SysYParser::EqExpContext* ctx) override;
std::any visitCond(SysYParser::CondContext* ctx) override;
private:
enum class BlockFlow {
Continue,
Terminated,
};
BlockFlow VisitBlockItemResult(SysYParser::BlockItemContext& item);
ir::Value* EvalExpr(SysYParser::ExpContext& expr);
ir::Value* EvalCond(SysYParser::CondContext& cond);
// 辅助函数
BlockFlow HandleReturnStmt(SysYParser::StmtContext* ctx);
BlockFlow HandleIfStmt(SysYParser::StmtContext* ctx);
BlockFlow HandleWhileStmt(SysYParser::StmtContext* ctx);
BlockFlow HandleBreakStmt(SysYParser::StmtContext* ctx);
BlockFlow HandleContinueStmt(SysYParser::StmtContext* ctx);
BlockFlow HandleAssignStmt(SysYParser::StmtContext* ctx);
ir::Module& module_;
const SemanticContext& sema_;
ir::Function* func_;
ir::IRBuilder builder_;
// 名称绑定由 Sema 负责IRGen 只维护“声明 -> 存储槽位”的代码生成状态。
std::unordered_map<SysYParser::VarDefContext*, ir::Value*> storage_map_;
std::unordered_map<std::string, ir::Value*> param_map_;
std::unordered_map<std::string, ir::Value*> global_map_;
// 循环栈,用于 break/continue
struct LoopContext {
ir::BasicBlock* condBlock;
ir::BasicBlock* bodyBlock;
ir::BasicBlock* exitBlock;
};
std::vector<LoopContext> loopStack_;
};
std::unique_ptr<ir::Module> GenerateIR(SysYParser::CompUnitContext& tree,
const SemanticContext& sema);