diff --git a/src/main/java/org/jcnc/snow/compiler/backend/generator/CallGenerator.java b/src/main/java/org/jcnc/snow/compiler/backend/generator/CallGenerator.java
index 04dfaa1..bd49f24 100644
--- a/src/main/java/org/jcnc/snow/compiler/backend/generator/CallGenerator.java
+++ b/src/main/java/org/jcnc/snow/compiler/backend/generator/CallGenerator.java
@@ -16,40 +16,62 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
- * {@code CallGenerator} 负责将 IR 层的 {@link CallInstruction} 生成对应的 VM 层函数调用指令。
+ * CallGenerator 负责将 IR 层的 CallInstruction 转换为 VM 层的函数调用指令。
*
- * 支持 syscall、普通函数调用、一维/多维数组下标访问、以及字符串常量池绑定等功能。
- *
- *
+ * 功能包括:
*
- * - syscall: 支持字符串常量与寄存器到子命令的绑定与解析
- * - 数组下标访问: 支持所有主流基础类型 “__index_b/s/i/l/f/d/r”
- * - 普通函数: 支持自动推断返回值类型与槽位类型
+ * - 处理系统调用(syscall),支持字符串常量池
+ * - 数组元素访问及赋值(__index / __setindex 系列)
+ * - 普通函数调用,根据返回类型选择合适的 STORE 指令
*
*/
public class CallGenerator implements InstructionGenerator {
/**
- * 字符串常量池:用于绑定虚拟寄存器 id 到字符串值(供 syscall 子命令使用)。
- *
- * 使用 ConcurrentHashMap 保证并发安全,所有 registerStringConst 的注册和读取都是线程安全的。
+ * 字符串常量池,用于 syscall 子命令的字符串存储,
+ * 键为虚拟寄存器 ID,值为字符串常量。
*/
private static final Map STRING_CONST_POOL = new ConcurrentHashMap<>();
/**
- * 注册一个字符串常量,绑定到虚拟寄存器 id。
+ * 当前正在生成的函数名,用于错误上下文。
+ */
+ private String fn;
+
+ /**
+ * 注册字符串常量到常量池。
*
- * @param regId 虚拟寄存器 id
- * @param value 字符串常量
+ * @param regId 虚拟寄存器 ID
+ * @param value 字符串常量值
*/
public static void registerStringConst(int regId, String value) {
STRING_CONST_POOL.put(regId, value);
}
/**
- * 返回本生成器支持的 IR 指令类型。
+ * 将语言层类型名映射为 VM 指令的类型前缀字符。
*
- * @return {@link CallInstruction} 类型的 Class 对象
+ * @param name 类型名称,如 "int", "double", "string"
+ * @return 对应的 VM 类型前缀('I','D','R' 等)
+ */
+ private static char normalizeTypePrefix(String name) {
+ if (name == null) return 'I';
+ String n = name.toLowerCase(Locale.ROOT);
+ return switch (n) {
+ case "byte" -> 'B';
+ case "short" -> 'S';
+ case "int", "integer", "bool", "boolean" -> 'I';
+ case "long" -> 'L';
+ case "float" -> 'F';
+ case "double" -> 'D';
+ case "string" -> 'R'; // 字符串为引用类型
+ case "void" -> 'V';
+ default -> 'R'; // 结构体、自定义对象均视为引用类型
+ };
+ }
+
+ /**
+ * 返回本生成器支持的 IR 指令类型,此处为 CallInstruction。
*/
@Override
public Class supportedClass() {
@@ -57,12 +79,12 @@ public class CallGenerator implements InstructionGenerator {
}
/**
- * 生成指定的调用指令,包括 syscall、数组下标、普通函数。
+ * 核心生成方法,根据函数名分发到 syscall、数组操作或普通调用的处理逻辑。
*
- * @param ins IR 层的调用指令
- * @param out VM 程序构建器
- * @param slotMap 寄存器到槽位的映射表
- * @param currentFn 当前函数名
+ * @param ins 待转换的 IR 调用指令
+ * @param out VM 程序构建器,用于输出指令
+ * @param slotMap IR 虚拟寄存器到 VM 本地槽位的映射
+ * @param currentFn 当前所在的函数名,用于上下文传递
*/
@Override
public void generate(CallInstruction ins,
@@ -71,91 +93,41 @@ public class CallGenerator implements InstructionGenerator {
String currentFn) {
String fn = ins.getFunctionName();
- // 特殊处理 syscall 调用
+ // 处理特殊的 syscall 调用
if ("syscall".equals(fn) || fn.endsWith(".syscall")) {
generateSyscall(ins, out, slotMap, fn);
return;
}
- // 各种一维数组类型(byte/short/int/long/float/double/boolean)读取
+ // 处理数组读取和写入的内置函数
switch (fn) {
- case "__index_b" -> {
- generateIndexInstruction(ins, out, slotMap, 'B');
- return;
- }
- case "__index_s" -> {
- generateIndexInstruction(ins, out, slotMap, 'S');
- return;
- }
- case "__index_i" -> {
- generateIndexInstruction(ins, out, slotMap, 'I');
- return;
- }
- case "__index_l" -> {
- generateIndexInstruction(ins, out, slotMap, 'L');
- return;
- }
- case "__index_f" -> {
- generateIndexInstruction(ins, out, slotMap, 'F');
- return;
- }
- case "__index_d" -> {
- generateIndexInstruction(ins, out, slotMap, 'D');
- return;
- }
- case "__index_r" -> {
- generateIndexInstruction(ins, out, slotMap, 'R');
- return;
- }
-
- case "__setindex_b" -> {
- generateSetIndexInstruction(ins, out, slotMap, 'B');
- return;
- }
- case "__setindex_s" -> {
- generateSetIndexInstruction(ins, out, slotMap, 'S');
- return;
- }
- case "__setindex_i" -> {
- generateSetIndexInstruction(ins, out, slotMap, 'I');
- return;
- }
- case "__setindex_l" -> {
- generateSetIndexInstruction(ins, out, slotMap, 'L');
- return;
- }
- case "__setindex_f" -> {
- generateSetIndexInstruction(ins, out, slotMap, 'F');
- return;
- }
- case "__setindex_d" -> {
- generateSetIndexInstruction(ins, out, slotMap, 'D');
- return;
- }
- case "__setindex_r" -> {
- generateSetIndexInstruction(ins, out, slotMap, 'R');
- return;
- }
+ case "__index_b" -> { generateIndexInstruction(ins, out, slotMap, 'B'); return; }
+ case "__index_s" -> { generateIndexInstruction(ins, out, slotMap, 'S'); return; }
+ case "__index_i" -> { generateIndexInstruction(ins, out, slotMap, 'I'); return; }
+ case "__index_l" -> { generateIndexInstruction(ins, out, slotMap, 'L'); return; }
+ case "__index_f" -> { generateIndexInstruction(ins, out, slotMap, 'F'); return; }
+ case "__index_d" -> { generateIndexInstruction(ins, out, slotMap, 'D'); return; }
+ case "__index_r" -> { generateIndexInstruction(ins, out, slotMap, 'R'); return; }
+ case "__setindex_b" -> { generateSetIndexInstruction(ins, out, slotMap, 'B'); return; }
+ case "__setindex_s" -> { generateSetIndexInstruction(ins, out, slotMap, 'S'); return; }
+ case "__setindex_i" -> { generateSetIndexInstruction(ins, out, slotMap, 'I'); return; }
+ case "__setindex_l" -> { generateSetIndexInstruction(ins, out, slotMap, 'L'); return; }
+ case "__setindex_f" -> { generateSetIndexInstruction(ins, out, slotMap, 'F'); return; }
+ case "__setindex_d" -> { generateSetIndexInstruction(ins, out, slotMap, 'D'); return; }
+ case "__setindex_r" -> { generateSetIndexInstruction(ins, out, slotMap, 'R'); return; }
}
- // 普通函数调用
+ // 默认:普通函数调用
generateNormalCall(ins, out, slotMap, fn);
}
- // ========== 私有辅助方法 ==========
-
/**
- * 生成数组元素赋值指令(arr[idx] = value),无返回值。
- *
- * 调用栈压栈顺序为:arr (引用类型, R),idx (整型, I),value (元素类型, T)。
- * 执行 SYSCALL ARR_SET 指令以完成数组赋值操作。
- *
+ * 生成数组元素赋值指令。
*
- * @param ins 当前的调用指令(包含参数信息)
- * @param out VM 指令生成器(用于输出 VM 指令)
- * @param slotMap 虚拟寄存器与槽位的映射表
- * @param valType 待写入的 value 的类型标识('B': byte, 'S': short, 'I': int, 'L': long, 'F': float, 'D': double, 其余为引用类型'R')
- * @throws IllegalStateException 如果参数数量不为3,则抛出异常
+ * @param ins 调用 __setindex_* 的 IR 指令
+ * @param out VM 指令构建器
+ * @param slotMap 寄存器到槽位映射
+ * @param valType 元素值的类型前缀(如 'I','R' 等)
*/
private void generateSetIndexInstruction(CallInstruction ins,
VMProgramBuilder out,
@@ -163,88 +135,175 @@ public class CallGenerator implements InstructionGenerator {
char valType) {
List args = ins.getArguments();
if (args.size() != 3) {
- // 参数数量错误,抛出异常并输出实际参数列表
- throw new IllegalStateException(
- "[CallGenerator] __setindex_* 需要三个参数(arr, idx, value),实际: " + args);
+ throw new IllegalStateException("[CallGenerator] __setindex_* 需要三个参数 (arr, idx, value),实际: " + args);
}
-
- // 第一个参数为数组对象,压入引用类型寄存器('R'),如 arr
- loadArgument(out, slotMap, args.get(0), 'R', ins.getFunctionName());
-
- // 第二个参数为索引值,压入整型寄存器('I'),如 idx
- loadArgument(out, slotMap, args.get(1), 'I', ins.getFunctionName());
-
- // 第三个参数为待赋值元素,根据元素类型压入相应类型寄存器
- // 支持类型:'B'(byte), 'S'(short), 'I'(int), 'L'(long), 'F'(float), 'D'(double)
- // 其他情况(如引用类型),按'R'处理
- switch (valType) {
- case 'B' -> loadArgument(out, slotMap, args.get(2), 'B', ins.getFunctionName());
- case 'S' -> loadArgument(out, slotMap, args.get(2), 'S', ins.getFunctionName());
- case 'I' -> loadArgument(out, slotMap, args.get(2), 'I', ins.getFunctionName());
- case 'L' -> loadArgument(out, slotMap, args.get(2), 'L', ins.getFunctionName());
- case 'F' -> loadArgument(out, slotMap, args.get(2), 'F', ins.getFunctionName());
- case 'D' -> loadArgument(out, slotMap, args.get(2), 'D', ins.getFunctionName());
- default -> loadArgument(out, slotMap, args.get(2), 'R', ins.getFunctionName());
- }
-
- // 输出 VM 指令:SYSCALL ARR_SET,完成数组元素写入操作
- out.emit(VMOpCode.SYSCALL + " " + "ARR_SET");
+ loadArgument(out, slotMap, args.get(0), 'R', ins.getFunctionName()); // 数组引用
+ loadArgument(out, slotMap, args.get(1), 'I', ins.getFunctionName()); // 索引
+ loadArgument(out, slotMap, args.get(2), valType, ins.getFunctionName()); // 值
+ out.emit(VMOpCode.SYSCALL + " ARR_SET");
}
+ /**
+ * 生成数组元素读取指令。
+ *
+ * @param ins 调用 __index_* 的 IR 指令
+ * @param out VM 指令构建器
+ * @param slotMap 寄存器到槽位映射
+ * @param retType 返回值类型前缀
+ */
+ private void generateIndexInstruction(CallInstruction ins,
+ VMProgramBuilder out,
+ Map slotMap,
+ char retType) {
+ String fn = ins.getFunctionName();
+ List args = ins.getArguments();
+ if (args.size() != 2) {
+ throw new IllegalStateException("[CallGenerator] " + fn + " 需要两个参数 (arr, idx),实际: " + args);
+ }
+ loadArgument(out, slotMap, args.get(0), 'R', fn); // 数组引用
+ loadArgument(out, slotMap, args.get(1), 'I', fn); // 索引
+ out.emit(VMOpCode.SYSCALL + " ARR_GET");
+
+ IRVirtualRegister dest = ins.getDest();
+ if (dest == null) {
+ throw new IllegalStateException("[CallGenerator] " + fn + " 必须有返回值寄存器");
+ }
+ Integer destSlot = slotMap.get(dest);
+ if (destSlot == null) {
+ throw new IllegalStateException("[CallGenerator] " + fn + " 未找到目标槽位");
+ }
+ // 根据类型选择 STORE 指令
+ switch (retType) {
+ case 'B' -> out.emit(OpHelper.opcode("B_STORE") + " " + destSlot);
+ case 'S' -> out.emit(OpHelper.opcode("S_STORE") + " " + destSlot);
+ case 'I' -> out.emit(OpHelper.opcode("I_STORE") + " " + destSlot);
+ case 'L' -> out.emit(OpHelper.opcode("L_STORE") + " " + destSlot);
+ case 'F' -> out.emit(OpHelper.opcode("F_STORE") + " " + destSlot);
+ case 'D' -> out.emit(OpHelper.opcode("D_STORE") + " " + destSlot);
+ default -> out.emit(OpHelper.opcode("R_STORE") + " " + destSlot);
+ }
+ out.setSlotType(destSlot, retType);
+ }
/**
- * 解析 syscall 子命令(第一个参数),支持字符串常量与已绑定字符串的虚拟寄存器。
+ * 生成系统调用(syscall)指令。
+ * 首个参数为子命令,支持常量或寄存器引用;其余参数均以引用形式加载。
+ * 若存在返回寄存器,则将结果存为整数类型。
*
- * @param arg 子命令参数(应为字符串常量或寄存器)
- * @param fn 当前函数名(仅用于报错信息)
- * @return 子命令(大写字符串)
- * @throws IllegalStateException 如果参数不是字符串常量或已绑定寄存器
+ * @param ins syscall 对应的 IR 调用指令
+ * @param out VM 指令构建器
+ * @param slotMap 寄存器到槽位的映射
+ * @param fn 函数名("syscall" 或以 ".syscall" 结尾)
+ */
+ private void generateSyscall(CallInstruction ins,
+ VMProgramBuilder out,
+ Map slotMap,
+ String fn) {
+ List args = ins.getArguments();
+ if (args.isEmpty()) {
+ throw new IllegalStateException("[CallGenerator] syscall 至少需要一个子命令");
+ }
+ String subcmd = resolveSyscallSubcmd(args.get(0), fn);
+ for (int i = 1; i < args.size(); i++) {
+ loadArgument(out, slotMap, args.get(i), 'R', fn);
+ }
+ out.emit(VMOpCode.SYSCALL + " " + subcmd);
+
+ IRVirtualRegister dest = ins.getDest();
+ if (dest != null) {
+ Integer slot = slotMap.get(dest);
+ if (slot == null) throw new IllegalStateException("[CallGenerator] syscall 未找到目标槽位");
+ out.emit(OpHelper.opcode("I_STORE") + " " + slot);
+ out.setSlotType(slot, 'I');
+ }
+ }
+
+ /**
+ * 解析 syscall 子命令字符串:
+ * 若为 IRConstant,则直接取字符串值;
+ * 若为 IRVirtualRegister,则从常量池中获取。
+ * 最终返回大写子命令名称。
+ *
+ * @param arg 第一个参数,常量或虚拟寄存器
+ * @param fn 所属函数名,用于错误提示
+ * @return 大写的子命令字符串
+ * @throws IllegalStateException 参数类型或常量池缺失时抛出
*/
private String resolveSyscallSubcmd(IRValue arg, String fn) {
- switch (arg) {
- case IRConstant(String s) -> {
+ if (arg instanceof IRConstant(Object value)) {
+ if (value instanceof String s) {
return s.toUpperCase(Locale.ROOT);
}
- case IRConstant(Object value) -> throw new IllegalStateException(
- "[CallGenerator] syscall 第一个参数必须是字符串常量 (function: %s, value: %s)"
- .formatted(fn, value)
- );
- case IRVirtualRegister(int id) -> {
- String s = STRING_CONST_POOL.get(id);
- if (s == null) {
- throw new IllegalStateException(
- "[CallGenerator] 未找到 syscall 字符串常量绑定 (function: %s, regId: %d)"
- .formatted(fn, id)
- );
- }
- return s.toUpperCase(Locale.ROOT);
- }
- case null, default -> throw new IllegalStateException(
- "[CallGenerator] syscall 第一个参数必须是字符串常量或已绑定字符串的寄存器 (function: %s, arg: %s)"
- .formatted(fn, arg)
- );
+ throw new IllegalStateException("[CallGenerator] syscall 子命令必须是字符串 (函数: " + fn + ")");
}
+ if (arg instanceof IRVirtualRegister(int id)) {
+ String s = STRING_CONST_POOL.get(id);
+ if (s == null) throw new IllegalStateException("[CallGenerator] 未注册的 syscall 字符串常量");
+ return s.toUpperCase(Locale.ROOT);
+ }
+ throw new IllegalStateException("[CallGenerator] syscall 子命令参数错误: " + arg);
}
/**
- * 加载一个参数到栈,支持指定默认类型。如果未设置类型则采用默认类型。
+ * 生成普通函数调用指令:
+ * 参数均以引用形式压栈,调用完成后,若返回类型非 void,
+ * 则选择合适的 STORE 指令保存结果。
*
- * @param out VM 程序构建器
- * @param slotMap 寄存器到槽位的映射
- * @param arg 参数值(应为虚拟寄存器)
- * @param defaultType 默认类型
- * @param fn 当前函数名(用于错误提示)
- * @throws IllegalStateException 如果参数不是虚拟寄存器,或槽位未找到
+ * @param ins 调用指令
+ * @param out 指令构建器
+ * @param slotMap 寄存器到槽位映射
+ * @param fn 被调用函数名称
*/
- private void loadArgument(VMProgramBuilder out, Map slotMap, IRValue arg, char defaultType, String fn) {
+ private void generateNormalCall(CallInstruction ins,
+ VMProgramBuilder out,
+ Map slotMap,
+ String fn) {
+ String retTypeName = GlobalFunctionTable.getReturnType(fn);
+ char retType = normalizeTypePrefix(retTypeName);
+
+ for (IRValue arg : ins.getArguments()) {
+ loadArgument(out, slotMap, arg, 'R', fn);
+ }
+ out.emitCall(fn, ins.getArguments().size());
+
+ if ("void".equals(retTypeName)) {
+ return;
+ }
+ IRVirtualRegister dest = ins.getDest();
+ if (dest == null) {
+ throw new IllegalStateException("[CallGenerator] 普通调用缺少返回寄存器");
+ }
+ Integer slot = slotMap.get(dest);
+ if (slot == null) {
+ throw new IllegalStateException("[CallGenerator] 未找到返回槽位");
+ }
+ out.emit(OpHelper.opcode(retType + "_STORE") + " " + slot);
+ out.setSlotType(slot, retType);
+ }
+
+ /**
+ * 加载参数:
+ * 验证为虚拟寄存器后,获取槽位和类型,
+ * 缺省时使用 defaultType,然后发出 LOAD 指令。
+ *
+ * @param out 指令构建器
+ * @param slotMap 寄存器到槽位映射
+ * @param arg IR 参数值
+ * @param defaultType 缺省类型前缀
+ * @param fn 所属函数名,用于错误提示
+ */
+ private void loadArgument(VMProgramBuilder out,
+ Map slotMap,
+ IRValue arg,
+ char defaultType,
+ String fn) {
+ this.fn = fn;
if (!(arg instanceof IRVirtualRegister vr)) {
- throw new IllegalStateException(
- "[CallGenerator] 参数必须为虚拟寄存器 (function: %s, arg: %s)".formatted(fn, arg));
+ throw new IllegalStateException("[CallGenerator] 参数必须是 IRVirtualRegister");
}
Integer slot = slotMap.get(vr);
if (slot == null) {
- throw new IllegalStateException(
- "[CallGenerator] 未找到虚拟寄存器的槽位映射 (function: %s, reg: %s)".formatted(fn, vr));
+ throw new IllegalStateException("[CallGenerator] 未找到参数槽位");
}
char t = out.getSlotType(slot);
if (t == '\0') t = defaultType;
@@ -252,175 +311,11 @@ public class CallGenerator implements InstructionGenerator {
}
/**
- * 生成一维/多维数组的下标访问指令(支持类型分派)。
- *
- * 本方法用于将 IR 层的数组下标访问表达式(如 arr[idx]),生成对应的 VM 指令序列。
- * 支持 byte/short/int/long/float/double/reference 等所有基础类型的数组元素访问。
- *
+ * 返回最近一次处理的函数名,可用于调试。
*
- *
- * - 1. 依次加载数组参数(arr)和下标参数(idx)到操作数栈
- * - 2. 发出 ARR_GET 系统调用指令(SYSCALL ARR_GET),通过 VM 访问对应元素
- * - 3. 根据元素声明类型,将结果写入目标槽位,支持类型分派(B/S/I/L/F/D/R)
- * - 4. 若参数或返回寄存器缺失,则抛出异常提示
- *
- *
- * @param ins 下标访问对应的 IR 调用指令,函数名通常为 __index_x
- * @param out VM 程序构建器,用于发出 VM 指令
- * @param slotMap IR 虚拟寄存器到 VM 槽位的映射表
- * @param retType 元素类型标识('B' byte, 'S' short, 'I' int, 'L' long, 'F' float, 'D' double, 'R' ref/obj)
- * @throws IllegalStateException 参数个数不符、缺少目标寄存器、未找到槽位等情况
+ * @return 函数名字符串
*/
- private void generateIndexInstruction(CallInstruction ins, VMProgramBuilder out, Map slotMap, char retType) {
- String fn = ins.getFunctionName();
- List args = ins.getArguments();
- if (args.size() != 2) {
- throw new IllegalStateException(
- "[CallGenerator] %s 需要两个参数(arr, idx),实际: %s".formatted(fn, args));
- }
- // 加载数组参数(寄存器类型按 R/ref 处理,默认对象槽位)
- loadArgument(out, slotMap, args.get(0), 'R', fn);
- // 加载下标参数(寄存器类型按 I/int 处理)
- loadArgument(out, slotMap, args.get(1), 'I', fn);
-
- // 发出 ARR_GET 系统调用(元素访问由 VM 完成类型分派)
- out.emit(VMOpCode.SYSCALL + " " + "ARR_GET");
-
- // 保存返回值到目标寄存器
- IRVirtualRegister dest = ins.getDest();
- if (dest == null) {
- throw new IllegalStateException(
- "[CallGenerator] %s 需要有目标寄存器用于保存返回值".formatted(fn));
- }
- Integer destSlot = slotMap.get(dest);
- if (destSlot == null) {
- throw new IllegalStateException(
- "[CallGenerator] %s 未找到目标寄存器的槽位映射 (dest: %s)".formatted(fn, dest));
- }
-
- // 按元素类型分派写入 VM 槽位
- switch (retType) {
- case 'B' -> {
- out.emit(OpHelper.opcode("B_STORE") + " " + destSlot);
- out.setSlotType(destSlot, 'B');
- }
- case 'S' -> {
- out.emit(OpHelper.opcode("S_STORE") + " " + destSlot);
- out.setSlotType(destSlot, 'S');
- }
- case 'I' -> {
- out.emit(OpHelper.opcode("I_STORE") + " " + destSlot);
- out.setSlotType(destSlot, 'I');
- }
- case 'L' -> {
- out.emit(OpHelper.opcode("L_STORE") + " " + destSlot);
- out.setSlotType(destSlot, 'L');
- }
- case 'F' -> {
- out.emit(OpHelper.opcode("F_STORE") + " " + destSlot);
- out.setSlotType(destSlot, 'F');
- }
- case 'D' -> {
- out.emit(OpHelper.opcode("D_STORE") + " " + destSlot);
- out.setSlotType(destSlot, 'D');
- }
- default -> {
- out.emit(OpHelper.opcode("R_STORE") + " " + destSlot);
- out.setSlotType(destSlot, 'R');
- }
- }
- }
-
- /**
- * 生成 syscall 指令分支逻辑。
- *
- * - 解析 syscall 子命令
- * - 压栈剩余参数
- * - 发出 SYSCALL 指令
- * - 若有返回值则保存至目标槽位
- *
- *
- * @param ins 调用指令
- * @param out VM 程序构建器
- * @param slotMap 寄存器到槽位映射
- * @param fn 当前函数名
- */
- private void generateSyscall(CallInstruction ins, VMProgramBuilder out, Map slotMap, String fn) {
- List args = ins.getArguments();
- if (args.isEmpty()) {
- throw new IllegalStateException(
- "[CallGenerator] syscall 需要子命令参数 (function: %s)".formatted(fn));
- }
-
- // 0. 解析 syscall 子命令(第一个参数)
- String subcmd = resolveSyscallSubcmd(args.getFirst(), fn);
-
- // 1. 压栈其余 syscall 参数(从 index 1 开始)
- for (int i = 1; i < args.size(); i++) {
- loadArgument(out, slotMap, args.get(i), 'R', fn);
- }
-
- // 2. 生成 SYSCALL 指令
- out.emit(VMOpCode.SYSCALL + " " + subcmd);
-
- // 3. 有返回值则保存到目标槽位
- IRVirtualRegister dest = ins.getDest();
- if (dest != null) {
- Integer destSlot = slotMap.get(dest);
- if (destSlot == null) {
- throw new IllegalStateException(
- "[CallGenerator] syscall 未找到目标寄存器的槽位映射 (function: %s, dest: %s)"
- .formatted(fn, dest));
- }
- out.emit(OpHelper.opcode("I_STORE") + " " + destSlot);
- out.setSlotType(destSlot, 'I');
- }
- }
-
- /**
- * 生成普通函数调用指令:
- *
- * - 推断返回值类型
- * - 压栈所有参数
- * - 生成 CALL 指令
- * - 保存返回值(若非 void)
- *
- *
- * @param ins 调用指令
- * @param out VM 程序构建器
- * @param slotMap 寄存器到槽位映射
- * @param fn 当前函数名
- */
- private void generateNormalCall(CallInstruction ins, VMProgramBuilder out, Map slotMap, String fn) {
- // 1. 推断返回值类型(首字母大写,缺省为 'I')
- String retTypeName = GlobalFunctionTable.getReturnType(fn);
- char retType = (retTypeName != null && !retTypeName.isEmpty()) ? Character.toUpperCase(retTypeName.charAt(0)) : 'I';
-
- // 2. 压栈所有参数
- for (IRValue arg : ins.getArguments()) {
- loadArgument(out, slotMap, arg, 'R', fn);
- }
-
- // 3. 发出 CALL 指令
- out.emitCall(fn, ins.getArguments().size());
-
- // 3.5 void 返回直接结束
- if ("void".equals(retTypeName)) {
- return;
- }
-
- // 4. 保存返回值到目标寄存器
- IRVirtualRegister dest = ins.getDest();
- if (dest == null) {
- throw new IllegalStateException(
- "[CallGenerator] 普通函数调用未找到目标寄存器 (function: %s)".formatted(fn));
- }
- Integer destSlot = slotMap.get(dest);
- if (destSlot == null) {
- throw new IllegalStateException(
- "[CallGenerator] 普通函数调用未找到目标寄存器的槽位映射 (function: %s, dest: %s)".formatted(fn, dest));
- }
- out.emit(OpHelper.opcode(retType + "_STORE") + " " + destSlot);
- out.setSlotType(destSlot, retType);
+ public String getFn() {
+ return fn;
}
}