refactor: 优化 CALL 指令修补逻辑并调整代码结构

- 改进 patchCallFixes 方法,支持更灵活的 super 调用匹配
- 重构代码,优化记录结构和方法注释
- 增加 lastSegment 方法的注释说明
- 调整类和方法的组织结构,提高可读性
This commit is contained in:
Luke 2025-09-01 17:07:09 +08:00
parent ef956fb930
commit dc38b4e1a8

View File

@ -23,39 +23,44 @@ import java.util.*;
public final class VMProgramBuilder { public final class VMProgramBuilder {
/** /**
* 未知目标的 CALL 指令修补记录(待目标地址确定后修正) * 未解析地址的占位符便于后期批量修补
* @param index CALL 指令在 code 列表中的位置
* @param target 目标函数的全名
* @param nArgs 参数个数
*/ */
private record CallFix(int index, String target, int nArgs) {}
/**
* 未知目标的分支指令修补记录(待目标标签确定后修正)
* @param index 分支指令在 code 列表中的位置
* @param label 跳转目标标签名
*/
private record BranchFix(int index, String label) {}
/** 未解析地址的占位符,便于后期批量修补 */
private static final String PLACEHOLDER = "-1"; private static final String PLACEHOLDER = "-1";
/**
/** VM 指令列表 */ * VM 指令列表
*/
private final List<String> code = new ArrayList<>(); private final List<String> code = new ArrayList<>();
/** 槽位(寄存器)类型映射表(如 I/F...,用于类型检查或代码生成优化) */ /**
* 槽位(寄存器)类型映射表( I/F...用于类型检查或代码生成优化)
*/
private final Map<Integer, Character> slotType = new HashMap<>(); private final Map<Integer, Character> slotType = new HashMap<>();
/** 符号(函数名/标签)到指令序号的映射表 */ /**
* 符号(函数名/标签)到指令序号的映射表
*/
private final Map<String, Integer> addr = new HashMap<>(); private final Map<String, Integer> addr = new HashMap<>();
/** 所有待修补的 CALL 指令集合 */ /**
* 所有待修补的 CALL 指令集合
*/
private final List<CallFix> callFixes = new ArrayList<>(); private final List<CallFix> callFixes = new ArrayList<>();
/** 所有待修补的分支指令集合 */ /**
* 所有待修补的分支指令集合
*/
private final List<BranchFix> branchFixes = new ArrayList<>(); private final List<BranchFix> branchFixes = new ArrayList<>();
/** 当前代码指针(已生成指令的数量/下一个指令的位置) */ /**
* 当前代码指针(已生成指令的数量/下一个指令的位置)
*/
private int pc = 0; private int pc = 0;
// ============================== /**
// 槽位类型操作 * 获取符号名最后一段即最后一个 '.' 之后的名字若无 '.' 则为原名
// ============================== *
* @param sym 符号全名
* @return 简名
*/
private static String lastSegment(String sym) {
int p = sym.lastIndexOf('.');
return (p >= 0 && p < sym.length() - 1) ? sym.substring(p + 1) : sym;
}
/** /**
* 设置槽位(局部变量/虚拟寄存器)的类型前缀 * 设置槽位(局部变量/虚拟寄存器)的类型前缀
@ -67,6 +72,8 @@ public final class VMProgramBuilder {
slotType.put(slot, prefix); slotType.put(slot, prefix);
} }
// ============================== 槽位类型操作 ==============================
/** /**
* 获取槽位的类型前缀默认为 'I'(整数类型) * 获取槽位的类型前缀默认为 'I'(整数类型)
* *
@ -77,10 +84,9 @@ public final class VMProgramBuilder {
return slotType.getOrDefault(slot, 'I'); return slotType.getOrDefault(slot, 'I');
} }
// =============函数/标签声明与指令生成=================
/** /**
* 声明一个函数/标签的起始地址并尝试修补所有引用到此符号的 CALL/BRANCH * 声明一个函数/标签的起始地址并尝试修补所有引用到此符号的 CALL/BRANCH
*
* @param name 函数或标签全名 "Person.getName""loop.start" * @param name 函数或标签全名 "Person.getName""loop.start"
*/ */
public void beginFunction(String name) { public void beginFunction(String name) {
@ -89,11 +95,17 @@ public final class VMProgramBuilder {
patchBranchFixes(name); patchBranchFixes(name);
} }
/** 函数结束接口,目前无具体实现,便于将来扩展。 */ // =============函数/标签声明与指令生成=================
public void endFunction() {}
/**
* 函数结束接口目前无具体实现便于将来扩展
*/
public void endFunction() {
}
/** /**
* 添加一条 VM 指令或标签末尾':'视为标签 * 添加一条 VM 指令或标签末尾':'视为标签
*
* @param line 指令或标签 * @param line 指令或标签
*/ */
public void emit(String line) { public void emit(String line) {
@ -109,8 +121,9 @@ public final class VMProgramBuilder {
/** /**
* 添加一条 CALL 指令目标尚未声明时使用占位符并登记延迟修补 * 添加一条 CALL 指令目标尚未声明时使用占位符并登记延迟修补
* @param target 目标函数全名IR 侧生成 *
* @param nArgs 实参个数 * @param target 目标函数全名IR 侧生成
* @param nArgs 实参个数
*/ */
public void emitCall(String target, int nArgs) { public void emitCall(String target, int nArgs) {
Integer a = resolve(target); Integer a = resolve(target);
@ -166,15 +179,13 @@ public final class VMProgramBuilder {
} }
/** /**
* 对所有待修补的 CALL 指令进行补丁 * 修补所有延迟 CALL
* 匹配规则 * 匹配规则
* 1. 全限定名完全匹配 * 1. 全限定名完全匹配
* 2. 简名(最后一段)匹配 * 2. super 调用支持多构造target .super 结尾name .__init__N 结尾且前缀匹配
* 3. super 调用target .super 结尾name .__init__ 结尾 * 3. 简名匹配 __init__N
* @param name 新声明的符号名
*/ */
private void patchCallFixes(String name) { private void patchCallFixes(String name) {
// 当前函数的简名去掉前缀
String nameSimple = lastSegment(name); String nameSimple = lastSegment(name);
for (Iterator<CallFix> it = callFixes.iterator(); it.hasNext(); ) { for (Iterator<CallFix> it = callFixes.iterator(); it.hasNext(); ) {
@ -182,13 +193,20 @@ public final class VMProgramBuilder {
// 全限定名完全匹配 // 全限定名完全匹配
boolean qualifiedMatch = f.target.equals(name); boolean qualifiedMatch = f.target.equals(name);
// 简名匹配
// super 调用绑定target .supername .__init__N 且前缀匹配
boolean superMatch = false;
if (f.target.endsWith(".super") && name.contains(".__init__")) {
String tStruct = f.target.substring(0, f.target.length() - 6); // 去掉 ".super"
String nStruct = name.substring(0, name.indexOf(".__init__"));
superMatch = tStruct.equals(nStruct);
}
// 简名匹配 getName, __init__N
String targetSimple = lastSegment(f.target); String targetSimple = lastSegment(f.target);
boolean simpleMatch = targetSimple.equals(nameSimple); boolean simpleMatch = targetSimple.equals(nameSimple);
// super 调用绑定
boolean superMatch = f.target.endsWith(".super") && name.endsWith(".__init__");
if (qualifiedMatch || simpleMatch || superMatch) { if (qualifiedMatch || superMatch || simpleMatch) {
int targetAddr = addr.get(name); int targetAddr = addr.get(name);
code.set(f.index, VMOpCode.CALL + " " + targetAddr + " " + f.nArgs); code.set(f.index, VMOpCode.CALL + " " + targetAddr + " " + f.nArgs);
it.remove(); it.remove();
@ -213,12 +231,21 @@ public final class VMProgramBuilder {
} }
/** /**
* 获取符号名最后一段即最后一个 '.' 之后的名字若无 '.' 则为原名 * 未知目标的 CALL 指令修补记录(待目标地址确定后修正)
* @param sym 符号全名 *
* @return 简名 * @param index CALL 指令在 code 列表中的位置
* @param target 目标函数的全名
* @param nArgs 参数个数
*/ */
private static String lastSegment(String sym) { private record CallFix(int index, String target, int nArgs) {
int p = sym.lastIndexOf('.'); }
return (p >= 0 && p < sym.length() - 1) ? sym.substring(p + 1) : sym;
/**
* 未知目标的分支指令修补记录(待目标标签确定后修正)
*
* @param index 分支指令在 code 列表中的位置
* @param label 跳转目标标签名
*/
private record BranchFix(int index, String label) {
} }
} }