diff options
| author | Cliff Click <cliffc@acm.org> | 2025-04-09 17:12:56 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2025-04-09 17:12:56 -0700 |
| commit | 074f718a104dbbb8b1b0a2205c176659a27dfd9f (patch) | |
| tree | 33168e69e4cf1cf72e17f722eb76b1eb2201fa9d | |
| parent | b32c6a879c0be7aebad25fabae6f0a24d5670366 (diff) | |
| download | Simple-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???
17 files changed, 167 insertions, 108 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); } } diff --git a/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java index a5316d62..631862e9 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java +++ b/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java @@ -140,9 +140,8 @@ public class Chapter21Test { assertEquals(60+0,R5.ld8(p2)); } - @Ignore @Test public void testArgCount() throws IOException { - String arg_count = ""; + String arg_count = "153.900000\n"; TestC.run("arg_count", arg_count); } } diff --git a/chapter21/src/test/java/com/seaofnodes/simple/progs/arg_count.c b/chapter21/src/test/java/com/seaofnodes/simple/progs/arg_count.c index 60637b1e..f0cae2b8 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/progs/arg_count.c +++ b/chapter21/src/test/java/com/seaofnodes/simple/progs/arg_count.c @@ -1,11 +1,9 @@ #include <stdio.h> -#include <stdbool.h> -#include <stdlib.h> -extern int test(); +extern double addAll( long long i0, double f1, long long i2, double f3, long long i4, double f5, long long i6, double f7, long long i8, double f9, long long i10, double f11, long long i12, double f13, long long i14, double f15, long long i16, double f17 ); int main() { - int result = test(); - printf("d\n", result); -return 0; -}
\ No newline at end of file + double result = addAll( 0, 1.1, 2, 3.1, 4, 5.1, 6, 7.1, 8, 9.1, 10, 11.1, 12, 13.1, 14, 15.1, 16, 17.1 ); + printf("%f\n", result); + return 0; +} diff --git a/chapter21/src/test/java/com/seaofnodes/simple/progs/arg_count.smp b/chapter21/src/test/java/com/seaofnodes/simple/progs/arg_count.smp index 58dbffba..102ead99 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/progs/arg_count.smp +++ b/chapter21/src/test/java/com/seaofnodes/simple/progs/arg_count.smp @@ -1,7 +1,6 @@ -val addAll = { int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, int n, int o -> - return a+b+c+d+e+f+g+h+i+j+k+l+m+n+o; +// -*- mode: java; -*- +val addAll = { int i0, flt f1, int i2, flt f3, int i4, flt f5, int i6, flt f7, int x8, flt f9, int i10, flt f11, int i12, flt f13, int i14, flt f15, int x16, flt f17 -> + return + i0 + f1+ i2+ f3+ i4+ f5+ i6+ f7+ x8 +f9 + + i10+f11+i12+f13+i14+f15+x16+f17; }; - -val test = { -> - return addAll(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15) + addAll(16,17,18,19,20,21,22,23,24,25,26,27,28,29,30); -};
\ No newline at end of file diff --git a/chapter21/src/test/java/com/seaofnodes/simple/progs/brain_fuck.smp b/chapter21/src/test/java/com/seaofnodes/simple/progs/brain_fuck.smp index 69e63ba3..d91eb24f 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/progs/brain_fuck.smp +++ b/chapter21/src/test/java/com/seaofnodes/simple/progs/brain_fuck.smp @@ -1,3 +1,4 @@ +// -*- mode: java; -*- val brain_fuck = { -> u8[] !program = new u8[106];program[0] = 43;program[1] = 43;program[2] = 43;program[3] = 43;program[4] = 43;program[5] = 43;program[6] = 43;program[7] = 43;program[8] = 91;program[9] = 62;program[10] = 43;program[11] = 43;program[12] = 43;program[13] = 43;program[14] = 91;program[15] = 62;program[16] = 43;program[17] = 43;program[18] = 62;program[19] = 43;program[20] = 43;program[21] = 43;program[22] = 62;program[23] = 43;program[24] = 43;program[25] = 43;program[26] = 62;program[27] = 43;program[28] = 60;program[29] = 60;program[30] = 60;program[31] = 60;program[32] = 45;program[33] = 93;program[34] = 62;program[35] = 43;program[36] = 62;program[37] = 43;program[38] = 62;program[39] = 45;program[40] = 62;program[41] = 62;program[42] = 43;program[43] = 91;program[44] = 60;program[45] = 93;program[46] = 60;program[47] = 45;program[48] = 93;program[49] = 62;program[50] = 62;program[51] = 46;program[52] = 62;program[53] = 45;program[54] = 45;program[55] = 45;program[56] = 46;program[57] = 43;program[58] = 43;program[59] = 43;program[60] = 43;program[61] = 43;program[62] = 43;program[63] = 43;program[64] = 46;program[65] = 46;program[66] = 43;program[67] = 43;program[68] = 43;program[69] = 46;program[70] = 62;program[71] = 62;program[72] = 46;program[73] = 60;program[74] = 45;program[75] = 46;program[76] = 60;program[77] = 46;program[78] = 43;program[79] = 43;program[80] = 43;program[81] = 46;program[82] = 45;program[83] = 45;program[84] = 45;program[85] = 45;program[86] = 45;program[87] = 45;program[88] = 46;program[89] = 45;program[90] = 45;program[91] = 45;program[92] = 45;program[93] = 45;program[94] = 45;program[95] = 45;program[96] = 45;program[97] = 46;program[98] = 62;program[99] = 62;program[100] = 43;program[101] = 46;program[102] = 62;program[103] = 43;program[104] = 43;program[105] = 46; int d = 0; |
