diff options
| author | Cliff Click <cliffc@acm.org> | 2025-03-18 00:34:34 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2025-03-18 00:34:34 -0700 |
| commit | 5faaadb794ad864ce3e26ed6a5fc4457a8aa2f15 (patch) | |
| tree | 7bd374540680f5b36fbe9ee0af764d5d4f5f2e67 /chapter21/src/main/java/com | |
| parent | 9929bca5617c2b0134ae16fb174df8d247443af8 (diff) | |
| download | Simple-5faaadb794ad864ce3e26ed6a5fc4457a8aa2f15.tar.gz Simple-5faaadb794ad864ce3e26ed6a5fc4457a8aa2f15.zip | |
progress on patching calls
Diffstat (limited to 'chapter21/src/main/java/com')
23 files changed, 159 insertions, 112 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 a2c836a8..c6ac68c4 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java @@ -230,7 +230,7 @@ public class CodeGen { for( int i=0; i < x.nIns(); i++ ) x._inputs.set(i, _instSelect(x.in(i),map) ); if( x instanceof MachNode mach ) - mach.postSelect(); // Post selection action + mach.postSelect(this); // Post selection action // Updates forward edges only. n._outputs.clear(); @@ -297,45 +297,6 @@ public class CodeGen { return this; } - public CodeGen exportELF() { - assert _phase == Phase.Encoding; - _phase = Phase.Export; - ElfFile obj = new ElfFile(this); - obj.export(); - return this; - } - - public static void print_as_hex(Encoding enc) { - for (byte b : enc._bits.toByteArray()) { - System.out.print(String.format("%02X", b)); - } - System.out.println(); - } - - public void print_as_hex() { - for (byte b : _encoding._bits.toByteArray()) { - System.out.print(String.format("%02X", b)); - } - System.out.println(); - } - - //// Debug purposes for now -// public CodeGen printENCODING() { -// ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); -// -// for(Node bb : CodeGen.CODE._cfg) { -// for(Node n: bb.outs()) { -// if(n instanceof MachNode) { -// ((MachNode) n).encoding(E); -// } -// } -// } -// -// print_as_hex(outputStream); -// // Get the raw bytes from the output stream -// return this; -// } - public String reg(Node n) { if( _phase.ordinal() >= Phase.RegAlloc.ordinal() ) { String s = _regAlloc.reg(n); @@ -361,6 +322,16 @@ public class CodeGen { public byte[] binary() { throw Utils.TODO(); } // --------------------------- + // Exporting to external formats + public CodeGen exportELF() { + assert _phase == Phase.Encoding; + _phase = Phase.Export; + ElfFile obj = new ElfFile(this); + obj.export(); + return this; + } + + // --------------------------- SB asm(SB sb) { return ASMPrinter.print(sb,this); } public String asm() { return asm(new SB()).toString(); } @@ -379,4 +350,35 @@ public class CodeGen { // Debugging helper public Node f(int idx) { return _stop.find(idx); } + + public static void print_as_hex(Encoding enc) { + for (byte b : enc._bits.toByteArray()) { + System.out.print(String.format("%02X", b)); + } + System.out.println(); + } + + public void print_as_hex() { + for (byte b : _encoding._bits.toByteArray()) { + System.out.print(String.format("%02X", b)); + } + System.out.println(); + } + + //// Debug purposes for now +// public CodeGen printENCODING() { +// ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); +// +// for(Node bb : CodeGen.CODE._cfg) { +// for(Node n: bb.outs()) { +// if(n instanceof MachNode) { +// ((MachNode) n).encoding(E); +// } +// } +// } +// +// print_as_hex(outputStream); +// // Get the raw bytes from the output stream +// return this; +// } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java index b263ea6b..c01eadd1 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java @@ -284,9 +284,10 @@ public class ElfFile { // create .text relocations DataSection text_rela = new DataSection(".rela.text", 4 /* SHT_RELA */); - for (Map.Entry<Node,TypeFunPtr> e : _code._encoding._funcRelos.entrySet()) { - int nid = e.getKey()._nid; - int sym_id = _funcs.get(e.getValue())._index; + for( Node n : _code._encoding._externals) { + int nid = n._nid; + TypeFunPtr tfp = n instanceof CallNode call ? call.tfp() : (TypeFunPtr)n._type; + int sym_id = _funcs.get(tfp)._index; int offset = _code._encoding._opStart[nid] + _code._encoding._opLen[nid] - 4; // u64 offset 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 6ddaa1f4..7cdbf1c8 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java @@ -42,18 +42,12 @@ public class Encoding { public byte[] buf() { return buf; } void set( byte[] buf0, int count0 ) { buf=buf0; count=count0; } }; - final public BAOS _bits; + final public BAOS _bits = new BAOS(); public int [] _opStart; // Start of opcodes, by _nid public byte[] _opLen; // Length of opcodes, by _nid - Encoding( CodeGen code ) { - _code = code; - _bits = new BAOS(); - _bigCons = new HashMap<>(); - _jmps = new HashMap<>(); - _funcRelos = new HashMap<>(); - } + Encoding( CodeGen code ) { _code = code; } // Shortcut to the defining register public short reg(Node n) { @@ -87,31 +81,30 @@ public class Encoding { } - // Relocation thinking: - // `encoding()` calls back with info (TFP needed, branch target needed). - // Record start of op & TFP/target info. - - // During some future RELO phase, after TFP layout/targets known - // call back with `ReloNode.patch(byte[],src_offset,TFP,dst_offset)` - // X86 gets a special pass for expanding short jumps. - - public final HashMap<Node,TypeFunPtr> _funcRelos; - public void relo( Node relo, TypeFunPtr t ) { - _funcRelos.put(relo, t); + // Nodes need "relocation" patching; things done after code is placed. + private final Ary<Node> _internals = new Ary<>(Node.class); + public final Ary<Node> _externals = new Ary<>(Node.class); + public Encoding relo( CallNode call ) { + (call.external() ? _externals : _internals).add(call); + return this; } + public Encoding reloTFP( ConstantNode con ) { _internals.add(con); return this; } + public void relo( NewNode nnn ) { // TODO: record alloc relocation info } // Store t as a 32/64 bit constant in the code space; generate RIP-relative // addressing to load it - public final HashMap<Node,Type> _bigCons; + public final HashMap<Node,Type> _bigCons = new HashMap<>(); public void largeConstant( Node relo, Type t ) { assert t.isConstant(); _bigCons.put(relo,t); // TODO: } - private final HashMap<CFGNode,CFGNode> _jmps; + + // Local relocation info for patching local jumps, once targets are known. + private final HashMap<CFGNode,CFGNode> _jmps = new HashMap<>(); public void jump( CFGNode jmp, CFGNode target ) { _jmps.put(jmp,target); } void encode() { @@ -222,9 +215,10 @@ public class Encoding { _opStart= new int [_code.UID()]; _opLen = new byte[_code.UID()]; for( CFGNode bb : _code._cfg ) { - if( !(bb instanceof MachNode) ) _opStart[bb._nid] = _bits.size(); + if( !(bb instanceof MachNode) || bb instanceof FunNode ) + _opStart[bb._nid] = _bits.size(); for( Node n : bb._outputs ) { - if( n instanceof MachNode mach ) { + if( n instanceof MachNode mach && !(n instanceof FunNode) ) { _opStart[n._nid] = _bits.size(); mach.encoding( this ); _opLen[n._nid] = (byte) (_bits.size() - _opStart[n._nid]); @@ -300,6 +294,20 @@ public class Encoding { int start = _opStart[jmp._nid]; ((RIPRelSize)jmp).patch(this, start, _opLen[jmp._nid], _opStart[target._nid] - start); } + + + // Walk the local code-address relocations + for( Node n : _internals ) { + TypeFunPtr tfp = n instanceof CallNode call ? call.tfp() : (TypeFunPtr)n._type; + FunNode fun = _code.link(tfp); + int start = _opStart[n._nid]; + ((RIPRelSize)n).patch(this, start, _opLen[n._nid], _opStart[fun._nid] - start); + } + + // Walk the external call relocations + for( Node call : _externals ) { + throw Utils.TODO(); + } } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/CallNode.java b/chapter21/src/main/java/com/seaofnodes/simple/node/CallNode.java index f8f34422..484a613e 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/CallNode.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/CallNode.java @@ -50,6 +50,10 @@ public class CallNode extends CFGNode { // Error if not a TFP public TypeFunPtr tfp() { return (TypeFunPtr)fptr()._type; } + // Call is to an externally supplied code + public boolean external() { return false; } + + // Find the Call End from the Call public CallEndNode cend() { // Always in use slot 0 diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/MachNode.java b/chapter21/src/main/java/com/seaofnodes/simple/node/MachNode.java index 2c67ff2d..5486b1c1 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/MachNode.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/MachNode.java @@ -9,7 +9,7 @@ public interface MachNode { default Machine machine() { return CodeGen.CODE._mach; } // Run a post-instruction-selection action - default void postSelect() { } + default void postSelect( CodeGen code ) { } // Register mask allowed on input i. 0 for no register. RegMask regmap( int i ); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java index e3c63ccc..b3384f21 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java @@ -14,7 +14,7 @@ public class BranchARM extends IfNode implements MachNode, RIPRelSize { @Override public String op() { return "j"+_bop; } @Override public String label() { return op(); } - @Override public void postSelect() { + @Override public void postSelect(CodeGen code) { Node set = in(1); Node cmp = set.in(1); // Bypass an expected Set and just reference the cmp directly 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 1d3d4d3d..ed22da06 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 @@ -5,7 +5,7 @@ import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; -public class CallARM extends CallNode implements MachNode { +public class CallARM extends CallNode implements MachNode, RIPRelSize { final TypeFunPtr _tfp; final String _name; @@ -25,9 +25,17 @@ public class CallARM extends CallNode implements MachNode { @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { - enc.relo(this,_tfp); // Record relo info + enc.relo(this); // BL - enc.add4(arm.b(0B100101,0)); // Target patched at link time + enc.add4(arm.b(0b100101,0)); // Target patched at link time + } + + // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding + @Override public byte encSize(int delta) { return 4; } + + // Delta is from opcode start + @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { + enc.patch4(opStart,arm.b(0b100101,delta)); } @Override public void asm(CodeGen code, SB sb) { 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 736bca47..2e8bf6ad 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 @@ -1,7 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; -import com.seaofnodes.simple.codegen.Encoding; -import com.seaofnodes.simple.codegen.RegMask; +import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.MachNode; @@ -10,4 +9,5 @@ public class FunARM extends FunNode implements MachNode { @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); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java index 2a702247..290421aa 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java @@ -8,7 +8,7 @@ public class RetARM extends ReturnNode implements MachNode { RetARM(ReturnNode ret, FunNode fun) { super(ret, fun); fun.setRet(this); } @Override public String op() { return "ret"; } // Correct Nodes outside the normal edges - @Override public void postSelect() { + @Override public void postSelect(CodeGen code) { FunNode fun = (FunNode)rpc().in(0); _fun = fun; fun.setRet(this); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java index eb06a4e0..429148d2 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java @@ -14,7 +14,7 @@ public class TFPARM extends ConstantNode implements MachNode { @Override public boolean isClone() { return true; } @Override public TFPARM copy() { return new TFPARM(this); } @Override public void encoding( Encoding enc ) { - enc.relo(this,(TypeFunPtr)_con); + enc.reloTFP(this); short self = enc.reg(this); // adrp x0, 0 int adrp = arm.adrp(1,0, 0b10000, 0,self); 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 6b3faa4e..a3f08730 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 @@ -542,9 +542,9 @@ public class arm extends Machine { } private Node call(CallNode call){ - if(call.fptr() instanceof ConstantNode con && con._con instanceof TypeFunPtr tfp) - return new CallARM(call, tfp); - return new CallRRARM(call); + return call.fptr() instanceof ConstantNode con && con._con instanceof TypeFunPtr tfp + ? new CallARM(call, tfp) + : new CallRRARM(call); } private Node or(OrNode or) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java index 30c63d8d..244e0456 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java @@ -7,7 +7,7 @@ import com.seaofnodes.simple.node.MachNode; import com.seaofnodes.simple.type.TypeFunPtr; // Add upper 20bits to PC. Immediate comes from the relocation info. -public class AUIPC extends ConstantNode implements MachNode { +public class AUIPC extends ConstantNode implements MachNode, RIPRelSize { AUIPC( TypeFunPtr tfp ) { super(tfp); } @Override public RegMask regmap(int i) { return null; } @Override public RegMask outregmap() { return riscv.WMASK; } @@ -15,11 +15,23 @@ public class AUIPC extends ConstantNode implements MachNode { @Override public AUIPC copy() { return new AUIPC((TypeFunPtr)_con); } @Override public String op() { return "auipc"; } @Override public void encoding( Encoding enc ) { - enc.relo(this,(TypeFunPtr)_con); + enc.reloTFP(this); short dst = enc.reg(this); enc.add4(riscv.u_type(0x17, dst, 0)); } + // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding + @Override public byte encSize(int delta) { return 4; } + + // Delta is from opcode start + @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { + //short rpc = enc.reg(this); + //// High half is where the TFP constant used to be, the last input + //short auipc = enc.reg(in(_inputs._len-1)); + //enc.patch4(opStart,riscv.i_type(0x67, rpc, 0, auipc, delta)); + throw Utils.TODO(); + } + @Override public void asm(CodeGen code, SB sb) { String reg = code.reg(this); sb.p(reg).p(" = PC+#"); 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 d0309829..538a68be 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 @@ -5,14 +5,13 @@ import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; -public class CallRISC extends CallNode implements MachNode { +public class CallRISC extends CallNode implements MachNode, RIPRelSize { final TypeFunPtr _tfp; final String _name; - CallRISC( CallNode call, TypeFunPtr tfp, AUIPC auipc ) { + CallRISC( CallNode call, TypeFunPtr tfp ) { super(call); assert tfp.isConstant(); _inputs.pop(); // Pop constant target - _inputs.add(auipc); // Add high-half address _tfp = tfp; _name = CodeGen.CODE.link(tfp)._name; } @@ -29,12 +28,24 @@ public class CallRISC extends CallNode implements MachNode { @Override public TypeFunPtr tfp() { return _tfp; } @Override public void encoding( Encoding enc ) { - enc.relo(this,_tfp); + enc.relo(this); + short rpc = enc.reg(this); + //// High half is where the TFP constant used to be, the last input + //short auipc = enc.reg(in(_inputs._len-1)); + //enc.add4(riscv.i_type(0x67, rpc, 0, auipc, 0)); + // TODO: JAL for range + throw Utils.TODO(); + } + + // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding + @Override public byte encSize(int delta) { return 4; } + + // Delta is from opcode start + @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { short rpc = enc.reg(this); // High half is where the TFP constant used to be, the last input short auipc = enc.reg(in(_inputs._len-1)); - int body = riscv.i_type(0x67, rpc, 0/*JALR.C*/, auipc, 0); - enc.add4(body); + enc.patch4(opStart,riscv.i_type(0x67, rpc, 0, auipc, delta&0xFFF)); } @Override public void asm(CodeGen code, SB sb) { 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 0e931e02..6f1e4b6c 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 @@ -1,7 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; -import com.seaofnodes.simple.codegen.Encoding; -import com.seaofnodes.simple.codegen.RegMask; +import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.MachNode; @@ -10,4 +9,5 @@ public class FunRISC extends FunNode implements MachNode { @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); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java index 9f89f983..181e9ac0 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java @@ -12,7 +12,7 @@ public class RetRISC extends ReturnNode implements MachNode{ RetRISC(ReturnNode ret, FunNode fun) { super(ret, fun); fun.setRet(this); } @Override public String op() { return "ret"; } // Correct Nodes outside the normal edges - @Override public void postSelect() { + @Override public void postSelect(CodeGen code) { FunNode fun = (FunNode)rpc().in(0); _fun = fun; fun.setRet(this); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java index d2bdcb8a..4b096e7b 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java @@ -14,7 +14,7 @@ public class TFPRISC extends ConstantNode implements MachNode { @Override public boolean isClone() { return true; } @Override public TFPRISC copy() { return new TFPRISC(this); } @Override public void encoding( Encoding enc ) { - enc.relo(this,(TypeFunPtr)_con); + enc.reloTFP(this); short dst = enc.reg(this); TypeFunPtr tfp = (TypeFunPtr)_con; // auipc t0,0 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 8e048c0a..e3cc8724 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 @@ -378,13 +378,9 @@ public class riscv extends Machine { } private Node call(CallNode call) { - // Options here are: - // 4G range in 2ops and either PC-relative or absolute - // 4K range in 1op absolute - // Since 4K is too small, we're going with 4G PC-relative in 2 ops - if( call.fptr() instanceof ConstantNode con && con._con instanceof TypeFunPtr tfp ) - return new CallRISC(call, tfp, new AUIPC(tfp)); - return new CallRRISC(call); + return call.fptr() instanceof ConstantNode con && con._con instanceof TypeFunPtr tfp + ? new CallRISC(call, tfp) + : new CallRRISC(call); } private Node nnn(NewNode nnn) { // TODO: pass in the TFP for alloc 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 bb5cf7bb..fc1da246 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 @@ -1,14 +1,12 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; import com.seaofnodes.simple.SB; -import com.seaofnodes.simple.codegen.CodeGen; -import com.seaofnodes.simple.codegen.Encoding; -import com.seaofnodes.simple.codegen.RegMask; +import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.CallNode; import com.seaofnodes.simple.node.MachNode; import com.seaofnodes.simple.type.TypeFunPtr; -public class CallX86 extends CallNode implements MachNode { +public class CallX86 extends CallNode implements MachNode, RIPRelSize { final TypeFunPtr _tfp; final String _name; CallX86( CallNode call, TypeFunPtr tfp ) { @@ -28,11 +26,18 @@ public class CallX86 extends CallNode implements MachNode { // Encoding is appended into the byte array; size is returned @Override public void encoding( Encoding enc ) { - enc.relo(this,_tfp); - enc.add1(0xe8); - enc.add4(0); // Target patched at link time + enc.relo(this).add1(0xe8).add4(0); } + // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding + @Override public byte encSize(int delta) { return 5; } + + // Delta is from opcode start + @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { + enc.patch4(opStart+1, delta-5); + } + + @Override public void asm(CodeGen code, SB sb) { sb.p(_name).p(" "); for( int i=0; i<nargs(); i++ ) 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 120053fa..22cb8698 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,7 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; -import com.seaofnodes.simple.codegen.Encoding; -import com.seaofnodes.simple.codegen.RegMask; +import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.MachNode; @@ -10,4 +9,5 @@ public class FunX86 extends FunNode implements MachNode { @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); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java index 667ab012..2d27e5c7 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java @@ -13,7 +13,7 @@ public class JmpX86 extends IfNode implements MachNode, RIPRelSize { } @Override public String op() { return "j"+_bop; } @Override public String label() { return op(); } - @Override public void postSelect() { + @Override public void postSelect(CodeGen code) { Node set = in(1); Node cmp = set.in(1); // Bypass an expected Set and just reference the cmp directly 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 1a08bb4c..34458e8f 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 @@ -8,7 +8,7 @@ public class RetX86 extends ReturnNode implements MachNode { RetX86( ReturnNode ret, FunNode fun ) { super(ret, fun); fun.setRet(this); } @Override public String op() { return "ret"; } // Correct Nodes outside the normal edges - @Override public void postSelect() { + @Override public void postSelect(CodeGen code) { FunNode fun = (FunNode)rpc().in(0); _fun = fun; fun.setRet(this); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java index a80531b6..6131fea6 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java @@ -35,7 +35,7 @@ public class TFPX86 extends ConstantNode implements MachNode { // lea to load function pointer address // lea rax, [rip+disp32] - enc.relo(this,(TypeFunPtr)_con); + enc.reloTFP(this); enc.add1(x86_64_v2.rex(dst, 0, 0)); enc.add1(0x8D); // opcode enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0b101)); 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 af5dbff4..ee0f89d6 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 @@ -453,9 +453,9 @@ public class x86_64_v2 extends Machine { } private Node call(CallNode call) { - if( call.fptr() instanceof ConstantNode con && con._con instanceof TypeFunPtr tfp ) - return new CallX86(call, tfp); - return new CallRX86(call); + return call.fptr() instanceof ConstantNode con && con._con instanceof TypeFunPtr tfp + ? new CallX86(call, tfp) + : new CallRX86(call); } // Because X86 flags, a normal ideal Bool is 2 X86 ops: a "cmp" and at "setz". |
