From 51f1f8f4b871e3b52eb0c5d18b03f362a2b37791 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Mon, 10 Aug 2026 11:11:18 -0700 Subject: Chapter 25: add separate compilation and simplify SSA construction Introduce Chapter 25 with separately compiled Simple modules, serialized IR, cross-compilation-unit linking, and native system-library integration. This also completes a broad parser and type-system cleanup needed to make graph construction independent of incomplete parse-time type information. Separate compilation and linking - Add compilation-unit Start/Stop nodes and track functions, classes, aliases, and global indices across compilation-unit boundaries. - Serialize canonical types and ideal graph nodes into ELF objects, including dependency metadata, relocations, global/local bitset remapping, and dense memory-alias information. - Load dependent objects on demand, recursively resolve source and object paths, relink calls and function pointers, and preserve external C symbols. - Distinguish the post-optimization ownership hook from unknown callers so private call graphs can remain precise while public functions remain externally callable. - Add command-line and build support for compiling modules and the reusable `sys` object library. Parser, constructors, and SSA - Replace inline constructor expansion with a hidden default `` followed by an explicit user constructor declared as `new Type = { ... }`. - Keep the default constructor private, pass private object memory through constructor calls, and require user constructors to initialize non-default fields before the object escapes. - Track possibly-uninitialized fields in parser `Var` state and diagnose early reads without encoding parser-only constraints in Load and Store nodes. - Make ordinary parser memory bulk and recover precise alias slices in the optimizer using `MemMerge`, `MemPhi`, and `BulkMemPhi` nodes. - Remove parser-supplied type constraints from Loads and ordinary Phis, defer integer/float arithmetic selection, and keep call shape driven by syntax instead of provisional inferred types. - Preserve chained field declarations as static parser information when flow types are not yet available, including postfix field updates through calls. Types, functions, and escape analysis - Add `TypeScalar` as the common lattice family for integer, float, memory pointer, and function-pointer values, with scalar TOP/BOT values for generic Loads, Stores, parameters, and invalid intermediate expressions. - Represent unresolved struct definitions directly with the `TypeStruct` forward-reference flag while retaining the separate open-structure concept; close and canonicalize recursive structures without side maps. - Add explicit `FunPtrNode` references so constant function pointers retain a graph edge to their Return, and keep referenced functions alive until Opto proves the pointer dead. - Refine public-function and class-initializer escape handling, including public-only fallback escape sets and monotone compilation-unit summaries. - Add guards, proof casts, read-only propagation, pointer-to-integer conversion for non-null FFI arguments, and consistent deep mutability checks at calls. Optimization and code generation - Make weak and unresolved graph inputs compute conservatively and monotonically throughout iterative peepholes and SCCP. - Preserve independent memory slices when sharpening Stores, retain control on conditional Stores, and freeze Store widths from their target field types. - Extend serialization for new node kinds, scalar types, Store modes, function pointers, and memory partitions, preserving serialize/deserialize bijection. - Complete native selection and encoding support across x86-64, RISC-V, and ARM, including FFI pointer conversion and missing integer operations. - Fix x86 immediate multiply REX encoding and assorted scheduling, register allocation, spilling, relocation, and constant-pool issues exposed by the larger linked graphs. System library, tests, and documentation - Compile and link the Simple `sys` library, including libc bindings, I/O, scanners, strings, vectors, array helpers, and executable entry points. - Add Chapter 25 module, serialization, constructor, forward-reference, postfix-update, system, Hello World, and Bubble Sort coverage; update golden graphs and spill expectations for the new IR shape. - Add module and type-system documentation, parser-simplification design notes, grammar updates, examples, diagrams, and graph visualization assets. The resulting compiler passes the raw Chapter 1-24 suite and the Chapter 25 system and separate-compilation tests, including a freshly rebuilt `sys.o` and the native Bubble Sort example. --- chapter25/docs/lattice.gv | 203 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 chapter25/docs/lattice.gv (limited to 'chapter25/docs/lattice.gv') diff --git a/chapter25/docs/lattice.gv b/chapter25/docs/lattice.gv new file mode 100644 index 00000000..8661082d --- /dev/null +++ b/chapter25/docs/lattice.gv @@ -0,0 +1,203 @@ +digraph Lattice { + compound = true; + // Define nodes + splines=false; + node [shape=circle, style=filled]; + nodesep=0.2; + ranksep=0.2; + + TOP [label=<⊤>, fillcolor=black, fontcolor=white]; + BOT [label=<⊥>, fillcolor=black, fontcolor=white]; + + // ---------------------- + // Control + XCTRL [label=<⊤:ctrl>, fillcolor=yellow, shape=oval]; + CTRL [label=<⊥:ctrl>, fillcolor=yellow, shape=oval]; + + TOP -> XCTRL; + XCTRL -> CTRL; + CTRL -> BOT; + + // ---------------------- + // Integers + INT_TOP [label=<⊤:int>, fillcolor=lightblue, shape=oval]; + INT_BOT [label=<⊥:int>, fillcolor=lightblue, shape=oval]; + + INT_HI [label="[min>max]" , fillcolor=lightblue, shape=oval]; + INT_XBOOL [label="[1...0]", fillcolor=lightblue, shape=oval]; + INT_CON [label="constants", fillcolor=lightblue, shape=oval]; + INT_CON0 [label="0", fillcolor=lightblue]; + INT_CON1 [label="1", fillcolor=lightblue]; + INT_BOOL [label="[0...1]", fillcolor=lightblue,shape=oval]; + INT_LO [label="[min INT_TOP; + INT_TOP -> INT_HI; + INT_HI -> INT_XBOOL; + INT_XBOOL -> INT_CON0; + INT_XBOOL -> INT_CON1; + INT_HI -> INT_CON; + INT_CON0 -> INT_BOOL; + INT_CON1 -> INT_BOOL; + INT_BOOL -> INT_LO; + INT_CON -> INT_LO; + INT_LO -> INT_BOT; + INT_BOT -> BOT; + + INT_CON0 -> INT_CON1 -> INT_CON [style=invis]; + + // ---------------------- + // Floats + FLT_TOP [label=<⊤:flt>, fillcolor=aqua, shape=oval]; + FLT_BOT [label=<⊥:flt>, fillcolor=aqua, shape=oval]; + + FLT_CON64 [label="64b consts\n[excludes\n32b consts]" , fillcolor=aqua, shape=oval]; + FLT_CON32 [label="32b consts", fillcolor=aqua, shape=oval]; + FLT_CONPI [label="3.14159...", fillcolor=aqua, shape=oval]; + FLT_X32 [label="~f32", fillcolor=aqua]; + FLT_CON0 [label="0." , fillcolor=aqua]; + FLT_32 [label="f32" , fillcolor=aqua]; + + TOP -> FLT_TOP; + FLT_TOP -> FLT_CON64 + FLT_TOP -> FLT_CONPI + FLT_CON64 -> FLT_BOT + FLT_CONPI -> FLT_BOT + + FLT_TOP -> FLT_X32; + FLT_X32 -> FLT_CON0; + FLT_X32 -> FLT_CON32; + FLT_CON0 -> FLT_32; + FLT_CON32 -> FLT_32; + FLT_32 -> FLT_BOT + + FLT_BOT -> BOT; + + FLT_CON0 -> FLT_CON32 -> FLT_CONPI -> FLT_CON64 [style=invis]; + + + // ---------------------- + // Pointers, just a boolean nil/not and a struct + PTR [shape=none, fillcolor=none, label=< + + + +
*ptr
struct
+ >]; + PTR0 [shape=none, fillcolor=none, label=< + + + +
*ptr?
struct
+ >]; + + TOP -> PTR; + PTR -> PTR0; + PTR0 -> BOT; + + // ---------------------- + // Structs + STRUCT_TOP [label=<⊤:struct>, fillcolor=lightgreen, shape=oval]; + STRUCT_BOT [label=<⊥:struct>, fillcolor=lightgreen, shape=oval]; + + STRUCT_S1 [shape=none, fillcolor=none, label=< + + +
fieldint/ptr
+ >]; + STRUCT_S2 [shape=none, fillcolor=none, label=< + + + +
fieldint/ptr
fieldint/ptr
+ >]; + STRUCT_SN [shape=none, fillcolor=none, label=< + + + + +
fieldint/ptr
... int/ptr
fieldint/ptr
+ >]; + + + TOP -> STRUCT_TOP; + STRUCT_TOP -> STRUCT_S1; + STRUCT_TOP -> STRUCT_S2; + STRUCT_TOP -> STRUCT_SN; + STRUCT_S1 -> STRUCT_BOT; + STRUCT_S2 -> STRUCT_BOT; + STRUCT_SN -> STRUCT_BOT; + STRUCT_BOT -> BOT; + + STRUCT_S1 -> STRUCT_S2 -> STRUCT_SN [style=invis]; + + // ---------------------- + // Memory + MEM_TOP [label=<⊤:mem>, fillcolor=blue, fontcolor=white, shape=oval]; + MEM_BOT [label=<⊥:mem>, fillcolor=blue, fontcolor=white, shape=oval]; + MEM_ALIAS1 [label="#1" , fillcolor=blue, fontcolor=white]; + MEM_ALIASDOTS [label="..." , fillcolor=blue, fontcolor=white, shape=oval]; + MEM_ALIASN [label="#n" , fillcolor=blue, fontcolor=white]; + + TOP -> MEM_TOP; + MEM_TOP -> MEM_ALIAS1; + MEM_TOP -> MEM_ALIASDOTS; + MEM_TOP -> MEM_ALIASN; + MEM_ALIAS1 -> MEM_BOT; + MEM_ALIASDOTS -> MEM_BOT; + MEM_ALIASN -> MEM_BOT; + MEM_BOT -> BOT; + + MEM_ALIAS1 -> MEM_ALIASDOTS -> MEM_ALIASN [style=invis]; + + // ---------------------- + // Tuples + + TUPLE_TOP [label=<⊤:tuple>, fillcolor=pink, shape=oval]; + TUPLE_BOT [label=<⊥:tuple>, fillcolor=pink, shape=oval]; + + TUPLE1 [shape=none, fillcolor=none, label=< + + + +
Tuple
type
+ >]; + TUPLE2 [shape=none, fillcolor=none, label=< + + + + +
Tuple
type
type
+ >]; + TUPLEN [shape=none, fillcolor=none, label=< + + + + + +
Tuple
type
...
type
+ >]; + + + TOP -> TUPLE_TOP; + TUPLE_TOP -> TUPLE1; + TUPLE_TOP -> TUPLE2; + TUPLE_TOP -> TUPLEN; + TUPLE1 -> TUPLE_BOT; + TUPLE2 -> TUPLE_BOT; + TUPLEN -> TUPLE_BOT; + TUPLE_BOT -> BOT; + + // ---------------------- + // Additional customization + {rank=same; TOP;} + {rank=same; INT_TOP; FLT_TOP; XCTRL; PTR; STRUCT_TOP; MEM_TOP; TUPLE_TOP} + {rank=same; INT_CON; INT_CON0; INT_CON1; + FLT_CON32; FLT_CON64; FLT_CON0; FLT_CONPI; + STRUCT_S1; STRUCT_S2; STRUCT_SN; + MEM_ALIAS1; MEM_ALIASDOTS; MEM_ALIASN; + TUPLE1; TUPLE2; TUPLEN; + } + {rank=same; INT_BOT; FLT_BOT; CTRL; PTR0; STRUCT_BOT; MEM_BOT; TUPLE_BOT} + {rank=same; BOT;} +} -- cgit v1.2.3