From 8d303dfde40b919ad079b3afd426fdb3812283a3 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Fri, 14 Feb 2025 12:09:30 -0800 Subject: [PATCH] x86 call args, risc5 load/store regs --- .../com/seaofnodes/simple/codegen/IFG.java | 3 +- .../simple/codegen/ListScheduler.java | 14 +++--- .../seaofnodes/simple/node/CallEndNode.java | 2 +- .../com/seaofnodes/simple/node/CallNode.java | 2 + .../simple/node/cpus/riscv/LoadRISC.java | 11 +++-- .../simple/node/cpus/riscv/MemOpRISC.java | 28 ++++++++++-- .../simple/node/cpus/riscv/NewRISC.java | 4 +- .../simple/node/cpus/riscv/ProjRISC.java | 6 ++- .../simple/node/cpus/riscv/StoreRISC.java | 10 +++-- .../simple/node/cpus/riscv/riscv.java | 43 ++++++++++++++++--- .../node/cpus/x86_64_v2/CallEndX86.java | 8 ++-- .../simple/node/cpus/x86_64_v2/CallX86.java | 1 + .../simple/node/cpus/x86_64_v2/x86_64_v2.java | 3 +- 13 files changed, 98 insertions(+), 37 deletions(-) diff --git a/chapter20/src/main/java/com/seaofnodes/simple/codegen/IFG.java b/chapter20/src/main/java/com/seaofnodes/simple/codegen/IFG.java index d35a4503..c2057933 100644 --- a/chapter20/src/main/java/com/seaofnodes/simple/codegen/IFG.java +++ b/chapter20/src/main/java/com/seaofnodes/simple/codegen/IFG.java @@ -254,7 +254,8 @@ public static boolean color(int round, RegAlloc alloc) { // Convert the 2-D array of bits (a 1-D array of BitSets) into an // adjacency matrix. - for( int i=1; i 0 ) + CNT[single ? 2 : 1]++; + } } } diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/CallEndNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/CallEndNode.java index 5ffba1b5..6b3c5410 100644 --- a/chapter20/src/main/java/com/seaofnodes/simple/node/CallEndNode.java +++ b/chapter20/src/main/java/com/seaofnodes/simple/node/CallEndNode.java @@ -21,7 +21,7 @@ public class CallEndNode extends CFGNode implements MultiNode { @Override public boolean isMultiHead() { return true; } @Override public boolean blockHead() { return true; } - CallNode call() { return (CallNode)in(0); } + public CallNode call() { return (CallNode)in(0); } @Override StringBuilder _print1(StringBuilder sb, BitSet visited) { diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/CallNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/CallNode.java index 84670443..caa68fac 100644 --- a/chapter20/src/main/java/com/seaofnodes/simple/node/CallNode.java +++ b/chapter20/src/main/java/com/seaofnodes/simple/node/CallNode.java @@ -48,6 +48,8 @@ public String name() { int nargs() { return nIns()-3; } // Minus control, memory, fptr // args from input 2 to last; last is function input public Node fptr() { return _inputs.last(); } + // Error if not a TFP + public TypeFunPtr tfp() { return (TypeFunPtr)fptr()._type; } // Find the Call End from the Call public CallEndNode cend() { diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java index d283d594..c73c8e5f 100644 --- a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java +++ b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java @@ -8,8 +8,8 @@ import java.io.ByteArrayOutputStream; public class LoadRISC extends MemOpRISC { - LoadRISC(LoadNode ld) { - super(ld, ld); + LoadRISC(LoadNode ld, Node base, Node idx, int off) { + super(ld, base, idx, off, 0); } @Override public RegMask regmap(int i) { @@ -25,10 +25,9 @@ public class LoadRISC extends MemOpRISC { } @Override public void asm(CodeGen code, SB sb) { - throw Utils.TODO(); + sb.p(code.reg(this)).p(","); + asm_address(code,sb); } - @Override public String op() { - return "ld" +_sz; - } + @Override public String op() { return "ld" +_sz; } } diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java index 2e2b3a47..bcd7924e 100644 --- a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java +++ b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java @@ -10,17 +10,34 @@ import java.util.BitSet; -public class MemOpRISC extends MemOpNode implements MachNode{ +public class MemOpRISC extends MemOpNode implements MachNode { + final int _off; // Limit 32 bits + final int _imm; // Limit 32 bits final char _sz = (char)('0'+(1<<_declaredType.log_size())); - MemOpRISC(Node op, MemOpNode mop) { - super(op, mop); + MemOpRISC( MemOpNode mop, Node base, Node idx, int off, int imm) { + super(mop,mop); + assert base._type instanceof TypeMemPtr && !(base instanceof AddNode); + assert ptr() == base; + _inputs.setX(3,idx); + _off = off; + _imm = imm; } + // Store-based flavors have a value edge + MemOpRISC( MemOpNode mop, Node base, Node idx, int off, int imm, Node val ) { + this(mop,base,idx,off,imm); + _inputs.setX(4,val); + } + + Node idx() { return in(3); } + Node val() { return in(4); } // Only for stores, including op-to-memory + @Override public StringBuilder _printMach(StringBuilder sb, BitSet visited) { return sb.append(".").append(_name); } @Override public String label() { return op(); } @Override public Type compute() { throw Utils.TODO(); } @Override public Node idealize() { throw Utils.TODO(); } + // Register mask allowed on input i. @Override public RegMask regmap(int i) { throw Utils.TODO(); @@ -32,6 +49,9 @@ public class MemOpRISC extends MemOpNode implements MachNode{ SB asm_address(CodeGen code, SB sb) { - return sb; + sb.p("[").p(code.reg(ptr())).p("+"); + if( idx() != null ) sb.p(code.reg(idx())); + else sb.p(_off); + return sb.p("]"); } } diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java index 396762a8..b31b775a 100644 --- a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java +++ b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java @@ -16,12 +16,12 @@ public class NewRISC extends NewNode implements MachNode{ // Register mask allowed on input i, the size @Override public RegMask regmap(int i) { // Size - if( i==1 ) return riscv.RET_MASK; + if( i==1 ) return riscv.A0_MASK; // All the memory alias edges return null; } - @Override public RegMask outregmap() { throw Utils.TODO(); } + @Override public RegMask outregmap() { return null; } // Register mask allowed as a result. Pointer result in standard calling // convention. diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ProjRISC.java b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ProjRISC.java index 50c8865d..853c0729 100644 --- a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ProjRISC.java +++ b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ProjRISC.java @@ -13,8 +13,10 @@ public class ProjRISC extends ProjNode implements MachNode{ // Register mask allowed on input i. 0 for no register. @Override public RegMask regmap(int i) { return null; } - // Register mask allowed as a result. 0 for no register. - @Override public RegMask outregmap() { return null; } + // Register mask allowed as a result. + @Override public RegMask outregmap() { + return ((MachNode)in(0)).outregmap(_idx); + } // Encoding is appended into the byte array; size is returned @Override public int encoding(ByteArrayOutputStream bytes) { diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java index db081f17..3d382fcd 100644 --- a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java +++ b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java @@ -14,14 +14,16 @@ // sw rs2,offset(rs1) public class StoreRISC extends MemOpRISC { - StoreRISC( StoreNode st) { - super(st, st); + StoreRISC( StoreNode st, Node base, Node idx, int off, int imm, Node val ) { + super(st, base, idx, off, imm, val); } // Wider mask to store both GPRs and FPRs @Override public RegMask regmap(int i) { if( i==1 ) return riscv.MEM_MASK; if( i==2 ) return riscv.RMASK; + if( i==3 ) return riscv.RMASK; + if( i==4 ) return riscv.RMASK; throw Utils.TODO(); } @@ -35,7 +37,9 @@ public class StoreRISC extends MemOpRISC { } @Override public void asm(CodeGen code, SB sb) { - + asm_address(code,sb).p(","); + if( val()==null ) sb.p("#").p(_imm); + else sb.p(code.reg(val())); } @Override public String op() { return "st"+_sz; } diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java index dbdfab8b..c16ec94d 100644 --- a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java +++ b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java @@ -29,7 +29,7 @@ public class riscv extends Machine{ public static RegMask FMASK = new RegMask(0b11111111111111111111111111111111L< N address( N mop ) { + off = 0; // Reset + idx = null; + Node base = mop.ptr(); + // Skip/throw-away a ReadOnly, only used to typecheck + if( base instanceof ReadOnlyNode read ) base = read.in(1); + assert !(base instanceof AddNode) && base._type instanceof TypeMemPtr; // Base ptr always, not some derived + if( mop.off() instanceof ConstantNode con && con._con instanceof TypeInteger ti ) { + off = (int)ti.value(); + assert off == ti.value(); // In 32-bit range + } else { + idx = mop.off(); + } + return mop; } + } diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallEndX86.java b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallEndX86.java index f89276f0..3e856dc4 100644 --- a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallEndX86.java +++ b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallEndX86.java @@ -12,14 +12,16 @@ public class CallEndX86 extends CallEndNode implements MachNode { final TypeFunPtr _tfp; - CallEndX86( CallEndNode cend, TypeFunPtr tfp ) { + CallEndX86( CallEndNode cend ) { super(cend); - _tfp = tfp; + _tfp = (TypeFunPtr)(cend.call().fptr()._type); } @Override public String label() { return op(); } @Override public RegMask regmap(int i) { return null; } - @Override public RegMask outregmap() { + @Override public RegMask outregmap() { throw Utils.TODO(); } + @Override public RegMask outregmap(int idx) { + if( idx != 2 ) return null; return _tfp._ret instanceof TypeFloat ? x86_64_v2.RET_FMASK : x86_64_v2.RET_MASK; } diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java index f0f879f1..40e1a138 100644 --- a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java +++ b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java @@ -27,6 +27,7 @@ public class CallX86 extends CallNode implements MachNode { @Override public RegMask outregmap() { return null; } @Override public String name() { return _name; } + @Override public TypeFunPtr tfp() { return _tfp; } // Encoding is appended into the byte array; size is returned @Override public int encoding(ByteArrayOutputStream bytes) { diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java index 3acff7ac..98fe0c83 100644 --- a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java +++ b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java @@ -155,7 +155,7 @@ static RegMask callInMask( int idx ) { case AddNode add -> add(add); case AndNode and -> and(and); case BoolNode bool -> cmp(bool); - case CallEndNode cend -> new CallEndNode((CallNode)cend.in(0)); + case CallEndNode cend -> new CallEndX86(cend); case CallNode call -> call(call); case CProjNode c -> new CProjNode(c); case ConstantNode con -> con(con); @@ -414,6 +414,7 @@ private N address( N mop ) { } return mop; } + private int imm( Node xval ) { assert val==null && imm==0; if( xval instanceof ConstantNode con && con._con instanceof TypeInteger ti ) {