From 19f9ea99114e9c1819239508f812d6521661f7bb Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Tue, 27 Oct 2026 19:06:47 -0700 Subject: Backport a bunch of fixes ARM encoding Extra fidx burned with no constructor Getting types during a parse to avoid a whole-program walk later --- .../seaofnodes/simple/node/cpus/arm/CallRRARM.java | 9 ++++--- .../simple/node/cpus/riscv/CallRRISC.java | 5 +++- .../simple/node/cpus/x86_64_v2/CallRX86.java | 7 +++-- .../com/seaofnodes/simple/IndirectCallTest.java | 30 ++++++++++++++++++++++ 4 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 chapter23/src/test/java/com/seaofnodes/simple/IndirectCallTest.java (limited to 'chapter23/src') diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java index 1949ae46..856af3b8 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java @@ -1,16 +1,19 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.simple.type.TypeFunPtr; import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; public class CallRRARM extends CallNode implements MachNode { - CallRRARM(CallNode call) { super(call); } + final TypeFunPtr _tfp; + CallRRARM( CallNode call ) { super(call); _tfp = call.tfp(); } + @Override public TypeFunPtr tfp() { return _tfp; } @Override public String op() { return "callr"; } @Override public String label() { return op(); } @Override public RegMask regmap(int i) { - return i==_inputs._len + return i==_inputs._len-1 ? arm.RMASK // Function call target : arm.callInMask(tfp(),i,fun()._maxArgSlot); // Normal argument } @@ -19,7 +22,7 @@ public class CallRRARM extends CallNode implements MachNode { @Override public void encoding( Encoding enc ) { // Needs a register, typically a jump-and-link-register opcode // blr - short self = enc.reg(this); + short self = enc.reg(fptr()); enc.add4(Arm64.blr(Arm64.OP_CALLRARM, self)); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java index 5eee596d..ffd47713 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java @@ -1,12 +1,15 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.simple.type.TypeFunPtr; import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; public class CallRRISC extends CallNode implements MachNode { - CallRRISC( CallNode call ) { super(call); } + final TypeFunPtr _tfp; + CallRRISC( CallNode call ) { super(call); _tfp = call.tfp(); } + @Override public TypeFunPtr tfp() { return _tfp; } @Override public String op() { return "callr"; } @Override public String label() { return op(); } @Override public RegMask regmap(int i) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java index f97163eb..c204f25c 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.simple.type.TypeFunPtr; import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.CallNode; @@ -7,11 +8,13 @@ import com.seaofnodes.simple.node.MachNode; import com.seaofnodes.simple.util.SB; public class CallRX86 extends CallNode implements MachNode { - CallRX86( CallNode call ) { super(call); } + final TypeFunPtr _tfp; + CallRX86( CallNode call ) { super(call); _tfp = call.tfp(); } + @Override public TypeFunPtr tfp() { return _tfp; } @Override public String op() { return "callr"; } @Override public String label() { return op(); } @Override public RegMask regmap(int i) { - return i==_inputs._len + return i==_inputs._len-1 ? x86_64_v2.WMASK // Function call target : x86_64_v2.callInMask(tfp(),i,fun()._maxArgSlot); // Normal argument } diff --git a/chapter23/src/test/java/com/seaofnodes/simple/IndirectCallTest.java b/chapter23/src/test/java/com/seaofnodes/simple/IndirectCallTest.java new file mode 100644 index 00000000..9bd1a342 --- /dev/null +++ b/chapter23/src/test/java/com/seaofnodes/simple/IndirectCallTest.java @@ -0,0 +1,30 @@ +package com.seaofnodes.simple; + +import com.seaofnodes.simple.codegen.CodeGen; +import com.seaofnodes.simple.codegen.RegMask; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeFunPtr; +import org.junit.Test; +import static org.junit.Assert.*; + +public class IndirectCallTest { + @Test public void testTargetOperand() { + for( String cpu : new String[]{"x86_64_v2","riscv","arm"} ) { + CodeGen code = new CodeGen("return 0;").driver(CodeGen.Phase.Select,cpu,"SystemV"); + Node target = PhiNode.make("target",TypeFunPtr.BOT,code._start); + target._type = TypeFunPtr.BOT; + CallNode ideal = new CallNode(null,code._start,null,target); + CallNode call = (CallNode)code._mach.instSelect(ideal); + // The last input is the call target, not another argument. + assertEquals("callr",((MachNode)call).op()); + RegMask mask = ((MachNode)call).regmap(call.nIns()-1); + assertTrue(mask.test(5)); + assertTrue(mask.test(6)); + // Machine operands can lose their ideal type (e.g. a spill reload). + // The call still needs the original signature for argument masks. + target._type = Type.BOTTOM; + assertSame(TypeFunPtr.BOT,call.tfp()); + } + } +} -- cgit v1.2.3