<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<title>i dunno what i am doing</title>
	<subtitle>Software engineering à la Mexicana</subtitle>
	<link rel="self" type="application/atom+xml" href="https://idunnowhatiamdoing.engineering/posts/feed.xml"/>
  <link rel="alternate" type="text/html" href="https://idunnowhatiamdoing.engineering/posts/"/>
  
	<updated>2026-07-24T00:00:00+00:00</updated>
	
	<id>https://idunnowhatiamdoing.engineering/posts/feed.xml</id>
	<entry xml:lang="en">
		<title>0x0 Shared Memory</title>
		<published>2026-07-24T00:00:00+00:00</published>
		<updated>2026-07-24T00:00:00+00:00</updated>
		<link rel="alternate" type="text/html" href="https://idunnowhatiamdoing.engineering/posts/0x0-shared-memory/"/>
		<id>https://idunnowhatiamdoing.engineering/posts/0x0-shared-memory/</id>
    
		<content type="html" xml:base="https://idunnowhatiamdoing.engineering/posts/0x0-shared-memory/">&lt;p&gt;In my last post about, I ended with a deliberately narrow release statement.&lt;&#x2F;p&gt;
&lt;p&gt;Then I wrote the caveats:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Cross-thread shared ownership is unsupported. Reference counting is
non-atomic. Shared graphs must be immutable and acyclic. There are no weak
references or cycle collector.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It was also an excellent list of things that would bother me until I either
implemented them or stopped pretending I wanted a multithreaded runtime.&lt;&#x2F;p&gt;
&lt;p&gt;So I kept going.&lt;&#x2F;p&gt;
&lt;p&gt;The Linux x86-64 direct-ELF profile now has registered native threads, checked
&lt;code&gt;Send&lt;&#x2F;code&gt; and &lt;code&gt;Share&lt;&#x2F;code&gt; transfer, atomic strong and weak ownership, synchronized
mutable graphs, weak references, bounded cycle collection, generated ownership
adapters for foreign calls, and direct-artifact instrumentation.&lt;&#x2F;p&gt;
&lt;p&gt;The release soak ran for 86,400 active seconds. It completed 139,255 batches,
peaked at 8,484 KiB of RSS, kept its longest collector pause below 1.7
milliseconds, ended with no candidate backlog, and returned every tracked
ownership and resource counter to its starting value.&lt;&#x2F;p&gt;
&lt;p&gt;The less pleasant lesson is that making a reference count atomic is not the
same thing as making a runtime thread-safe.&lt;&#x2F;p&gt;
&lt;p&gt;Not even remotely.&lt;&#x2F;p&gt;
&lt;p&gt;Imagine two threads own the same object.&lt;&#x2F;p&gt;
&lt;p&gt;An atomic increment can stop them from losing a retain. An atomic decrement
can decide which thread observed the final strong reference.&lt;&#x2F;p&gt;
&lt;p&gt;That still leaves several questions:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Was the object fully initialized before the second thread saw it?&lt;&#x2F;li&gt;
&lt;li&gt;Is the payload immutable?&lt;&#x2F;li&gt;
&lt;li&gt;If it is mutable, which operation serializes access?&lt;&#x2F;li&gt;
&lt;li&gt;Where is the object recorded while a collector stops the world?&lt;&#x2F;li&gt;
&lt;li&gt;What happens if a worker panics or is cancelled?&lt;&#x2F;li&gt;
&lt;li&gt;Can a weak reference become strong while the final release is running?&lt;&#x2F;li&gt;
&lt;li&gt;Who destroys a foreign resource, and on which thread?&lt;&#x2F;li&gt;
&lt;li&gt;What happens when two objects keep each other alive?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;An atomic counter answers one question:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Who won this counter transition?&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;A managed runtime needs to answer the rest of the protocol.&lt;&#x2F;p&gt;
&lt;p&gt;That changed how I thought about this work. The goal was not &quot;add threads.&quot;
The goal was to define every transition that becomes ambiguous when another
thread can observe it.&lt;&#x2F;p&gt;
&lt;p&gt;The design ended up in three decisions:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;ADR-0196 defines the managed object ABI-v2;&lt;&#x2F;li&gt;
&lt;li&gt;ADR-0197 defines the native thread memory model;&lt;&#x2F;li&gt;
&lt;li&gt;ADR-0198 defines cycle collection and finalization.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The decisions matter because these three subjects cannot safely be designed
independently. Object layout determines what a weak handle can preserve.
Thread publication determines what the collector can see. Finalization
determines what foreign code is allowed to resurrect.&lt;&#x2F;p&gt;
&lt;p&gt;The previous Linux-v1 memory profile was intentionally small.&lt;&#x2F;p&gt;
&lt;p&gt;One owner slot represented one complete allocation arena. Shared ownership used
one non-atomic strong count for the whole immutable, acyclic graph. It worked
for the five released value families and made region-style cleanup cheap.&lt;&#x2F;p&gt;
&lt;p&gt;It could not represent independently shared nodes.&lt;&#x2F;p&gt;
&lt;p&gt;It also could not represent a weak handle whose bookkeeping survives after the
payload dies. Reusing the old slot would have made v1 and v2 handles
ambiguously valid, which is exactly the kind of compatibility shortcut that
becomes a debugging hobby later.&lt;&#x2F;p&gt;
&lt;p&gt;ABI-v2 therefore uses a separate handle domain. A v2 handle sets its high bit
and points to a generation-checked, 128-byte control block.&lt;&#x2F;p&gt;
&lt;p&gt;The control records:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;lifecycle state;&lt;&#x2F;li&gt;
&lt;li&gt;generation;&lt;&#x2F;li&gt;
&lt;li&gt;descriptor identity;&lt;&#x2F;li&gt;
&lt;li&gt;payload address and size;&lt;&#x2F;li&gt;
&lt;li&gt;atomic strong and weak counts;&lt;&#x2F;li&gt;
&lt;li&gt;strong and weak edge storage;&lt;&#x2F;li&gt;
&lt;li&gt;resource state;&lt;&#x2F;li&gt;
&lt;li&gt;pin count;&lt;&#x2F;li&gt;
&lt;li&gt;collector trial state.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The payload is stable and non-moving. It can die before the control block,
which is what makes a weak reference possible.&lt;&#x2F;p&gt;
&lt;p&gt;The lifecycle is explicit:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;allocating&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;live&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;destroying&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;payload-dead&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;control-dead&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Publication moves an object from &lt;code&gt;allocating&lt;&#x2F;code&gt; to &lt;code&gt;live&lt;&#x2F;code&gt; only after its
descriptor and initialized children validate. The thread that wins strong zero
destroys the payload exactly once and releases its implicit weak reference.
The thread that later wins weak zero recycles the control exactly once.&lt;&#x2F;p&gt;
&lt;p&gt;Stale generations, mixed v1&#x2F;v2 handles, invalid descriptors, counter
overflow, double release, and partial construction all fail closed.&lt;&#x2F;p&gt;
&lt;p&gt;This is a larger object header than v1. It is supposed to be. Unique values and
regions do not pay for it unless they are promoted into managed shared
ownership.&lt;&#x2F;p&gt;
&lt;p&gt;Runtime bookkeeping cannot repair ownership that the compiler never
understood.&lt;&#x2F;p&gt;
&lt;p&gt;The old direct backend had late cleanup logic that inferred lifetimes from
source names. That was enough for a narrow single-threaded profile. It was not
enough for control-flow joins, moved values, closure captures, thread roots, or
collector safepoints.&lt;&#x2F;p&gt;
&lt;p&gt;Bindings now carry typed ownership records before native layout:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;ownership class;&lt;&#x2F;li&gt;
&lt;li&gt;current disposition;&lt;&#x2F;li&gt;
&lt;li&gt;cleanup operation;&lt;&#x2F;li&gt;
&lt;li&gt;conservative &lt;code&gt;Send&lt;&#x2F;code&gt; property;&lt;&#x2F;li&gt;
&lt;li&gt;conservative &lt;code&gt;Share&lt;&#x2F;code&gt; property.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The syntax can expose that contract where needed:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(ƒ mutable-map-worker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (∷ (→ I64 I64))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (cap pure)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (param-own node borrowed managed-v2 send share)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (node)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ...)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A control-flow join preserves a value only when its incoming states agree. If
one branch released a value and another kept it, later use fails closed instead
of guessing.&lt;&#x2F;p&gt;
&lt;p&gt;Interprocedural summaries carry owned returns through helpers. Cleanup is
inserted in typed IR. The old source-name lifetime walkers are gone.&lt;&#x2F;p&gt;
&lt;p&gt;Every direct ELF artifact also contains a versioned root-map record. User calls
have compiler-emitted safepoints. When the collector requests a stop, a
registered thread acknowledges the current generation and waits on a futex
until the world resumes.&lt;&#x2F;p&gt;
&lt;p&gt;That is a lot of machinery for a small language.&lt;&#x2F;p&gt;
&lt;p&gt;It is also the minimum shape of an answer to:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Where are the live managed values right now?&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The runtime uses registered Linux &lt;code&gt;clone&lt;&#x2F;code&gt; threads with guarded stacks,
generation-checked handles, thread-local controls, and typed join outcomes.&lt;&#x2F;p&gt;
&lt;p&gt;A thread attaches before it can hold managed roots. It detaches only after
roots, resources, pins, callbacks, and local caches have closed.&lt;&#x2F;p&gt;
&lt;p&gt;Sharing and moving are different operations.&lt;&#x2F;p&gt;
&lt;p&gt;A shared argument is retained before publication. A unique &lt;code&gt;Send&lt;&#x2F;code&gt; value moves
its existing owner into the worker:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(≔ ((resource (managed-v2-resource-open &amp;quot;README.md&amp;quot;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (thread&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      (managed-thread-spawn-move &amp;quot;unique-handoff-worker&amp;quot; resource))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (value&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      (managed-thread-outcome-value-or&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        (managed-thread-join-outcome thread)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        0)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  value)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The source object cannot remain secretly usable after the move. Borrowed stack
values, unsafe captures, non-&lt;code&gt;Send&lt;&#x2F;code&gt; fields, and foreign callback state are
rejected with a path explaining which part blocked transfer.&lt;&#x2F;p&gt;
&lt;p&gt;Normal return, panic, cancellation, failed spawn, and join all converge on the
same cleanup obligations. Worker cleanup closes the published root before the
kernel clears the join futex.&lt;&#x2F;p&gt;
&lt;p&gt;The atomic workload is deliberately boring:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(≔ ((cell (managed-atomic-i64-new 0))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (one (managed-thread-spawn &amp;quot;atomic-ring-worker&amp;quot; cell))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (two (managed-thread-spawn &amp;quot;atomic-ring-worker&amp;quot; cell))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (three (managed-thread-spawn &amp;quot;atomic-ring-worker&amp;quot; cell))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (four (managed-thread-spawn &amp;quot;atomic-ring-worker&amp;quot; cell)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (managed-thread-join one)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (managed-thread-join two)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (managed-thread-join three)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (managed-thread-join four)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (managed-atomic-i64-load cell (atomic-order-acquire Unit))))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Each worker performs 1,024 increments. The useful part is not the final number.
The useful part is that publication, atomic operations, joins, root closure,
and terminal counters all agree about how the number got there.&lt;&#x2F;p&gt;
&lt;p&gt;The compiler provides checked atomic load, store, exchange,
compare-exchange, fetch-add, fetch-sub, and fence operations. The x86-64 path
uses locked read-modify-write instructions and explicit fences. An independent
assembly oracle checks the emitted instruction behavior.&lt;&#x2F;p&gt;
&lt;p&gt;But atomic reference counting protects lifetime only.&lt;&#x2F;p&gt;
&lt;p&gt;It does not make an arbitrary payload safe to mutate.&lt;&#x2F;p&gt;
&lt;p&gt;Safe shared mutation goes through synchronization-aware cells or collections.
There is no plain mutable escape hatch that becomes safe because the owner
count happens to be atomic.&lt;&#x2F;p&gt;
&lt;p&gt;Replacing a shared edge follows a specific order:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;retain the replacement;&lt;&#x2F;li&gt;
&lt;li&gt;acquire the runtime lock;&lt;&#x2F;li&gt;
&lt;li&gt;publish the new edge;&lt;&#x2F;li&gt;
&lt;li&gt;record the possible cycle candidate;&lt;&#x2F;li&gt;
&lt;li&gt;release the lock;&lt;&#x2F;li&gt;
&lt;li&gt;transfer or release the old edge.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Readers clone the published owner while synchronized. Writers cannot expose a
half-updated graph.&lt;&#x2F;p&gt;
&lt;p&gt;The mutable-map workload runs four workers, each performing 1,024 edge
replacements. It records synchronization operations and contention, then
requires all roots and pending cycle candidates to close.&lt;&#x2F;p&gt;
&lt;p&gt;Unsynchronized shared cells are compile-time failures.&lt;&#x2F;p&gt;
&lt;p&gt;I like this rule because it separates two ideas that are often collapsed:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;an object can remain alive across threads;&lt;&#x2F;li&gt;
&lt;li&gt;an object can be mutated safely across threads.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The first needs atomic ownership. The second needs a synchronization protocol.&lt;&#x2F;p&gt;
&lt;p&gt;A weak reference owns a generation-checked control, not the payload.&lt;&#x2F;p&gt;
&lt;p&gt;It cannot read the payload directly. It must upgrade:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(≔ ((strong (managed-v2-new 73 (managed-descriptor-i64 Unit)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (weak (managed-v2-weak-new strong))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (upgrade (managed-v2-weak-upgrade weak)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (if (managed-v2-weak-upgrade-present? upgrade)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (managed-v2-weak-upgrade-read upgrade)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    0))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Upgrade uses compare-and-exchange from a positive strong count. It linearizes
either before final release or after strong zero. It cannot resurrect a dead
payload.&lt;&#x2F;p&gt;
&lt;p&gt;The race gate runs one, two, four, and eight worker lanes with different
release delays. Every attempt must become either a successful or failed
upgrade. Payload destruction must happen once. Payload, control, weak-owner,
thread, and root counters must close.&lt;&#x2F;p&gt;
&lt;p&gt;The negative cases matter as much as the successful one:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;stale generation;&lt;&#x2F;li&gt;
&lt;li&gt;double weak drop;&lt;&#x2F;li&gt;
&lt;li&gt;weak counter overflow;&lt;&#x2F;li&gt;
&lt;li&gt;direct payload read;&lt;&#x2F;li&gt;
&lt;li&gt;upgrade after death;&lt;&#x2F;li&gt;
&lt;li&gt;an intentional hidden weak-count leak.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;There are no weak-death callbacks in this release. Observation has a smaller,
more predictable contract: upgrade succeeds or it does not.&lt;&#x2F;p&gt;
&lt;p&gt;Two objects can each have a positive strong count while nothing outside their
component can reach them.&lt;&#x2F;p&gt;
&lt;p&gt;Reference counting sees two live objects.&lt;&#x2F;p&gt;
&lt;p&gt;The program sees garbage.&lt;&#x2F;p&gt;
&lt;p&gt;The first 0x0 cycle collector uses bounded stop-the-world trial deletion.
Synchronized edge updates record candidates through descriptor-aware write
barriers. A collection starts only after every registered managed thread has
acknowledged the current safepoint generation.&lt;&#x2F;p&gt;
&lt;p&gt;For a candidate component, the collector copies strong counts into trial
counts and subtracts internal edges without modifying the real counts. A
component whose trial counts reach zero and which has no registered root is
disconnected and can be reclaimed.&lt;&#x2F;p&gt;
&lt;p&gt;Weak edges do not contribute to reachability.&lt;&#x2F;p&gt;
&lt;p&gt;The workload makes the problem explicit:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(≔ ((first (managed-graph-node-new value))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (second (managed-graph-node-new (+ value 1))))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (managed-graph-edge-store first second)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (managed-graph-edge-store second first)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (managed-v2-release first)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (managed-v2-release second)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (managed-cycle-collect 64)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The collector is bounded by candidate work, object work, and pause time.
Exhausting a bound defers an intact component. A failed handshake,
bookkeeping allocation, cancellation, or shutdown drain resumes stopped
threads and leaves the real graph valid.&lt;&#x2F;p&gt;
&lt;p&gt;Runtime-owned resource destruction is deterministic and exactly once.
User-visible finalizer resurrection is rejected.&lt;&#x2F;p&gt;
&lt;p&gt;This is not a moving collector. It is not a concurrent collector. It is a
small, bounded policy for the graph semantics 0x0 currently publishes.&lt;&#x2F;p&gt;
&lt;p&gt;The earlier native memory release had direct evidence for five families:
&lt;code&gt;Unit&lt;&#x2F;code&gt;, &lt;code&gt;Bool&lt;&#x2F;code&gt;, &lt;code&gt;I64&lt;&#x2F;code&gt;, &lt;code&gt;Text&lt;&#x2F;code&gt;, and &lt;code&gt;List&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The managed release no longer promotes a few hand-picked composite types.
One versioned ABI schema generates descriptor identities, runtime
constructors, compiler validation, and common lifetime tests for every managed
direct value family in the support matrix.&lt;&#x2F;p&gt;
&lt;p&gt;That includes sums, errors, maps, bytes, paths, linear handles, protocols,
actors, runtime state, process and socket handles, closures, host buffers, and
hardware evidence.&lt;&#x2F;p&gt;
&lt;p&gt;The generated matrix is only the common floor. Family-specific tests still
exercise:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;map mutation and contention;&lt;&#x2F;li&gt;
&lt;li&gt;exactly-once resource close;&lt;&#x2F;li&gt;
&lt;li&gt;thread transfer;&lt;&#x2F;li&gt;
&lt;li&gt;weak observation;&lt;&#x2F;li&gt;
&lt;li&gt;cross-family cycles;&lt;&#x2F;li&gt;
&lt;li&gt;invalid descriptors;&lt;&#x2F;li&gt;
&lt;li&gt;omitted destructors;&lt;&#x2F;li&gt;
&lt;li&gt;forbidden sharing of linear resources.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A row is not promoted because a tagged-list model exists somewhere else in the
repository. It needs direct native positive, negative, leak, and stress
evidence.&lt;&#x2F;p&gt;
&lt;p&gt;The old release required hand-written ownership adapters at foreign
boundaries.&lt;&#x2F;p&gt;
&lt;p&gt;The new FFI schema makes ownership part of the declaration. The supported
modes are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;immediate;&lt;&#x2F;li&gt;
&lt;li&gt;borrowed for one call;&lt;&#x2F;li&gt;
&lt;li&gt;borrowed for a named scope;&lt;&#x2F;li&gt;
&lt;li&gt;transferred owned;&lt;&#x2F;li&gt;
&lt;li&gt;shared retained;&lt;&#x2F;li&gt;
&lt;li&gt;weak;&lt;&#x2F;li&gt;
&lt;li&gt;pinned buffer;&lt;&#x2F;li&gt;
&lt;li&gt;resource handle;&lt;&#x2F;li&gt;
&lt;li&gt;callback context.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Declarations also name the ABI, destructor, retain and release operations,
error convention, thread affinity, callback policy, and pin direction.&lt;&#x2F;p&gt;
&lt;p&gt;A generator turns the canonical table into 0x0 adapter source and metadata.
The runtime operations handle temporary borrows, longer scopes, transferred
values, retained sharing, weak observation, pins, resources, callback roots,
and collector-visible foreign roots.&lt;&#x2F;p&gt;
&lt;p&gt;Callbacks entering from a foreign thread attach it, publish temporary roots,
contain panic at the no-unwind boundary, close pins and roots, and detach after
terminal accounting.&lt;&#x2F;p&gt;
&lt;p&gt;Unknown ownership remains explicitly unsafe. It cannot quietly acquire safe
&lt;code&gt;Send&lt;&#x2F;code&gt;, &lt;code&gt;Share&lt;&#x2F;code&gt;, weak, or collector behavior.&lt;&#x2F;p&gt;
&lt;p&gt;There is a C fixture in the FFI gate. It is an independent SysV x86-64 oracle,
not a production implementation or bootstrap dependency. A self-hosted 0x0
object builder emits the 0x0 side of the C→0x0→C round trip so register,
relocation, callback, and ownership behavior can be checked from both sides of
the boundary.&lt;&#x2F;p&gt;
&lt;p&gt;The dangerous border became small, generated, and inspectable.&lt;&#x2F;p&gt;
&lt;p&gt;Raw direct ELF executables do not automatically become ASan or TSan programs.
They do not link Clang&#x27;s sanitizer runtime, and saying &quot;sanitizer-backed&quot;
without explaining the lanes would hide an important distinction.&lt;&#x2F;p&gt;
&lt;p&gt;The release uses several complementary profiles.&lt;&#x2F;p&gt;
&lt;p&gt;The exact production bytes run normally and under &lt;code&gt;qemu-x86_64 -strace&lt;&#x2F;code&gt;.
Their hash must remain identical. The external lane observes mappings,
unmappings, thread creation, futexes, syscalls, and signals without replacing
the artifact.&lt;&#x2F;p&gt;
&lt;p&gt;Separate compiler-instrumented direct ELF profiles check:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;managed use-after-free and bounds;&lt;&#x2F;li&gt;
&lt;li&gt;stack lifetime and global roots;&lt;&#x2F;li&gt;
&lt;li&gt;division, shifts, alignment, tags, and initialization;&lt;&#x2F;li&gt;
&lt;li&gt;logical objects, controls, weak owners, roots, candidates, threads,
resources, pins, callbacks, and foreign roots;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Send&lt;&#x2F;code&gt;, &lt;code&gt;Share&lt;&#x2F;code&gt;, atomic order, write barriers, safepoints, and
happens-before contracts.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Hosted ASan, UBSan, LSan, and TSan programs calibrate the negative detector
oracles. They are test-only artifacts, not the thing being shipped.&lt;&#x2F;p&gt;
&lt;p&gt;The positive instrumented and production programs must agree. The negative
matrix must detect stale handles, double release, bounds errors, incomplete
construction, division by zero, logical leaks, invalid atomic orders, missing
barriers, and stale collector roots.&lt;&#x2F;p&gt;
&lt;p&gt;This does not pretend the raw ELF is secretly a Clang-instrumented binary.&lt;&#x2F;p&gt;
&lt;p&gt;It gives each kind of evidence an honest name.&lt;&#x2F;p&gt;
&lt;p&gt;Fast loops catch obvious leaks and races. They do not prove that a bounded
runtime remains bounded after scheduler variation, repeated collection,
callbacks, cancellation, and allocator reuse.&lt;&#x2F;p&gt;
&lt;p&gt;The release soak is identity-bound to the compiler source, compiler artifact,
runtime, workloads, soak sources, and artifact manifest. Changing any of them
makes the evidence stale.&lt;&#x2F;p&gt;
&lt;p&gt;It is also restart-safe. Completed batches are durable; interrupted partial
batches do not count. A lock prevents two writers from claiming the same
state.&lt;&#x2F;p&gt;
&lt;p&gt;The accepted run reported:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Measurement&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Result&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Active duration&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;86,400 seconds&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Completed batches&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;139,255&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;First peak RSS&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;8,236 KiB&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Final peak RSS&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;8,444 KiB&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Maximum peak RSS&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;8,484 KiB&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Maximum collector pause&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1,697,507 ns&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Maximum candidate backlog&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;0&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Maximum synchronization operations&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;24,594&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Maximum contention events&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;7,069,550&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;The terminal counters matched their baselines:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;objects: &lt;code&gt;0 → 0&lt;&#x2F;code&gt;;&lt;&#x2F;li&gt;
&lt;li&gt;controls: &lt;code&gt;0 → 0&lt;&#x2F;code&gt;;&lt;&#x2F;li&gt;
&lt;li&gt;strong references: &lt;code&gt;0 → 0&lt;&#x2F;code&gt;;&lt;&#x2F;li&gt;
&lt;li&gt;weak references: &lt;code&gt;0 → 0&lt;&#x2F;code&gt;;&lt;&#x2F;li&gt;
&lt;li&gt;roots: &lt;code&gt;0 → 0&lt;&#x2F;code&gt;;&lt;&#x2F;li&gt;
&lt;li&gt;registered threads: &lt;code&gt;1 → 1&lt;&#x2F;code&gt;;&lt;&#x2F;li&gt;
&lt;li&gt;resources: &lt;code&gt;0 → 0&lt;&#x2F;code&gt;;&lt;&#x2F;li&gt;
&lt;li&gt;pins: &lt;code&gt;0 → 0&lt;&#x2F;code&gt;;&lt;&#x2F;li&gt;
&lt;li&gt;callbacks: &lt;code&gt;0 → 0&lt;&#x2F;code&gt;;&lt;&#x2F;li&gt;
&lt;li&gt;foreign roots: &lt;code&gt;0 → 0&lt;&#x2F;code&gt;;&lt;&#x2F;li&gt;
&lt;li&gt;mapped spans: &lt;code&gt;0 → 0&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The main managed thread remains registered, which is why the thread baseline
and final value are both one. The important property is no drift.&lt;&#x2F;p&gt;
&lt;p&gt;The collector&#x27;s largest observed pause was about 3.4% of its 50-millisecond
release ceiling.&lt;&#x2F;p&gt;
&lt;p&gt;After the run completed, the release decision could move from
&lt;code&gt;implemented-awaiting-evidence&lt;&#x2F;code&gt; to &lt;code&gt;pass&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;A runtime feature is not complete if adding it quietly breaks the language&#x27;s
bootstrap proof.&lt;&#x2F;p&gt;
&lt;p&gt;The final gate rebuilt three native compiler generations. All three produced
the same SHA-256 artifact:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;a0f77d7afb178b17eb516cf96c9010accee2136388e8f51fda180e660f4fe936&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Their measured peaks were 125,444 KiB, 125,496 KiB, and 125,264 KiB under a
256 MiB per-process ceiling.&lt;&#x2F;p&gt;
&lt;p&gt;The C-free assembly-seed recovery also remained below its independent 512 MiB
ceiling. The managed runtime did not turn C back into a hidden first-root
dependency.&lt;&#x2F;p&gt;
&lt;p&gt;The release gate joins the runtime evidence with compiler succession, seed
recovery, retained v1 regressions, documentation, and every Phase 0 through 8
ledger.&lt;&#x2F;p&gt;
&lt;p&gt;The source-owned version of a release policy checker initially exhausted itself
by recursively searching the entire compiler source. Fixing the runtime exposed
a checker that could not safely inspect the larger runtime.&lt;&#x2F;p&gt;
&lt;p&gt;The search was changed to bounded chunks. That then exposed previously masked
parenthesis errors in several policy checkers.&lt;&#x2F;p&gt;
&lt;p&gt;The proof machinery had to survive the same growth it was trying to prove.&lt;&#x2F;p&gt;
&lt;p&gt;At the end, the live state was still exactly where it started.&lt;&#x2F;p&gt;
&lt;p&gt;Shared memory is not a permission slip.&lt;&#x2F;p&gt;
&lt;p&gt;It is a protocol.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Glossary&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Managed object: a value whose independently tracked lifetime is represented by
an ABI-v2 control block and descriptor.&lt;&#x2F;p&gt;
&lt;p&gt;Strong reference: ownership that keeps a managed payload alive.&lt;&#x2F;p&gt;
&lt;p&gt;Weak reference: ownership that keeps the control block observable without
keeping the payload alive.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Send&lt;&#x2F;code&gt;: the property that permits ownership of a value to move across a thread
boundary.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Share&lt;&#x2F;code&gt;: the property that permits shared ownership of a value across threads.&lt;&#x2F;p&gt;
&lt;p&gt;Safepoint: a compiler-emitted location where a registered thread can
acknowledge a collector stop request.&lt;&#x2F;p&gt;
&lt;p&gt;Root map: metadata describing managed values that must remain reachable while
a function is active.&lt;&#x2F;p&gt;
&lt;p&gt;Trial deletion: a cycle-collection algorithm that subtracts internal edges
from temporary counts to find components with no outside owners.&lt;&#x2F;p&gt;
&lt;p&gt;Write barrier: runtime bookkeeping performed when a managed graph edge changes.&lt;&#x2F;p&gt;
&lt;p&gt;FFI: Foreign Function Interface, the contract used when 0x0 code and foreign
code call each other.&lt;&#x2F;p&gt;
&lt;p&gt;Linearizable: behaving as if a concurrent operation took effect at one
well-defined instant between its start and completion.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>0x0 Memory</title>
		<published>2026-07-19T00:00:00+00:00</published>
		<updated>2026-07-19T00:00:00+00:00</updated>
		<link rel="alternate" type="text/html" href="https://idunnowhatiamdoing.engineering/posts/0x0-memory/"/>
		<id>https://idunnowhatiamdoing.engineering/posts/0x0-memory/</id>
    
		<content type="html" xml:base="https://idunnowhatiamdoing.engineering/posts/0x0-memory/">&lt;p&gt;The new first-root recovery path could build both native &lt;code&gt;0x0&lt;&#x2F;code&gt;
compiler artifacts without generating C. The original monolithic seed command
had peaked at 12,667,784 KiB of RSS. Splitting planning from emission brought
the measured compiler builder down to 3,345,556 KiB.&lt;&#x2F;p&gt;
&lt;p&gt;That was a real improvement. It also meant a 714,488-byte executable still
needed more than three GiB of resident memory to recover itself.&lt;&#x2F;p&gt;
&lt;p&gt;The caveat was doing useful work. It was telling me that the bootstrap proof
was correct, but its memory model was not finished.&lt;&#x2F;p&gt;
&lt;p&gt;So I kept going.&lt;&#x2F;p&gt;
&lt;p&gt;The final C-free builder recovery now peaks at 344,860 KiB. The native compiler
succession runs between 70,232 and 77,984 KiB per generation. The accepted
native Linux memory soak ran for 86,400 seconds, completed one million configured
leak iterations and 577,424 soak batches, ended at 10,380 KiB peak RSS, and
returned every tracked live counter to zero.&lt;&#x2F;p&gt;
&lt;p&gt;The useful part is not only that the numbers are smaller.&lt;&#x2F;p&gt;
&lt;p&gt;The useful part is that &lt;code&gt;0x0&lt;&#x2F;code&gt; now has an answer to a more important question:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Which memory is allowed to live at this point in the program, and who is
responsible for ending its lifetime?&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;That question changed the seed, the compiler, the direct-ELF runtime, the test
strategy, and the release contract.&lt;&#x2F;p&gt;
&lt;p&gt;It is difficult to optimize memory when every number means something
different.&lt;&#x2F;p&gt;
&lt;p&gt;One tool reports the largest child process. Another reports the shell wrapper.
One workload includes parsing and emission. Another begins after a cached
compiler image already exists. An application has a small RSS because it never
releases anything, but also never runs long enough for that to matter.&lt;&#x2F;p&gt;
&lt;p&gt;Those results can all be numerically true and still describe different
systems.&lt;&#x2F;p&gt;
&lt;p&gt;The first phase of the work was making the measurements difficult to lie with.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;0x0&lt;&#x2F;code&gt; now freezes workload identities with source hashes, commands, input
rules, output assertions, owners, and budget classes. Memory telemetry uses a
versioned tab-separated envelope with run, identity, phase, metric, and terminal
records.&lt;&#x2F;p&gt;
&lt;p&gt;The validator rejects:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;unknown schema versions or metrics;&lt;&#x2F;li&gt;
&lt;li&gt;missing or duplicated phases;&lt;&#x2F;li&gt;
&lt;li&gt;non-increasing event sequences;&lt;&#x2F;li&gt;
&lt;li&gt;negative unsigned counters;&lt;&#x2F;li&gt;
&lt;li&gt;decreasing cumulative counters;&lt;&#x2F;li&gt;
&lt;li&gt;conflicting source or compiler identities;&lt;&#x2F;li&gt;
&lt;li&gt;missing terminal status.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The budgets are separate too:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;C-free seed recovery          512 MiB process-group RSS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;normal compiler succession    256 MiB per process&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;explicit heavy compiler lane    4 GiB process-group RSS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;native Linux applications      64 MiB RSS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;completed native owner scope     0 live-byte delta&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;completed resource scope         0 open-resource delta&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There is no combined score. A small application cannot hide a leaking
compiler. A passing compiler cannot hide a file descriptor leak. A bounded
seed cannot excuse an unbounded native request loop.&lt;&#x2F;p&gt;
&lt;p&gt;This sounds bureaucratic until a measurement improves suspiciously. Then a
source hash, phase identity, and independent budget are much cheaper than
guessing what changed.&lt;&#x2F;p&gt;
&lt;p&gt;The old seed recovery workers repeatedly loaded and normalized the compiler
source. More importantly, the runtime did not have a clean distinction between
the compiler state that had to survive and the scratch that could disappear.&lt;&#x2F;p&gt;
&lt;p&gt;The new path first constructs one immutable normalized compiler image.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;compiler&#x2F;main.0x0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;parse and normalize once&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0X0NIMG2 immutable image&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        +----&amp;gt; layout measurement worker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        +----&amp;gt; function emission worker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The image contains a version, a complete build identity, a module identity, a
canonical dense function-name table, and normalized function forms in the same
order. It deliberately excludes raw source, lexer scratch, parser stacks, and
output buffers.&lt;&#x2F;p&gt;
&lt;p&gt;Its identity includes the source hash, compiler-image hash, target, ABI, and
representation version. Reusing an image after any of those change is an
error, not a cache hit.&lt;&#x2F;p&gt;
&lt;p&gt;The binary format is deterministic and pointer-free. It uses little-endian
integers, a bounded string table, explicit tags, recursive pairs, and dense
vectors. The loader rejects unknown tags, truncated values, invalid intern
indexes, duplicate strings, excessive nesting, and trailing bytes.&lt;&#x2F;p&gt;
&lt;p&gt;Publication is transactional enough for the bootstrap boundary: write a
temporary file, flush it, &lt;code&gt;fsync&lt;&#x2F;code&gt; it, close it, and rename it over the final
path. A sidecar records the identity, size, and content hash. Every planning
and emission phase validates the manifest and image again.&lt;&#x2F;p&gt;
&lt;p&gt;The result is not merely a cache. It is a lifetime boundary. Everything inside
the image is immutable and intentionally retained. Everything used to produce
it is eligible to die.&lt;&#x2F;p&gt;
&lt;p&gt;The first bounded recovery implementation reclaimed memory by terminating a
worker process after a batch. It worked, but process exit was doing the job the
runtime should eventually understand.&lt;&#x2F;p&gt;
&lt;p&gt;The new seed has resettable scratch arenas.&lt;&#x2F;p&gt;
&lt;p&gt;One persistent measurement worker and one persistent emission worker load the
compiler environment and normalized image once. Each request creates an arena
checkpoint, performs one bounded unit of work, publishes only its stable
result, and resets to the checkpoint.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;immutable image and compiler environment&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          checkpoint scratch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       measure or emit one function&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          publish stable result&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             reset scratch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The scratch arena reserves 512 MiB of virtual address space with
&lt;code&gt;MAP_NORESERVE&lt;&#x2F;code&gt;; it does not make 512 MiB resident. Pages are committed on
demand. Reset discards whole scratch pages with &lt;code&gt;madvise(MADV_DONTNEED)&lt;&#x2F;code&gt;,
restores counters and the used offset, and invalidates the checkpoint.&lt;&#x2F;p&gt;
&lt;p&gt;Reset is also a safety operation. It fails if the checkpoint is stale, nested,
over capacity, or owns a resource that was opened after the mark and never
closed. The image serializer rejects any value whose address belongs to the
active scratch arena, including scratch children hidden inside a pair.&lt;&#x2F;p&gt;
&lt;p&gt;That prevents a temporary value from quietly escaping into the supposedly
immutable compiler image.&lt;&#x2F;p&gt;
&lt;p&gt;The full compiler currently has 910 functions. Recovery resets measurement
scratch once per function and emission scratch 911 times: once for each
function and once for the ABI note.&lt;&#x2F;p&gt;
&lt;p&gt;Process isolation remains available as a diagnostic mode. It is no longer the
production reclamation mechanism.&lt;&#x2F;p&gt;
&lt;p&gt;Lifetime fixes stop old work from accumulating. Representation fixes reduce
the cost of the state that really must remain alive.&lt;&#x2F;p&gt;
&lt;p&gt;The seed&#x27;s generic value cell used to occupy 56 bytes. It now occupies 24.
The common tag and two payload words are enough for integers, text and symbol
references, pairs, closures, builtins, and dense vectors. Function metadata
moved into a separate descriptor instead of inflating every value.&lt;&#x2F;p&gt;
&lt;p&gt;That is a 57.14 percent reduction in cell allocator bytes.&lt;&#x2F;p&gt;
&lt;p&gt;Repeated text and symbols are interned in deterministic first-use order. A
hash match still compares the complete bytes, so collisions cannot make two
different names alias. Textual token and node kinds become stable integer IDs.
Line and column values are packed into checked 16-bit fields. Indexed
top-level function forms use dense vectors instead of a cons cell for every
entry.&lt;&#x2F;p&gt;
&lt;p&gt;The point was not to turn the language into a pile of clever bit tricks.&lt;&#x2F;p&gt;
&lt;p&gt;The point was to spend rich tree structures where the compiler has trees, and
dense indexed structures where the compiler has tables.&lt;&#x2F;p&gt;
&lt;p&gt;The next accidental lifetime was the artifact itself.&lt;&#x2F;p&gt;
&lt;p&gt;A compiler that constructs an entire ELF image as hexadecimal text may hold
the AST, layout, machine bytes, hex encoding, concatenated output, and decoded
file representation at the same time. The final file may be small while the
path to it is extremely expensive.&lt;&#x2F;p&gt;
&lt;p&gt;Seed recovery now uses a bounded 65,536-byte binary buffer. Exact writes retry
interruptions, advance after short writes, reject zero progress, and fail on
disk-full or invalid-path errors. Full buffers are flushed and reused.&lt;&#x2F;p&gt;
&lt;p&gt;The recovery protocol is deliberately boring:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;write ELF header and startup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;for each canonical function:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    emit one bounded chunk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    append its bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    reset emission scratch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;append ABI note&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;verify exact planned file size&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;chmod 0755&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The partial file starts as mode &lt;code&gt;0600&lt;&#x2F;code&gt;. It becomes executable only after its
size matches the frozen plan and every append succeeds. &lt;code&gt;chmod&lt;&#x2F;code&gt; is still the
small commit operation from the previous design; the difference is that the
bytes no longer travel through one giant retained text value.&lt;&#x2F;p&gt;
&lt;p&gt;The compiler&#x27;s current x86-64 function emitter still creates a hexadecimal
encoding internally. That value is bounded to one function and dies at the
next reset. Hex remains useful for diagnostics. It is no longer the artifact
transport.&lt;&#x2F;p&gt;
&lt;p&gt;The normal native compiler needed the same treatment.&lt;&#x2F;p&gt;
&lt;p&gt;A compiler pipeline has an obvious sequence:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;source -&amp;gt; tokens -&amp;gt; normalized forms -&amp;gt; validated forms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       -&amp;gt; optimized forms -&amp;gt; layout -&amp;gt; machine code -&amp;gt; artifact&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It is easy to implement that sequence while retaining every arrow&#x27;s input and
output until process exit.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;0x0&lt;&#x2F;code&gt; now has an explicit retention graph. Raw source, tokens, validation
worklists, type and effect constraints, optimizer candidates, rendered OISA
records, and generated function chunks are phase-local. The normalized forms
and final native address table are the main compilation-lifetime structures.&lt;&#x2F;p&gt;
&lt;p&gt;The frontend copies strings, symbols, and packed spans into normalized nodes,
then releases source and lexer storage. Validation keeps the validated module,
not its lookup tables and branch joins. Optimizer passes run in scratch and
copy only the accepted form graph into persistent storage. Layout retains
names, sizes, and addresses. Emission writes one function and resets.&lt;&#x2F;p&gt;
&lt;p&gt;Diagnostics still keep line and column information because normalized nodes
own compact spans. Releasing the parser does not mean releasing the ability to
explain an error.&lt;&#x2F;p&gt;
&lt;p&gt;Compiler dumps became observations rather than phases. Optimizer variants run
sequentially. Each process constructs one requested representation, streams
it, records a compact comparison summary, and exits before the next variant.
There is no in-process list containing O0, every intermediate pass, O1, SSA,
LIR, and disassembly at once.&lt;&#x2F;p&gt;
&lt;p&gt;The historical interpreter multi-dump peak was 7,852,696 KiB. The accepted
sequential native optimizer lane measured 90,916 KiB. That is not one magical
allocator optimization; it is the result of changing execution, retention,
and serialization together.&lt;&#x2F;p&gt;
&lt;p&gt;Normal native and OISA compiler output is streamed too. Writers maintain an
online byte count and FNV-1a-64 digest while writing, so callers can validate
the result without retaining or rereading a complete output value.&lt;&#x2F;p&gt;
&lt;p&gt;Three compiler generations now reproduce the same artifact at:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: right&quot;&gt;Generation&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Peak RSS&lt;&#x2F;th&gt;&lt;th&gt;Parity&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;1&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;77,984 KiB&lt;&#x2F;td&gt;&lt;td&gt;trusted parent, byte-identical&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;2&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;70,232 KiB&lt;&#x2F;td&gt;&lt;td&gt;generation 1, byte-identical&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;3&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;77,984 KiB&lt;&#x2F;td&gt;&lt;td&gt;generation 2, byte-identical&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;That is the ordinary self-host path, not the expensive assembly-seed recovery
path.&lt;&#x2F;p&gt;
&lt;p&gt;Compiler memory was only half of the roadmap.&lt;&#x2F;p&gt;
&lt;p&gt;I only care about &lt;code&gt;0x0&lt;&#x2F;code&gt; as a Linux application platform right now. For that
target, process-lifetime allocation is not enough. A server cannot call
&lt;code&gt;mmap&lt;&#x2F;code&gt;, forget every result, and claim success because the kernel cleans up
when the process eventually dies.&lt;&#x2F;p&gt;
&lt;p&gt;The direct ELF backend now implements a managed native profile with:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;unique ownership and moves;&lt;&#x2F;li&gt;
&lt;li&gt;lexical drops;&lt;&#x2F;li&gt;
&lt;li&gt;bounded regions with escape checks;&lt;&#x2F;li&gt;
&lt;li&gt;precise non-atomic reference counting for shared acyclic values;&lt;&#x2F;li&gt;
&lt;li&gt;request and task arena resets;&lt;&#x2F;li&gt;
&lt;li&gt;destructors for files, sockets, and supervised child processes.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This code is emitted directly into the Linux x86-64 executable. It does not
call C, Python, a tracing collector, or a hidden helper runtime.&lt;&#x2F;p&gt;
&lt;p&gt;A unique value has one owner. Moving it transfers that ownership. The compiler
inserts terminal drops in reverse lexical order and rejects double drops,
use-after-move, and ownership-class mismatches.&lt;&#x2F;p&gt;
&lt;p&gt;A region owns a bounded collection of allocations. Releasing the region
releases the collection together. Returning a value whose region ends at that
return is rejected before native layout. Cleanup is emitted on normal exits
and panic paths.&lt;&#x2F;p&gt;
&lt;p&gt;A genuinely shared value uses precise strong reference counting. Retains make
aliases; releases destroy the value when the count reaches zero. The current
profile is single-threaded, so these counters are intentionally non-atomic.
Shared graphs are immutable and acyclic. Explicit cycles are rejected; cyclic
working state belongs in a bounded region.&lt;&#x2F;p&gt;
&lt;p&gt;Each unique, shared, or region owner receives a 16 MiB demand-mapped address
range. Again, virtual capacity is not resident memory. Only touched pages
consume RSS. Text and list allocations made under that owner use the range,
and the terminal drop or reset reclaims the complete composite with
&lt;code&gt;munmap(2)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Generation-checked owner slots catch stale handles even when an alias crosses
a function boundary.&lt;&#x2F;p&gt;
&lt;p&gt;Memory safety is not complete if the heap returns to zero while the process
leaks a socket on every request.&lt;&#x2F;p&gt;
&lt;p&gt;Files, sockets, and supervised child processes are ownership-bearing native
values. File and socket destruction calls &lt;code&gt;close(2)&lt;&#x2F;code&gt;. Child destruction sends
&lt;code&gt;SIGKILL&lt;&#x2F;code&gt; and waits with &lt;code&gt;wait4(2)&lt;&#x2F;code&gt;, preventing zombies and orphans. Resources
registered inside an owner are destroyed before its mapping is released.&lt;&#x2F;p&gt;
&lt;p&gt;The runtime publishes logical counters for live slots, live bytes, regions,
shared values, resources, drops, request resets, task resets, mapped spans,
and mapped bytes.&lt;&#x2F;p&gt;
&lt;p&gt;RSS is useful evidence. It is not the only evidence.&lt;&#x2F;p&gt;
&lt;p&gt;A flat RSS curve can hide a logical leak inside an allocator that reuses
pages. Zero logical counters can hide an allocator that never gives pages back
to the kernel. The release gate requires both the ownership counters and the
resident-memory plateau.&lt;&#x2F;p&gt;
&lt;p&gt;It also includes negative controls. One test deliberately suppresses inferred
cleanup. The leak detector must catch that program. A leak suite that cannot
detect an intentional leak has only proved that its happy path is quiet.&lt;&#x2F;p&gt;
&lt;p&gt;Fast loops catch obvious imbalance. They do not catch every periodic cleanup
bug, counter wrap, child-process leak, or slow RSS staircase.&lt;&#x2F;p&gt;
&lt;p&gt;The final release operation therefore had an inconvenient acceptance test:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MEMOPT_RELEASE_SOAK&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;MEMOPT_LEAK_ITERATIONS=1000000&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;MEMOPT_SOAK_SECONDS=86400&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;make&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; native-memory-soak-check&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The accepted run recorded:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Measurement&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Result&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Duration&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;86,400 seconds&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Configured leak iterations&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1,000,000&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Soak batches&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;577,424&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Iterations per soak child&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;16&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Warm peak RSS&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;10,104 KiB&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Final peak RSS&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;10,380 KiB&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Live allocations&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;0&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Live resources&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;0&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Mapped spans&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;0&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;The runner writes accepted evidence only after the full duration. An
interrupted or failed run publishes nothing. The evidence records the compiler
and fixture hashes, so changing the compiler invalidates the result.&lt;&#x2F;p&gt;
&lt;p&gt;A one-second test cannot be renamed into a release soak. A fixture cannot
stand in for wall-clock evidence. The final cross-domain validator fails closed
if the durable run is missing, too short, stale, or attached to another
compiler revision.&lt;&#x2F;p&gt;
&lt;p&gt;After the run returned &lt;code&gt;native memory soak check ok&lt;&#x2F;code&gt;, the release decision
could finally change to &lt;code&gt;pass&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The seed-recovery progression now looks like this:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Recovery design&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Peak RSS&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Monolithic seed ELF builder&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;12,667,784 KiB&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Bounded process workers&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;3,345,556 KiB&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Image + arenas + compact values + binary output&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;344,860 KiB&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;The final full recoveries were:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Artifact&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Peak RSS&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Limit&lt;&#x2F;th&gt;&lt;th&gt;Parity&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;ELF compiler builder&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;343,524 KiB&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;524,288 KiB&lt;&#x2F;td&gt;&lt;td&gt;stage 2&#x2F;stage 3 identical&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;ELF OISA compiler&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;343,344 KiB&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;524,288 KiB&lt;&#x2F;td&gt;&lt;td&gt;trusted OISA identical&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Builder ratchet rerun&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;344,860 KiB&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;524,288 KiB&lt;&#x2F;td&gt;&lt;td&gt;seed builder identical&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;The 512 MiB release ceiling leaves room above the measured host without
pretending every machine has identical RSS behavior.&lt;&#x2F;p&gt;
&lt;p&gt;More importantly, the explanation changed.&lt;&#x2F;p&gt;
&lt;p&gt;The old answer was, &quot;the seed VM retains a lot, so give it four GiB.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;The new answer names the retained image, scratch arenas, value layout, output
buffer, compiler phase graph, native owners, resource destructors, and release
evidence. Each has an owner, a boundary, and a gate.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-this-does-not-claim&quot;&gt;What This Does Not Claim&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-this-does-not-claim&quot; aria-label=&quot;Anchor link for: what-this-does-not-claim&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The current production statement is intentionally narrow:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;0x0&lt;&#x2F;code&gt; has a bounded memory and lifetime profile for direct ELF Linux x86-64
programs using Unit, Bool, I64, Text, and List values.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I started this work because 3.2 GiB felt like an embarrassing footnote on a
successful self-host.&lt;&#x2F;p&gt;
&lt;p&gt;The result is better: memory is no longer an unnamed pile owned by the
process. The compiler knows which state must persist. Workers know what can be
reset. Native values know who drops them. Resources have destructors. The
release knows what was measured.&lt;&#x2F;p&gt;
&lt;p&gt;And after twenty-four hours, everything that was supposed to be dead was still
dead.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>0x0 Self-Hosting Without The C Detour</title>
		<published>2026-07-17T00:00:00+00:00</published>
		<updated>2026-07-17T00:00:00+00:00</updated>
		<link rel="alternate" type="text/html" href="https://idunnowhatiamdoing.engineering/posts/0x0-self-hosting/"/>
		<id>https://idunnowhatiamdoing.engineering/posts/0x0-self-hosting/</id>
    
		<content type="html" xml:base="https://idunnowhatiamdoing.engineering/posts/0x0-self-hosting/">&lt;p&gt;Which compiler built the compiler? What built that compiler? Which artifact is
trusted? What happens if the trusted binary disappears? Does recovery go
through another language? Does the process finish on a machine I can actually
afford?&lt;&#x2F;p&gt;
&lt;p&gt;It is easy to say a compiler compiles itself after one successful demo. It is
harder to make the claim precise enough that a clean checkout can prove it.&lt;&#x2F;p&gt;
&lt;p&gt;That is what changed in &lt;code&gt;0x0&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;After writing about &lt;a href=&quot;&#x2F;posts&#x2F;0x0-technically&#x2F;&quot;&gt;0x0 technically&lt;&#x2F;a&gt;, its
&lt;a href=&quot;&#x2F;posts&#x2F;abi-0x0&#x2F;&quot;&gt;ABI and ELF boundary&lt;&#x2F;a&gt;, and its
&lt;a href=&quot;&#x2F;posts&#x2F;0x0-distribution&#x2F;&quot;&gt;distribution model&lt;&#x2F;a&gt;, I ended up back at the least
glamorous part of language design: deleting old scaffolding, drawing a stricter
trust boundary, and watching a compiler use twelve gigabytes of memory to
produce a file smaller than one megabyte.&lt;&#x2F;p&gt;
&lt;p&gt;The work is recorded in ADR-0188 through ADR-0191. Together they changed the
answer to a useful question:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Can &lt;code&gt;0x0&lt;&#x2F;code&gt; recover and reproduce its native compiler without generating C?&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The answer is now yes.&lt;&#x2F;p&gt;
&lt;p&gt;The answer also comes with footnotes, because trustworthy bootstrapping is
mostly footnotes with executable tests.&lt;&#x2F;p&gt;
&lt;p&gt;The first change was not a compiler feature. It was deleting
&lt;code&gt;python-dehosting-roadmap.md&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;That file planned the migration of the repository&#x27;s Python tooling into &lt;code&gt;0x0&lt;&#x2F;code&gt;.
It was useful while the migration was moving. At closure, the live ledger
reported 176 migrated rows, with zero remaining rows, zero host-only rows, and
zero temporary shim rows.&lt;&#x2F;p&gt;
&lt;p&gt;Keeping the roadmap after that point would not preserve useful history. It
would create a second, stale place where somebody could try to record current
state.&lt;&#x2F;p&gt;
&lt;p&gt;The active truth now lives in things that can fail:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the migration progress ledger;&lt;&#x2F;li&gt;
&lt;li&gt;the no-Python exceptions ledger;&lt;&#x2F;li&gt;
&lt;li&gt;the Python de-hosting progress gate;&lt;&#x2F;li&gt;
&lt;li&gt;the no-Python repository gate;&lt;&#x2F;li&gt;
&lt;li&gt;release checks and ADRs.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;There is still an explicit exceptions ledger for residual non-source helpers
that need native JSON, time, or rewrite replacements. That is not hidden behind
a completed percentage. It is a named caveat with a gate around it.&lt;&#x2F;p&gt;
&lt;p&gt;I like this distinction more than I expected. A roadmap says what I intended
to do. A ledger and a gate say what the checkout can prove now.&lt;&#x2F;p&gt;
&lt;p&gt;ADR-0188 retired the intention document after the proof replaced it.&lt;&#x2F;p&gt;
&lt;p&gt;Before these changes, the full self-host target could pass through a native
helper built like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;compiler&#x2F;compat-main.0x0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stage 2 OISA compiler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;build&#x2F;native&#x2F;zero-native.c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;host C compiler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;bin&#x2F;zero-native&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There is nothing fake about generating C. It is a useful backend and an
excellent compatibility oracle. C gives a young language access to mature
optimizers, system headers, linkers, and decades of platform knowledge.&lt;&#x2F;p&gt;
&lt;p&gt;But it proves a different statement.&lt;&#x2F;p&gt;
&lt;p&gt;It proves that &lt;code&gt;0x0&lt;&#x2F;code&gt; can translate its compiler through C and that a host C
toolchain can finish the job. It does not prove that the native &lt;code&gt;0x0&lt;&#x2F;code&gt; compiler
path can recover itself without that detour.&lt;&#x2F;p&gt;
&lt;p&gt;I did not want &lt;code&gt;make full-selfhost&lt;&#x2F;code&gt; to quietly answer the easier question.&lt;&#x2F;p&gt;
&lt;p&gt;ADR-0189 moved the normal gate to the native ELF compiler builder:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;trusted zero-elf-compiler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;zero-elf-compiler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;zero-elf-stage2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;zero-elf-stage3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;zero-elf-stage2 == zero-elf-stage3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The comparison is byte-for-byte. Stage 2 must compile the compiler into stage
3 without changing it.&lt;&#x2F;p&gt;
&lt;p&gt;The C route still exists, but now its names tell the truth:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;make&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c-compat-native&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;make&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c-compat-full-selfhost&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;make&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; native-compat-check&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Compatibility is useful. Compatibility is not the trusted root.&lt;&#x2F;p&gt;
&lt;p&gt;Removing C from the normal gate exposed the next question.&lt;&#x2F;p&gt;
&lt;p&gt;What if the trusted release compiler is missing?&lt;&#x2F;p&gt;
&lt;p&gt;A self-hosted compiler cannot appear from its own source. There is always a
first executable somewhere: an older compiler, an interpreter, a tiny seed, or
another language implementation.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;0x0&lt;&#x2F;code&gt; keeps a small x86-64 assembly seed. Its OISA succession looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;seed&#x2F;zero.s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stage1.oisa&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stage2.oisa&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stage3.oisa&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stage2.oisa == stage3.oisa&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;OISA is the intermediate instruction set used by the self-host chain. The
assembly seed can produce stage 1. Stage 1 compiles the compiler into stage 2.
Stage 2 compiles it into stage 3. If stages 2 and 3 differ, the succession is
not stable and the bootstrap stops.&lt;&#x2F;p&gt;
&lt;p&gt;The remaining hole was turning that stable &lt;code&gt;stage2.oisa&lt;&#x2F;code&gt; image into the native
ELF compiler artifacts without asking the compatibility backend to emit C.&lt;&#x2F;p&gt;
&lt;p&gt;ADR-0190 added direct seed commands for two executables:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;an ELF OISA compiler, which compiles &lt;code&gt;compiler&#x2F;main.0x0&lt;&#x2F;code&gt; back to the expected
stage 2 OISA image;&lt;&#x2F;li&gt;
&lt;li&gt;an ELF compiler builder, which emits another native ELF compiler builder and
can reproduce itself byte-for-byte.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That gives the recovery chain another branch:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;seed&#x2F;zero.s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stable stage2.oisa&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    +----&amp;gt; native zero-oisa-compiler ----&amp;gt; expected stage2.oisa&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    +----&amp;gt; native zero-elf-compiler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              zero-elf-stage2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              zero-elf-stage3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              stage2 == stage3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;No C source is generated in that branch. No C program is compiled. The seed
path writes the ELF compiler artifacts directly.&lt;&#x2F;p&gt;
&lt;p&gt;This does not mean &lt;code&gt;0x0&lt;&#x2F;code&gt; materializes from nothing. The first trusted boundary
still includes the assembly seed and the host machinery needed to assemble and
run it. The current native target is Linux x86-64. The operating system, CPU,
assembler, linker, and source checkout remain part of the bootstrap story.&lt;&#x2F;p&gt;
&lt;p&gt;The first direct seed implementation worked.&lt;&#x2F;p&gt;
&lt;p&gt;It was also a small memory disaster.&lt;&#x2F;p&gt;
&lt;p&gt;The monolithic &lt;code&gt;compiler-elf-builder-stage2&lt;&#x2F;code&gt; command loaded the stage 2 image,
parsed the compiler, planned the ELF layout, generated every function, and
held parser, layout, and code-generation temporaries until the process exited.
On the measured compiler source, it peaked at:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;12,667,784 KiB RSS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The output executable was around 672 kilobytes.&lt;&#x2F;p&gt;
&lt;p&gt;Chunking only the final text did not help. The problem was not the size of the
hex string written to disk. The seed VM retained all the intermediate
allocations that had produced it.&lt;&#x2F;p&gt;
&lt;p&gt;This is the kind of bug that makes a feature technically complete and
operationally imaginary. A recovery path that needs an undocumented 16 GiB
allowance is not a comfortable first root.&lt;&#x2F;p&gt;
&lt;p&gt;ADR-0191 changed the unit of work.&lt;&#x2F;p&gt;
&lt;p&gt;Direct ELF generation has a slightly annoying dependency. A function body may
contain an absolute call to another function. To encode that call, the emitter
needs the callee&#x27;s address. To know that address, it needs to know the sizes of
all functions before it.&lt;&#x2F;p&gt;
&lt;p&gt;So the compiler cannot safely emit arbitrary functions and discover the
layout afterward.&lt;&#x2F;p&gt;
&lt;p&gt;The solution was to separate planning from emission:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;normalize and index function order&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;measure function sizes in bounded batches&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;freeze names, addresses, entry point, file size,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ELF header&#x2F;start bytes, and ABI note in a plan&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;emit function chunks in bounded batches&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;against the frozen address table&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;append ABI note&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;verify exact planned size&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;chmod executable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The default batch contains 32 functions. Each worker loads the stable stage 2
compiler state, handles its bounded slice, writes its result, and exits. Exit
is important: it gives the operating system a chance to reclaim everything the
seed VM does not reclaim during a long process.&lt;&#x2F;p&gt;
&lt;p&gt;The first pass measures function sizes. Those measurements produce a raw
address table. The plan finalizer then computes the artifact-specific startup
stub, entry point, function base, exact file size, and ABI note.&lt;&#x2F;p&gt;
&lt;p&gt;The second pass emits real function bytes using the frozen addresses. The OISA
compiler and the compiler builder share function measurement and body
emission, while keeping separate startup and plan identities.&lt;&#x2F;p&gt;
&lt;p&gt;This makes every emitted call agree with the same layout without keeping every
function&#x27;s temporary state alive at the same time.&lt;&#x2F;p&gt;
&lt;p&gt;It is slower. Stage 2 loading and normalization repeat across workers. That is
an acceptable trade for a recovery and audit path. I would rather wait for a
bounded process than discover that the bootstrap proof only works on one large
machine.&lt;&#x2F;p&gt;
&lt;p&gt;There is another detail in the new flow that I like.&lt;&#x2F;p&gt;
&lt;p&gt;The output file is not executable while it is being assembled.&lt;&#x2F;p&gt;
&lt;p&gt;The driver writes the header and startup bytes, appends every decoded function
chunk, appends the ABI note, and compares the actual file size with the frozen
plan. Only after all those checks pass does it apply executable permissions.&lt;&#x2F;p&gt;
&lt;p&gt;That turns &lt;code&gt;chmod&lt;&#x2F;code&gt; into a tiny commit operation.&lt;&#x2F;p&gt;
&lt;p&gt;A killed worker may leave a partial file, but it does not leave a partial file
pretending to be a compiler. The filesystem metadata communicates whether the
transaction completed.&lt;&#x2F;p&gt;
&lt;p&gt;This is not a replacement for atomic rename or signed release artifacts. It is
still a useful local invariant: incomplete compiler bytes should not look
runnable.&lt;&#x2F;p&gt;
&lt;p&gt;The long bounded run found a bug outside the compiler.&lt;&#x2F;p&gt;
&lt;p&gt;The RSS limiter samples the worker process group while the build runs. Over a
long self-host, the shell created tens of thousands of short-lived sampler
children. One valid build finished and produced the correct artifact, but the
wrapper surfaced shell &lt;code&gt;wait&lt;&#x2F;code&gt; status &lt;code&gt;127&lt;&#x2F;code&gt; instead of the command&#x27;s real
status.&lt;&#x2F;p&gt;
&lt;p&gt;The compiler had succeeded. The evidence wrapper had lied about it.&lt;&#x2F;p&gt;
&lt;p&gt;The fix was to let the monitored command record its own exit status inside the
process group before the leader exits, with &lt;code&gt;wait&lt;&#x2F;code&gt; retained as a fallback. The
full target was then rerun through the limiter.&lt;&#x2F;p&gt;
&lt;p&gt;This is a useful bootstrap lesson. A proof is only as reliable as the program
collecting the proof. Build wrappers, timeout handlers, memory samplers, and
comparison commands are part of the trust story too.&lt;&#x2F;p&gt;
&lt;p&gt;The original 729-function builder measurement dropped from 12,667,784 KiB to
3,154,848 KiB peak RSS.&lt;&#x2F;p&gt;
&lt;p&gt;The current 736-function compiler completed with these results:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Artifact&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Peak RSS&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Output size&lt;&#x2F;th&gt;&lt;th&gt;Parity result&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;ELF compiler builder&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;3,345,556 KiB&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;672,106 bytes&lt;&#x2F;td&gt;&lt;td&gt;self-reproduced byte-for-byte&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;ELF OISA compiler&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;3,337,388 KiB&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;672,023 bytes&lt;&#x2F;td&gt;&lt;td&gt;emitted the trusted stage 2 image byte-for-byte&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Both ran below the enforced 4 GiB ceiling. Both returned status zero through
the fixed process-group limiter. Neither generated C.&lt;&#x2F;p&gt;
&lt;p&gt;The result is not tiny. Three-point-two GiB is still a serious recovery budget
for a 672 KiB artifact. The important change is that the budget is now bounded,
measured, enforced, and low enough for an ordinary development machine.&lt;&#x2F;p&gt;
&lt;p&gt;There is more memory work to do. There is no reason to turn a successful bound
into a permanent excuse.&lt;&#x2F;p&gt;
&lt;p&gt;The project now has three deliberately different paths.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;make full-selfhost&lt;&#x2F;code&gt; prefers the trusted release compiler. It builds a native
ELF compiler builder, uses that builder to produce stage 2, uses stage 2 to
produce stage 3, and compares the two executables byte-for-byte.&lt;&#x2F;p&gt;
&lt;p&gt;If the trusted release compiler is absent, the target can recover the native
builder from the seed-produced stage 2 OISA image through the bounded driver.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;make bootstrap-from-seed&lt;&#x2F;code&gt; explicitly starts from the assembly seed, proves
OISA stage 2&#x2F;stage 3 equality, emits both native compiler artifacts through the
bounded seed path, and proves the native compiler builder can reproduce itself.&lt;&#x2F;p&gt;
&lt;p&gt;This is the expensive path on purpose. It exists to recover or audit the
trusted release root, not to make every edit pay the full bootstrap cost.&lt;&#x2F;p&gt;
&lt;p&gt;The generated-C and GAS-backed paths remain available behind explicit
&lt;code&gt;c-compat-*&lt;&#x2F;code&gt; and &lt;code&gt;native-compat-check&lt;&#x2F;code&gt; targets. They are useful for comparison,
platform experiments, and catching backend disagreement.&lt;&#x2F;p&gt;
&lt;p&gt;They no longer silently define what &quot;full self-host&quot; means.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;0x0&lt;&#x2F;code&gt; can compile its compiler into a native executable, run that compiler like
another program, and reproduce it without generating C.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Glossary&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Self-hosting: a compiler written in the language it compiles.&lt;&#x2F;p&gt;
&lt;p&gt;Bootstrap: the process that creates the first usable compiler artifact from a
smaller trusted root.&lt;&#x2F;p&gt;
&lt;p&gt;Trusted root: the starting artifact or implementation accepted as the basis of
the compiler succession proof.&lt;&#x2F;p&gt;
&lt;p&gt;Seed: the small assembly implementation used to start the &lt;code&gt;0x0&lt;&#x2F;code&gt; compiler
chain.&lt;&#x2F;p&gt;
&lt;p&gt;OISA: the intermediate instruction set used by the &lt;code&gt;0x0&lt;&#x2F;code&gt; self-host chain.&lt;&#x2F;p&gt;
&lt;p&gt;ELF: Executable and Linkable Format, the native executable format emitted by
the current Linux x86-64 backend.&lt;&#x2F;p&gt;
&lt;p&gt;RSS: Resident Set Size, an approximation of the physical memory held by a
process.&lt;&#x2F;p&gt;
&lt;p&gt;Parity: byte-for-byte agreement between two independently produced stages or
artifacts.&lt;&#x2F;p&gt;
&lt;p&gt;ABI note: the marker appended to a direct ELF artifact to identify the binary
contract it claims to implement.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>0x0 Distribution</title>
		<published>2026-07-12T00:00:00+00:00</published>
		<updated>2026-07-12T00:00:00+00:00</updated>
		<link rel="alternate" type="text/html" href="https://idunnowhatiamdoing.engineering/posts/0x0-distribution/"/>
		<id>https://idunnowhatiamdoing.engineering/posts/0x0-distribution/</id>
    
		<content type="html" xml:base="https://idunnowhatiamdoing.engineering/posts/0x0-distribution/">&lt;p&gt;I&#x27;m learning that adding a network to a programming language is easy if I lie
to myself, just a bit.&lt;&#x2F;p&gt;
&lt;p&gt;I can call a socket, serialize a value, send some bytes, and say the language
is distributed. The demo works. Two terminals print something. I am genius
for a few seconds.&lt;&#x2F;p&gt;
&lt;p&gt;Then one node disappears after receiving a message but before acknowledging
it. The sender does not know whether to retry. The retry may perform the work
twice. A worker crashes, restarts, and finds an old message. Two nodes disagree
about membership. A token leaks into a diagnostic report. The network delivers
message &lt;code&gt;2&lt;&#x2F;code&gt; before message &lt;code&gt;1&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The socket was the easy part.&lt;&#x2F;p&gt;
&lt;p&gt;The real distributed system begins when the answer to &quot;what happened?&quot; is
&quot;we cannot know from here.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;That is the problem &lt;code&gt;0x0&lt;&#x2F;code&gt; is starting to tackle.&lt;&#x2F;p&gt;
&lt;p&gt;This follows my earlier attempt to describe &lt;a href=&quot;&#x2F;posts&#x2F;0x0-technically&#x2F;&quot;&gt;0x0 technically&lt;&#x2F;a&gt;.
The short version is that &lt;code&gt;0x0&lt;&#x2F;code&gt; is a small, symbolic, pure-functional language
kernel with a self-hosted compiler. It looks like a Lisp, emits native
artifacts, and has an unhealthy interest in making its contracts inspectable.&lt;&#x2F;p&gt;
&lt;p&gt;That last part turns out to be useful when the network gets involved.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;A Remote Call Is Not A Function Call&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A local function call has a fairly comfortable contract. Control enters a
function and eventually returns, panics, or kills the process. The caller and
callee share one machine&#x27;s memory and failure boundary.&lt;&#x2F;p&gt;
&lt;p&gt;A remote operation adds uncomfortable states:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the message was never sent;&lt;&#x2F;li&gt;
&lt;li&gt;the message was sent but never received;&lt;&#x2F;li&gt;
&lt;li&gt;the message was received but not processed;&lt;&#x2F;li&gt;
&lt;li&gt;the message was processed but not acknowledged;&lt;&#x2F;li&gt;
&lt;li&gt;the acknowledgement was sent but not received;&lt;&#x2F;li&gt;
&lt;li&gt;the operation ran twice;&lt;&#x2F;li&gt;
&lt;li&gt;the recipient restarted and forgot what it knew;&lt;&#x2F;li&gt;
&lt;li&gt;the sender and recipient disagree about who belongs to the cluster.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is why I do not want remote execution to look exactly like an ordinary
function call. Hiding those states does not remove them. It only makes the
failure policy accidental.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;0x0&lt;&#x2F;code&gt; starts from actors and messages instead.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(ƒ send-job&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (∷ (→ (RemoteActor Text) Text Any))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (↯ actor)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (worker payload)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (⟿ worker payload))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;RemoteActor&lt;&#x2F;code&gt; type carries intent. The &lt;code&gt;actor&lt;&#x2F;code&gt; effect says this function
crosses the actor runtime boundary. The &lt;code&gt;⟿&lt;&#x2F;code&gt; form says this is a remote send.&lt;&#x2F;p&gt;
&lt;p&gt;There is an important limitation: this source form does not open a network
connection by itself. The compiler lowers it to an ordinary tagged value:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(list &amp;quot;RemoteActorSend&amp;quot; worker payload)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That value is a descriptor. It says what the program wants the runtime to do.
The runtime remains responsible for scheduling, transport, delivery, and
failure policy.&lt;&#x2F;p&gt;
&lt;p&gt;I like this separation. Syntax records intent. Data carries the intent across
the boundary. Effects prevent pure code from secretly performing the action.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The Actor-Shaped Core&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The actor model gives each unit of work an identity and a mailbox. Instead of
sharing mutable state directly, actors exchange messages. In the model used by
&lt;code&gt;0x0&lt;&#x2F;code&gt;, an actor has:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;an actor reference containing a node, name, and message type;&lt;&#x2F;li&gt;
&lt;li&gt;a FIFO mailbox;&lt;&#x2F;li&gt;
&lt;li&gt;a processed-message log;&lt;&#x2F;li&gt;
&lt;li&gt;a restart count;&lt;&#x2F;li&gt;
&lt;li&gt;an alive or dead state.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Messages have a sender, recipient, payload, and type. The local model uses a
deterministic scheduler: actor names have a stable order and one message is
dequeued per step.&lt;&#x2F;p&gt;
&lt;p&gt;It creates useful failure boundaries. A worker can fail without making every
actor share its stack and mutable state. A mailbox gives pending work an
explicit home. An actor reference separates logical identity from a raw
pointer or socket.&lt;&#x2F;p&gt;
&lt;p&gt;The repository also defines pure constructors for the runtime vocabulary:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(actor-ref node name)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(actor-mailbox owner messages)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(actor-typed-send sender recipient payload)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(actor-dead-letter sender recipient payload)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(actor-supervision-policy strategy max-restarts window)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(actor-crash-report actor failure fingerprint)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(actor-restart-limit policy count window)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;They produce values such as:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(list &amp;quot;ActorSupervisionPolicy&amp;quot; strategy max-restarts window)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A policy can be inspected, serialized, hashed, tested, or rejected before a
host runtime acts on it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Fault Tolerance Means Deciding How To Fail&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A failure has a bounded effect and a defined next decision.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;0x0&lt;&#x2F;code&gt; breaks that decision into a few explicit pieces.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Supervision&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A supervisor owns a restart strategy, a maximum restart count, and a time
window. A crash becomes a typed report. The next action becomes a supervision
decision: restart, stop, or escalate.&lt;&#x2F;p&gt;
&lt;p&gt;The useful part is the restart budget. It is a denial-of-service loop with
optimistic branding. A bounded restart policy makes the failure visible when
recovery is no longer working.&lt;&#x2F;p&gt;
&lt;p&gt;The local fixture models a worker receiving &lt;code&gt;one&lt;&#x2F;code&gt;, &lt;code&gt;boom&lt;&#x2F;code&gt;, and &lt;code&gt;two&lt;&#x2F;code&gt;. &lt;code&gt;boom&lt;&#x2F;code&gt;
causes a crash; the supervisor restarts the worker if its budget allows it; the
event report records the crash and restart.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Dead Letters And Acknowledgements&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;An undeliverable message is not discarded as an invisible transport detail. It
can become an &lt;code&gt;ActorDeadLetter&lt;&#x2F;code&gt; or &lt;code&gt;DistributedDeadLetterReport&lt;&#x2F;code&gt;. Successful
delivery has a &lt;code&gt;DistributedDeliveryAck&lt;&#x2F;code&gt; descriptor.&lt;&#x2F;p&gt;
&lt;p&gt;An acknowledgement still does not prove that business work happened exactly
once. It only proves whatever layer the acknowledgement contract defines. That
distinction matters. Distributed systems get dangerous when &quot;received,&quot;
&quot;processed,&quot; and &quot;committed&quot; are treated as synonyms.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Replay&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Actor events have a sequence and a replay fingerprint. The goal is to make a
failure reproducible from the event stream.&lt;&#x2F;p&gt;
&lt;p&gt;Determinism helps here. If scheduling order is stable, replay and bounded model
checking have fewer meaningless interleavings to explore. The repository has
contracts for replay events, fingerprints, distributed replay plans, and
counterexample reports.&lt;&#x2F;p&gt;
&lt;p&gt;The current replay gate is deliberately small. It validates fixture
fingerprints and rejects known tampering cases; it is not yet a durable,
cryptographically chained event log. The shape exists before the full storage
system does.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Capability Boundaries&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;0x0&lt;&#x2F;code&gt; separates source effects from detailed runtime capabilities such as:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cap.actor.runtime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cap.replay.deterministic&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cap.distributed.node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cap.network.client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cap.network.server&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Cluster membership also carries capability advertisements. A node should not
receive work it is not allowed or able to perform. The cluster contract names
rejection cases for invalid credentials, sender spoofing, replayed nonces, and
capability mismatch.&lt;&#x2F;p&gt;
&lt;p&gt;This is fault tolerance too. Rejecting an invalid transition before it mutates
state is usually cheaper than recovering afterward.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Distribution As Layers&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The current design is easier to understand as layers:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0x0 actor syntax&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tagged intent values&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;deterministic actor and supervision model&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;host transport boundary&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;event, replay, and release evidence&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;At the source level, &lt;code&gt;actor&lt;&#x2F;code&gt;, &lt;code&gt;remote-actor&lt;&#x2F;code&gt;, &lt;code&gt;!&lt;&#x2F;code&gt;, &lt;code&gt;⟿&lt;&#x2F;code&gt;, &lt;code&gt;receive&lt;&#x2F;code&gt;, and &lt;code&gt;select&lt;&#x2F;code&gt;
become tagged data.&lt;&#x2F;p&gt;
&lt;p&gt;At the runtime-contract level, &lt;code&gt;runtime&#x2F;distributed-actors.0x0&lt;&#x2F;code&gt; defines nodes,
envelopes, partitions, membership, authentication, acknowledgements, dead
letters, reconnect plans, supervision, and replay.&lt;&#x2F;p&gt;
&lt;p&gt;At the local behavior level, the actor gate checks fixture reports for FIFO
mailboxes, crashes, restart policy, duplicates, out-of-order messages,
partitions, unauthorized sends, and counterexamples.&lt;&#x2F;p&gt;
&lt;p&gt;At the transport level, the distributed-cluster gate opens one-shot loopback
TCP listeners, probes three named nodes, records their addresses and capability
advertisements, and verifies the report and replay contract.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What The Current Gate Actually Proves&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The repository documentation carefully calls this a bounded loopback boundary.
Looking at the implementation makes the boundary even clearer.&lt;&#x2F;p&gt;
&lt;p&gt;The cluster adapter really opens local TCP listeners and exchanges status JSON
over &lt;code&gt;127.0.0.1&lt;&#x2F;code&gt;. That proves the host environment can create and reach the
transport endpoints used by the gate.&lt;&#x2F;p&gt;
&lt;p&gt;The current adapter also writes deterministic fixture evidence for delivery
acknowledgements, duplicates, dead letters, supervised restarts, partitions,
timeouts, reconnects, unauthorized tokens, spoofing, nonce replay, and
capability mismatches. The tests verify that those report fields and stable
diagnostics remain present, and that raw credentials do not appear in the
report.&lt;&#x2F;p&gt;
&lt;p&gt;What it does not yet do is drive every one of those failure cases through a
long-lived concurrent message transport. The actor adapter is also a fixed
deterministic fixture, not yet a general scheduler for arbitrary application
actors.&lt;&#x2F;p&gt;
&lt;p&gt;So:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0x0&lt;&#x2F;code&gt; has source forms and pure contracts for actor and distributed intent;&lt;&#x2F;li&gt;
&lt;li&gt;it has deterministic supervision, failure, replay, and model-check evidence
shapes;&lt;&#x2F;li&gt;
&lt;li&gt;it has a real local TCP probe boundary and stable report gates;&lt;&#x2F;li&gt;
&lt;li&gt;it does not yet have a production remote cluster runtime.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;There are no durable distributed mailboxes, WAN partition claims,
cross-version protocol negotiation, managed membership service, or remote
datacenter deployment here yet.&lt;&#x2F;p&gt;
&lt;p&gt;A contract scaffold is valuable when it is presented as a
contract scaffold. It gives the next implementation something precise to
replace and something stable to preserve.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Why The Lisp-Like Syntax Helps&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The parentheses are not what make a system distributed. They do make the
language unusually convenient for describing one.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The Syntax Is Already A Tree&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(⟿ worker &amp;quot;compile&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;is already close to its abstract syntax tree. The compiler does not need to
recover a complicated structure from many unrelated grammar rules. It sees a
list whose head is &lt;code&gt;⟿&lt;&#x2F;code&gt; and whose remaining elements are arguments.&lt;&#x2F;p&gt;
&lt;p&gt;The lowering is correspondingly boring:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(list &amp;quot;RemoteActorSend&amp;quot; worker &amp;quot;compile&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Boring lowering is good. There are fewer places for source intent to disappear
between parser, checker, compiler, runtime, and replay tooling.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Code And Protocol Data Share A Shape&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Actor messages, supervision policies, replay events, and cluster descriptors
are tagged lists. Source code is also made of symbolic list forms.&lt;&#x2F;p&gt;
&lt;p&gt;I would call this homoiconic in spirit. The useful property today is simpler:
the source tree and the runtime contract tree resemble each other.&lt;&#x2F;p&gt;
&lt;p&gt;That resemblance makes small domain-specific forms cheap to add. &lt;code&gt;receive&lt;&#x2F;code&gt; and
&lt;code&gt;select&lt;&#x2F;code&gt; do not require inventing an entirely separate mini-language. They are
new symbolic heads with checked argument shapes and explicit lowerings.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effects Stay Visible&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The function shape puts its contract next to its implementation:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(ƒ handle-message&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (∷ (→ (Actor Text) Text Any))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (↯ actor)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (worker message)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (! worker message))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The type says what values cross the boundary. The effect row says what kind of
world the function may touch. The body says what it does. All three are forms
in the same tree and can be inspected before code generation.&lt;&#x2F;p&gt;
&lt;p&gt;For a distributed language, that is more than visual consistency. It lets the
compiler reject pure code that attempts an actor or network effect. The syntax
makes authority reviewable.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Small Syntax Supports Multiple Interpreters&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;0x0&lt;&#x2F;code&gt; has a self-hosted compiler, an assembly recovery seed, native backends,
runtime tooling, and evidence checkers. A uniform s-expression surface reduces
how many different parsers and representations those paths need to agree on.&lt;&#x2F;p&gt;
&lt;p&gt;When the project is trying to verify compiler succession, ABI rules, runtime
capabilities, and replay contracts, a small grammar is not minimalism for its
own sake. It is a way to reduce the trusted surface.&lt;&#x2F;p&gt;
&lt;p&gt;The tradeoff is real. Unicode symbols such as &lt;code&gt;ƒ&lt;&#x2F;code&gt;, &lt;code&gt;∷&lt;&#x2F;code&gt;, &lt;code&gt;↯&lt;&#x2F;code&gt;, and &lt;code&gt;⟿&lt;&#x2F;code&gt; are compact
and visually distinct, but they are harder to type, search for, and explain to
tools that assume ASCII. Parentheses also make malformed nesting easy for a
human to miss without editor support.&lt;&#x2F;p&gt;
&lt;p&gt;I still think the structural win is worth exploring. The syntax makes policy
look like data, and distributed systems are mostly policy wearing a network
cable.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The Lesson&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The interesting part of distribution in &lt;code&gt;0x0&lt;&#x2F;code&gt; is not that it can open a local
socket. Almost every general-purpose language can do that.&lt;&#x2F;p&gt;
&lt;p&gt;The interesting part is the attempt to make the uncomfortable decisions
explicit:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;who owns a mailbox;&lt;&#x2F;li&gt;
&lt;li&gt;what identifies a node and an actor;&lt;&#x2F;li&gt;
&lt;li&gt;what a message is allowed to contain;&lt;&#x2F;li&gt;
&lt;li&gt;which effects a function may perform;&lt;&#x2F;li&gt;
&lt;li&gt;what happens when a worker crashes;&lt;&#x2F;li&gt;
&lt;li&gt;how often it may restart;&lt;&#x2F;li&gt;
&lt;li&gt;where an undeliverable message goes;&lt;&#x2F;li&gt;
&lt;li&gt;what an acknowledgement means;&lt;&#x2F;li&gt;
&lt;li&gt;which event order is replayed;&lt;&#x2F;li&gt;
&lt;li&gt;what a gate actually proves.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The Lisp-like syntax helps because every one of those decisions can become a
small symbolic form, a tagged value, or a checked policy. The fault-tolerance
story helps because every failure can become an event and a bounded next
decision instead of an invisible exception somewhere behind a remote call.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Glossary&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Actor: an isolated unit of computation with an identity and a mailbox.&lt;&#x2F;p&gt;
&lt;p&gt;Mailbox: the queue of messages waiting for an actor.&lt;&#x2F;p&gt;
&lt;p&gt;Supervision: a policy for deciding whether a failed actor should restart,
stop, or escalate its failure.&lt;&#x2F;p&gt;
&lt;p&gt;Dead letter: a message that could not be delivered to its intended recipient.&lt;&#x2F;p&gt;
&lt;p&gt;Replay: reproducing or validating behavior from a recorded event sequence.&lt;&#x2F;p&gt;
&lt;p&gt;Capability: explicit authority to perform an effect such as actor execution,
network access, or file access.&lt;&#x2F;p&gt;
&lt;p&gt;Partition: a condition where nodes cannot communicate even though one or both
may still be running.&lt;&#x2F;p&gt;
&lt;p&gt;S-expression: a parenthesized symbolic list used to represent code or data.&lt;&#x2F;p&gt;
&lt;p&gt;Homoiconicity: the property of a language whose code has the same basic
representation as its data. &lt;code&gt;0x0&lt;&#x2F;code&gt; currently benefits from this resemblance
without claiming a complete Lisp macro environment.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>ABI 0x0</title>
		<published>2026-07-04T00:00:00+00:00</published>
		<updated>2026-07-04T00:00:00+00:00</updated>
		<link rel="alternate" type="text/html" href="https://idunnowhatiamdoing.engineering/posts/abi-0x0/"/>
		<id>https://idunnowhatiamdoing.engineering/posts/abi-0x0/</id>
    
		<content type="html" xml:base="https://idunnowhatiamdoing.engineering/posts/abi-0x0/">&lt;p&gt;I&#x27;m learning a lot designing my own programming language, 0x0.
Some terms I&#x27;m recalling from my days of compiling linux.
But most, I&#x27;m totally lost. Here&#x27;s my journey with ABI&#x27;s Ox0.&lt;&#x2F;p&gt;
&lt;p&gt;Wine can run a Windows program on Linux. On x86-64, that does
not mean every instruction is being interpreted by an emulator.
Windows code and Linux code can exist in the same process,
in the same virtual address space.&lt;&#x2F;p&gt;
&lt;p&gt;The magic ends when one side tries to call the other.&lt;&#x2F;p&gt;
&lt;p&gt;At that point the CPU does not care about &quot;Windows function&quot; or &quot;Linux
function&quot;. It cares about registers, stack layout, memory addresses, return
values, symbol tables, object formats, and ownership rules. That pile of
promises is the ABI: the Application Binary Interface.&lt;&#x2F;p&gt;
&lt;p&gt;An API says:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;read_proc_version&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;args&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;An ABI says:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;which register contains &lt;code&gt;args&lt;&#x2F;code&gt;;&lt;&#x2F;li&gt;
&lt;li&gt;which register contains the return value;&lt;&#x2F;li&gt;
&lt;li&gt;whether the caller or callee cleans anything up;&lt;&#x2F;li&gt;
&lt;li&gt;how the stack must be aligned;&lt;&#x2F;li&gt;
&lt;li&gt;what object file symbol exposes the function;&lt;&#x2F;li&gt;
&lt;li&gt;what the pointed-to memory looks like;&lt;&#x2F;li&gt;
&lt;li&gt;who owns that memory after the call returns;&lt;&#x2F;li&gt;
&lt;li&gt;what counts as success or failure.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is why ABI work is writing a border treaty between two runtimes.&lt;&#x2F;p&gt;
&lt;p&gt;The fun part is that this is also a useful way to understand what &lt;code&gt;0x0&lt;&#x2F;code&gt;
is doing with ELF output. &lt;code&gt;0x0&lt;&#x2F;code&gt; is not just &quot;emitting a binary&quot;.
It is deciding what binary promises exist, how to stamp them into
artifacts, and how to reject artifacts that do not keep those promises.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The Wine: Same Process, Different Contracts&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;ArcaneNibble&#x27;s post, &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;arcanenibble.com&#x2F;how-to-call-linux-code-from-a-wine-process.html&quot;&gt;&quot;How to call Linux code from a Wine process&quot;&lt;&#x2F;a&gt;,
is a great real-world ABI tour because it starts from a weird but practical
question: if Wine has Windows and Linux code in one process, can a
Windows-side program call Linux-side code?&lt;&#x2F;p&gt;
&lt;p&gt;The answer is &quot;yes&quot;, but every version of &quot;yes&quot; is really an ABI story.&lt;&#x2F;p&gt;
&lt;p&gt;One route is the raw, low-level route. If Linux shared libraries are already
mapped into the process, you can go hunting through loaded ELF metadata.
The post walks through finding the loaded libc image, finding &lt;code&gt;PT_DYNAMIC&lt;&#x2F;code&gt;,
reading dynamic table entries such as &lt;code&gt;DT_SYMTAB&lt;&#x2F;code&gt;, &lt;code&gt;DT_STRTAB&lt;&#x2F;code&gt;,
and &lt;code&gt;DT_GNU_HASH&lt;&#x2F;code&gt;, then manually locating &lt;code&gt;dlsym&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;That is already a good ELF lesson: section headers are mostly a
link-time and tooling convenience. The runtime loader cares about program
headers and dynamic metadata. When inspecting a loaded image, file
offsets are not the main thing anymore. Virtual addresses are.&lt;&#x2F;p&gt;
&lt;p&gt;But finding the function address is not enough. The post has to call
the Linuxfunction with the System V x86-64 calling convention, even
though the caller is still a Windows program. A function pointer value
by itself is just an address. The ABI tells you how to enter that
address without corrupting the conversation.&lt;&#x2F;p&gt;
&lt;p&gt;That matters on x86-64 because Windows and System V use different
calling conventions. The first few integer or pointer arguments
live in different registers, stack rules differ, and a compiler needs
to know which contract it is targeting. In Rust terms, this is the
difference between tagging a function as something like
&lt;code&gt;extern &quot;system&quot;&lt;&#x2F;code&gt; for the Windows side and &lt;code&gt;extern &quot;sysv64&quot;&lt;&#x2F;code&gt; for
the Linux side.&lt;&#x2F;p&gt;
&lt;p&gt;The cleaner route in the article is Wine&#x27;s &lt;code&gt;unixlib&lt;&#x2F;code&gt; mechanism.
Instead of freely mixing Windows and Linux code inside one module,
Wine pairs a PE DLL with a normal native ELF &lt;code&gt;.so&lt;&#x2F;code&gt;. The PE side
asks Wine for a handle to the native side, then calls
&lt;code&gt;__wine_unix_call_dispatcher&lt;&#x2F;code&gt; with:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;a unixlib handle;&lt;&#x2F;li&gt;
&lt;li&gt;a numeric function index;&lt;&#x2F;li&gt;
&lt;li&gt;one pointer-sized argument.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The ELF side exports a known data symbol, &lt;code&gt;__wine_unix_call_funcs&lt;&#x2F;code&gt;,
which is an array of function pointers. Each function has the same
simple shape: one pointer argument, one 32-bit status result.
Complex arguments get packed behind the pointer.&lt;&#x2F;p&gt;
&lt;p&gt;This is the part I like most: unixlib makes the ABI bridge boring
on purpose. The dispatcher can bridge between the Windows ABI
and the System V ABI because the callable surface has been reduced
to one uniform function shape.&lt;&#x2F;p&gt;
&lt;p&gt;That is a general systems trick. When the boundary is dangerous,
make the shape of the boundary small.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;ELF, the Container&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;ELF is the file format in the middle of this story. It can
describe executable images, relocatable object files, shared
objects, symbols, relocation records, loadable segments,
interpreter paths, dynamic linking data, notes, and more.&lt;&#x2F;p&gt;
&lt;p&gt;An ELF file can say:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;I am ELF64&quot;;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;I target x86-64&quot;;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;load this segment at this virtual address&quot;;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;this is a relocation against this symbol&quot;;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;this dynamic table points to these runtime structures&quot;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It does not, by itself, tell you that a language&#x27;s &lt;code&gt;Text&lt;&#x2F;code&gt;
value is a NUL-terminated UTF-8 pointer. It does not tell
you that a return value is split between a payload register
and a tag register. It does not tell you whether an object
file is safe to link with another object file from the
same language.&lt;&#x2F;p&gt;
&lt;p&gt;Those are ABI choices layered on top of the object format.&lt;&#x2F;p&gt;
&lt;p&gt;Wine&#x27;s unixlib works because it uses ELF for the Linux side,
PE for the Windows side, and a deliberately tiny ABI bridge
between them. &lt;code&gt;0x0&lt;&#x2F;code&gt; is interesting for the same reason: it
treats ELF as the serialization format, then defines a small
language ABI on top of it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What 0x0 Actually Manages&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;0x0&lt;&#x2F;code&gt; is a symbolic, Lisp-like, pure-functional language kernel
with a self-hosted compiler chain. The repository has several
native artifact paths:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;direct ELF64&#x2F;x86-64 executables;&lt;&#x2F;li&gt;
&lt;li&gt;ELF64 relocatable objects;&lt;&#x2F;li&gt;
&lt;li&gt;archives;&lt;&#x2F;li&gt;
&lt;li&gt;linked executables;&lt;&#x2F;li&gt;
&lt;li&gt;compatibility C and GAS paths used for comparison and recovery.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The important thing is that the ABI is not left as an implied
property of the current compiler. The repository writes it down
and checks it.&lt;&#x2F;p&gt;
&lt;p&gt;The ABI guide says ABI version &lt;code&gt;0.1&lt;&#x2F;code&gt; is Linux x86-64 only. It
uses ELF64, little-endian encoding, and an exact marker:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0x0 ABI 0.1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Direct ELF binaries append that marker as a NUL-terminated
string. Relocatable objects carry it in &lt;code&gt;.note.0x0.abi&lt;&#x2F;code&gt;. The
linker rejects inputs with a different marker and appends
the accepted marker to linked output.&lt;&#x2F;p&gt;
&lt;p&gt;That marker is doing the same kind of work as the unixlib
exported symbol array, but at a different layer. It is a
cheap, inspectable way to say: this artifact claims to speak
this binary contract.&lt;&#x2F;p&gt;
&lt;p&gt;The current runtime value ABI is intentionally small:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;payload: rax&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tag:     r15&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Current direct-ELF tags are:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0 = Unit &#x2F; nil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1 = I64 or Bool payload&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2 = NUL-terminated UTF-8 Text pointer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3 = cons&#x2F;list pointer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Function returns use &lt;code&gt;rax&lt;&#x2F;code&gt; and &lt;code&gt;r15&lt;&#x2F;code&gt;. Function arguments
use paired payload and tag registers for up to six arguments.
Payloads go through the normal x86-64 argument registers:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;arg0 rdi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;arg1 rsi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;arg2 rdx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;arg3 rcx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;arg4 r8&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;arg5 r9&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Tags use another register set:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;arg0 r10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;arg1 r11&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;arg2 r12&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;arg3 r13&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;arg4 r14&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;arg5 r15&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There is no vague &quot;and then more arguments go somewhere&quot;
clause in ABI &lt;code&gt;0.1&lt;&#x2F;code&gt;. More than six arguments are rejected
by the current direct ELF path. That is a good thing.
A small ABI with a clear failure mode is better than a
larger ABI that exists only as compiler behavior nobody
has written down yet.&lt;&#x2F;p&gt;
&lt;p&gt;Text values are NUL-terminated UTF-8. Lists are cons
cells. A cons node is a 24-byte record:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;offset 0  = car payload&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;offset 8  = car tag&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;offset 16 = cdr payload&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Allocation in the direct ELF runtime is process-lifetime
allocation backed by Linux syscalls such as &lt;code&gt;mmap&lt;&#x2F;code&gt;.
There is no ABI &lt;code&gt;0.1&lt;&#x2F;code&gt; garbage collector hiding behind the
scenes. Again, that limitation is useful because it is
explicit.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Direct ELF: Writing The Process Image&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;One of the more satisfying parts of &lt;code&gt;0x0&lt;&#x2F;code&gt; is that direct
ELF output is literal. The compiler emits ELF64&#x2F;x86-64
bytes as hex text, then the wrapper turns that hex into
an executable file.&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;code&gt;compiler2&#x2F;elf-runtime.0x0&lt;&#x2F;code&gt;, the ELF helper writes the
ELF magic bytes, &lt;code&gt;ET_EXEC&lt;&#x2F;code&gt;, machine &lt;code&gt;x86-64&lt;&#x2F;code&gt;, an entry
point, one program header, and one &lt;code&gt;PT_LOAD&lt;&#x2F;code&gt; image.
The compatibility compiler has the same spirit: comments in
&lt;code&gt;compiler&#x2F;compat-main.0x0&lt;&#x2F;code&gt; say the backend writes a single
&lt;code&gt;PT_LOAD&lt;&#x2F;code&gt; ELF image and serializes little-endian header
fields as hex strings because the seed and compiler paths
pass artifacts as text.&lt;&#x2F;p&gt;
&lt;p&gt;That sounds primitive until you remember what an
executable needs to be at this stage. For the direct path,
&lt;code&gt;0x0&lt;&#x2F;code&gt; does not need a general-purpose linker. It needs a
deterministic process image for the language slice it supports.&lt;&#x2F;p&gt;
&lt;p&gt;The startup code is also part of the ABI. The direct ELF
startup initializes the runtime arena, preserves process
metadata for &lt;code&gt;argv&lt;&#x2F;code&gt; and &lt;code&gt;env&lt;&#x2F;code&gt;, calls &lt;code&gt;main&lt;&#x2F;code&gt;, and prints
the supported result types. Compiler artifacts use a different
wrapper: they read source and output paths from process
arguments, compile, then write the output file.&lt;&#x2F;p&gt;
&lt;p&gt;This is another place where API and ABI split apart. The
user writes a &lt;code&gt;main&lt;&#x2F;code&gt; function. The emitted executable has
a process entry point, stack assumptions, syscall snippets,
runtime arena initialization, and result-printing behavior.
The ABI is the glue between those layers.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Object Files And The Linker: Refusing To Guess&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The object path is where &lt;code&gt;0x0&lt;&#x2F;code&gt; starts looking more like a
traditional native toolchain. It emits ELF64 &lt;code&gt;ET_REL&lt;&#x2F;code&gt;
objects and links them into Linux ELF64 executables.&lt;&#x2F;p&gt;
&lt;p&gt;The interesting bit is that &lt;code&gt;zero-link&lt;&#x2F;code&gt; is not just a
wrapper around &lt;code&gt;ld&lt;&#x2F;code&gt;. It  reads ELF section and symbol
tables itself and writes the executable itself. The current
linker accepts the compiler&#x27;s object slice, resolves
symbols, applies supported relocations, lays out &lt;code&gt;.text&lt;&#x2F;code&gt;,
&lt;code&gt;.rodata&lt;&#x2F;code&gt;, &lt;code&gt;.data&lt;&#x2F;code&gt;, and &lt;code&gt;.bss&lt;&#x2F;code&gt;, and writes separate load
segments for executable and writable data.&lt;&#x2F;p&gt;
&lt;p&gt;The supported relocation set is explicit. The diagnostics
are explicit. The ABI marker check is explicit.&lt;&#x2F;p&gt;
&lt;p&gt;For example, objects with the wrong ABI marker are not
&quot;probably fine&quot;. They are rejected with an ABI mismatch
diagnostic. The tests mutate a deterministic object from
&lt;code&gt;0x0 ABI 0.1&lt;&#x2F;code&gt; to &lt;code&gt;0x0 ABI 9.9&lt;&#x2F;code&gt; and require the linker to
refuse it.&lt;&#x2F;p&gt;
&lt;p&gt;That is the difference between a binary format and a managed
ABI. ELF lets you put the bits somewhere. The toolchain
policy decides which bits are allowed to cross the boundary.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;ABI As Release Evidence&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The part I appreciate most in &lt;code&gt;0x0&lt;&#x2F;code&gt; is the amount of ABI
state that lives in plain data files:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;abi&#x2F;VERSION&lt;&#x2F;code&gt;;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;abi&#x2F;layout-goldens.tsv&lt;&#x2F;code&gt;;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;abi&#x2F;value-layouts.tsv&lt;&#x2F;code&gt;;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;abi&#x2F;backend-contract-matrix.tsv&lt;&#x2F;code&gt;;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;abi&#x2F;diagnostic-contracts.tsv&lt;&#x2F;code&gt;;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;release&#x2F;abi-contract-evidence.tsv&lt;&#x2F;code&gt;;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;compat&#x2F;abi-matrix.tsv&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The value layout schema separates executable&#x2F;object
ABI &lt;code&gt;0.1&lt;&#x2F;code&gt; from ABI v1 value layout families. That
distinction matters. The executable marker says whether
artifacts can link and run together. The value layout
schema says how language values such as &lt;code&gt;Option&lt;&#x2F;code&gt;,
&lt;code&gt;Result&lt;&#x2F;code&gt;, &lt;code&gt;Map&lt;&#x2F;code&gt;, &lt;code&gt;Bytes&lt;&#x2F;code&gt;, &lt;code&gt;Error&lt;&#x2F;code&gt;, paths, handles,
actors, sockets, closures, and host buffers are
represented when they cross runtime boundaries.&lt;&#x2F;p&gt;
&lt;p&gt;Those two ideas are related, but they are not the same.
A project that merges them too early will eventually
have to answer painful questions like: did this change
break object compatibility, source compatibility,
runtime value compatibility, or only one backend&#x27;s
implementation detail?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;0x0&lt;&#x2F;code&gt;&#x27;s answer is to make the rows separate and then
gate them:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;make abi-check&lt;&#x2F;code&gt; checks released artifacts and ABI
examples&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;make abi-layout-check&lt;&#x2F;code&gt; checks the required layout
schema and docs&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;make abi-v1-layout-check&lt;&#x2F;code&gt; checks promoted core value
layouts&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;make abi-contract-hardening-check&lt;&#x2F;code&gt; checks the broader
ABI evidence&lt;&#x2F;li&gt;
&lt;li&gt;linker and object tests check marker handling,
relocations, symbol resolution, diagnostics, and
output layout.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The tests are not just testing &quot;does the program print 42&quot;.
They are testing whether the artifacts still speak the
same binary language.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The Lesson&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The Wine article is interesting because it shows how thin
the wall between &quot;Windows process&quot; and &quot;Linux process&quot;
can be. The wall is the ABI.&lt;&#x2F;p&gt;
&lt;p&gt;The unixlib approach says: make the wall narrow and
well-shaped. Use a PE side, a normal ELF side, a known
exported function array, a dispatcher, one pointer
argument, and one status result.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;0x0&lt;&#x2F;code&gt; is applying the same kind of discipline to its own
compiler outputs. It does not treat &quot;ELF&quot; as a magic word
that makes binaries real. It defines:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the target;&lt;&#x2F;li&gt;
&lt;li&gt;the marker;&lt;&#x2F;li&gt;
&lt;li&gt;the value representation;&lt;&#x2F;li&gt;
&lt;li&gt;the call registers;&lt;&#x2F;li&gt;
&lt;li&gt;the stack discipline;&lt;&#x2F;li&gt;
&lt;li&gt;the object sections;&lt;&#x2F;li&gt;
&lt;li&gt;the supported relocations;&lt;&#x2F;li&gt;
&lt;li&gt;the linker behavior;&lt;&#x2F;li&gt;
&lt;li&gt;the diagnostics;&lt;&#x2F;li&gt;
&lt;li&gt;the release evidence.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is what &quot;managing ABI&quot; looks like in practice. You
keep the boundary small, stamp the boundary into the
artifact, and make every tool that crosses it prove
that it understands the stamp.&lt;&#x2F;p&gt;
&lt;p&gt;Maybe the most useful mental model is this:&lt;&#x2F;p&gt;
&lt;p&gt;ELF is the envelope. ABI is the language inside
the envelope.&lt;&#x2F;p&gt;
&lt;p&gt;If the language is underspecified, two tools can both
produce perfectly valid ELF and still fail to understand
each other. If the ABI is explicit, the tools can be
small, strict, and boring in the best possible way.&lt;&#x2F;p&gt;
&lt;p&gt;That is the lesson I want to keep from both Wine and &lt;code&gt;0x0&lt;&#x2F;code&gt;:
the hard part is not always producing bytes. The hard part
is deciding which bytes are a promise.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Sources And Notes&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;ArcaneNibble, &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;arcanenibble.com&#x2F;how-to-call-linux-code-from-a-wine-process.html&quot;&gt;&quot;How to call Linux code from a Wine process&quot;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;0x0&lt;&#x2F;code&gt; repository files inspected while writing this: &lt;code&gt;README.md&lt;&#x2F;code&gt;,
&lt;code&gt;docs&#x2F;abi.md&lt;&#x2F;code&gt;, &lt;code&gt;docs&#x2F;abi-value-layouts.md&lt;&#x2F;code&gt;, &lt;code&gt;docs&#x2F;compiler.md&lt;&#x2F;code&gt;,
&lt;code&gt;docs&#x2F;linker.md&lt;&#x2F;code&gt;, &lt;code&gt;docs&#x2F;native-toolchain.md&lt;&#x2F;code&gt;, &lt;code&gt;compiler2&#x2F;elf-runtime.0x0&lt;&#x2F;code&gt;,
&lt;code&gt;compiler2&#x2F;object-format.0x0&lt;&#x2F;code&gt;, &lt;code&gt;compiler&#x2F;compat-main.0x0&lt;&#x2F;code&gt;,
&lt;code&gt;tools&#x2F;zero-link.py&lt;&#x2F;code&gt;, &lt;code&gt;tools&#x2F;zero-elf-info.py&lt;&#x2F;code&gt;, and ABI&#x2F;linker tests under
&lt;code&gt;tests&#x2F;&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Glossary&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;ABI: Application Binary Interface. The binary-level contract
for calls, values, registers, stack layout, symbols, object
files, and runtime ownership.&lt;&#x2F;p&gt;
&lt;p&gt;API: Application Programming Interface. The source-level
interface a programmer uses, such as a function name,
parameters, and documented behavior.&lt;&#x2F;p&gt;
&lt;p&gt;ELF: Executable and Linkable Format. The common binary file
format for Linux executables, object files, shared libraries,
segments, sections, symbols, and relocations.&lt;&#x2F;p&gt;
&lt;p&gt;PE: Portable Executable. The Windows executable and DLL
file format.&lt;&#x2F;p&gt;
&lt;p&gt;DLL: Dynamic Link Library. A Windows shared library.&lt;&#x2F;p&gt;
&lt;p&gt;SO: Shared Object. A Unix&#x2F;Linux shared library, usually
ending in &lt;code&gt;.so&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;FFI: Foreign Function Interface. A way for code written for
one language or runtime to call code written for another.&lt;&#x2F;p&gt;
&lt;p&gt;GAS: GNU Assembler. The assembler syntax&#x2F;tooling path used
by the compatibility object backend.&lt;&#x2F;p&gt;
&lt;p&gt;SysV: System V. In this post, shorthand for the System V
x86-64 ABI used by Linux and other Unix-like systems
on x86-64.&lt;&#x2F;p&gt;
&lt;p&gt;WinAPI: Windows API. The operating-system API exposed
by Windows.&lt;&#x2F;p&gt;
&lt;p&gt;WOW64: Windows-on-Windows 64-bit. The Windows subsystem
for running 32-bit Windows code on 64-bit Windows; Wine
has analogous concerns for 32-bit-on-64-bit support.&lt;&#x2F;p&gt;
&lt;p&gt;libc: The C standard library implementation used by a
Unix-like system, often also exposing POSIX and
Linux-specific functions.&lt;&#x2F;p&gt;
&lt;p&gt;POSIX: Portable Operating System Interface. A family of
Unix-like operating system API standards.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;mmap&lt;&#x2F;code&gt;: A Unix&#x2F;Linux system call used to map memory
into a process address space.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;DT_*&lt;&#x2F;code&gt;: ELF dynamic table tags, such as &lt;code&gt;DT_SYMTAB&lt;&#x2F;code&gt;
and &lt;code&gt;DT_STRTAB&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;PT_*&lt;&#x2F;code&gt;: ELF program header types, such as &lt;code&gt;PT_LOAD&lt;&#x2F;code&gt;
and &lt;code&gt;PT_DYNAMIC&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;ET_*&lt;&#x2F;code&gt;: ELF file types, such as &lt;code&gt;ET_EXEC&lt;&#x2F;code&gt; and &lt;code&gt;ET_REL&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;PT_LOAD&lt;&#x2F;code&gt;: An ELF program header type telling the loader
to map a segment into memory.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;PT_DYNAMIC&lt;&#x2F;code&gt;: An ELF program header type pointing to
dynamic linking metadata.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;ET_EXEC&lt;&#x2F;code&gt;: An ELF file type for executable files.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;ET_REL&lt;&#x2F;code&gt;: An ELF file type for relocatable object
files.&lt;&#x2F;p&gt;
&lt;p&gt;PLT: Procedure Linkage Table. ELF machinery commonly used
for calls that are resolved through dynamic linking.&lt;&#x2F;p&gt;
&lt;p&gt;GOT: Global Offset Table. ELF machinery commonly used
to hold addresses needed by position-independent and
dynamically linked code.&lt;&#x2F;p&gt;
&lt;p&gt;NUL: The zero byte, often used to terminate C strings.&lt;&#x2F;p&gt;
&lt;p&gt;UTF-8: Unicode Transformation Format 8-bit. A byte
encoding for Unicode text.&lt;&#x2F;p&gt;
&lt;p&gt;OISA: The intermediate instruction set used by &lt;code&gt;0x0&lt;&#x2F;code&gt;
in its compiler pipeline.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>0x0, Technically</title>
		<published>2026-06-21T00:00:00+00:00</published>
		<updated>2026-06-21T00:00:00+00:00</updated>
		<link rel="alternate" type="text/html" href="https://idunnowhatiamdoing.engineering/posts/0x0-technically/"/>
		<id>https://idunnowhatiamdoing.engineering/posts/0x0-technically/</id>
    
		<content type="html" xml:base="https://idunnowhatiamdoing.engineering/posts/0x0-technically/">&lt;p&gt;Technically as I see it.&lt;&#x2F;p&gt;
&lt;p&gt;The language looks like a Lisp:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code zero-x-zero&quot;&gt;&lt;code data-lang=&quot;0x0&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;;;; A source contract plus a pure effect boundary.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;⊙&lt;&#x2F;span&gt; examples.add&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ƒ&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function&quot;&gt;add&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;  &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;∷&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;→&lt;&#x2F;span&gt; &lt;span class=&quot;z-type&quot;&gt;I64&lt;&#x2F;span&gt; &lt;span class=&quot;z-type&quot;&gt;I64&lt;&#x2F;span&gt; &lt;span class=&quot;z-type&quot;&gt;I64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;  &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;cap&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant&quot;&gt;pure&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;  &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;doc&lt;&#x2F;span&gt; &lt;span class=&quot;z-string&quot;&gt;&quot;Return the sum of two integers.&quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;  &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;a b&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;  &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;+&lt;&#x2F;span&gt; a b&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ƒ&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function&quot;&gt;main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;  &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;∷&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;→&lt;&#x2F;span&gt; &lt;span class=&quot;z-type&quot;&gt;Unit&lt;&#x2F;span&gt; &lt;span class=&quot;z-type&quot;&gt;I64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;  &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;cap&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant&quot;&gt;pure&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;  &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;_&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;  &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;add &lt;span class=&quot;z-constant z-numeric&quot;&gt;20&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric&quot;&gt;22&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The colors here follow the same token families as the
project&#x27;s editor support: comments, strings, numbers,
delimiters, keywords, constants, types, functions,
and operators.&lt;&#x2F;p&gt;
&lt;p&gt;0x0 is a small symbolic functional kernel whose
compiler is written in 0x0 from the beginning.
The assembly seed is kept around as a
recovery&#x2F;audit path. The normal point of gravity
is &lt;code&gt;compiler&#x2F;main.0x0&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The project:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;compiler&#x2F;main.0x0 -&amp;gt; stage1.oisa&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stage1.oisa      -&amp;gt; stage2.oisa&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stage2.oisa      -&amp;gt; stage3.oisa&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stage2.oisa == stage3.oisa&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That comparison is the self-hosting gate.
If stage 2 and stage 3 disagree,
the compiler is not actually preserving itself.&lt;&#x2F;p&gt;
&lt;p&gt;That is the part I like.&lt;&#x2F;p&gt;
&lt;p&gt;0x0 starts with the parts almost aggressively:
bootstrap boundary, compiler succession, ABI notes,
object metadata, linker diagnostics, release
hashes, and compatibility gates.&lt;&#x2F;p&gt;
&lt;p&gt;A file is a sequence of parenthesized forms.
&lt;code&gt;(⊙ name)&lt;&#x2F;code&gt; declares the module.
&lt;code&gt;(ƒ name ...)&lt;&#x2F;code&gt; declares a function.
&lt;code&gt;∷&lt;&#x2F;code&gt; declares a checked source contract.
&lt;code&gt;cap&lt;&#x2F;code&gt; declares what kind of effects the function
is allowed to reach.
&lt;code&gt;doc&lt;&#x2F;code&gt; is source metadata for generated API docs.
&lt;code&gt;≔&lt;&#x2F;code&gt; introduces local bindings.
&lt;code&gt;if&lt;&#x2F;code&gt; and &lt;code&gt;do&lt;&#x2F;code&gt; are the control surface.&lt;&#x2F;p&gt;
&lt;p&gt;The current value world is:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;I64&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Text&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Bool&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Unit&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;cons-style lists&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The current builtin world is useful but still small:
arithmetic, comparison, list operations,
text operations, stdin&#x2F;stdout, argv&#x2F;env,
file read&#x2F;write, &lt;code&gt;print&lt;&#x2F;code&gt;, and &lt;code&gt;panic&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The type checker rejects malformed function shapes,
duplicate declarations, unbound symbols,
call arity errors, builtin arity errors,
obvious concrete type mismatches, bad &lt;code&gt;if&lt;&#x2F;code&gt;
conditions when known, and pure&#x2F;effect boundary
violations.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;unannotated functions default to &lt;code&gt;io&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;(cap pure)&lt;&#x2F;code&gt; functions may call pure functions
and pure builtins&lt;&#x2F;li&gt;
&lt;li&gt;pure functions cannot call &lt;code&gt;read-file&lt;&#x2F;code&gt;,
&lt;code&gt;write-file&lt;&#x2F;code&gt;, &lt;code&gt;read-stdin&lt;&#x2F;code&gt;, &lt;code&gt;argv&lt;&#x2F;code&gt;, &lt;code&gt;env&lt;&#x2F;code&gt;, &lt;code&gt;print&lt;&#x2F;code&gt;,
&lt;code&gt;panic&lt;&#x2F;code&gt;, or non-pure user functions&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Local packages are manifest and lockfile backed:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code zero-x-zero&quot;&gt;&lt;code data-lang=&quot;0x0&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;;;; Local package imports resolve through 0x0.lock.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;⊙&lt;&#x2F;span&gt; examples.core_data&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;↥&lt;&#x2F;span&gt; &lt;span class=&quot;z-string&quot;&gt;&quot;pkg:core-map&quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;↥&lt;&#x2F;span&gt; &lt;span class=&quot;z-string&quot;&gt;&quot;pkg:core-json&quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;↥&lt;&#x2F;span&gt; &lt;span class=&quot;z-string&quot;&gt;&quot;pkg:core-result&quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ƒ&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function&quot;&gt;main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;  &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;∷&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;→&lt;&#x2F;span&gt; &lt;span class=&quot;z-type&quot;&gt;Unit&lt;&#x2F;span&gt; &lt;span class=&quot;z-type&quot;&gt;I64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;  &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;_&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;  &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;≔&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;m &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;map-put&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;map-empty&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-string&quot;&gt;&quot;base&quot;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric&quot;&gt;35&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;      &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;base &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;option-value-or&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;map-get&lt;&#x2F;span&gt; m &lt;span class=&quot;z-string&quot;&gt;&quot;base&quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;      &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;from-json &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;option-value-or&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;json-get-int&lt;&#x2F;span&gt; &lt;span class=&quot;z-string&quot;&gt;&quot;{\&quot;n\&quot;:7}&quot;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string&quot;&gt;&quot;n&quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;    &lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;+&lt;&#x2F;span&gt; base from-json&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The package layer is a local manifest plus a checked
lockfile. That is still useful because it gives
imports a stable name before the project grows a
registry around them.&lt;&#x2F;p&gt;
&lt;p&gt;The direct ELF ABI uses a payload plus a tag:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rax = value payload&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;r15 = value tag&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0 = Unit &#x2F; nil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1 = I64 or Bool&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2 = NUL-terminated UTF-8 Text pointer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3 = cons&#x2F;list pointer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Direct ELF output is Linux x86-64 today. It can emit
integer&#x2F;control-flow code, calls, recursion, locals,
text operations, list operations, file&#x2F;stdin&#x2F;stdout
operations, and compiler artifacts. There is also a
C compatibility path, a GAS&#x2F;object compatibility path,
a direct object writer slice, an archive writer,
a linker, and an optimizer with small verified passes.&lt;&#x2F;p&gt;
&lt;p&gt;It owns enough of the pipeline to make release
engineering part of the language design:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;source parser and semantic validator&lt;&#x2F;li&gt;
&lt;li&gt;OISA backend for self-hosting&lt;&#x2F;li&gt;
&lt;li&gt;C compatibility backend&lt;&#x2F;li&gt;
&lt;li&gt;direct ELF64&#x2F;x86-64 executable backend&lt;&#x2F;li&gt;
&lt;li&gt;object&#x2F;archive&#x2F;linker slices&lt;&#x2F;li&gt;
&lt;li&gt;ABI marker checks&lt;&#x2F;li&gt;
&lt;li&gt;optimizer pass registry&lt;&#x2F;li&gt;
&lt;li&gt;diagnostics classes&lt;&#x2F;li&gt;
&lt;li&gt;generated API docs from source annotations&lt;&#x2F;li&gt;
&lt;li&gt;independent compiler work for cross-checking&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So what is 0x0, technically?&lt;&#x2F;p&gt;
&lt;p&gt;It is a self-hosting language kernel where the
compiler trust path is the main feature. It is a
small source language wrapped around an auditable
native toolchain experiment. It is not &lt;em&gt;yet&lt;&#x2F;em&gt; mature
enough yet to be your batteries included app stack.&lt;&#x2F;p&gt;
&lt;p&gt;That is the kind of weird I respect.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>jmp0x1b</title>
		<published>2026-06-13T00:00:00+00:00</published>
		<updated>2026-06-13T00:00:00+00:00</updated>
		<link rel="alternate" type="text/html" href="https://idunnowhatiamdoing.engineering/posts/jmp0x1b/"/>
		<id>https://idunnowhatiamdoing.engineering/posts/jmp0x1b/</id>
    
		<content type="html" xml:base="https://idunnowhatiamdoing.engineering/posts/jmp0x1b/">&lt;p&gt;I decided to focus all my energy on my desire to become a
galactic civilization.&lt;&#x2F;p&gt;
&lt;p&gt;Yes, it&#x27;s stupid and naive. And you are right to believe
that. Only a fool would like to help me with such an
impossible and naive dream.&lt;&#x2F;p&gt;
&lt;p&gt;I just don&#x27;t care anymore about the human experiment.&lt;&#x2F;p&gt;
&lt;p&gt;I came down to Earth to have experiences and live by my
own sword. I have failed most of my life in doing that.&lt;&#x2F;p&gt;
&lt;p&gt;&#x27;Nuff.&lt;&#x2F;p&gt;
&lt;p&gt;I will die working on &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;jmp0x1b.com&quot;&gt;https:&#x2F;&#x2F;jmp0x1b.com&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;and I&#x27;m happy with that path. My path. My only path.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ll be writing about the engineering challenges.&lt;&#x2F;p&gt;
&lt;p&gt;If you care, come back and enjoy it.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Hardware Memory</title>
		<published>2025-10-19T00:00:00+00:00</published>
		<updated>2025-10-19T00:00:00+00:00</updated>
		<link rel="alternate" type="text/html" href="https://idunnowhatiamdoing.engineering/posts/memory/"/>
		<id>https://idunnowhatiamdoing.engineering/posts/memory/</id>
    
		<content type="html" xml:base="https://idunnowhatiamdoing.engineering/posts/memory/">&lt;p&gt;I recently binged Halt and Catch Fire &lt;strong&gt;again&lt;&#x2F;strong&gt;. The episode where they
reverse-engineered the BIOS took me right back to when I&#x27;d watch my dad with
his oscilloscopes like he was doing magic from another universe.
It got me thinking about chips and memory. I took a microprocessors class in
college, it was a blast.
For the first post on my new, new, new blog, I&#x27;m starting with &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;research.swtch.com&#x2F;hwmm&quot;&gt;hardware memory&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Memory&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Rust doesn&#x27;t magically remove the problem. What it &lt;em&gt;does&lt;&#x2F;em&gt; do is give you
unusually strong leverage: safe code is designed to avoid data races (which
Rust treats as Undefined Behavior), and when you need atomics, Rust exposes
the same fundamental ordering toolbox used by other systems languages.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;three contracts&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hardware contract&lt;&#x2F;strong&gt;: what CPUs may do.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Language contract&lt;&#x2F;strong&gt;: what the compiler may assume and reorder.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Type contract&lt;&#x2F;strong&gt;: what Rust will (and won&#x27;t) let you express safely.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Contract 1: Hardware does not promise as-written execution&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Russ Cox opens his hardware memory model series with the key punchline:
optimizations that were invisible in single-threaded programs become
&lt;em&gt;visible&lt;&#x2F;em&gt; with threads, and it depends becomes the default unless you have a
contract.&lt;&#x2F;p&gt;
&lt;p&gt;A classic litmus test is &lt;strong&gt;message passing&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Thread 1 # Thread 2
x = 1 r1 = y
y = 1 r2 = x&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Can Thread 2 observe &lt;code&gt;r1 = 1&lt;&#x2F;code&gt; but &lt;code&gt;r2 = 0&lt;&#x2F;code&gt;?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;On a sequentially consistent machine: &lt;strong&gt;no&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;On x86 TSO: &lt;strong&gt;no&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;On weaker hardware like ARM&#x2F;POWER: it can be &lt;strong&gt;yes&lt;&#x2F;strong&gt; without extra
barriers&#x2F;fences.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So even before we talk about compilers, &lt;em&gt;my writes become visible to other
cores in program order&lt;&#x2F;em&gt; is not a universal hardware law.
Another famous one is &lt;strong&gt;store buffering&lt;&#x2F;strong&gt; (a.k.a. store buffer &#x2F; write queue):&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Thread 1 # Thread 2
x = 1 y = 1
r1 = y r2 = x&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Can we end with &lt;code&gt;r1 = 0&lt;&#x2F;code&gt; and &lt;code&gt;r2 = 0&lt;&#x2F;code&gt;?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Sequentially consistent: &lt;strong&gt;no&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;x86 TSO: &lt;strong&gt;yes&lt;&#x2F;strong&gt; (both stores sit in per-core buffers; both reads miss them).&lt;&#x2F;li&gt;
&lt;li&gt;ARM&#x2F;POWER: &lt;strong&gt;yes&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If your brain is screaming &lt;em&gt;but that&#x27;s illegal&lt;&#x2F;em&gt;, good, your brain is sequentially
consistent. Your CPU is not required to be.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Contract 2: The language memory model is where compilers get permission&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Even if hardware were perfectly sequentially consistent, the compiler still wants
to reorder, eliminate, and fuse loads&#x2F;stores for speed. Those transformations
were &lt;em&gt;invisible&lt;&#x2F;em&gt; in single-threaded code. With threads, they become visible.&lt;&#x2F;p&gt;
&lt;p&gt;Language memory models generally converge on a pragmatic deal often summarized as:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;DRF-SC&lt;&#x2F;strong&gt;: &lt;em&gt;Data-race-free programs behave as if sequentially consistent.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Russ Cox describes that as a major goal in mainstream language memory models
(Java, C&#x2F;C++, Rust, etc.).&lt;&#x2F;p&gt;
&lt;p&gt;But: &lt;strong&gt;DRF-SC is a conditional promise&lt;&#x2F;strong&gt;. If you have a data race, the language
may give you anything from &lt;em&gt;we define a weak-but-sane behavior&lt;&#x2F;em&gt; (Java historically
tried) to &lt;em&gt;the program has no defined meaning&lt;&#x2F;em&gt; (C&#x2F;C++ land).
Rust lands firmly in the &lt;em&gt;no defined meaning&lt;&#x2F;em&gt; camp for data races.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Contract 3: Rust&#x27;s type system tries to prevent you from &lt;em&gt;writing&lt;&#x2F;em&gt; data races&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Rust&#x27;s unsafe book states it plainly:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;data race is Undefined Behavior&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;And safe Rust is designed to make data races impossible to express (mostly
through ownership&#x2F;borrowing; with &lt;code&gt;Send&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;Sync&lt;&#x2F;code&gt; controlling what can cross threads).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Important nuance:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Rust does &lt;strong&gt;not&lt;&#x2F;strong&gt; prevent &lt;em&gt;all&lt;&#x2F;em&gt; race conditions (logic races, lost updates,
timing bugs).&lt;&#x2F;li&gt;
&lt;li&gt;It targets &lt;strong&gt;data races&lt;&#x2F;strong&gt;: unsynchronized concurrent access where at least
one access is a write.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is why Rust concurrency often feels like:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;You don&#x27;t get to share mutable stuff unless you prove how you&#x27;re coordinating it.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;And the moment you &lt;em&gt;do&lt;&#x2F;em&gt; want to coordinate at a lower level (lock-free structures,
custom primitives), you end up using &lt;strong&gt;atomics&lt;&#x2F;strong&gt; (safe) or &lt;code&gt;unsafe&lt;&#x2F;code&gt; (very sharp).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Rust atomics: what they are actually for&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Atomics are not &lt;em&gt;faster mutexes&lt;&#x2F;em&gt;. They are the &lt;em&gt;vocabulary&lt;&#x2F;em&gt; used to build
synchronization: the tool that creates &lt;strong&gt;happens-before&lt;&#x2F;strong&gt; edges and constrains
reordering.&lt;&#x2F;p&gt;
&lt;p&gt;Rust&#x27;s atomic orderings (&lt;code&gt;Relaxed&lt;&#x2F;code&gt;, &lt;code&gt;Acquire&lt;&#x2F;code&gt;, &lt;code&gt;Release&lt;&#x2F;code&gt;, &lt;code&gt;AcqRel&lt;&#x2F;code&gt;, &lt;code&gt;SeqCst&lt;&#x2F;code&gt;) are
documented in &lt;code&gt;std::sync::atomic::Ordering&lt;&#x2F;code&gt;.
Here&#x27;s the practical mental model I recommend:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Relaxed&lt;&#x2F;code&gt;: atomicity without ordering&lt;&#x2F;strong&gt;
Good for counters, stats, &lt;em&gt;eventually consistent&lt;&#x2F;em&gt; observations.
It prevents torn reads&#x2F;writes of that atomic variable, but does not promise when
other memory becomes visible.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Release&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;Acquire&lt;&#x2F;code&gt;: publish–subscribe&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Writer: do regular work, then &lt;strong&gt;Release-store&lt;&#x2F;strong&gt; a flag.&lt;&#x2F;li&gt;
&lt;li&gt;Reader: &lt;strong&gt;Acquire-load&lt;&#x2F;strong&gt; the flag, then it can safely observe what was published.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Rust docs describe &lt;code&gt;Release&lt;&#x2F;code&gt; as making prior operations ordered before an &lt;code&gt;Acquire&lt;&#x2F;code&gt;
load that observes that value.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;SeqCst&lt;&#x2F;code&gt;: the &lt;em&gt;everyone agrees&lt;&#x2F;em&gt; mode&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Same synchronization power as Acquire&#x2F;Release, plus a single global order of all
&lt;code&gt;SeqCst&lt;&#x2F;code&gt; operations (simplifies reasoning; can cost more).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Example 1: A clean publish–subscribe in Rust (no &lt;code&gt;unsafe&lt;&#x2F;code&gt;)&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This example uses only atomics, so it stays fully safe. It shows the shape of
the pattern:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sync&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;atomic&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;AtomicBool&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; AtomicUsize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Ordering&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sync&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Arc&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;thread&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Shared&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    data&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; AtomicUsize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    ready&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; AtomicBool&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Arc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Shared&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        data&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; AtomicUsize&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        ready&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; AtomicBool&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; t1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        thread&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;move&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;store&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;42&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Ordering&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Relaxed&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ready&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;store&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Ordering&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Release&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; t2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        thread&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;move&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            while&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; !&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ready&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;load&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Ordering&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Acquire&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; v&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;load&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Ordering&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Relaxed&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;            assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;v&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 42&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    t1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    t2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The Release store on ready ensures the prior write to data becomes visible
to any thread that sees &lt;code&gt;ready == true&lt;&#x2F;code&gt; via an &lt;code&gt;Acquire&lt;&#x2F;code&gt; load.
Where I usually go wrong: I make ready relaxed too, and then the reader can
observe the flag without observing the published data on some
platforms&#x2F;optimizations, the exact &lt;em&gt;it depends&lt;&#x2F;em&gt; Russ warns about.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Example 2: Acquire&#x2F;Release is not global sequential consistency&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A spicy detail from the language-memory-model world: Acquire&#x2F;Release does
not impose a single total order across different memory locations.
Russ Cox shows the store-buffering litmus test remains possible under
C++11 acquire&#x2F;release atomics, even though it is disallowed under
sequentially consistent atomics.
That means: you can correctly synchronize publication on one atomic, and
still not get &lt;em&gt;whole-program sequential consistency&lt;&#x2F;em&gt; for free.
This is why SeqCst exists: sometimes you want fewer degrees of freedom for the
machine, because you want fewer degrees of freedom in your own head.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The unsafe cliff: memory ordering is only half the story&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Memory model can &lt;em&gt;be&lt;&#x2F;em&gt; two different beasts:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Concurrency ordering (atomics, fences, visibility)&lt;&#x2F;li&gt;
&lt;li&gt;Aliasing &amp;amp; provenance (what references mean; what the optimizer may assume)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Rust&#x27;s aliasing rules are why &lt;code&gt;&amp;amp;T&lt;&#x2F;code&gt; implies &lt;em&gt;not being mutated&lt;&#x2F;em&gt; and &lt;code&gt;&amp;amp;mut T&lt;&#x2F;code&gt;
implies &lt;em&gt;unique&lt;&#x2F;em&gt;. When you build interior mutability (like Cell, RefCell, Mutex),
Rust requires you to go through &lt;code&gt;UnsafeCell&amp;lt;T&amp;gt;&lt;&#x2F;code&gt;, it’s the sanctioned escape
hatch.
Key point from the UnsafeCell docs:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;UnsafeCell&lt;&#x2F;code&gt; relaxes the immutability guarantee behind &lt;code&gt;&amp;amp;T&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;but it does not make aliasing &lt;code&gt;&amp;amp;mut&lt;&#x2F;code&gt; references okay (uniqueness is still
required).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Researchers and the Rust unsafe-code community have proposed operational models
like Stacked Borrows and Tree Borrows to formalize which pointer uses are allowed
and which become UB.&lt;&#x2F;p&gt;
&lt;p&gt;If you write unsafe abstractions, this is the layer that decides whether your code
is &lt;em&gt;works on my machine&lt;&#x2F;em&gt; or &lt;em&gt;silently illegal&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;How to build confidence: Loom + Miri&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Loom is a concurrency testing tool that repeatedly runs your test while exploring
possible thread schedules under the C11-style memory model used for Rust atomics
in practice.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Great for: custom mutexes, channels, lock-free structures, tricky state machines.&lt;&#x2F;li&gt;
&lt;li&gt;Not great for: &lt;em&gt;just add Loom to everything&lt;&#x2F;em&gt; (it’s targeted, and can explode in complexity).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Miri interprets Rust and detects many classes of UB (out-of-bounds, use-after-free,
invalid aliasing patterns, etc.).&lt;&#x2F;p&gt;
&lt;p&gt;If your project has unsafe, running cargo miri test is a very direct &lt;em&gt;are we lying
to the compiler?&lt;&#x2F;em&gt; check.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;A tiny ordering cheat-sheet&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Just sharing read-only data across threads&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Prefer: Arc&lt;T&gt; + immutable data.&lt;&#x2F;li&gt;
&lt;li&gt;No atomics needed.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Shared mutable state&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Prefer: Mutex, RwLock, channels (higher-level synchronization).&lt;&#x2F;li&gt;
&lt;li&gt;Atomics only when you’re building primitives or chasing specific
perf needs.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Counters &#x2F; metrics&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Often: Relaxed.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Publish–subscribe &#x2F; “ready flag”&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Writer: Release store&lt;&#x2F;li&gt;
&lt;li&gt;Reader: Acquire load&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You want the simplest reasoning model&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Use: SeqCst (until profiling proves you need weaker).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The hardware wants speed. The compiler wants freedom. Our job is to
write down the constraints that make your program actually mean what
you think it means.&lt;&#x2F;p&gt;
&lt;p&gt;Rust helps by making &lt;em&gt;accidentally racy&lt;&#x2F;em&gt; code hard to express, and by
giving you the same atomic tools used to build the rest of the ecosystem.
The cost is that when you go low-level, you&#x27;re now negotiating with three
contracts at once: CPU, compiler, and Rust&#x27;s own rules.&lt;&#x2F;p&gt;
</content>
	</entry>
</feed>
