增加注释

This commit is contained in:
Luke 2025-05-11 23:05:51 +08:00
parent 48b7418b03
commit 965b1a1add
2 changed files with 81 additions and 20 deletions

View File

@ -16,7 +16,7 @@ import java.lang.reflect.Field;
import java.util.Map; import java.util.Map;
/** /**
* 为单个 {@link IRFunction} 生成对应的虚拟机指令序列 * VMCodeGenerator为单个 {@link IRFunction} 生成对应的虚拟机指令序列
* <p> * <p>
* 本类依据中间表示函数的指令列表调用 {@link VMProgramBuilder} 输出相应的 VM 操作码 * 本类依据中间表示函数的指令列表调用 {@link VMProgramBuilder} 输出相应的 VM 操作码
* 包括常量加载算术运算函数调用和返回等指令生成逻辑 * 包括常量加载算术运算函数调用和返回等指令生成逻辑

View File

@ -5,33 +5,74 @@ import org.jcnc.snow.vm.engine.VMOpCode;
import java.util.*; import java.util.*;
/** /**
* Builds a linear VM program, resolving CALL addresses even if the * 构建线性 VM 程序支持对函数调用地址的延迟解析与修补
* target function appears later. Now emits CALL &lt;addr&gt; &lt;nArgs&gt;. * <p>
* 本类在生成程序时按顺序追加指令并在定义函数入口时修补之前遇到的对该函数的调用
* 最终可产出完整的指令列表用于 VM 执行
* </p>
*/ */
public final class VMProgramBuilder { public final class VMProgramBuilder {
/**
* 记录待修补的调用信息包括指令索引目标函数名称及参数个数
*/
private record Fix(int index, String target, int nArgs) {} private record Fix(int index, String target, int nArgs) {}
/**
* 用于在目标地址未知时的占位符
*/
private static final String PLACEHOLDER = "-1"; private static final String PLACEHOLDER = "-1";
/**
* 存储生成的指令行按追加顺序对应程序计数器地址
*/
private final List<String> code = new ArrayList<>(); private final List<String> code = new ArrayList<>();
/**
* 已知函数名称到其入口地址程序计数的映射表
*/
private final Map<String, Integer> labelAddr = new HashMap<>(); private final Map<String, Integer> labelAddr = new HashMap<>();
/**
* 存放所有尚未解析目标地址的调用信息待函数定义时进行修补
*/
private final List<Fix> unresolved = new ArrayList<>(); private final List<Fix> unresolved = new ArrayList<>();
/**
* 当前程序计数器表示下一条指令的地址
*/
private int pc = 0; private int pc = 0;
/* ---------- public API ---------- */ /**
* 标记函数入口位置并即时修补之前对该函数的所有延迟调用
*
* @param name 函数名称
*/
public void beginFunction(String name) { public void beginFunction(String name) {
labelAddr.put(name, pc); labelAddr.put(name, pc);
patchFixesFor(name); patchFixesFor(name);
} }
/**
* 追加一条原始指令到程序并将程序计数器递增
*
* @param line 完整的指令文本
*/
public void emit(String line) { public void emit(String line) {
code.add(line); code.add(line);
pc++; pc++;
} }
/** Emits CALL addr nArgs (addr may be unknown yet). */ /**
* 生成函数调用指令 "CALL &lt;addr&gt; &lt;nArgs&gt;"
* <ul>
* <li>若目标函数已定义则直接使用其地址</li>
* <li>否则使用占位符并记录调用信息待后续修补</li>
* </ul>
*
* @param targetFn 目标函数名称
* @param nArgs 调用参数数量
*/
public void emitCall(String targetFn, int nArgs) { public void emitCall(String targetFn, int nArgs) {
Integer addr = resolve(targetFn); Integer addr = resolve(targetFn);
if (addr != null) { if (addr != null) {
@ -42,27 +83,47 @@ public final class VMProgramBuilder {
} }
} }
/**
* 完成指令生成并返回不可变的指令列表
*
* @return 按执行顺序排列的完整指令列表
* @throws IllegalStateException 若仍存在未修补的调用目标
*/
public List<String> build() { public List<String> build() {
if (!unresolved.isEmpty()) if (!unresolved.isEmpty()) {
throw new IllegalStateException("Unresolved CALL targets: " + unresolved); throw new IllegalStateException("Unresolved CALL targets: " + unresolved);
}
return List.copyOf(code); return List.copyOf(code);
} }
/* ---------- internal helpers ---------- */ /**
* 尝试解析给定标签对应的地址
* <p>
* 若标签包含包名 '.' 分隔则尝试匹配简单名称后缀
* </p>
*
* @param label 函数标签或全限定名称
* @return 已知地址 {@code null} 表示尚未定义
*/
private Integer resolve(String label) { private Integer resolve(String label) {
Integer a = labelAddr.get(label); Integer addr = labelAddr.get(label);
if (a == null && label.contains(".")) { if (addr == null && label.contains(".")) {
a = labelAddr.get(label.substring(label.lastIndexOf('.')+1)); String simpleName = label.substring(label.lastIndexOf('.') + 1);
addr = labelAddr.get(simpleName);
} }
return a; return addr;
} }
/**
* 修补指定函数名称对应的所有延迟调用将占位符替换为实际地址
*
* @param name 函数名称
*/
private void patchFixesFor(String name) { private void patchFixesFor(String name) {
for (Iterator<Fix> it = unresolved.iterator(); it.hasNext(); ) { for (Iterator<Fix> it = unresolved.iterator(); it.hasNext(); ) {
Fix f = it.next(); Fix fix = it.next();
if (f.target.equals(name) || f.target.endsWith("."+name)) { if (fix.target.equals(name) || fix.target.endsWith("." + name)) {
code.set(f.index, VMOpCode.CALL + " " + pc + " " + f.nArgs); code.set(fix.index, VMOpCode.CALL + " " + pc + " " + fix.nArgs);
it.remove(); it.remove();
} }
} }