summaryrefslogtreecommitdiff
path: root/chapter21/src/main/java
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2025-04-09 17:12:56 -0700
committerCliff Click <cliffc@acm.org>2025-04-09 17:12:56 -0700
commit074f718a104dbbb8b1b0a2205c176659a27dfd9f (patch)
tree33168e69e4cf1cf72e17f722eb76b1eb2201fa9d /chapter21/src/main/java
parentb32c6a879c0be7aebad25fabae6f0a24d5670366 (diff)
downloadSimple-074f718a104dbbb8b1b0a2205c176659a27dfd9f.tar.gz
Simple-074f718a104dbbb8b1b0a2205c176659a27dfd9f.zip
Handle large arg count function
2 print modes for stack slots - slot# or stack offset, only available after encoding. Compute maxArgSlot in one place on all archs. X86 yank flags from Splits - lest we split a XMM into the flags???
Diffstat (limited to 'chapter21/src/main/java')
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java6
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/Machine.java4
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java42
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/FunNode.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java14
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java8
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java7
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java5
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java6
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java4
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java131
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java17
13 files changed, 155 insertions, 93 deletions
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java
index f5d32dd2..515e2c10 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java
@@ -297,9 +297,11 @@ public class CodeGen {
return this;
}
- public String reg(Node n) {
+ // Human readable register name
+ public String reg(Node n) { return reg(n,null); }
+ public String reg(Node n, FunNode fun) {
if( _phase.ordinal() >= Phase.RegAlloc.ordinal() ) {
- String s = _regAlloc.reg(n);
+ String s = _regAlloc.reg(n,fun);
if( s!=null ) return s;
}
return "N"+ n._nid;
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Machine.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Machine.java
index bf3bfdb9..220ce7a4 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Machine.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Machine.java
@@ -1,6 +1,7 @@
package com.seaofnodes.simple.codegen;
import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.TypeFunPtr;
abstract public class Machine {
// Human readable machine name. Something like "x86-64" or "arm" or "risc5"
@@ -20,6 +21,9 @@ abstract public class Machine {
// Instruction select from ideal nodes
public abstract Node instSelect( Node n );
+ // Maximum stack slot (or 0) for the args in this TFP.
+ public abstract short maxArgSlot(TypeFunPtr tfp);
+
// Convert a register to a zero-based stack *slot*, or -1.
// Stack slots are assumed 8 bytes each.
// Actual stack layout is up to each CPU.
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java
index c84e6011..0f480a33 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java
@@ -51,6 +51,29 @@ public class RegAlloc {
// - If color fails:
// - - Split uncolorable LRGs
+ // RA gives all registers a number, starting at 0. Stack slots continue
+ // this numbering going up from the last register number. Common register
+ // numbers are 0-15 for GPRs, 16-31 for FPRs, 32 for flags, and stack slots
+ // starting at register#33 going up. These numbers are machine-specific,
+ // YMMV, etc; e.g. RPC is only in stack slot 0 on X86; other cpus start
+ // with the rpc in a register which may spill into any generic spill slot.
+
+ // For ease of reading & printing, stack slots start again at slot#0 - but
+ // during RA they are actually biased by CPU.MAX_REG.
+
+ // Stack Layout during Reg Alloc:
+ //
+ // Stack
+ // Num -- Caller ------
+ // N+1 argN
+ // ...
+ // 1 arg0
+ // -------- Callee -------
+ // 0 RPC
+ // N+M PAD
+ // N+ Spills
+ // N+2 Spills
+
// Top-level program graph structure
final CodeGen _code;
@@ -130,11 +153,18 @@ public class RegAlloc {
}
// Printable register number for node n
- String reg( Node n ) {
+ String reg( Node n ) { return reg(n,null); }
+ String reg( Node n, FunNode fun ) {
LRG lrg = lrg(n);
if( lrg==null ) return null;
+ // No register yet, use LRG
if( lrg._reg == -1 ) return "V"+lrg._lrg;
- return _code._mach.reg(lrg._reg);
+ // Chosen machine register unless stack-slot and past RA
+ int slot = _code._mach.stackSlot(lrg._reg);
+ if( slot == -1 || _code._phase.ordinal() <= CodeGen.Phase.RegAlloc.ordinal() || fun==null )
+ return _code._mach.reg(lrg._reg);
+ // Stack-slot past RA uses the frame layout logic
+ return "[rsp+"+fun.computeStackSlot(slot)*8+"]";
}
// -----------------------
@@ -542,9 +572,11 @@ public class RegAlloc {
private void postColor() {
int maxSlot = -1;
for( CFGNode bb : _code._cfg ) { // For all ops
- if( bb instanceof FunNode )
- maxSlot = -1;
- if( bb instanceof ReturnNode ret )
+ if( bb instanceof FunNode fun ) {
+ fun._maxArgSlot = _code._mach.maxArgSlot(fun.sig());
+ maxSlot = -1; // Reset for new function
+ }
+ if( bb instanceof ReturnNode ret ) // Capture max seen
ret.fun()._maxSlot = (short)maxSlot;
for( int j=0; j<bb.nOuts(); j++ ) {
Node n = bb.out(j);
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/FunNode.java b/chapter21/src/main/java/com/seaofnodes/simple/node/FunNode.java
index 2e32b75e..0562b5b8 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/FunNode.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/FunNode.java
@@ -180,7 +180,7 @@ public class FunNode extends RegionNode {
// outbound calls, but not leaf. Set during an unrelated RA scan.
public boolean _hasCalls;
- // Max observed spill slot, set during RA postcolor
+ // One more than largest spill slot, set during RA postcolor.
public short _maxSlot = -1;
// Max argument slot, set during early Encoding.
public short _maxArgSlot = -1;
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java
index 71e9ef87..b919df66 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java
@@ -23,14 +23,16 @@ public class FunARM extends FunNode implements MachNode {
// | PAD16 |
// +--------+
@Override public void encoding( Encoding enc ) {
- // Stack frame size: _maxSlot - max(arg), padded to 16.
- _maxArgSlot = arm.maxSlot(enc._fun.sig());
- _frameAdjust = (short) (_maxSlot+1 - _maxArgSlot);
- if( _frameAdjust == 0 ) return; // Skip if no frame adjust
- enc.add4(arm.imm_inst(arm.OPI_ADD, (_frameAdjust*8)&0xFFF, arm.RSP, arm.RSP));
+ // Size of local stack frame.
+ // Can be negative if the stack args passed are never referenced
+ int sz = Math.max(_maxSlot - _maxArgSlot,0);
+ sz = ((sz+1) & -2)+1; // Pad to 16
+ if( _frameAdjust != 0 )
+ enc.add4(arm.imm_inst(arm.OPI_ADD, (_frameAdjust*8)&0xFFF, arm.RSP, arm.RSP));
}
@Override public void asm(CodeGen code, SB sb) {
- sb.p("rsp += #").p(_frameAdjust*8);
+ if( _frameAdjust != 0 )
+ sb.p("rsp += #").p(_frameAdjust*8);
}
}
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java
index e3d2de47..0aea0ae9 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java
@@ -27,9 +27,9 @@ public class arm extends Machine {
static final int D16 = 48, D17 = 49, D18 = 50, D19 = 51, D20 = 52, D21 = 53, D22 = 54, D23 = 55;
static final int D24 = 56, D25 = 57, D26 = 58, D27 = 59, D28 = 60, D29 = 61, D30 = 62, D31 = 63;
- static final int MAX_REG = 64;
- static final int D_OFFSET = 31;
static final int FLAGS = 64;
+ static final int MAX_REG = 65;
+ static final int D_OFFSET = 31;
static final String[] REGS = new String[] {
"X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7",
@@ -43,7 +43,7 @@ public class arm extends Machine {
"flags"
};
@Override public String reg( int reg ) {
- return reg < REGS.length ? REGS[reg] : "[rsp+"+(reg-REGS.length)*8+"]";
+ return reg < REGS.length ? REGS[reg] : "[stk#"+(reg-REGS.length)+"]";
}
// Stack slots, in units of 8 bytes.
@Override public int stackSlot( int reg ) {
@@ -542,7 +542,7 @@ public class arm extends Machine {
throw Utils.TODO(); // Pass on stack slot
}
// Return the max stack slot used by this signature, or 0
- static short maxSlot( TypeFunPtr tfp ) {
+ @Override public short maxArgSlot( TypeFunPtr tfp ) {
// Count floats in signature up to index
int fcnt=0;
for( int i=0; i<tfp.nargs(); i++ )
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java
index 7babe04c..5f888806 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java
@@ -23,9 +23,10 @@ public class FunRISC extends FunNode implements MachNode {
// | PAD16 |
// +--------+
@Override public void encoding( Encoding enc ) {
- // Stack frame size: _maxSlot - max(arg), padded to 16.
- _maxArgSlot = riscv.maxSlot(enc._fun.sig());
- _frameAdjust = (short) (_maxSlot+1 - _maxArgSlot);
+ // Size of local stack frame.
+ // Can be negative if the stack args passed are never referenced
+ int sz = Math.max(_maxSlot - _maxArgSlot,0);
+ sz = ((sz+1) & -2)+1; // Pad to 16
if( _frameAdjust != 0 )
enc.add4(riscv.i_type(riscv.OP_IMM, riscv.SP, 0, riscv.SP, (_frameAdjust*-8) & 0xFFF));
}
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java
index fe767a36..5b2ea9b9 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java
@@ -261,8 +261,7 @@ public class riscv extends Machine {
throw Utils.TODO(); // Pass on stack slot
}
- // Return the max stack slot used by this signature, or 0
- static short maxSlot( TypeFunPtr tfp ) {
+ @Override public short maxArgSlot( TypeFunPtr tfp ) {
// Count floats in signature up to index
int fcnt=0;
for( int i=0; i<tfp.nargs(); i++ )
@@ -321,7 +320,7 @@ public class riscv extends Machine {
}
@Override public String reg( int reg ) {
- return reg < REGS.length ? REGS[reg] : "[rsp+"+(reg-REGS.length)*8+"]";
+ return reg < REGS.length ? REGS[reg] : "[stk#"+(reg-REGS.length)+"]";
}
// Stack slots, in units of 8 bytes.
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java
index 15805fee..106d1255 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java
@@ -24,9 +24,9 @@ public class FunX86 extends FunNode implements MachNode {
// | callee | // slot 2, callEE
// +--------+
@Override public void encoding( Encoding enc ) {
- // Stack frame size: _maxSlot - max(arg), padded to 16.
- _maxArgSlot = x86_64_v2.maxArgSlot(enc._fun.sig());
- int sz = _maxSlot - _maxArgSlot;
+ // Stack frame size: _maxSlot - max(arg).
+ // Can be negative if the stack args passed are never referenced
+ int sz = Math.max(_maxSlot - _maxArgSlot,0);
// If non-leaf function, pad to 16b
if( _hasCalls ) sz = ((sz+1) & -2)+1;
assert x86_64_v2.imm8(sz*8);
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java
index 4faf7cb4..ca9f148c 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java
@@ -30,7 +30,7 @@ public class RetX86 extends ReturnNode implements MachNode {
@Override public void asm(CodeGen code, SB sb) {
int frameAdjust = ((FunX86)fun())._frameAdjust;
if( frameAdjust>0 )
- sb.p("rsp += #").p(frameAdjust*-8).p("\nret");
+ sb.p("rsp += #").p(frameAdjust*8).p("\nret");
// Post code-gen, just print the "ret"
if( code._phase.ordinal() <= CodeGen.Phase.RegAlloc.ordinal() )
// Prints return reg (either RAX or XMM0), RPC (always [rsp-4]) and
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java
index 8e3112cd..c7685ae1 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java
@@ -3,6 +3,7 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2;
import com.seaofnodes.simple.SB;
import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.codegen.*;
+import com.seaofnodes.simple.node.FunNode;
import com.seaofnodes.simple.node.Node;
import com.seaofnodes.simple.node.SplitNode;
import com.seaofnodes.simple.type.Type;
@@ -92,6 +93,7 @@ public class SplitX86 extends SplitNode {
// General form: "mov dst = src"
@Override public void asm(CodeGen code, SB sb) {
- sb.p(code.reg(this)).p(" = ").p(code.reg(in(1)));
+ FunNode fun = code._encoding._fun;
+ sb.p(code.reg(this,fun)).p(" = ").p(code.reg(in(1),fun));
}
}
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java
index ea0ab27b..2f70dc0c 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java
@@ -36,7 +36,7 @@ public class x86_64_v2 extends Machine {
static RegMask RPC_MASK = new RegMask(RPC);
static final long SPILLS = -(1L << MAX_REG);
- static final RegMask SPLIT_MASK = new RegMask(WR_BITS | FP_BITS | (1L<<FLAGS) | SPILLS, -1L );
+ static final RegMask SPLIT_MASK = new RegMask(WR_BITS | FP_BITS /* | (1L<<FLAGS)*/ | SPILLS, -1L );
// Load/store mask; both GPR and FPR
static RegMask MEM_MASK = new RegMask(WR_BITS | FP_BITS);
@@ -175,12 +175,6 @@ public class x86_64_v2 extends Machine {
}
}
- // Calling conv metadata
- public int GPR_COUNT_CONV_WIN64 = 4; // RCX, RDX, R9, R9
- public int XMM_COUNT_CONV_WIN64 = 4; // XMM0L, XMM1L, XMM2L, XMM3L
-
- public int GPR_COUNT_CONV_SYSTEM_V = 6; // RDI, RSI, RDX, RCX, R8, R9
- public int XMM_COUNT_CONV_SYSTEM_V = 4; // XMM0, XMM1, XMM2, XMM3 ....
// Human-readable name for a register number, e.g. "RAX".
// Hard crash for bad register number, fix yer bugs!
public static final String[] REGS = new String[]{
@@ -191,7 +185,7 @@ public class x86_64_v2 extends Machine {
"flags",
};
@Override public String reg( int reg ) {
- return reg < REGS.length ? REGS[reg] : "[rsp+"+(reg-REGS.length)*8+"]";
+ return reg < REGS.length ? REGS[reg] : "[stk#"+(reg-REGS.length)+"]";
}
// Stack slots, in units of 8 bytes.
@@ -199,8 +193,46 @@ public class x86_64_v2 extends Machine {
return reg < REGS.length ? -1 : reg-REGS.length;
}
+ // Limit of float args passed in registers
+ static RegMask[] XMMS8 = new RegMask[]{
+ new RegMask(XMM0), new RegMask(XMM1), new RegMask(XMM2), new RegMask(XMM3),
+ new RegMask(XMM4), new RegMask(XMM5), new RegMask(XMM6), new RegMask(XMM7),
+ };
+
+ // Map from function signature and argument index to register.
+ // Used to set input registers to CallNodes, and ParmNode outputs.
+ static RegMask callInMask( TypeFunPtr tfp, int idx ) {
+ if( idx==0 ) return RPC_MASK;
+ if( idx==1 ) return null;
+ return switch( CodeGen.CODE._callingConv ) {
+ case "SystemV" -> callSys5 (tfp,idx);
+ case "Win64" -> callWin64(tfp,idx);
+ default -> throw Utils.TODO();
+ };
+ }
+
+ // Maximum stack args used by this signature, +1 for RPC
+ @Override public short maxArgSlot( TypeFunPtr tfp ) {
+ return switch( CodeGen.CODE._callingConv ) {
+ case "SystemV" -> maxArgSlotSys5 (tfp);
+ case "Win64" -> maxArgSlotWin64(tfp);
+ default -> throw Utils.TODO();
+ };
+ }
- // WIN64(param passing)
+ // Win64 - max *4* args in registers of all kinds; after that on stack.
+ // Stack args land in increasing memory order.
+ // foo( int arg0, int arg1, int arg2, int arg3, int stk1, flt stk2, int stk3, ... )
+ //
+ // -- Prior Frame --
+ // RPC
+ // stk3
+ // stk2
+ // stk1
+ // -- Caller Frame; 16b align --
+ // RPC
+ // PAD
+ // -- Callee Frame; 16b align --
static RegMask[] CALLINMASK_WIN64 = new RegMask[] {
RCX_MASK,
RDX_MASK,
@@ -208,6 +240,19 @@ public class x86_64_v2 extends Machine {
R09_MASK,
};
+ private static RegMask callWin64(TypeFunPtr tfp, int idx ) {
+ // idx 2,3,4,5 passed in registers, with stack slot mirrors
+ // idx >= 6 passed on stack, starting at slot#1 (#0 reserved for RPC)
+ if( idx >= 6 )
+ return new RegMask(MAX_REG+1/*RPC*/+(idx-2));
+ return tfp.arg(idx-2) instanceof TypeFloat
+ ? XMMS8[idx-2]
+ : CALLINMASK_WIN64[idx-2];
+ }
+ static short maxArgSlotWin64(TypeFunPtr tfp) {
+ return (short)(1/*RPC*/+ tfp.nargs());
+ }
+
// SystemV(param passing)
static RegMask[] CALLINMASK_SYSTEMV = new RegMask[] {
RDI_MASK,
@@ -218,57 +263,29 @@ public class x86_64_v2 extends Machine {
R09_MASK,
};
- // Limit of float args passed in registers
- static RegMask[] XMMS4 = new RegMask[]{
- new RegMask(XMM0), new RegMask(XMM1), new RegMask(XMM2), new RegMask(XMM3),
- };
-
- // Map from function signature and argument index to register.
- // Used to set input registers to CallNodes, and ParmNode outputs.
- static RegMask callInMask( TypeFunPtr tfp, int idx ) {
- if( idx==0 ) return RPC_MASK;
- if( idx==1 ) return null;
- // Count floats in signature up to index
- int fcnt=0;
- for( int i=2; i<idx; i++ )
- if( tfp.arg(i-2) instanceof TypeFloat )
- fcnt++;
- // Floats up to XMMS in XMM registers
- if( tfp.arg(idx-2) instanceof TypeFloat ) {
- if( fcnt < XMMS4.length )
- return XMMS4[fcnt];
- } else {
- RegMask[] cargs = switch( CodeGen.CODE._callingConv ) {
- case "SystemV" -> CALLINMASK_SYSTEMV;
- case "Win64" -> CALLINMASK_WIN64;
- default -> throw new IllegalArgumentException("Unknown calling convention: "+CodeGen.CODE._callingConv);
- };
- if( idx-2-fcnt < cargs.length )
- return cargs[idx-2-fcnt];
+ private static RegMask callSys5(TypeFunPtr tfp, int idx ) {
+ // First 6 integers passed in registers: rdi,rsi,rdx,rcx,r08,r09
+ // First 8 floats passed in registers: xmm0-xmm7
+ int icnt=0, fcnt=0; // Count of ints, floats
+ for( int i=2; i<idx; i++ ) {
+ if( tfp.arg(i-2) instanceof TypeFloat ) fcnt++;
+ else icnt++;
}
- throw Utils.TODO(); // Pass on stack slot
- }
-
- // Return the max stack slot used by this signature, or 1 (for RPC)
- static short maxArgSlot( TypeFunPtr tfp ) {
- // Count floats in signature up to index
- int fcnt=0;
- for( int i=0; i<tfp.nargs(); i++ )
- if( tfp.arg(i) instanceof TypeFloat )
- fcnt++;
- if( fcnt >= XMMS4.length )
- throw Utils.TODO();
- RegMask[] cargs = switch( CodeGen.CODE._callingConv ) {
- case "SystemV" -> CALLINMASK_SYSTEMV;
- case "Win64" -> CALLINMASK_WIN64;
- default -> throw new IllegalArgumentException("Unknown calling convention: "+CodeGen.CODE._callingConv);
- };
- if( tfp.nargs()-fcnt >= cargs.length )
- throw Utils.TODO();
- return 1; // No stack args, plus RPC
+ int nstk = Math.max(icnt-6,0)+Math.max(fcnt-8,0);
+ return tfp.arg(idx-2) instanceof TypeFloat
+ ? fcnt<8 ? XMMS8 [fcnt] : new RegMask(MAX_REG+nstk)
+ : icnt<6 ? CALLINMASK_SYSTEMV[icnt] : new RegMask(MAX_REG+nstk);
+ }
+ static short maxArgSlotSys5(TypeFunPtr tfp) {
+ int icnt=0, fcnt=0; // Count of ints, floats
+ for( int i=0; i<tfp.nargs(); i++ ) {
+ if( tfp.arg(i) instanceof TypeFloat ) fcnt++;
+ else icnt++;
+ }
+ int nstk = Math.max(icnt-6,0)+Math.max(fcnt-8,0);
+ return (short)(1+nstk);
}
-
// caller saved(systemv)
static final long SYSTEM5_CALLER_SAVE =
(1L << RAX) | (1L << RCX) | (1L << RDX) |
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java b/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java
index c040d414..0d7dd57e 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java
@@ -64,6 +64,8 @@ public abstract class ASMPrinter {
}
private static int print(int iadr, SB sb, CodeGen code, FunNode fun, int cfgidx) {
+ FunNode old = code._encoding._fun;
+ code._encoding._fun = fun; // Useful printing after RA
// Function header
sb.nl().p("---");
if( fun._name != null ) sb.p(fun._name).p(" ");
@@ -71,7 +73,7 @@ public abstract class ASMPrinter {
sb.p("---------------------------").nl();
if( fun._frameAdjust != 0 )
- iadr = doInst(iadr,sb,code,cfgidx,fun,true,true);
+ iadr = doInst(iadr,sb,code,fun,cfgidx,fun,true,true);
while( !(code._cfg.at(cfgidx) instanceof ReturnNode) )
iadr = doBlock(iadr,sb,code,fun,cfgidx++);
@@ -79,6 +81,7 @@ public abstract class ASMPrinter {
sb.p("---");
fun.sig().print(sb);
sb.p("---------------------------").nl();
+ code._encoding._fun = old;
return iadr;
}
@@ -100,10 +103,10 @@ public abstract class ASMPrinter {
// Post-RegAlloc phi prints all on one line
if( postAlloc ) {
if( !once ) { once=true; sb.fix(4," ").p(" ").fix(encWidth,"").p(" "); }
- sb.p(phi._label).p(':').p(code.reg(phi)).p(',');
+ sb.p(phi._label).p(':').p(code.reg(phi,fun)).p(',');
} else {
// Pre-RegAlloc phi prints one line per
- sb.fix(4," ").p(" ").fix(encWidth,"").p(" ").fix(opWidth,phi._label).p(" ").p(code.reg(phi));
+ sb.fix(4," ").p(" ").fix(encWidth,"").p(" ").fix(opWidth,phi._label).p(" ").p(code.reg(phi,fun));
if( phi.getClass() == PhiNode.class ) {
sb.p(" = phi( ");
for( int i=1; i<phi.nIns(); i++ )
@@ -118,12 +121,12 @@ public abstract class ASMPrinter {
// All the non-phis
for( int i=0; i<bb.nOuts(); i++ )
if( !(bb.out(i) instanceof PhiNode) )
- iadr = doInst(iadr, sb,code, cfgidx, bb.out(i),postAlloc, postEncode );
+ iadr = doInst(iadr, sb,code, fun, cfgidx, bb.out(i),postAlloc, postEncode );
return iadr;
}
- static int doInst( int iadr, SB sb, CodeGen code, int cfgidx, Node n, boolean postAlloc, boolean postEncode ) {
+ static int doInst( int iadr, SB sb, CodeGen code, FunNode fun, int cfgidx, Node n, boolean postAlloc, boolean postEncode ) {
if( n==null || n instanceof CProjNode ) return iadr;
if( postAlloc && n instanceof CalleeSaveNode ) return iadr;
if( postEncode && n instanceof ProjNode ) return iadr;
@@ -152,7 +155,7 @@ public abstract class ASMPrinter {
// get indent slightly and just print their index & node#
if( n instanceof ProjNode proj ) {
if( proj._type instanceof TypeMem ) return iadr; // Nothing for the hidden ones
- sb.fix(4," ").p(" ").fix(encWidth,"").p(" ").fix(opWidth,proj._label==null ? "---" : proj._label).p(" ").p(code.reg(n)).nl();
+ sb.fix(4," ").p(" ").fix(encWidth,"").p(" ").fix(opWidth,proj._label==null ? "---" : proj._label).p(" ").p(code.reg(n,fun)).nl();
return iadr;
}
@@ -249,7 +252,7 @@ public abstract class ASMPrinter {
if( !(n instanceof CFGNode) && n instanceof MultiNode ) {
for( Node proj : n._outputs ) {
assert proj instanceof ProjNode;
- doInst(iadr,sb,code, cfgidx, proj,postAlloc,postEncode);
+ doInst(iadr,sb,code,fun, cfgidx, proj,postAlloc,postEncode);
}
}