summaryrefslogtreecommitdiff
path: root/src/main/java/com/seaofnodes/simple/codegen/CompUnit.java
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-08-10 11:11:18 -0700
committerCliff Click <cliffc@acm.org>2026-10-08 16:52:27 -0700
commitd32f97238c903765dec4e9a9f3cbfa5fd12cded6 (patch)
treea5ac731801ef7066bab6359c4e85c2bdd20082a6 /src/main/java/com/seaofnodes/simple/codegen/CompUnit.java
parentb5ebb2032aa04cf4506d533127d373d4cf5a25c6 (diff)
downloadSimple-linear.tar.gz
Simple-linear.zip
Chapter 25: Modules, Separate Compilation, and SSA Constructionlinear
Co-authored-by: Hsiang-Ying Fu <66062782+fuhsnn@users.noreply.github.com> Co-authored-by: fuhsnn <66062782+fuhsnn@users.noreply.github.com> Co-authored-by: Symious <14933944+symious@users.noreply.github.com> Co-authored-by: Jun Kawasaki <jun784@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'src/main/java/com/seaofnodes/simple/codegen/CompUnit.java')
-rw-r--r--src/main/java/com/seaofnodes/simple/codegen/CompUnit.java135
1 files changed, 135 insertions, 0 deletions
diff --git a/src/main/java/com/seaofnodes/simple/codegen/CompUnit.java b/src/main/java/com/seaofnodes/simple/codegen/CompUnit.java
new file mode 100644
index 00000000..d1326cee
--- /dev/null
+++ b/src/main/java/com/seaofnodes/simple/codegen/CompUnit.java
@@ -0,0 +1,135 @@
+package com.seaofnodes.simple.codegen;
+
+import com.seaofnodes.simple.Parser;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeStruct;
+import com.seaofnodes.simple.util.*;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.*;
+import static com.seaofnodes.simple.codegen.CodeGen.CODE;
+
+// A compilation-unit, which is an external reference and source and object
+// files. These are mirrored over a file system tree (so form a tree), both
+// the source tree and build/object tree.
+public class CompUnit {
+ public final CompUnit _par; // Parent, e.g. A/B
+ final String _fname; // Full slashed file name starting from module root, e.g. A/B/C
+ final public String _cname; // Full dotted class name starting from module root, e.g. A.B.C
+ final String _name; // Base name, e.g. C
+ final ExternNode _ext; // Found in external libs; e.g. libc
+ final File _smp; // Simple source file, e.g. module_root/A/B/C.smp
+ public final File _obj; // ELF output file, e.g. build/A/B/C.o
+ final public String _src; // Source code, from file or test case
+ //public Encoding _encoding; // Encoding for output
+
+ public TypeStruct _clz; // The one TypeStruct being published
+ //BAOS _serial; // Serialized IR for this ELF file
+ Ary<CompUnit> _deps; // CompUnits that this CompUnit depends on
+
+ // Per-Compilation-Unit Start/StopNodes, keeping alive all exported Nodes.
+ // Null means no code loaded (yet).
+ public StartCUNode _start;
+ public StopCUNode _stop ;
+
+
+ // Discovered source file. Source is loaded if required to parse, and null
+ // otherwise.
+ CompUnit( CompUnit par, String fname, String cname, String name ) throws IOException {
+ _par = par;
+ _fname= fname;
+ _cname= cname;
+ _name = name;
+ _ext = null;
+ _smp = new File( CODE. _modDir + "/" + fname + ".smp");
+ _obj = new File( CODE._buildDir + "/" + fname + ".o" );
+
+ boolean mustCompile = _smp.exists() && // Has source to compile
+ ( !_obj.exists() || // No object file
+ _smp.lastModified() > _obj.lastModified() || // Out-of-date with source?
+ checkDependentObjs() ); // Out-of-date with other objs?
+ _src = mustCompile ? new String(Files.readAllBytes(_smp.toPath())) : null;
+ }
+
+ // Test case. No source file. Source code passed in as a String. Fake
+ // class name.
+ CompUnit( String fname, String src ) {
+ _par = null;
+ _name = fname;
+ _fname= fname;
+ _cname= fname;
+ _ext = null;
+ _smp = null;
+ _obj = null;
+ _src = src;
+ }
+
+ // External CompUnit, pulled in from an external library like libc
+ CompUnit( ExternNode ext, String symbol ) {
+ _par = null;
+ _name = symbol;
+ _fname= _name;
+ _cname= null;
+ _ext = ext;
+ _smp = null;
+ _obj = null;
+ _src = null;
+ }
+
+ // External Simple object file, or namespace parent, found on an external search path.
+ CompUnit( File obj, CompUnit par, String fname, String cname, String name ) {
+ _par = par;
+ _name = name;
+ _fname= fname;
+ _cname= cname;
+ _ext = null;
+ _smp = null;
+ _obj = obj;
+ _src = null;
+ }
+
+ // Return true if _obj is out-of-date relative to dependents.
+ private boolean checkDependentObjs() {
+ ElfReader elf = CODE.getElf(_obj);
+ elf.loadPublicSymbols();
+ for( String dep : elf._deps ) {
+ File obj = new File(CODE._buildDir+"/"+dep+".o");
+ if( obj.lastModified() > _obj.lastModified() ) // Out-of-date with deps?
+ return true;
+ }
+ return false;
+ }
+
+ // Add a discovered dependency, for later writing out in an ELF file, ".simple" section
+ void addDep(CompUnit dep) {
+ if( _deps == null ) _deps = new Ary<>(CompUnit.class);
+ _deps.add(dep);
+ }
+
+ public void addFun(CodeGen code, FunNode fun) {
+ assert fun.in(1)==_start;
+ _stop.addDef(fun.ret());
+ code.add(_stop);
+ _stop.addDep(fun);
+ }
+
+ void setStart(CodeGen code) {
+ _stop = new StopCUNode().init();
+ _start = new StartCUNode(code._start,_stop, Type.BOTTOM, _fname).init();
+ code._stop.addDef(_stop);
+ }
+
+
+ @Override public String toString() {
+ String x = "{"+_cname;
+ if( _smp!=null && _smp.exists()) x += ",hasSMP";
+ if( _obj!=null && _obj.exists()) x += ",hasObj";
+ if( _src!=null ) x += ",hasSrc";
+ if( _ext != null ) x += ",isExt";
+ x += "}";
+ return x;
+ }
+}