Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public class IterPeeps {

public IterPeeps( long seed ) { _work = new WorkList<>(seed); }

@SuppressWarnings("unchecked")
public <N extends Node> N add( N n ) { return (N)_work.push(n); }

public void addAll( Ary<Node> ary ) { _work.addAll(ary); }
Expand Down Expand Up @@ -126,6 +127,7 @@ private boolean progressOnList(CodeGen code) {
* Classic WorkList, with a fast add/remove, dup removal, random pull.
* The Node's nid is used to check membership in the worklist.
*/
@SuppressWarnings("unchecked")
public static class WorkList<E extends Node> {

private Node[] _es;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,6 @@
abstract public class Coalesce {

public static boolean coalesce( int round, RegAlloc alloc ) {
// Convert the 2-D array of bits (a 1-D array of BitSets) into an
// adjacency matrix.
int maxlrg = alloc._LRGS.length;
for( int i=1; i<maxlrg; i++ ) {
BitSet ifg = IFG.IFG.atX(i);
if( ifg != null ) {
LRG lrg0 = alloc._LRGS[i];
for( int lrg = ifg.nextSetBit(0); lrg>=0; lrg=ifg.nextSetBit(lrg+1) ) {
LRG lrg1 = alloc._LRGS[lrg];
lrg0.addNeighbor(lrg1);
lrg1.addNeighbor(lrg0);
}
}
}

// Walk all the splits, looking for coalesce chances
boolean progress = false;
Expand All @@ -37,7 +23,7 @@ public static boolean coalesce( int round, RegAlloc alloc ) {
if( v1 != v2 ) {
LRG ov1 = v1, ov2 = v2;
// Get the smaller neighbor count in v1
if( (v1._adj==null ? 0 : v1._adj._len) > (v2._adj==null ? 0 : v2._adj._len) )
if( v1.nadj() > v2.nadj() )
{ v1 = v2; v2 = alloc.lrg(n); }
int v2len = v2._adj==null ? 0 : v2._adj._len;
// See that they do not conflict (coalescing would make a self-conflict)
Expand All @@ -58,9 +44,9 @@ public static boolean coalesce( int round, RegAlloc alloc ) {
// Most constrained mask
RegMask mask = v1._mask==v2._mask ? v1._mask : v1._mask.copy().and(v2._mask);
// Check for capacity
if( (v2._adj==null ? 0 : v2._adj._len) >= mask.size() ) {
if( v2.nadj() >= mask.size() ) {
// Fails capacity, will not be trivial colorable
v2._adj.setLen(v2len);
if( v2._adj!=null ) v2._adj.setLen(v2len);
continue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
import java.util.HashMap;
import java.util.IdentityHashMap;

@SuppressWarnings("unchecked")
public class CodeGen {
public static final String PORTS = "com.compilerprogramming.ezlang.compiler.nodes.cpus";
// Last created CodeGen as a global; used all over to avoid passing about a
// "context".
public static CodeGen CODE;
Expand Down Expand Up @@ -187,7 +189,8 @@ public CodeGen typeCheck() {

// Convert to target hardware nodes
public int _tInsSel;
public CodeGen instSelect( String base, String cpu, String callingConv ) {
public CodeGen instSelect( String cpu, String callingConv ) { return instSelect(cpu,callingConv,PORTS); }
public CodeGen instSelect( String cpu, String callingConv, String base ) {
assert _phase.ordinal() <= Phase.TypeCheck.ordinal();
_phase = Phase.InstSelect;

Expand Down Expand Up @@ -313,16 +316,21 @@ public String reg(Node n) {
// ---------------------------
// 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(); }

Expand All @@ -331,12 +339,13 @@ public CodeGen encode() {
public CodeGen exportELF(String fname) throws IOException {
assert _phase == Phase.Encoding;
_phase = Phase.Export;
ElfFile obj = new ElfFile(this);
obj.export(fname);
if( fname == null ) new LinkMem(this).link(); // In memory patching
else new ElfFile(this).export(fname); // External ELF file
return this;
}

// ---------------------------
public boolean _asmLittle=true;
SB asm(SB sb) { return ASMPrinter.print(sb,this); }
public String asm() { return asm(new SB()).toString(); }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@
import com.compilerprogramming.ezlang.compiler.nodes.*;
import com.compilerprogramming.ezlang.compiler.sontypes.*;

import java.util.Map;
import java.util.HashMap;
import java.io.*;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.io.IOException;
import java.io.FileOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.BufferedOutputStream;
import java.util.HashMap;
import java.util.Map;

public class ElfFile {

Expand Down Expand Up @@ -69,6 +67,10 @@ public static class Symbol {
// top 4bits are the "bind", bottom 4 are "type"
int _info;

// bind 1011
// 00001111
// 10110000

Symbol(String name, int parent, int bind, int type) {
_name = name;
_parent = parent;
Expand All @@ -78,6 +80,7 @@ public static class Symbol {
void writeHeader(ByteBuffer out) {
out.putInt(_name_pos); // name
out.put((byte) _info); // info
// default visibility
out.put((byte) 0); // other
out.putShort((short) _parent); // shndx
out.putLong(_value); // value
Expand Down Expand Up @@ -117,7 +120,7 @@ void writeHeader(ByteBuffer out) {
out.putLong(size()); // size
out.putInt(_link); // link
out.putInt(_info); // info
out.putLong(1); // addralign
out.putLong(16); // addralign
if (_type == 2) {
out.putLong(SYMBOL_SIZE);// entsize
} else if (_type == 4) {
Expand All @@ -140,7 +143,7 @@ public static class SymbolSection extends Section {
}

@Override
void writeHeader(ByteBuffer out) {
void writeHeader(ByteBuffer out) {
// points to string table section
_link = 1;

Expand All @@ -159,23 +162,22 @@ void push(Symbol s) {
}

@Override
void write(ByteBuffer out) {
void write(ByteBuffer out) {
// Index 0 both designates the first entry in the table and serves as the undefined symbol index
for( int i = 0; i < SYMBOL_SIZE/4; i++ ) {
out.putInt(0);
}
int num=1;
// index is already set
for( Symbol s : _loc ) {
s._index = num++;
s.writeHeader(out);
}
for( Symbol s : _symbols ) {
s._index = num++;
s.writeHeader(out);
}
}

@Override
int size() {
int size() {
return (1 + _symbols.len() + _loc.len()) * SYMBOL_SIZE;
}
}
Expand Down Expand Up @@ -210,54 +212,21 @@ private void pushSection(Section s) {
s._index = _sections._len;
}

/* creates function and stores where it starts*/
private final HashMap<SONTypeFunPtr,Symbol> _funcs = new HashMap<>();
private void encodeFunctions(SymbolSection symbols, DataSection text) {
int func_start = 0;
for( int i=0; i<_code._cfg._len; i++ ) {
Node bb = _code._cfg.at(i);
if( bb instanceof FunNode f ) {
// skip until the function ends
while( !(_code._cfg.at(i) instanceof ReturnNode) ) {
i++;
}

Node r = _code._cfg.at(i);
int end = _code._encoding._opStart[r._nid] + _code._encoding._opLen[r._nid];

Symbol func = new Symbol(f._name, text._index, SYM_BIND_GLOBAL, SYM_TYPE_FUNC);
func._size = end - func_start;
func._value = func_start;
symbols.push(func);
_funcs.put(f.sig(), func);

// next function starts where the last one ends
func_start = end;
}
}
}

public final HashMap<SONType,Symbol> _bigCons = new HashMap<>();
private void encodeConstants(SymbolSection symbols, DataSection rdata) {
int cnt = 0;
for (Map.Entry<Node,SONType> 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);

SONType t = e.getValue();
if ( t instanceof SONTypeFloat 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++;
if( !(_code._cfg.at(i) instanceof FunNode fun) ) continue;
// skip until the function ends
while( !(_code._cfg.at(i) instanceof ReturnNode ret) )
i++;
int end = _code._encoding._opStart[ret._nid] + _code._encoding._opLen[ret._nid];

Symbol func = new Symbol(fun._name, text._index, SYM_BIND_GLOBAL, SYM_TYPE_FUNC);
func._value = _code._encoding._opStart[fun._nid];
func._size = end - func._value;
symbols.push(func);
_funcs.put(fun.sig(), func);
}
}

Expand All @@ -271,67 +240,90 @@ public void export(String fname) throws IOException {
SymbolSection symbols = new SymbolSection(".symtab", 2 /* SHT_STRTAB */);
pushSection(symbols);

// zero flag by default
// we've already constructed this entire section in the encoding phase
DataSection text = new DataSection(".text", 1 /* SHT_PROGBITS */, _code._encoding._bits);
text._flags = SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR;
pushSection(text);

DataSection rdata = new DataSection(".rodata", 1 /* SHT_PROGBITS */);
// Build and write constant pool
Encoding.BAOS cpool = new Encoding.BAOS();
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 ) {
Symbol sym = new Symbol(s._name, idx++, SYM_BIND_LOCAL, SYM_TYPE_SECTION);
// we can reuse the same name pos from the actual section
sym._name_pos = s._name_pos;
sym._size = s.size();
symbols.push(sym);
}

// calculate local index
int num = 1;
for( Symbol s : symbols._loc )
s._index = num++;
// extra space for .rela.text
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);
int sym_id = _funcs.get(extern)._index;
int offset = _code._encoding._opStart[nid] + _code._encoding._opLen[nid] - 4;
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 = enc._opStart[nid] + enc._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._index << 32L) | 4L /* PLT32 */);
// i64 addend
write8(text_rela._contents, -4);
}
// relocations to constants
if (false) for (Map.Entry<Node,SONType> 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) | 1L /* 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);
}

text_rela._flags = SHF_INFO_LINK;
text_rela._link = 2;
text_rela._info = text._index;
pushSection(text_rela);

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);

// populate string table
for( Section s : _sections ) { s._name_pos = writeCString(strtab, s._name); }
for( Symbol s : symbols._symbols ) { s._name_pos = writeCString(strtab, s._name); }
for( Symbol s : symbols._loc ) { s._name_pos = writeCString(strtab, s._name); }

int idx = 1;
for( Section s : _sections ) {
Symbol sym = new Symbol(s._name, idx++, SYM_BIND_LOCAL, SYM_TYPE_SECTION);
// we can reuse the same name pos from the actual section
sym._name_pos = s._name_pos;
sym._size = s.size();
symbols.push(sym);
}

int size = 64; // ELF header
// size of all section data
for( Section s : _sections ) {
Expand Down Expand Up @@ -379,7 +371,10 @@ public void export(String fname) throws IOException {
}
assert out.position() == size;

BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fname));
File file = new File(fname);
if( file.getParentFile()!=null )
file.getParentFile().mkdirs();
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
bos.write(out.array());
bos.close();
}
Expand Down
Loading