增加注释
This commit is contained in:
parent
48b7418b03
commit
965b1a1add
@ -16,7 +16,7 @@ import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 为单个 {@link IRFunction} 生成对应的虚拟机指令序列。
|
||||
* VMCodeGenerator为单个 {@link IRFunction} 生成对应的虚拟机指令序列。
|
||||
* <p>
|
||||
* 本类依据中间表示函数的指令列表,调用 {@link VMProgramBuilder} 输出相应的 VM 操作码,
|
||||
* 包括常量加载、算术运算、函数调用和返回等指令生成逻辑。
|
||||
|
||||
@ -5,64 +5,125 @@ import org.jcnc.snow.vm.engine.VMOpCode;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Builds a linear VM program, resolving CALL addresses even if the
|
||||
* target function appears later. Now emits “CALL <addr> <nArgs>”.
|
||||
* 构建线性 VM 程序,支持对函数调用地址的延迟解析与修补。
|
||||
* <p>
|
||||
* 本类在生成程序时按顺序追加指令,并在定义函数入口时修补之前遇到的对该函数的调用。
|
||||
* 最终可产出完整的指令列表,用于 VM 执行。
|
||||
* </p>
|
||||
*/
|
||||
public final class VMProgramBuilder {
|
||||
|
||||
/**
|
||||
* 记录待修补的调用信息,包括指令索引、目标函数名称及参数个数。
|
||||
*/
|
||||
private record Fix(int index, String target, int nArgs) {}
|
||||
|
||||
/**
|
||||
* 用于在目标地址未知时的占位符。
|
||||
*/
|
||||
private static final String PLACEHOLDER = "-1";
|
||||
|
||||
/**
|
||||
* 存储生成的指令行,按追加顺序对应程序计数器地址。
|
||||
*/
|
||||
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 int pc = 0;
|
||||
|
||||
/* ---------- public API ---------- */
|
||||
|
||||
/**
|
||||
* 标记函数入口位置,并即时修补之前对该函数的所有延迟调用。
|
||||
*
|
||||
* @param name 函数名称
|
||||
*/
|
||||
public void beginFunction(String name) {
|
||||
labelAddr.put(name, pc);
|
||||
patchFixesFor(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 追加一条原始指令到程序,并将程序计数器递增。
|
||||
*
|
||||
* @param line 完整的指令文本
|
||||
*/
|
||||
public void emit(String line) {
|
||||
code.add(line);
|
||||
pc++;
|
||||
}
|
||||
|
||||
/** Emits CALL addr nArgs (addr may be unknown yet). */
|
||||
/**
|
||||
* 生成函数调用指令 "CALL <addr> <nArgs>"。
|
||||
* <ul>
|
||||
* <li>若目标函数已定义,则直接使用其地址;</li>
|
||||
* <li>否则使用占位符并记录调用信息,待后续修补。</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param targetFn 目标函数名称
|
||||
* @param nArgs 调用参数数量
|
||||
*/
|
||||
public void emitCall(String targetFn, int nArgs) {
|
||||
Integer addr = resolve(targetFn);
|
||||
if (addr != null) {
|
||||
emit(VMOpCode.CALL + " " + addr + " " + nArgs);
|
||||
} else {
|
||||
emit(VMOpCode.CALL + " " + PLACEHOLDER + " " + nArgs);
|
||||
unresolved.add(new Fix(pc-1, targetFn, nArgs));
|
||||
unresolved.add(new Fix(pc - 1, targetFn, nArgs));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 完成指令生成并返回不可变的指令列表。
|
||||
*
|
||||
* @return 按执行顺序排列的完整指令列表
|
||||
* @throws IllegalStateException 若仍存在未修补的调用目标
|
||||
*/
|
||||
public List<String> build() {
|
||||
if (!unresolved.isEmpty())
|
||||
throw new IllegalStateException("Unresolved CALL targets: "+unresolved);
|
||||
if (!unresolved.isEmpty()) {
|
||||
throw new IllegalStateException("Unresolved CALL targets: " + unresolved);
|
||||
}
|
||||
return List.copyOf(code);
|
||||
}
|
||||
|
||||
/* ---------- internal helpers ---------- */
|
||||
|
||||
/**
|
||||
* 尝试解析给定标签对应的地址。
|
||||
* <p>
|
||||
* 若标签包含包名(以 '.' 分隔),则尝试匹配简单名称后缀。
|
||||
* </p>
|
||||
*
|
||||
* @param label 函数标签或全限定名称
|
||||
* @return 已知地址,或 {@code null} 表示尚未定义
|
||||
*/
|
||||
private Integer resolve(String label) {
|
||||
Integer a = labelAddr.get(label);
|
||||
if (a == null && label.contains(".")) {
|
||||
a = labelAddr.get(label.substring(label.lastIndexOf('.')+1));
|
||||
Integer addr = labelAddr.get(label);
|
||||
if (addr == null && label.contains(".")) {
|
||||
String simpleName = label.substring(label.lastIndexOf('.') + 1);
|
||||
addr = labelAddr.get(simpleName);
|
||||
}
|
||||
return a;
|
||||
return addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修补指定函数名称对应的所有延迟调用,将占位符替换为实际地址。
|
||||
*
|
||||
* @param name 函数名称
|
||||
*/
|
||||
private void patchFixesFor(String name) {
|
||||
for (Iterator<Fix> it = unresolved.iterator(); it.hasNext();) {
|
||||
Fix f = it.next();
|
||||
if (f.target.equals(name) || f.target.endsWith("."+name)) {
|
||||
code.set(f.index, VMOpCode.CALL + " " + pc + " " + f.nArgs);
|
||||
for (Iterator<Fix> it = unresolved.iterator(); it.hasNext(); ) {
|
||||
Fix fix = it.next();
|
||||
if (fix.target.equals(name) || fix.target.endsWith("." + name)) {
|
||||
code.set(fix.index, VMOpCode.CALL + " " + pc + " " + fix.nArgs);
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user