From 41ae6269689e2b3cde9f7ac4227923d4085dceda Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Fri, 2 Oct 2026 16:21:02 -0700 Subject: More better layout ch10a,b,11 --- chapter10b/#README.md# | 174 ------------------------ chapter10b/.#README.md | 1 - chapter10b/README.md | 119 ++++++++++------- chapter10b/docs/Makefile | 15 +-- chapter10b/docs/example1.json | 31 +++++ chapter10b/docs/example1.svg | 248 +++++++++++++++++++++------------- chapter10b/docs/example2a.json | 20 +++ chapter10b/docs/example2a.svg | 185 ++++++++++++++------------ chapter10b/docs/example2b.json | 30 +++++ chapter10b/docs/example2b.svg | 251 ++++++++++++++++++++-------------- chapter10b/docs/example2c.json | 23 ++++ chapter10b/docs/example2c.svg | 177 ++++++++++++++++-------- chapter10b/docs/lattice.gv | 25 +++- chapter10b/docs/lattice.svg | 296 ++++++++++++++++++++++------------------- 14 files changed, 886 insertions(+), 709 deletions(-) delete mode 100644 chapter10b/#README.md# delete mode 100644 chapter10b/.#README.md create mode 100644 chapter10b/docs/example1.json create mode 100644 chapter10b/docs/example2a.json create mode 100644 chapter10b/docs/example2b.json create mode 100644 chapter10b/docs/example2c.json (limited to 'chapter10b') diff --git a/chapter10b/#README.md# b/chapter10b/#README.md# deleted file mode 100644 index 6380b79e..00000000 --- a/chapter10b/#README.md# +++ /dev/null @@ -1,174 +0,0 @@ -# Chapter 10b: Splitting Memory - -[Previous: Chapter 10a](../chapter10a/README.md) | -[Next: Chapter 11](../chapter11/README.md) - -Chapter 10a made memory effects explicit with one SSA memory value. This -chapter keeps exactly that parser model and recovers independent memory chains -through graph rewrites. There is no new language syntax; the -[grammar](docs/10-grammar.md), pointer types, and null checks are unchanged. - -## Why split memory? - -```java -struct Point { int x; int y; } -Point p = new Point; -p.x = 42; -while (arg > 0) { - p.y = p.y + arg; - arg = arg - 1; -} -return p.x; -``` - -The loop changes `y`, so it cannot affect `x`. With one memory chain the load -of `x` follows the loop's stores. Splitting the fields lets ordinary -load-after-store forwarding turn the return value into 42. - -![Independent field dependencies](docs/example1.svg) - -Control, pointer, and value edges are omitted when they do not explain memory. - -## Equivalence-class aliasing - -Each struct field has an integer alias identity. Two different fields receive -different identities, even if they have the same spelling in different structs. -Two instances of the same struct share their field aliases. Thus different -classes never alias; accesses in the same class **may alias**. Same-class does -not mean same-address: forwarding still checks pointer identity. - -The parser assigns field identities at struct declarations, beginning at 2. -These identities are independent of Start's output indices. The default slot -of a memory aggregate is 1; precise slots are greater than 1. - -We do not allocate a Start projection, scope binding, or loop Phi for every -declared field. Start supplies one memory value, Scope holds one `$mem` binding, -and Return consumes one complete memory value. The optimizer introduces slices -only where graph operations require them. - -## Three memory nodes - -| Node | Meaning | -|---|---| -| `MemMerge` | A complete memory state: a default plus precise alias overrides | -| `MemPhi` | One alias selected according to the incoming control path | -| `BulkMemPhi` | All aliases except an explicit exclusion set, selected by control | - -`MemMerge` combines independent pieces of memory at one program point. It is -not a control-flow merge. For example, after storing to alias `x`: - -```text -prior = current memory -store = Store_x(prior, pointer, value) -current memory = MemMerge(default=prior, x=store) -``` - -The Store selects its precise input from any incoming MemMerge. Loads and -precise memory Phis do the same. A missing precise entry falls back to the -default, provided that default still covers the requested alias. - -The explicit entries override the default: the semantic slices are disjoint, -and their union covers all memory. Flattening stacked aggregates preserves -entries that the outer aggregate has not replaced. This allows an `x` store -and a later `y` store to remain visible together at Return. - -![An aggregate preserves both updates](docs/example2a.svg) - -## Splitting a memory Phi - -Scope initially creates a BulkMemPhi wherever the ordinary SSA algorithm needs -to merge memory. Its empty exclusion set means that it covers every alias. -After the Region is complete, the Phi inspects its memory inputs and users. -When they require a precise alias, it splits out that alias: - -```text -BulkPhi(R, left, right) - becomes -MemMerge( - default = BulkPhi_except{x}(R, left, right), - x = MemPhi_x(R, slice(left,x), slice(right,x))) -``` - -The new precise Phi and the remaining bulk Phi share a Region and matching -control-path indices. A loop uses the same transformation, with the backedge -among those inputs. Each further split preserves all previously extracted -slices; replacing a bulk Phi must never drop their parallel precise Phis. - -![Precise and bulk Phis share a control merge](docs/example2b.svg) - -A bulk Phi can bypass an incoming aggregate only when all of that aggregate's -explicit slices are already excluded from the Phi. A precise consumer can -select one entry. A whole-memory consumer cannot just select the default: -that would lose the explicit updates. - -## Types and the worklist - -The memory type lattice adds a flat element `MEM#N` for each precise alias. -Meeting different aliases gives `TypeMem.BOT`. It does not track field values, -private objects, or escape information. Bulk exclusion sets belong to the -graph nodes, not to an expanded type lattice. - -![The type domains, including precise memory aliases](docs/lattice.svg) - -Scalar Phis remain ordinary PhiNodes. The scope's Phi factory chooses a -BulkMemPhi for whole memory; splitting constructs MemPhis explicitly. Generic -arithmetic factoring through Phis must not factor a memory aggregate. - -Memory splitting can increase node count. Progress comes from extracting an -alias from a bulk Phi and simplifying its precise chain, rather than from -requiring every rewrite to shrink the graph. Nodes must have conservative -initial types before introducing cyclic inputs. New bulk and precise Phis are -queued, so a recursive peephole cannot start another split halfway through the -first one. - -This also extends the worklist lesson from Chapter 9. A bulk Phi inspects its -users, so changes to a user's partition must wake the producer. Selecting a -slice from an aggregate can expose a new bulk-Phi user; that selected definition -must be queued too. The optimizer's worklist completeness assertion remains -enabled and checks these dependencies. - -## Evaluation and ordering - -MemMerge is a dependency node; it emits no heap operation. Its evaluator result -is a memory token, while Store mutates the object's fields. The scheduler must -distinguish aggregation from overwriting memory. A MemMerge is not a clobber, -and stores in different alias classes do not impose load/store anti-dependencies. - -![Ordering applies within the affected alias](docs/example2c.svg) - -Tests cover independent-field folding, parallel memory Phis, multiple field -updates surviving at Return, early returns, nested loops with break/continue, -and reads before subsequent stores through potentially aliased pointers. - -## What remains for later chapters? - -Chapter 10b knows every access's alias while parsing. What is lazy here is the -construction of memory partitions. Chapter 25 also allows an existing access's -alias to become known later, using the same representation. Its private -constructor memory, escape tracking, incomplete types, and module alias -remapping are separate extensions and are not needed here. - -Chapters 11-24 currently retain their older parser-managed memory chains. -Forwarding this representation through those snapshots is tracked in the -[backport queue](../docs/chapter-backports.md). Chapter 11's scheduling lesson -therefore still shows the older graph construction, with the same language. - -## Build and test - -With JDK 21 or newer, from this directory: - -```sh -make lib -make tests -make release -make view -``` - -Make builds this complete snapshot without Maven. `make release` writes -`build/release/simple.jar`; `make view` launches the shared graph viewer. -Both the root Maven reactor and the supplied IDEA module descriptor include -the chapter. From the repository root, test both halves with: - -```sh -make tests CHAPTERS="chapter10a chapter10b" -``` diff --git a/chapter10b/.#README.md b/chapter10b/.#README.md deleted file mode 100644 index c657b199..00000000 --- a/chapter10b/.#README.md +++ /dev/null @@ -1 +0,0 @@ -cliffc@DESKTOP-DAD.21980:1790387027 \ No newline at end of file diff --git a/chapter10b/README.md b/chapter10b/README.md index 671d53c3..7cb4cc75 100644 --- a/chapter10b/README.md +++ b/chapter10b/README.md @@ -5,7 +5,7 @@ Chapter 10a made memory effects explicit with one SSA memory value. This chapter keeps exactly that parser model and recovers independent memory chains -through graph rewrites. There is no new language syntax; the +through graph rewrites. There is no new language syntax; the [grammar](docs/10-grammar.md), pointer types, and null checks are unchanged. ## Why split memory? @@ -27,6 +27,15 @@ load-after-store forwarding turn the return value into 42. ![Independent field dependencies](docs/example1.svg) +The graph shows the split chains before the final Load folds. Its memory input +goes straight to the Store of 42, bypassing the loop's `y` chain. As in 10a, +definitions appear above uses, apart from loop backedges, and arrows point +from use to definition. As in 10a, small, detached True/False projections +show the source branches gating Loads and Stores. Other control-flow context, +including Regions and their Phi bindings, is omitted. Chapter 11 chooses +the actual scheduling inputs; the vertical placement of independent chains +does not specify their execution order. + ## Equivalence-class aliasing Each struct field has an integer alias identity. Two different fields receive @@ -71,14 +80,21 @@ and their union covers all memory. Flattening stacked aggregates preserves entries that the outer aggregate has not replaced. This allows an `x` store and a later `y` store to remain visible together at Return. +The graph below shows `p.x = arg; p.y = 42; return p;` after redundant +initialization stores have been removed. MemMerge takes the default memory +in slot 1 and the `x` and `y` overrides in slots 2 and 3. + ![An aggregate preserves both updates](docs/example2a.svg) + ## Splitting a memory Phi Scope initially creates a BulkMemPhi wherever the ordinary SSA algorithm needs -to merge memory. Its empty exclusion set means that it covers every alias. -After the Region is complete, the Phi inspects its memory inputs and users. -When they require a precise alias, it splits out that alias: +to merge memory. It starts by covering all aliases and an empty exclusion set +while the merge point is finalized. Later, peeps will split out precise memory +slices from the bulk memory, lazily on demand. + +Precise single aliases can be split out from the bulk by this transformation: ```text BulkPhi(R, left, right) @@ -88,19 +104,47 @@ MemMerge( x = MemPhi_x(R, slice(left,x), slice(right,x))) ``` -The new precise Phi and the remaining bulk Phi share a Region and matching -control-path indices. A loop uses the same transformation, with the backedge -among those inputs. Each further split preserves all previously extracted -slices; replacing a bulk Phi must never drop their parallel precise Phis. +The new precise Phi and the remaining bulk Phi share a Region (omitted from +the illustrations) and matching control-path indices. A loop uses the same +transformation, with the backedge among those inputs. Each further split preserves all previously extracted +slices (and peephole optimizations tidy up the stacked splits). + +Here the two branches store 3 or 4 into `p.x`, then return `p`. The graph shows +the partition immediately after extracting `x`, before further simplification +of the bulk Phi and its incoming aggregates. ![Precise and bulk Phis share a control merge](docs/example2b.svg) -A bulk Phi can bypass an incoming aggregate only when all of that aggregate's -explicit slices are already excluded from the Phi. A precise consumer can -select one entry. A whole-memory consumer cannot just select the default: -that would lose the explicit updates. +This transform is invasive, and is disallowed from being called recursively; +you can end up splitting around a loop (which is good) but then visiting a +1/2-split loop head (which is bad). The new nodes from the split are put +on the worklist and visited after the current split completes. + +Since bulk Phis merge a bunch of aliases, they have to take care when +peepholing vs MemMerges: there cannot be any overlap between the MemMerge +precise merges and the bulk Phi. -## Types and the worklist +Phi refactoring can combine matching Loads or Stores as in Chapter 10a (pushing +up or pulling down). The Phi new memory operands can use precise MemPhis for +the alias. This peep requires precise aliases, and is otherwise blocked by +BulkMems - and thus is a trigger for splitting a BulkMem. + +This also extends the worklist lesson from Chapter 9. A bulk Phi inspects its +users, so changes to a user's partition must wake the producer - job for +`addDep()`. Selecting a slice from an aggregate can expose a new bulk-Phi +user; that selected definition must be queued too. In short, any time we're +working with MemMerge, MemPhi or BulkMemPhi we can expect some non-local +dependencies. + +Memory splitting can increase node count - but Phis (Mem, Bulk or otherwise) +make no code. Progress comes from extracting an alias from a bulk Phi and +removing some Loads & Stores, rather than from requiring every rewrite +to shrink the graph. In other words, the total Load/Store count is going down +even if the MemPhi count is going up. + + + +## Types The type lattice retains Chapter 10a's six domains, colors, and notation: `⊤` means top, `⊥` means bottom, and a suffix names the domain. The other five @@ -110,45 +154,18 @@ alias between memory top (`TypeMem.TOP`) and memory bottom (`TypeMem.BOT`). ![The type domains, including precise memory aliases](docs/lattice.svg) The parallel `MEM#2`, `MEM#3`, and further alias elements describe independent -field slices. For the first `Point` declaration above, these two aliases identify -`Point.x` and `Point.y`. Meeting different aliases gives memory bottom; joining -them gives memory top. Each precise alias is its own dual. The ellipsis stands -for more parallel aliases, not a type representing a set of aliases. - -Memory bottom covers all memory. The default aggregate slot numbered 1 is a -graph input position, not a precise field alias in this diagram. Types do not -track field values, private objects, or escape information. Bulk exclusion sets +field slices. For the first `Point` declaration above, these two aliases identify +`Point.x` and `Point.y`. Meeting different aliases gives memory bottom; joining +them gives memory top. Each precise alias is its own dual. (And the ellipsis stands +for more parallel aliases, not a type representing a set of aliases). + +Memory bottom covers all memory. The default aggregate slot numbered 1 is a +graph input position, not a precise field alias in this diagram. Types do not +track field values, private objects, or escape information. Bulk exclusion sets and the default-plus-overrides structure of MemMerge belong to graph nodes, -not to an expanded type lattice. As in Chapter 10a, diagram edges show lattice +not to an expanded type lattice. As in Chapter 10a, diagram edges show lattice order, with top above bottom; field and tuple-element type lattices are elided. -Scalar Phis remain ordinary PhiNodes. The scope's Phi factory chooses a -BulkMemPhi for whole memory; splitting constructs MemPhis explicitly. Phi -factoring can combine matching Loads or Stores as in Chapter 10a, but cannot -factor MemMerge or BulkMemPhi. Its new memory operands use precise MemPhis for -the operation's alias. Load safety checks only immediate memory users, rejecting -Stores, Phis, and MemMerges. A Phi or aggregate might lead to a later write; -we conservatively skip the rewrite instead of searching farther to save one Load. - -Factoring waits while a BulkMemPhi remains at the same Region. Bulk splitting -identifies parallel slices by Region and alias, whereas factoring a Store can -introduce a memory Phi *before* the Store at that same Region. Waiting avoids -mistaking that earlier memory for the aggregate's completed slice. - -Memory splitting can increase node count. Progress comes from extracting an -alias from a bulk Phi and simplifying its precise chain, rather than from -requiring every rewrite to shrink the graph. Nodes must have conservative -initial types before introducing cyclic inputs. New bulk and precise Phis are -queued, so a recursive peephole cannot start another split halfway through the -first one. - -This also extends the worklist lesson from Chapter 9. A bulk Phi inspects its -users, so changes to a user's partition must wake the producer. Selecting a -slice from an aggregate can expose a new bulk-Phi user; that selected definition -must be queued too. The optimizer's worklist completeness assertion remains -enabled and checks these dependencies. Factoring also depends on user counts: -removing a use wakes recorded dependents even when the definition's type stays -unchanged. ## Evaluation and ordering @@ -157,6 +174,10 @@ is a memory token, while Store mutates the object's fields. The scheduler must distinguish aggregation from overwriting memory. A MemMerge is not a clobber, and stores in different alias classes do not impose load/store anti-dependencies. +In `int old = p.x; p.x = arg; p.y = arg; return old;`, the Load must precede +the later `x` Store; the `y` Store has an independent memory chain. The graph +retains the Load to show this scheduling requirement before local folding. + ![Ordering applies within the affected alias](docs/example2c.svg) Tests cover independent-field folding, parallel memory Phis, multiple field diff --git a/chapter10b/docs/Makefile b/chapter10b/docs/Makefile index 055882b2..6fa0f057 100644 --- a/chapter10b/docs/Makefile +++ b/chapter10b/docs/Makefile @@ -1,14 +1 @@ -GV := $(wildcard *.gv) -SVG := $(patsubst %.gv,%.svg,$(GV)) -.DELETE_ON_ERROR: - -.PHONY: all -all: $(SVG) - -%.svg: %.gv - dot -Tsvg $< > $@ - @sed -i 's/\r$$//' $@ - -.PHONY: clean -clean: - @rm -f $(SVG) +include ../../graph/docs.mk diff --git a/chapter10b/docs/example1.json b/chapter10b/docs/example1.json new file mode 100644 index 00000000..67c277e1 --- /dev/null +++ b/chapter10b/docs/example1.json @@ -0,0 +1,31 @@ +{ + "ver": 1, + "comp": "chapter10b/docs/example1.svg", + "step": 1, + "roots": [24], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 1, "role": "MEM", "label": null}], "proj": {"par": 1, "idx": 1}}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "DATA", "label": null}], "proj": {"par": 1, "idx": 2}}, + {"id": 5, "label": "new Point", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}], "proj": null}, + {"id": 6, "label": "#0", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 7, "label": "#42", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 8, "label": "Store p.x", "type": "MEM#2", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 7, "role": "DATA", "label": null}], "proj": null}, + {"id": 9, "label": "Store p.y", "type": "MEM#3", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 6, "role": "DATA", "label": null}], "proj": null}, + {"id": 11, "label": "MemPhi y", "type": "MEM#3", "kind": "PHI", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": null}, {"idx": 1, "def": 9, "role": "MEM", "label": null}, {"idx": 2, "def": 19, "role": "MEM", "label": null}], "proj": null}, + {"id": 12, "label": "Phi arg", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 21, "role": "DATA", "label": null}], "proj": null}, + {"id": 15, "label": "True", "type": null, "kind": "CTRL", "edges": [], "proj": {"par": 0, "idx": 0}}, + {"id": 16, "label": "False", "type": null, "kind": "CTRL", "edges": [], "proj": {"par": 0, "idx": 1}}, + {"id": 17, "label": "Load p.y", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 15, "role": "CTRL", "label": null}, {"idx": 1, "def": 11, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 0, "role": "DATA", "label": null}], "proj": null}, + {"id": 18, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 17, "role": "DATA", "label": null}, {"idx": 2, "def": 12, "role": "DATA", "label": null}], "proj": null}, + {"id": 19, "label": "Store p.y", "type": "MEM#3", "kind": "MEM", "edges": [{"idx": 0, "def": 15, "role": "CTRL", "label": null}, {"idx": 1, "def": 11, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 18, "role": "DATA", "label": null}], "proj": null}, + {"id": 20, "label": "#1", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 21, "label": "-", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 12, "role": "DATA", "label": null}, {"idx": 2, "def": 20, "role": "DATA", "label": null}], "proj": null}, + {"id": 22, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 8, "role": "MEM", "label": null}, {"idx": 3, "def": 11, "role": "MEM", "label": null}], "proj": null}, + {"id": 23, "label": "Load p.x", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 16, "role": "CTRL", "label": null}, {"idx": 1, "def": 8, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 0, "role": "DATA", "label": null}], "proj": null}, + {"id": 24, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 22, "role": "MEM", "label": null}, {"idx": 2, "def": 23, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter10b/docs/example1.svg b/chapter10b/docs/example1.svg index f0b57612..46faf818 100644 --- a/chapter10b/docs/example1.svg +++ b/chapter10b/docs/example1.svg @@ -1,93 +1,155 @@ - - - - - - -Memory - - - -M - -Initial memory - - - -X - -Store x = 42 - - - -X->M - - - - - -Y - -Loop: Store y - - - -Y->M - - - - - - -L - -Load x (42) - - - -L->X - - - - - -MemMerge - -MemMerge - - - -MemMerge->X - - - - - -MemMerge->Y - - - - - - -Return - -Return - - - -Return->L - - - - - -Return->MemMerge - - - - - +#6[0] → #1 · ASSOC#7[0] → #1 · ASSOC#8[1] → #3 · MEM#8[2] → #5 · DATA#8[3] → #7 · DATA#9[1] → #3 · MEM#9[2] → #5 · DATA#9[3] → #6 · DATA#11[1] → #9 · MEM#11[2] → #19 · MEM#12[1] → #4 · DATA#12[2] → #21 · DATA#17[0] → #15 · CTRL#17[1] → #11 · MEM#17[2] → #5 · DATA#18[1] → #17 · DATA#18[2] → #12 · DATA#19[0] → #15 · CTRL#19[1] → #11 · MEM#19[2] → #5 · DATA#19[3] → #18 · DATA#20[0] → #1 · ASSOC#21[1] → #12 · DATA#21[2] → #20 · DATA#22[1] → #3 · MEM#22[2] → #8 · MEM#22[3] → #11 · MEM#23[0] → #16 · CTRL#23[1] → #8 · MEM#23[2] → #5 · DATA#24[1] → #22 · MEM#24[2] → #23 · DATAStart  #1#1 Start +Type not computed + +$mem  #3/1#3 $mem +Projection 1 of #1 +Type not computed + +[0] → #1 MEMarg  #4/2#4 arg +Projection 2 of #1 +Type not computed + +[0] → #1 DATAnew Point  #5#5 new Point +Type not computed + +[0] → — CTRL0#0  #6#6 #0 +Type not computed + +[0] → #1 ASSOC0#42  #7#7 #42 +Type not computed + +[0] → #1 ASSOC0Store p.x  #8MEM#2#8 Store p.x +MEM#2 + +[0] → — CTRL +[1] → #3 MEM +[2] → #5 DATA +[3] → #7 DATA0123Store p.y  #9MEM#3#9 Store p.y +MEM#3 + +[0] → — CTRL +[1] → #3 MEM +[2] → #5 DATA +[3] → #6 DATA0123MemPhi y  #11MEM#3#11 MemPhi y +MEM#3 + +[0] → — ASSOC +[1] → #9 MEM +[2] → #19 MEM012Phi arg  #12#12 Phi arg +Type not computed + +[0] → — ASSOC +[1] → #4 DATA +[2] → #21 DATA012True  #15/0#15 True +Projection 0 of #0 +Type not computed + +False  #16/1#16 False +Projection 1 of #0 +Type not computed + +Load p.y  #17#17 Load p.y +Type not computed + +[0] → #15 CTRL +[1] → #11 MEM +[2] → #5 DATA +[3] → — DATA0123+  #18#18 + +Type not computed + +[0] → — CTRL +[1] → #17 DATA +[2] → #12 DATA012Store p.y  #19MEM#3#19 Store p.y +MEM#3 + +[0] → #15 CTRL +[1] → #11 MEM +[2] → #5 DATA +[3] → #18 DATA0123#1  #20#20 #1 +Type not computed + +[0] → #1 ASSOC0-  #21#21 - +Type not computed + +[0] → — CTRL +[1] → #12 DATA +[2] → #20 DATA012MemMerge  #22#22 MemMerge +Type not computed + +[0] → — CTRL +[1] → #3 MEM +[2] → #8 MEM +[3] → #11 MEM0123Load p.x  #23#23 Load p.x +Type not computed + +[0] → #16 CTRL +[1] → #8 MEM +[2] → #5 DATA +[3] → — DATA0123Return  #24#24 Return +Type not computed + +[0] → — CTRL +[1] → #22 MEM +[2] → #23 DATA012 diff --git a/chapter10b/docs/example2a.json b/chapter10b/docs/example2a.json new file mode 100644 index 00000000..2a9461b6 --- /dev/null +++ b/chapter10b/docs/example2a.json @@ -0,0 +1,20 @@ +{ + "ver": 1, + "comp": "chapter10b/docs/example2a.svg", + "step": 1, + "roots": [11], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 1, "role": "MEM", "label": null}], "proj": {"par": 1, "idx": 1}}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "DATA", "label": null}], "proj": {"par": 1, "idx": 2}}, + {"id": 5, "label": "new Point", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}], "proj": null}, + {"id": 7, "label": "Store p.x", "type": "MEM#2", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 8, "label": "#42", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 9, "label": "Store p.y", "type": "MEM#3", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 8, "role": "DATA", "label": null}], "proj": null}, + {"id": 10, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 7, "role": "MEM", "label": null}, {"idx": 3, "def": 9, "role": "MEM", "label": null}], "proj": null}, + {"id": 11, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 10, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter10b/docs/example2a.svg b/chapter10b/docs/example2a.svg index 47bc3a8f..b43a55b4 100644 --- a/chapter10b/docs/example2a.svg +++ b/chapter10b/docs/example2a.svg @@ -1,82 +1,103 @@ - - - - - - -Memory - - - -M - -Default memory - - - -X - -Store x - - - -X->M - - - - - -Y - -Store y - - - -Y->M - - - - - -MemMerge - -MemMerge - - - -MemMerge->M - - -default - - - -MemMerge->X - - -x - - - -MemMerge->Y - - -y - - - -Return - -Return - - - -Return->MemMerge - - - - - +#7[1] → #3 · MEM#7[2] → #5 · DATA#7[3] → #4 · DATA#8[0] → #1 · ASSOC#9[1] → #3 · MEM#9[2] → #5 · DATA#9[3] → #8 · DATA#10[1] → #3 · MEM#10[2] → #7 · MEM#10[3] → #9 · MEM#11[1] → #10 · MEM#11[2] → #5 · DATAStart  #1#1 Start +Type not computed + +$mem  #3/1#3 $mem +Projection 1 of #1 +Type not computed + +[0] → #1 MEMarg  #4/2#4 arg +Projection 2 of #1 +Type not computed + +[0] → #1 DATAnew Point  #5#5 new Point +Type not computed + +[0] → — CTRL0Store p.x  #7MEM#2#7 Store p.x +MEM#2 + +[0] → — CTRL +[1] → #3 MEM +[2] → #5 DATA +[3] → #4 DATA0123#42  #8#8 #42 +Type not computed + +[0] → #1 ASSOC0Store p.y  #9MEM#3#9 Store p.y +MEM#3 + +[0] → — CTRL +[1] → #3 MEM +[2] → #5 DATA +[3] → #8 DATA0123MemMerge  #10#10 MemMerge +Type not computed + +[0] → — CTRL +[1] → #3 MEM +[2] → #7 MEM +[3] → #9 MEM0123Return  #11#11 Return +Type not computed + +[0] → — CTRL +[1] → #10 MEM +[2] → #5 DATA012 diff --git a/chapter10b/docs/example2b.json b/chapter10b/docs/example2b.json new file mode 100644 index 00000000..3d919618 --- /dev/null +++ b/chapter10b/docs/example2b.json @@ -0,0 +1,30 @@ +{ + "ver": 1, + "comp": "chapter10b/docs/example2b.svg", + "step": 1, + "roots": [23], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 1, "role": "MEM", "label": null}], "proj": {"par": 1, "idx": 1}}, + {"id": 5, "label": "new Point", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}], "proj": null}, + {"id": 6, "label": "#0", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 7, "label": "Store p.x", "type": "MEM#2", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 6, "role": "DATA", "label": null}], "proj": null}, + {"id": 8, "label": "Store p.y", "type": "MEM#3", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 6, "role": "DATA", "label": null}], "proj": null}, + {"id": 9, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 7, "role": "MEM", "label": null}, {"idx": 3, "def": 8, "role": "MEM", "label": null}], "proj": null}, + {"id": 11, "label": "True", "type": null, "kind": "CTRL", "edges": [], "proj": {"par": 0, "idx": 0}}, + {"id": 12, "label": "False", "type": null, "kind": "CTRL", "edges": [], "proj": {"par": 0, "idx": 1}}, + {"id": 13, "label": "#3", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 14, "label": "Store p.x", "type": "MEM#2", "kind": "MEM", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}, {"idx": 1, "def": 7, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 13, "role": "DATA", "label": null}], "proj": null}, + {"id": 15, "label": "#4", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 16, "label": "Store p.x", "type": "MEM#2", "kind": "MEM", "edges": [{"idx": 0, "def": 12, "role": "CTRL", "label": null}, {"idx": 1, "def": 7, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 15, "role": "DATA", "label": null}], "proj": null}, + {"id": 17, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 9, "role": "MEM", "label": null}, {"idx": 2, "def": 14, "role": "MEM", "label": null}], "proj": null}, + {"id": 18, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 9, "role": "MEM", "label": null}, {"idx": 2, "def": 16, "role": "MEM", "label": null}], "proj": null}, + {"id": 20, "label": "MemPhi x", "type": "MEM#2", "kind": "PHI", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": null}, {"idx": 1, "def": 14, "role": "MEM", "label": null}, {"idx": 2, "def": 16, "role": "MEM", "label": null}], "proj": null}, + {"id": 21, "label": "BulkMemPhi except x", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": null}, {"idx": 1, "def": 17, "role": "MEM", "label": null}, {"idx": 2, "def": 18, "role": "MEM", "label": null}], "proj": null}, + {"id": 22, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 21, "role": "MEM", "label": null}, {"idx": 2, "def": 20, "role": "MEM", "label": null}], "proj": null}, + {"id": 23, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 22, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter10b/docs/example2b.svg b/chapter10b/docs/example2b.svg index cb10b90b..54ddad9d 100644 --- a/chapter10b/docs/example2b.svg +++ b/chapter10b/docs/example2b.svg @@ -1,101 +1,150 @@ - - - - - - -Memory - - - -P - -MemPhi(x) - - - -Left - -Left - - - -P->Left - - -slice x - - - -Right - -Right - - - -P->Right - - -slice x - - - -Region - -Region - - - -P->Region - - - - - -B - -BulkMemPhi(All except x) - - - -B->Left - - - - - -B->Right - - - - - -B->Region - - - - - -MemMerge - -MemMerge - - - -MemMerge->P - - -x - - - -MemMerge->B - - -default - - - +#6[0] → #1 · ASSOC#7[1] → #3 · MEM#7[2] → #5 · DATA#7[3] → #6 · DATA#8[1] → #3 · MEM#8[2] → #5 · DATA#8[3] → #6 · DATA#9[1] → #3 · MEM#9[2] → #7 · MEM#9[3] → #8 · MEM#13[0] → #1 · ASSOC#14[0] → #11 · CTRL#14[1] → #7 · MEM#14[2] → #5 · DATA#14[3] → #13 · DATA#15[0] → #1 · ASSOC#16[0] → #12 · CTRL#16[1] → #7 · MEM#16[2] → #5 · DATA#16[3] → #15 · DATA#17[1] → #9 · MEM#17[2] → #14 · MEM#18[1] → #9 · MEM#18[2] → #16 · MEM#20[1] → #14 · MEM#20[2] → #16 · MEM#21[1] → #17 · MEM#21[2] → #18 · MEM#22[1] → #21 · MEM#22[2] → #20 · MEM#23[1] → #22 · MEM#23[2] → #5 · DATAStart  #1#1 Start +Type not computed + +$mem  #3/1#3 $mem +Projection 1 of #1 +Type not computed + +[0] → #1 MEMnew Point  #5#5 new Point +Type not computed + +[0] → — CTRL0#0  #6#6 #0 +Type not computed + +[0] → #1 ASSOC0Store p.x  #7MEM#2#7 Store p.x +MEM#2 + +[0] → — CTRL +[1] → #3 MEM +[2] → #5 DATA +[3] → #6 DATA0123Store p.y  #8MEM#3#8 Store p.y +MEM#3 + +[0] → — CTRL +[1] → #3 MEM +[2] → #5 DATA +[3] → #6 DATA0123MemMerge  #9#9 MemMerge +Type not computed + +[0] → — CTRL +[1] → #3 MEM +[2] → #7 MEM +[3] → #8 MEM0123True  #11/0#11 True +Projection 0 of #0 +Type not computed + +False  #12/1#12 False +Projection 1 of #0 +Type not computed + +#3  #13#13 #3 +Type not computed + +[0] → #1 ASSOC0Store p.x  #14MEM#2#14 Store p.x +MEM#2 + +[0] → #11 CTRL +[1] → #7 MEM +[2] → #5 DATA +[3] → #13 DATA0123#4  #15#15 #4 +Type not computed + +[0] → #1 ASSOC0Store p.x  #16MEM#2#16 Store p.x +MEM#2 + +[0] → #12 CTRL +[1] → #7 MEM +[2] → #5 DATA +[3] → #15 DATA0123MemMerge  #17#17 MemMerge +Type not computed + +[0] → — CTRL +[1] → #9 MEM +[2] → #14 MEM012MemMerge  #18#18 MemMerge +Type not computed + +[0] → — CTRL +[1] → #9 MEM +[2] → #16 MEM012MemPhi x  #20MEM#2#20 MemPhi x +MEM#2 + +[0] → — ASSOC +[1] → #14 MEM +[2] → #16 MEM012BulkMemPhi except x  #21#21 BulkMemPhi except x +Type not computed + +[0] → — ASSOC +[1] → #17 MEM +[2] → #18 MEM012MemMerge  #22#22 MemMerge +Type not computed + +[0] → — CTRL +[1] → #21 MEM +[2] → #20 MEM012Return  #23#23 Return +Type not computed + +[0] → — CTRL +[1] → #22 MEM +[2] → #5 DATA012 diff --git a/chapter10b/docs/example2c.json b/chapter10b/docs/example2c.json new file mode 100644 index 00000000..380815a2 --- /dev/null +++ b/chapter10b/docs/example2c.json @@ -0,0 +1,23 @@ +{ + "ver": 1, + "comp": "chapter10b/docs/example2c.svg", + "step": 1, + "roots": [13], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 1, "role": "MEM", "label": null}], "proj": {"par": 1, "idx": 1}}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "DATA", "label": null}], "proj": {"par": 1, "idx": 2}}, + {"id": 5, "label": "new Point", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}], "proj": null}, + {"id": 6, "label": "#0", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 7, "label": "Store p.x", "type": "MEM#2", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 6, "role": "DATA", "label": null}], "proj": null}, + {"id": 8, "label": "Store p.y", "type": "MEM#3", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 6, "role": "DATA", "label": null}], "proj": null}, + {"id": 9, "label": "Load p.x", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 7, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 0, "role": "DATA", "label": null}], "proj": null}, + {"id": 10, "label": "Store p.x", "type": "MEM#2", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 7, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 11, "label": "Store p.y", "type": "MEM#3", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 8, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 12, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 10, "role": "MEM", "label": null}, {"idx": 3, "def": 11, "role": "MEM", "label": null}], "proj": null}, + {"id": 13, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 12, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter10b/docs/example2c.svg b/chapter10b/docs/example2c.svg index 531fabfe..01bbe10a 100644 --- a/chapter10b/docs/example2c.svg +++ b/chapter10b/docs/example2c.svg @@ -1,56 +1,121 @@ - - - - - - -Memory - - - -M - -Prior x memory - - - -L - -Load p.x - - - -L->M - - - - - -S - -Store p.x - - - -S->M - - - - - -S->L - - -execute load first - - - -Y - -Store p.y: independent - - - +#6[0] → #1 · ASSOC#7[1] → #3 · MEM#7[2] → #5 · DATA#7[3] → #6 · DATA#8[1] → #3 · MEM#8[2] → #5 · DATA#8[3] → #6 · DATA#9[1] → #7 · MEM#9[2] → #5 · DATA#10[1] → #7 · MEM#10[2] → #5 · DATA#10[3] → #4 · DATA#11[1] → #8 · MEM#11[2] → #5 · DATA#11[3] → #4 · DATA#12[1] → #3 · MEM#12[2] → #10 · MEM#12[3] → #11 · MEM#13[1] → #12 · MEM#13[2] → #9 · DATAStart  #1#1 Start +Type not computed + +$mem  #3/1#3 $mem +Projection 1 of #1 +Type not computed + +[0] → #1 MEMarg  #4/2#4 arg +Projection 2 of #1 +Type not computed + +[0] → #1 DATAnew Point  #5#5 new Point +Type not computed + +[0] → — CTRL0#0  #6#6 #0 +Type not computed + +[0] → #1 ASSOC0Store p.x  #7MEM#2#7 Store p.x +MEM#2 + +[0] → — CTRL +[1] → #3 MEM +[2] → #5 DATA +[3] → #6 DATA0123Store p.y  #8MEM#3#8 Store p.y +MEM#3 + +[0] → — CTRL +[1] → #3 MEM +[2] → #5 DATA +[3] → #6 DATA0123Load p.x  #9#9 Load p.x +Type not computed + +[0] → — CTRL +[1] → #7 MEM +[2] → #5 DATA +[3] → — DATA0123Store p.x  #10MEM#2#10 Store p.x +MEM#2 + +[0] → — CTRL +[1] → #7 MEM +[2] → #5 DATA +[3] → #4 DATA0123Store p.y  #11MEM#3#11 Store p.y +MEM#3 + +[0] → — CTRL +[1] → #8 MEM +[2] → #5 DATA +[3] → #4 DATA0123MemMerge  #12#12 MemMerge +Type not computed + +[0] → — CTRL +[1] → #3 MEM +[2] → #10 MEM +[3] → #11 MEM0123Return  #13#13 Return +Type not computed + +[0] → — CTRL +[1] → #12 MEM +[2] → #9 DATA012 diff --git a/chapter10b/docs/lattice.gv b/chapter10b/docs/lattice.gv index a37a1738..93d99dd8 100644 --- a/chapter10b/docs/lattice.gv +++ b/chapter10b/docs/lattice.gv @@ -97,9 +97,28 @@ digraph Lattice { node [fillcolor="#ffc0cb"]; TUPLE_TOP [label="⊤:tuple"]; TUPLE_BOT [label="⊥:tuple"]; - TUPLE1 [label="(type)", shape=box]; - TUPLE2 [label="(type, type)", shape=box]; - TUPLEN [label="(type, …)", shape=box]; + // Each black element stands for a recursively nested type lattice. + TUPLE1 [shape=plain, label=< + + + +
tuple
type
+ >]; + TUPLE2 [shape=plain, label=< + + + + +
tuple
type
type
+ >]; + TUPLEN [shape=plain, label=< + + + + + +
tuple
type
…
type
+ >]; {rank=same; TUPLE1; TUPLE2; TUPLEN;} TUPLE1 -> TUPLE2 -> TUPLEN [style=invis]; TUPLE_TOP -> {TUPLE1 TUPLE2 TUPLEN}; diff --git a/chapter10b/docs/lattice.svg b/chapter10b/docs/lattice.svg index ff554601..8d2e2875 100644 --- a/chapter10b/docs/lattice.svg +++ b/chapter10b/docs/lattice.svg @@ -4,123 +4,123 @@ - - + + Lattice - + cluster_control - -Control + +Control cluster_integer - -Integer + +Integer cluster_pointer - -Pointer = nullability × struct type + +Pointer = nullability × struct type cluster_struct - -Struct -named collection of named scalar types + +Struct +named collection of named scalar types cluster_memory - -Memory -precise alias slices + +Memory +precise alias slices cluster_tuple - -Tuple -collection of types + +Tuple +collection of types TOP - -⊤ + +⊤ XCTRL - -⊤:ctrl + +⊤:ctrl TOP->XCTRL - - + + INT_TOP - -⊤:int + +⊤:int TOP->INT_TOP - - + + PTR_TOP - -⊤:ptr -[*⊤:struct] + +⊤:ptr +[*⊤:struct] TOP->PTR_TOP - - + + STRUCT_TOP - -⊤:struct -[struct top] + +⊤:struct +[struct top] TOP->STRUCT_TOP - - + + MEM_TOP - -⊤:mem + +⊤:mem TOP->MEM_TOP - - + + TUPLE_TOP - -⊤:tuple + +⊤:tuple TOP->TUPLE_TOP - - + + @@ -137,7 +137,7 @@ XCTRL->CTRL - + @@ -150,38 +150,38 @@ INT_NEG - -… −2, −1 + +… −2, −1 INT_TOP->INT_NEG - - + + INT_ZERO - -0 + +0 INT_TOP->INT_ZERO - - + + INT_POS - -1, 2, … + +1, 2, … INT_TOP->INT_POS - - + + @@ -199,70 +199,70 @@ INT_NEG->INT_BOT - - + + INT_ZERO->INT_BOT - - + + INT_POS->INT_BOT - - + + PTR_NULL - -null + +null PTR_TOP->PTR_NULL - - + + PTR_PERSON - -*Person + +*Person PTR_TOP->PTR_PERSON - - + + PTR_S1 - -*s1 + +*s1 PTR_TOP->PTR_S1 - - + + PTR_MORE - -*s2, … + +*s2, … PTR_TOP->PTR_MORE - - + + @@ -287,8 +287,8 @@ PTR_NULL->PTR_PERSON_NIL - - + + @@ -299,8 +299,8 @@ PTR_NULL->PTR_S1_NIL - - + + @@ -311,8 +311,8 @@ PTR_NULL->PTR_MORE_NIL - - + + @@ -331,41 +331,41 @@ PTR_PERSON->PTR_ANY - - + + PTR_PERSON->PTR_PERSON_NIL - - + + PTR_S1->PTR_ANY - - + + PTR_S1->PTR_S1_NIL - - + + PTR_MORE->PTR_ANY - - + + PTR_MORE->PTR_MORE_NIL - - + + @@ -397,8 +397,8 @@ STRUCT_TOP->STRUCT_PERSON - - + + @@ -410,8 +410,8 @@ STRUCT_TOP->STRUCT_S1 - - + + @@ -423,8 +423,8 @@ STRUCT_TOP->STRUCT_S2 - - + + @@ -435,8 +435,8 @@ STRUCT_TOP->STRUCT_MORE - - + + @@ -488,8 +488,8 @@ MEM_TOP->MEM_ALIAS2 - - + + @@ -500,8 +500,8 @@ MEM_TOP->MEM_ALIAS3 - - + + @@ -512,8 +512,8 @@ MEM_TOP->MEM_MORE - - + + @@ -551,70 +551,94 @@ TUPLE1 - -(type) + + + +tuple + + +type TUPLE_TOP->TUPLE1 - - + + TUPLE2 - -(type, type) + + + +tuple + + +type + + +type TUPLE_TOP->TUPLE2 - - + + TUPLEN - -(type, …) + + + +tuple + + +type + + +… + + +type TUPLE_TOP->TUPLEN - - + + TUPLE_BOT - -⊥:tuple + +⊥:tuple TUPLE_BOT->BOT - - + + TUPLE1->TUPLE_BOT - - + + TUPLE2->TUPLE_BOT - - + + TUPLEN->TUPLE_BOT - - + + -- cgit v1.2.3