summaryrefslogtreecommitdiff
path: root/chapter21/src/main/java/com
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2025-04-05 13:58:07 -0700
committerCliff Click <cliffc@acm.org>2025-04-05 13:58:07 -0700
commit7277ab049ab9cae5fa64cd5ea958f69278f773a4 (patch)
tree55289107814ed0dac39288dd55520aed9a5d66e5 /chapter21/src/main/java/com
parentfc7d2bce649854982a3c16de164bbaafec11bc27 (diff)
downloadSimple-7277ab049ab9cae5fa64cd5ea958f69278f773a4.tar.gz
Simple-7277ab049ab9cae5fa64cd5ea958f69278f773a4.zip
Fix elf constants
Record more relocation info in the machine-specific encodings. Use it when building ELF. Switch to simpler Newtons; some encoding bug in the complex one.
Diffstat (limited to 'chapter21/src/main/java/com')
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java64
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java52
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/LinkMem.java3
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java10
7 files changed, 60 insertions, 75 deletions
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 62bcfcde..746ecfed 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java
@@ -8,6 +8,7 @@ import java.io.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.HashMap;
+import java.util.Map;
public class ElfFile {
@@ -228,30 +229,6 @@ public class ElfFile {
}
}
- public final HashMap<Type, Symbol> _bigCons = new HashMap<>();
- private void encodeConstants(SymbolSection symbols, DataSection rdata) {
- int cnt = 0;
- for (Map.Entry<Node,Type> e : _code._encoding._bigCons.entrySet()) {
- if (_bigCons.get(e.getValue()) != null) {
- continue;
- }
-
- Symbol glob = new Symbol("GLOB$"+cnt, rdata._index, SYM_BIND_GLOBAL, SYM_TYPE_FUNC);
- glob._value = rdata._contents.size();
- symbols.push(glob);
-
- Type t = e.getValue();
- if ( t instanceof TypeFloat tf ) {
- write8(rdata._contents, Double.doubleToLongBits(tf._con));
- } else {
- throw Utils.TODO();
- }
-
- glob._size = rdata._contents.size() - glob._value;
- _bigCons.put(e.getValue(), glob);
- cnt++;
- }
- }
public void export(String fname) throws IOException {
DataSection strtab = new DataSection(".strtab", 3 /* SHT_SYMTAB */);
// first byte is reserved for an empty string
@@ -270,15 +247,14 @@ public class ElfFile {
// Build and write constant pool
BAOS cpool = new BAOS();
- _code._encoding.writeConstantPool(cpool,false);
+ Encoding enc = _code._encoding;
+ enc.writeConstantPool(cpool,false);
DataSection rdata = new DataSection(".rodata", 1 /* SHT_PROGBITS */, cpool);
rdata._flags = SHF_ALLOC;
pushSection(rdata);
// populate function symbols
encodeFunctions(symbols, text);
- // populate big constants
- encodeConstants(symbols, rdata);
int idx = 1;
for( Section s : _sections ) {
@@ -294,21 +270,23 @@ public class ElfFile {
for( Symbol s : symbols._loc )
s._index = num++;
// extra space for .rela.text
- int start_global = symbols._loc.size();
- for(Symbol a: symbols._symbols) {
+ int start_global = num+1; // Add one to skip the final .rela.text local symbol
+ for( Symbol a: symbols._symbols )
a._index = start_global++;
+ int bigConIdx = start_global;
+ start_global += enc._bigCons.size();
// create .text relocations
DataSection text_rela = new DataSection(".rela.text", 4 /* SHT_RELA */);
- for( Node n : _code._encoding._externals.keySet()) {
+ for( Node n : enc._externals.keySet()) {
int nid = n._nid;
- String extern = _code._encoding._externals.get(n);
+ String extern = enc._externals.get(n);
Symbol sym = new Symbol(extern, 0, SYM_BIND_GLOBAL, SYM_TYPE_NOTYPE);
sym._index = start_global++;
symbols.push(sym);
- int offset = _code._encoding._opStart[nid] + _code._encoding._opLen[nid] - 4;
+ int offset = enc._opStart[nid] + enc._opLen[nid] - 4;
// u64 offset
write8(text_rela._contents, offset);
@@ -318,17 +296,15 @@ public class ElfFile {
write8(text_rela._contents, -4);
}
- // relocations to constants
- for (Map.Entry<Node,Type> e : _code._encoding._bigCons.entrySet()) {
- int nid = e.getKey()._nid;
- int sym_id = _bigCons.get(e.getValue())._index;
- int offset = _code._encoding._opStart[nid] + _code._encoding._opLen[nid] - 4;
-
- // u64 offset
- write8(text_rela._contents, offset);
- // u64 info
- write8(text_rela._contents, ((long)sym_id << 32L) | 2L /* PC32 */);
- // i64 addend
+ // Write relocations for the constant pool
+ for( Encoding.Relo relo : enc._bigCons.values() ) {
+ Symbol glob = new Symbol("GLOB$"+bigConIdx, rdata._index, SYM_BIND_GLOBAL, SYM_TYPE_FUNC);
+ glob._value = relo._target;
+ glob._size = 1 << relo._t.log_size();
+ glob._index = bigConIdx++;
+ symbols.push(glob);
+ write8(text_rela._contents, relo._opStart+relo._off);
+ write8(text_rela._contents, ((long)glob._index << 32L) | relo._elf );
write8(text_rela._contents, -4);
}
@@ -337,7 +313,7 @@ public class ElfFile {
text_rela._info = text._index;
pushSection(text_rela);
- Symbol sym = new Symbol(text_rela._name, num, SYM_BIND_LOCAL, SYM_TYPE_SECTION);
+ Symbol sym = new Symbol(text_rela._name, num++, SYM_BIND_LOCAL, SYM_TYPE_SECTION);
sym._name_pos = text_rela._name_pos;
sym._size = text_rela.size();
symbols.push(sym);
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 f90ce96a..a66fc579 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java
@@ -44,8 +44,19 @@ public class Encoding {
public int [] _opStart; // Start of opcodes, by _nid
public byte[] _opLen; // Length of opcodes, by _nid
- // Big Constant relocation info
- public final HashMap<Node,Type> _bigCons = new HashMap<>();
+ // Big Constant relocation info.
+ public static class Relo {
+ public final Node _op;
+ public final Type _t; // Constant type
+ public final byte _off; // Offset from start of opcode
+ public final byte _elf; // ELF relocation type, e.g. 2/PC32
+ public int _target; // Where constant is finally placede
+ public int _opStart; // Opcode start
+ Relo( Node op, Type t, byte off, byte elf ) {
+ _op=op; _t=t; _off=off; _elf=elf;
+ }
+ }
+ public final HashMap<Node,Relo> _bigCons = new HashMap<>();
Encoding( CodeGen code ) { _code = code; }
@@ -135,9 +146,11 @@ public class Encoding {
// Store t as a 32/64 bit constant in the code space; generate RIP-relative
// addressing to load it
- public void largeConstant( Node relo, Type t ) {
+ public void largeConstant( Node relo, Type t, int off, int elf ) {
assert t.isConstant();
- _bigCons.put(relo,t);
+ assert (byte)off == off;
+ assert (byte)elf == elf;
+ _bigCons.put(relo,new Relo(relo,t,(byte)off,(byte)elf));
}
void encode() {
@@ -151,14 +164,13 @@ public class Encoding {
// Record opcode start and length.
writeEncodings();
- // ELF handles big constants, they
- // are accessed by RIP-relative addressing.
-
- if(_code._JIT) writeConstantPool(true);
// Short-form RIP-relative support: replace long encodings with short
// encodings and compact the code, changing all the offsets.
compactShortForm();
+ // Patch RIP-relative and local encodings now.
+ patchLocalRelocations();
+
}
// Basic block layout: invert branches to keep blocks in-order; insert
@@ -364,8 +376,8 @@ public class Encoding {
// Write the constant pool into the BAOS and optionally patch locally
void writeConstantPool( BAOS bits, boolean patch ) {
- HashSet<Type> ts = new HashSet<>();
- for( Type t : _bigCons.values() ) {
+ HashSet<Relo> ts = new HashSet<>();
+ for( Relo t : _bigCons.values() ) {
if( ts.contains(t) )
throw Utils.TODO(); // Dup! Compress!
ts.add(t);
@@ -375,21 +387,21 @@ public class Encoding {
// By log size
for( int log = 3; log >= 0; log-- ) {
// Write the 8-byte constants
- for( Node relo : _bigCons.keySet() ) {
- Type t = _bigCons.get(relo);
- if( t.log_size()==log ) {
+ for( Node op : _bigCons.keySet() ) {
+ Relo relo = _bigCons.get(op);
+ if( relo._t.log_size()==log ) {
// Map from relo to constant start and patch
- if( patch ) {
- int target = _bits.size();
- int start = _opStart[relo._nid];
- ((RIPRelSize)relo).patch(this, start, _opLen[relo._nid], target - start);
- }
+ relo._target = bits.size();
+ relo._opStart= _opStart[op._nid];
+ // Go ahead and locally patch in-memory
+ if( patch )
+ ((RIPRelSize)op).patch(this, relo._opStart, _opLen[op._nid], relo._target - relo._opStart);
// Put constant into code space.
- if( t instanceof TypeTuple tt ) // Constant tuples put all entries
+ if( relo._t instanceof TypeTuple tt ) // Constant tuples put all entries
for( Type tx : tt._types )
addN(log,tx,bits);
else
- addN(log,t,bits);
+ addN(log,relo._t,bits);
}
}
}
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/LinkMem.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/LinkMem.java
index 35d2008a..07a5dd12 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/LinkMem.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/LinkMem.java
@@ -10,9 +10,6 @@ public class LinkMem {
// are accessed by RIP-relative addressing.
_code._encoding.writeConstantPool(_code._encoding._bits,true);
- // Patch RIP-relative and local encodings now.
- _code._encoding.patchLocalRelocations();
-
return _code;
}
}
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java
index 45ecc430..dc125af2 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java
@@ -18,7 +18,7 @@ public class FloatARM extends ConstantNode implements MachNode, RIPRelSize {
@Override public FloatARM copy() { return new FloatARM(this); }
@Override public void encoding( Encoding enc ) {
- enc.largeConstant(this,_con);
+ enc.largeConstant(this,_con,0,-1/*TODO: ARM-style ELF patching*/);
short dst = (short)(enc.reg(this) - arm.D_OFFSET);
double d = ((TypeFloat)_con).value();
long x = Double.doubleToRawLongBits(d);
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java
index d1bd4a94..0a7b02e3 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java
@@ -16,7 +16,7 @@ public class FltRISC extends ConstantNode implements MachNode, RIPRelSize {
@Override public FltRISC copy() { return new FltRISC(this); }
@Override public void encoding( Encoding enc ) {
- enc.largeConstant(this,_con);
+ enc.largeConstant(this,_con, 0, -1/*TODO: RISC5 style patching*/);
short dst = (short)(enc.reg(this) - riscv.F_OFFSET);
short tmp = (short)riscv.T6;
// AUIPC dst,#hi20_constant_pool
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java
index c9df7b99..e3b20003 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java
@@ -19,7 +19,6 @@ public class FltX86 extends ConstantNode implements MachNode, RIPRelSize{
// F2 0F 10 /r MOVSD xmm1, m64
_encSize = 1/*Fop*/+0/*REX*/+2/*op*/+1/*MODRM*/+4/*offset*/;
short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET);
- enc.largeConstant(this,_con);
// Fopcode
enc.add1(0xF2);
// rex prefix must come next (REX.W is not set)
@@ -28,6 +27,7 @@ public class FltX86 extends ConstantNode implements MachNode, RIPRelSize{
// hard-code rip here
enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0x05));
enc.add4(0);
+ enc.largeConstant(this,_con,_encSize-4,2/*ELF encoding PC32*/);
}
// Delta is from opcode start
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 2e475f13..c040d414 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java
@@ -29,11 +29,11 @@ public abstract class ASMPrinter {
sb.p("--- Constant Pool ------").nl();
// By log size
for( int log = 3; log >= 0; log-- ) {
- for( Node relo : enc._bigCons.keySet() ) {
- Type t = enc._bigCons.get(relo);
- if( t.log_size()==log ) {
+ for( Node op : enc._bigCons.keySet() ) {
+ Encoding.Relo relo = enc._bigCons.get(op);
+ if( relo._t.log_size()==log ) {
sb.hex2(iadr).p(" ");
- if( t instanceof TypeTuple tt ) {
+ if( relo._t instanceof TypeTuple tt ) {
for( Type tx : tt._types ) {
switch( log ) {
case 0: sb.hex1(enc.read1(iadr)); break;
@@ -53,7 +53,7 @@ public abstract class ASMPrinter {
}
iadr += (1<<log);
}
- t.print(sb).nl();
+ relo._t.print(sb).nl();
}
}
}