<h1 id="link-recording"><a rel="noopener" target="_blank" href="https://youtu.be/DBw7MHUTKnc">🔗 Recording</a></h1> <span id="continue-reading"></span><!--s--> <h2 id="iota-transpiling-llvm-to-a-high-level-language">Iota: Transpiling LLVM to a high-level language</h2> <!-- .slide: data-background-image="https://llvm.org/img/DragonFull.png" data-background-opacity="0.2" --> <!--s--> <h1 id="why">?!?!WHY!?!?</h1> <!-- .slide: data-background-image="https://cdn.pixabay.com/photo/2022/08/01/04/24/chicken-7357303_960_720.jpg" data-background-opacity="0.2" --> <!--s--> <h2 id="created-by-froggey-as-part-of-the-mezzano-project">Created by froggey as part of the Mezzano project</h2> <ul> <li>Demo 1: 2015</li> <li>Demo 5: 2020</li> <li>Latest Commit at time of writing: 2025-05-01</li> </ul> <!--s--> <h1 id="what-is-mezanno">What is <a rel="noopener" target="_blank" href="https://github.com/froggey/Mezzano">Mezanno</a>?</h1> <!--n--> <p>Mezzano is a high-level language operating system, meaning no ELF binaries, the only thing it runs is a given high-level language. But what if we wish to run something written for a conventional Unix system? I dunno, maybe DOOM!!! If it doesn’t run DOOM is it even a viable piece of tech?</p> <p><a rel="noopener" target="_blank" href="https://github.com/froggey/Mezzano/blob/master/doc/quickstart.md">Blinkenlights</a>:</p> <ul> <li><span style="color:green"><strong>Green</strong></span>: Disk read in progress</li> <li><span style="color:red"><strong>Red</strong></span>: Disk write in progress</li> <li><span style="color:purple"><strong>Purple</strong></span>: GC in progress</li> <li><span style="color:cyan"><strong>Cyan</strong></span>: Activity, system is not idle</li> <li><span style="color:yellow"><strong>Yellow</strong></span>: Snapshot in progress</li> <li><span style="color:brown"><strong>Brown</strong></span>: Page fault being serviced</li> <li><span style="color:lightgreen"><strong>Light Green</strong></span>: Network activity</li> </ul> <svg id="container" width="1010.453125" xmlns="http://www.w3.org/2000/svg" class="flowchart" height="269" viewBox="0 0 1010.453125 269" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#container{font-family:serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#container .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#container .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#container .error-icon{fill:#552222;}#container .error-text{fill:#552222;stroke:#552222;}#container .edge-thickness-normal{stroke-width:1px;}#container .edge-thickness-thick{stroke-width:3.5px;}#container .edge-pattern-solid{stroke-dasharray:0;}#container .edge-thickness-invisible{stroke-width:0;fill:none;}#container .edge-pattern-dashed{stroke-dasharray:3;}#container .edge-pattern-dotted{stroke-dasharray:2;}#container .marker{fill:#333333;stroke:#333333;}#container .marker.cross{stroke:#333333;}#container svg{font-family:serif;font-size:16px;}#container p{margin:0;}#container .label{font-family:serif;color:#333;}#container .cluster-label text{fill:#333;}#container .cluster-label span{color:#333;}#container .cluster-label span p{background-color:transparent;}#container .label text,#container span{fill:#333;color:#333;}#container .node rect,#container .node circle,#container .node ellipse,#container .node polygon,#container .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#container .rough-node .label text,#container .node .label text,#container .image-shape .label,#container .icon-shape .label{text-anchor:middle;}#container .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#container .rough-node .label,#container .node .label,#container .image-shape .label,#container .icon-shape .label{text-align:center;}#container .node.clickable{cursor:pointer;}#container .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#container .arrowheadPath{fill:#333333;}#container .edgePath .path{stroke:#333333;stroke-width:2.0px;}#container .flowchart-link{stroke:#333333;fill:none;}#container .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#container .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#container .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#container .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#container .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#container .cluster text{fill:#333;}#container .cluster span{color:#333;}#container div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#container .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#container rect.text{fill:none;stroke-width:0;}#container .icon-shape,#container .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#container .icon-shape p,#container .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#container .icon-shape rect,#container .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#container .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#container .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#container :root{--mermaid-font-family:serif;}</style><g><marker id="container_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"></path></marker><marker id="container_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"></path></marker><marker id="container_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"></circle></marker><marker id="container_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"></circle></marker><marker id="container_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"></path></marker><marker id="container_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"></path></marker><g class="root"><g class="clusters"><g class="cluster" id="subGraph0" data-look="classic"><rect style="" x="232.53125" y="121" width="769.921875" height="140"></rect><g class="cluster-label" transform="translate(572.7578125, 121)"><foreignObject width="89.46875" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Managed OS</p></span></div></foreignObject></g></g></g><g class="edgePaths"><path d="M182.531,199L186.698,199C190.865,199,199.198,199,207.531,199C215.865,199,224.198,199,241.061,199C257.924,199,283.318,199,296.014,199L308.711,199" id="L_HLC_SC_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_HLC_SC_0" data-points="W3sieCI6MTgyLjUzMTI1LCJ5IjoxOTl9LHsieCI6MjA3LjUzMTI1LCJ5IjoxOTl9LHsieCI6MjMyLjUzMTI1LCJ5IjoxOTl9LHsieCI6MzEyLjcxMDkzNzUsInkiOjE5OX1d" marker-end="url(#container_flowchart-v2-pointEnd)"></path><path d="M451.73,86L472.581,98.667C493.432,111.333,535.134,136.667,565.869,150.816C596.604,164.966,616.372,167.932,626.257,169.416L636.141,170.899" id="L_INS_AS_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_INS_AS_0" data-points="W3sieCI6NDUxLjczMDIzMDk3ODI2MDg2LCJ5Ijo4Nn0seyJ4Ijo1NzYuODM1OTM3NSwieSI6MTYyfSx7IngiOjYzNi4xNDA2MjUsInkiOjE3MC44OTg2ODI1OTQ2MTg3Mn1d" marker-end="url(#container_flowchart-v2-crossEnd)"></path><path d="M462.352,199L481.432,199C500.513,199,538.674,199,566.977,197.946C595.279,196.891,613.723,194.783,622.945,193.729L632.167,192.674" id="L_SC_AS_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_SC_AS_0" data-points="W3sieCI6NDYyLjM1MTU2MjUsInkiOjE5OX0seyJ4Ijo1NzYuODM1OTM3NSwieSI6MTk5fSx7IngiOjYzNi4xNDA2MjUsInkiOjE5Mi4yMjAwNTEzNTY0ODA5NX1d" marker-end="url(#container_flowchart-v2-pointEnd)"></path><path d="M797.438,183L805.789,183C814.141,183,830.844,183,846.88,183C862.917,183,878.286,183,885.971,183L893.656,183" id="L_AS_OS_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_AS_OS_0" data-points="W3sieCI6Nzk3LjQzNzUsInkiOjE4M30seyJ4Ijo4NDcuNTQ2ODc1LCJ5IjoxODN9LHsieCI6ODk3LjY1NjI1LCJ5IjoxODN9XQ==" marker-end="url(#container_flowchart-v2-pointEnd)"></path></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_HLC_SC_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_INS_AS_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(576.8359375, 199)"><g class="label" data-id="L_SC_AS_0" transform="translate(-34.3046875, -12)"><foreignObject width="68.609375" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>Compiled</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(847.546875, 183)"><g class="label" data-id="L_AS_OS_0" transform="translate(-25.109375, -12)"><foreignObject width="50.21875" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>Run By</p></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="flowchart-SC-0" transform="translate(387.53125, 199)"><rect class="basic label-container" style="" x="-74.8203125" y="-27" width="149.640625" height="54"></rect><g class="label" style="" transform="translate(-44.8203125, -12)"><rect></rect><foreignObject width="89.640625" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Source Code</p></span></div></foreignObject></g></g><g class="node default" id="flowchart-AS-1" transform="translate(716.7890625, 183)"><rect class="basic label-container" style="" x="-80.6484375" y="-27" width="161.296875" height="54"></rect><g class="label" style="" transform="translate(-50.6484375, -12)"><rect></rect><foreignObject width="101.296875" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Machine Code</p></span></div></foreignObject></g></g><g class="node default" id="flowchart-HLC-2" transform="translate(95.265625, 199)"><rect class="basic label-container" style="" x="-87.265625" y="-27" width="174.53125" height="54"></rect><g class="label" style="" transform="translate(-57.265625, -12)"><rect></rect><foreignObject width="114.53125" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>High-level Code</p></span></div></foreignObject></g></g><g class="node default" id="flowchart-INS-5" transform="translate(387.53125, 47)"><rect class="basic label-container" style="" x="-130" y="-39" width="260" height="78"></rect><g class="label" style="" transform="translate(-100, -24)"><rect></rect><foreignObject width="200" height="48"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Cannot be Inserted from the outside</p></span></div></foreignObject></g></g><g class="node default" id="flowchart-OS-10" transform="translate(937.5546875, 183)"><rect class="basic label-container" style="" x="-39.8984375" y="-27" width="79.796875" height="54"></rect><g class="label" style="" transform="translate(-9.8984375, -12)"><rect></rect><foreignObject width="19.796875" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>OS</p></span></div></foreignObject></g></g></g></g></g></svg> <p>Hope you can all compile mermaid in your heads… no? Well nevermind let me fetch the blackboard.</p> <p>Python to python OS</p> <!--s--> <h1 id="but-why">But why?</h1> <ul> <li>Easier to compile to</li> <li>Memory-safe</li> <li>High-level ABI</li> <li>Extremely cheap IPC <ul> <li>Global Address Space</li> </ul> </li> <li>Higher-level errors (conditions and segfaults)</li> <li>Safer???</li> </ul> <!--s--> <h1 id="iota">Iota</h1> <!--s--> <h2 id="what-is-an-instruction">What is an instruction?</h2> <!--s--> <pre><code class="language-llvm">%x = add i32 1, %y </code></pre> <!--s--> <h2 id="it-got-inputs">It got inputs</h2> <pre><code class="language-llvm">%x = add i32 >>1, %y<< </code></pre> <!--s--> <h2 id="it-got-an-output">It got an output</h2> <pre><code class="language-llvm">>>%x<< = add i32 1, %y </code></pre> <!--s--> <h2 id="it-got-types">It got types</h2> <pre><code class="language-llvm">%x = add >>i32<< 1, %y </code></pre> <!--s--> <h2 id="it-s-basically-a-function">??? It’s basically a function ???</h2> <p><code>@llvm.sqrt.f32 == math.sqrt</code></p> <!--s--> <p><img src="https://images.squarespace-cdn.com/content/v1/53ae3013e4b0a141bca21c9f/1409962221681-H8BI0BY0UE3GHE79A80L/close+enough.jpg" alt="Close Enough stick meme" /></p> <!--s--> <h1 id="not-really">Not really.</h1> <!--s--> <h1 id="but-still">But still</h1> <!--s--> <h1 id="iota-the-transpiler">Iota the transpiler</h1> <!--s--> <h3 id="c-llvm-bitcode-lisp">C ➢ LLVM bitcode ➢ Lisp</h3> <!--s--> <pre><code class="language-c">int zoo(int x, int y) { return x + y; } </code></pre> <pre><code class="language-llvm">define i32 @zoo(i32 %x, i32 %y) #0 { %add = add nsw i32 %y, %x ret i32 %add } </code></pre> <pre><code class="language-lisp">(define-llvm-function |zoo| (|x.0| |y.1|) (add.i32 |x.0| |y.1|)) </code></pre> <!--s--> <pre><code class="language-lisp" data-line-numbers="|1|3-4|5,7|6">(define-llvm-function |zoo| ((|x.0| |y.1|) :need-frame-pointer nil) (let () (declare (type (unsigned-byte 32) |x.0|) (type (unsigned-byte 32) |y.1|)) (block nil (tagbody (return (add.i32 |x.0| |y.1|)))))) </code></pre> <!--s--> <pre><code class="language-lisp">(defstruct (llvm-context (:constructor make-llvm-context-1)) (stack-pointer 0 :type (unsigned-byte 64)) (memory (error "memory not supplied") :type octet-vector) entry-point (setjmp-stack (make-array 8 :adjustable t :fill-pointer 0))) </code></pre> <!--s--> <h3 id="initial-memory">Initial memory</h3> <pre><code class="language-lisp">(defun make-context (&rest personality-initargs) (make-llvm-context 2097152 ;; data start #.(make-array 2320 :element-type '(unsigned-byte 8) :initial-contents '(0 9 32 0 0 0 0 0 56 0 32 0 56 0 32 72 101 108 108 111 ...)) '|_start|)) </code></pre> <!--s--> <h1 id="control-flow">Control flow</h1> <!--s--> <pre><code class="language-c">int fib(int n) { if (n <= 1) return 1; return n * fib(n - 1); } </code></pre> <!--s--> <pre><code class="language-llvm">define i32 @fib(i32 %n) #0 { entry: %retval = alloca i32, align 4 %n.addr = alloca i32, align 4 store i32 %n, i32* %n.addr, align 4 %0 = load i32, i32* %n.addr, align 4 %cmp = icmp sle i32 %0, 1 br i1 %cmp, label %if.then, label %if.end if.then: ; preds = %entry store i32 1, i32* %retval br label %return if.end: ; preds = %entry %1 = load i32, i32* %n.addr, align 4 %2 = load i32, i32* %n.addr, align 4 %sub = sub nsw i32 %2, 1 %call = call i32 @fib(i32 %sub) %mul = mul nsw i32 %1, %call store i32 %mul, i32* %retval br label %return return: ; preds = %if.end, %if.then %3 = load i32, i32* %retval ret i32 %3 } </code></pre> <!--s--> <pre><code class="language-lisp" data-line-numbers="|2|10,14,17,19|12,13|15">(define-llvm-function |fib| ((|n.0|) :need-frame-pointer t) (let ((|storemerge.11| 0)) (declare (type (unsigned-byte 32) |n.0|) (type (unsigned-byte 32) |storemerge.11|)) (block nil (tagbody (let* ((|n.addr2.5| (alloca 4))) (declare (type (unsigned-byte 32) |n.addr2.5|)) (store.i32 |n.0| |n.addr2.5|) (tagbody (if (icmp.slt.fused.i32 |n.0| 2) (progn (go |if.then.2|)) (progn (go |if.end.3|))) |if.then.2| (psetq |storemerge.11| 1) (go |return.4|) |return.4| (return |storemerge.11|) |if.end.3| (let* ((|%7| (load.i32 |n.addr2.5|))) (declare (type (unsigned-byte 32) |%7|)) (psetq |storemerge.11| (mul.i32 |%7| (call-direct |fib| (add.i32 |%7| 4294967295)))) (go |return.4|)))))))) </code></pre> <!--s--> <h2 id="runtime-implementation">Runtime implementation</h2> <!--s--> <h3 id="alloca">Alloca</h3> <pre><code class="language-lisp">(defmacro alloca (size) (incf size 15) (setf size (logand size (lognot 15))) `(decf (llvm-context-stack-pointer llvm-context) ,size)) </code></pre> <!--s--> <h3 id="typed-operations">Typed operations</h3> <pre><code class="language-lisp">(define-sized-op mul ((lhs rhs) size) `(* ,lhs ,rhs)) </code></pre> <p>Generates:</p> <ul> <li><code>mul.i32</code></li> <li><code>mul.i64</code></li> <li><code>mul.f32</code></li> <li><code>mul.f64</code></li> <li>…</li> </ul> <!--s--> <h2 id="even-fuller-program">Even fuller program!!!</h2> <h1 id="doom">DOOM</h1> <!--s--> <h2 id="discussion-points">Discussion points:</h2> <ul> <li> <p>GO uses <code>for</code> even for <code>while</code></p> </li> <li> <p>Even <code>if</code> is syntax sugar in Haskell</p> </li> <li> <p>Elixir removed <code>unless</code></p> <ul> <li><code>if</code> is often extended with an <code>else</code> later on</li> <li><code>unless ... else</code> is considered an anti-pattern</li> </ul> </li> <li> <p>Would <code>if</code> be replaced with <code>&&</code></p> </li> <li> <p><code>until</code> instead of <code>do ... while</code></p> </li> <li> <p><code>while</code> itself can be misunderstood as an <code>if</code></p> </li> <li> <p><code>linters</code> automatically folding <code>if (!cond)</code> to <code>unless (cond)</code></p> </li> <li> <p><code>Bools</code> should not be used in general</p> </li> <li> <p><code>x % y == 0</code> vs. <code>divisible_by(x, y)</code></p> </li> <li> <p><code>oddp</code>, <code>evenp</code>, <code>zerop</code></p> </li> <li> <p><a rel="noopener" target="_blank" href="https://dl.acm.org/doi/10.1145/3661167.3661180">Fun paper</a> on negations being the primary source of slow comprehension</p> </li> </ul> <!-- Local Variables: --> <!-- indent-tabs-mode: t --> <!-- End: -->