From de2d08cfaa659d1c22f2cbbfa84748bd5c307ac4 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Fri, 21 Mar 2025 15:12:05 -0700 Subject: Stack slot updates Spill code work --- .../com/seaofnodes/simple/codegen/Encoding.java | 38 +++++++++++++++- .../com/seaofnodes/simple/codegen/Machine.java | 28 +++++++++++- .../com/seaofnodes/simple/codegen/RegAlloc.java | 22 +++++++-- .../java/com/seaofnodes/simple/node/FunNode.java | 34 ++++++++++++++ .../java/com/seaofnodes/simple/node/MachNode.java | 3 -- .../com/seaofnodes/simple/node/cpus/arm/arm.java | 6 ++- .../seaofnodes/simple/node/cpus/riscv/FunRISC.java | 25 +++++++++- .../seaofnodes/simple/node/cpus/riscv/RetRISC.java | 13 ++++-- .../simple/node/cpus/riscv/SplitRISC.java | 39 ++++++++++++++-- .../seaofnodes/simple/node/cpus/riscv/riscv.java | 28 ++++++++++-- .../simple/node/cpus/x86_64_v2/FunX86.java | 33 +++++++++++++- .../simple/node/cpus/x86_64_v2/RetX86.java | 17 ++++++- .../simple/node/cpus/x86_64_v2/SplitX86.java | 30 ++++++++++-- .../simple/node/cpus/x86_64_v2/x86_64_v2.java | 53 +++++++++++++++------- .../com/seaofnodes/simple/print/ASMPrinter.java | 13 ++++-- .../java/com/seaofnodes/simple/Chapter21Test.java | 1 - 16 files changed, 334 insertions(+), 49 deletions(-) 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 e227eaff..67eeb3c2 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java @@ -231,12 +231,19 @@ public class Encoding { // Write encoding bits in order into a big byte array. // Record opcode start and length. + public FunNode _fun; // Currently encoding function private void writeEncodings() { _opStart= new int [_code.UID()]; _opLen = new byte[_code.UID()]; for( CFGNode bb : _code._cfg ) { - if( !(bb instanceof MachNode) || bb instanceof FunNode ) + if( !(bb instanceof MachNode mach0) ) _opStart[bb._nid] = _bits.size(); + else if( bb instanceof FunNode fun ) { + _fun = fun; // Currently encoding function + _opStart[bb._nid] = _bits.size(); + mach0.encoding( this ); + _opLen[bb._nid] = (byte) (_bits.size() - _opStart[bb._nid]); + } for( Node n : bb._outputs ) { if( n instanceof MachNode mach && !(n instanceof FunNode) ) { _opStart[n._nid] = _bits.size(); @@ -365,4 +372,33 @@ public class Encoding { ((RIPRelSize)src).patch(this, start, _opLen[src._nid], target - start); } } + + + // Actual stack layout is up to each CPU. + // X86, with too many args & spills: + // | CALLER | + // | argN | // slot 1, required by callER + // +--------+ + // | RPC | // slot 0, required by callER + // | callee | // slot 3, callEE + // | callee | // slot 2, callEE + // | PAD16 | + // +--------+ + + // RISC/ARM, with too many args & spills: + // | CALLER | + // | argN | // slot 0, required by callER + // +--------+ + // | callee | // slot 3, callEE: might be RPC + // | callee | // slot 2, callEE + // | callee | // slot 1, callEE + // | PAD16 | + // +--------+ + private void frameSize() { + for( Node n : _code._start.outs() ) { + if( n instanceof FunNode fun ) { + throw Utils.TODO(); + } + } + } } 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 fbc3f6c2..295eab0a 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Machine.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Machine.java @@ -5,8 +5,6 @@ import com.seaofnodes.simple.node.*; abstract public class Machine { // Human readable machine name. Something like "x86-64" or "arm" or "risc5" public abstract String name(); - // Human-readable name for a register number, e.g. "RAX" or "R0" - public abstract String reg( int reg ); // Default opcode size for printing; 4 bytes for most 32-bit risc chips public int defaultOpSize() { return 4; } // Create a split op; any register to any register, including stack slots @@ -21,4 +19,30 @@ abstract public class Machine { public abstract IfNode never( CFGNode ctrl ); // Instruction select from ideal nodes public abstract Node instSelect( Node n ); + + // 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. + // X86, with too many args & spills: + // | CALLER | + // | argN | // slot 1, required by callER + // +--------+ + // | RPC | // slot 0, required by callER + // | callee | // slot 3, callEE + // | callee | // slot 2, callEE + // | PAD16 | + // +--------+ + + // RISC/ARM, with too many args & spills: + // | CALLER | + // | argN | // slot 0, required by callER + // +--------+ + // | callee | // slot 3, callEE: might be RPC + // | callee | // slot 2, callEE + // | callee | // slot 1, callEE + // | PAD16 | + // +--------+ + public abstract int stackSlot( int reg ); + // Human-readable name for a register number, e.g. "RAX" or "R0" + public abstract String reg( int reg ); } 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 4b3557cd..f323ea22 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java @@ -141,9 +141,15 @@ public class RegAlloc { public void regAlloc() { // Insert callee-save registers - for( CFGNode bb : _code._cfg ) + FunNode lastFun=null; + for( CFGNode bb : _code._cfg ) { if( bb instanceof FunNode fun ) - insertCalleeSave(fun); + insertCalleeSave(lastFun=fun); + // Leaf routine, or not? + // X86 requires 16b RSP aligned if NOT leaf + if( bb instanceof CallNode ) lastFun._hasCalls = true; + } + // Top driver: repeated rounds of coloring and splitting. byte round=0; @@ -460,11 +466,21 @@ public class RegAlloc { // ----------------------- // POST PASS: Remove empty spills that biased-coloring made 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 ) + ret.fun()._maxSlot = (short)maxSlot; for( int j=0; j 0 ? "addi" : "ret"; + } // Correct Nodes outside the normal edges @Override public void postSelect(CodeGen code) { FunNode fun = (FunNode)rpc().in(0); @@ -20,12 +22,17 @@ public class RetRISC extends ReturnNode implements MachNode{ @Override public RegMask regmap(int i) { return riscv.retMask(_fun.sig(),i); } @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { + int frameAdjust = ((FunRISC)fun())._frameAdjust; + if( frameAdjust > 0 ) + enc.add4(riscv.i_type(riscv.I_TYPE, riscv.SP, 0, riscv.SP, (frameAdjust*-8) & 0xFFF)); short rpc = enc.reg(rpc()); - int body = riscv.i_type(0x67, riscv.ZERO, 0, rpc, 0); - enc.add4(body); + enc.add4(riscv.i_type(0x67, riscv.ZERO, 0, rpc, 0)); } @Override public void asm(CodeGen code, SB sb) { + int frameAdjust = ((FunRISC)fun())._frameAdjust; + if( frameAdjust>0 ) + 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 A0 or FA0), RPC (always R1) and then diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java index 54a6db38..c6a31bdb 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.node.SplitNode; @@ -9,9 +10,39 @@ public class SplitRISC extends SplitNode { @Override public RegMask regmap(int i) { return riscv.SPLIT_MASK; } @Override public RegMask outregmap() { return riscv.SPLIT_MASK; } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this ); - short src1 = enc.reg(in(1)); - int body = riscv.r_type(riscv.OP,dst,0,src1,riscv.ZERO,0); - enc.add4(body); + short dst = enc.reg(this ); + short src = enc.reg(in(1)); + + // Flag for being either XMM or stack + boolean dstX = dst >= riscv.F_OFFSET; + boolean srcX = src >= riscv.F_OFFSET; + + if( dst >= riscv.MAX_REG ) { + // Store to SP + if( src >= riscv.MAX_REG ) + throw Utils.TODO(); // Very rare stack-stack move + int off = enc._fun.computeStackSlot(dst - riscv.MAX_REG)*8; + throw Utils.TODO(); + } + if( src >= riscv.MAX_REG ) { + // Load from SP + int off = enc._fun.computeStackSlot(src - riscv.MAX_REG)*8; + throw Utils.TODO(); + } + // pick opcode based on regs + if( !dstX && !srcX ) { + // GPR->GPR + enc.add4(riscv.r_type(riscv.OP,dst,0,src,riscv.ZERO,0)); + } else if( dstX && srcX ) { + // FPR->FPR + throw Utils.TODO(); + } else if( dstX && !srcX ) { + //GPR->FPR + throw Utils.TODO(); + } else if( !dstX && srcX ) { + //FPR->GPR + throw Utils.TODO(); + } + } } 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 dceef330..72ca0beb 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 @@ -28,9 +28,9 @@ public class riscv extends Machine { static int FA6 = 48, FA7 = 49, FS2 = 50, FS3 = 51, FS4 = 52, FS5 = 53, FS6 = 54, FS7 = 55; static int FS8 = 56, FS9 = 57, FS10 = 58, FS11 = 59, FT8 = 60, FT9 = 61, FT10 = 62, FT11 = 63; - static final int MAX_REG = 61; + static final int MAX_REG = 64; - static final int F_OFFSET = 31; + static final int F_OFFSET = 32; static final String[] REGS = new String[] { "zero","rpc" , "sp" , "gp" , "tp" , "t0" , "t1" , "t2" , @@ -245,6 +245,21 @@ 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 ) { + // Count floats in signature up to index + int fcnt=0; + for( int i=0; i= XMMS.length ) + throw Utils.TODO(); + RegMask[] cargs = CALLINMASK; + if( tfp.nargs()-fcnt >= cargs.length ) + throw Utils.TODO(); + return 0; // No stack args + } + // callee saved(riscv) static final long CALLEE_SAVE = (1L<< S0) | (1L<< S1) | (1L<< S2 ) | (1L<< S3 ) | @@ -289,9 +304,16 @@ public class riscv extends Machine { } @Override public String reg( int reg ) { - return reg < REGS.length ? REGS[reg] : "[rsp+"+(reg-REGS.length)*4+"]"; + return reg < REGS.length ? REGS[reg] : "[rsp+"+(reg-REGS.length)*8+"]"; + } + + // Stack slots, in units of 8 bytes. + @Override public int stackSlot( int reg ) { + return reg < REGS.length ? -1 : reg-REGS.length; } + + // Return a MachNode unconditional branch @Override public CFGNode jump() { return new UJmpRISC(); 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 22cb8698..55b2b8af 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 @@ -1,13 +1,44 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.MachNode; public class FunX86 extends FunNode implements MachNode { FunX86( FunNode fun ) { super(fun); } + @Override public String op() { return "addi"; } @Override public RegMask regmap(int i) { return null; } @Override public RegMask outregmap() { return null; } - @Override public void encoding( Encoding enc ) { } @Override public void postSelect(CodeGen code) { code.link(this); } + + // Actual stack layout is up to each CPU. + // X86, with too many args & spills: + // | CALLER | + // | argN | // slot 1, required by callER + // +--------+ + // | RPC | // slot 0, required by callER + // | callee | // slot 3, callEE + // | callee | // slot 2, callEE + // | PAD16 | + // +--------+ + @Override public void encoding( Encoding enc ) { + // Stack frame size: _maxSlot - max(arg), padded to 16. + _maxArgSlot = x86_64_v2.maxSlot(enc._fun.sig()); + int sz = _maxSlot - _maxArgSlot; + // If non-leaf function, pad to 16b + if( _hasCalls ) sz = ((sz+1) & -2)+1; + assert x86_64_v2.imm8(sz*8); + _frameAdjust = (short)sz; + if( sz == 0 ) return; // Skip if no frame adjust + + // opcode: 0x83, addi rsp with immediate 8 + enc.add1( 0x83 ); + enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0, x86_64_v2.RSP) ); + enc.add1(sz*8); + } + + @Override public void asm(CodeGen code, SB sb) { + sb.p("rsp += #").p(_frameAdjust*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 34458e8f..bc4d5805 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 @@ -6,7 +6,9 @@ import com.seaofnodes.simple.node.*; public class RetX86 extends ReturnNode implements MachNode { RetX86( ReturnNode ret, FunNode fun ) { super(ret, fun); fun.setRet(this); } - @Override public String op() { return "ret"; } + @Override public String op() { + return ((FunX86)fun())._frameAdjust > 0 ? "addi" : "ret"; + } // Correct Nodes outside the normal edges @Override public void postSelect(CodeGen code) { FunNode fun = (FunNode)rpc().in(0); @@ -15,9 +17,20 @@ public class RetX86 extends ReturnNode implements MachNode { } @Override public RegMask regmap(int i) { return x86_64_v2.retMask(_fun.sig(),i); } @Override public RegMask outregmap() { return null; } - @Override public void encoding( Encoding enc ) { enc.add1(0xC3); } + @Override public void encoding( Encoding enc ) { + int frameAdjust = ((FunX86)fun())._frameAdjust; + if( frameAdjust > 0 ) { + enc.add1( 0x83 ); + enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0, x86_64_v2.RSP) ); + enc.add1(frameAdjust*-8); + } + enc.add1(0xC3); + } @Override public void asm(CodeGen code, SB sb) { + int frameAdjust = ((FunX86)fun())._frameAdjust; + if( frameAdjust>0 ) + 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 21c20b81..15657de0 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 @@ -1,6 +1,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.Node; import com.seaofnodes.simple.node.SplitNode; @@ -13,7 +14,6 @@ public class SplitX86 extends SplitNode { // Need to handle 8 cases: . reg->reg, reg->xmm, reg->flags, xmm->reg, xmm->xmm, xmm->flags, flags->reg, flags->xmm, // flags->flags. - // Currently not handling flags // Encoding is appended into the byte array; size is returned @Override public void encoding( Encoding enc ) { // REX.W + 8B /r MOV r64, r/m64 @@ -39,10 +39,34 @@ public class SplitX86 extends SplitNode { return; } + // Flag for being either XMM or stack boolean dstX = dst >= x86_64_v2.XMM_OFFSET; boolean srcX = src >= x86_64_v2.XMM_OFFSET; - if( dstX ) dst -= x86_64_v2.XMM_OFFSET; - if( srcX ) src -= x86_64_v2.XMM_OFFSET; + + // Stack spills + if( dst >= x86_64_v2.MAX_REG ) { + if( src >= x86_64_v2.MAX_REG ) + throw Utils.TODO(); // Very rare stack-stack move + // TODO: Missing FP 0x66 prefix + if( srcX ) { src -= (short)x86_64_v2.XMM_OFFSET; enc.add1(0x66); } + int off = enc._fun.computeStackSlot(dst - x86_64_v2.MAX_REG)*8; + enc.add1(x86_64_v2.rex(src, x86_64_v2.RSP, -1)); + enc.add1( 0x89 ); + x86_64_v2.indirectAdr(0, (short)-1, (short)x86_64_v2.RSP, off, src, enc); + return; + } + if( src >= x86_64_v2.MAX_REG ) { + if( dstX ) { dst -= (short)x86_64_v2.XMM_OFFSET; enc.add1(0x66); } + int off = enc._fun.computeStackSlot(src - x86_64_v2.MAX_REG)*8; + enc.add1(x86_64_v2.rex(dst, x86_64_v2.RSP, -1)); + enc.add1( 0x8B ); + x86_64_v2.indirectAdr(0, (short)-1, (short)x86_64_v2.RSP, off, dst, enc); + return; + } + + // reg-reg move. Adjust numbering for GPR vs FPR reg set + if( dstX ) dst -= (short) x86_64_v2.XMM_OFFSET; + if( srcX ) src -= (short) x86_64_v2.XMM_OFFSET; // 0x66 if moving between register classes if( dstX ^ srcX ) enc.add1(0x66); 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 dc3b86a8..9d7b1a26 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 @@ -13,8 +13,8 @@ public class x86_64_v2 extends Machine { @Override public String name() { return "x86_64_v2"; } @Override public int defaultOpSize() { return 5; } - public static int RAX = 0, RCX = 1, RDX = 2, RBX = 3, RSP = 4, RBP = 5, RSI = 6, RDI = 7; - public static int R08 = 8, R09 = 9, R10 = 10, R11 = 11, R12 = 12, R13 = 13, R14 = 14, R15 = 15; + public static final int RAX = 0, RCX = 1, RDX = 2, RBX = 3, RSP = 4, RBP = 5, RSI = 6, RDI = 7; + public static final int R08 = 8, R09 = 9, R10 = 10, R11 = 11, R12 = 12, R13 = 13, R14 = 14, R15 = 15; public static final int XMM0 = 16, XMM1 = 17, XMM2 = 18, XMM3 = 19, XMM4 = 20, XMM5 = 21, XMM6 = 22, XMM7 = 23; public static final int XMM8 = 24, XMM9 = 25, XMM10 = 26, XMM11 = 27, XMM12 = 28, XMM13 = 29, XMM14 = 30, XMM15 = 31; @@ -118,7 +118,7 @@ public class x86_64_v2 extends Machine { // don't need to use REX if 0x40. public static byte rexF(int reg, int ptr, int idx, boolean wide, Encoding enc) { int rex = rex(reg, ptr, idx, wide); - if (rex == 0x40) return 0; + if (rex == REX) return 0; enc.add1(rex); return 1; } @@ -172,12 +172,18 @@ public class x86_64_v2 extends Machine { "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", - "flags", "[rsp-4]", + "flags", }; @Override public String reg( int reg ) { - return reg < REGS.length ? REGS[reg] : "[rsp+"+(reg-REGS.length)*4+"]"; + return reg < REGS.length ? REGS[reg] : "[rsp+"+(reg-REGS.length)*8+"]"; } + // Stack slots, in units of 8 bytes. + @Override public int stackSlot( int reg ) { + return reg < REGS.length ? -1 : reg-REGS.length; + } + + // WIN64(param passing) static RegMask[] CALLINMASK_WIN64 = new RegMask[] { RCX_MASK, @@ -227,6 +233,25 @@ public class x86_64_v2 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 ) { + // Count floats in signature up to index + int fcnt=0; + for( int i=0; i= 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 0; // No stack args + } + // Return single int/ptr register. Used by CallEnd output and Return input. static RegMask retMask( TypeFunPtr tfp ) { return tfp.ret() instanceof TypeFloat ? XMM0_MASK : RAX_MASK; @@ -236,9 +261,9 @@ public class x86_64_v2 extends Machine { // caller saved(systemv) static final long SYSTEM5_CALLER_SAVE = (1L<< RAX) | (1L<< RCX) | (1L<< RDX) | - (1L << RDI) | (1L << RSI) | - (1L << R08) | (1L << R09) | (1L << R10) | (1L << R11) | - (1L << FLAGS) | // Flags are killed + (1L << RDI) | (1L << RSI) | + (1L << R08) | (1L << R09) | (1L << R10) | (1L << R11) | + (1L << FLAGS) | // Flags are killed // All FP regs are killed FP_BITS; static final RegMask SYSTEM5_CALLER_SAVE_MASK = new RegMask(SYSTEM5_CALLER_SAVE); @@ -255,16 +280,13 @@ public class x86_64_v2 extends Machine { static RegMask x86CallerSave() { return switch (CodeGen.CODE._callingConv) { - case "SystemV" -> SYSTEM5_CALLER_SAVE_MASK; - case "Win64" -> WIN64_CALLER_SAVE_MASK; - default -> throw new IllegalArgumentException("Unknown calling convention: " + CodeGen.CODE._callingConv); + case "SystemV" -> SYSTEM5_CALLER_SAVE_MASK; + case "Win64" -> WIN64_CALLER_SAVE_MASK; + default -> throw new IllegalArgumentException("Unknown calling convention: " + CodeGen.CODE._callingConv); }; } - @Override - public RegMask callerSave() { - return x86CallerSave(); - } + @Override public RegMask callerSave() { return x86CallerSave(); } static final RegMask SYSTEM5_CALLEE_SAVE_MASK; static final RegMask WIN64_CALLEE_SAVE_MASK; @@ -293,7 +315,6 @@ public class x86_64_v2 extends Machine { } @Override public RegMask calleeSave() { return x86CalleeSave(); } - static final RegMask[] WIN64_RET_MASKS, SYS5_RET_MASKS; static { WIN64_RET_MASKS = makeRetMasks( WIN64_CALLEE_SAVE_MASK); 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 ab997ab9..efa94b8b 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java @@ -56,7 +56,8 @@ public abstract class ASMPrinter { fun.sig().print(sb); sb.p("---------------------------").nl(); - + if( fun._frameAdjust != 0 ) + iadr = doInst(iadr,sb,code,cfgidx,fun,true,true); while( !(code._cfg.at(cfgidx) instanceof ReturnNode) ) iadr = doBlock(iadr,sb,code,fun,cfgidx++); @@ -113,7 +114,8 @@ public abstract class ASMPrinter { if( postAlloc && n instanceof CalleeSaveNode ) return iadr; if( postEncode && n instanceof ProjNode ) return iadr; if( n instanceof MemMergeNode ) return iadr; - final int encWidth = code._mach.defaultOpSize()*2; + final int dopz = code._mach.defaultOpSize(); + final int encWidth = dopz*2; // All blocks ending in a Region will need to either fall into or jump // to this block. Until the post-reg-alloc block layout cleanup, we @@ -192,13 +194,14 @@ public abstract class ASMPrinter { // Multiple ops, template style, no RA, no scheduling. Print out // one-line-per-newline, with encoding bits up front. int size = code._encoding._opLen[n._nid]; - int off = code._mach.defaultOpSize(); + int off = Math.min(size,dopz); while( isMultiOp!=null ) { sb.hex2(iadr).p(" "); - int len = Math.min(off,size); + int len = Math.min(size-off,dopz); for( int i=0; i>3; if( delta==0 ) delta = 1; assertEquals("Expect spills:",spills,code._regAlloc._spillScaled,delta); -- cgit v1.2.3