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、普通函数调用、一维/多维数组下标访问、以及字符串常量池绑定等功能。 - *

- * + * 功能包括: * */ 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 指令分支逻辑。 - *
    - *
  1. 解析 syscall 子命令
  2. - *
  3. 压栈剩余参数
  4. - *
  5. 发出 SYSCALL 指令
  6. - *
  7. 若有返回值则保存至目标槽位
  8. - *
- * - * @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'); - } - } - - /** - * 生成普通函数调用指令: - *
    - *
  1. 推断返回值类型
  2. - *
  3. 压栈所有参数
  4. - *
  5. 生成 CALL 指令
  6. - *
  7. 保存返回值(若非 void)
  8. - *
- * - * @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; } }