summaryrefslogtreecommitdiff
path: root/src/main/java/com/seaofnodes/simple/codegen/CompUnit.java
blob: d1326ceefa1411e3c4a076c5e19716e078e11d88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
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;
    }
}