优化ir
This commit is contained in:
parent
f886933d7c
commit
e6bf9ecd12
@ -1,193 +0,0 @@
|
||||
package org.jcnc.snow.compiler.builder;
|
||||
|
||||
import org.jcnc.snow.compiler.ir.core.IRFunction;
|
||||
import org.jcnc.snow.compiler.ir.core.IROp;
|
||||
import org.jcnc.snow.compiler.ir.core.IRProgram;
|
||||
import org.jcnc.snow.compiler.ir.instr.BinOpInstruction;
|
||||
import org.jcnc.snow.compiler.ir.instr.LoadConstInstruction;
|
||||
import org.jcnc.snow.compiler.ir.instr.ReturnInstruction;
|
||||
import org.jcnc.snow.compiler.ir.value.Constant;
|
||||
import org.jcnc.snow.compiler.ir.value.VirtualRegister;
|
||||
import org.jcnc.snow.compiler.parser.ast.*;
|
||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||
import org.jcnc.snow.compiler.parser.ast.base.Node;
|
||||
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* BasicIRBuilder 类 —— 负责将 AST(抽象语法树)转换为 IR(中间表示)。
|
||||
* <p>
|
||||
* 支持的功能包括:
|
||||
* <ul>
|
||||
* <li>模块(Module)到函数(Function)到语句(Statement)到表达式(Expression)的递归编译</li>
|
||||
* <li>整数字面量、变量标识符、四则运算(+ - * /)的表达式处理</li>
|
||||
* <li>变量声明、赋值、返回(return)语句的处理</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* 注意:
|
||||
* - 当前仅支持简单语言特性;
|
||||
* - 变量采用虚拟寄存器(VirtualRegister)建模,未来可扩展 SSA。
|
||||
*/
|
||||
public final class BasicIRBuilder {
|
||||
|
||||
/* ───────────────── 顶层 API ───────────────── */
|
||||
|
||||
/**
|
||||
* 当前作用域中,变量名 -> 虚拟寄存器(VirtualRegister)的映射
|
||||
*/
|
||||
private final Map<String, VirtualRegister> variables = new HashMap<>();
|
||||
|
||||
/* ───────────────── 内部实现 ───────────────── */
|
||||
/**
|
||||
* 当前正在构建的 IRFunction 实例
|
||||
*/
|
||||
private IRFunction currentFn;
|
||||
|
||||
/**
|
||||
* 将一组顶层 AST 节点(模块、函数、语句)编译为 IRProgram。
|
||||
*
|
||||
* @param roots AST 根节点列表
|
||||
* @return 编译生成的 IRProgram 对象
|
||||
*/
|
||||
public IRProgram buildProgram(List<Node> roots) {
|
||||
IRProgram prog = new IRProgram(); // 创建新的 IRProgram
|
||||
for (Node node : roots) dispatchTop(node, prog); // 依次处理所有顶层节点
|
||||
return prog;
|
||||
}
|
||||
|
||||
/* ─────────────── 函数体级别状态 ─────────────── */
|
||||
|
||||
/**
|
||||
* 处理单个顶层节点。
|
||||
* 可能是:模块(ModuleNode)、函数(FunctionNode)、单条语句(StatementNode)。
|
||||
*
|
||||
* @param node AST 顶层节点
|
||||
* @param irProgram 正在构建的 IRProgram
|
||||
*/
|
||||
private void dispatchTop(Node node, IRProgram irProgram) {
|
||||
switch (node) {
|
||||
case ModuleNode moduleNode ->
|
||||
moduleNode.functions().forEach(functionNode -> dispatchTop(functionNode, irProgram)); // 递归处理模块内的函数
|
||||
case FunctionNode functionNode ->
|
||||
irProgram.add(buildFunction(functionNode)); // 将函数编译成 IRFunction 并加入 IRProgram
|
||||
case StatementNode _ -> {
|
||||
//TODO 单条语句(如脚本式 main)
|
||||
}
|
||||
default -> throw new IllegalStateException("不支持的顶级节点: " + node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将一个 FunctionNode 编译成 IRFunction。
|
||||
*
|
||||
* @param functionNode AST 中的函数节点
|
||||
* @return 生成的 IRFunction
|
||||
*/
|
||||
private IRFunction buildFunction(FunctionNode functionNode) {
|
||||
currentFn = new IRFunction(functionNode.name()); // 创建新 IRFunction
|
||||
variables.clear(); // 清空变量表(每个函数独立)
|
||||
|
||||
// 将函数参数映射为新的寄存器(未进一步使用参数,但保留未来拓展空间)
|
||||
for (ParameterNode parameterNode : functionNode.parameters()) {
|
||||
variables.put(parameterNode.name(), currentFn.newRegister());
|
||||
}
|
||||
|
||||
// 编译函数体中的每条语句
|
||||
for (StatementNode statementNode : functionNode.body()) stmt(statementNode);
|
||||
|
||||
return currentFn;
|
||||
}
|
||||
|
||||
/* ─── 处理语句 ─── */
|
||||
|
||||
/**
|
||||
* 编译单个语句节点为 IR 指令。
|
||||
*
|
||||
* @param statementNode 语句 AST 节点
|
||||
*/
|
||||
private void stmt(StatementNode statementNode) {
|
||||
switch (statementNode) {
|
||||
case ExpressionStatementNode expressionStatementNode ->
|
||||
expr(expressionStatementNode.expression()); // 表达式语句:只求值,无需保存
|
||||
case AssignmentNode assignmentNode -> { // 赋值语句
|
||||
VirtualRegister virtualRegister = expr(assignmentNode.value());
|
||||
variables.put(assignmentNode.variable(), virtualRegister);
|
||||
}
|
||||
case DeclarationNode declarationNode -> { // 变量声明
|
||||
if (declarationNode.getInitializer().isPresent()) { // 有初始化器
|
||||
VirtualRegister virtualRegister = expr(declarationNode.getInitializer().get());
|
||||
variables.put(declarationNode.getName(), virtualRegister);
|
||||
} else { // 无初始化器,分配空寄存器
|
||||
variables.put(declarationNode.getName(), currentFn.newRegister());
|
||||
}
|
||||
}
|
||||
case ReturnNode returnNode -> { // 返回语句
|
||||
if (returnNode.getExpression().isPresent())
|
||||
currentFn.add(new ReturnInstruction(expr(returnNode.getExpression().get())));
|
||||
else currentFn.add(new ReturnInstruction(null));
|
||||
}
|
||||
default -> throw new IllegalStateException("不支持的语句: " + statementNode);
|
||||
}
|
||||
}
|
||||
|
||||
/* ─── 处理表达式 ─── */
|
||||
|
||||
/**
|
||||
* 编译单个表达式节点,结果保存在一个新的寄存器中。
|
||||
*
|
||||
* @param expressionNode 表达式 AST 节点
|
||||
* @return 保存结果的虚拟寄存器
|
||||
*/
|
||||
private VirtualRegister expr(ExpressionNode expressionNode) {
|
||||
return switch (expressionNode) {
|
||||
case BinaryExpressionNode binaryExpressionNode -> bin(binaryExpressionNode); // 二元运算
|
||||
case NumberLiteralNode numberLiteralNode -> number(numberLiteralNode); // 数字字面量
|
||||
case IdentifierNode identifierNode -> { // 变量引用
|
||||
VirtualRegister virtualRegister = variables.get(identifierNode.name());
|
||||
if (virtualRegister == null)
|
||||
throw new IllegalStateException("变量 " + identifierNode.name() + " 未定义");
|
||||
yield virtualRegister;
|
||||
}
|
||||
default -> throw new IllegalStateException("不支持的表达式: " + expressionNode);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 二元运算表达式(如加减乘除)。
|
||||
*
|
||||
* @param b 二元表达式节点
|
||||
* @return 保存结果的寄存器
|
||||
*/
|
||||
private VirtualRegister bin(BinaryExpressionNode b) {
|
||||
VirtualRegister l = expr(b.left()); // 左操作数
|
||||
VirtualRegister r = expr(b.right()); // 右操作数
|
||||
VirtualRegister d = currentFn.newRegister(); // 结果寄存器
|
||||
|
||||
// 选择对应的 IR 操作符
|
||||
IROp op = switch (b.operator()) {
|
||||
case "+" -> IROp.ADD_I32;
|
||||
case "-" -> IROp.SUB_I32;
|
||||
case "*" -> IROp.MUL_I32;
|
||||
case "/" -> IROp.DIV_I32;
|
||||
default -> throw new IllegalStateException("未知运算符 " + b.operator());
|
||||
};
|
||||
|
||||
currentFn.add(new BinOpInstruction(op, d, l, r)); // 添加二元运算指令
|
||||
return d;
|
||||
}
|
||||
|
||||
/**
|
||||
* 编译一个整数字面量。
|
||||
*
|
||||
* @param numberLiteralNode 数字字面量节点
|
||||
* @return 保存常量的寄存器
|
||||
*/
|
||||
private VirtualRegister number(NumberLiteralNode numberLiteralNode) {
|
||||
VirtualRegister virtualRegister = currentFn.newRegister(); // 分配一个新的寄存器
|
||||
currentFn.add(new LoadConstInstruction(virtualRegister, new Constant(Integer.parseInt(numberLiteralNode.value())))); // 加载常量指令
|
||||
return virtualRegister;
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
package org.jcnc.snow.compiler.cli;
|
||||
|
||||
import org.jcnc.snow.compiler.builder.BasicIRBuilder;
|
||||
import org.jcnc.snow.compiler.ir.builder.ProgramBuilder;
|
||||
import org.jcnc.snow.compiler.ir.core.IRProgram;
|
||||
import org.jcnc.snow.compiler.lexer.core.LexerEngine;
|
||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||
@ -50,10 +50,11 @@ public class SnowCompiler {
|
||||
SemanticAnalyzerRunner.runSemanticAnalysis(ast, false);
|
||||
|
||||
/* 4. AST → IRProgram */
|
||||
IRProgram program = new BasicIRBuilder().buildProgram(ast);
|
||||
IRProgram program = new ProgramBuilder().buildProgram(ast);
|
||||
System.out.println("=== IR ===");
|
||||
System.out.println(program);
|
||||
|
||||
|
||||
/* 5. 后端:寄存器分配 & 代码生成 + VM 执行 */
|
||||
// for (IRFunction fn : program.functions()) {
|
||||
// var alloc = new RegisterAllocator();
|
||||
|
||||
@ -0,0 +1,145 @@
|
||||
package org.jcnc.snow.compiler.ir.builder;
|
||||
|
||||
import org.jcnc.snow.compiler.ir.core.IRFunction;
|
||||
import org.jcnc.snow.compiler.ir.core.IROp;
|
||||
import org.jcnc.snow.compiler.ir.instr.BinOpInstruction;
|
||||
import org.jcnc.snow.compiler.ir.instr.LoadConstInstruction;
|
||||
import org.jcnc.snow.compiler.ir.instr.ReturnInstruction;
|
||||
import org.jcnc.snow.compiler.ir.value.Constant;
|
||||
import org.jcnc.snow.compiler.ir.value.VirtualRegister;
|
||||
import org.jcnc.snow.compiler.parser.ast.*;
|
||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
||||
|
||||
/**
|
||||
* FunctionBuilder 负责将 AST 中的 FunctionNode 构建为 IRFunction。
|
||||
*
|
||||
* <p>构建流程:
|
||||
* <ol>
|
||||
* <li>创建 IRFunction 并绑定到作用域;</li>
|
||||
* <li>将函数参数声明为虚拟寄存器;</li>
|
||||
* <li>遍历函数体中的语句,生成对应的 IR 指令。</li>
|
||||
* </ol>
|
||||
*/
|
||||
final class FunctionBuilder {
|
||||
|
||||
/** 当前正在构建的 IRFunction 实例 */
|
||||
private IRFunction fn;
|
||||
|
||||
/** 管理变量名到虚拟寄存器的映射 */
|
||||
private final Scope scope = new Scope();
|
||||
|
||||
/**
|
||||
* 将给定的 FunctionNode 转换为 IRFunction。
|
||||
*
|
||||
* @param node 要转换的函数节点
|
||||
* @return 构建完成的 IRFunction
|
||||
*/
|
||||
IRFunction build(FunctionNode node) {
|
||||
fn = new IRFunction(node.name());
|
||||
scope.attachFunction(fn);
|
||||
for (ParameterNode p : node.parameters()) {
|
||||
scope.declare(p.name());
|
||||
}
|
||||
for (StatementNode s : node.body()) {
|
||||
stmt(s);
|
||||
}
|
||||
return fn;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理不同类型的语句节点,并生成相应的 IR 指令。
|
||||
*
|
||||
* @param s 要处理的语句节点
|
||||
*/
|
||||
private void stmt(StatementNode s) {
|
||||
switch (s) {
|
||||
case ExpressionStatementNode(ExpressionNode expression) ->
|
||||
// 处理表达式语句,无需保存结果
|
||||
expr(expression);
|
||||
case AssignmentNode(String variable, ExpressionNode value) -> {
|
||||
// 处理赋值语句:计算右侧表达式并赋值
|
||||
VirtualRegister result = expr(value);
|
||||
if (scope.lookup(variable) == null) {
|
||||
scope.declare(variable, result);
|
||||
} else {
|
||||
scope.put(variable, result);
|
||||
}
|
||||
}
|
||||
case DeclarationNode d -> {
|
||||
// 处理声明语句,可能带初始化
|
||||
if (d.getInitializer().isPresent()) {
|
||||
scope.declare(d.getName(), expr(d.getInitializer().get()));
|
||||
} else {
|
||||
scope.declare(d.getName());
|
||||
}
|
||||
}
|
||||
case ReturnNode r -> {
|
||||
// 处理返回语句,区分是否带返回值
|
||||
if (r.getExpression().isPresent()) {
|
||||
fn.add(new ReturnInstruction(expr(r.getExpression().get())));
|
||||
} else {
|
||||
fn.add(new ReturnInstruction(null));
|
||||
}
|
||||
}
|
||||
case null, default -> throw new IllegalStateException("Unsupported statement: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据表达式类型生成对应的 IR 值,并返回结果寄存器。
|
||||
*
|
||||
* @param e 要处理的表达式节点
|
||||
* @return 存放表达式结果的虚拟寄存器
|
||||
*/
|
||||
private VirtualRegister expr(ExpressionNode e) {
|
||||
if (e instanceof NumberLiteralNode num) {
|
||||
return number(num);
|
||||
} else if (e instanceof IdentifierNode(String name)) {
|
||||
// 处理变量引用,从作用域获取寄存器
|
||||
VirtualRegister vr = scope.lookup(name);
|
||||
if (vr == null) {
|
||||
throw new IllegalStateException("Undefined variable " + name);
|
||||
}
|
||||
return vr;
|
||||
} else if (e instanceof BinaryExpressionNode bin) {
|
||||
return bin(bin);
|
||||
}
|
||||
throw new IllegalStateException("Unsupported expression: " + e);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成加载数值常量的指令。
|
||||
*
|
||||
* @param n 数字字面量节点
|
||||
* @return 存放常量的虚拟寄存器
|
||||
*/
|
||||
private VirtualRegister number(NumberLiteralNode n) {
|
||||
VirtualRegister vr = fn.newRegister();
|
||||
fn.add(new LoadConstInstruction(vr, new Constant(Integer.parseInt(n.value()))));
|
||||
return vr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成二元运算指令,并返回结果寄存器。
|
||||
*
|
||||
* @param b 二元表达式节点
|
||||
* @return 存放运算结果的虚拟寄存器
|
||||
*/
|
||||
private VirtualRegister bin(BinaryExpressionNode b) {
|
||||
VirtualRegister l = expr(b.left());
|
||||
VirtualRegister r = expr(b.right());
|
||||
VirtualRegister d = fn.newRegister();
|
||||
|
||||
IROp op = switch (b.operator()) {
|
||||
case "+" -> IROp.ADD_I32;
|
||||
case "-" -> IROp.SUB_I32;
|
||||
case "*" -> IROp.MUL_I32;
|
||||
case "/" -> IROp.DIV_I32;
|
||||
default -> throw new IllegalStateException("Unknown operator " + b.operator());
|
||||
};
|
||||
|
||||
fn.add(new BinOpInstruction(op, d, l, r));
|
||||
return d;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,82 @@
|
||||
package org.jcnc.snow.compiler.ir.builder;
|
||||
|
||||
import org.jcnc.snow.compiler.ir.core.IRFunction;
|
||||
import org.jcnc.snow.compiler.ir.core.IRProgram;
|
||||
import org.jcnc.snow.compiler.parser.ast.FunctionNode;
|
||||
import org.jcnc.snow.compiler.parser.ast.ModuleNode;
|
||||
import org.jcnc.snow.compiler.parser.ast.base.Node;
|
||||
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ProgramBuilder 用于将 AST 根节点列表构建为 IRProgram。
|
||||
*
|
||||
* <p>功能:
|
||||
* <ul>
|
||||
* <li>遍历顶层节点,识别模块、函数或顶层语句;</li>
|
||||
* <li>将函数节点转换为 IRFunction 并添加到 IRProgram;</li>
|
||||
* <li>对脚本式顶层语句自动包装为特殊的 _start 函数。</li>
|
||||
* </ul>
|
||||
*/
|
||||
public final class ProgramBuilder {
|
||||
|
||||
/**
|
||||
* 构建一个完整的 IRProgram。
|
||||
*
|
||||
* @param roots AST 根节点列表,可包含 ModuleNode、FunctionNode 或 StatementNode
|
||||
* @return 构建好的 IRProgram 实例
|
||||
* @throws IllegalStateException 当遇到不支持的顶层节点时抛出
|
||||
*/
|
||||
public IRProgram buildProgram(List<Node> roots) {
|
||||
IRProgram prog = new IRProgram();
|
||||
for (Node n : roots) {
|
||||
if (n instanceof ModuleNode m) {
|
||||
// 模块节点:将模块内的所有函数加入程序
|
||||
m.functions().forEach(f -> prog.add(buildFunction(f)));
|
||||
} else if (n instanceof FunctionNode f) {
|
||||
// 顶层函数节点
|
||||
prog.add(buildFunction(f));
|
||||
} else if (n instanceof StatementNode s) {
|
||||
// 顶层脚本语句,包装为 _start 函数
|
||||
prog.add(buildFunction(wrapTopLevel(s)));
|
||||
} else {
|
||||
throw new IllegalStateException("Unsupported top-level node: " + n);
|
||||
}
|
||||
}
|
||||
return prog;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 FunctionBuilder 构建 IRFunction。
|
||||
*
|
||||
* @param fn AST 中的 FunctionNode
|
||||
* @return 构建完成的 IRFunction
|
||||
*/
|
||||
private IRFunction buildFunction(FunctionNode fn) {
|
||||
return new FunctionBuilder().build(fn);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将顶层脚本式语句包装为名为 _start 的 FunctionNode。
|
||||
*
|
||||
* <p>构造参数说明:
|
||||
* <ul>
|
||||
* <li>函数名固定为 "_start";</li>
|
||||
* <li>返回类型设为 null,表示类型推断或默认处理;</li>
|
||||
* <li>参数列表为空;</li>
|
||||
* <li>函数体仅包含给定的单条语句。</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param stmt 要包装的顶层语句节点
|
||||
* @return 新建的 FunctionNode
|
||||
*/
|
||||
private FunctionNode wrapTopLevel(StatementNode stmt) {
|
||||
return new FunctionNode(
|
||||
"_start",
|
||||
null,
|
||||
String.valueOf(List.of()),
|
||||
List.of(stmt)
|
||||
);
|
||||
}
|
||||
}
|
||||
77
src/main/java/org/jcnc/snow/compiler/ir/builder/Scope.java
Normal file
77
src/main/java/org/jcnc/snow/compiler/ir/builder/Scope.java
Normal file
@ -0,0 +1,77 @@
|
||||
package org.jcnc.snow.compiler.ir.builder;
|
||||
|
||||
import org.jcnc.snow.compiler.ir.core.IRFunction;
|
||||
import org.jcnc.snow.compiler.ir.value.VirtualRegister;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Scope 用于管理单个函数的变量名与虚拟寄存器的映射。
|
||||
*
|
||||
* <p>功能:
|
||||
* <ul>
|
||||
* <li>维护变量声明后的寄存器分配;</li>
|
||||
* <li>支持将已有寄存器与变量重新绑定;</li>
|
||||
* <li>根据变量名查找对应的虚拟寄存器。</li>
|
||||
* </ul>
|
||||
*/
|
||||
final class Scope {
|
||||
|
||||
/** 存储变量名到 VirtualRegister 的映射 */
|
||||
private final Map<String, VirtualRegister> vars = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 当前作用域所属的 IRFunction,用于分配新的寄存器。
|
||||
*/
|
||||
private IRFunction fn;
|
||||
|
||||
/**
|
||||
* 关联一个 IRFunction 到当前作用域,用于后续寄存器分配。
|
||||
*
|
||||
* @param fn 要绑定的 IRFunction 实例
|
||||
*/
|
||||
void attachFunction(IRFunction fn) {
|
||||
this.fn = fn;
|
||||
}
|
||||
|
||||
/**
|
||||
* 声明一个新变量,并为其分配一个新的虚拟寄存器。
|
||||
*
|
||||
* @param name 变量名
|
||||
*/
|
||||
void declare(String name) {
|
||||
VirtualRegister reg = fn.newRegister();
|
||||
vars.put(name, reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 声明或导入一个已有寄存器到当前作用域。
|
||||
*
|
||||
* @param name 变量名
|
||||
* @param reg 对应的虚拟寄存器
|
||||
*/
|
||||
void declare(String name, VirtualRegister reg) {
|
||||
vars.put(name, reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新已声明变量对应的虚拟寄存器。
|
||||
*
|
||||
* @param name 变量名
|
||||
* @param reg 新的虚拟寄存器
|
||||
*/
|
||||
void put(String name, VirtualRegister reg) {
|
||||
vars.put(name, reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据变量名查找其对应的虚拟寄存器。
|
||||
*
|
||||
* @param name 变量名
|
||||
* @return 对应的 VirtualRegister,若未声明则返回 null
|
||||
*/
|
||||
VirtualRegister lookup(String name) {
|
||||
return vars.get(name);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user