diff options
Diffstat (limited to 'chapter21/src/main/java')
10 files changed, 169 insertions, 45 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 64ea8201..f5d32dd2 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java @@ -308,16 +308,21 @@ public class CodeGen { // --------------------------- // Encoding public int _tEncode; + public boolean _JIT; public Encoding _encoding; - public CodeGen encode() { + public CodeGen encode(boolean jit) { assert _phase == Phase.RegAlloc; _phase = Phase.Encoding; long t0 = System.currentTimeMillis(); _encoding = new Encoding(this); + _JIT = jit; _encoding.encode(); _tEncode = (int)(System.currentTimeMillis() - t0); return this; } + public CodeGen encode() { + return encode(false); + } // Encoded binary, no relocation info public byte[] binary() { return _encoding.bits(); } 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 223911ba..62bcfcde 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java @@ -228,6 +228,30 @@ 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 @@ -253,6 +277,8 @@ public class ElfFile { // populate function symbols encodeFunctions(symbols, text); + // populate big constants + encodeConstants(symbols, rdata); int idx = 1; for( Section s : _sections ) { @@ -267,8 +293,9 @@ public class ElfFile { int num = 1; for( Symbol s : symbols._loc ) s._index = num++; + // extra space for .rela.text int start_global = symbols._loc.size(); - for(Symbol a: symbols._symbols) + for(Symbol a: symbols._symbols) { a._index = start_global++; // create .text relocations @@ -276,16 +303,31 @@ public class ElfFile { for( Node n : _code._encoding._externals.keySet()) { int nid = n._nid; String extern = _code._encoding._externals.get(n); - if(!extern.isEmpty()) throw Utils.TODO(); - // Todo: fix this up later when external functions will be in TU - //int sym_id = _funcs.get(extern)._index; - int sym_id = 0; + + 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; + + // u64 offset + write8(text_rela._contents, offset); + // u64 info + write8(text_rela._contents, ((long)sym._index << 32L) | 4L /* PLT32 */); + // i64 addend + 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) | 4L /* PLT32 */); + write8(text_rela._contents, ((long)sym_id << 32L) | 2L /* PC32 */); // i64 addend write8(text_rela._contents, -4); } @@ -295,7 +337,7 @@ public class ElfFile { text_rela._info = text._index; pushSection(text_rela); - Symbol sym = new Symbol(text_rela._name, idx++, 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 0f9aac89..f90ce96a 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java @@ -151,9 +151,14 @@ 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(); + } // Basic block layout: invert branches to keep blocks in-order; insert diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetRISC.java index 636c5a5f..8d4a2f71 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetRISC.java @@ -4,7 +4,7 @@ import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; -// corresponds to slt (and NOT sltu, slti, sltiu) +// corresponds to slt sltu public class SetRISC extends MachConcreteNode implements MachNode { final boolean _unsigned; public SetRISC( Node cmp, boolean unsigned ) { super(cmp); _unsigned=unsigned; } @@ -12,7 +12,7 @@ public class SetRISC extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return riscv.RMASK; } @Override public RegMask outregmap() { return riscv.WMASK; } @Override public void encoding( Encoding enc ) { - riscv.r_type(enc,this,_unsigned ? 0b011 : 0x010,0); + riscv.r_type(enc,this,_unsigned ? 0b011 : 0b010,0); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" < ").p(code.reg(in(2))); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java index f6f3474f..921fa336 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java @@ -15,13 +15,14 @@ public class CmpMemX86 extends MemOpX86 { @Override public void encoding( Encoding enc ) { // REX.W + 81 /7 id CMP r/m64, imm32 | REX.W + 39 /r CMP r/m64,r64 // CMP [mem], imm32 + short ptr = enc.reg(ptr()); short idx = enc.reg(idx()); short src = enc.reg(val()); enc.add1(x86_64_v2.rex(src, ptr, idx)); // opcode varies by immediate - enc.add1( src == -1 ? 0x39 : 0x81 ); + enc.add1( src == -1 ? 0x81 : 0x39); // includes modrm x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src == -1 ? 7 : src, enc); 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 708269bd..c9df7b99 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 @@ -4,7 +4,7 @@ import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; -public class FltX86 extends ConstantNode implements MachNode, RIPRelSize { +public class FltX86 extends ConstantNode implements MachNode, RIPRelSize{ private byte _encSize; FltX86(ConstantNode con ) { super(con); } @Override public String op() { return "ld8"; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java index d6c977a5..6d6aa89c 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java @@ -1,12 +1,39 @@ 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.node.MachNode; import com.seaofnodes.simple.node.Node; +import com.seaofnodes.simple.node.*; + // Arithmetic Right Shift -public class SarIX86 extends ImmX86 { - SarIX86( Node add, int imm ) { super(add,imm); assert x86_64_v2.imm8(imm); } +public class SarIX86 extends MachConcreteNode implements MachNode { + final int _imm; + SarIX86( Node sari, int imm ) { super(sari); assert x86_64_v2.imm8(imm); _inputs.pop(); _imm = imm; } @Override public String op() { return "sari"; } @Override public String glabel() { return ">>"; } - @Override int opcode() { return 0xC1; } - @Override int mod() { return 7; } + int opcode() { return 0xC1; } + int mod() { return 7; } + + @Override public RegMask regmap(int i) { return x86_64_v2.RMASK; } + @Override public RegMask outregmap() { return x86_64_v2.WMASK; } + + @Override public void encoding(Encoding enc) { + short dst = enc.reg(this); // Also src1 + enc.add1(x86_64_v2.rex(0, dst, 0)); + enc.add1( opcode()); + + enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); + + // immediate(4 bytes) 32 bits or (1 byte)8 bits + if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); + else enc.add4(_imm); + } + + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" ").p(glabel()).p("= #").p(_imm); + } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java index 35818a91..c53e0ea9 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java @@ -2,10 +2,38 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; import com.seaofnodes.simple.node.Node; -public class ShlIX86 extends ImmX86 { - ShlIX86( Node add, int imm ) { super(add,imm); } +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.codegen.*; +import com.seaofnodes.simple.node.*; + +public class ShlIX86 extends MachConcreteNode implements MachNode { + final int _imm; + ShlIX86( Node shli, int imm ) { + super(shli); + assert x86_64_v2.imm8(imm); + _inputs.pop(); // Pop constant input off + _imm = imm; + } + public int opcode() { return 0xC1; } + public int mod() { return 4; } + + @Override public RegMask regmap(int i) { return x86_64_v2.RMASK; } + @Override public RegMask outregmap() { return x86_64_v2.WMASK; } + @Override public String op() { return "shli"; } @Override public String glabel() { return "<<"; } - @Override int opcode() { return 0xC1; } - @Override int mod() { return 4; } + @Override public void encoding(Encoding enc) { + short dst = enc.reg(this); // Also src1 + enc.add1(x86_64_v2.rex(0, dst, 0)); + enc.add1( opcode()); + + enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); + + // immediate(4 bytes) 32 bits or (1 byte)8 bits + if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); + else enc.add4(_imm); + } + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" ").p(glabel()).p("= #").p(_imm); + } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java index 0e96962b..c79b8817 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java @@ -2,10 +2,33 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; import com.seaofnodes.simple.node.Node; -public class ShrIX86 extends ImmX86 { - ShrIX86( Node add, int imm ) { super(add,imm); } +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.codegen.*; +import com.seaofnodes.simple.node.*; + +public class ShrIX86 extends MachConcreteNode implements MachNode { + final int _imm; + ShrIX86( Node shri, int imm ) { super(shri); assert x86_64_v2.imm8(imm); _inputs.pop(); _imm = imm; } @Override public String op() { return "shri"; } @Override public String glabel() { return ">>>"; } - @Override int opcode() { return 0xC1; } - @Override int mod() { return 5; } + int opcode() { return 0xC1; } + int mod() { return 5; } + + @Override public RegMask regmap(int i) { return x86_64_v2.RMASK; } + @Override public RegMask outregmap() { return x86_64_v2.WMASK; } + + @Override public void encoding(Encoding enc) { + short dst = enc.reg(this); // Also src1 + enc.add1(x86_64_v2.rex(0, dst, 0)); + enc.add1( opcode()); + + enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); + + // immediate(4 bytes) 32 bits or (1 byte)8 bits + if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); + else enc.add4(_imm); + } + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" ").p(glabel()).p("= #").p(_imm); + } } 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 39048f2d..bf8f92ad 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 @@ -146,31 +146,24 @@ public class x86_64_v2 extends Machine { public static void indirectAdr( int scale, short index, short base, int offset, int reg, Encoding enc ) { // Assume indirect assert 0 <= base && base < 16; - assert index != RSP; + assert -1 <= index && index < 16 && index != RSP; MOD mod = MOD.INDIRECT; // is 1 byte enough or need more? if( offset != 0 ) mod = imm8(offset) - ? MOD.INDIRECT_disp8 - : MOD.INDIRECT_disp32; + ? MOD.INDIRECT_disp8 + : MOD.INDIRECT_disp32; - // needs to pick optimal displacement mod if we want to encode base - // when we only have base = RSP then we still need displacement added so ti becomes: [RSP+RSP*1+0x0] - // RSP as index in this case is special and refers to: [base + disp8] - if( mod == MOD.INDIRECT && (base == RBP || base == R13) ) + if( mod == MOD.INDIRECT && (base == RBP || base == R13) ) { mod = MOD.INDIRECT_disp8; + } else if( index == -1 && (base == RSP || base == R12) ) { + index = RSP; + } - // special encoding for [base +offset] if( index == -1 ) { - // Case for mov reg, [disp] (load) - enc.add1(modrm(offset == 0 ? MOD.INDIRECT_disp8 : mod, reg, x86_64_v2.RSP)); - enc.add1(sib(scale, x86_64_v2.RSP, base)); - // special case - // still add zero it is part of SIB byte - if(offset == 0) enc.add1(offset); + enc.add1(modrm(mod, reg, base)); } else { - // rsp is hard-coded here(0x04) enc.add1(modrm(mod, reg, x86_64_v2.RSP)); enc.add1(sib(scale, index, base)); } @@ -592,20 +585,20 @@ public class x86_64_v2 extends Machine { } private Node sar(SarNode sar) { - if( sar.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti ) - return new SarIX86(sar, (int)(ti.value() & 0x03f) ); + if( sar.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti && imm8(ti.value())) + return new SarIX86(sar, (int)(ti.value() & 0xff) ); return new SarX86(sar); } private Node shl(ShlNode shl) { - if( shl.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti ) - return new ShlIX86(shl, (int)(ti.value() & 0x03f) ); + if( shl.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti && imm8(ti.value())) + return new ShlIX86(shl, (int)(ti.value() & 0xff) ); return new ShlX86(shl); } private Node shr( ShrNode shr ) { - if( shr.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti ) - return new ShrIX86(shr, (int)(ti.value() & 0x03f) ); + if( shr.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti && imm8(ti.value()) ) + return new ShrIX86(shr, (int)(ti.value() & 0xff) ); return new ShrX86(shr); } |
