Skip to content

Commit 6f968b4

Browse files
committed
Back out much CompUnit
CompUnits to track source dependencies, but then a single Elf file is generated.
1 parent 1b8c2fb commit 6f968b4

20 files changed

Lines changed: 223 additions & 231 deletions

chapter25/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ public CodeGen loopTree() {
425425
}
426426

427427
// ---------------------------
428+
public BAOS _serial;
428429
public void serialize() {
429430
assert _phase.ordinal() <= Phase.LoopTree.ordinal();
430431
_phase = Phase.Serialize;
@@ -656,47 +657,35 @@ public String reg(Node n) {
656657

657658
// ---------------------------
658659
// Encoding
660+
public Encoding _encoding;
659661
public CodeGen encode() {
660662
assert _phase == Phase.RegAlloc;
661663
_phase = Phase.Encoding;
662664
long t0 = System.currentTimeMillis();
663-
for( CompUnit ref : _compunits.values() )
664-
if( ref._src != null )
665-
(ref._encoding = new Encoding(this)).encode(ref);
665+
666+
_encoding = new Encoding(this).encode();
667+
666668
_times[Phase.Encoding.ordinal()] = System.currentTimeMillis() - t0;
667669
return this;
668670
}
669671

670672
// ---------------------------
671673
// Exporting to external formats
674+
ElfWriter _elf;
672675
public CodeGen exportELF( boolean inMemory, boolean main ) {
673676
assert _phase == Phase.Encoding;
674677
_phase = Phase.Export;
675678
long t0 = System.currentTimeMillis();
676-
if( inMemory ) {
677-
new LinkMem(this).link(compunit()._encoding); // In memory patching
678-
} else {
679-
ElfWriter elf = new ElfWriter(this);
680-
for( CompUnit cu : _compunits.values() )
681-
exportElf(cu,elf,main);
679+
if( _encoding!=null ) {
680+
if( inMemory )
681+
new LinkMem(this).link(_encoding); // In memory patching
682+
else
683+
_elf = new ElfWriter(this).export(main);
682684
}
683685
_times[Phase.Export.ordinal()] = System.currentTimeMillis() - t0;
684686
return this;
685687
}
686688

687-
private void exportElf(CompUnit cu, ElfWriter elf, boolean main) {
688-
// Not being written, or already written out?
689-
if( cu._encoding==null || cu._didWrite ) return;
690-
cu._didWrite = true; // Flag as will-be-written
691-
// Write dependent obj files before users of it, to force correct time
692-
// stamps.
693-
if( cu._deps != null )
694-
for( CompUnit dep : cu._deps )
695-
exportElf(dep,elf,false);
696-
elf.export(cu,main);
697-
}
698-
699-
700689

701690
// ---------------------------
702691

@@ -801,8 +790,7 @@ ElfReader getElf(File f) {
801790
public boolean _asmLittle=true;
802791
public String asm() { return asm(new SB()).toString(); }
803792
SB asm(SB sb) {
804-
for( CompUnit ref : _compunits.values() )
805-
ASMPrinter.print(sb,this,ref);
793+
ASMPrinter.print(sb,this);
806794
return sb;
807795
}
808796

chapter25/src/main/java/com/seaofnodes/simple/codegen/CompUnit.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,15 @@ public class CompUnit {
2424
final File _smp; // Simple source file, e.g. module_root/A/B/C.smp
2525
final File _obj; // ELF output file, e.g. build/A/B/C.o
2626
final public String _src; // Source code, from file or test case
27-
public Encoding _encoding; // Encoding for output
27+
//public Encoding _encoding; // Encoding for output
2828

2929
public TypeStruct _clz; // The one TypeStruct being published
30-
BAOS _serial; // Serialized IR for this ELF file
30+
//BAOS _serial; // Serialized IR for this ELF file
3131
Ary<CompUnit> _deps; // CompUnits that this CompUnit depends on
32-
boolean _didWrite; // Used to topo-sort a collection of CompUnits to write all at once
3332

34-
// List of symbols exported by this compilation unit, and their Node
35-
// definitions.
36-
public HashMap<String,Node> _exported;
33+
//// List of symbols exported by this compilation unit, and their Node
34+
//// definitions.
35+
//public HashMap<String,Node> _exported;
3736
// Per-Compilation-Unit Start/StopNodes, keeping alive all exported Nodes.
3837
// Null means no code loaded (yet).
3938
public StartCUNode _start;
@@ -50,11 +49,12 @@ public class CompUnit {
5049
_ext = null;
5150
_smp = new File( CODE. _modDir + "/" + fname + ".smp");
5251
_obj = new File( CODE._buildDir + "/" + fname + ".o" );
53-
_src = !_obj.exists() || // No object file?
54-
_smp.lastModified() > _obj.lastModified() || // Out-of-date with source?
55-
checkDependentObjs() // Out-of-date with other objs?
56-
? new String(Files.readAllBytes(_smp.toPath()))
57-
: null;
52+
53+
boolean mustCompile = _smp.exists() && // Has source to compile
54+
( !_obj.exists() || // No object file
55+
_smp.lastModified() > _obj.lastModified() || // Out-of-date with source?
56+
checkDependentObjs() ); // Out-of-date with other objs?
57+
_src = mustCompile ? new String(Files.readAllBytes(_smp.toPath())) : null;
5858
}
5959

6060
// Test case. No source file. Source code passed in as a String. Fake
@@ -121,7 +121,7 @@ public void addFun(CodeGen code, FunNode fun) {
121121

122122
void setStart(CodeGen code) {
123123
_stop = new StopCUNode().init();
124-
_start = new StartCUNode(code._start,_stop, Type.BOTTOM).init();
124+
_start = new StartCUNode(code._start,_stop, Type.BOTTOM, _fname).init();
125125
code._stop.addDef(_stop);
126126
}
127127

chapter25/src/main/java/com/seaofnodes/simple/codegen/ElfReader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ void loadPublicSymbols() {
9090

9191
// Loads the entire IR
9292
public TypeStruct loadSimple(CodeGen code) {
93-
Serialize.readAll(code,this,_compunit, code._aliases, code._fidxs, code._rpcs);
93+
Serialize.readAll(code, this, code._aliases, code._fidxs, code._rpcs);
9494
return _clz;
9595
}
9696

chapter25/src/main/java/com/seaofnodes/simple/codegen/ElfWriter.java

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,15 @@ public int symbol( String name, int shndx, int bind, int type ) {
183183
// creates function and stores where it starts.
184184
// Filters to just this class.obj file.
185185
void encodeFunctions(StopNode stop, Encoding enc, int text_idx) {
186-
for( Node ret : stop._inputs ) {
187-
FunNode fun = ((ReturnNode)ret).fun();
188-
int end = enc.opStart(fun.ret()) + enc.opLen(fun.ret());
189-
long value = enc.opStart(fun);
190-
long size = end - value;
191-
if( fun._name != null ) // Anonymous functions have no name
192-
symbol(fun._name, text_idx, SYM_BIND_GLOBAL, SYM_TYPE_FUNC, value, size);
186+
for( Node stopcu : stop._inputs ) {
187+
for( Node ret : stopcu._inputs ) {
188+
FunNode fun = ((ReturnNode)ret).fun();
189+
int end = enc.opStart(fun.ret()) + enc.opLen(fun.ret());
190+
long value = enc.opStart(fun);
191+
long size = end - value;
192+
if( fun._name != null ) // Anonymous functions have no name
193+
symbol(fun._name, text_idx, SYM_BIND_GLOBAL, SYM_TYPE_FUNC, value, size);
194+
}
193195
}
194196
}
195197

@@ -247,7 +249,7 @@ public class SimpleSection extends DataSection {
247249

248250
// ------------------------------------------------------------------------
249251

250-
public void export(CompUnit ref, boolean main) {
252+
public ElfWriter export(boolean main) {
251253
// Sections are created in the order they are emitted.
252254
_sections = new Ary<>(Section.class);
253255

@@ -263,7 +265,7 @@ public void export(CompUnit ref, boolean main) {
263265
SymbolSection symbols = new SymbolSection(nlocals);
264266

265267
// we've already constructed these entire sections in the encoding phase
266-
Encoding enc = ref._encoding;
268+
Encoding enc = _code._encoding;
267269
DataSection text = new DataSection(".text" , Section.SHT_PROGBITS, enc._bits , DataSection.SHF_ALLOC | DataSection.SHF_WRITE | DataSection.SHF_EXECINSTR );
268270
// Constant pool
269271
DataSection rodata = new DataSection(".rodata", Section.SHT_PROGBITS, enc._cpool, DataSection.SHF_ALLOC );
@@ -273,7 +275,7 @@ public void export(CompUnit ref, boolean main) {
273275

274276

275277
// populate function symbols
276-
symbols.encodeFunctions(ref._stop, ref._encoding, text._index);
278+
symbols.encodeFunctions(_code._stop, _code._encoding, text._index);
277279
// The "main" symbol, starting code is always location 0
278280
if( main )
279281
symbols.symbolMain(text._index);
@@ -295,7 +297,7 @@ public void export(CompUnit ref, boolean main) {
295297
}
296298

297299
// Create a "Simple" section for Simple types and ir
298-
SimpleSection simple = new SimpleSection(ref._serial);
300+
SimpleSection simple = new SimpleSection(_code._serial);
299301

300302
// Write the local section header symbols
301303
assert nlocals == 1+_sections._len;
@@ -343,7 +345,7 @@ public void export(CompUnit ref, boolean main) {
343345

344346
assert out.position() == size;
345347

346-
String objName = _code._buildDir + "/" + ref._fname + ".o";
348+
String objName = _code._buildDir + "/" + _code._srcName + ".o";
347349
File file = new File(objName);
348350
if( file.getParentFile()!=null )
349351
file.getParentFile().mkdirs();
@@ -358,6 +360,7 @@ public void export(CompUnit ref, boolean main) {
358360
// Reset for next ELF
359361
_sections = null;
360362
_strtab = null;
363+
return this;
361364
}
362365

363366
}

chapter25/src/main/java/com/seaofnodes/simple/codegen/Encoding.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,13 @@ public void largeConstant( Node relo, Type t, int off, int elf ) {
177177
}
178178

179179
// --------------------------------------------------
180-
void encode( CompUnit ref ) {
180+
Encoding encode( ) {
181181
// Basic block layout: negate branches to keep blocks in-order; insert
182182
// unconditional jumps. Attempt to keep backwards branches taken,
183183
// forwards not-taken (this is the default prediction on most
184184
// hardware). Layout is still Reverse Post Order but with more
185185
// restrictions.
186-
basicBlockLayout( ref );
186+
basicBlockLayout( );
187187

188188
// Write encoding bits in order into a big byte array.
189189
// Record opcode start and length.
@@ -200,14 +200,16 @@ void encode( CompUnit ref ) {
200200

201201
// Patch RIP-relative and local encodings now.
202202
patchLocalRelocations();
203+
204+
return this;
203205
}
204206

205207
// --------------------------------------------------
206208
// Basic block layout: negate branches to keep blocks in-order; insert
207209
// unconditional jumps. Attempt to keep backwards branches taken, forwards
208210
// not-taken (this is the default prediction on most hardware). Layout is
209211
// still Reverse Post Order but with more restrictions.
210-
private void basicBlockLayout( CompUnit cu ) {
212+
private void basicBlockLayout( ) {
211213
IdentityHashMap<LoopNode,Ary<CFGNode>> rpos = new IdentityHashMap<>();
212214
_cfg = new Ary<>(CFGNode.class);
213215
rpos.put(_code._start.loop(),_cfg);
@@ -216,7 +218,7 @@ private void basicBlockLayout( CompUnit cu ) {
216218
// Do them all except the <clinit>
217219
FunNode clinit=null;
218220
for( FunNode fun : _code._linker ) {
219-
if( fun != null && !fun.isDead() && fun._compunit == cu ) {
221+
if( fun != null && !fun.isDead() ) {
220222
if( fun.isClz() ) {
221223
clinit = fun;
222224
} else {

chapter25/src/main/java/com/seaofnodes/simple/codegen/Opto.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,10 @@ private static void sccp( CodeGen code, Ary<Type> oldTypes ) {
164164
Type oval = n._type, nval = n.compute();
165165
if( oval == nval ) continue;
166166
assert oval.isa(nval); // Types start high and always fall
167-
Type pesiVal = oldTypes.at(n._nid);
167+
Type pesiVal = oldTypes.atX(n._nid);
168168
// TODO: This asset should be valid. Fails because no way to represent
169169
// "all the outside world except things I know about"
170-
assert nval.isa(pesiVal); // Never fall worse than the pessimistic pass
170+
assert pesiVal==null || nval.isa(pesiVal); // Never fall worse than the pessimistic pass
171171
n._type = nval;
172172

173173
// Now we have a series of stanzas where we lazily create the Call

chapter25/src/main/java/com/seaofnodes/simple/codegen/ParseAll.java

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -107,15 +107,6 @@ private static void parseAll(CodeGen code, CompUnit cunit) {
107107
// closed-over types.
108108
code._stop.walk( (Node n) -> {
109109
n.upgradeType(Parser.TYPES);
110-
// If function types have sharpened, we need to revisit inline
111-
// decisions.
112-
if( n instanceof FunNode fun ) {
113-
code.add(n); // Recheck after parse stops making new function calls
114-
// Linked call sites might now inline, need to recheck
115-
for( Node cend : fun.ret().outs() )
116-
if( cend instanceof CallEndNode )
117-
code.add(cend);
118-
}
119110
if( n instanceof FRefNode fref ) {
120111
TypeStruct clz = (TypeStruct)Parser.TYPES.get(fref._name);
121112
if( clz == null )
@@ -133,6 +124,10 @@ private static void parseAll(CodeGen code, CompUnit cunit) {
133124
code.add(add);
134125
return null;
135126
} );
127+
128+
// If we loaded Opto-typed code, skip first Iter
129+
if( !NEEDS_LOAD.isEmpty() )
130+
code._phase = CodeGen.Phase.Iter;
136131
}
137132

138133
// Parse one Simple source code file. Add all the FRefs produced to the worklist.
@@ -202,9 +197,9 @@ private static void loadDeps(CodeGen code, CompUnit cunit) {
202197
elf.loadPublicSymbols();
203198
for( String fname : elf._deps ) {
204199
// Check CompUnit for being up to date
205-
CompUnit sub = makeCUnit(code,null,fname,depObj(code,cunit,fname));
200+
CompUnit sub = makeCUnit(code,null,fname,null/*depObj(code,cunit,fname)*/);
206201
// If not seen before or out of date, parse the new nested cunit
207-
if( sub._clz == null )
202+
if( sub._clz == null && sub._par == null )
208203
WORK.add(sub);
209204
}
210205
} catch( IOException ioe ) {
@@ -234,31 +229,29 @@ private static void loadCompUnit(CodeGen code, CompUnit cunit) {
234229
// cross-references will pick them up there.
235230
ElfReader elf = ElfReader.load(cunit._obj,cunit);
236231
cunit._clz = elf.loadSimple(code);
237-
StopCUNode lStop = (StopCUNode)elf._nodes.at(elf._nodes._len-2);
238-
StartCUNode lStart = lStop.start();
239-
240-
// Loaded fidxs have already been remapped into this CodeGen's local
241-
// namespace. Publish the function heads so Opto can resolve escaped
242-
// function pointers without scanning the whole loaded graph.
243-
for( Node use : lStart._outputs )
244-
if( use instanceof FunNode fun )
232+
StartNode lstart = (StartNode)elf._nodes.at(0);
233+
StopNode lstop = ( StopNode)elf._nodes.last();
234+
235+
// Add all new loaded functions to the linker table
236+
for( Node n : lstop._inputs ) {
237+
StopCUNode stop = (StopCUNode)n;
238+
StartCUNode start = stop.start();
239+
CompUnit cu = code._compunits.get(start._fname);
240+
cu._start = start;
241+
cu._stop = stop ;
242+
243+
for( Node ret : stop._inputs ) {
244+
FunNode fun = ((ReturnNode)ret).fun();
245245
code.link(fun);
246+
}
247+
}
246248

247-
// The global Stop owns each loaded CompUnit Stop; the global Start
248-
// replaces the loaded Start as the single external-world boundary.
249-
cunit._start = lStart;
250-
cunit._stop = lStop ;
251-
code._stop.addDef(cunit._stop);
252-
code.add(code._stop);
253-
code.add(lStop);
254-
lStart.in(0).subsume(code._start);
255-
code.add(code._start);
256-
257-
// Loaded CompUnits carry post-Opto types. Keep those strong facts and
258-
// let the next global analysis reconcile them with parsed code.
249+
// Hook the new code into the existing code graph
250+
for( Node lstopcu : lstop._inputs )
251+
code._stop.addDef(lstopcu);
252+
lstart.subsume(code._start);
259253

260254
// Add the new top-level loaded class
261-
// assert !Parser.TYPES.containsKey(cunit._clz._name);
262255
Parser.TYPES.put(cunit._clz._name,cunit._clz);
263256
Field inst = cunit._clz.field(cunit._name);
264257
if( inst != null ) // Also the instance type, if a constructor exists

0 commit comments

Comments
 (0)