summaryrefslogtreecommitdiff
path: root/chapter21/src/main/java/com
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2025-03-18 00:34:34 -0700
committerCliff Click <cliffc@acm.org>2025-03-18 00:34:34 -0700
commit5faaadb794ad864ce3e26ed6a5fc4457a8aa2f15 (patch)
tree7bd374540680f5b36fbe9ee0af764d5d4f5f2e67 /chapter21/src/main/java/com
parent9929bca5617c2b0134ae16fb174df8d247443af8 (diff)
downloadSimple-5faaadb794ad864ce3e26ed6a5fc4457a8aa2f15.tar.gz
Simple-5faaadb794ad864ce3e26ed6a5fc4457a8aa2f15.zip
progress on patching calls
Diffstat (limited to 'chapter21/src/main/java/com')
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java82
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java7
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java54
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/CallNode.java4
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/MachNode.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java14
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java4
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java6
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java16
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java23
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java4
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java10
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java19
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java4
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java6
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".