diff --git a/src/main/java/org/jcnc/snow/compiler/ir/instruction/CallInstruction.java b/src/main/java/org/jcnc/snow/compiler/ir/instruction/CallInstruction.java index 405f0f6..13db658 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/instruction/CallInstruction.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/instruction/CallInstruction.java @@ -1,115 +1,95 @@ package org.jcnc.snow.compiler.ir.instruction; +import org.jcnc.snow.compiler.ir.common.GlobalFunctionTable; import org.jcnc.snow.compiler.ir.core.IRInstruction; import org.jcnc.snow.compiler.ir.core.IROpCode; +import org.jcnc.snow.compiler.ir.core.IRValue; import org.jcnc.snow.compiler.ir.core.IRVisitor; import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; -import org.jcnc.snow.compiler.ir.core.IRValue; import java.util.ArrayList; import java.util.List; /** * CallInstruction —— 表示一次函数调用的中间代码指令 - * 形式为:dest = CALL functionName, arg1, arg2, ... + *
+ *   dest = CALL foo, arg1, arg2, ...
+ * 
+ * 若被调函数返回 void,则 {@code dest} 可以为 {@code null}, + * 并且不会参与寄存器分配。 */ public class CallInstruction extends IRInstruction { - /** - * 调用结果存放的目标虚拟寄存器 - */ + /** 调用结果目标寄存器;void 返回时可为 null */ private final IRVirtualRegister dest; - - /** - * 被调用的函数名 - */ + /** 被调用的函数名(含模块限定) */ private final String functionName; - - /** - * 传递给函数的参数列表 - */ + /** 实参列表 */ private final List arguments; - /** - * 构造函数,创建一个函数调用指令 - * - * @param dest 调用结果存放的目标寄存器 - * @param functionName 被调用的函数名 - * @param args 参数列表 - */ - public CallInstruction(IRVirtualRegister dest, String functionName, List args) { + public CallInstruction(IRVirtualRegister dest, + String functionName, + List args) { this.dest = dest; this.functionName = functionName; this.arguments = List.copyOf(args); } - /** - * 获取该指令的操作码 - * - * @return 操作码 CALL - */ + // === 基本信息 === @Override public IROpCode op() { return IROpCode.CALL; } - /** - * 获取该指令涉及的操作数(目标寄存器和所有参数) - * - * @return 操作数列表 - */ + /** 仅在函数有返回值时才暴露目标寄存器 */ + @Override + public IRVirtualRegister dest() { + return isVoidReturn() ? null : dest; + } + + /** 操作数列表:void 调用不包含 dest */ @Override public List operands() { List ops = new ArrayList<>(); - ops.add(dest); + if (!isVoidReturn() && dest != null) { + ops.add(dest); + } ops.addAll(arguments); return ops; } - /** - * 获取目标虚拟寄存器 - * - * @return 目标虚拟寄存器 - */ + // === Getter === public IRVirtualRegister getDest() { return dest; } - /** - * 获取被调用的函数名 - * - * @return 函数名 - */ public String getFunctionName() { return functionName; } - /** - * 获取参数列表 - * - * @return 参数列表 - */ public List getArguments() { return arguments; } - /** - * 接受 IRVisitor 访问 - * - * @param visitor 访问者 - */ + // === 帮助方法 === + /** 判断被调函数是否返回 void */ + private boolean isVoidReturn() { + return "void".equals(GlobalFunctionTable.getReturnType(functionName)); + } + + // === 访客模式 === @Override public void accept(IRVisitor visitor) { visitor.visit(this); } - /** - * 获取该指令的字符串表示 - * - * @return 字符串形式 - */ + // === 字符串表示 === @Override public String toString() { - StringBuilder sb = new StringBuilder(dest + " = CALL " + functionName); + StringBuilder sb = new StringBuilder(); + if (!isVoidReturn() && dest != null) { + sb.append(dest).append(" = "); + } + sb.append("CALL ").append(functionName); for (IRValue arg : arguments) { sb.append(", ").append(arg); }