diff options
| author | Cliff Click <cliffc@acm.org> | 2025-04-29 13:27:50 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2025-04-29 13:27:50 -0700 |
| commit | f505e8b554fed728c4952c06fbf2005d01540683 (patch) | |
| tree | 81ec096e775c949bfd656aa8d90d5146bf078c04 /chapter21/src/main/java | |
| parent | 562885524138d941c214dc66cd30fcd0da5e6269 (diff) | |
| parent | 7e1deb4cbd52c7ebbec78e2ceeb35875e83c6e3a (diff) | |
| download | Simple-f505e8b554fed728c4952c06fbf2005d01540683.tar.gz Simple-f505e8b554fed728c4952c06fbf2005d01540683.zip | |
Merge branch 'main' into ch22
Diffstat (limited to 'chapter21/src/main/java')
23 files changed, 78 insertions, 57 deletions
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/BuildLRG.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/BuildLRG.java index a2bb21ed..e9b5eb2e 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/BuildLRG.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/BuildLRG.java @@ -63,7 +63,7 @@ abstract public class BuildLRG { } // MultiNodes have projections which set registers - if( n instanceof MultiNode ) + if( n instanceof MultiNode && !(n instanceof CFGNode) ) for( Node proj : n.outs() ) if( proj instanceof MachNode ) defLRG(alloc,proj); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java index d7057839..c35ea6a4 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java @@ -324,7 +324,6 @@ public class Encoding { if( !(bb instanceof MachNode mach0) ) _opStart[bb._nid] = _bits.size(); else if( bb instanceof FunNode fun ) { - padN(16,_bits); _fun = fun; // Currently encoding function _opStart[bb._nid] = _bits.size(); mach0.encoding( this ); @@ -338,7 +337,6 @@ public class Encoding { } } } - padN(16,_bits); } // -------------------------------------------------- diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/GlobalCodeMotion.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/GlobalCodeMotion.java index 289d1786..40f827ec 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/GlobalCodeMotion.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/GlobalCodeMotion.java @@ -167,6 +167,8 @@ public abstract class GlobalCodeMotion { !(memuse instanceof NewNode) && // Load-use directly defines memory (memuse._type instanceof TypeMem || + // Load-use directly defines memory + memuse instanceof CallNode || // Load-use indirectly defines memory (memuse._type instanceof TypeTuple tt && tt._types[ld._alias] instanceof TypeMem)) ) continue outer; @@ -277,9 +279,9 @@ public abstract class GlobalCodeMotion { lca = anti_dep( load, late[mem._nid], mem.cfg0(), lca, st ); } break; // Loads do not cause anti-deps on other loads - case CallNode st: - assert late[st._nid]!=null; - lca = anti_dep(load,late[st._nid],st.cfg0(),lca,st); + case CallNode call: + assert late[call._nid]!=null; + lca = anti_dep(load,late[call._nid],call.cfg0(),lca,call); break; case PhiNode phi: // Repeat anti-dep for matching Phi inputs. diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/IFG.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/IFG.java index 81955779..fdd4e2f9 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/IFG.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/IFG.java @@ -242,14 +242,12 @@ abstract public class IFG { private static void mergeLiveOut( RegAlloc alloc, CFGNode priorbb, int i ) { CFGNode bb = priorbb.cfg(i); if( bb == null ) return; // Start has no prior - if( !bb.blockHead() ) bb = bb.cfg0(); - //if( i==0 && !(bb instanceof StartNode) ) bb = bb.cfg0(); - assert bb.blockHead(); + while( !bb.blockHead() ) bb = bb.cfg0(); // Lazy get live-out set for bb - IdentityHashMap<LRG, Node> lrgs = BBOUTS.computeIfAbsent( bb, k -> new IdentityHashMap<>() ); + IdentityHashMap<LRG, Node> lrgs = BBOUTS.computeIfAbsent( bb, k -> new IdentityHashMap<>() ); - for( LRG lrg : TMP.keySet() ) { + for( LRG lrg : TMP.keySet() ) { Node def = TMP.get(lrg); // Effective def comes from phi input from prior block if( def instanceof PhiNode phi && phi.cfg0()==priorbb ) { 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 1c12bfcb..2766414f 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Machine.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Machine.java @@ -16,8 +16,12 @@ abstract public class Machine { public abstract long callerSave(); // List of never-save registers, e.g. RSP or a ZERO register if you have one public abstract long neverSave(); - // Call Argument Mask - public abstract RegMask callArgMask(TypeFunPtr tfp, int arg); + // Call Argument Mask. Passed in the function signature and argument + // number (2-based; 0 is for control and 1 for memory). Also passed in a 0 + // for the function itself, or for *outgoing* calls, the maximum stack slot + // given to the incoming function arguments (stack slots reserved for + // incoming arguments). + public abstract RegMask callArgMask(TypeFunPtr tfp, int arg, int maxArgSlot); // Return register mask, based on signature (GPR vs FPR) public abstract RegMask retMask(TypeFunPtr tfp); // Return PC register 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 49f057a3..3a99c097 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java @@ -262,7 +262,7 @@ public class RegAlloc { } // Single-def live range with an empty mask. There are many single-reg - // uses. Theory is there's many repeats if the same reg amongst the uses. + // uses. Theory is there's many repeats of the same reg amongst the uses. // In of splitting once per use, start by splitting into groups based on // required input register. boolean splitEmptyMaskByUse( byte round, LRG lrg ) { @@ -271,26 +271,32 @@ public class RegAlloc { // Look at each use, and break into non-overlapping register classes. Ary<RegMask> rclass = new Ary<>(RegMask.class); boolean done=false; + int ncalls=0; while( !done ) { done = true; for( Node use : def._outputs ) - if( use instanceof MachNode mach ) + if( use instanceof MachNode mach ) { + if( mach instanceof CallNode ) ncalls++; for( int i=1; i<use.nIns(); i++ ) if( use.in(i)==def ) done = putIntoRegClass( rclass, mach.regmap(i) ); + } } - // See how many register classes we split into - if( rclass._len <= 1 ) return false; + // See how many register classes we split into. Generally not + // productive to split like this across calls, which are going to kill + // all registers anyways. + if( rclass._len <= 1 || ncalls > 1 ) return false; - // Split by class + // Split by classh + Ary<Node> ns = new Ary<>(Node.class); for( RegMask rmask : rclass ) { + ns.addAll(def._outputs); Node split = makeSplit(def,"popular",round,lrg); split.insertAfter( def ); if( split.nIns()>1 ) split.setDef(1,def); // all uses by class to split - for( int j=0; j < def._outputs._len; j++ ) { - Node use = def._outputs.at(j); + for( Node use : ns ) { if( use instanceof MachNode mach && use!=split ) { // Check all use inputs for n, in case there's several for( int i = 1; i < use.nIns(); i++ ) @@ -299,10 +305,11 @@ public class RegAlloc { RegMask m = mach.regmap( i ); if( m!=null && mach.regmap( i ).overlap( rmask ) ) // Modify use to use the split version specialized to this rclass - { use.setDefOrdered( i, split ); j--; break; } + use.setDefOrdered( i, split ); } } } + ns.clear(); } return true; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/RegMask.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/RegMask.java index 79de3fbf..ec0c4e30 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/RegMask.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/RegMask.java @@ -4,11 +4,11 @@ import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.SB; /** RegMask - * A "register mask" - 1 bit set for each allowed register. In addition + * A "register mask" - 1 bit set for each allowed register. In addition, * "stack slot" registers may be allowed, effectively making the set infinite. * <p> * For smaller and simpler machines it suffices to make such masks an i64 or - * i128 (64 or 128 bit integers), and this presentation is by far the better + * i128 (64- or 128-bit integers), and this presentation is by far the better * way to go... if all register allocations can fit in this bit limitation. * The allocator will need bits for stack-based parameters and for splits * which cannot get a register. For a 32-register machine like the X86, add 1 @@ -28,7 +28,7 @@ public class RegMask { public RegMask(int bit) { if( bit < 64 ) _bits0 = 1L<<bit; - else _bits1 = 1L<<(bit=64); + else _bits1 = 1L<<(bit-64); } public RegMask(long bits ) { _bits0 = bits; } public RegMask(long bits0, long bits1 ) { _bits0 = bits0; _bits1 = bits1; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/NewNode.java b/chapter21/src/main/java/com/seaofnodes/simple/node/NewNode.java index 3d4bad5e..5a8c1b6b 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/NewNode.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/NewNode.java @@ -90,8 +90,8 @@ public class NewNode extends Node implements MultiNode { private RegMask _retMask; private RegMask _kills; public void cacheRegs(CodeGen code) { - _arg2Reg = code._mach.callArgMask(TypeFunPtr.CALLOC,2).firstReg(); - _arg3Mask = code._mach.callArgMask(TypeFunPtr.CALLOC,3); + _arg2Reg = code._mach.callArgMask(TypeFunPtr.CALLOC,2,0).firstReg(); + _arg3Mask = code._mach.callArgMask(TypeFunPtr.CALLOC,3,0); // Return mask depends on TFP (either GPR or FPR) _retMask = code._mach.retMask(TypeFunPtr.CALLOC); // Kill mask is all caller-saves, and any mirror stack slots for args diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/StoreNode.java b/chapter21/src/main/java/com/seaofnodes/simple/node/StoreNode.java index b9f99f4e..a6992f04 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/StoreNode.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/StoreNode.java @@ -84,6 +84,12 @@ public class StoreNode extends MemOpNode { } } + // Store of zero after alloc + if( mem() instanceof ProjNode prj && prj.in(0) instanceof NewNode && + prj.in(0)==ptr().in(0) && // Same NewNode memory & pointer + (val()._type==TypeInteger.ZERO || val()._type==Type.NIL ) ) + return mem(); + return null; } @@ -105,7 +111,7 @@ public class StoreNode extends MemOpNode { TypeMemPtr tmp = (TypeMemPtr)ptr()._type; if( tmp._obj.field(_name)._final && !_init ) return Parser.error("Cannot modify final field '"+_name+"'",_loc); - Type t = val()._type; + //Type t = val()._type; //return _init || t.isa(_declaredType) ? null : Parser.error("Cannot store "+t+" into field "+_declaredType+" "+_name,_loc); return null; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java index 63d418ff..7f6fe93c 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java @@ -21,7 +21,7 @@ public class CallARM extends CallNode implements MachNode, RIPRelSize { @Override public String label() { return op(); } @Override public String name() { return _name; } @Override public TypeFunPtr tfp() { return _tfp; } - @Override public RegMask regmap(int i) { return arm.callInMask(_tfp,i); } + @Override public RegMask regmap(int i) { return arm.callInMask(_tfp,i,fun()._maxArgSlot); } @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java index b3f55659..87dde38c 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java @@ -11,7 +11,7 @@ public class CallRRARM extends CallNode implements MachNode { @Override public RegMask regmap(int i) { return i==_inputs._len ? arm.RMASK // Function call target - : arm.callInMask(tfp(),i); // Normal argument + : arm.callInMask(tfp(),i,fun()._maxArgSlot); // Normal argument } @Override public RegMask outregmap() { return null; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/ParmARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/ParmARM.java index 4d0f95ab..b419fe0a 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/ParmARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/ParmARM.java @@ -9,7 +9,7 @@ public class ParmARM extends ParmNode implements MachNode { final RegMask _rmask; ParmARM(ParmNode parm) { super(parm); - _rmask = arm.callInMask(fun().sig(),_idx); + _rmask = arm.callInMask(fun().sig(),_idx,0); } @Override public RegMask regmap(int i) { return null; } @Override public RegMask outregmap() { return _rmask; } 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 5056bc74..260025d1 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 @@ -563,8 +563,8 @@ public class arm extends Machine { return (opcode << 26) | delta; } - @Override public RegMask callArgMask(TypeFunPtr tfp, int idx ) { return callInMask(tfp,idx); } - static RegMask callInMask(TypeFunPtr tfp, int idx ) { + @Override public RegMask callArgMask(TypeFunPtr tfp, int idx, int maxArgSlot ) { return callInMask(tfp,idx,maxArgSlot); } + static RegMask callInMask(TypeFunPtr tfp, int idx, int maxArgSlot ) { if( idx==0 ) return CodeGen.CODE._rpcMask; if( idx==1 ) return null; // Count floats in signature up to index diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java index 5aff94d3..ae9cdcd9 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java @@ -19,9 +19,9 @@ public class CallRISC extends CallNode implements MachNode, RIPRelSize { @Override public String op() { return "call"; } @Override public String label() { return op(); } @Override public RegMask regmap(int i) { - return riscv.callInMask(_tfp,i); + return riscv.callInMask(_tfp,i,fun()._maxArgSlot); } - @Override public RegMask outregmap() { return riscv.RPC_MASK; } + @Override public RegMask outregmap() { return null; } @Override public String name() { return _name; } @Override public TypeFunPtr tfp() { return _tfp; } @@ -29,8 +29,7 @@ public class CallRISC extends CallNode implements MachNode, RIPRelSize { // Short form +/-4K: beq r0,r0,imm12 // Long form: auipc rX,imm20/32; jal r0,[rX+imm12/32] enc.relo(this); - short rpc = enc.reg(this); - enc.add4(riscv.j_type(riscv.OP_JAL, rpc, 0)); + enc.add4(riscv.j_type(riscv.OP_JAL, riscv.RPC, 0)); } // Delta is from opcode start @@ -42,9 +41,8 @@ public class CallRISC extends CallNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - short rpc = enc.reg(this); if( opLen==4 ) { - enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, rpc, delta)); + enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, riscv.RPC, delta)); } else { throw Utils.TODO(); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java index 2afbbfa9..dcc53cbf 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java @@ -11,7 +11,7 @@ public class CallRRISC extends CallNode implements MachNode { @Override public RegMask regmap(int i) { return i==_inputs._len-1 ? riscv.RMASK // Function call target - : riscv.callInMask(tfp(),i); // Normal argument + : riscv.callInMask(tfp(),i,fun()._maxArgSlot); // Normal argument } @Override public RegMask outregmap() { return null; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ParmRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ParmRISC.java index 02d53560..0f8db4e5 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ParmRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ParmRISC.java @@ -9,7 +9,7 @@ public class ParmRISC extends ParmNode implements MachNode { final RegMask _rmask; ParmRISC(ParmNode parm) { super(parm); - _rmask = riscv.callInMask(fun().sig(),_idx); + _rmask = riscv.callInMask(fun().sig(),_idx,0); } @Override public RegMask regmap(int i) { return null; } @Override public RegMask outregmap() { return _rmask; } 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 47d1db75..54c6b828 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 @@ -253,8 +253,8 @@ public class riscv extends Machine { }; } - @Override public RegMask callArgMask( TypeFunPtr tfp, int idx ) { return callInMask(tfp,idx); } - static RegMask callInMask( TypeFunPtr tfp, int idx ) { + @Override public RegMask callArgMask( TypeFunPtr tfp, int idx, int maxArgSlot ) { return callInMask(tfp,idx,maxArgSlot); } + static RegMask callInMask( TypeFunPtr tfp, int idx, int maxArgSlot ) { if( idx==0 ) return RPC_MASK; if( idx==1 ) return null; // Count floats in signature up to index @@ -272,6 +272,7 @@ public class riscv extends Machine { return cargs[idx-2-fcnt]; } // Pass on stack slot(8 and higher) + if( maxArgSlot>0 ) throw Utils.TODO(); return new RegMask(MAX_REG + 1 + (idx - 2)); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java index b9d4fa8d..1a74f817 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java @@ -12,7 +12,7 @@ public class CallRX86 extends CallNode implements MachNode { @Override public RegMask regmap(int i) { return i==_inputs._len ? x86_64_v2.WMASK // Function call target - : x86_64_v2.callInMask(tfp(),i); // Normal argument + : x86_64_v2.callInMask(tfp(),i,fun()._maxArgSlot); // Normal argument } @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java index f6e67fb4..c97037e2 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java @@ -20,7 +20,7 @@ public class CallX86 extends CallNode implements MachNode, RIPRelSize { @Override public String label() { return op(); } @Override public String name() { return _name; } @Override public TypeFunPtr tfp() { return _tfp; } - @Override public RegMask regmap(int i) { return x86_64_v2.callInMask(_tfp,i); } + @Override public RegMask regmap(int i) { return x86_64_v2.callInMask(_tfp,i,fun()._maxArgSlot); } @Override public RegMask outregmap() { return null; } @Override public int nargs() { return nIns()-2; } // Minus control, memory, fptr diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ParmX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ParmX86.java index 7a6dbb13..5cfdd804 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ParmX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ParmX86.java @@ -9,7 +9,7 @@ public class ParmX86 extends ParmNode implements MachNode { final RegMask _rmask; ParmX86( ParmNode parm ) { super(parm); - _rmask = x86_64_v2.callInMask(fun().sig(),_idx); + _rmask = x86_64_v2.callInMask(fun().sig(),_idx,1/*RPC*/); } @Override public RegMask regmap(int i) { return null; } @Override public RegMask outregmap() { return _rmask; } 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 f965157b..960ea6f8 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 @@ -49,9 +49,16 @@ public class SplitX86 extends SplitNode { // Stack spills if( dst >= x86_64_v2.MAX_REG ) { - if( src >= x86_64_v2.MAX_REG ) - throw Utils.TODO(); // Very rare stack-stack move int off = enc._fun.computeStackOffset(enc._code,dst); + if( src >= x86_64_v2.MAX_REG ) { + // Rare stack-stack move. push [RSP+soff]; pop [RSP+doff] + int soff = enc._fun.computeStackOffset(enc._code,src); + enc.add1(0xFF); + x86_64_v2.indirectAdr(0, (short)-1/*index*/, (short)x86_64_v2.RSP, soff, 6, enc); + enc.add1(0x8F); + x86_64_v2.indirectAdr(0, (short)-1/*index*/, (short)x86_64_v2.RSP, off, 0, enc); + return; + } StoreX86.encVal(enc, srcX ? TypeFloat.F64 : TypeInteger.BOT, (short)x86_64_v2.RSP, (short)-1/*index*/, src, off, 0); return; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java index c906c3f2..76fb4e8d 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java @@ -44,7 +44,7 @@ public class StoreX86 extends MemOpX86 { case 0: enc.add1(_imm); break; case 1: enc.add2(_imm); break; case 2: enc.add4(_imm); break; - case 3: enc.add8(_imm); break; + case 3: enc.add4(_imm); break; // Limit of a 4 byte immediate } } else { encVal(enc,_declaredType,ptr,idx,src,_off,_scale); 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 23c12ae7..2b7fddb1 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 @@ -185,13 +185,13 @@ public class x86_64_v2 extends Machine { // Map from function signature and argument index to register. // Used to set input registers to CallNodes, and ParmNode outputs. - @Override public RegMask callArgMask( TypeFunPtr tfp, int idx ) { return callInMask(tfp,idx); } - static RegMask callInMask( TypeFunPtr tfp, int idx ) { + @Override public RegMask callArgMask( TypeFunPtr tfp, int idx, int maxArgSlot ) { return callInMask(tfp,idx,maxArgSlot); } + static RegMask callInMask( TypeFunPtr tfp, int idx, int maxArgSlot ) { 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); + case "SystemV" -> callSys5 (tfp,idx,maxArgSlot); + case "Win64" -> callWin64(tfp,idx,maxArgSlot); default -> throw Utils.TODO(); }; } @@ -230,11 +230,11 @@ public class x86_64_v2 extends Machine { R09_MASK, }; - static RegMask callWin64(TypeFunPtr tfp, int idx ) { + static RegMask callWin64(TypeFunPtr tfp, int idx, int maxArgSlot ) { // 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 new RegMask(MAX_REG+maxArgSlot+(idx-2)); return tfp.arg(idx-2) instanceof TypeFloat ? XMMS8 [idx-2] : WIN64_CALL[idx-2]; @@ -271,7 +271,7 @@ public class x86_64_v2 extends Machine { R09_MASK, }; - static RegMask callSys5(TypeFunPtr tfp, int idx ) { + static RegMask callSys5(TypeFunPtr tfp, int idx, int maxArgSlot ) { // 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 @@ -281,8 +281,8 @@ public class x86_64_v2 extends Machine { } 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+1/*RPC*/+nstk) - : icnt<6 ? SYS5_CALL[icnt] : new RegMask(MAX_REG+1/*RPC*/+nstk); + ? fcnt<8 ? XMMS8 [fcnt] : new RegMask(MAX_REG+maxArgSlot+nstk) + : icnt<6 ? SYS5_CALL[icnt] : new RegMask(MAX_REG+maxArgSlot+nstk); } static short maxArgSlotSys5(TypeFunPtr tfp) { int icnt=0, fcnt=0; // Count of ints, floats |
