<?xml version="1.0" encoding="UTF-8" ?> <?xml-stylesheet href="./assets/rss.xsl" type="text/xsl"?> <rss version="2.0"> <channel> <title>Takashi Idobe</title> <link>https://takashiidobe.com</link> <description>Thoughts on Programming</description>
<item>
<title>Translating Intrinsics</title>
<pubDate>Thu, 03 Sep 2026 12:54:06 +0000</pubDate>
<guid>https://blog/translating-intrinsics.html</guid>
<description><![CDATA[<p>This is part of <a
href="https://github.com/takashiidobe/slate">Slate</a>, a C to Rust
translator! Take a look at the previous post here: <a
href="./switch-to-match.md">Switch to Match</a>.</p>
<p>Today’s topic is about intrinsics. Intrinsics are functions supplied
by a compiler that map to hardware instructions. These fall into two
buckets:</p>
<ol type="1">
<li><code>builtins</code></li>
</ol>
<p>For example, the function
<code>__builtin_popcount(unsigned int)</code> for GCC and Clang provide
a population count function. These lower to special “compiler
instructions”, e.g. <code>llvm.ctpop</code> for clang that are fast
pathed to special hardware instructions (e.g. <code>POPCNT</code> for
x86). Not all architectures have hardware instructions for every
builtin, so sometimes these will be emulated in software depending on
your target.</p>
<ol start="2" type="1">
<li>Hardware intrinsics</li>
</ol>
<p>For example, <code>_mm_popcnt_u32(unsigned int)</code> for x86 on
SSE4.2. This intrinsic looks like a function, and will lower to
<code>POPCNT</code> in asm.</p>
<p>We’ll focus on the second bucket today.</p>
<p>Slate provides architecture support for x86_64, ARM, and RISC-V in
its libc-shim. That means we also need to support intrinsics for those
architectures. Now a quick google search shows that there are ~10000
intrinsics for x86 and arm and much more for RISC-V.</p>
<p>If I were to write out every signature by hand, I probably wouldn’t
transcribe all the signatures before dying (of boredom). So we have to
have another approach.</p>
<p>Thankfully, the compiler authors and hardware manufacturers have us
covered.</p>
<h2 id="read-the-manual">Read the Manual</h2>
<p>Intel provides an xml file that you can parse for every intrinsic,
what its name is, its arguments, its return type, a doc string, what cpu
features it uses, what header file it belongs in, etc. ARM does
something similar, except in JSON, and RISC-V provides a python script
that generates all of its headers, because it has a lot more intrinsics
than either x86 or ARM.</p>
<p>You can use these to generate the header files themselves. In clang,
the way this is done is by parsing the manual files, and then generating
definitions in a DSL called <code>tablegen</code>. This is used all
through clang, and it is a somewhat C looking language that is used for
generating all kinds of things, include llvm instructions, Clang’s IR
(which we’ll get to another time)</p>
<p>How this flows through clang looks like this:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode txt"><code class="sourceCode default"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>┌─────────────────────────────┐</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>│ ISA manual                  │</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>│ (Arm ARM, RISC-V RVV spec,  │</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>│ Intel SDM)                  │</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>└──────────────┬──────────────┘</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>               │</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>               ▼</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>┌─────────────────────────────┐</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>│ hand-written TableGen       │</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>│ (arm_neon.td, arm_sve.td,   │</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>│ RISCVVectorBuiltins.td)     │</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>└──────────────┬──────────────┘</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>               │</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>               ▼</span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>┌─────────────────────────────┐</span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>│ clang-tblgen emitter        │</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>│ (NeonEmitter / SveEmitter / │</span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>│ RVV intrinsic emitter,      │</span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>│ `-gen-arm-neon` etc.)       │</span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>└──────────────┬──────────────┘</span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>               │</span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>               ▼</span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>┌─────────────────────────────┐</span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>│ generated C header          │</span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>│ (immintrin.h, arm_neon.h,   │</span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>│  arm_sve.h, riscv_vector.h) │</span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>│                             │</span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>└──────────────┬──────────────┘</span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>               │</span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>               ▼</span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a>┌─────────────────────────────┐</span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a>│ used by CGBuiltin.cpp       │</span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a>│ + Sema to map builtin call  │</span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a>│ -&gt; llvm.* intrinsic at      │</span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a>│ CIR/IR emission time        │</span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a>└─────────────────────────────┘</span></code></pre></div>
<p>Sadly that last point means slate can’t just copy paste clang’s
headers into <code>libc-shim</code> and call it a day. The Clang IR
(CIR) that it reads turns into raw llvm intrinsics.</p>
<h2 id="the-power-of-tablegen">The power of Tablegen</h2>
<p>Since Slate is pinned to a given Clang version (since Clang IR isn’t
built by default for Clang yet), we can use their tablegen parser. This
allows us to get all the information that clang records for each
intrinsic, and then change its form to something slate can
recognize.</p>
<p>To that end, there’s a support crate for slate called
<code>slate-intrinsic-gen</code> that parses each tablegen and creates a
struct for each entry that looks like:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>IntrinsicSignature <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    name<span class="op">:</span> <span class="st">&quot;llvm.x86.sse42.crc32.32.8&quot;</span><span class="op">,</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    overloaded<span class="op">:</span> <span class="cn">false</span><span class="op">,</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    ret<span class="op">:</span> <span class="cn">Some</span>(<span class="st">&quot;i32&quot;</span>)<span class="op">,</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    params<span class="op">:</span> <span class="cn">Some</span>(<span class="op">&amp;</span>[</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>        IntrinsicParam <span class="op">{</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>            llvm_type<span class="op">:</span> <span class="st">&quot;i32&quot;</span><span class="op">,</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>            immarg<span class="op">:</span> <span class="cn">false</span><span class="op">,</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">},</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>        IntrinsicParam <span class="op">{</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>            llvm_type<span class="op">:</span> <span class="st">&quot;i8&quot;</span><span class="op">,</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>            immarg<span class="op">:</span> <span class="cn">false</span><span class="op">,</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">},</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>    ])<span class="op">,</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>    overloaded_positions<span class="op">:</span> <span class="cn">None</span><span class="op">,</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This allows us to recover the whole name itself. For example, for
this program:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>__attribute__<span class="op">((</span>target<span class="op">(</span><span class="st">&quot;sse4.2&quot;</span><span class="op">)))</span> <span class="dt">static</span> <span class="dt">unsigned</span> <span class="dt">long</span> <span class="dt">long</span> crc32_probe<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">unsigned</span> <span class="dt">int</span> crc <span class="op">=</span> _mm_crc32_u8<span class="op">(</span><span class="dv">0</span><span class="bu">u</span><span class="op">,</span> <span class="bn">0x12</span><span class="bu">u</span><span class="op">);</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>  crc              <span class="op">=</span> _mm_crc32_u16<span class="op">(</span>crc<span class="op">,</span> <span class="bn">0x3456</span><span class="bu">u</span><span class="op">);</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  crc              <span class="op">=</span> _mm_crc32_u32<span class="op">(</span>crc<span class="op">,</span> <span class="bn">0x789abcde</span><span class="bu">u</span><span class="op">);</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> _mm_crc32_u64<span class="op">(</span>crc<span class="op">,</span> <span class="bn">0x123456789abcdef0</span><span class="bu">ull</span><span class="op">);</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Slate will generate something like this:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>target_feature<span class="at">(</span>enable <span class="op">=</span> <span class="st">&quot;sse4.2&quot;</span><span class="at">)]</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">unsafe</span> <span class="kw">fn</span> _mm_crc32_u8(a<span class="op">:</span> <span class="dt">u32</span><span class="op">,</span> b<span class="op">:</span> <span class="dt">u8</span>) <span class="op">-&gt;</span> <span class="dt">u32</span> <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">unsafe</span> <span class="op">{</span> __slate_intrinsic_x86_sse42_crc32_32_8_f27bf8581dad0801(a<span class="op">,</span> b) <span class="op">}</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>target_feature<span class="at">(</span>enable <span class="op">=</span> <span class="st">&quot;sse4.2&quot;</span><span class="at">)]</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="kw">unsafe</span> <span class="kw">fn</span> _mm_crc32_u16(a<span class="op">:</span> <span class="dt">u32</span><span class="op">,</span> b<span class="op">:</span> <span class="dt">u16</span>) <span class="op">-&gt;</span> <span class="dt">u32</span> <span class="op">{</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">unsafe</span> <span class="op">{</span> __slate_intrinsic_x86_sse42_crc32_32_16_658f6bf45a185a4a(a<span class="op">,</span> b) <span class="op">}</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>target_feature<span class="at">(</span>enable <span class="op">=</span> <span class="st">&quot;sse4.2&quot;</span><span class="at">)]</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a><span class="kw">unsafe</span> <span class="kw">fn</span> _mm_crc32_u32(a<span class="op">:</span> <span class="dt">u32</span><span class="op">,</span> b<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="dt">u32</span> <span class="op">{</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">unsafe</span> <span class="op">{</span> __slate_intrinsic_x86_sse42_crc32_32_32_f5e6b09e791bc818(a<span class="op">,</span> b) <span class="op">}</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>target_feature<span class="at">(</span>enable <span class="op">=</span> <span class="st">&quot;sse4.2&quot;</span><span class="at">)]</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a><span class="kw">unsafe</span> <span class="kw">fn</span> _mm_crc32_u64(a<span class="op">:</span> <span class="dt">u64</span><span class="op">,</span> b<span class="op">:</span> <span class="dt">u64</span>) <span class="op">-&gt;</span> <span class="dt">u64</span> <span class="op">{</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">unsafe</span> <span class="op">{</span> __slate_intrinsic_x86_sse42_crc32_64_64_a6b1e708219fb1bb(a<span class="op">,</span> b) <span class="op">}</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>target_feature<span class="at">(</span>enable <span class="op">=</span> <span class="st">&quot;popcnt,sse3,sse4.1,sse4.2,ssse3&quot;</span><span class="at">)]</span></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a><span class="kw">unsafe</span> <span class="kw">fn</span> crc32_probe() <span class="op">-&gt;</span> <span class="dt">u64</span> <span class="op">{</span></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> v1<span class="op">:</span> <span class="dt">u32</span> <span class="op">=</span> <span class="kw">unsafe</span> <span class="op">{</span> _mm_crc32_u8(<span class="dv">0</span><span class="op">,</span> <span class="dv">18</span>) <span class="op">};</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> v2<span class="op">:</span> <span class="dt">u32</span> <span class="op">=</span> <span class="kw">unsafe</span> <span class="op">{</span> _mm_crc32_u16(v1<span class="op">,</span> <span class="dv">13398</span>) <span class="op">};</span></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> v3<span class="op">:</span> <span class="dt">u32</span> <span class="op">=</span> <span class="kw">unsafe</span> <span class="op">{</span> _mm_crc32_u32(v2<span class="op">,</span> <span class="dv">2023406814</span>) <span class="op">};</span></span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> v4<span class="op">:</span> <span class="dt">u64</span> <span class="op">=</span> <span class="dv">1311768467463790320u64</span><span class="op">;</span></span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">unsafe</span> <span class="op">{</span> _mm_crc32_u64(v3 <span class="kw">as</span> <span class="dt">u64</span><span class="op">,</span> v4) <span class="op">}</span></span>
<span id="cb4-28"><a href="#cb4-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb4-29"><a href="#cb4-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-30"><a href="#cb4-30" aria-hidden="true" tabindex="-1"></a><span class="kw">unsafe</span> <span class="kw">extern</span> <span class="st">&quot;unadjusted&quot;</span> <span class="op">{</span></span>
<span id="cb4-31"><a href="#cb4-31" aria-hidden="true" tabindex="-1"></a>    <span class="at">#[</span>link_name <span class="op">=</span> <span class="st">&quot;llvm.x86.sse42.crc32.32.8&quot;</span><span class="at">]</span></span>
<span id="cb4-32"><a href="#cb4-32" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> __slate_intrinsic_x86_sse42_crc32_32_8_f27bf8581dad0801(_0<span class="op">:</span> <span class="dt">u32</span><span class="op">,</span> _1<span class="op">:</span> <span class="dt">u8</span>) <span class="op">-&gt;</span> <span class="dt">u32</span><span class="op">;</span></span>
<span id="cb4-33"><a href="#cb4-33" aria-hidden="true" tabindex="-1"></a>    <span class="at">#[</span>link_name <span class="op">=</span> <span class="st">&quot;llvm.x86.sse42.crc32.32.16&quot;</span><span class="at">]</span></span>
<span id="cb4-34"><a href="#cb4-34" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> __slate_intrinsic_x86_sse42_crc32_32_16_658f6bf45a185a4a(_0<span class="op">:</span> <span class="dt">u32</span><span class="op">,</span> _1<span class="op">:</span> <span class="dt">u16</span>) <span class="op">-&gt;</span> <span class="dt">u32</span><span class="op">;</span></span>
<span id="cb4-35"><a href="#cb4-35" aria-hidden="true" tabindex="-1"></a>    <span class="at">#[</span>link_name <span class="op">=</span> <span class="st">&quot;llvm.x86.sse42.crc32.32.32&quot;</span><span class="at">]</span></span>
<span id="cb4-36"><a href="#cb4-36" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> __slate_intrinsic_x86_sse42_crc32_32_32_f5e6b09e791bc818(_0<span class="op">:</span> <span class="dt">u32</span><span class="op">,</span> _1<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="dt">u32</span><span class="op">;</span></span>
<span id="cb4-37"><a href="#cb4-37" aria-hidden="true" tabindex="-1"></a>    <span class="at">#[</span>link_name <span class="op">=</span> <span class="st">&quot;llvm.x86.sse42.crc32.64.64&quot;</span><span class="at">]</span></span>
<span id="cb4-38"><a href="#cb4-38" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> __slate_intrinsic_x86_sse42_crc32_64_64_a6b1e708219fb1bb(_0<span class="op">:</span> <span class="dt">u64</span><span class="op">,</span> _1<span class="op">:</span> <span class="dt">u64</span>) <span class="op">-&gt;</span> <span class="dt">u64</span><span class="op">;</span></span>
<span id="cb4-39"><a href="#cb4-39" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Now note that slate does all of its external linking itself, since
not all intrinsics in clang are supported by rust.</p>
<p>But there’s one thing wrong here: the tablegen says crc32’s signature
takes a <code>i32 and i8</code> and returns an <code>i32</code> but the
intrinsic itself is all unsigned (<code>u32 and u8</code> returning a
<code>u8</code>). What gives?</p>
<h2 id="some-thorns-in-our-side-overrides">Some thorns in our side
(Overrides)</h2>
<p>Note that actually some functions have different signatures, used to
disambiguate what the actual function is:</p>
<p>So we keep a separate table that contains the overridden link name,
its params and return type as well, so we can use this to generate what
we want. For <code>crc32.32.8</code>, that means we override its
parameters:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>StdarchOverride <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    link_name<span class="op">:</span> <span class="st">&quot;llvm.x86.sse42.crc32.32.8&quot;</span><span class="op">,</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    params<span class="op">:</span> <span class="op">&amp;</span>[<span class="st">&quot;u32&quot;</span><span class="op">,</span> <span class="st">&quot;u8&quot;</span>]<span class="op">,</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    ret<span class="op">:</span> <span class="cn">Some</span>(<span class="st">&quot;u32&quot;</span>)<span class="op">,</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="op">},</span></span></code></pre></div>
<p>Also, there’s another thorn in our side where rust’s target features
don’t map to LLVM’s:</p>
<p>for example, <code>crc32</code> functionality is gated behind the
feature flag <code>crc32</code> in clang. In Rust, this is gated behind
the broader <code>sse4.2</code> flag. Likewise <code>bmi</code>, bit
manipulation instructions for haswell is different on clang than it is
in rust, <code>bmi1</code>. So we have to disambiguate that as well.</p>
<h2 id="why-bother">Why bother?</h2>
<p>If we pass the previous program to C2Rust, note that it’ll lean on
rust to emit the right intrinsics:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="at">#![</span>feature<span class="at">(</span>stdsimd<span class="at">)]</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;x86&quot;</span><span class="at">)]</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">use</span> <span class="pp">::core::arch::x86::</span><span class="op">{</span>_mm_crc32_u8<span class="op">,</span> _mm_crc32_u16<span class="op">,</span> _mm_crc32_u32<span class="op">};</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="at">)]</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">use</span> <span class="pp">::core::arch::x86_64::</span><span class="op">{</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>    _mm_crc32_u8<span class="op">,</span> _mm_crc32_u16<span class="op">,</span> _mm_crc32_u32<span class="op">,</span> _mm_crc32_u64<span class="op">,</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a><span class="kw">unsafe</span> <span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="kw">fn</span> crc32_probe() <span class="op">-&gt;</span> <span class="pp">::core::ffi::</span><span class="dt">c_ulonglong</span> <span class="op">{</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> crc<span class="op">:</span> <span class="pp">::core::ffi::</span><span class="dt">c_uint</span> <span class="op">=</span> _mm_crc32_u8(</span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>        <span class="dv">0</span> <span class="kw">as</span> <span class="pp">::core::ffi::</span><span class="dt">c_uint</span><span class="op">,</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>        <span class="dv">0x12</span> <span class="kw">as</span> <span class="pp">::core::ffi::</span><span class="dt">c_uchar</span><span class="op">,</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>    )<span class="op">;</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>    crc <span class="op">=</span> _mm_crc32_u16(crc<span class="op">,</span> <span class="dv">0x3456</span> <span class="kw">as</span> <span class="pp">::core::ffi::</span><span class="dt">c_ushort</span>)<span class="op">;</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>    crc <span class="op">=</span> _mm_crc32_u32(crc<span class="op">,</span> <span class="dv">0x789abcde</span> <span class="kw">as</span> <span class="pp">::core::ffi::</span><span class="dt">c_uint</span>)<span class="op">;</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> _mm_crc32_u64(</span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a>        crc <span class="kw">as</span> <span class="pp">::core::ffi::</span><span class="dt">c_ulonglong</span><span class="op">,</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a>        <span class="dv">0x123456789abcdef0</span> <span class="kw">as</span> <span class="pp">::core::ffi::</span><span class="dt">c_ulonglong</span><span class="op">,</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a>    )<span class="op">;</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Which works, most of the time. Rust supports almost all intrinsics
for x86 that return a value, however, it doesn’t support the intrinsics
that are used for their effects:</p>
<p>For example, take this program that flushes the cache line(s) for the
CPU:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;immintrin.h&gt;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>__attribute__<span class="op">((</span>target<span class="op">(</span><span class="st">&quot;clflushopt&quot;</span><span class="op">)))</span> <span class="dt">void</span> flush<span class="op">(</span><span class="dt">void</span> <span class="op">*</span>addr<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>    __builtin_ia32_clflushopt<span class="op">(</span>addr<span class="op">);</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>    _mm_sfence<span class="op">();</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> x <span class="op">=</span> <span class="dv">42</span><span class="op">;</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>    flush<span class="op">(&amp;</span>x<span class="op">);</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>    printf<span class="op">(</span><span class="st">&quot;</span><span class="sc">%d\n</span><span class="st">&quot;</span><span class="op">,</span> x<span class="op">);</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>There is no intrinsic for this in the Rust stdlib, so the
<code>flush</code> function gets deleted by C2Rust wholesale:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;x86&quot;</span><span class="at">)]</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">use</span> <span class="pp">::core::arch::x86::</span>_mm_sfence<span class="op">;</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="at">)]</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">use</span> <span class="pp">::core::arch::x86_64::</span>_mm_sfence<span class="op">;</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="op">{</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> printf(__format<span class="op">:</span> <span class="op">*</span><span class="kw">const</span> <span class="pp">::core::ffi::</span><span class="dt">c_char</span><span class="op">,</span> <span class="op">...</span>) <span class="op">-&gt;</span> <span class="pp">::core::ffi::</span><span class="dt">c_int</span><span class="op">;</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a><span class="kw">unsafe</span> <span class="kw">fn</span> main_0() <span class="op">-&gt;</span> <span class="pp">::core::ffi::</span><span class="dt">c_int</span> <span class="op">{</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> x<span class="op">:</span> <span class="pp">::core::ffi::</span><span class="dt">c_int</span> <span class="op">=</span> <span class="dv">42</span> <span class="kw">as</span> <span class="pp">::core::ffi::</span><span class="dt">c_int</span><span class="op">;</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>    flush(<span class="op">&amp;</span>raw <span class="kw">mut</span> x <span class="kw">as</span> <span class="op">*</span><span class="kw">mut</span> <span class="pp">::core::ffi::</span><span class="dt">c_void</span>)<span class="op">;</span> <span class="co">// flush called</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>    <span class="co">// without a definition</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>    printf(<span class="st">b&quot;%d</span><span class="sc">\n\0</span><span class="st">&quot;</span><span class="op">.</span>as_ptr() <span class="kw">as</span> <span class="op">*</span><span class="kw">const</span> <span class="pp">::core::ffi::</span><span class="dt">c_char</span><span class="op">,</span> x)<span class="op">;</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span> <span class="kw">as</span> <span class="pp">::core::ffi::</span><span class="dt">c_int</span><span class="op">;</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">fn</span> main() <span class="op">{</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">unsafe</span> <span class="op">{</span> <span class="pp">::std::process::</span>exit(main_0() <span class="kw">as</span> <span class="dt">i32</span>) <span class="op">}</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>By adding the mapping yourself, you can translate this program and
get the same result as the C would.</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="at">#![</span>feature<span class="at">(</span>clflushopt_target_feature<span class="at">)]</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="at">#![</span>feature<span class="at">(</span>abi_unadjusted<span class="at">)]</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="at">#![</span>feature<span class="at">(</span>link_llvm_intrinsics<span class="at">)]</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="at">#![</span>feature<span class="at">(</span>c_variadic<span class="at">)]</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="at">#![</span>allow<span class="at">(</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>    dead_code<span class="op">,</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>    unused<span class="op">,</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>    non_camel_case_types<span class="op">,</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>    non_snake_case<span class="op">,</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>    non_upper_case_globals<span class="op">,</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>    arithmetic_overflow<span class="op">,</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>    unconditional_panic<span class="op">,</span></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>    suspicious_runtime_symbol_definitions<span class="op">,</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>    unpredictable_function_pointer_comparisons<span class="op">,</span></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a>    unused_comparisons</span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a><span class="at">)]</span></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true" tabindex="-1"></a><span class="kw">unsafe</span> <span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="op">{</span></span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> printf(_0<span class="op">:</span> <span class="op">*</span><span class="kw">const</span> <span class="pp">core::ffi::</span><span class="dt">c_char</span><span class="op">,</span> <span class="op">...</span>) <span class="op">-&gt;</span> <span class="dt">i32</span><span class="op">;</span></span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-22"><a href="#cb9-22" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>target_feature<span class="at">(</span>enable <span class="op">=</span> <span class="st">&quot;clflushopt&quot;</span><span class="at">)]</span></span>
<span id="cb9-23"><a href="#cb9-23" aria-hidden="true" tabindex="-1"></a><span class="kw">unsafe</span> <span class="kw">fn</span> flush(_v0<span class="op">:</span> <span class="op">*</span><span class="kw">mut</span> <span class="pp">core::ffi::</span><span class="dt">c_void</span>) <span class="op">{</span></span>
<span id="cb9-24"><a href="#cb9-24" aria-hidden="true" tabindex="-1"></a>    <span class="kw">unsafe</span> <span class="op">{</span></span>
<span id="cb9-25"><a href="#cb9-25" aria-hidden="true" tabindex="-1"></a>        <span class="kw">unsafe</span> <span class="op">{</span> __slate_intrinsic_x86_clflushopt_2bf6694e0a93403a(_v0) <span class="op">};</span></span>
<span id="cb9-26"><a href="#cb9-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-27"><a href="#cb9-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">unsafe</span> <span class="op">{</span></span>
<span id="cb9-28"><a href="#cb9-28" aria-hidden="true" tabindex="-1"></a>        <span class="kw">unsafe</span> <span class="op">{</span> __slate_intrinsic_x86_sse_sfence_f8b270d178b3d220() <span class="op">};</span></span>
<span id="cb9-29"><a href="#cb9-29" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-30"><a href="#cb9-30" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span><span class="op">;</span></span>
<span id="cb9-31"><a href="#cb9-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb9-32"><a href="#cb9-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-33"><a href="#cb9-33" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
<span id="cb9-34"><a href="#cb9-34" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> x<span class="op">:</span> <span class="dt">i32</span> <span class="op">=</span> <span class="dv">42</span><span class="op">;</span></span>
<span id="cb9-35"><a href="#cb9-35" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> _v2<span class="op">:</span> <span class="op">*</span><span class="kw">mut</span> <span class="pp">core::ffi::</span><span class="dt">c_void</span> <span class="op">=</span> <span class="pp">std::ptr::addr_of_mut!</span>(x) <span class="kw">as</span> <span class="op">*</span><span class="kw">mut</span> <span class="pp">core::ffi::</span><span class="dt">c_void</span><span class="op">;</span></span>
<span id="cb9-36"><a href="#cb9-36" aria-hidden="true" tabindex="-1"></a>    <span class="kw">unsafe</span> <span class="op">{</span> flush(_v2 <span class="kw">as</span> <span class="op">*</span><span class="kw">mut</span> <span class="pp">core::ffi::</span><span class="dt">c_void</span>) <span class="op">};</span></span>
<span id="cb9-37"><a href="#cb9-37" aria-hidden="true" tabindex="-1"></a>    <span class="kw">unsafe</span> <span class="op">{</span> printf(c<span class="st">&quot;%d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">.</span>as_ptr()<span class="op">,</span> x) <span class="op">};</span></span>
<span id="cb9-38"><a href="#cb9-38" aria-hidden="true" tabindex="-1"></a>    <span class="pp">std::process::</span>exit(<span class="dv">0</span> <span class="kw">as</span> <span class="dt">i32</span>)<span class="op">;</span></span>
<span id="cb9-39"><a href="#cb9-39" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb9-40"><a href="#cb9-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-41"><a href="#cb9-41" aria-hidden="true" tabindex="-1"></a><span class="kw">unsafe</span> <span class="kw">extern</span> <span class="st">&quot;unadjusted&quot;</span> <span class="op">{</span></span>
<span id="cb9-42"><a href="#cb9-42" aria-hidden="true" tabindex="-1"></a>    <span class="at">#[</span>link_name <span class="op">=</span> <span class="st">&quot;llvm.x86.clflushopt&quot;</span><span class="at">]</span></span>
<span id="cb9-43"><a href="#cb9-43" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> __slate_intrinsic_x86_clflushopt_2bf6694e0a93403a(_0<span class="op">:</span> <span class="op">*</span><span class="kw">mut</span> <span class="pp">core::ffi::</span><span class="dt">c_void</span>)<span class="op">;</span></span>
<span id="cb9-44"><a href="#cb9-44" aria-hidden="true" tabindex="-1"></a>    <span class="at">#[</span>link_name <span class="op">=</span> <span class="st">&quot;llvm.x86.sse.sfence&quot;</span><span class="at">]</span></span>
<span id="cb9-45"><a href="#cb9-45" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> __slate_intrinsic_x86_sse_sfence_f8b270d178b3d220()<span class="op">;</span></span>
<span id="cb9-46"><a href="#cb9-46" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="in-sum">In Sum</h2>
<p>The whole flow looks like this:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode txt"><code class="sourceCode default"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>┌─────────────────────────────┐</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>│ C source                    │</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>│ _mm_add_epi32(..)           │</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>└──────────────┬──────────────┘</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>               │</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>               ▼</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>┌─────────────────────────────┐</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>│ Clang + CIR                 │</span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>│ (headers inlined, resolved  │</span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>│ to LLVM intrinsic call)     │</span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>└──────────────┬──────────────┘</span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>               │</span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a>               ▼</span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>┌─────────────────────────────┐</span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a>│ cir.call_llvm_intrinsic op  │</span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a>│ (llvm.x86.foo, concrete     │</span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a>│ operand/result types)       │</span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>└──────────────┬──────────────┘</span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a>               │</span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a>               ▼</span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true" tabindex="-1"></a>┌─────────────────────────────┐        ┌─────────────────────────────┐</span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true" tabindex="-1"></a>│ intrinsics.rs               │        │  slate-intrinsic-gen        │</span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true" tabindex="-1"></a>│ mangled_link_name /         │        │ (offline, once per LLVM     │</span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true" tabindex="-1"></a>│ find_stdarch_override       │◀───────│ stdarch version — mines     │</span>
<span id="cb10-25"><a href="#cb10-25" aria-hidden="true" tabindex="-1"></a>│ against intrinsics_table.rs │        │ Intrinsics.h + stdarch      │</span>
<span id="cb10-26"><a href="#cb10-26" aria-hidden="true" tabindex="-1"></a>│                             │        │ #[link_name] attrs)         │</span>
<span id="cb10-27"><a href="#cb10-27" aria-hidden="true" tabindex="-1"></a>└──────────────┬──────────────┘        └─────────────────────────────┘</span>
<span id="cb10-28"><a href="#cb10-28" aria-hidden="true" tabindex="-1"></a>               │</span>
<span id="cb10-29"><a href="#cb10-29" aria-hidden="true" tabindex="-1"></a>               ▼</span>
<span id="cb10-30"><a href="#cb10-30" aria-hidden="true" tabindex="-1"></a>┌─────────────────────────────┐</span>
<span id="cb10-31"><a href="#cb10-31" aria-hidden="true" tabindex="-1"></a>│ extern &quot;unadjusted&quot;         │</span>
<span id="cb10-32"><a href="#cb10-32" aria-hidden="true" tabindex="-1"></a>│ #[link_name = &quot;llvm.foo&quot;]   │</span>
<span id="cb10-33"><a href="#cb10-33" aria-hidden="true" tabindex="-1"></a>│ fn decl (shim)              │</span>
<span id="cb10-34"><a href="#cb10-34" aria-hidden="true" tabindex="-1"></a>└──────────────┬──────────────┘</span>
<span id="cb10-35"><a href="#cb10-35" aria-hidden="true" tabindex="-1"></a>               │</span>
<span id="cb10-36"><a href="#cb10-36" aria-hidden="true" tabindex="-1"></a>               ▼</span>
<span id="cb10-37"><a href="#cb10-37" aria-hidden="true" tabindex="-1"></a>┌─────────────────────────────┐</span>
<span id="cb10-38"><a href="#cb10-38" aria-hidden="true" tabindex="-1"></a>│ generated Rust fn call site │</span>
<span id="cb10-39"><a href="#cb10-39" aria-hidden="true" tabindex="-1"></a>│ (compiled + run)            │</span>
<span id="cb10-40"><a href="#cb10-40" aria-hidden="true" tabindex="-1"></a>└─────────────────────────────┘</span></code></pre></div>]]></description>
</item>
<item>
<title>Switch To Match</title>
<pubDate>Wed, 02 Sep 2026 22:03:41 +0000</pubDate>
<guid>https://blog/switch-to-match.html</guid>
<description><![CDATA[<p>More talk about <a
href="https://github.com/takashiidobe/slate">Slate</a>, a C to Rust
translator! Take a look at the previous post here: <a
href="./one-libc-for-all.md">One libc for all</a>.</p>
<p>Today’s topic is about translating C’s <code>switch</code> to rust’s
<code>match</code>, which shockingly has a decent amount of literature
about it (unbeknownst to me).</p>
<p>We’ll start out with this example which demonstrates the main
features of switch in C:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> score<span class="op">(</span><span class="dt">int</span> x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> out <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span> <span class="op">(</span>x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">case</span> <span class="dv">1</span><span class="op">:</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    out <span class="op">+=</span> <span class="dv">10</span><span class="op">;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>  <span class="cf">case</span> <span class="dv">2</span><span class="op">:</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    out <span class="op">+=</span> <span class="dv">20</span><span class="op">;</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">break</span><span class="op">;</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>  <span class="cf">case</span> <span class="dv">3</span><span class="op">:</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>  <span class="cf">case</span> <span class="dv">4</span><span class="op">:</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    out <span class="op">+=</span> <span class="dv">40</span><span class="op">;</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">break</span><span class="op">;</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>  <span class="cf">default</span><span class="op">:</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>    out <span class="op">+=</span> <span class="dv">90</span><span class="op">;</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> out<span class="op">;</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>  printf<span class="op">(</span><span class="st">&quot;</span><span class="sc">%d</span><span class="st"> </span><span class="sc">%d</span><span class="st"> </span><span class="sc">%d</span><span class="st"> </span><span class="sc">%d</span><span class="st"> </span><span class="sc">%d\n</span><span class="st">&quot;</span><span class="op">,</span> score<span class="op">(</span><span class="dv">1</span><span class="op">),</span> score<span class="op">(</span><span class="dv">2</span><span class="op">),</span> score<span class="op">(</span><span class="dv">3</span><span class="op">),</span> score<span class="op">(</span><span class="dv">4</span><span class="op">),</span> score<span class="op">(</span><span class="dv">5</span><span class="op">));</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<ul>
<li><code>score(1)</code> hits the first branch, where it adds
<code>10</code> to out. However, there is no break after 1, so it also
falls through into case 2, which adds <code>20</code> to out. Thus, out
will be <code>30</code> and printed.</li>
<li><code>score(2)</code> increments out by 20 and then breaks out. So
it prints out <code>20</code>.</li>
<li><code>score(3)</code> hits the 3 or 4 branch, increments out by
<code>40</code> and prints.</li>
<li><code>score(4)</code> does the same thing, printing
<code>40</code>.</li>
<li><code>score(5)</code> will just print out <code>90</code>, since
even without a break it falls through into nothing.</li>
</ul>
<p>If we were to draw a graph of this, it would look like:</p>
<pre><code>                    ┌─────────────┐
                    │  entry      │
                    │  out = 0    │
                    └──────┬──────┘
                           │
                           ▼
                    ┌─────────────┐
                    │  switch(x)  │
                    └──┬──┬──┬──┬─┘
          x==1         │  │  │  │ default
      ┌────────────────┘  │  │  └────────────────────┐
      │            x==2   │  │ x==3,4                │
      │            ┌──────┘  └────────┐              │
      │            │                  │              │
      ▼            ▼                  ▼              ▼
┌───────────┐   ┌───────────┐    ┌───────────┐ ┌───────────┐
│ case 1:   │   │ case 2:   │    │ case 3:   │ │ default:  │
│ out += 10 │──▶│ out += 20 │    │           │ │ out += 90 │
└───────────┘   └─────┬─────┘    └─────┬─────┘ └─────┬─────┘
                      │                │             │
                      │                ▼             │
                      │          ┌───────────┐       │
                      │          │ case 4:   │       │
                      │          │ out += 40 │       │
                      │          └─────┬─────┘       │
                      │                │             │
                      └──────┬─────────┴─────────────┘
                             ▼
                      ┌─────────────┐
                      │ return out  │
                      └─────────────┘</code></pre>
<p>We could try to convert this to rust but sadly, rust’s match doesn’t
have fallthrough. So we’ll have to be a bit more creative.</p>
<h2 id="recovering-structure">Recovering Structure</h2>
<p>There’s a theorem from the 60s (the structured program theorem)
saying any Control Flow Graph (CFG) can be represented with three
control flow structures: sequence, selection (if/else), and iteration (a
loop over a boolean condition).</p>
<p>There are many ways of recovering structure, so let’s look at three
concrete ways of converting switch to match: how C2Rust’s relooper does
it, and the classic “folk theorem” construction using a loop and a
program counter, and then a bottom up traversal algorithm that generates
the best results.</p>
<h2 id="relooper">Relooper</h2>
<p>C2Rust currently emits this for the switch case in C we looked at,
using an algorithm called Relooper:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">&#39;s_34</span><span class="op">:</span> <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">match</span> x <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>        <span class="dv">1</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>            out <span class="op">+=</span> <span class="dv">10</span><span class="op">;</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>        <span class="dv">2</span> <span class="op">=&gt;</span> <span class="op">{}</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>        <span class="dv">3</span> <span class="op">|</span> <span class="dv">4</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>            out <span class="op">+=</span> <span class="dv">40</span><span class="op">;</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>            <span class="cf">break</span> <span class="ot">&#39;s_34</span><span class="op">;</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>        _ <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>            out <span class="op">+=</span> <span class="dv">90</span><span class="op">;</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>            <span class="cf">break</span> <span class="ot">&#39;s_34</span><span class="op">;</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>    out <span class="op">+=</span> <span class="dv">20</span><span class="op">;</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Relooper’s trick is when code is shared by multiple branches but some
branches need to skip it, it wraps the branch in a labeled block and has
those branches break out of the label before reaching the shared code.
So:</p>
<ul>
<li><code>out += 20</code> (case 2’s body) is hoisted outside and after
the <code>match</code>, since it’s the code shared by case 1’s
fallthrough and entering case 2 directly.</li>
<li>Every case that must <em>not</em> run that trailing code (3, 4,
<code>default</code>) gets an explicit <code>break 's_34</code>, so it
doesn’t run into the <code>out += 20</code> code.</li>
<li>Case 1 has no break, so it falls off the end of its arm into the
shared trailer, which executes <code>out += 20</code>.</li>
<li>Case 2’s own arm is deleted, because its body <em>is</em> the shared
trailing code.</li>
</ul>
<p>Basically, Relooper will add an outer loop with break label for every
fallthrough case, minus 1. So in this case, let’s count the
fallthroughs:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="cf">switch</span> <span class="op">(</span>x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="cf">case</span> <span class="op">-</span><span class="dv">500</span> <span class="op">...</span> <span class="op">-</span><span class="dv">1</span><span class="op">:</span> <span class="co">// 1</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  out <span class="op">+=</span> <span class="dv">100</span><span class="op">;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="cf">case</span> <span class="dv">0</span><span class="op">:</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="cf">case</span> <span class="dv">1</span><span class="op">:</span> <span class="co">// 2</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>  out <span class="op">+=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="cf">case</span> <span class="dv">2</span> <span class="op">...</span> <span class="dv">100</span><span class="op">:</span> <span class="co">// 3</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>  out <span class="op">+=</span> <span class="dv">2</span><span class="op">;</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>out <span class="op">&gt;</span> <span class="dv">50</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">break</span><span class="op">;</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>  out <span class="op">+=</span> <span class="dv">3</span><span class="op">;</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a><span class="cf">case</span> <span class="dv">101</span><span class="op">:</span> <span class="co">// 4</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>  out <span class="op">+=</span> <span class="dv">4</span><span class="op">;</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>x <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>    <span class="cf">break</span><span class="op">;</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a><span class="cf">default</span><span class="op">:</span> <span class="co">// 5</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>  out <span class="op">+=</span> <span class="dv">5</span><span class="op">;</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a><span class="cf">case</span> <span class="dv">200</span> <span class="op">...</span> <span class="dv">500</span><span class="op">:</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a><span class="cf">case</span> <span class="dv">600</span><span class="op">:</span></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a><span class="cf">case</span> <span class="dv">700</span> <span class="op">...</span> <span class="dv">900</span><span class="op">:</span></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a>  out <span class="op">+=</span> <span class="dv">6</span><span class="op">;</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a>  <span class="cf">break</span><span class="op">;</span></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true" tabindex="-1"></a><span class="cf">case</span> <span class="dv">999</span><span class="op">:</span> <span class="co">// 6</span></span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true" tabindex="-1"></a>  out <span class="op">+=</span> <span class="dv">7</span><span class="op">;</span></span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true" tabindex="-1"></a><span class="cf">case</span> <span class="dv">1000</span><span class="op">:</span> <span class="co">// 7</span></span>
<span id="cb4-28"><a href="#cb4-28" aria-hidden="true" tabindex="-1"></a>  out <span class="op">+=</span> <span class="dv">8</span><span class="op">;</span></span>
<span id="cb4-29"><a href="#cb4-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Since there are 7 fallthroughs, there will be 6 wrapping loops
generated, making this code hard to read:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">&#39;s_73</span><span class="op">:</span> <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="ot">&#39;c_720</span><span class="op">:</span> <span class="op">{</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>        <span class="ot">&#39;c_700</span><span class="op">:</span> <span class="op">{</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>            <span class="ot">&#39;c_698</span><span class="op">:</span> <span class="op">{</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>                <span class="ot">&#39;c_695</span><span class="op">:</span> <span class="op">{</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>                    <span class="ot">&#39;c_704</span><span class="op">:</span> <span class="op">{</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>                        <span class="cf">match</span> x <span class="op">{</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>                            <span class="op">-</span><span class="dv">500</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>                                out <span class="op">+=</span> <span class="dv">100</span> <span class="op">;</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>                            <span class="op">}</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>                            <span class="dv">0</span> <span class="op">|</span> <span class="dv">1</span> <span class="op">=&gt;</span> <span class="op">{}</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>                            <span class="dv">2</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>                                <span class="cf">break</span> <span class="ot">&#39;c_695</span><span class="op">;</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>                            <span class="op">}</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>                            <span class="dv">101</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>                                <span class="cf">break</span> <span class="ot">&#39;c_698</span><span class="op">;</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>                            <span class="op">}</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a>                            <span class="dv">200</span> <span class="op">|</span> <span class="dv">600</span> <span class="op">|</span> <span class="dv">700</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a>                                <span class="cf">break</span> <span class="ot">&#39;c_720</span><span class="op">;</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a>                            <span class="op">}</span></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a>                            <span class="dv">999</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a>                                out <span class="op">+=</span> <span class="dv">7</span><span class="op">;</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true" tabindex="-1"></a>                                <span class="cf">break</span> <span class="ot">&#39;c_704</span><span class="op">;</span></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true" tabindex="-1"></a>                            <span class="op">}</span></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true" tabindex="-1"></a>                            <span class="dv">1000</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true" tabindex="-1"></a>                                <span class="cf">break</span> <span class="ot">&#39;c_704</span><span class="op">;</span></span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true" tabindex="-1"></a>                            <span class="op">}</span></span>
<span id="cb5-28"><a href="#cb5-28" aria-hidden="true" tabindex="-1"></a>                            _ <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb5-29"><a href="#cb5-29" aria-hidden="true" tabindex="-1"></a>                                <span class="cf">break</span> <span class="ot">&#39;c_700</span><span class="op">;</span></span>
<span id="cb5-30"><a href="#cb5-30" aria-hidden="true" tabindex="-1"></a>                            <span class="op">}</span></span>
<span id="cb5-31"><a href="#cb5-31" aria-hidden="true" tabindex="-1"></a>                        <span class="op">}</span></span>
<span id="cb5-32"><a href="#cb5-32" aria-hidden="true" tabindex="-1"></a>                        out <span class="op">+=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb5-33"><a href="#cb5-33" aria-hidden="true" tabindex="-1"></a>                        <span class="cf">break</span> <span class="ot">&#39;c_695</span><span class="op">;</span></span>
<span id="cb5-34"><a href="#cb5-34" aria-hidden="true" tabindex="-1"></a>                    <span class="op">}</span></span>
<span id="cb5-35"><a href="#cb5-35" aria-hidden="true" tabindex="-1"></a>                    out <span class="op">+=</span> <span class="dv">8</span><span class="op">;</span></span>
<span id="cb5-36"><a href="#cb5-36" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">break</span> <span class="ot">&#39;s_73</span><span class="op">;</span></span>
<span id="cb5-37"><a href="#cb5-37" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb5-38"><a href="#cb5-38" aria-hidden="true" tabindex="-1"></a>                out <span class="op">+=</span> <span class="dv">2</span><span class="op">;</span></span>
<span id="cb5-39"><a href="#cb5-39" aria-hidden="true" tabindex="-1"></a>                <span class="cf">if</span> out <span class="op">&gt;</span> <span class="dv">50</span> <span class="op">{</span></span>
<span id="cb5-40"><a href="#cb5-40" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">break</span> <span class="ot">&#39;s_73</span><span class="op">;</span></span>
<span id="cb5-41"><a href="#cb5-41" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb5-42"><a href="#cb5-42" aria-hidden="true" tabindex="-1"></a>                    out <span class="op">+=</span> <span class="dv">3</span><span class="op">;</span></span>
<span id="cb5-43"><a href="#cb5-43" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb5-44"><a href="#cb5-44" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb5-45"><a href="#cb5-45" aria-hidden="true" tabindex="-1"></a>            out <span class="op">+=</span> <span class="dv">4</span><span class="op">;</span></span>
<span id="cb5-46"><a href="#cb5-46" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> x <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span> <span class="op">{</span></span>
<span id="cb5-47"><a href="#cb5-47" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span> <span class="ot">&#39;s_73</span><span class="op">;</span></span>
<span id="cb5-48"><a href="#cb5-48" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb5-49"><a href="#cb5-49" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb5-50"><a href="#cb5-50" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">5</span><span class="op">;</span></span>
<span id="cb5-51"><a href="#cb5-51" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-52"><a href="#cb5-52" aria-hidden="true" tabindex="-1"></a>    out <span class="op">+=</span> <span class="dv">6</span><span class="op">;</span></span>
<span id="cb5-53"><a href="#cb5-53" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="the-structured-programming-theorem-folk-version">The Structured
Programming Theorem: Folk version</h2>
<p>The folk theorem of the structured programming theorem has a simple
kernel: interpret the unstructured part as a subprogram and hand-write a
tiny interpreter for it.</p>
<p>We create a value that’s our program counter (in this case,
<code>__switch_case0</code>). Since the switch only checks
<code>x</code>, we can assign this to <code>x</code>, and map the
different case branches (1,2,3,4,default) to one number per distinct
case (0,1,2,3,4).</p>
<p>Afterwards, we enter the interpreter and interpret the program. Any
node that has a break, say 1, 3, 4 (which line up with the switches that
have breaks in the C program break out of the loop immediately. To
handle fall through, the cases set <code>__switch_case0</code> to the
next execution. In this case, since we only have fallthrough, it will
always be the next block (0 sets <code>__switch_case0</code> to 1), (2
sets <code>__switch_case0</code> to 3). This program emulates the C’s
switch code perfectly.</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> x <span class="op">=</span> <span class="dv">1</span><span class="op">;</span> <span class="co">// what we call the function with, in this case 1</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>        <span class="co">// the mapping of switch cases to unique blocks:</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> <span class="kw">mut</span> __switch_case0<span class="op">:</span> <span class="dt">i32</span> <span class="op">=</span> <span class="cf">match</span> x <span class="op">{</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>            <span class="dv">1</span> <span class="op">=&gt;</span> <span class="dv">0</span><span class="op">,</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>            <span class="dv">2</span> <span class="op">=&gt;</span> <span class="dv">1</span><span class="op">,</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>            <span class="dv">3</span> <span class="op">=&gt;</span> <span class="dv">2</span><span class="op">,</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>            <span class="dv">4</span> <span class="op">=&gt;</span> <span class="dv">3</span><span class="op">,</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>            _ <span class="op">=&gt;</span> <span class="dv">4</span><span class="op">,</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">};</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>        <span class="ot">&#39;__switch0</span><span class="op">:</span> <span class="cf">loop</span> <span class="op">{</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>            <span class="cf">match</span> __switch_case0 <span class="op">{</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>                <span class="dv">0</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>                    out <span class="op">+=</span> <span class="dv">10</span><span class="op">;</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a>                    <span class="co">// in the fallthrough case, we increment __switch_case by 1</span></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a>                    <span class="co">// and then continue</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a>                    __switch_case0 <span class="op">=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">continue</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a>                <span class="dv">1</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a>                    out <span class="op">+=</span> <span class="dv">20</span><span class="op">;</span></span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a>                    <span class="co">// for a fallthrough case we generate a break. This</span></span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true" tabindex="-1"></a>                    <span class="co">// can be elided, but it&#39;s left here to be explicit</span></span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">break</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb6-27"><a href="#cb6-27" aria-hidden="true" tabindex="-1"></a>                <span class="dv">2</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb6-28"><a href="#cb6-28" aria-hidden="true" tabindex="-1"></a>                    __switch_case0 <span class="op">=</span> <span class="dv">3</span><span class="op">;</span></span>
<span id="cb6-29"><a href="#cb6-29" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">continue</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb6-30"><a href="#cb6-30" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb6-31"><a href="#cb6-31" aria-hidden="true" tabindex="-1"></a>                <span class="dv">3</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb6-32"><a href="#cb6-32" aria-hidden="true" tabindex="-1"></a>                    out <span class="op">+=</span> <span class="dv">40</span><span class="op">;</span></span>
<span id="cb6-33"><a href="#cb6-33" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">break</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb6-34"><a href="#cb6-34" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb6-35"><a href="#cb6-35" aria-hidden="true" tabindex="-1"></a>                <span class="dv">4</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb6-36"><a href="#cb6-36" aria-hidden="true" tabindex="-1"></a>                    out <span class="op">+=</span> <span class="dv">90</span><span class="op">;</span></span>
<span id="cb6-37"><a href="#cb6-37" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">break</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb6-38"><a href="#cb6-38" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb6-39"><a href="#cb6-39" aria-hidden="true" tabindex="-1"></a>                _ <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb6-40"><a href="#cb6-40" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">break</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb6-41"><a href="#cb6-41" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb6-42"><a href="#cb6-42" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb6-43"><a href="#cb6-43" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb6-44"><a href="#cb6-44" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-45"><a href="#cb6-45" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This version is worse than what relooper generates. However, for the
7 fallthrough version, note that we’re guaranteed only one outer loop
for our match, because the dispatcher (<code>__switch_case0</code>) at
the top handles control flow.</p>
<p>Personally, I find this much more readable than 7 nested levels, so I
chose this as the default lowering representation of a switch.</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> out<span class="op">:</span> <span class="dt">i32</span> <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> __switch_value0 <span class="op">=</span> <span class="op">...;</span> <span class="co">// whatever the value is</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> <span class="kw">mut</span> __switch_case0<span class="op">:</span> <span class="dt">i32</span> <span class="op">=</span> <span class="cf">match</span> __switch_value0 <span class="op">{</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>            <span class="op">-</span><span class="dv">500</span><span class="op">..=-</span><span class="dv">1</span> <span class="op">=&gt;</span> <span class="dv">0</span><span class="op">,</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>            <span class="dv">0</span> <span class="op">=&gt;</span> <span class="dv">1</span><span class="op">,</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>            <span class="dv">1</span> <span class="op">=&gt;</span> <span class="dv">2</span><span class="op">,</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>            <span class="dv">2</span><span class="op">..=</span><span class="dv">100</span> <span class="op">=&gt;</span> <span class="dv">3</span><span class="op">,</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>            <span class="dv">101</span> <span class="op">=&gt;</span> <span class="dv">4</span><span class="op">,</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>            <span class="dv">200</span><span class="op">..=</span><span class="dv">500</span> <span class="op">=&gt;</span> <span class="dv">6</span><span class="op">,</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>            <span class="dv">600</span> <span class="op">=&gt;</span> <span class="dv">7</span><span class="op">,</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a>            <span class="dv">700</span><span class="op">..=</span><span class="dv">900</span> <span class="op">=&gt;</span> <span class="dv">8</span><span class="op">,</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a>            <span class="dv">999</span> <span class="op">=&gt;</span> <span class="dv">9</span><span class="op">,</span></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a>            <span class="dv">1000</span> <span class="op">=&gt;</span> <span class="dv">10</span><span class="op">,</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a>            _ <span class="op">=&gt;</span> <span class="dv">5</span><span class="op">,</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a>        <span class="op">};</span></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true" tabindex="-1"></a>        <span class="ot">&#39;__switch0</span><span class="op">:</span> <span class="cf">loop</span> <span class="op">{</span></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true" tabindex="-1"></a>            <span class="cf">match</span> __switch_case0 <span class="op">{</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true" tabindex="-1"></a>                <span class="dv">0</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true" tabindex="-1"></a>                    out <span class="op">+=</span> <span class="dv">100</span><span class="op">;</span></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true" tabindex="-1"></a>                    __switch_case0 <span class="op">=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">continue</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb7-25"><a href="#cb7-25" aria-hidden="true" tabindex="-1"></a>                <span class="dv">1</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb7-26"><a href="#cb7-26" aria-hidden="true" tabindex="-1"></a>                    __switch_case0 <span class="op">=</span> <span class="dv">2</span><span class="op">;</span></span>
<span id="cb7-27"><a href="#cb7-27" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">continue</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb7-28"><a href="#cb7-28" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb7-29"><a href="#cb7-29" aria-hidden="true" tabindex="-1"></a>                <span class="dv">2</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb7-30"><a href="#cb7-30" aria-hidden="true" tabindex="-1"></a>                    out <span class="op">+=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb7-31"><a href="#cb7-31" aria-hidden="true" tabindex="-1"></a>                    __switch_case0 <span class="op">=</span> <span class="dv">3</span><span class="op">;</span></span>
<span id="cb7-32"><a href="#cb7-32" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">continue</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb7-33"><a href="#cb7-33" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb7-34"><a href="#cb7-34" aria-hidden="true" tabindex="-1"></a>                <span class="dv">3</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb7-35"><a href="#cb7-35" aria-hidden="true" tabindex="-1"></a>                    out <span class="op">+=</span> <span class="dv">2</span><span class="op">;</span></span>
<span id="cb7-36"><a href="#cb7-36" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">if</span> out <span class="op">&gt;</span> <span class="dv">50</span> <span class="op">{</span></span>
<span id="cb7-37"><a href="#cb7-37" aria-hidden="true" tabindex="-1"></a>                        <span class="cf">break</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb7-38"><a href="#cb7-38" aria-hidden="true" tabindex="-1"></a>                    <span class="op">}</span></span>
<span id="cb7-39"><a href="#cb7-39" aria-hidden="true" tabindex="-1"></a>                    out <span class="op">+=</span> <span class="dv">3</span><span class="op">;</span></span>
<span id="cb7-40"><a href="#cb7-40" aria-hidden="true" tabindex="-1"></a>                    __switch_case0 <span class="op">=</span> <span class="dv">4</span><span class="op">;</span></span>
<span id="cb7-41"><a href="#cb7-41" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">continue</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb7-42"><a href="#cb7-42" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb7-43"><a href="#cb7-43" aria-hidden="true" tabindex="-1"></a>                <span class="dv">4</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb7-44"><a href="#cb7-44" aria-hidden="true" tabindex="-1"></a>                    out <span class="op">+=</span> <span class="dv">4</span><span class="op">;</span></span>
<span id="cb7-45"><a href="#cb7-45" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">if</span> x <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span> <span class="op">{</span></span>
<span id="cb7-46"><a href="#cb7-46" aria-hidden="true" tabindex="-1"></a>                        <span class="cf">break</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb7-47"><a href="#cb7-47" aria-hidden="true" tabindex="-1"></a>                    <span class="op">}</span></span>
<span id="cb7-48"><a href="#cb7-48" aria-hidden="true" tabindex="-1"></a>                    __switch_case0 <span class="op">=</span> <span class="dv">5</span><span class="op">;</span></span>
<span id="cb7-49"><a href="#cb7-49" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">continue</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb7-50"><a href="#cb7-50" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb7-51"><a href="#cb7-51" aria-hidden="true" tabindex="-1"></a>                <span class="dv">5</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb7-52"><a href="#cb7-52" aria-hidden="true" tabindex="-1"></a>                    out <span class="op">+=</span> <span class="dv">5</span><span class="op">;</span></span>
<span id="cb7-53"><a href="#cb7-53" aria-hidden="true" tabindex="-1"></a>                    __switch_case0 <span class="op">=</span> <span class="dv">6</span><span class="op">;</span></span>
<span id="cb7-54"><a href="#cb7-54" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">continue</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb7-55"><a href="#cb7-55" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb7-56"><a href="#cb7-56" aria-hidden="true" tabindex="-1"></a>                <span class="dv">6</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb7-57"><a href="#cb7-57" aria-hidden="true" tabindex="-1"></a>                    __switch_case0 <span class="op">=</span> <span class="dv">7</span><span class="op">;</span></span>
<span id="cb7-58"><a href="#cb7-58" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">continue</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb7-59"><a href="#cb7-59" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb7-60"><a href="#cb7-60" aria-hidden="true" tabindex="-1"></a>                <span class="dv">7</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb7-61"><a href="#cb7-61" aria-hidden="true" tabindex="-1"></a>                    __switch_case0 <span class="op">=</span> <span class="dv">8</span><span class="op">;</span></span>
<span id="cb7-62"><a href="#cb7-62" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">continue</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb7-63"><a href="#cb7-63" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb7-64"><a href="#cb7-64" aria-hidden="true" tabindex="-1"></a>                <span class="dv">8</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb7-65"><a href="#cb7-65" aria-hidden="true" tabindex="-1"></a>                    out <span class="op">+=</span> <span class="dv">6</span><span class="op">;</span></span>
<span id="cb7-66"><a href="#cb7-66" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">break</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb7-67"><a href="#cb7-67" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb7-68"><a href="#cb7-68" aria-hidden="true" tabindex="-1"></a>                <span class="dv">9</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb7-69"><a href="#cb7-69" aria-hidden="true" tabindex="-1"></a>                    out <span class="op">+=</span> <span class="dv">7</span><span class="op">;</span></span>
<span id="cb7-70"><a href="#cb7-70" aria-hidden="true" tabindex="-1"></a>                    __switch_case0 <span class="op">=</span> <span class="dv">10</span><span class="op">;</span></span>
<span id="cb7-71"><a href="#cb7-71" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">continue</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb7-72"><a href="#cb7-72" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb7-73"><a href="#cb7-73" aria-hidden="true" tabindex="-1"></a>                <span class="dv">10</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb7-74"><a href="#cb7-74" aria-hidden="true" tabindex="-1"></a>                    out <span class="op">+=</span> <span class="dv">8</span><span class="op">;</span></span>
<span id="cb7-75"><a href="#cb7-75" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">break</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb7-76"><a href="#cb7-76" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb7-77"><a href="#cb7-77" aria-hidden="true" tabindex="-1"></a>                _ <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb7-78"><a href="#cb7-78" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">break</span> <span class="ot">&#39;__switch0</span><span class="op">;</span></span>
<span id="cb7-79"><a href="#cb7-79" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb7-80"><a href="#cb7-80" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb7-81"><a href="#cb7-81" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb7-82"><a href="#cb7-82" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-83"><a href="#cb7-83" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Now let’s do better. Note that the CFG only goes one direction
(down). So each node in the CFG does the following:</p>
<ol type="1">
<li>Executes its block</li>
<li>Either (breaks to end or falls through to the next branch)</li>
</ol>
<p>We can use this to optimize our representation of our match by taking
the switch case bottom up. The rules are simple:</p>
<ul>
<li><code>default</code> is translated to <code>_</code>. Keep in mind
that <code>default</code> can fallthrough (<code>_</code> in rust
cannot) so we must always move the <code>_</code> pattern to the end of
the switch case and handle fallthrough.</li>
<li>We traverse the switch case bottom-up, and collect the blocks we’ve
seen in reverse order and the labels we’ve seen. On break, for each
label we’ll write the blocks we’ve seen in reverse order (since we’re
traversing in reverse, this will write out the blocks in the proper
order) for each label we’ve seen. Then we’ll clear our cache of blocks
and labels.</li>
<li>We stop when we hit the start of the block and clear our current
cache of blocks and labels.</li>
</ul>
<p>Since this is a straight-line construction, we can prove this with
induction:</p>
<p><em>Invariant:</em> right before we process case <code>i</code>, the
buffer holds exactly the code that runs when control jumps into case
<code>i + 1</code>’s label and executes until the next
<code>break</code> or the end of the switch.</p>
<p><em>Step:</em> if case <code>i</code> has no break, prepending its
block to the buffer gives exactly the code that runs from a jump into
case <code>i</code>’s label, so the buffer now satisfies the invariant
for <code>i</code>. If case <code>i</code> has a break, the buffer for
<code>i</code> is just its own block, since nothing after it is ever
reached from a jump to <code>i</code>.</p>
<p>So by induction, the buffer at the moment we flush label
<code>L</code> always equals C’s fallthrough semantics for entering at
<code>L</code> which is exactly what a <code>match</code> arm needs to
contain.</p>
<p>So let’s run through this example:</p>
<table>
<colgroup>
<col style="width: 3%" />
<col style="width: 26%" />
<col style="width: 17%" />
<col style="width: 12%" />
<col style="width: 40%" />
</colgroup>
<thead>
<tr>
<th>Step</th>
<th>What we see (bottom-up)</th>
<th>Buffered blocks</th>
<th>Buffered labels</th>
<th>Emitted</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><code>default:</code> block <code>out += 90</code></td>
<td><code>out += 90</code></td>
<td><code>_</code></td>
<td>-</td>
</tr>
<tr>
<td>2</td>
<td>end of switch (implicit break)</td>
<td>-</td>
<td>-</td>
<td><code>_ =&gt; out += 90</code></td>
</tr>
<tr>
<td>3</td>
<td><code>break</code> (before <code>default</code>)</td>
<td>-</td>
<td>-</td>
<td>(clear buffer)</td>
</tr>
<tr>
<td>4</td>
<td><code>case 4:</code> block <code>out += 40</code></td>
<td><code>out += 40</code></td>
<td><code>4</code></td>
<td>-</td>
</tr>
<tr>
<td>5</td>
<td><code>case 3:</code> (empty)</td>
<td><code>out += 40</code></td>
<td><code>3, 4</code></td>
<td>-</td>
</tr>
<tr>
<td>6</td>
<td><code>break</code> (before <code>case 3</code>)</td>
<td>-</td>
<td>-</td>
<td><code>3 =&gt; out += 40;</code> <code>4 =&gt; out += 40;</code>
(clear buffer)</td>
</tr>
<tr>
<td>7</td>
<td><code>case 2:</code> block <code>out += 20</code></td>
<td><code>out += 20</code></td>
<td><code>2</code></td>
<td>-</td>
</tr>
<tr>
<td>8</td>
<td><code>case 1:</code> block <code>out += 10</code></td>
<td><code>out += 10; out += 20</code></td>
<td><code>1, 2</code></td>
<td>-</td>
</tr>
<tr>
<td>9</td>
<td>start of switch (implicit break)</td>
<td>-</td>
<td>-</td>
<td><code>1 =&gt; out += 10; out += 20;</code>
<code>2 =&gt; out += 20;</code></td>
</tr>
</tbody>
</table>
<p>That gets us this:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="cf">match</span> x <span class="op">{</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>    <span class="dv">1</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">10</span><span class="op">;</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">20</span><span class="op">;</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>    <span class="dv">2</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">20</span><span class="op">;</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>    <span class="dv">3</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">40</span><span class="op">;</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>    <span class="dv">4</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">40</span><span class="op">;</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">90</span><span class="op">;</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>We can converge identical blocks, so note 3 and 4 are the same, so
the block can be deleted and the label for 3 can be replaced with either
<code>|</code> for or or you can use a range (for types that can).</p>
<p>This gets us:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="cf">match</span> x <span class="op">{</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>    <span class="dv">1</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">10</span><span class="op">;</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">20</span><span class="op">;</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>    <span class="dv">2</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">20</span><span class="op">;</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>    <span class="dv">3</span> <span class="op">|</span> <span class="dv">4</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">40</span><span class="op">;</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">90</span><span class="op">;</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Which is exactly what I would handwrite in a translation.</p>
<p>With a little range coalescing, this also handles the 7 fallthrough
case:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="cf">match</span> x <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">-</span><span class="dv">500</span><span class="op">..=-</span><span class="dv">1</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">100</span><span class="op">;</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">2</span><span class="op">;</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> out <span class="op">&gt;</span> <span class="dv">50</span> <span class="op">{</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>            out <span class="op">+=</span> <span class="dv">3</span><span class="op">;</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>            out <span class="op">+=</span> <span class="dv">4</span><span class="op">;</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> x <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span> <span class="op">{</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>                out <span class="op">+=</span> <span class="dv">5</span><span class="op">;</span></span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a>                out <span class="op">+=</span> <span class="dv">6</span><span class="op">;</span></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span> <span class="op">|</span> <span class="dv">1</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">2</span><span class="op">;</span></span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> out <span class="op">&gt;</span> <span class="dv">50</span> <span class="op">{</span></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true" tabindex="-1"></a>            out <span class="op">+=</span> <span class="dv">3</span><span class="op">;</span></span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true" tabindex="-1"></a>            out <span class="op">+=</span> <span class="dv">4</span><span class="op">;</span></span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> x <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span> <span class="op">{</span></span>
<span id="cb10-25"><a href="#cb10-25" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb10-26"><a href="#cb10-26" aria-hidden="true" tabindex="-1"></a>                out <span class="op">+=</span> <span class="dv">5</span><span class="op">;</span></span>
<span id="cb10-27"><a href="#cb10-27" aria-hidden="true" tabindex="-1"></a>                out <span class="op">+=</span> <span class="dv">6</span><span class="op">;</span></span>
<span id="cb10-28"><a href="#cb10-28" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb10-29"><a href="#cb10-29" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb10-30"><a href="#cb10-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-31"><a href="#cb10-31" aria-hidden="true" tabindex="-1"></a>    <span class="dv">2</span><span class="op">..=</span><span class="dv">100</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb10-32"><a href="#cb10-32" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">2</span><span class="op">;</span></span>
<span id="cb10-33"><a href="#cb10-33" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> out <span class="op">&gt;</span> <span class="dv">50</span> <span class="op">{</span></span>
<span id="cb10-34"><a href="#cb10-34" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb10-35"><a href="#cb10-35" aria-hidden="true" tabindex="-1"></a>            out <span class="op">+=</span> <span class="dv">3</span><span class="op">;</span></span>
<span id="cb10-36"><a href="#cb10-36" aria-hidden="true" tabindex="-1"></a>            out <span class="op">+=</span> <span class="dv">4</span><span class="op">;</span></span>
<span id="cb10-37"><a href="#cb10-37" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> x <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span> <span class="op">{</span></span>
<span id="cb10-38"><a href="#cb10-38" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb10-39"><a href="#cb10-39" aria-hidden="true" tabindex="-1"></a>                out <span class="op">+=</span> <span class="dv">5</span><span class="op">;</span></span>
<span id="cb10-40"><a href="#cb10-40" aria-hidden="true" tabindex="-1"></a>                out <span class="op">+=</span> <span class="dv">6</span><span class="op">;</span></span>
<span id="cb10-41"><a href="#cb10-41" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb10-42"><a href="#cb10-42" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb10-43"><a href="#cb10-43" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-44"><a href="#cb10-44" aria-hidden="true" tabindex="-1"></a>    <span class="dv">101</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb10-45"><a href="#cb10-45" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">4</span><span class="op">;</span></span>
<span id="cb10-46"><a href="#cb10-46" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> x <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span> <span class="op">{</span></span>
<span id="cb10-47"><a href="#cb10-47" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb10-48"><a href="#cb10-48" aria-hidden="true" tabindex="-1"></a>            out <span class="op">+=</span> <span class="dv">5</span><span class="op">;</span></span>
<span id="cb10-49"><a href="#cb10-49" aria-hidden="true" tabindex="-1"></a>            out <span class="op">+=</span> <span class="dv">6</span><span class="op">;</span></span>
<span id="cb10-50"><a href="#cb10-50" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb10-51"><a href="#cb10-51" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-52"><a href="#cb10-52" aria-hidden="true" tabindex="-1"></a>    <span class="dv">200</span><span class="op">..=</span><span class="dv">500</span> <span class="op">|</span> <span class="dv">600</span> <span class="op">|</span> <span class="dv">700</span><span class="op">..=</span><span class="dv">900</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb10-53"><a href="#cb10-53" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">6</span><span class="op">;</span></span>
<span id="cb10-54"><a href="#cb10-54" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-55"><a href="#cb10-55" aria-hidden="true" tabindex="-1"></a>    <span class="dv">999</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb10-56"><a href="#cb10-56" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">7</span><span class="op">;</span></span>
<span id="cb10-57"><a href="#cb10-57" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">8</span><span class="op">;</span></span>
<span id="cb10-58"><a href="#cb10-58" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-59"><a href="#cb10-59" aria-hidden="true" tabindex="-1"></a>    <span class="dv">1000</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb10-60"><a href="#cb10-60" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">8</span><span class="op">;</span></span>
<span id="cb10-61"><a href="#cb10-61" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-62"><a href="#cb10-62" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb10-63"><a href="#cb10-63" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">5</span><span class="op">;</span></span>
<span id="cb10-64"><a href="#cb10-64" aria-hidden="true" tabindex="-1"></a>        out <span class="op">+=</span> <span class="dv">6</span><span class="op">;</span></span>
<span id="cb10-65"><a href="#cb10-65" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-66"><a href="#cb10-66" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Some improvement could be made to hoist the
<code>if out &gt; 50 {} else {}</code> out, since there are lots of
repeated sub blocks here, but that’s for another time.</p>
<h2 id="generality-aint-all-its-cracked-up-to-be">Generality ain’t all
it’s cracked up to be</h2>
<p>Handling the general case is hard. For C2Rust, relooper is the way to
go because the switch might have a stray goto out of it, and because its
first pass is only transpilation with an optional post-processing
pass.</p>
<p>Slate’s first lowering pass is pretty similar (I chose to implement
the folk theorem in the lowering phase for its simplicity, even if it
has worse output). However, Slate has an advantage in that it runs
post-processing, so it can consume lowered output and recover structure
from it. Thus, we can apply the bottom up algorithm conservatively and
get the ideal match output from the conclusion for almost every
switch.</p>]]></description>
</item>
<item>
<title>One libc for all</title>
<pubDate>Tue, 01 Sep 2026 12:57:15 +0000</pubDate>
<guid>https://blog/one-libc-for-all.html</guid>
<description><![CDATA[<p>I’ve been working on <a
href="https://github.com/takashiidobe/slate">Slate</a>, a C to Rust
translator. Take a look at the previous post here: <a
href="./translating-long-double-to-rust.md">Translating long double to
rust</a>. Today’s topic is why slate provides its own libc that it links
to, and why that’s useful for a c to rust transpiler.</p>
<p>When I first started out on slate, I didn’t link to a custom libc.
Why would you, you install a compiler, it’s automatically pointed at the
libc you have configured, and you can start compiling. The compiler has
everything you need. This works for a single target setup. If you’re
compiling code for only your target (I’m on x86_64-unknown-linux-gnu).
However, C and Rust are both easily cross compiled for other
targets.</p>
<p>There are a series of preprocessor macros that are defined per
target, which can enable and disable code. For a very trivial example,
here’s a program that prints differently based on if you’re on x86_64 or
not:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="pp">#if defined(__x86_64__)</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    puts<span class="op">(</span><span class="st">&quot;hi from x86_64&quot;</span><span class="op">);</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="pp">#else</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    puts<span class="op">(</span><span class="st">&quot;hi from any other architecture&quot;</span><span class="op">);</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>When compiling the program, some C compilers like gcc and clang will
define the <code>__x86_64__</code> macro when compiling your code,
setting it only for x86_64 systems, so it’s possible to test for it.
Because the preprocessor can only choose one block here, the actual
programs that the C compiler will see after preprocessing are
either:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    puts<span class="op">(</span><span class="st">&quot;hi from x86_64&quot;</span><span class="op">);</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Or:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    puts<span class="op">(</span><span class="st">&quot;hi from any other architecture&quot;</span><span class="op">);</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This is fine and dandy. Rust also has a similar mechanism
(<code>#[cfg(...)]</code>) blocks that let us do the same thing, so this
is semantically the same program:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="pp">cfg!</span>(target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span>) <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>        <span class="pp">println!</span>(<span class="st">&quot;hi from x86_64&quot;</span>)<span class="op">;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>        <span class="pp">println!</span>(<span class="st">&quot;hi from any other architecture&quot;</span>)<span class="op">;</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Now the crux is that we want to take the C program and translate it
to Rust. How do we do that? The C preprocessor plays a cruel trick on us
– since it only preserves blocks that are enabled for you (either
through <code>-D...</code> or through the compiler, you can’t actually
see the full program, you’ll only see the program after preprocessing.
So, we could say translate to:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="pp">println!</span>(<span class="st">&quot;hi from x86_64&quot;</span>)<span class="op">;</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// or this: println!(&quot;hi from any other architecture&quot;);</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>But we’d have lost cross compilation.</p>
<p>What’s even worse in a way is that this program is wrong – on a
non-x86_64 architecture, you want to see
<code>hi from any other architecture</code>, but you’ll see
<code>hi from x86_64</code> regardless of what target you compile
for.</p>
<p>One half of the problem is how to splice the preprocessor blocks such
that we can recover the original program. That’s for another time.
However, C also allows us to configure our build differently based on
different flags, which is really useful.</p>
<p>For an example here, I have a macro that I use for setting memory
alignment:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#if defined(__STDC_VERSION__) &amp;&amp; __STDC_VERSION__ &gt;= 202311L</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#define __aligned</span><span class="op">(</span><span class="pp">X</span><span class="op">)</span><span class="pp"> </span><span class="op">[[</span><span class="at">aligned</span><span class="op">(</span><span class="at">X</span><span class="op">)]]</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#elif defined(__STDC_VERSION__) &amp;&amp; __STDC_VERSION__ &gt;= 201112L</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="pp">#define __aligned</span><span class="op">(</span><span class="pp">X</span><span class="op">)</span><span class="pp"> </span><span class="kw">_Alignas</span><span class="op">(</span><span class="pp">X</span><span class="op">)</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="pp">#elif defined(__GNUC__) || defined(__clang__)</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="pp">#define __aligned</span><span class="op">(</span><span class="pp">X</span><span class="op">)</span><span class="pp"> __attribute__</span><span class="op">((</span><span class="pp">aligned</span><span class="op">(</span><span class="pp">X</span><span class="op">)))</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a><span class="pp">#elif defined(_MSC_VER)</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="pp">#define __aligned</span><span class="op">(</span><span class="pp">X</span><span class="op">)</span><span class="pp"> __declspec</span><span class="op">(</span><span class="pp">align</span><span class="op">(</span><span class="pp">X</span><span class="op">))</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a><span class="pp">#else</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a><span class="pp">#define __aligned</span><span class="op">(</span><span class="pp">X</span><span class="op">)</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span></code></pre></div>
<p>Different compilers and different versions of the c standard library
have different ways of expressing this concept. Since this was
non-standard until C11, MSVC and clang chose different ways to express
this concept. However, until C11, since this was not in the standard,
compilers didn’t need to have a way to express it. In that case, aligned
is defined as an empty string.</p>
<p>This is an important part of C, and without support for this, you can
only support truly standard C that uses no architecture specific
features or compiler features. Thus, to translate C, Slate needs to
provide this faculty.</p>
<p>Thinking back to the start of this blog post though, our target only
has a standard library for our target. So slate can’t rely on the user’s
libc for platform code, and has to provide its own libc. To actually
compile a whole matrix of libc code, slate defines target specific
macros in its own libc:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#if defined(__SLATE_ARCH_X86_64) + defined(__SLATE_ARCH_X86) +                 </span><span class="op">\</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="pp">        defined(__SLATE_ARCH_AARCH64) + defined(__SLATE_ARCH_ARM) +            </span><span class="op">\</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="pp">        defined(__SLATE_ARCH_RISCV64) + defined(__SLATE_ARCH_RISCV32) !=       </span><span class="op">\</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="pp">#error &quot;Slate requires one supported target architecture.&quot;</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span></code></pre></div>
<p>Which are passed at build time based on the target that’s requested
to be cross compiled:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="pp">FixtureFlavor::</span>Macos <span class="op">=&gt;</span> <span class="op">&amp;</span>[</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;-D_SLATE_LIBC&quot;</span><span class="op">,</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;-D__SLATE_ARCH_AARCH64&quot;</span><span class="op">,</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;-D__SLATE_VENDOR_APPLE&quot;</span><span class="op">,</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;-D__SLATE_KERNEL_DARWIN&quot;</span><span class="op">,</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;-D__SLATE_PLATFORM_MACOS&quot;</span><span class="op">,</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;-D__SLATE_LIBC_DARWIN&quot;</span><span class="op">,</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;-D__SLATE_OBJ_MACHO&quot;</span><span class="op">,</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;-D__SLATE_WORDSIZE_64&quot;</span><span class="op">,</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;-D__SLATE_ENDIAN_LITTLE&quot;</span><span class="op">,</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>]<span class="op">,</span></span></code></pre></div>
<p>This allows slate’s libc, libc-shim, to be compiled for different
targets and still show one consistent libc for rust externs to link
to.</p>
<h2 id="the-strerror_r-incident">the <code>strerror_r</code>
incident</h2>
<p>Here’s a question for you, dear reader. What’s the signature of
<code>strerror_r</code>?</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> strerror_r<span class="op">(</span><span class="dt">int</span> errnum<span class="op">,</span> <span class="dt">char</span> <span class="op">*</span>buf<span class="op">,</span> <span class="dt">size_t</span> buflen<span class="op">);</span></span></code></pre></div>
<p>or is it?</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="dt">char</span> <span class="op">*</span>strerror_r<span class="op">(</span><span class="dt">int</span> errnum<span class="op">,</span> <span class="dt">char</span> <span class="op">*</span>buf<span class="op">,</span> <span class="dt">size_t</span> buflen<span class="op">);</span></span></code></pre></div>
<p>The answer is it depends based on which libc you’re using. The first
definition is the standard one, and the second one is the gnu extended
one.</p>
<p>This would be fine on systems with 32-bit pointers, but nowadays
those are rarer, we live in the 64-bit world. So these have different
ABIs. It’s not really that bad except for the fact that
<code>strerror_r</code> has different behavior in the gnu version than
it does for the standard one.</p>
<p>And so any C program translated to Rust on a glibc system vs a musl
one where the signatures agree will have diverging behavior, and any
where you compile on a 64-bit system will simply not recompile.
Wonderful.</p>
<h2 id="qsort_r-has-different-signatures"><code>qsort_r</code> has
different signatures</h2>
<p>What’s the signature of <code>qsort_r</code> in freebsd?</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> qsort_r<span class="op">(</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="op">*</span>base<span class="op">,</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> nmemb<span class="op">,</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> size<span class="op">,</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="op">*</span>thunk<span class="op">,</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="op">(*</span>cmp<span class="op">)(</span><span class="dt">void</span> <span class="op">*,</span> <span class="dt">const</span> <span class="dt">void</span> <span class="op">*,</span> <span class="dt">const</span> <span class="dt">void</span> <span class="op">*)</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
<p>or is it?</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> qsort_r<span class="op">(</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="op">*</span>base<span class="op">,</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> nmemb<span class="op">,</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> size<span class="op">,</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="op">(*</span>cmp<span class="op">)(</span><span class="dt">const</span> <span class="dt">void</span> <span class="op">*,</span> <span class="dt">const</span> <span class="dt">void</span> <span class="op">*,</span> <span class="dt">void</span> <span class="op">*),</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="op">*</span>thunk</span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
<p>As you might expect the answer is both of them are valid. The first
version is the standard POSIX version, and the second one is the old BSD
version, which was different. Since the first version was standardized
in 2024, freebsd decided to do a swap. So if you were to compile on a
newer version of freebsd and send your transpiled code to an older
version (or vice versa), your code would be incorrect. C side this is
fine because the linker will choose the correct symbol, but the externs
in rust won’t line up if translated through slate.</p>
<p>Both of these problems (and others) can be handled if you control the
libc itself – you can link older versions of code for compatibility, or
choose the right version to match the target and use
<code>#[cfg]</code>s to have cross target and cross version code work
just fine.</p>]]></description>
</item>
<item>
<title>Translating Long Double to Rust</title>
<pubDate>Wed, 12 Aug 2026 16:04:52 +0000</pubDate>
<guid>https://blog/translating-long-double-to-rust.html</guid>
<description><![CDATA[<p>I’ve been working on <a
href="https://github.com/takashiidobe/slate">Slate</a>, a C to Rust
translator. There are a few particularly thorny parts of translating C
to Rust, but given how much <code>long double</code> made me suffer,
I’ve decided to write it up.</p>
<p>If you’ve never used <code>long double</code>, you may breathe a sigh
of relief. If you use either <code>f64</code> (<code>double</code>) or
<code>f128</code>s (<code>_Float128/__float128</code>) then you’re
absolved of sin and free to go. The heathens who wish to learn suffering
may stay till the rest of the post to learn more.</p>
<p><code>long double</code> has been around since C89. The standard just
says that it must be as precise as <code>double</code>
(<code>f64</code>). Because of this, long double can be pretty much any
bit-size from 64-bits to infinite bits. In practice, there are a few
dominant ones:</p>
<ol type="1">
<li>f64. MSVC does this for x86.</li>
<li>f80. GCC + Clang do this for x86. This is padded to 12-bytes or
16-bytes.</li>
<li>double-double. Two f64s glued together. For older PowerPC and IBM
architectures.</li>
<li>f128. Arm64, PowerPC, RISC-V.</li>
</ol>
<p><code>f64</code> and <code>f128</code> are not hard to support. On a
target where <code>long double</code> ==
<code>f64</code>/<code>f128</code>, you would just swap out every long
double you see for the appropriate type in rust, and when you pass it to
extern C code, it’ll be bit aligned and properly handled.</p>
<p><code>f80</code> is the real problem, and what the rest of the blog
will explain. Afaik, <a
href="https://github.com/immunant/c2rust/issues/1723">C2Rust doesn’t
support <code>long double</code> properly because it translates to
f128</a>. There have been efforts in the past to add <code>f80</code>
support, but this’ll probably take a while.</p>
<h2 id="representing-f80">Representing f80</h2>
<p>With long double, we need to be able to do anything you would
normally be able to do with the type in C. That means the arithmetic
ops, casting to and from, passing to functions as value or pointer, and
being able to use it in callbacks.</p>
<p>A first try is this:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>repr<span class="at">(</span>C<span class="op">,</span> align<span class="at">(</span><span class="dv">16</span><span class="at">))]</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>derive<span class="at">(</span><span class="bu">Clone</span><span class="op">,</span> <span class="bu">Copy</span><span class="at">)]</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">struct</span> LongDouble <span class="op">{</span> bytes<span class="op">:</span> [<span class="dt">u8</span><span class="op">;</span> <span class="dv">10</span>] <span class="op">};</span></span></code></pre></div>
<p>With this we fulfill the requirements of its size and alignment. We
could then even emulate the f80 math itself in rust, so when you call
any long double function that has been translated to rust, and call a
non-translated C function, the bits are all perfectly legal.</p>
<p>Sadly, long doubles are passed in floating point registers, whereas
these chars are passed in general purpose registers, so trying to
implement this as is will cause corruption.</p>
<p>We can have the rust type be plain bytes and implement every
operation as asm:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">unsafe</span> <span class="kw">fn</span> add(<span class="kw">self</span><span class="op">,</span> rhs<span class="op">:</span> <span class="dt">Self</span>) <span class="op">-&gt;</span> <span class="dt">Self</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> out <span class="op">=</span> LongDouble <span class="op">{</span> bytes<span class="op">:</span> [<span class="dv">0</span><span class="op">;</span> <span class="dv">10</span>] <span class="op">};</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">unsafe</span> <span class="op">{</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>        <span class="pp">core::arch::asm!</span>(</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;fld tbyte ptr [{a}]&quot;</span><span class="op">,</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;fld tbyte ptr [{b}]&quot;</span><span class="op">,</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;faddp st(1), st(0)&quot;</span><span class="op">,</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;fstp tbyte ptr [{out}]&quot;</span><span class="op">,</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>            a   <span class="op">=</span> <span class="kw">in</span>(reg) <span class="kw">self</span><span class="op">.</span>bytes<span class="op">.</span>as_ptr()<span class="op">,</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>            b   <span class="op">=</span> <span class="kw">in</span>(reg) rhs<span class="op">.</span>bytes<span class="op">.</span>as_ptr()<span class="op">,</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>            out <span class="op">=</span> <span class="kw">in</span>(reg) out<span class="op">.</span>bytes<span class="op">.</span>as_mut_ptr()<span class="op">,</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>            out(<span class="st">&quot;st(0)&quot;</span>) _<span class="op">,</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>            out(<span class="st">&quot;st(1)&quot;</span>) _<span class="op">,</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>            out(<span class="st">&quot;st(2)&quot;</span>) _<span class="op">,</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>            out(<span class="st">&quot;st(3)&quot;</span>) _<span class="op">,</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>            out(<span class="st">&quot;st(4)&quot;</span>) _<span class="op">,</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>            out(<span class="st">&quot;st(5)&quot;</span>) _<span class="op">,</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>            out(<span class="st">&quot;st(6)&quot;</span>) _<span class="op">,</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>            out(<span class="st">&quot;st(7)&quot;</span>) _<span class="op">,</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a>        )<span class="op">;</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a>    out</span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This works, but you would have to implement every primitive long
double op yourself in handwritten assembly. (If you heard a groan, that
was me).</p>
<p>Instead, here’s a nice trick: you can shim the calls and let libc do
the rest.</p>
<p>So on the rust side:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>repr<span class="at">(</span>C<span class="op">,</span> align<span class="at">(</span><span class="dv">16</span><span class="at">))]</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>derive<span class="at">(</span><span class="bu">Clone</span><span class="op">,</span> <span class="bu">Copy</span><span class="at">)]</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">struct</span> LongDouble(<span class="kw">pub</span> [<span class="dt">u8</span><span class="op">;</span> <span class="dv">10</span>])<span class="op">;</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="kw">unsafe</span> <span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="op">{</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> __slate_ld_add(a<span class="op">:</span> LongDouble<span class="op">,</span> b<span class="op">:</span> LongDouble) <span class="op">-&gt;</span> LongDouble<span class="op">;</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// whatever other ops you want to provide</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Use the same storage on the C side:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">typedef</span> <span class="kw">struct</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">_Alignas</span><span class="op">(</span><span class="dv">16</span><span class="op">)</span> <span class="dt">unsigned</span> <span class="dt">char</span> bytes<span class="op">[</span><span class="dv">10</span><span class="op">];</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> slate_f80<span class="op">;</span></span></code></pre></div>
<p>And then write two functions, one to convert chars to long double and
one back:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="kw">inline</span> <span class="dt">long</span> <span class="dt">double</span> unpack<span class="op">(</span>slate_f80 v<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">long</span> <span class="dt">double</span> x <span class="op">=</span> <span class="fl">0.0</span><span class="bu">L</span><span class="op">;</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    memcpy<span class="op">(&amp;</span>x<span class="op">,</span> v<span class="op">.</span>bytes<span class="op">,</span> <span class="dv">10</span><span class="op">);</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> x<span class="op">;</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="kw">inline</span> slate_f80 pack<span class="op">(</span><span class="dt">long</span> <span class="dt">double</span> x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>    slate_f80 v <span class="op">=</span> <span class="op">{</span><span class="dv">0</span><span class="op">};</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>    memcpy<span class="op">(</span>v<span class="op">.</span>bytes<span class="op">,</span> <span class="op">&amp;</span>x<span class="op">,</span> <span class="dv">10</span><span class="op">);</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> v<span class="op">;</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb6"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>slate_f80 __slate_ld_add<span class="op">(</span>slate_f80 a<span class="op">,</span> slate_f80 b<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> pack<span class="op">(</span>unpack<span class="op">(</span>a<span class="op">)</span> <span class="op">+</span> unpack<span class="op">(</span>b<span class="op">));</span> <span class="op">}</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>slate_f80 __slate_ld_sub<span class="op">(</span>slate_f80 a<span class="op">,</span> slate_f80 b<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> pack<span class="op">(</span>unpack<span class="op">(</span>a<span class="op">)</span> <span class="op">-</span> unpack<span class="op">(</span>b<span class="op">));</span> <span class="op">}</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>slate_f80 __slate_ld_mul<span class="op">(</span>slate_f80 a<span class="op">,</span> slate_f80 b<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> pack<span class="op">(</span>unpack<span class="op">(</span>a<span class="op">)</span> <span class="op">*</span> unpack<span class="op">(</span>b<span class="op">));</span> <span class="op">}</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>slate_f80 __slate_ld_div<span class="op">(</span>slate_f80 a<span class="op">,</span> slate_f80 b<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> pack<span class="op">(</span>unpack<span class="op">(</span>a<span class="op">)</span> <span class="op">/</span> unpack<span class="op">(</span>b<span class="op">));</span> <span class="op">}</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>slate_f80 __slate_ld_neg<span class="op">(</span>slate_f80 a<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> pack<span class="op">(-</span>unpack<span class="op">(</span>a<span class="op">));</span> <span class="op">}</span></span></code></pre></div>
<p>You could also implement casting, relops in the same way:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> __slate_ld_eq<span class="op">(</span>slate_f80 a<span class="op">,</span> slate_f80 b<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> unpack<span class="op">(</span>a<span class="op">)</span> <span class="op">==</span> unpack<span class="op">(</span>b<span class="op">);</span> <span class="op">}</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="dt">int32_t</span> __slate_ld_to_i32<span class="op">(</span>slate_f80 a<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">(</span><span class="dt">int32_t</span><span class="op">)</span>unpack<span class="op">(</span>a<span class="op">);</span> <span class="op">}</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>slate_f80 __slate_ld_from_i32<span class="op">(</span><span class="dt">int32_t</span> x<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> pack<span class="op">((</span><span class="dt">long</span> <span class="dt">double</span><span class="op">)</span>x<span class="op">);</span> <span class="op">}</span></span></code></pre></div>
<p>Likewise, for any arbitrary function:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="dt">long</span> <span class="dt">double</span> custom<span class="op">(</span><span class="dt">long</span> <span class="dt">double</span><span class="op">,</span> <span class="dt">int</span><span class="op">);</span></span></code></pre></div>
<p>You would replace it with a call to:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>slate_f80 __slate_custom<span class="op">(</span>slate_f80 a<span class="op">,</span> <span class="dt">int</span> b<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> pack<span class="op">(</span>custom<span class="op">(</span>unpack<span class="op">(</span>a<span class="op">),</span> b<span class="op">));</span> <span class="op">}</span></span></code></pre></div>
<p>This makes it so we don’t have to know anything about the underlying
long double type at all (no assembly writing for me) and keeps our shim
code fairly light.</p>]]></description>
</item>
<item>
<title>The One Billion Row Challenge</title>
<pubDate>Sat, 25 Apr 2026 20:30:34 +0000</pubDate>
<guid>https://blog/one-billion-row-challenge.html</guid>
<description><![CDATA[<h1 id="the-one-billion-row-challenge">The One
Billion Row Challenge</h1>
<p>A couple of years ago, the <a href="https://1brc.dev/">1 Billion Row
Challenge</a> got popular. The challenge is to write a program that
reads a text file with the format of: <code>$CITY_NAME;$TEMP\n</code> of
some size, and then for each city, the program should print out the min,
mean, and max values per city, alphabetically ordered.</p>
<p>So if you have:</p>
<pre><code>Hamburg;12.0
Hamburg;34.2</code></pre>
<p>You would condense this down to:</p>
<pre><code>Hamburg;12.0;23.1;34.2
   ^      ^    ^    ^
 city    min  mean max</code></pre>
<p>And print that out.</p>
<p>I decided to do this in Rust, and this post is what I learned.</p>
<h2 id="preliminaries">Preliminaries</h2>
<p>Since I knew I wanted to try out a few different methods, to start
off with I defined a trait so I would only have to rewrite the core
logic.</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">type</span> Temp <span class="op">=</span> <span class="dt">i16</span><span class="op">;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>derive<span class="at">(</span><span class="bu">Debug</span><span class="op">,</span> <span class="bu">Clone</span><span class="op">,</span> <span class="bu">PartialEq</span><span class="op">,</span> <span class="bu">Eq</span><span class="at">)]</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">struct</span> StationResult <span class="op">{</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span> station<span class="op">:</span> <span class="dt">String</span><span class="op">,</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span> min<span class="op">:</span> Temp<span class="op">,</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span> mean<span class="op">:</span> Temp<span class="op">,</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span> max<span class="op">:</span> Temp<span class="op">,</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">trait</span> Solver<span class="op">:</span> <span class="bu">Default</span> <span class="op">{</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> process(<span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">,</span> station<span class="op">:</span> <span class="op">&amp;</span><span class="dt">str</span><span class="op">,</span> temp<span class="op">:</span> Temp)<span class="op">;</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> process_bytes(<span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">,</span> station<span class="op">:</span> <span class="op">&amp;</span>[<span class="dt">u8</span>]<span class="op">,</span> temp<span class="op">:</span> Temp) <span class="op">-&gt;</span> <span class="pp">io::</span><span class="dt">Result</span><span class="op">&lt;</span>()<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> station <span class="op">=</span> <span class="pp">std::</span><span class="dt">str</span><span class="pp">::</span>from_utf8(station)<span class="op">.</span>map_err(<span class="op">|</span>error<span class="op">|</span> <span class="op">{</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>            <span class="pp">io::</span><span class="bu">Error</span><span class="pp">::</span>new(</span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>                <span class="pp">io::ErrorKind::</span>InvalidData<span class="op">,</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>                <span class="pp">format!</span>(<span class="st">&quot;invalid station name UTF-8: {error}&quot;</span>)<span class="op">,</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a>            )</span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span>)<span class="op">?;</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a>        <span class="kw">self</span><span class="op">.</span>process(station<span class="op">,</span> temp)<span class="op">;</span></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a>        <span class="cn">Ok</span>(())</span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> finish(<span class="kw">self</span>) <span class="op">-&gt;</span> <span class="dt">Vec</span><span class="op">&lt;</span>StationResult<span class="op">&gt;;</span></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>As well, I needed to keep the stats for each station:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">type</span> Temp <span class="op">=</span> <span class="dt">i16</span><span class="op">;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">type</span> TempSum <span class="op">=</span> <span class="dt">i64</span><span class="op">;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">type</span> Count <span class="op">=</span> <span class="dt">u32</span><span class="op">;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>derive<span class="at">(</span><span class="bu">Default</span><span class="op">,</span> <span class="bu">Clone</span><span class="op">,</span> <span class="bu">Copy</span><span class="at">)]</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct</span> Stats <span class="op">{</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span>(<span class="kw">crate</span>) sum<span class="op">:</span> TempSum<span class="op">,</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span>(<span class="kw">crate</span>) count<span class="op">:</span> Count<span class="op">,</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span>(<span class="kw">crate</span>) min<span class="op">:</span> Temp<span class="op">,</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span>(<span class="kw">crate</span>) max<span class="op">:</span> Temp<span class="op">,</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a><span class="kw">impl</span> Stats <span class="op">{</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn</span> add(<span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">,</span> temp<span class="op">:</span> Temp) <span class="op">{</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="kw">self</span><span class="op">.</span>count <span class="op">==</span> <span class="dv">0</span> <span class="op">{</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>            <span class="kw">self</span><span class="op">.</span>min <span class="op">=</span> temp<span class="op">;</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>            <span class="kw">self</span><span class="op">.</span>max <span class="op">=</span> temp<span class="op">;</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>            <span class="kw">self</span><span class="op">.</span>min <span class="op">=</span> <span class="kw">self</span><span class="op">.</span>min<span class="op">.</span>min(temp)<span class="op">;</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a>            <span class="kw">self</span><span class="op">.</span>max <span class="op">=</span> <span class="kw">self</span><span class="op">.</span>max<span class="op">.</span>max(temp)<span class="op">;</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a>        <span class="kw">self</span><span class="op">.</span>sum <span class="op">+=</span> <span class="pp">TempSum::</span>from(temp)<span class="op">;</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a>        <span class="kw">self</span><span class="op">.</span>count <span class="op">+=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn</span> into_result(<span class="kw">self</span><span class="op">,</span> station<span class="op">:</span> <span class="dt">String</span>) <span class="op">-&gt;</span> StationResult <span class="op">{</span></span>
<span id="cb4-28"><a href="#cb4-28" aria-hidden="true" tabindex="-1"></a>        StationResult <span class="op">{</span></span>
<span id="cb4-29"><a href="#cb4-29" aria-hidden="true" tabindex="-1"></a>            station<span class="op">,</span></span>
<span id="cb4-30"><a href="#cb4-30" aria-hidden="true" tabindex="-1"></a>            min<span class="op">:</span> <span class="kw">self</span><span class="op">.</span>min<span class="op">,</span></span>
<span id="cb4-31"><a href="#cb4-31" aria-hidden="true" tabindex="-1"></a>            mean<span class="op">:</span> round_mean_tenths(<span class="kw">self</span><span class="op">.</span>sum<span class="op">,</span> <span class="kw">self</span><span class="op">.</span>count)<span class="op">,</span></span>
<span id="cb4-32"><a href="#cb4-32" aria-hidden="true" tabindex="-1"></a>            max<span class="op">:</span> <span class="kw">self</span><span class="op">.</span>max<span class="op">,</span></span>
<span id="cb4-33"><a href="#cb4-33" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb4-34"><a href="#cb4-34" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-35"><a href="#cb4-35" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>With a helper for reading input:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">fn</span> process_measurements<span class="op">&lt;</span>R<span class="op">,</span> S<span class="op">&gt;</span>(reader<span class="op">:</span> R<span class="op">,</span> solver<span class="op">:</span> <span class="op">&amp;</span><span class="kw">mut</span> S) <span class="op">-&gt;</span> <span class="pp">io::</span><span class="dt">Result</span><span class="op">&lt;</span>()<span class="op">&gt;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">where</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    R<span class="op">:</span> <span class="bu">BufRead</span><span class="op">,</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    S<span class="op">:</span> Solver<span class="op">,</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> line <span class="kw">in</span> reader<span class="op">.</span>lines() <span class="op">{</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> line <span class="op">=</span> line<span class="op">?;</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> <span class="cn">Some</span>((station<span class="op">,</span> temp)) <span class="op">=</span> line<span class="op">.</span>split_once(<span class="ch">&#39;;&#39;</span>) <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>            <span class="cf">continue</span><span class="op">;</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">};</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>        solver<span class="op">.</span>process(station<span class="op">,</span> parse_temperature_tenths(temp)<span class="op">?</span>)<span class="op">;</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>    <span class="cn">Ok</span>(())</span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>A helper for writing output:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">fn</span> write_results_to_path(path<span class="op">:</span> <span class="dt">Option</span><span class="op">&lt;&amp;</span><span class="dt">str</span><span class="op">&gt;,</span> results<span class="op">:</span> <span class="op">&amp;</span>[StationResult]) <span class="op">-&gt;</span> <span class="pp">io::</span><span class="dt">Result</span><span class="op">&lt;</span>()<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">match</span> path <span class="op">{</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>        <span class="cn">Some</span>(path) <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>            <span class="kw">let</span> file <span class="op">=</span> <span class="pp">File::</span>create(path)<span class="op">?;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>            <span class="kw">let</span> writer <span class="op">=</span> <span class="pp">BufWriter::</span>new(file)<span class="op">;</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>            write_results(writer<span class="op">,</span> results)</span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>        <span class="cn">None</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>            <span class="kw">let</span> stdout <span class="op">=</span> <span class="pp">io::</span>stdout()<span class="op">;</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>            <span class="kw">let</span> writer <span class="op">=</span> stdout<span class="op">.</span>lock()<span class="op">;</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>            write_results(writer<span class="op">,</span> results)</span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And finally, running the solver:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">fn</span> run_solver<span class="op">&lt;</span>S<span class="op">&gt;</span>(input_path<span class="op">:</span> <span class="op">&amp;</span><span class="dt">str</span><span class="op">,</span> output_path<span class="op">:</span> <span class="dt">Option</span><span class="op">&lt;&amp;</span><span class="dt">str</span><span class="op">&gt;</span>) <span class="op">-&gt;</span> <span class="pp">io::</span><span class="dt">Result</span><span class="op">&lt;</span>()<span class="op">&gt;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">where</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    S<span class="op">:</span> Solver<span class="op">,</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> file <span class="op">=</span> <span class="pp">File::</span>open(input_path)<span class="op">.</span>map_err(<span class="op">|</span>error<span class="op">|</span> not_found_error(input_path<span class="op">,</span> error))<span class="op">?;</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> reader <span class="op">=</span> <span class="pp">BufReader::</span>with_capacity(<span class="dv">8</span> <span class="op">*</span> <span class="dv">1024</span> <span class="op">*</span> <span class="dv">1024</span><span class="op">,</span> file)<span class="op">;</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> solver <span class="op">=</span> <span class="pp">S::</span><span class="kw">default</span>()<span class="op">;</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>    <span class="pp">input::</span>process_measurements(reader<span class="op">,</span> <span class="op">&amp;</span><span class="kw">mut</span> solver)<span class="op">?;</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>    <span class="pp">output::</span>write_results_to_path(output_path<span class="op">,</span> <span class="op">&amp;</span>solver<span class="op">.</span>finish())</span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>As well, I wanted to create a couple of things. First off, I needed
<code>cargo flamegraph</code> to see where time was being spent, and I
wrote a script so I could generate input of different sizes. The 1
billion rows would be wasteful to do my target runs on, so I took the
weather data from the one billion rows repo and generated a million row
sample to run on.</p>
<h2 id="the-easiest-solution-btreemap">The Easiest Solution
(BTreeMap)</h2>
<p>First off, let’s start off with the basics. The simplest solution I
could think of was to:</p>
<ol type="1">
<li>For each line, split at the ‘;’ character.
<ul>
<li>The left side is the station name.</li>
<li>The right side is the temperature.</li>
<li>Take the temperature, and then record the current total, current
count, current minimum, and current maximum.</li>
</ul></li>
<li>Sort the cities.</li>
<li>Calculate the mean by doing sum / count;</li>
<li>Print out “{city};{min};{mean};{max}” for each city.</li>
</ol>
<p>You know what’s better than sorting at the end? Having a data
structure do it for you. So at first, I used a <code>BTreeMap</code>.
With the <code>Solver</code> trait, I just needed to implement
<code>process</code> and <code>finish</code>.</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>derive<span class="at">(</span><span class="bu">Default</span><span class="at">)]</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">struct</span> BasicBTreeMapSolver <span class="op">{</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>    stats_by_station<span class="op">:</span> BTreeMap<span class="op">&lt;</span><span class="dt">String</span><span class="op">,</span> Stats<span class="op">&gt;,</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a><span class="kw">impl</span> Solver <span class="cf">for</span> BasicBTreeMapSolver <span class="op">{</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> process(<span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">,</span> station<span class="op">:</span> <span class="op">&amp;</span><span class="dt">str</span><span class="op">,</span> temp<span class="op">:</span> Temp) <span class="op">{</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">self</span><span class="op">.</span>stats_by_station</span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>entry(station<span class="op">.</span>to_string())</span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>or_default()</span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>add(temp)<span class="op">;</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> finish(<span class="kw">self</span>) <span class="op">-&gt;</span> <span class="dt">Vec</span><span class="op">&lt;</span>StationResult<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">self</span><span class="op">.</span>stats_by_station</span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>into_iter()</span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>map(<span class="op">|</span>(station<span class="op">,</span> stats)<span class="op">|</span> stats<span class="op">.</span>into_result(station))</span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>collect()</span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This solution crunches through one million rows in 218ms on my Ryzen
5 7600 CPU.</p>
<p>Not bad but we could do better. Taking a look at the flamegraph here,
there’s not too much to say, but it looks like the btreemap logic itself
is taking the longest amount of time, so we should tackle that
first.</p>
<object type="image/svg+xml" data="../assets/obrc/btreemap.svg" width="100%" height="100%">
</object>
<h2 id="the-next-solution-hashmap">The Next Solution (HashMap)</h2>
<p>BTreeMap is slow for this solution because we don’t need a sorted
order all the time, just at the end. To do that, we can fall back to
good old HashMap and sort once at the end.</p>
<p>And with that:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">impl</span> Solver <span class="cf">for</span> BasicHashMapSolver <span class="op">{</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> process(<span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">,</span> station<span class="op">:</span> <span class="op">&amp;</span><span class="dt">str</span><span class="op">,</span> temp<span class="op">:</span> Temp) <span class="op">{</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="kw">let</span> <span class="cn">Some</span>(stats) <span class="op">=</span> <span class="kw">self</span><span class="op">.</span>stats_by_station<span class="op">.</span>get_mut(station) <span class="op">{</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>            stats<span class="op">.</span>add(temp)<span class="op">;</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>            <span class="kw">let</span> <span class="kw">mut</span> stats <span class="op">=</span> <span class="pp">Stats::</span><span class="kw">default</span>()<span class="op">;</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>            stats<span class="op">.</span>add(temp)<span class="op">;</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>            <span class="kw">self</span><span class="op">.</span>stats_by_station<span class="op">.</span>insert(station<span class="op">.</span>to_string()<span class="op">,</span> stats)<span class="op">;</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> finish(<span class="kw">self</span>) <span class="op">-&gt;</span> <span class="dt">Vec</span><span class="op">&lt;</span>StationResult<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> <span class="kw">mut</span> results<span class="op">:</span> <span class="dt">Vec</span><span class="op">&lt;</span>_<span class="op">&gt;</span> <span class="op">=</span> <span class="kw">self</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>stats_by_station</span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>into_iter()</span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>map(<span class="op">|</span>(station<span class="op">,</span> stats)<span class="op">|</span> stats<span class="op">.</span>into_result(station))</span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>collect()<span class="op">;</span></span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true" tabindex="-1"></a>        results<span class="op">.</span>sort_unstable_by(<span class="op">|</span>left<span class="op">,</span> right<span class="op">|</span> left<span class="op">.</span>station<span class="op">.</span>cmp(<span class="op">&amp;</span>right<span class="op">.</span>station))<span class="op">;</span></span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true" tabindex="-1"></a>        results</span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-22"><a href="#cb9-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This about halves the run time, to 110ms. I was expecting more of a
modest improvement, but this is pretty nice. The next chunk I see taking
a lot of time is read_line, so we can work on that next.</p>
<object type="image/svg+xml" data="../assets/obrc/hashmap.svg" width="100%" height="100%">
</object>
<h2 id="memory-mapping">Memory Mapping</h2>
<p>The next bottleneck looked to be I/O: BufReader was taking the most
amount of time. The Bufreader already reads in chunks, but we want to
avoid going back to the kernel for reads. Memory mapping is one way to
do that.</p>
<p>All we have to do is change our input hook to memory map our input
file.</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">fn</span> run_solver_mmap<span class="op">&lt;</span>S<span class="op">:</span> Solver<span class="op">&gt;</span>(input_path<span class="op">:</span> <span class="op">&amp;</span><span class="dt">str</span><span class="op">,</span> output_path<span class="op">:</span> <span class="dt">Option</span><span class="op">&lt;&amp;</span><span class="dt">str</span><span class="op">&gt;</span>) <span class="op">-&gt;</span> <span class="pp">io::</span><span class="dt">Result</span><span class="op">&lt;</span>()<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> file <span class="op">=</span> <span class="pp">File::</span>open(input_path)<span class="op">?;</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> mmap <span class="op">=</span> <span class="kw">unsafe</span> <span class="op">{</span> <span class="pp">MmapOptions::</span>new()<span class="op">.</span>map(<span class="op">&amp;</span>file)<span class="op">?</span> <span class="op">};</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> solver <span class="op">=</span> <span class="pp">S::</span><span class="kw">default</span>()<span class="op">;</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>    <span class="pp">input::</span>process_measurements_bytes(<span class="op">&amp;</span>mmap<span class="op">,</span> <span class="op">&amp;</span><span class="kw">mut</span> solver)<span class="op">?;</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>    <span class="pp">output::</span>write_results_to_path(output_path<span class="op">,</span> <span class="op">&amp;</span>solver<span class="op">.</span>finish())</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This gets us an even faster runtime of 79ms.</p>
<object type="image/svg+xml" data="../assets/obrc/hashmap-mmap.svg" width="100%" height="100%">
</object>
<h2 id="more-changes">More changes</h2>
<p>At this point I was pretty satisfied. Memory mapping the input file +
using a HashMap was already pretty good. But the flamegraph does show
that <code>parse_temperature_tenths_bytes</code> is pretty slow (32% of
runtime), so let’s dig into that.</p>
<p>The current implementation is:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> parse_temperature_tenths_bytes(value<span class="op">:</span> <span class="op">&amp;</span>[<span class="dt">u8</span>]) <span class="op">-&gt;</span> <span class="pp">io::</span><span class="dt">Result</span><span class="op">&lt;</span>Temp<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> negative <span class="op">=</span> value<span class="op">.</span>first() <span class="op">==</span> <span class="cn">Some</span>(<span class="op">&amp;</span><span class="ch">b&#39;-&#39;</span>)<span class="op">;</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> digits <span class="op">=</span> <span class="cf">if</span> negative <span class="op">{</span> <span class="op">&amp;</span>value[<span class="dv">1</span><span class="op">..</span>] <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span> value <span class="op">};</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>                                                                                                                              </span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> digits<span class="op">.</span>len() <span class="op">&lt;</span> <span class="dv">3</span> <span class="op">||</span> digits[digits<span class="op">.</span>len() <span class="op">-</span> <span class="dv">2</span>] <span class="op">!=</span> <span class="ch">b&#39;.&#39;</span> <span class="op">{</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="cn">Err</span>(invalid_temperature_bytes(value))<span class="op">;</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>                                                                                                                       </span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> whole <span class="op">=</span> <span class="op">&amp;</span>digits[<span class="op">..</span>digits<span class="op">.</span>len() <span class="op">-</span> <span class="dv">2</span>]<span class="op">;</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> fraction <span class="op">=</span> digits[digits<span class="op">.</span>len() <span class="op">-</span> <span class="dv">1</span>]<span class="op">;</span></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> whole<span class="op">.</span>is_empty()</span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">||</span> <span class="op">!</span>whole<span class="op">.</span>iter()<span class="op">.</span>all(<span class="op">|</span>byte<span class="op">|</span> byte<span class="op">.</span>is_ascii_digit())</span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">||</span> <span class="op">!</span>fraction<span class="op">.</span>is_ascii_digit()</span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="cn">Err</span>(invalid_temperature_bytes(value))<span class="op">;</span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a>                                                                                                                       </span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> temp <span class="op">=</span> <span class="pp">Temp::</span>from(fraction <span class="op">-</span> <span class="ch">b&#39;0&#39;</span>)<span class="op">;</span></span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> multiplier <span class="op">=</span> <span class="dv">10</span><span class="op">;</span></span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">&amp;</span>digit <span class="kw">in</span> whole<span class="op">.</span>iter()<span class="op">.</span>rev() <span class="op">{</span></span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true" tabindex="-1"></a>        temp <span class="op">+=</span> <span class="pp">Temp::</span>from(digit <span class="op">-</span> <span class="ch">b&#39;0&#39;</span>) <span class="op">*</span> multiplier<span class="op">;</span></span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true" tabindex="-1"></a>        multiplier <span class="op">*=</span> <span class="dv">10</span><span class="op">;</span></span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-24"><a href="#cb11-24" aria-hidden="true" tabindex="-1"></a>                                                                                                                       </span>
<span id="cb11-25"><a href="#cb11-25" aria-hidden="true" tabindex="-1"></a>    <span class="cn">Ok</span>(<span class="cf">if</span> negative <span class="op">{</span> <span class="op">-</span>temp <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span> temp <span class="op">}</span>)</span>
<span id="cb11-26"><a href="#cb11-26" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This has a few branches and error checking. We can make this
branchless by exploiting the fact that there are only 4 formats. We just
need to check if the first character is the negative sign, then grab the
fractional part from the end, and otherwise grab the number itself. We
can then recreate the value itself that way, fully branchless.</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> parse_temperature_tenths_bytes(value<span class="op">:</span> <span class="op">&amp;</span>[<span class="dt">u8</span>]) <span class="op">-&gt;</span> <span class="pp">io::</span><span class="dt">Result</span><span class="op">&lt;</span>Temp<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> neg <span class="op">=</span> (value[<span class="dv">0</span>] <span class="op">==</span> <span class="ch">b&#39;-&#39;</span>) <span class="kw">as</span> <span class="dt">usize</span><span class="op">;</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> frac <span class="op">=</span> (value[value<span class="op">.</span>len() <span class="op">-</span> <span class="dv">1</span>] <span class="op">-</span> <span class="ch">b&#39;0&#39;</span>) <span class="kw">as</span> Temp<span class="op">;</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> ones <span class="op">=</span> (value[value<span class="op">.</span>len() <span class="op">-</span> <span class="dv">3</span>] <span class="op">-</span> <span class="ch">b&#39;0&#39;</span>) <span class="kw">as</span> Temp<span class="op">;</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> has_tens <span class="op">=</span> (value<span class="op">.</span>len() <span class="op">-</span> neg <span class="op">&gt;</span> <span class="dv">3</span>) <span class="kw">as</span> Temp<span class="op">;</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> tens <span class="op">=</span> has_tens <span class="op">*</span> (value[neg] <span class="op">-</span> <span class="ch">b&#39;0&#39;</span>) <span class="kw">as</span> Temp<span class="op">;</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> sign <span class="op">=</span> <span class="dv">1</span> <span class="op">-</span> <span class="dv">2</span> <span class="op">*</span> neg <span class="kw">as</span> Temp<span class="op">;</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>    <span class="cn">Ok</span>(sign <span class="op">*</span> (tens <span class="op">*</span> <span class="dv">100</span> <span class="op">+</span> ones <span class="op">*</span> <span class="dv">10</span> <span class="op">+</span> frac))</span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This has two advantages: one, dropping the runtime to 72ms, a nice
improvement, but also dropping the variance between runs. We used to
have about 5-8ms variance, but now this is less than &lt;1ms between
runs, since branchless solutions are more consistent.</p>
<object type="image/svg+xml" data="../assets/obrc/hashmap-mmap-branchless-bytes.svg" width="100%" height="100%">
</object>
<h2 id="handle-the-bytes">Handle the bytes</h2>
<p>Why bother having strings at all? Why not index a city by its bytes?
We can do that and combined with a faster hashmap (Fnv), I got a 60ms
runtime on my computer.</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">struct</span> FnvBytesSolver <span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>    stats_by_station<span class="op">:</span> FnvHashMap<span class="op">&lt;</span><span class="dt">Vec</span><span class="op">&lt;</span><span class="dt">u8</span><span class="op">&gt;,</span> Stats<span class="op">&gt;,</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a><span class="kw">impl</span> Solver <span class="cf">for</span> FnvBytesSolver <span class="op">{</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> process_bytes(<span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">,</span> station<span class="op">:</span> <span class="op">&amp;</span>[<span class="dt">u8</span>]<span class="op">,</span> temp<span class="op">:</span> Temp) <span class="op">-&gt;</span> <span class="pp">io::</span><span class="dt">Result</span><span class="op">&lt;</span>()<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="kw">let</span> <span class="cn">Some</span>(stats) <span class="op">=</span> <span class="kw">self</span><span class="op">.</span>stats_by_station<span class="op">.</span>get_mut(station) <span class="op">{</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>            stats<span class="op">.</span>add(temp)<span class="op">;</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>            <span class="kw">let</span> <span class="kw">mut</span> stats <span class="op">=</span> <span class="pp">Stats::</span><span class="kw">default</span>()<span class="op">;</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>            stats<span class="op">.</span>add(temp)<span class="op">;</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>            <span class="kw">self</span><span class="op">.</span>stats_by_station<span class="op">.</span>insert(station<span class="op">.</span>to_vec()<span class="op">,</span> stats)<span class="op">;</span></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a>        <span class="cn">Ok</span>(())</span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> finish(<span class="kw">self</span>) <span class="op">-&gt;</span> <span class="dt">Vec</span><span class="op">&lt;</span>StationResult<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> <span class="kw">mut</span> results <span class="op">=</span> <span class="dt">Vec</span><span class="pp">::</span>with_capacity(<span class="kw">self</span><span class="op">.</span>stats_by_station<span class="op">.</span>len())<span class="op">;</span></span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> (station<span class="op">,</span> stats) <span class="kw">in</span> <span class="kw">self</span><span class="op">.</span>stats_by_station <span class="op">{</span></span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a>            <span class="kw">let</span> station <span class="op">=</span> <span class="dt">String</span><span class="pp">::</span>from_utf8(station)<span class="op">.</span>expect(<span class="st">&quot;valid UTF-8&quot;</span>)<span class="op">;</span></span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a>            results<span class="op">.</span>push(stats<span class="op">.</span>into_result(station))<span class="op">;</span></span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true" tabindex="-1"></a>        results<span class="op">.</span>sort_unstable_by(<span class="op">|</span>l<span class="op">,</span> r<span class="op">|</span> l<span class="op">.</span>station<span class="op">.</span>cmp(<span class="op">&amp;</span>r<span class="op">.</span>station))<span class="op">;</span></span>
<span id="cb13-24"><a href="#cb13-24" aria-hidden="true" tabindex="-1"></a>        results</span>
<span id="cb13-25"><a href="#cb13-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-26"><a href="#cb13-26" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<object type="image/svg+xml" data="../assets/obrc/fnv-bytes-mmap.svg" width="100%" height="100%">
</object>
<h2 id="a-dead-end">A Dead end</h2>
<p>At this point, I had about hit wits end. About 48% of runtime was in
FnvHasher’s <code>get_mut</code>, and otherwise about 17% of runtime was
in <code>float_to_decimal_common_exact</code>.</p>
<p>So the next two things are to remove the hashmap and fix the output
formatting.</p>
<p>The biggest impact would be to rip out the hashmap itself and come up
with a custom flat hashmap.</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> fingerprint(key<span class="op">:</span> <span class="op">&amp;</span>[<span class="dt">u8</span>]) <span class="op">-&gt;</span> <span class="dt">u64</span> <span class="op">{</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> buf <span class="op">=</span> [<span class="dv">0u8</span><span class="op">;</span> <span class="dv">8</span>]<span class="op">;</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> n <span class="op">=</span> key<span class="op">.</span>len()<span class="op">.</span>min(<span class="dv">8</span>)<span class="op">;</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>    buf[<span class="op">..</span>n]<span class="op">.</span>copy_from_slice(<span class="op">&amp;</span>key[<span class="op">..</span>n])<span class="op">;</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">u64</span><span class="pp">::</span>from_le_bytes(buf)</span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> table_index(fp<span class="op">:</span> <span class="dt">u64</span><span class="op">,</span> key_len<span class="op">:</span> <span class="dt">usize</span>) <span class="op">-&gt;</span> <span class="dt">usize</span> <span class="op">{</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> h <span class="op">=</span> fp <span class="op">^</span> (key_len <span class="kw">as</span> <span class="dt">u64</span>)<span class="op">.</span>wrapping_shl(<span class="dv">17</span>)<span class="op">;</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> h <span class="op">=</span> h <span class="op">^</span> (h <span class="op">&gt;&gt;</span> <span class="dv">30</span>)<span class="op">;</span></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> h <span class="op">=</span> h<span class="op">.</span>wrapping_mul(<span class="dv">0xbf58476d1ce4e5b9</span>)<span class="op">;</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> h <span class="op">=</span> h <span class="op">^</span> (h <span class="op">&gt;&gt;</span> <span class="dv">27</span>)<span class="op">;</span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> h <span class="op">=</span> h<span class="op">.</span>wrapping_mul(<span class="dv">0x94d049bb133111eb</span>)<span class="op">;</span></span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> h <span class="op">=</span> h <span class="op">^</span> (h <span class="op">&gt;&gt;</span> <span class="dv">31</span>)<span class="op">;</span></span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a>    (h <span class="kw">as</span> <span class="dt">usize</span>) <span class="op">&amp;</span> TABLE_MASK</span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> TABLE_SIZE<span class="op">:</span> <span class="dt">usize</span> <span class="op">=</span> <span class="dv">1</span> <span class="op">&lt;&lt;</span> <span class="dv">17</span><span class="op">;</span> </span>
<span id="cb14-19"><a href="#cb14-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-20"><a href="#cb14-20" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Slot<span class="op">&lt;</span><span class="ot">&#39;a</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb14-21"><a href="#cb14-21" aria-hidden="true" tabindex="-1"></a>    fingerprint<span class="op">:</span> <span class="dt">u64</span><span class="op">,</span></span>
<span id="cb14-22"><a href="#cb14-22" aria-hidden="true" tabindex="-1"></a>    key<span class="op">:</span> <span class="op">&amp;</span><span class="ot">&#39;a</span> [<span class="dt">u8</span>]<span class="op">,</span></span>
<span id="cb14-23"><a href="#cb14-23" aria-hidden="true" tabindex="-1"></a>    stats<span class="op">:</span> Stats<span class="op">,</span></span>
<span id="cb14-24"><a href="#cb14-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb14-25"><a href="#cb14-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-26"><a href="#cb14-26" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> FlatTable<span class="op">&lt;</span><span class="ot">&#39;a</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb14-27"><a href="#cb14-27" aria-hidden="true" tabindex="-1"></a>    slots<span class="op">:</span> <span class="dt">Box</span><span class="op">&lt;</span>[Slot<span class="op">&lt;</span><span class="ot">&#39;a</span><span class="op">&gt;</span>]<span class="op">&gt;,</span></span>
<span id="cb14-28"><a href="#cb14-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb14-29"><a href="#cb14-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-30"><a href="#cb14-30" aria-hidden="true" tabindex="-1"></a><span class="kw">impl</span><span class="op">&lt;</span><span class="ot">&#39;a</span><span class="op">&gt;</span> FlatTable<span class="op">&lt;</span><span class="ot">&#39;a</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb14-31"><a href="#cb14-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> update(<span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">,</span> key<span class="op">:</span> <span class="op">&amp;</span><span class="ot">&#39;a</span> [<span class="dt">u8</span>]<span class="op">,</span> temp<span class="op">:</span> Temp) <span class="op">{</span></span>
<span id="cb14-32"><a href="#cb14-32" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> fp <span class="op">=</span> fingerprint(key)<span class="op">;</span></span>
<span id="cb14-33"><a href="#cb14-33" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> <span class="kw">mut</span> idx <span class="op">=</span> table_index(fp<span class="op">,</span> key<span class="op">.</span>len())<span class="op">;</span></span>
<span id="cb14-34"><a href="#cb14-34" aria-hidden="true" tabindex="-1"></a>        <span class="cf">loop</span> <span class="op">{</span></span>
<span id="cb14-35"><a href="#cb14-35" aria-hidden="true" tabindex="-1"></a>            <span class="kw">let</span> slot <span class="op">=</span> <span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">.</span>slots[idx]<span class="op">;</span></span>
<span id="cb14-36"><a href="#cb14-36" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> slot<span class="op">.</span>key<span class="op">.</span>is_empty() <span class="op">{</span>               </span>
<span id="cb14-37"><a href="#cb14-37" aria-hidden="true" tabindex="-1"></a>                slot<span class="op">.</span>fingerprint <span class="op">=</span> fp<span class="op">;</span></span>
<span id="cb14-38"><a href="#cb14-38" aria-hidden="true" tabindex="-1"></a>                slot<span class="op">.</span>key <span class="op">=</span> key<span class="op">;</span></span>
<span id="cb14-39"><a href="#cb14-39" aria-hidden="true" tabindex="-1"></a>                slot<span class="op">.</span>stats <span class="op">=</span> <span class="pp">Stats::</span><span class="kw">default</span>()<span class="op">;</span></span>
<span id="cb14-40"><a href="#cb14-40" aria-hidden="true" tabindex="-1"></a>                slot<span class="op">.</span>stats<span class="op">.</span>add(temp)<span class="op">;</span></span>
<span id="cb14-41"><a href="#cb14-41" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span><span class="op">;</span></span>
<span id="cb14-42"><a href="#cb14-42" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb14-43"><a href="#cb14-43" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> slot<span class="op">.</span>fingerprint <span class="op">==</span> fp <span class="op">&amp;&amp;</span> slot<span class="op">.</span>key <span class="op">==</span> key <span class="op">{</span></span>
<span id="cb14-44"><a href="#cb14-44" aria-hidden="true" tabindex="-1"></a>                slot<span class="op">.</span>stats<span class="op">.</span>add(temp)<span class="op">;</span></span>
<span id="cb14-45"><a href="#cb14-45" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span><span class="op">;</span></span>
<span id="cb14-46"><a href="#cb14-46" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb14-47"><a href="#cb14-47" aria-hidden="true" tabindex="-1"></a>            idx <span class="op">=</span> (idx <span class="op">+</span> <span class="dv">1</span>) <span class="op">&amp;</span> TABLE_MASK<span class="op">;</span> </span>
<span id="cb14-48"><a href="#cb14-48" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb14-49"><a href="#cb14-49" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-50"><a href="#cb14-50" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The second thing is to fix up the output formatting:</p>
<div class="sourceCode" id="cb15"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">fn</span> format_temperature_tenths(temp<span class="op">:</span> Temp) <span class="op">-&gt;</span> <span class="dt">String</span> <span class="op">{</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>    <span class="pp">format!</span>(<span class="st">&quot;{:.1}&quot;</span><span class="op">,</span> temp <span class="kw">as</span> <span class="dt">f64</span> <span class="op">/</span> <span class="dv">10.0</span>)</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Into this: avoids the 17% of runtime in outputting the float:</p>
<div class="sourceCode" id="cb16"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">fn</span> format_temperature_tenths(temp<span class="op">:</span> Temp) <span class="op">-&gt;</span> <span class="dt">String</span> <span class="op">{</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> neg <span class="op">=</span> temp <span class="op">&lt;</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> abs <span class="op">=</span> temp<span class="op">.</span>unsigned_abs()<span class="op">;</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> neg <span class="op">{</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>        <span class="pp">format!</span>(<span class="st">&quot;-{}.{}&quot;</span><span class="op">,</span> abs <span class="op">/</span> <span class="dv">10</span><span class="op">,</span> abs <span class="op">%</span> <span class="dv">10</span>)</span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>        <span class="pp">format!</span>(<span class="st">&quot;{}.{}&quot;</span><span class="op">,</span> abs <span class="op">/</span> <span class="dv">10</span><span class="op">,</span> abs <span class="op">%</span> <span class="dv">10</span>)</span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>With both of those fixes, we get a dramatic improvement to 36ms
runtime.</p>
<object type="image/svg+xml" data="../assets/obrc/fast.svg" width="100%" height="100%">
</object>
<h2 id="parallelization">Parallelization</h2>
<p>After this, it’s pretty unclear how to improve this single-threaded
solution any more. I decided to drop –no-inline from my cargo
flamegraphs since it said 90% of runtime was in
<code>process_bytes</code> and the rest was inlined into it. But looking
at the flamegraph while counting inlining, it seems like it’s doing
about the minimal amount of work required.</p>
<p>A simple way to use parallelism is to cut the input into equal sized
chunks by the number of threads, and then join at the end.</p>
<p>To chunk:</p>
<div class="sourceCode" id="cb17"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> chunks_for_threads(bytes<span class="op">:</span> <span class="op">&amp;</span>[<span class="dt">u8</span>]<span class="op">,</span> threads<span class="op">:</span> <span class="dt">usize</span>) <span class="op">-&gt;</span> <span class="dt">Vec</span><span class="op">&lt;</span>(<span class="dt">usize</span><span class="op">,</span> <span class="dt">usize</span>)<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> len <span class="op">=</span> bytes<span class="op">.</span>len()<span class="op">;</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> threads <span class="op">=</span> threads<span class="op">.</span>min(len)<span class="op">;</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> chunks <span class="op">=</span> <span class="dt">Vec</span><span class="pp">::</span>with_capacity(threads)<span class="op">;</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> start <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> index <span class="kw">in</span> <span class="dv">0</span><span class="op">..</span>threads <span class="op">{</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> start <span class="op">&gt;=</span> len <span class="op">{</span> <span class="cf">break</span><span class="op">;</span> <span class="op">}</span></span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> end <span class="op">=</span> <span class="cf">if</span> index <span class="op">+</span> <span class="dv">1</span> <span class="op">==</span> threads <span class="op">{</span></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a>            len</span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a>            align_end_to_line(bytes<span class="op">,</span> len <span class="op">*</span> (index <span class="op">+</span> <span class="dv">1</span>) <span class="op">/</span> threads)</span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">};</span></span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> start <span class="op">&lt;</span> end <span class="op">{</span> chunks<span class="op">.</span>push((start<span class="op">,</span> end))<span class="op">;</span> <span class="op">}</span></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a>        start <span class="op">=</span> end<span class="op">;</span></span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a>    chunks</span>
<span id="cb17-17"><a href="#cb17-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb17-18"><a href="#cb17-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-19"><a href="#cb17-19" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> align_end_to_line(bytes<span class="op">:</span> <span class="op">&amp;</span>[<span class="dt">u8</span>]<span class="op">,</span> pos<span class="op">:</span> <span class="dt">usize</span>) <span class="op">-&gt;</span> <span class="dt">usize</span> <span class="op">{</span></span>
<span id="cb17-20"><a href="#cb17-20" aria-hidden="true" tabindex="-1"></a>    memchr(<span class="ch">b&#39;</span><span class="sc">\n</span><span class="ch">&#39;</span><span class="op">,</span> <span class="op">&amp;</span>bytes[pos<span class="op">..</span>])<span class="op">.</span>map_or(bytes<span class="op">.</span>len()<span class="op">,</span> <span class="op">|</span>offset<span class="op">|</span> pos <span class="op">+</span> offset <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb17-21"><a href="#cb17-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>To run in parallel:</p>
<div class="sourceCode" id="cb18"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">fn</span> run_parallel_borrowed_mmap(input_path<span class="op">:</span> <span class="op">&amp;</span><span class="dt">str</span><span class="op">,</span> output_path<span class="op">:</span> <span class="dt">Option</span><span class="op">&lt;&amp;</span><span class="dt">str</span><span class="op">&gt;,</span> threads<span class="op">:</span> <span class="dt">usize</span>) <span class="op">-&gt;</span> <span class="pp">io::</span><span class="dt">Result</span><span class="op">&lt;</span>()<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> file <span class="op">=</span> <span class="pp">File::</span>open(input_path)<span class="op">?;</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> mmap <span class="op">=</span> <span class="kw">unsafe</span> <span class="op">{</span> <span class="pp">MmapOptions::</span>new()<span class="op">.</span>map(<span class="op">&amp;</span>file)<span class="op">?</span> <span class="op">};</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> chunks <span class="op">=</span> chunks_for_threads(<span class="op">&amp;</span>mmap<span class="op">,</span> threads<span class="op">.</span>max(<span class="dv">1</span>))<span class="op">;</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> local_tables <span class="op">=</span> <span class="pp">thread::</span>scope(<span class="op">|</span>scope<span class="op">|</span> <span class="op">{</span></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> handles<span class="op">:</span> <span class="dt">Vec</span><span class="op">&lt;</span>_<span class="op">&gt;</span> <span class="op">=</span> chunks<span class="op">.</span>iter()<span class="op">.</span>map(<span class="op">|&amp;</span>(start<span class="op">,</span> end)<span class="op">|</span> <span class="op">{</span></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a>            <span class="kw">let</span> bytes <span class="op">=</span> <span class="op">&amp;</span>mmap[start<span class="op">..</span>end]<span class="op">;</span></span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a>            scope<span class="op">.</span>spawn(<span class="kw">move</span> <span class="op">||</span> <span class="op">{</span></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>                <span class="kw">let</span> <span class="kw">mut</span> table <span class="op">=</span> <span class="pp">FlatTable::</span>new()<span class="op">;</span></span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>                process_bytes(bytes<span class="op">,</span> <span class="op">&amp;</span><span class="kw">mut</span> table)<span class="op">;</span></span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a>                table</span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span>)</span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span>)<span class="op">.</span>collect()<span class="op">;</span></span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-16"><a href="#cb18-16" aria-hidden="true" tabindex="-1"></a>        handles<span class="op">.</span>into_iter()</span>
<span id="cb18-17"><a href="#cb18-17" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>map(<span class="op">|</span>h<span class="op">|</span> h<span class="op">.</span>join()<span class="op">.</span>expect(<span class="st">&quot;worker thread panicked&quot;</span>))</span>
<span id="cb18-18"><a href="#cb18-18" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="pp">collect::</span><span class="op">&lt;</span><span class="dt">Vec</span><span class="op">&lt;</span>_<span class="op">&gt;&gt;</span>()</span>
<span id="cb18-19"><a href="#cb18-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>)<span class="op">;</span></span>
<span id="cb18-20"><a href="#cb18-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-21"><a href="#cb18-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> table <span class="op">=</span> <span class="pp">FlatTable::</span>new()<span class="op">;</span></span>
<span id="cb18-22"><a href="#cb18-22" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> local <span class="kw">in</span> local_tables <span class="op">{</span></span>
<span id="cb18-23"><a href="#cb18-23" aria-hidden="true" tabindex="-1"></a>        table<span class="op">.</span>merge_from(<span class="op">&amp;</span>local)<span class="op">;</span></span>
<span id="cb18-24"><a href="#cb18-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb18-25"><a href="#cb18-25" aria-hidden="true" tabindex="-1"></a>    <span class="co">// sort and write</span></span>
<span id="cb18-26"><a href="#cb18-26" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>To merge:</p>
<div class="sourceCode" id="cb19"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> merge_from(<span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">,</span> other<span class="op">:</span> <span class="op">&amp;</span>FlatTable<span class="op">&lt;</span><span class="ot">&#39;a</span><span class="op">&gt;</span>) <span class="op">{</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">&amp;</span>slot <span class="kw">in</span> other<span class="op">.</span>slots<span class="op">.</span>iter() <span class="op">{</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> slot<span class="op">.</span>key<span class="op">.</span>is_empty() <span class="op">{</span> <span class="cf">continue</span><span class="op">;</span> <span class="op">}</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> <span class="kw">mut</span> idx <span class="op">=</span> table_index(slot<span class="op">.</span>fingerprint<span class="op">,</span> slot<span class="op">.</span>key<span class="op">.</span>len())<span class="op">;</span></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">loop</span> <span class="op">{</span></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>            <span class="kw">let</span> target <span class="op">=</span> <span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">.</span>slots[idx]<span class="op">;</span></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> target<span class="op">.</span>key<span class="op">.</span>is_empty() <span class="op">{</span></span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a>                <span class="op">*</span>target <span class="op">=</span> slot<span class="op">;</span></span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span><span class="op">;</span></span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> target<span class="op">.</span>fingerprint <span class="op">==</span> slot<span class="op">.</span>fingerprint <span class="op">&amp;&amp;</span> target<span class="op">.</span>key <span class="op">==</span> slot<span class="op">.</span>key <span class="op">{</span></span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a>                target<span class="op">.</span>stats<span class="op">.</span>sum <span class="op">+=</span> slot<span class="op">.</span>stats<span class="op">.</span>sum<span class="op">;</span></span>
<span id="cb19-13"><a href="#cb19-13" aria-hidden="true" tabindex="-1"></a>                target<span class="op">.</span>stats<span class="op">.</span>count <span class="op">+=</span> slot<span class="op">.</span>stats<span class="op">.</span>count<span class="op">;</span></span>
<span id="cb19-14"><a href="#cb19-14" aria-hidden="true" tabindex="-1"></a>                target<span class="op">.</span>stats<span class="op">.</span>min <span class="op">=</span> target<span class="op">.</span>stats<span class="op">.</span>min<span class="op">.</span>min(slot<span class="op">.</span>stats<span class="op">.</span>min)<span class="op">;</span></span>
<span id="cb19-15"><a href="#cb19-15" aria-hidden="true" tabindex="-1"></a>                target<span class="op">.</span>stats<span class="op">.</span>max <span class="op">=</span> target<span class="op">.</span>stats<span class="op">.</span>max<span class="op">.</span>max(slot<span class="op">.</span>stats<span class="op">.</span>max)<span class="op">;</span></span>
<span id="cb19-16"><a href="#cb19-16" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span><span class="op">;</span></span>
<span id="cb19-17"><a href="#cb19-17" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb19-18"><a href="#cb19-18" aria-hidden="true" tabindex="-1"></a>            idx <span class="op">=</span> (idx <span class="op">+</span> <span class="dv">1</span>) <span class="op">&amp;</span> TABLE_MASK<span class="op">;</span></span>
<span id="cb19-19"><a href="#cb19-19" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb19-20"><a href="#cb19-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb19-21"><a href="#cb19-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>With that, we get a runtime of about 21ms.</p>
<object type="image/svg+xml" data="../assets/obrc/fast-par.svg" width="100%" height="100%">
</object>
<h2 id="conclusion">Conclusion</h2>
<p>In the end, we started out with about a 220ms runtime and got it down
all the way to 21ms, about a 10x improvement. The first improvement of
just using a hashmap did most of the work, down to 110ms, and each
respective improvement took more and more work to do for less and less
gain.</p>
<p>Cargo flamegraph made it easy to find hotspots, but it doesn’t tell
you how to improve your solution – that requires hard thought, but it’s
useful to figure out where there’s room to improve.</p>]]></description>
</item>
<item>
<title>Bigints</title>
<pubDate>Mon, 02 Mar 2026 23:32:16 +0000</pubDate>
<guid>https://blog/bigints.html</guid>
<description><![CDATA[<p>Let’s talk about writing Bigints. A Bigint is a
data structure that allows one to do math on integers that are larger
than the computer’s register size. On a 64 bit computer, registers are
64 bits, so if you want to add two numbers that are larger than can fit
in 64 bits, you’d need to put them in two registers or more per number,
and then apply each mathematical operation to all the registers.</p>
<p>Let’s start off with a <code>u128</code> type. That would look
something like this:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>derive<span class="at">(</span><span class="bu">Debug</span><span class="op">,</span> <span class="bu">Clone</span><span class="op">,</span> <span class="bu">Copy</span><span class="at">)]</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">struct</span> Uint128 <span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span> h<span class="op">:</span> <span class="dt">u64</span><span class="op">,</span> </span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span> l<span class="op">:</span> <span class="dt">u64</span><span class="op">,</span> </span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>For addition, subtraction, and multiplication thankfully nightly rust
has <code>overflowing_*</code>, <code>widening_*</code> and
<code>wrapping_*</code> methods on integers that allow us a simple
implementation.</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">impl</span> <span class="pp">std::ops::</span><span class="bu">Add</span> <span class="cf">for</span> Uint128 <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">type</span> Output <span class="op">=</span> <span class="dt">Self</span><span class="op">;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="at">#[</span>inline<span class="at">(</span>never<span class="at">)]</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> add(<span class="kw">self</span><span class="op">,</span> rhs<span class="op">:</span> <span class="dt">Self</span>) <span class="op">-&gt;</span> <span class="dt">Self</span><span class="pp">::</span>Output <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> (l<span class="op">,</span> carry) <span class="op">=</span> <span class="kw">self</span><span class="op">.</span>l<span class="op">.</span>overflowing_add(rhs<span class="op">.</span>l)<span class="op">;</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> h <span class="op">=</span> <span class="kw">self</span><span class="op">.</span>h<span class="op">.</span>wrapping_add(rhs<span class="op">.</span>h)<span class="op">.</span>wrapping_add(carry <span class="kw">as</span> <span class="dt">u64</span>)<span class="op">;</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Self</span> <span class="op">{</span> l<span class="op">,</span> h <span class="op">}</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb3"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">impl</span> <span class="pp">std::ops::</span><span class="bu">Sub</span> <span class="cf">for</span> Uint128 <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">type</span> Output <span class="op">=</span> <span class="dt">Self</span><span class="op">;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    <span class="at">#[</span>inline<span class="at">(</span>never<span class="at">)]</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> sub(<span class="kw">self</span><span class="op">,</span> rhs<span class="op">:</span> <span class="dt">Self</span>) <span class="op">-&gt;</span> <span class="dt">Self</span><span class="pp">::</span>Output <span class="op">{</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> (l<span class="op">,</span> borrow) <span class="op">=</span> <span class="kw">self</span><span class="op">.</span>l<span class="op">.</span>overflowing_sub(rhs<span class="op">.</span>l)<span class="op">;</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> h <span class="op">=</span> <span class="kw">self</span><span class="op">.</span>h<span class="op">.</span>wrapping_sub(rhs<span class="op">.</span>h)<span class="op">.</span>wrapping_sub(borrow <span class="kw">as</span> <span class="dt">u64</span>)<span class="op">;</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Self</span> <span class="op">{</span> l<span class="op">,</span> h <span class="op">}</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb4"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">impl</span> <span class="pp">std::ops::</span><span class="bu">Mul</span> <span class="cf">for</span> Uint128 <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> mul(<span class="kw">self</span><span class="op">,</span> rhs<span class="op">:</span> <span class="dt">Self</span>) <span class="op">-&gt;</span> <span class="dt">Self</span><span class="pp">::</span>Output <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> (p0_lo<span class="op">,</span> p0_hi) <span class="op">=</span> <span class="kw">self</span><span class="op">.</span>l<span class="op">.</span>widening_mul(rhs<span class="op">.</span>l)<span class="op">;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> t1_lo <span class="op">=</span> <span class="kw">self</span><span class="op">.</span>l<span class="op">.</span>wrapping_mul(rhs<span class="op">.</span>h)<span class="op">;</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> t2_lo <span class="op">=</span> <span class="kw">self</span><span class="op">.</span>h<span class="op">.</span>wrapping_mul(rhs<span class="op">.</span>l)<span class="op">;</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> h <span class="op">=</span> p0_hi<span class="op">.</span>wrapping_add(t1_lo)<span class="op">.</span>wrapping_add(t2_lo)<span class="op">;</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Self</span> <span class="op">{</span> h<span class="op">,</span> l<span class="op">:</span> p0_lo <span class="op">}</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>For division we have to handwrite and lean on the <code>u128</code>
type, but we get a pretty nice result in the end:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">impl</span> <span class="pp">std::ops::</span><span class="bu">Div</span> <span class="cf">for</span> Uint128 <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> div(<span class="kw">self</span><span class="op">,</span> rhs<span class="op">:</span> <span class="dt">Self</span>) <span class="op">-&gt;</span> <span class="dt">Self</span><span class="pp">::</span>Output <span class="op">{</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> n <span class="op">=</span> (<span class="kw">self</span><span class="op">.</span>h <span class="kw">as</span> <span class="dt">u128</span>) <span class="op">&lt;&lt;</span> <span class="dv">64</span> <span class="op">|</span> <span class="kw">self</span><span class="op">.</span>l <span class="kw">as</span> <span class="dt">u128</span><span class="op">;</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> d <span class="op">=</span> (rhs<span class="op">.</span>h <span class="kw">as</span> <span class="dt">u128</span>) <span class="op">&lt;&lt;</span> <span class="dv">64</span> <span class="op">|</span> rhs<span class="op">.</span>l <span class="kw">as</span> <span class="dt">u128</span><span class="op">;</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> q <span class="op">=</span> n <span class="op">/</span> d<span class="op">;</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Self</span> <span class="op">{</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>            l<span class="op">:</span> q <span class="kw">as</span> <span class="dt">u64</span><span class="op">,</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>            h<span class="op">:</span> (q <span class="op">&gt;&gt;</span> <span class="dv">64</span>) <span class="kw">as</span> <span class="dt">u64</span><span class="op">,</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The assembly delegates to a compiler builtin called
<code>__udivti3</code>, so our code is pretty much loads that up and all
the hairy work is done for us.</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode asm"><code class="sourceCode fasm"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>&lt;bigints<span class="op">::</span>u128<span class="op">::</span>Uint128 as core<span class="op">::</span>ops<span class="op">::</span>arith<span class="op">::</span>Div<span class="op">&gt;::</span>div<span class="op">:</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">push</span> <span class="kw">rax</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>    <span class="bu">mov</span> <span class="kw">rax</span><span class="op">,</span> <span class="kw">rdx</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>    <span class="bu">or</span> <span class="kw">rax</span><span class="op">,</span> <span class="kw">rcx</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">je</span> <span class="op">.</span>LBB_2</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">call</span> <span class="dt">qword</span> <span class="dt">ptr</span> <span class="op">[</span>rip <span class="op">+</span> __udivti3<span class="fu">@</span><span class="er">G</span>OTPCREL<span class="op">]</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>    <span class="bu">pop</span> <span class="kw">rcx</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">ret</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a><span class="fu">.LBB_2:</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>    <span class="bu">lea</span> <span class="kw">rdi</span><span class="op">,</span> <span class="op">[</span>rip <span class="op">+</span> <span class="op">.</span>Lanon<span class="op">.</span><span class="dv">12</span><span class="op">]</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">call</span> <span class="dt">qword</span> <span class="dt">ptr</span> <span class="op">[</span>rip <span class="op">+</span> core<span class="op">::</span>panicking<span class="op">::</span>panic_const<span class="op">::</span>panic_const_div_by_zero<span class="fu">@</span><span class="er">G</span>OTPCREL<span class="op">]</span></span></code></pre></div>
<p>And that’s it, right?</p>
<p>Sadly I wrote a bug in the beginning for my platform (x86_64). The
bigints struct has to flip its members since this is a little-endian
platform.</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>derive<span class="at">(</span><span class="bu">Debug</span><span class="op">,</span> <span class="bu">Clone</span><span class="op">,</span> <span class="bu">Copy</span><span class="at">)]</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">struct</span> Uint128 <span class="op">{</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span> l<span class="op">:</span> <span class="dt">u64</span><span class="op">,</span> </span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span> h<span class="op">:</span> <span class="dt">u64</span><span class="op">,</span> </span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Otherwise the multiplication incurs two extra <code>mov</code>s at
the start of the function to load the members into the right place.</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode asm"><code class="sourceCode fasm"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="bu">mov</span> <span class="kw">rax</span><span class="op">,</span> <span class="kw">rdx</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="bu">mov</span> <span class="kw">rdx</span><span class="op">,</span> <span class="kw">rcx</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="bu">mulx</span> <span class="kw">r8</span><span class="op">,</span> <span class="kw">rdx</span><span class="op">,</span> <span class="kw">rsi</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="bu">imul</span> <span class="kw">rax</span><span class="op">,</span> <span class="kw">rsi</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="bu">imul</span> <span class="kw">rdi</span><span class="op">,</span> <span class="kw">rcx</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a><span class="bu">add</span> <span class="kw">rax</span><span class="op">,</span> <span class="kw">rdi</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a><span class="bu">add</span> <span class="kw">rax</span><span class="op">,</span> <span class="kw">r8</span></span></code></pre></div>
<p>If you write the struct the other way, i.e:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>derive<span class="at">(</span><span class="bu">Debug</span><span class="op">,</span> <span class="bu">Clone</span><span class="op">,</span> <span class="bu">Copy</span><span class="at">)]</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>cfg<span class="at">(</span>target_endian <span class="op">=</span> <span class="st">&quot;little&quot;</span><span class="at">)]</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">struct</span> Uint128 <span class="op">{</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span> l<span class="op">:</span> <span class="dt">u64</span><span class="op">,</span> <span class="co">// bits 0-63 (lower address)</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span> h<span class="op">:</span> <span class="dt">u64</span><span class="op">,</span> <span class="co">// bits 64-127 (higher address)</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>derive<span class="at">(</span><span class="bu">Debug</span><span class="op">,</span> <span class="bu">Clone</span><span class="op">,</span> <span class="bu">Copy</span><span class="at">)]</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>cfg<span class="at">(</span>target_endian <span class="op">=</span> <span class="st">&quot;big&quot;</span><span class="at">)]</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">struct</span> Uint128 <span class="op">{</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span> h<span class="op">:</span> <span class="dt">u64</span><span class="op">,</span> <span class="co">// bits 64-127 (lower address)</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span> l<span class="op">:</span> <span class="dt">u64</span><span class="op">,</span> <span class="co">// bits 0-63 (higher address)</span></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Then the two <code>mov</code>s disappear from the x86_64 generated
codegen.</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode asm"><code class="sourceCode fasm"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="bu">mulx</span> <span class="kw">r8</span><span class="op">,</span> <span class="kw">rdx</span><span class="op">,</span> <span class="kw">rsi</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="bu">imul</span> <span class="kw">rax</span><span class="op">,</span> <span class="kw">rsi</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="bu">imul</span> <span class="kw">rdi</span><span class="op">,</span> <span class="kw">rcx</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="bu">add</span> <span class="kw">rax</span><span class="op">,</span> <span class="kw">rdi</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="bu">add</span> <span class="kw">rax</span><span class="op">,</span> <span class="kw">r8</span></span></code></pre></div>
<p>Now I needed a way to make sure all my operations were closer to
native, so I wrote up a test harness that used
<code>cargo-show-asm</code> to check the generated assembly on a variety
of platforms (including a big-endian one, s390x) to make sure that there
were no unnecessary moves being produced.</p>
<p>I used this and compared my implementations to native to see if they
were being properly optimized and found out that for aarch64, using
<code>overflowing_sub</code> and <code>wrapping_sub</code> nets
this:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode asm"><code class="sourceCode fasm"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>&lt;bigints<span class="op">::</span>u128<span class="op">::</span>Uint128 as core<span class="op">::</span>ops<span class="op">::</span>arith<span class="op">::</span>Sub<span class="op">&gt;::</span>sub<span class="op">:</span>                                                                                                                                                                                                                                                                                                                                </span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>    subs x0<span class="op">,</span> x0<span class="op">,</span> x2                                                                                                                                                                                                                                                                                                                                                                    </span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>    <span class="bu">sub</span> x8<span class="op">,</span> x1<span class="op">,</span> x3                                                                                                                                                                                                                                                                                                                                                                     </span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>    cset w9<span class="op">,</span> lo                                                                                                                                                                                                                                                                                                                                                                        </span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>    <span class="bu">sub</span> x1<span class="op">,</span> x8<span class="op">,</span> x9                                                                                                                                                                                                                                                                                                                                                                     </span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">ret</span>                                                                                                                                                                                                                                                                                                                                                                                </span></code></pre></div>
<p>Whereas the native version looks like so:</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode asm"><code class="sourceCode fasm"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>&lt;bigints<span class="op">::</span>u128<span class="op">::</span>Uint128 as core<span class="op">::</span>ops<span class="op">::</span>arith<span class="op">::</span>Sub<span class="op">&gt;::</span>sub<span class="op">:</span>                                                                                                                                                                                                                                                                                                                                </span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>  subs x0<span class="op">,</span> x0<span class="op">,</span> x2</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>  sbc  x1<span class="op">,</span> x1<span class="op">,</span> x3</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">ret</span></span></code></pre></div>
<p>While for x86_64, it’s properly optimized:</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode asm"><code class="sourceCode fasm"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>&lt;bigints<span class="op">::</span>u128<span class="op">::</span>Uint128 as core<span class="op">::</span>ops<span class="op">::</span>arith<span class="op">::</span>Sub<span class="op">&gt;::</span>sub<span class="op">:</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">mov</span> <span class="kw">rax</span><span class="op">,</span> <span class="kw">rdi</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    <span class="bu">sub</span> <span class="kw">rax</span><span class="op">,</span> <span class="kw">rdx</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    <span class="bu">sbb</span> <span class="kw">rsi</span><span class="op">,</span> <span class="kw">rcx</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>    <span class="bu">mov</span> <span class="kw">rdx</span><span class="op">,</span> <span class="kw">rsi</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">ret</span></span></code></pre></div>
<p>As well, for multiplication, there’s an extra instruction due to
scheduling:</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode asm"><code class="sourceCode fasm"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>&lt;bigints<span class="op">::</span>u128<span class="op">::</span>Uint128 as core<span class="op">::</span>ops<span class="op">::</span>arith<span class="op">::</span>Mul<span class="op">&gt;::</span>mul<span class="op">:</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">mul</span> x9<span class="op">,</span> x2<span class="op">,</span> x1</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    <span class="bu">mul</span> x8<span class="op">,</span> x2<span class="op">,</span> x0</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>    umulh x10<span class="op">,</span> x2<span class="op">,</span> x0</span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>    madd x9<span class="op">,</span> x3<span class="op">,</span> x0<span class="op">,</span> x9</span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>    <span class="bu">mov</span> x0<span class="op">,</span> x8</span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>    <span class="bu">add</span> x1<span class="op">,</span> x9<span class="op">,</span> x10</span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">ret</span></span></code></pre></div>
<div class="sourceCode" id="cb15"><pre
class="sourceCode asm"><code class="sourceCode fasm"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>&lt;bigints<span class="op">::</span>u128<span class="op">::</span>Uint128 as core<span class="op">::</span>ops<span class="op">::</span>arith<span class="op">::</span>Mul<span class="op">&gt;::</span>mul<span class="op">:</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>    umulh x10<span class="op">,</span> x0<span class="op">,</span> x2    </span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>    <span class="bu">mul</span> x9<span class="op">,</span> x1<span class="op">,</span> x2       </span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>    madd x9<span class="op">,</span> x3<span class="op">,</span> x0<span class="op">,</span> x9  </span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>    <span class="bu">mul</span> x0<span class="op">,</span> x0<span class="op">,</span> x2       </span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>    <span class="bu">add</span> x1<span class="op">,</span> x9<span class="op">,</span> x10      </span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">ret</span></span></code></pre></div>
<p>I assume this is an LLVM backend issue somewhere, but it’s hard to
fault them, I doubt anyone would write this code anyway since the u128
types exist.</p>
<p>The resulting code is here: <a
href="https://github.com/takashiidobe/bigints">Bigints</a></p>]]></description>
</item>
<item>
<title>Assembly Language</title>
<pubDate>Wed, 03 Dec 2025 03:28:56 +0000</pubDate>
<guid>https://blog/assembly-language.html</guid>
<description><![CDATA[<p>Confession: I don’t know much about assembly.
Thankfully compilers are good enough these days that it doesn’t matter,
but I’ve always been curious about writing assembly as is. I ended up
writing some m68k assembly last post when writing an m68k to x86_64
interpreter. So I had the bright idea to write my own assembly language.
For fun.</p>
<p>Now the actual plan was as follows: write an assembly language spec,
write an interpreter, and write an encoder/decoder (so I could test out
how different design decisions affected code density in the binary). My
first order of business was to decide on the size of my opcodes. I
decided to go with 16-bit like the m68k – I thought it would be spartan
enough to not endlessly iterate and be compact yet give me enough space
to design instructions. My first decision was to reverse one design
decision I think hampered the m68k, splitting registers into address and
data registers.</p>
<p>On the m68k, there are 16 32-bit registers. This is for a CPU that
came out in 1979; compare it to a similar Intel CPU at the time, the
8086. The 8086 came with 8 16-bit registers. You get 2 times the
registers with 2 times the bit-width. Sadly, with the data
register/address register split, the 8 data registers store the usual
data and the 8 address registers are for indirect accessing of memory. I
assume this was chosen because this made registers take 3-bits (2^3 = 8)
instead of 4-bits (2^4 = 16), and because the m68k had support for 8
effective addressing modes on its two operands, which took up 6 bits in
total (EA + Reg). Given a 4-bit group, you’d be left with another 3 bits
for the register for a binary operator, or to do what you wanted.</p>
<p>I wanted to see if it was possible to support 16 registers, so I bit
the 4-bit bullet per register. Given that an instruction set needs to
have at least 30 must have instructions, you also need to reserve at
least 5 bits for every instruction so you know which opcode to use. I
decided to go with a scheme that would allow me to have up to 64
instructions – a 4-bit major group, with a further 2-bits subdividing
each group with 4 instructions each, so I would have 16 groups with 4
subgroups in each group. This left me with 10-bits. You see the problem.
If each register costs you 4-bits, and you have 2 of them, you’re left
with 2 bits per instruction. But wait, there’s more. Each instruction
must also carry bits for its size. I wanted 16 64-bit registers, so each
instruction had to support an 8-bit, 16-bit, 32-bit, and 64-bit variant
(I called these byte, short, long, word). This is 4 choices, so this
takes up 2-bits.</p>
<p>So there you have it. Each binary instruction has 4-bits for group,
4-bits for subgroup, 2-bits for size, 4-bits for register 1 (which is
the target) and 4-bits for register 2. This works out for most
instructions, like arithmetic ones, but you cannot do an arithmetic
operation + change the addressing mode.</p>
<p>To do so, I added three instructions as full 12-bit instructions.
<code>lea</code>, (load effective address), a load and store
instruction. These took up 4 instructions a pop (since they take up a
whole group), but I was able to cram in a 2-bit effective address for
each of these.</p>
<p>The effective addresses are:</p>
<ol type="1">
<li>register direct, as is: <code>%rX</code></li>
<li>register indirect, the address of the register,
<code>(%rX)</code></li>
<li>immediate, <code>$10</code></li>
<li>offset indirect <code>-4(%sp)</code></li>
</ol>
<p>Since you can only place this on either the src or the target, this
is a bit barebones, but it works out fine.</p>
<p>I decided not to go with a condition flag design (like m68k, arm,
x86) and take a flagless design – in exchange though, you have to
implement a lot of branching operations. For the branching
instructions:</p>
<ol type="1">
<li>Branch if Equal</li>
<li>Branch if not equal</li>
<li>Branch less than</li>
<li>Branch less than equal</li>
<li>Branch if Zero</li>
<li>Branch if not zero</li>
</ol>
<p>I could’ve gone with a sparser set, but I figured it’d be ok to use
the instructions since branching is quite commonplace. For the cmp side,
I decided to go with a sparser set, explicitly requiring a not or a flip
of operands to get <code>&lt;=</code>, <code>&gt;</code>, and
<code>&gt;=</code>.</p>
<ol type="1">
<li>Cmp equal</li>
<li>Cmp not equal</li>
<li>Cmp less than equal</li>
<li>Cmp less than</li>
</ol>
<p>I also wanted compact operations that used immediates a lot, so I
provided immediate verisons of add, sub, mul, mov. If I dropped the
size, I could have 6-bits left over. So I can have immediates from
0..63. However, I really wanted to be able to use <code>64</code>. It
turns out you actually can support the range of 0..64 for these ops:</p>
<p>For <code>add</code> and <code>sub</code> with 0, this does nothing,
so you can read this code and emit a no-op instead. For <code>mul</code>
and <code>mov</code>, it zeroes out the target register. You can do the
same with <code>xor %rX, %rX</code>, which zeroes out the target
register. Thus, in the textual assembly format, You can support 65
values (which requires 7-bits) by rewriting the last case to something
supported. You can also do this with div (rewrite
<code>div %rX, $0</code> with <code>trap</code>), or <code>mod</code> as
well.</p>
<p>I decided to add a few extra assembly directives:</p>
<ul>
<li><code>.byte</code> to include a byte array,</li>
<li><code>.ascii</code> to include an ascii string,</li>
<li><code>.asciz</code> to include an ascii string with a null
terminator</li>
<li><code>.include</code> to include the file copy pasted as in C, to
link multiple assembly files together.</li>
</ul>
<p>After hooking up syscall write on linux, you can write assembly
pretty well:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode asm"><code class="sourceCode fasm"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>        movi <span class="op">%</span>r0<span class="op">,</span> <span class="op">$</span><span class="bn">1</span>         <span class="op">#</span> syscall write </span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>        movi <span class="op">%</span>r1<span class="op">,</span> <span class="op">$</span><span class="bn">1</span>         <span class="op">#</span> stdout</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>        <span class="bu">load</span><span class="op">.</span>l <span class="op">%</span>r2<span class="op">,</span> msg      <span class="op">#</span> r2 <span class="op">=</span> <span class="op">&amp;</span>msg</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>        movi <span class="op">%</span>r3<span class="op">,</span> <span class="op">$</span><span class="bn">12</span>        <span class="op">#</span> length</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>        trap                 <span class="op">#</span> perform write</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">ret</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="fu">msg:</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>        .asciz <span class="st">&quot;hello world\n&quot;</span></span></code></pre></div>
<p>And recursive fibonacci isn’t so bad:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode asm"><code class="sourceCode fasm"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a># Calculate fib<span class="op">(</span><span class="dv">10</span><span class="op">)</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>        movi <span class="op">%</span>r1<span class="op">,</span> <span class="op">$</span><span class="bn">10</span>        <span class="op">#</span> n <span class="op">=</span> <span class="dv">10</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">call</span> fib</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">jmp</span> done</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="fu">fib:</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>        # Prologue<span class="op">:</span> save caller<span class="op">-</span>saved registers</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>        <span class="bu">push</span><span class="op">.</span>w <span class="op">%</span>r2</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>        <span class="bu">push</span><span class="op">.</span>w <span class="op">%</span>r3</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>        # Base case<span class="op">:</span> if n <span class="op">==</span> <span class="dv">0</span><span class="op">,</span> return <span class="dv">0</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>        brz<span class="op">.</span>l <span class="op">%</span>r1<span class="op">,</span> base_case</span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>        # Base case<span class="op">:</span> if n <span class="op">==</span> <span class="dv">1</span><span class="op">,</span> return <span class="dv">1</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>        <span class="bu">mov</span><span class="op">.</span>l <span class="op">%</span>r3<span class="op">,</span> <span class="op">%</span>r1</span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>        subi<span class="op">.</span>l <span class="op">%</span>r3<span class="op">,</span> <span class="op">$</span><span class="bn">1</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>        brz<span class="op">.</span>l <span class="op">%</span>r3<span class="op">,</span> base_case</span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>        # Recursive case<span class="op">:</span> fib<span class="op">(</span>n<span class="op">-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>        subi  <span class="op">%</span>r1<span class="op">,</span> <span class="op">$</span><span class="bn">1</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>        <span class="bu">push</span><span class="op">.</span>w <span class="op">%</span>r1            <span class="op">#</span> Save n<span class="op">-</span><span class="dv">1</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>        <span class="cf">call</span> fib</span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a>        <span class="bu">mov</span><span class="op">.</span>l <span class="op">%</span>r2<span class="op">,</span> <span class="op">%</span>r0        <span class="op">#</span> r2 <span class="op">=</span> fib<span class="op">(</span>n<span class="op">-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a>        <span class="bu">pop</span><span class="op">.</span>w <span class="op">%</span>r1             <span class="op">#</span> Restore n<span class="op">-</span><span class="dv">1</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a>        # fib<span class="op">(</span>n<span class="op">-</span><span class="dv">2</span><span class="op">)</span></span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a>        subi<span class="op">.</span>l <span class="op">%</span>r1<span class="op">,</span> <span class="op">$</span><span class="bn">1</span></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a>        <span class="bu">push</span><span class="op">.</span>w <span class="op">%</span>r1</span>
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a>        <span class="cf">call</span> fib</span>
<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a>        <span class="bu">mov</span><span class="op">.</span>l <span class="op">%</span>r3<span class="op">,</span> <span class="op">%</span>r0        <span class="op">#</span> r3 <span class="op">=</span> fib<span class="op">(</span>n<span class="op">-</span><span class="dv">2</span><span class="op">)</span></span>
<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a>        <span class="bu">pop</span><span class="op">.</span>w <span class="op">%</span>r1</span>
<span id="cb2-32"><a href="#cb2-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-33"><a href="#cb2-33" aria-hidden="true" tabindex="-1"></a>        # Return fib<span class="op">(</span>n<span class="op">-</span><span class="dv">1</span><span class="op">)</span> <span class="op">+</span> fib<span class="op">(</span>n<span class="op">-</span><span class="dv">2</span><span class="op">)</span></span>
<span id="cb2-34"><a href="#cb2-34" aria-hidden="true" tabindex="-1"></a>        <span class="bu">mov</span><span class="op">.</span>l <span class="op">%</span>r0<span class="op">,</span> <span class="op">%</span>r2</span>
<span id="cb2-35"><a href="#cb2-35" aria-hidden="true" tabindex="-1"></a>        <span class="bu">add</span><span class="op">.</span>l <span class="op">%</span>r0<span class="op">,</span> <span class="op">%</span>r3</span>
<span id="cb2-36"><a href="#cb2-36" aria-hidden="true" tabindex="-1"></a>        <span class="cf">jmp</span> end_fib</span>
<span id="cb2-37"><a href="#cb2-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-38"><a href="#cb2-38" aria-hidden="true" tabindex="-1"></a><span class="fu">base_case:</span></span>
<span id="cb2-39"><a href="#cb2-39" aria-hidden="true" tabindex="-1"></a>        <span class="bu">mov</span><span class="op">.</span>l <span class="op">%</span>r0<span class="op">,</span> <span class="op">%</span>r1        <span class="op">#</span> Return n</span>
<span id="cb2-40"><a href="#cb2-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-41"><a href="#cb2-41" aria-hidden="true" tabindex="-1"></a><span class="fu">end_fib:</span></span>
<span id="cb2-42"><a href="#cb2-42" aria-hidden="true" tabindex="-1"></a>        # Epilogue<span class="op">:</span> restore registers</span>
<span id="cb2-43"><a href="#cb2-43" aria-hidden="true" tabindex="-1"></a>        <span class="bu">pop</span><span class="op">.</span>w <span class="op">%</span>r3</span>
<span id="cb2-44"><a href="#cb2-44" aria-hidden="true" tabindex="-1"></a>        <span class="bu">pop</span><span class="op">.</span>w <span class="op">%</span>r2</span>
<span id="cb2-45"><a href="#cb2-45" aria-hidden="true" tabindex="-1"></a>        <span class="cf">ret</span></span>
<span id="cb2-46"><a href="#cb2-46" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-47"><a href="#cb2-47" aria-hidden="true" tabindex="-1"></a><span class="fu">done:</span></span>
<span id="cb2-48"><a href="#cb2-48" aria-hidden="true" tabindex="-1"></a>        <span class="bu">nop</span></span></code></pre></div>
<p>I really enjoyed this project – it was interesting to design an
assembly language, since it made me value what instructions could be
supported with such little space. I still won’t be writing assembly, but
at least I can understand why it’s so hard to design a good
ISA!</p>]]></description>
</item>
<item>
<title>An M68k to x86_64 linux interpreter</title>
<pubDate>Sat, 29 Nov 2025 00:17:00 +0000</pubDate>
<guid>https://blog/an-m68k-to-x86-64-linux-interpreter.html</guid>
<description><![CDATA[<p>I’ve always been interested in Virtual
Machines, even having a copy of <a
href="https://www.amazon.com/Virtual-Machines-Versatile-Platforms-Architecture/dp/1558609105">Virtual
Machines: Versatile Platforms</a> on my bookshelf. I decided it would be
fun to implement a program that could read an m68000 ELF binary and run
it on my x86_64 linux computer. The repo is here: <a
href="https://github.com/Takashiidobe/behistun/">Behistun</a>.</p>
<p>First things first, we had to compile some m68k ELF binaries. I fired
up my copy of crosstool and made myself an
<code>m68k-unknown-linux-gnu-gcc</code> toolchain.</p>
<p>To decode a binary, you have to first read the relevant ELF sections
of a binary. To do so, I used the <code>goblin</code> library, which
took care of that. The rest was to decode each instruction, and then
execute it on a virtual CPU.</p>
<p>So, I started writing out a file with a new <code>m68k</code>
assembly instruction, compiled it, and then tried to decode it with my
program. This would fail, so I would go to work decoding it.</p>
<p>I did this until I implemented the whole <code>m68000</code> set,
which wasn’t too bad, given that the <code>m68k</code> instruction set
is pretty compact. After decoding, I had to write a CPU that would
emulate everything, and I was good to go. This took a bit longer than
plain decoding, but after I got this to work out. Perfect! A fun little
weekend project, right?</p>
<p>Unfortunately I wanted more. And this is where the pain really
started. I wanted to compile C code for the <code>m68000</code> and run
it on my little interpreter. Couldn’t be so bad, right?</p>
<p>Unfortunately not. I wrote <code>cat</code> in c and then compiled it
and tried to run it on my interpreter – decoding error. It turned out
that the ELF binary had smuggled in an <code>fmove</code> (floating
point register move). Why does <code>cat</code>, a program which does
not have any floating point usage, need to move a floating point
register?</p>
<p>No matter what flags you use to compile your code, <code>glibc</code>
for the <code>m68k</code> target actually is compiled with floating
point support. Thus, it’s not possible to use <code>glibc</code> as your
<code>libc</code> for compiling <code>m68000</code>. Bummer. Sadly this
took me a day of searching to find out why floating point registers were
being smuggled into my user code. The <code>-mcpu=X</code> flag was
useless, even using <code>-msoft-float</code> was useless. Anyway, I
decided to go back to crosstool and try to compile a <code>musl</code>
toolchain. Musl would never betray me, would it?</p>
<p>Sadly it too requires floating point registers, and thus does not
support the 68000, on <code>setjmp</code>, to clear registers. I was
losing hope. But crosstool supports one last libc.
<code>uclibc-ng</code>. And <code>uclibc</code> delivered. It actually
did support non-floating point <code>m68k</code> and we were in
business. I compiled for the <code>m68020</code> to play it safe (each
compiler takes about 30 minutes to compile on my computer), and was back
at my interpreter, ready to compile some C.</p>
<p>To get <code>cat</code> to work though, I needed to do some syscall
passthrough. I needed to map the <code>m68000</code>’s pointers from
guest to host, and also map the syscall numbers from m68k linux to
x86_64 linux. But once that was done, I could finally write C, compile
to m68000 linux elf, and run it on my x86_64 linux elf machine.</p>
<p>Of course, there was a bit more to do – I had to implement the rest
of the <code>m68010</code> and <code>m68020</code> instruction set,
which I discovered I didn’t complete by using fuzzing to generate random
C programs with <code>csmith</code>, so I implemented those
instructions, and was off to the races – all I had to do was implement
syscalls.</p>
<p>In the end, I decided to translate about 200 or so syscalls, wrote
tests for them, and tested them out against
<code>qemu-m68k-static</code> for compatibility. There’s plenty more
syscalls left to do, but I figured these would be a good chunk of
syscalls, so I was done with that. Maybe I’ll come back and implement
the rest of them, who knows. The remaining ones are really tough, so I
skipped most of those.</p>]]></description>
</item>
<item>
<title>Writing Rust for the Atari Mint</title>
<pubDate>Fri, 28 Nov 2025 23:21:40 +0000</pubDate>
<guid>https://blog/writing-rust-for-the-atari-mint.html</guid>
<description><![CDATA[<p>Recently I decided to get into a retrocomputing
mood. I watched <a
href="https://www.youtube.com/watch?v=8VsiYWW9r48&amp;list=PLzH6n4zXuckpwdGMHgRH5N9xNHzVGCxwf">Matt
Godbolt’s videos on Computerphile talking about how computers work</a>
and after listening to him talk about learning how to program on these
old computers, I was ready to learn more. I was ready to open my wallet
and buy a retrocomputer and test out programming on these computers. On
ebay an Atari ST costs about $200. I reached into my pocket to grab my
credit card to buy one before coming to the realization that I’m broke.
Luckily, there’s a pretty active community programming these retro
computers, complete with emulators. I found a couple emulators like <a
href="https://aranym.github.io/">aranym</a> <a
href="https://hatari-emu.org/">hatari</a> and went on my way.</p>
<p>You could write code for these emulators in assembly or C, due to
there being a gcc toolchain for them: <a
href="https://tho-otto.de/crossmint.php"
class="uri">https://tho-otto.de/crossmint.php</a>. I downloaded gcc,
hooked up binutils and libraries, and started to write some code.</p>
<p>I went to go write some simple coreutils for the emulator, but
compiling my first binary (<code>rm</code>), my binary was &gt;100KB.
Given that the atari ST was supposed to run on 1.44MB floppies, eating
up a little over 1/15th of your storage on a 50-line C program is a
little absurd.</p>
<p>It turns out that the <code>libc</code> that the Atari mint toolchain
ships with links to a library called <code>mintlib</code>, which is a
pretty complete <code>libc</code>, but its binaries are huge. There’s an
alternative <code>libc</code> which isn’t as complete, called
<code>libcmini</code>. I linked to that <code>libc</code> instead and
saw the familiar file size of 4KB. Nice.</p>
<p>However, the binaries are still pretty large if you think about it.
An assembly version of this would probably fit in a few hundred bytes,
so C in this case does have a pretty large penalty.</p>
<p>I decided to start writing my own minimalistic <code>libc</code> and
incrementally build out some parts of it. The first part was the C
runtime, <code>crt0.S</code>. Afterwards, writing initializers and
finalizers, setting up the stack, env vars, and jumping to start. All of
this was pretty tricky but doable. Some interesting bits were the system
calls: <a
href="https://github.com/Takashiidobe/mintbox/blob/main/src/libc/include/mint/mintbind.h">mintbind.h</a>
where, given this isn’t a Linux OS, a lot of the system calls are pretty
interesting – there’s even a “malloc” so you can delegate memory
management to the kernel.</p>
<p>While writing the libc was fun to see what was under the hood, I
wanted some higher-level code. So I decided I wanted to write Rust.
First things first – I downloaded the <code>a.out</code> toolchain from
Thorsten Otto’s website. I needed the ELF one, since that was what
rust’s toolchain supported. Next, I had to write up a <a
href="https://github.com/Takashiidobe/mints/blob/main/m68k-atari-mintelf.json">target.json
file</a>, describing the properties of the architecture I was
targeting.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode json"><code class="sourceCode json"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;arch&quot;</span><span class="fu">:</span> <span class="st">&quot;m68k&quot;</span><span class="fu">,</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;atomic-cas&quot;</span><span class="fu">:</span> <span class="kw">false</span><span class="fu">,</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;cpu&quot;</span><span class="fu">:</span> <span class="st">&quot;M68040&quot;</span><span class="fu">,</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;crt-objects-fallback&quot;</span><span class="fu">:</span> <span class="st">&quot;false&quot;</span><span class="fu">,</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;crt-static-default&quot;</span><span class="fu">:</span> <span class="kw">false</span><span class="fu">,</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;crt-static-respected&quot;</span><span class="fu">:</span> <span class="kw">false</span><span class="fu">,</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;code-model&quot;</span><span class="fu">:</span> <span class="st">&quot;large&quot;</span><span class="fu">,</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;data-layout&quot;</span><span class="fu">:</span> <span class="st">&quot;E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16&quot;</span><span class="fu">,</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;dynamic-linking&quot;</span><span class="fu">:</span> <span class="kw">true</span><span class="fu">,</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;eh-frame-header&quot;</span><span class="fu">:</span> <span class="kw">false</span><span class="fu">,</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;executables&quot;</span><span class="fu">:</span> <span class="kw">true</span><span class="fu">,</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;has-rpath&quot;</span><span class="fu">:</span> <span class="kw">true</span><span class="fu">,</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;has-thread-local&quot;</span><span class="fu">:</span> <span class="kw">true</span><span class="fu">,</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;linker&quot;</span><span class="fu">:</span> <span class="st">&quot;m68k-atari-mintelf-gcc&quot;</span><span class="fu">,</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;llvm-target&quot;</span><span class="fu">:</span> <span class="st">&quot;m68k-unknown-elf&quot;</span><span class="fu">,</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;linker-is-gnu&quot;</span><span class="fu">:</span> <span class="kw">true</span><span class="fu">,</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;linker-flavor&quot;</span><span class="fu">:</span> <span class="st">&quot;gcc&quot;</span><span class="fu">,</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;pre-link-args&quot;</span><span class="fu">:</span> <span class="fu">{</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>    <span class="dt">&quot;gcc&quot;</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>      <span class="st">&quot;-nostartfiles&quot;</span><span class="ot">,</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>      <span class="st">&quot;-nostdlib&quot;</span><span class="ot">,</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>      <span class="st">&quot;-m68000&quot;</span><span class="ot">,</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>      <span class="st">&quot;-no-pie&quot;</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>    <span class="ot">]</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>  <span class="fu">},</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;late-link-args&quot;</span><span class="fu">:</span> <span class="fu">{</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>    <span class="dt">&quot;gcc&quot;</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>      <span class="st">&quot;-Wl,--gc-sections&quot;</span><span class="ot">,</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>      <span class="st">&quot;/home/takashi/current/mintbox/build/objs/crt0.o&quot;</span><span class="ot">,</span></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a>      <span class="st">&quot;-Wl,--start-group&quot;</span><span class="ot">,</span></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a>      <span class="st">&quot;-L/home/takashi/current/mintbox/build&quot;</span><span class="ot">,</span></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a>      <span class="st">&quot;-lcbox&quot;</span><span class="ot">,</span></span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a>      <span class="st">&quot;-Wl,--end-group&quot;</span><span class="ot">,</span></span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a>      <span class="st">&quot;-lgcc&quot;</span></span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a>    <span class="ot">]</span></span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a>  <span class="fu">},</span></span>
<span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;max-atomic-width&quot;</span><span class="fu">:</span> <span class="dv">32</span><span class="fu">,</span></span>
<span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;os&quot;</span><span class="fu">:</span> <span class="st">&quot;mint&quot;</span><span class="fu">,</span></span>
<span id="cb1-40"><a href="#cb1-40" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;panic-strategy&quot;</span><span class="fu">:</span> <span class="st">&quot;abort&quot;</span><span class="fu">,</span></span>
<span id="cb1-41"><a href="#cb1-41" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;position-independent-executables&quot;</span><span class="fu">:</span> <span class="kw">false</span><span class="fu">,</span></span>
<span id="cb1-42"><a href="#cb1-42" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;relocation-model&quot;</span><span class="fu">:</span> <span class="st">&quot;static&quot;</span><span class="fu">,</span></span>
<span id="cb1-43"><a href="#cb1-43" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;static-position-independent-executables&quot;</span><span class="fu">:</span> <span class="kw">false</span><span class="fu">,</span></span>
<span id="cb1-44"><a href="#cb1-44" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;target-endian&quot;</span><span class="fu">:</span> <span class="st">&quot;big&quot;</span><span class="fu">,</span></span>
<span id="cb1-45"><a href="#cb1-45" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;target-mcount&quot;</span><span class="fu">:</span> <span class="st">&quot;_mcount&quot;</span><span class="fu">,</span></span>
<span id="cb1-46"><a href="#cb1-46" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;target-pointer-width&quot;</span><span class="fu">:</span> <span class="dv">32</span><span class="fu">,</span></span>
<span id="cb1-47"><a href="#cb1-47" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;vendor&quot;</span><span class="fu">:</span> <span class="st">&quot;atari&quot;</span></span>
<span id="cb1-48"><a href="#cb1-48" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span></span></code></pre></div>
<p>After quite a bit of fumbling around, reading docs online, reading
the forums I was able to compile some code for rust. However, I ran into
the same problem where my binaries were 100KB. I couldn’t link to
libcmini, however, since I wanted to link to <code>alloc</code> in my
no_std Rust code. To do so, I needed an allocator, which I wanted to
delegate to the libc for. However, this requires
<code>posix_memalign</code>, which <code>libcmini</code> does not
provide. I implemented it in my libc, and was off to the races.</p>
<p>However, Rust turned out to be a pain in a very different way than
writing C. If you try to implement printing with <a
href="https://github.com/Takashiidobe/mints/blob/main/src/lib.rs#L38-L43">Rust’s
fmt helpers</a> when you try to print a type that can’t be “inlined” by
the compiler, it’ll pull in compiler builtins, and bundle a 300KB
runtime, bloating your binary by that much. If you for example, try to
debug print an integer, that’s 300KB. There might be some workaround by
using <code>args.as_str()</code> and failing, but this didn’t work in my
case. So I decided to stop here. But it was a fun
experiment.</p>]]></description>
</item>
<item>
<title>Daemons</title>
<pubDate>Thu, 13 Nov 2025 14:42:06 +0000</pubDate>
<guid>https://blog/daemons.html</guid>
<description><![CDATA[<p>Daemons are processes that run in the
background without interaction. An example would be <code>sshd</code>,
which accepts ssh connections in the background.</p>
<p>Nowadays, on linux, it’s recommended to use <code>systemd</code> to
manage your daemons. <code>sshd</code> and other services are registered
through <code>systemd</code>. We’re going to go old school in this post
for fun.</p>
<p>A daemon shouldn’t be reachable from the outside world, and it should
do a task on some activity or change. You can run one or as many of them
as you want to – maybe you want just one like a singleton, or many
splitting up a task, or you can emulate a single writer many readers
pattern.</p>
<p>Regardless, here’s the checklist of “how to daemon”</p>
<ol type="1">
<li>Fork + exit from the parent.</li>
<li><code>setsid()</code> after the first fork to get a new progress
group id.</li>
<li>disable <code>SIGHUP</code> to prevent the terminal from killing the
daemon.</li>
<li>Fork again to make sure the daemon process cannot get a
terminal.</li>
<li><code>umask(027)</code> to set permissions for files it owns</li>
<li><code>chdir()</code> to the directory you want</li>
<li>Close all FDs that aren’t 0/1/2, and redirect 0/1/2 to log
files.</li>
<li>Get the <code>pidfile</code>, write your pid, keep the file open
while alive.</li>
<li>Install signal handling, <code>SIGTERM</code>, <code>SIGINT</code>
for shutdown, <code>SIGHUP</code> for reloading.</li>
<li>Open any files required for the task.</li>
<li>Do the task.</li>
<li>Install code on exit, to close resources used + unlink the
pidfile.</li>
</ol>
<p>That’s a lot of work. Luckily, the <code>bsd</code> folks have us
(the linux folks) covered. They have <code>libdaemon</code>, which has a
set of helpers to write daemons. If you choose a higher level language
like Rust or Python, setting up a daemon is 15 lines of code.</p>
<p>In C, the setup code is closer to 40 lines, but it’s not that bad
regardless with <code>libdaemon</code> – it sets up steps 1 to 7 for us.
That leaves just a few steps. We set the path for the pidfile, and
register it with <code>daemon_pid_file_proc</code> for it to be set up
in the <code>daemon_pid_file_create</code> call later, returning if we
couldn’t create it.</p>
<p>Next, there’s signal handlers installed for <code>SIGTERM</code> and
<code>SIGINT</code>, and then we do our main loop.</p>
<p>Finally, we’ll do our work, which in this case, reads the
request_path, checks how many bytes it has, and then every 5 seconds,
logs that to another file.</p>
<p>Pretty simple, but does the trick in showcasing how a daemon
works.</p>
<p>First, we have our includes.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;errno.h&gt;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;fcntl.h&gt;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;libdaemon/daemon.h&gt;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;libdaemon/dpid.h&gt;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;signal.h&gt;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;string.h&gt;</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;sys/stat.h&gt;</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;time.h&gt;</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;unistd.h&gt;</span></span></code></pre></div>
<p>Next, our actual work, which will print to the fd we provide.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span> log_file_size<span class="op">(</span><span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>request_path<span class="op">,</span> <span class="dt">int</span> result_fd<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> stat st<span class="op">;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>stat<span class="op">(</span>request_path<span class="op">,</span> <span class="op">&amp;</span>st<span class="op">)</span> <span class="op">&lt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>errno <span class="op">==</span> ENOENT<span class="op">)</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>      dprintf<span class="op">(</span>result_fd<span class="op">,</span> <span class="st">&quot;# </span><span class="sc">%s</span><span class="st"> missing</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> request_path<span class="op">);</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">else</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>      dprintf<span class="op">(</span>result_fd<span class="op">,</span> <span class="st">&quot;# error reading </span><span class="sc">%s</span><span class="st">: </span><span class="sc">%s\n</span><span class="st">&quot;</span><span class="op">,</span> request_path<span class="op">,</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>              strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span><span class="op">;</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>  dprintf<span class="op">(</span>result_fd<span class="op">,</span> <span class="st">&quot;# </span><span class="sc">%s</span><span class="st"> has </span><span class="sc">%ld</span><span class="st"> bytes</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> request_path<span class="op">,</span> st<span class="op">.</span>st_size<span class="op">);</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Next, setting up the variables we need for
<code>libdaemon</code>.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">volatile</span> <span class="dt">sig_atomic_t</span> stop_flag <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span> on_stop<span class="op">(</span><span class="dt">int</span> _sig<span class="op">)</span> <span class="op">{</span> stop_flag <span class="op">=</span> <span class="dv">1</span><span class="op">;</span> <span class="op">}</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>pidfile_path <span class="op">=</span> <span class="st">&quot;/tmp/byte_count_daemon.pid&quot;</span><span class="op">;</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>request_path <span class="op">=</span> <span class="st">&quot;/tmp/byte_count_requests.txt&quot;</span><span class="op">;</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>result_path <span class="op">=</span> <span class="st">&quot;/tmp/byte_count_results.txt&quot;</span><span class="op">;</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>pidfile_proc<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> pidfile_path<span class="op">;</span> <span class="op">}</span></span></code></pre></div>
<p>And then the main function:</p>
<ol type="1">
<li>You can pass it a <code>-f</code> flag as the first argument, if you
want to run in the foreground for testing.</li>
<li>Next, the daemon identifier comes from the name of the binary, and
then the pidfile path is set afterwards.</li>
<li>The daemon call is made only if it’s not foregrounded – so we can
kill the process.</li>
<li>Signal handlers are registered.</li>
<li>Pidfile is created – if it can’t be exclusively owned, return
here.</li>
<li>Open up an fd we need exclusively to write our results to. If we
can’t, we return.</li>
<li>The main loop, along with sleeping for 5 seconds between tasks.</li>
<li>Stopping and cleaning up.</li>
</ol>
<div class="sourceCode" id="cb4"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">*</span>argv<span class="op">[])</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">// 1.</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> foreground <span class="op">=</span> <span class="op">(</span>argc <span class="op">&gt;</span> <span class="dv">1</span> <span class="op">&amp;&amp;</span> strcmp<span class="op">(</span>argv<span class="op">[</span><span class="dv">1</span><span class="op">],</span> <span class="st">&quot;-f&quot;</span><span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// 2.</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>  daemon_pid_file_ident <span class="op">=</span> daemon_ident_from_argv0<span class="op">(</span>argv<span class="op">[</span><span class="dv">0</span><span class="op">]);</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>  daemon_pid_file_proc <span class="op">=</span> pidfile_proc<span class="op">;</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">// 3.</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(!</span>foreground<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>daemon<span class="op">(</span><span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">)</span> <span class="op">&lt;</span> <span class="dv">0</span><span class="op">)</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>  <span class="co">// 4.</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> sigaction sa <span class="op">=</span> <span class="op">{</span><span class="dv">0</span><span class="op">};</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>  sa<span class="op">.</span>sa_handler <span class="op">=</span> on_stop<span class="op">;</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>  sigaction<span class="op">(</span>SIGINT<span class="op">,</span> <span class="op">&amp;</span>sa<span class="op">,</span> NULL<span class="op">);</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>  sigaction<span class="op">(</span>SIGTERM<span class="op">,</span> <span class="op">&amp;</span>sa<span class="op">,</span> NULL<span class="op">);</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a>  <span class="co">// 5.</span></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>daemon_pid_file_create<span class="op">()</span> <span class="op">&lt;</span> <span class="dv">0</span><span class="op">)</span></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true" tabindex="-1"></a>  <span class="co">// 6.</span></span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> results_fd <span class="op">=</span> open<span class="op">(</span>result_path<span class="op">,</span> O_WRONLY <span class="op">|</span> O_CREAT <span class="op">|</span> O_APPEND<span class="op">,</span> <span class="bn">0644</span><span class="op">);</span></span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>results_fd <span class="op">&lt;</span> <span class="dv">0</span><span class="op">)</span></span>
<span id="cb4-28"><a href="#cb4-28" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb4-29"><a href="#cb4-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-30"><a href="#cb4-30" aria-hidden="true" tabindex="-1"></a>  <span class="co">// 7.</span></span>
<span id="cb4-31"><a href="#cb4-31" aria-hidden="true" tabindex="-1"></a>  dprintf<span class="op">(</span>results_fd<span class="op">,</span> <span class="st">&quot;# byte count request daemon started pid=</span><span class="sc">%d\n</span><span class="st">&quot;</span><span class="op">,</span> getpid<span class="op">());</span></span>
<span id="cb4-32"><a href="#cb4-32" aria-hidden="true" tabindex="-1"></a>  <span class="cf">while</span> <span class="op">(!</span>stop_flag<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-33"><a href="#cb4-33" aria-hidden="true" tabindex="-1"></a>    log_file_size<span class="op">(</span>request_path<span class="op">,</span> results_fd<span class="op">);</span></span>
<span id="cb4-34"><a href="#cb4-34" aria-hidden="true" tabindex="-1"></a>    nanosleep<span class="op">(&amp;(</span><span class="kw">struct</span> timespec<span class="op">){</span><span class="dv">5</span><span class="op">,</span> <span class="dv">0</span><span class="op">},</span> NULL<span class="op">);</span> </span>
<span id="cb4-35"><a href="#cb4-35" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb4-36"><a href="#cb4-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-37"><a href="#cb4-37" aria-hidden="true" tabindex="-1"></a>  <span class="co">// 8.</span></span>
<span id="cb4-38"><a href="#cb4-38" aria-hidden="true" tabindex="-1"></a>  dprintf<span class="op">(</span>results_fd<span class="op">,</span> <span class="st">&quot;# stopping</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">);</span></span>
<span id="cb4-39"><a href="#cb4-39" aria-hidden="true" tabindex="-1"></a>  daemon_pid_file_remove<span class="op">();</span></span>
<span id="cb4-40"><a href="#cb4-40" aria-hidden="true" tabindex="-1"></a>  close<span class="op">(</span>results_fd<span class="op">);</span></span>
<span id="cb4-41"><a href="#cb4-41" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb4-42"><a href="#cb4-42" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Compile the daemon with <code>cc daemon.c -o daemon -ldaemon</code>,
and run it in the foreground with <code>daemon -f</code>.</p>
<p>Once you start the daemon, you can write and save into
<code>/tmp/byte_count_requests.txt</code> and then
<code>tail -f /tmp/byte_count_results.txt</code> to see what the daemon
is doing.</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode txt"><code class="sourceCode default"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a># byte count request daemon started pid=438577</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a># /tmp/byte_count_requests.txt missing</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a># /tmp/byte_count_requests.txt missing</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a># /tmp/byte_count_requests.txt has 11 bytes</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a># /tmp/byte_count_requests.txt has 25 bytes</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a># /tmp/byte_count_requests.txt has 25 bytes</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a># /tmp/byte_count_requests.txt has 25 bytes</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a># /tmp/byte_count_requests.txt has 25 bytes</span></code></pre></div>
<p>A crash course on daemons in a handful of lines!</p>]]></description>
</item>
<item>
<title>Writing a Container</title>
<pubDate>Wed, 12 Nov 2025 20:55:26 +0000</pubDate>
<guid>https://blog/writing-a-container.html</guid>
<description><![CDATA[<p>I use containers on the job daily, but to be
honest, don’t have much idea other than they’re vaguely
<code>chroot()</code> + <code>cgroupsv2</code> + <code>seccomp</code>.
So, to rectify that, let’s build our own containers.</p>
<h2 id="dependencies">Dependencies</h2>
<p>First off, some dependencies. Since we want to run binaries inside of
our chroot, and our chroot is going to be far away from root, we have
two options:</p>
<ol type="1">
<li>compile with vanilla <code>gcc</code> and then copy our shared
libraries to our chroot.</li>
<li>Statically compile our dependencies.</li>
</ol>
<p>I went with 2. But that leaves the compiler itself. Luckily, there’s
a project called <a
href="https://crosstool-ng.github.io/">crosstool-NG</a> that allows you
to generate cross-compilers pretty easily. My target is
<code>x86_64-unknown-linux-gnu</code>, so I just needed a build of
<code>x86_64-unknown-linux-musl</code>. After adding the compiler to
your <code>$PATH</code>, you’re also ready to statically compile some
code.</p>
<h2 id="a-shell">A Shell</h2>
<p>To get interactivity in our <code>chroot</code>, we’ll need a shell.
I chose <code>dash</code> because it’s easier to compile. Clone it, and
let’s compile it with our cross compiler.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> clone https://git.kernel.org/pub/scm/utils/dash/dash.git/ <span class="at">--depth</span><span class="op">=</span>1</span></code></pre></div>
<p>In bash or zsh, set your compiler, and build. Dash will be built in
<code>src/dash</code>. Copy it for later.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="bu">cd</span> dash</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">PATH</span><span class="op">=</span><span class="st">&quot;</span><span class="va">$HOME</span><span class="st">/x-tools/x86_64-unknown-linux-musl/bin:</span><span class="va">$PATH</span><span class="st">&quot;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">CC</span><span class="op">=</span><span class="st">&quot;x86_64-unknown-linux-musl-gcc&quot;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">LD</span><span class="op">=</span><span class="st">&quot;x86_64-unknown-linux-musl-ld&quot;</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">CFLAGS</span><span class="op">=</span><span class="st">&quot;-Os&quot;</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">LDFLAGS</span><span class="op">=</span><span class="st">&quot;--static&quot;</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span></span></code></pre></div>
<h2 id="a-userspace">A Userspace</h2>
<p>For a userspace, I decided to use toybox.</p>
<p>Same drill, compile it statically.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> clone https://github.com/landley/toybox.git <span class="at">--depth</span><span class="op">=</span>1</span></code></pre></div>
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="bu">cd</span> toybox</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">PATH</span><span class="op">=</span><span class="st">&quot;</span><span class="va">$HOME</span><span class="st">/x-tools/x86_64-unknown-linux-musl/bin:</span><span class="va">$PATH</span><span class="st">&quot;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">CROSS_COMPILE</span><span class="op">=</span>x86_64-unknown-linux-musl- </span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">LDFLAGS</span><span class="op">=</span><span class="st">&quot;--static&quot;</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> distclean</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> defconfig</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> toybox CROSS_COMPILE=<span class="va">$CROSS_COMPILE</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span></span></code></pre></div>
<p><code>toybox</code> will be in the root directory. Keep it for
later.</p>
<h2 id="an-operating-system">An operating system?</h2>
<p>Now we’ll need the directory structure of an operating system.
Luckily, toybox also has us covered. There’s a script called
<code>mkroot/mkroot.sh</code> which when run, will create our root
filesystem.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> mkroot/mkroot.sh</span></code></pre></div>
<p>Run it, and copy the <code>root</code> dir to where you want your OS
to be. Now, copy over <code>dash</code> and <code>toybox</code> into
<code>root/bin</code>, and you have a userspace and a shell. What more
could you want?</p>
<h2 id="chrooting-to-our-os">Chrooting to our OS</h2>
<p>If you <code>cd</code> into <code>root</code> and then run
<code>bin/toybox ls</code>, you actually have an OS inside your OS. Of
course, it’s pretty useless since you can <code>cd</code> out. This is
basically what <code>chroot</code> does for us – it puts the root dir
wherever you specify, and that’s it.</p>
<p>With that out of the way, let’s write a program that uses
<code>chroot</code>.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#define </span><span class="ot">_GNU_SOURCE</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;errno.h&gt;</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdarg.h&gt;</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdbool.h&gt;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdlib.h&gt;</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;string.h&gt;</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;unistd.h&gt;</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a><span class="co">/*</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a><span class="co"> * Stage 0: Minimal chroot launcher.</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a><span class="co"> *</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a><span class="co"> * This version demonstrates the tiniest &quot;container&quot;: it simply chroots into a</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a><span class="co"> * user-specified directory and execs a command. You must run it as root and</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a><span class="co"> * it is trivial to escape by pointing -r at &quot;/&quot; or any other host path</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a><span class="co">   and escaping.</span></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a><span class="co"> */</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span> die<span class="op">(</span><span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>fmt<span class="op">,</span> <span class="op">...)</span> <span class="op">{</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a>  <span class="dt">va_list</span> ap<span class="op">;</span></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a>  va_start<span class="op">(</span>ap<span class="op">,</span> fmt<span class="op">);</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a>  vfprintf<span class="op">(</span>stderr<span class="op">,</span> fmt<span class="op">,</span> ap<span class="op">);</span></span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a>  va_end<span class="op">(</span>ap<span class="op">);</span></span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(!*</span>fmt <span class="op">||</span> fmt<span class="op">[</span>strlen<span class="op">(</span>fmt<span class="op">)</span> <span class="op">-</span> <span class="dv">1</span><span class="op">]</span> <span class="op">!=</span> <span class="ch">&#39;</span><span class="sc">\n</span><span class="ch">&#39;</span><span class="op">)</span></span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true" tabindex="-1"></a>    fputc<span class="op">(</span><span class="ch">&#39;</span><span class="sc">\n</span><span class="ch">&#39;</span><span class="op">,</span> stderr<span class="op">);</span></span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true" tabindex="-1"></a>  exit<span class="op">(</span>EXIT_FAILURE<span class="op">);</span></span>
<span id="cb6-27"><a href="#cb6-27" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb6-28"><a href="#cb6-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-29"><a href="#cb6-29" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span> usage<span class="op">(</span><span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>prog<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-30"><a href="#cb6-30" aria-hidden="true" tabindex="-1"></a>  fprintf<span class="op">(</span>stderr<span class="op">,</span> <span class="st">&quot;Usage: </span><span class="sc">%s</span><span class="st"> -r &lt;rootfs&gt; -- &lt;cmd&gt; [args...]</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> prog<span class="op">);</span></span>
<span id="cb6-31"><a href="#cb6-31" aria-hidden="true" tabindex="-1"></a>  exit<span class="op">(</span><span class="dv">2</span><span class="op">);</span></span>
<span id="cb6-32"><a href="#cb6-32" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb6-33"><a href="#cb6-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-34"><a href="#cb6-34" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-35"><a href="#cb6-35" aria-hidden="true" tabindex="-1"></a>  <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>root <span class="op">=</span> NULL<span class="op">;</span></span>
<span id="cb6-36"><a href="#cb6-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-37"><a href="#cb6-37" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* Parse: expect -r &lt;root&gt; followed by -- and the command */</span></span>
<span id="cb6-38"><a href="#cb6-38" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">1</span><span class="op">;</span> i <span class="op">&lt;</span> argc<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb6-39"><a href="#cb6-39" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(!</span>strcmp<span class="op">(</span>argv<span class="op">[</span>i<span class="op">],</span> <span class="st">&quot;-r&quot;</span><span class="op">)</span> <span class="op">&amp;&amp;</span> i <span class="op">+</span> <span class="dv">1</span> <span class="op">&lt;</span> argc<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-40"><a href="#cb6-40" aria-hidden="true" tabindex="-1"></a>      root <span class="op">=</span> argv<span class="op">[++</span>i<span class="op">];</span></span>
<span id="cb6-41"><a href="#cb6-41" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(!</span>strcmp<span class="op">(</span>argv<span class="op">[</span>i<span class="op">],</span> <span class="st">&quot;--&quot;</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb6-42"><a href="#cb6-42" aria-hidden="true" tabindex="-1"></a>      argv <span class="op">+=</span> i <span class="op">+</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb6-43"><a href="#cb6-43" aria-hidden="true" tabindex="-1"></a>      argc <span class="op">-=</span> i <span class="op">+</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb6-44"><a href="#cb6-44" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
<span id="cb6-45"><a href="#cb6-45" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>argv<span class="op">[</span>i<span class="op">][</span><span class="dv">0</span><span class="op">]</span> <span class="op">==</span> <span class="ch">&#39;-&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-46"><a href="#cb6-46" aria-hidden="true" tabindex="-1"></a>      usage<span class="op">(</span>argv<span class="op">[</span><span class="dv">0</span><span class="op">]);</span></span>
<span id="cb6-47"><a href="#cb6-47" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb6-48"><a href="#cb6-48" aria-hidden="true" tabindex="-1"></a>      argv <span class="op">+=</span> i<span class="op">;</span></span>
<span id="cb6-49"><a href="#cb6-49" aria-hidden="true" tabindex="-1"></a>      argc <span class="op">-=</span> i<span class="op">;</span></span>
<span id="cb6-50"><a href="#cb6-50" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
<span id="cb6-51"><a href="#cb6-51" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-52"><a href="#cb6-52" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb6-53"><a href="#cb6-53" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(!</span>root <span class="op">||</span> argc <span class="op">&lt;</span> <span class="dv">1</span><span class="op">)</span></span>
<span id="cb6-54"><a href="#cb6-54" aria-hidden="true" tabindex="-1"></a>    usage<span class="op">(</span>argv<span class="op">[</span><span class="dv">0</span><span class="op">]);</span></span>
<span id="cb6-55"><a href="#cb6-55" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-56"><a href="#cb6-56" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>chroot<span class="op">(</span>root<span class="op">)</span> <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb6-57"><a href="#cb6-57" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;chroot(</span><span class="sc">%s</span><span class="st">): </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> root<span class="op">,</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb6-58"><a href="#cb6-58" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>chdir<span class="op">(</span><span class="st">&quot;/&quot;</span><span class="op">)</span> <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb6-59"><a href="#cb6-59" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;chdir(/): </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb6-60"><a href="#cb6-60" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-61"><a href="#cb6-61" aria-hidden="true" tabindex="-1"></a>  execvp<span class="op">(</span>argv<span class="op">[</span><span class="dv">0</span><span class="op">],</span> argv<span class="op">);</span></span>
<span id="cb6-62"><a href="#cb6-62" aria-hidden="true" tabindex="-1"></a>  die<span class="op">(</span><span class="st">&quot;execvp(&#39;</span><span class="sc">%s</span><span class="st">&#39;) failed: </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> argv<span class="op">[</span><span class="dv">0</span><span class="op">],</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb6-63"><a href="#cb6-63" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Compile this and we have to run it as root. Point it to our little
filesystem and we can drop into the shell.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="fu">gcc</span> container.c <span class="at">-o</span> container <span class="at">-lseccomp</span></span></code></pre></div>
<p>Note that we have to use <code>sudo</code> here otherwise we can’t
get into the <code>chroot</code>.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="fu">sudo</span> ./container <span class="at">-r</span> ./root <span class="at">--</span> /bin/dash</span></code></pre></div>
<p>We’re actually not able to do too much to just leave:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="co"># pwd</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="ex">/</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="co"># cd /root/takashi</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="ex">/bin/dash:</span> 5: cd: can<span class="st">&#39;t cd to /root/takashi</span></span></code></pre></div>
<p>But remember, we’re root. We can escape using proc.</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="co"># toybox mkdir /proc</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="co"># toybox mount -t proc proc /proc</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="co"># toybox chroot /proc/1/root /bin/sh</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> whoami</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="ex">root</span></span></code></pre></div>
<p>And you’re in a root shell as root. Freedom, so very easily.</p>
<h2 id="some-more-security">Some more security</h2>
<p>We’ll want to prevent running as root. And also escaping so easily.
This time around, we’ll make the container runnable without root, mount
<code>/proc</code> privately, clean up the environment, and change our
user to nobody. We can still run any syscall we want though.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span> make_private_mounts<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>mount<span class="op">(</span>NULL<span class="op">,</span> <span class="st">&quot;/&quot;</span><span class="op">,</span> NULL<span class="op">,</span> MS_REC <span class="op">|</span> MS_PRIVATE<span class="op">,</span> NULL<span class="op">)</span> <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;mount(/, MS_PRIVATE): </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span> bind_mount_self<span class="op">(</span><span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>path<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>mount<span class="op">(</span>path<span class="op">,</span> path<span class="op">,</span> NULL<span class="op">,</span> MS_BIND <span class="op">|</span> MS_REC<span class="op">,</span> NULL<span class="op">)</span> <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;bind-mount </span><span class="sc">%s</span><span class="st">: </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> path<span class="op">,</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span> close_all_fds_except012<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> dir <span class="op">=</span> open<span class="op">(</span><span class="st">&quot;/proc/self/fd&quot;</span><span class="op">,</span> O_RDONLY <span class="op">|</span> O_DIRECTORY <span class="op">|</span> O_CLOEXEC<span class="op">);</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>dir <span class="op">&lt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> fd <span class="op">=</span> <span class="dv">3</span><span class="op">;</span> fd <span class="op">&lt;</span> <span class="dv">1024</span><span class="op">;</span> <span class="op">++</span>fd<span class="op">)</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a>      close<span class="op">(</span>fd<span class="op">);</span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span><span class="op">;</span></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a>  <span class="dt">char</span> name<span class="op">[</span>PATH_MAX<span class="op">];</span></span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(;;)</span> <span class="op">{</span></span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true" tabindex="-1"></a>    <span class="dt">ssize_t</span> n <span class="op">=</span> syscall<span class="op">(</span>SYS_getdents64<span class="op">,</span> dir<span class="op">,</span> name<span class="op">,</span> <span class="kw">sizeof</span><span class="op">(</span>name<span class="op">));</span></span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>n <span class="op">&lt;=</span> <span class="dv">0</span><span class="op">)</span></span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">ssize_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> n<span class="op">;)</span> <span class="op">{</span></span>
<span id="cb11-24"><a href="#cb11-24" aria-hidden="true" tabindex="-1"></a>      <span class="kw">struct</span> linux_dirent64 <span class="op">{</span></span>
<span id="cb11-25"><a href="#cb11-25" aria-hidden="true" tabindex="-1"></a>        ino64_t d_ino<span class="op">;</span></span>
<span id="cb11-26"><a href="#cb11-26" aria-hidden="true" tabindex="-1"></a>        off64_t d_off<span class="op">;</span></span>
<span id="cb11-27"><a href="#cb11-27" aria-hidden="true" tabindex="-1"></a>        <span class="dt">unsigned</span> <span class="dt">short</span> d_reclen<span class="op">;</span></span>
<span id="cb11-28"><a href="#cb11-28" aria-hidden="true" tabindex="-1"></a>        <span class="dt">unsigned</span> <span class="dt">char</span> d_type<span class="op">;</span></span>
<span id="cb11-29"><a href="#cb11-29" aria-hidden="true" tabindex="-1"></a>        <span class="dt">char</span> d_name<span class="op">[];</span></span>
<span id="cb11-30"><a href="#cb11-30" aria-hidden="true" tabindex="-1"></a>      <span class="op">};</span></span>
<span id="cb11-31"><a href="#cb11-31" aria-hidden="true" tabindex="-1"></a>      <span class="kw">struct</span> linux_dirent64 <span class="op">*</span>d <span class="op">=</span> <span class="op">(</span><span class="kw">struct</span> linux_dirent64 <span class="op">*)(</span>name <span class="op">+</span> i<span class="op">);</span></span>
<span id="cb11-32"><a href="#cb11-32" aria-hidden="true" tabindex="-1"></a>      i <span class="op">+=</span> d<span class="op">-&gt;</span>d_reclen<span class="op">;</span></span>
<span id="cb11-33"><a href="#cb11-33" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(!</span>strcmp<span class="op">(</span>d<span class="op">-&gt;</span>d_name<span class="op">,</span> <span class="st">&quot;.&quot;</span><span class="op">)</span> <span class="op">||</span> <span class="op">!</span>strcmp<span class="op">(</span>d<span class="op">-&gt;</span>d_name<span class="op">,</span> <span class="st">&quot;..&quot;</span><span class="op">))</span></span>
<span id="cb11-34"><a href="#cb11-34" aria-hidden="true" tabindex="-1"></a>        <span class="cf">continue</span><span class="op">;</span></span>
<span id="cb11-35"><a href="#cb11-35" aria-hidden="true" tabindex="-1"></a>      <span class="dt">int</span> fd <span class="op">=</span> atoi<span class="op">(</span>d<span class="op">-&gt;</span>d_name<span class="op">);</span></span>
<span id="cb11-36"><a href="#cb11-36" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>fd <span class="op">&gt;</span> <span class="dv">2</span> <span class="op">&amp;&amp;</span> fd <span class="op">!=</span> dir<span class="op">)</span></span>
<span id="cb11-37"><a href="#cb11-37" aria-hidden="true" tabindex="-1"></a>        close<span class="op">(</span>fd<span class="op">);</span></span>
<span id="cb11-38"><a href="#cb11-38" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-39"><a href="#cb11-39" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb11-40"><a href="#cb11-40" aria-hidden="true" tabindex="-1"></a>  close<span class="op">(</span>dir<span class="op">);</span></span>
<span id="cb11-41"><a href="#cb11-41" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb11-42"><a href="#cb11-42" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-43"><a href="#cb11-43" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span> drop_privileges<span class="op">(</span>uid_t uid<span class="op">,</span> gid_t gid<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-44"><a href="#cb11-44" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>setgroups<span class="op">(</span><span class="dv">0</span><span class="op">,</span> NULL<span class="op">)</span> <span class="op">==</span> <span class="op">-</span><span class="dv">1</span> <span class="op">&amp;&amp;</span> errno <span class="op">!=</span> EPERM<span class="op">)</span></span>
<span id="cb11-45"><a href="#cb11-45" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;setgroups: </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb11-46"><a href="#cb11-46" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>setgid<span class="op">(</span>gid<span class="op">)</span> <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb11-47"><a href="#cb11-47" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;setgid: </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb11-48"><a href="#cb11-48" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>setuid<span class="op">(</span>uid<span class="op">)</span> <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb11-49"><a href="#cb11-49" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;setuid: </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb11-50"><a href="#cb11-50" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb11-51"><a href="#cb11-51" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-52"><a href="#cb11-52" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span> write_file_fmt<span class="op">(</span><span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>path<span class="op">,</span> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>fmt<span class="op">,</span> <span class="op">...)</span> <span class="op">{</span></span>
<span id="cb11-53"><a href="#cb11-53" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> fd <span class="op">=</span> open<span class="op">(</span>path<span class="op">,</span> O_WRONLY<span class="op">);</span></span>
<span id="cb11-54"><a href="#cb11-54" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>fd <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb11-55"><a href="#cb11-55" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;open(</span><span class="sc">%s</span><span class="st">): </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> path<span class="op">,</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb11-56"><a href="#cb11-56" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-57"><a href="#cb11-57" aria-hidden="true" tabindex="-1"></a>  <span class="dt">char</span> buf<span class="op">[</span><span class="dv">256</span><span class="op">];</span></span>
<span id="cb11-58"><a href="#cb11-58" aria-hidden="true" tabindex="-1"></a>  <span class="dt">va_list</span> ap<span class="op">;</span></span>
<span id="cb11-59"><a href="#cb11-59" aria-hidden="true" tabindex="-1"></a>  va_start<span class="op">(</span>ap<span class="op">,</span> fmt<span class="op">);</span></span>
<span id="cb11-60"><a href="#cb11-60" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> len <span class="op">=</span> vsnprintf<span class="op">(</span>buf<span class="op">,</span> <span class="kw">sizeof</span><span class="op">(</span>buf<span class="op">),</span> fmt<span class="op">,</span> ap<span class="op">);</span></span>
<span id="cb11-61"><a href="#cb11-61" aria-hidden="true" tabindex="-1"></a>  va_end<span class="op">(</span>ap<span class="op">);</span></span>
<span id="cb11-62"><a href="#cb11-62" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>len <span class="op">&lt;</span> <span class="dv">0</span> <span class="op">||</span> <span class="op">(</span><span class="dt">size_t</span><span class="op">)</span>len <span class="op">&gt;=</span> <span class="kw">sizeof</span><span class="op">(</span>buf<span class="op">))</span></span>
<span id="cb11-63"><a href="#cb11-63" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;formatting </span><span class="sc">%s</span><span class="st"> failed&quot;</span><span class="op">,</span> path<span class="op">);</span></span>
<span id="cb11-64"><a href="#cb11-64" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>write<span class="op">(</span>fd<span class="op">,</span> buf<span class="op">,</span> len<span class="op">)</span> <span class="op">!=</span> len<span class="op">)</span></span>
<span id="cb11-65"><a href="#cb11-65" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;write(</span><span class="sc">%s</span><span class="st">): </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> path<span class="op">,</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb11-66"><a href="#cb11-66" aria-hidden="true" tabindex="-1"></a>  close<span class="op">(</span>fd<span class="op">);</span></span>
<span id="cb11-67"><a href="#cb11-67" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb11-68"><a href="#cb11-68" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-69"><a href="#cb11-69" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span> setup_user_namespace<span class="op">(</span>uid_t host_uid<span class="op">,</span> gid_t host_gid<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-70"><a href="#cb11-70" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>unshare<span class="op">(</span>CLONE_NEWUSER<span class="op">)</span> <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb11-71"><a href="#cb11-71" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;unshare(CLONE_NEWUSER): </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb11-72"><a href="#cb11-72" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-73"><a href="#cb11-73" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>access<span class="op">(</span><span class="st">&quot;/proc/self/setgroups&quot;</span><span class="op">,</span> F_OK<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span>
<span id="cb11-74"><a href="#cb11-74" aria-hidden="true" tabindex="-1"></a>    write_file_fmt<span class="op">(</span><span class="st">&quot;/proc/self/setgroups&quot;</span><span class="op">,</span> <span class="st">&quot;deny</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">);</span></span>
<span id="cb11-75"><a href="#cb11-75" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-76"><a href="#cb11-76" aria-hidden="true" tabindex="-1"></a>  write_file_fmt<span class="op">(</span><span class="st">&quot;/proc/self/uid_map&quot;</span><span class="op">,</span> <span class="st">&quot;0 </span><span class="sc">%u</span><span class="st"> 1</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> host_uid<span class="op">);</span></span>
<span id="cb11-77"><a href="#cb11-77" aria-hidden="true" tabindex="-1"></a>  write_file_fmt<span class="op">(</span><span class="st">&quot;/proc/self/gid_map&quot;</span><span class="op">,</span> <span class="st">&quot;0 </span><span class="sc">%u</span><span class="st"> 1</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> host_gid<span class="op">);</span></span>
<span id="cb11-78"><a href="#cb11-78" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And the changes to main:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>root <span class="op">=</span> NULL<span class="op">;</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>  uid_t host_uid <span class="op">=</span> geteuid<span class="op">();</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>  gid_t host_gid <span class="op">=</span> getegid<span class="op">();</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> rootless <span class="op">=</span> <span class="op">(</span>host_uid <span class="op">!=</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>  uid_t uid <span class="op">=</span> rootless <span class="op">?</span> <span class="dv">0</span> <span class="op">:</span> <span class="dv">65534</span><span class="op">;</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>  gid_t gid <span class="op">=</span> rootless <span class="op">?</span> <span class="dv">0</span> <span class="op">:</span> <span class="dv">65534</span><span class="op">;</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">1</span><span class="op">;</span> i <span class="op">&lt;</span> argc<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(!</span>strcmp<span class="op">(</span>argv<span class="op">[</span>i<span class="op">],</span> <span class="st">&quot;-r&quot;</span><span class="op">)</span> <span class="op">&amp;&amp;</span> i <span class="op">+</span> <span class="dv">1</span> <span class="op">&lt;</span> argc<span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>      root <span class="op">=</span> argv<span class="op">[++</span>i<span class="op">];</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(!</span>strcmp<span class="op">(</span>argv<span class="op">[</span>i<span class="op">],</span> <span class="st">&quot;-u&quot;</span><span class="op">)</span> <span class="op">&amp;&amp;</span> i <span class="op">+</span> <span class="dv">1</span> <span class="op">&lt;</span> argc<span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a>      uid <span class="op">=</span> <span class="op">(</span>uid_t<span class="op">)</span>strtoul<span class="op">(</span>argv<span class="op">[++</span>i<span class="op">],</span> NULL<span class="op">,</span> <span class="dv">10</span><span class="op">);</span></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(!</span>strcmp<span class="op">(</span>argv<span class="op">[</span>i<span class="op">],</span> <span class="st">&quot;-g&quot;</span><span class="op">)</span> <span class="op">&amp;&amp;</span> i <span class="op">+</span> <span class="dv">1</span> <span class="op">&lt;</span> argc<span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a>      gid <span class="op">=</span> <span class="op">(</span>gid_t<span class="op">)</span>strtoul<span class="op">(</span>argv<span class="op">[++</span>i<span class="op">],</span> NULL<span class="op">,</span> <span class="dv">10</span><span class="op">);</span></span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(!</span>strcmp<span class="op">(</span>argv<span class="op">[</span>i<span class="op">],</span> <span class="st">&quot;--&quot;</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a>      argv <span class="op">+=</span> i <span class="op">+</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a>      argc <span class="op">-=</span> i <span class="op">+</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>argv<span class="op">[</span>i<span class="op">][</span><span class="dv">0</span><span class="op">]</span> <span class="op">==</span> <span class="ch">&#39;-&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true" tabindex="-1"></a>      usage<span class="op">(</span>argv<span class="op">[</span><span class="dv">0</span><span class="op">]);</span></span>
<span id="cb12-22"><a href="#cb12-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb12-23"><a href="#cb12-23" aria-hidden="true" tabindex="-1"></a>      argv <span class="op">+=</span> i<span class="op">;</span></span>
<span id="cb12-24"><a href="#cb12-24" aria-hidden="true" tabindex="-1"></a>      argc <span class="op">-=</span> i<span class="op">;</span></span>
<span id="cb12-25"><a href="#cb12-25" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
<span id="cb12-26"><a href="#cb12-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb12-27"><a href="#cb12-27" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb12-28"><a href="#cb12-28" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(!</span>root <span class="op">||</span> argc <span class="op">&lt;</span> <span class="dv">1</span><span class="op">)</span></span>
<span id="cb12-29"><a href="#cb12-29" aria-hidden="true" tabindex="-1"></a>    usage<span class="op">(</span>argv<span class="op">[</span><span class="dv">0</span><span class="op">]);</span></span>
<span id="cb12-30"><a href="#cb12-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-31"><a href="#cb12-31" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>rootless <span class="op">&amp;&amp;</span> <span class="op">(</span>uid <span class="op">!=</span> <span class="dv">0</span> <span class="op">||</span> gid <span class="op">!=</span> <span class="dv">0</span><span class="op">))</span></span>
<span id="cb12-32"><a href="#cb12-32" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;non-root users must use -u/-g 0 in this stage&quot;</span><span class="op">);</span></span>
<span id="cb12-33"><a href="#cb12-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-34"><a href="#cb12-34" aria-hidden="true" tabindex="-1"></a>  setup_user_namespace<span class="op">(</span>host_uid<span class="op">,</span> host_gid<span class="op">);</span></span>
<span id="cb12-35"><a href="#cb12-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-36"><a href="#cb12-36" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>unshare<span class="op">(</span>CLONE_NEWNS<span class="op">)</span> <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb12-37"><a href="#cb12-37" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;unshare(CLONE_NEWNS): </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb12-38"><a href="#cb12-38" aria-hidden="true" tabindex="-1"></a>  make_private_mounts<span class="op">();</span></span>
<span id="cb12-39"><a href="#cb12-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-40"><a href="#cb12-40" aria-hidden="true" tabindex="-1"></a>  bind_mount_self<span class="op">(</span>root<span class="op">);</span></span>
<span id="cb12-41"><a href="#cb12-41" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>chroot<span class="op">(</span>root<span class="op">)</span> <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb12-42"><a href="#cb12-42" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;chroot(</span><span class="sc">%s</span><span class="st">): </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> root<span class="op">,</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb12-43"><a href="#cb12-43" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>chdir<span class="op">(</span><span class="st">&quot;/&quot;</span><span class="op">)</span> <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb12-44"><a href="#cb12-44" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;chdir(/): </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb12-45"><a href="#cb12-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-46"><a href="#cb12-46" aria-hidden="true" tabindex="-1"></a>  mkdir<span class="op">(</span><span class="st">&quot;/proc&quot;</span><span class="op">,</span> <span class="bn">0555</span><span class="op">);</span></span>
<span id="cb12-47"><a href="#cb12-47" aria-hidden="true" tabindex="-1"></a>  mount<span class="op">(</span><span class="st">&quot;proc&quot;</span><span class="op">,</span> <span class="st">&quot;/proc&quot;</span><span class="op">,</span> <span class="st">&quot;proc&quot;</span><span class="op">,</span> MS_NOSUID <span class="op">|</span> MS_NODEV <span class="op">|</span> MS_NOEXEC<span class="op">,</span> NULL<span class="op">);</span></span>
<span id="cb12-48"><a href="#cb12-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-49"><a href="#cb12-49" aria-hidden="true" tabindex="-1"></a>  clearenv<span class="op">();</span></span>
<span id="cb12-50"><a href="#cb12-50" aria-hidden="true" tabindex="-1"></a>  close_all_fds_except012<span class="op">();</span></span>
<span id="cb12-51"><a href="#cb12-51" aria-hidden="true" tabindex="-1"></a>  drop_privileges<span class="op">(</span>uid<span class="op">,</span> gid<span class="op">);</span></span>
<span id="cb12-52"><a href="#cb12-52" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-53"><a href="#cb12-53" aria-hidden="true" tabindex="-1"></a>  execvp<span class="op">(</span>argv<span class="op">[</span><span class="dv">0</span><span class="op">],</span> argv<span class="op">);</span></span>
<span id="cb12-54"><a href="#cb12-54" aria-hidden="true" tabindex="-1"></a>  die<span class="op">(</span><span class="st">&quot;execvp(&#39;</span><span class="sc">%s</span><span class="st">&#39;) failed: </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> argv<span class="op">[</span><span class="dv">0</span><span class="op">],</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb12-55"><a href="#cb12-55" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Now, do we have an escape? If you do it right, no. However, there’s a
convoluted way of getting out.</p>
<p>If we know there’s a process that has access to the root file system,
mounting, etc, we “hack” it in a bit of an odd way with
<code>ptrace</code>. <code>Ptrace</code> allows us to “observe” and
“control” the execution of other processes. With this, we can have it be
a confused deputy and mount our file system and therefore get a way to
chroot out. Compile this program and point it to a victim pid on the
host that can mount for us:</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>  pid_t pid <span class="op">=</span> atoi<span class="op">(</span>argv<span class="op">[</span><span class="dv">1</span><span class="op">]);</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> user_regs_struct regs<span class="op">;</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>  </span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>  ptrace<span class="op">(</span>PTRACE_ATTACH<span class="op">,</span> pid<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>  waitpid<span class="op">(</span>pid<span class="op">,</span> NULL<span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>  ptrace<span class="op">(</span>PTRACE_GETREGS<span class="op">,</span> pid<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="op">&amp;</span>regs<span class="op">);</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>  regs<span class="op">.</span>orig_rax <span class="op">=</span> SYS_mount<span class="op">;</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>  regs<span class="op">.</span>rdi <span class="op">=</span> <span class="op">(</span><span class="dt">unsigned</span> <span class="dt">long</span><span class="op">)</span><span class="st">&quot;/host&quot;</span><span class="op">;</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>  regs<span class="op">.</span>rsi <span class="op">=</span> <span class="op">(</span><span class="dt">unsigned</span> <span class="dt">long</span><span class="op">)</span><span class="st">&quot;/mnt&quot;</span><span class="op">;</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>  regs<span class="op">.</span>rdx <span class="op">=</span> MS_BIND<span class="op">;</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>  regs<span class="op">.</span>r10 <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>  ptrace<span class="op">(</span>PTRACE_SETREGS<span class="op">,</span> pid<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="op">&amp;</span>regs<span class="op">);</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a>  ptrace<span class="op">(</span>PTRACE_SYSCALL<span class="op">,</span> pid<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a>  waitpid<span class="op">(</span>pid<span class="op">,</span> NULL<span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a>  ptrace<span class="op">(</span>PTRACE_DETACH<span class="op">,</span> pid<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And we are out:</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> toybox chroot /mnt /bin/sh</span></code></pre></div>
<h2 id="even-more-security">Even More Security</h2>
<p>So we’ve learned that <code>ptrace</code> is evil in this case. What
we need is a way to only allow certain syscalls. Thankfully,
<code>seccomp</code> will do that for us – if you try to run a syscall,
it will get killed.</p>
<p>Let’s add some extra headers and some helpers:</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;seccomp.h&gt;</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;signal.h&gt;</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;sys/prctl.h&gt;</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;sys/resource.h&gt;</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span> setup_user_namespace<span class="op">(</span>uid_t host_uid<span class="op">,</span> gid_t host_gid<span class="op">,</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>                                 uid_t target_uid<span class="op">,</span> gid_t target_gid<span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">char</span> map_buf<span class="op">[</span><span class="dv">256</span><span class="op">];</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> len <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>host_uid <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a>    len <span class="op">=</span> snprintf<span class="op">(</span>map_buf<span class="op">,</span> <span class="kw">sizeof</span><span class="op">(</span>map_buf<span class="op">),</span> <span class="st">&quot;0 </span><span class="sc">%u</span><span class="st"> 1</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> host_uid<span class="op">);</span></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>target_uid <span class="op">!=</span> <span class="dv">0</span><span class="op">)</span></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a>      len <span class="op">+=</span> snprintf<span class="op">(</span>map_buf <span class="op">+</span> len<span class="op">,</span> <span class="kw">sizeof</span><span class="op">(</span>map_buf<span class="op">)</span> <span class="op">-</span> len<span class="op">,</span> <span class="st">&quot;</span><span class="sc">%u</span><span class="st"> </span><span class="sc">%u</span><span class="st"> 1</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span></span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true" tabindex="-1"></a>                      target_uid<span class="op">,</span> target_uid<span class="op">);</span></span>
<span id="cb15-16"><a href="#cb15-16" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb15-17"><a href="#cb15-17" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>target_uid <span class="op">!=</span> <span class="dv">0</span><span class="op">)</span></span>
<span id="cb15-18"><a href="#cb15-18" aria-hidden="true" tabindex="-1"></a>      die<span class="op">(</span><span class="st">&quot;non-root users must run with -u 0 (got </span><span class="sc">%u</span><span class="st">)&quot;</span><span class="op">,</span> target_uid<span class="op">);</span></span>
<span id="cb15-19"><a href="#cb15-19" aria-hidden="true" tabindex="-1"></a>    len <span class="op">=</span> snprintf<span class="op">(</span>map_buf<span class="op">,</span> <span class="kw">sizeof</span><span class="op">(</span>map_buf<span class="op">),</span> <span class="st">&quot;0 </span><span class="sc">%u</span><span class="st"> 1</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> host_uid<span class="op">);</span></span>
<span id="cb15-20"><a href="#cb15-20" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb15-21"><a href="#cb15-21" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>len <span class="op">&lt;</span> <span class="dv">0</span> <span class="op">||</span> <span class="op">(</span><span class="dt">size_t</span><span class="op">)</span>len <span class="op">&gt;=</span> <span class="kw">sizeof</span><span class="op">(</span>map_buf<span class="op">))</span></span>
<span id="cb15-22"><a href="#cb15-22" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;uid_map formatting overflow&quot;</span><span class="op">);</span></span>
<span id="cb15-23"><a href="#cb15-23" aria-hidden="true" tabindex="-1"></a>  write_file_fmt<span class="op">(</span><span class="st">&quot;/proc/self/uid_map&quot;</span><span class="op">,</span> <span class="st">&quot;</span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> map_buf<span class="op">);</span></span>
<span id="cb15-24"><a href="#cb15-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-25"><a href="#cb15-25" aria-hidden="true" tabindex="-1"></a>  len <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb15-26"><a href="#cb15-26" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>host_uid <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-27"><a href="#cb15-27" aria-hidden="true" tabindex="-1"></a>    len <span class="op">=</span> snprintf<span class="op">(</span>map_buf<span class="op">,</span> <span class="kw">sizeof</span><span class="op">(</span>map_buf<span class="op">),</span> <span class="st">&quot;0 </span><span class="sc">%u</span><span class="st"> 1</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> host_gid<span class="op">);</span></span>
<span id="cb15-28"><a href="#cb15-28" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>target_gid <span class="op">!=</span> <span class="dv">0</span><span class="op">)</span></span>
<span id="cb15-29"><a href="#cb15-29" aria-hidden="true" tabindex="-1"></a>      len <span class="op">+=</span> snprintf<span class="op">(</span>map_buf <span class="op">+</span> len<span class="op">,</span> <span class="kw">sizeof</span><span class="op">(</span>map_buf<span class="op">)</span> <span class="op">-</span> len<span class="op">,</span> <span class="st">&quot;</span><span class="sc">%u</span><span class="st"> </span><span class="sc">%u</span><span class="st"> 1</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span></span>
<span id="cb15-30"><a href="#cb15-30" aria-hidden="true" tabindex="-1"></a>                      target_gid<span class="op">,</span> target_gid<span class="op">);</span></span>
<span id="cb15-31"><a href="#cb15-31" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb15-32"><a href="#cb15-32" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>target_gid <span class="op">!=</span> <span class="dv">0</span><span class="op">)</span></span>
<span id="cb15-33"><a href="#cb15-33" aria-hidden="true" tabindex="-1"></a>      die<span class="op">(</span><span class="st">&quot;non-root users must run with -g 0 (got </span><span class="sc">%u</span><span class="st">)&quot;</span><span class="op">,</span> target_gid<span class="op">);</span></span>
<span id="cb15-34"><a href="#cb15-34" aria-hidden="true" tabindex="-1"></a>    len <span class="op">=</span> snprintf<span class="op">(</span>map_buf<span class="op">,</span> <span class="kw">sizeof</span><span class="op">(</span>map_buf<span class="op">),</span> <span class="st">&quot;0 </span><span class="sc">%u</span><span class="st"> 1</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> host_gid<span class="op">);</span></span>
<span id="cb15-35"><a href="#cb15-35" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb15-36"><a href="#cb15-36" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>len <span class="op">&lt;</span> <span class="dv">0</span> <span class="op">||</span> <span class="op">(</span><span class="dt">size_t</span><span class="op">)</span>len <span class="op">&gt;=</span> <span class="kw">sizeof</span><span class="op">(</span>map_buf<span class="op">))</span></span>
<span id="cb15-37"><a href="#cb15-37" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;gid_map formatting overflow&quot;</span><span class="op">);</span></span>
<span id="cb15-38"><a href="#cb15-38" aria-hidden="true" tabindex="-1"></a>  write_file_fmt<span class="op">(</span><span class="st">&quot;/proc/self/gid_map&quot;</span><span class="op">,</span> <span class="st">&quot;</span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> map_buf<span class="op">);</span></span>
<span id="cb15-39"><a href="#cb15-39" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb15-40"><a href="#cb15-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-41"><a href="#cb15-41" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span> sigsys_handler<span class="op">(</span><span class="dt">int</span> _nr<span class="op">,</span> siginfo_t <span class="op">*</span>info<span class="op">,</span> <span class="dt">void</span> <span class="op">*</span>_uctx<span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-42"><a href="#cb15-42" aria-hidden="true" tabindex="-1"></a>  <span class="op">(</span><span class="dt">void</span><span class="op">)</span>_nr<span class="op">;</span></span>
<span id="cb15-43"><a href="#cb15-43" aria-hidden="true" tabindex="-1"></a>  <span class="op">(</span><span class="dt">void</span><span class="op">)</span>_uctx<span class="op">;</span></span>
<span id="cb15-44"><a href="#cb15-44" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(!</span>info<span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-45"><a href="#cb15-45" aria-hidden="true" tabindex="-1"></a>    fprintf<span class="op">(</span>stderr<span class="op">,</span> <span class="st">&quot;blocked syscall (no info)</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">);</span></span>
<span id="cb15-46"><a href="#cb15-46" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb15-47"><a href="#cb15-47" aria-hidden="true" tabindex="-1"></a>    fprintf<span class="op">(</span>stderr<span class="op">,</span> <span class="st">&quot;blocked syscall </span><span class="sc">%d</span><span class="st"> (arch </span><span class="sc">%#x</span><span class="st">, addr </span><span class="sc">%p</span><span class="st">)</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span></span>
<span id="cb15-48"><a href="#cb15-48" aria-hidden="true" tabindex="-1"></a>            info<span class="op">-&gt;</span>si_syscall<span class="op">,</span> info<span class="op">-&gt;</span>si_arch<span class="op">,</span> info<span class="op">-&gt;</span>si_call_addr<span class="op">);</span></span>
<span id="cb15-49"><a href="#cb15-49" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb15-50"><a href="#cb15-50" aria-hidden="true" tabindex="-1"></a>  _exit<span class="op">(</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb15-51"><a href="#cb15-51" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb15-52"><a href="#cb15-52" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-53"><a href="#cb15-53" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span> install_sigsys_logger<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-54"><a href="#cb15-54" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> sigaction sa<span class="op">;</span></span>
<span id="cb15-55"><a href="#cb15-55" aria-hidden="true" tabindex="-1"></a>  memset<span class="op">(&amp;</span>sa<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="kw">sizeof</span><span class="op">(</span>sa<span class="op">));</span></span>
<span id="cb15-56"><a href="#cb15-56" aria-hidden="true" tabindex="-1"></a>  sa<span class="op">.</span>sa_sigaction <span class="op">=</span> sigsys_handler<span class="op">;</span></span>
<span id="cb15-57"><a href="#cb15-57" aria-hidden="true" tabindex="-1"></a>  sa<span class="op">.</span>sa_flags <span class="op">=</span> SA_SIGINFO <span class="op">|</span> SA_RESETHAND<span class="op">;</span></span>
<span id="cb15-58"><a href="#cb15-58" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>sigaction<span class="op">(</span>SIGSYS<span class="op">,</span> <span class="op">&amp;</span>sa<span class="op">,</span> NULL<span class="op">)</span> <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb15-59"><a href="#cb15-59" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;sigaction(SIGSYS): </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb15-60"><a href="#cb15-60" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb15-61"><a href="#cb15-61" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-62"><a href="#cb15-62" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span> install_seccomp_allowlist<span class="op">()</span> <span class="op">{</span></span>
<span id="cb15-63"><a href="#cb15-63" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>prctl<span class="op">(</span>PR_SET_NO_NEW_PRIVS<span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">)</span> <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb15-64"><a href="#cb15-64" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;prctl(NO_NEW_PRIVS): </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb15-65"><a href="#cb15-65" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-66"><a href="#cb15-66" aria-hidden="true" tabindex="-1"></a>  scmp_filter_ctx ctx <span class="op">=</span> seccomp_init<span class="op">(</span>SCMP_ACT_TRAP<span class="op">);</span></span>
<span id="cb15-67"><a href="#cb15-67" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(!</span>ctx<span class="op">)</span></span>
<span id="cb15-68"><a href="#cb15-68" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;seccomp_init failed&quot;</span><span class="op">);</span></span>
<span id="cb15-69"><a href="#cb15-69" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-70"><a href="#cb15-70" aria-hidden="true" tabindex="-1"></a><span class="pp">#define ALLOW</span><span class="op">(</span><span class="pp">syscall</span><span class="op">)</span><span class="pp">                                                         </span><span class="op">\</span></span>
<span id="cb15-71"><a href="#cb15-71" aria-hidden="true" tabindex="-1"></a><span class="pp">  </span><span class="cf">do</span><span class="pp"> </span><span class="op">{</span><span class="pp">                                                                         </span><span class="op">\</span></span>
<span id="cb15-72"><a href="#cb15-72" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="cf">if</span><span class="pp"> </span><span class="op">(</span><span class="pp">seccomp_rule_add</span><span class="op">(</span><span class="pp">ctx</span><span class="op">,</span><span class="pp"> SCMP_ACT_ALLOW</span><span class="op">,</span><span class="pp"> SCMP_SYS</span><span class="op">(</span><span class="pp">syscall</span><span class="op">),</span><span class="pp"> </span><span class="dv">0</span><span class="op">))</span><span class="pp">           </span><span class="op">\</span></span>
<span id="cb15-73"><a href="#cb15-73" aria-hidden="true" tabindex="-1"></a><span class="pp">      die</span><span class="op">(</span><span class="st">&quot;allow &quot;</span><span class="pp"> </span><span class="op">#</span><span class="pp">syscall </span><span class="st">&quot; failed&quot;</span><span class="op">);</span><span class="pp">                                        </span><span class="op">\</span></span>
<span id="cb15-74"><a href="#cb15-74" aria-hidden="true" tabindex="-1"></a><span class="pp">  </span><span class="op">}</span><span class="pp"> </span><span class="cf">while</span><span class="pp"> </span><span class="op">(</span><span class="dv">0</span><span class="op">)</span></span>
<span id="cb15-75"><a href="#cb15-75" aria-hidden="true" tabindex="-1"></a><span class="pp">#define ALLOW_ARG</span><span class="op">(</span><span class="pp">syscall</span><span class="op">,</span><span class="pp"> idx</span><span class="op">,</span><span class="pp"> cmp</span><span class="op">,</span><span class="pp"> val</span><span class="op">)</span><span class="pp">                                      </span><span class="op">\</span></span>
<span id="cb15-76"><a href="#cb15-76" aria-hidden="true" tabindex="-1"></a><span class="pp">  </span><span class="cf">do</span><span class="pp"> </span><span class="op">{</span><span class="pp">                                                                         </span><span class="op">\</span></span>
<span id="cb15-77"><a href="#cb15-77" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="cf">if</span><span class="pp"> </span><span class="op">(</span><span class="pp">seccomp_rule_add</span><span class="op">(</span><span class="pp">ctx</span><span class="op">,</span><span class="pp"> SCMP_ACT_ALLOW</span><span class="op">,</span><span class="pp"> SCMP_SYS</span><span class="op">(</span><span class="pp">syscall</span><span class="op">),</span><span class="pp"> </span><span class="dv">1</span><span class="op">,</span><span class="pp">            </span><span class="op">\</span></span>
<span id="cb15-78"><a href="#cb15-78" aria-hidden="true" tabindex="-1"></a><span class="pp">                         SCMP_CMP</span><span class="op">(</span><span class="pp">idx</span><span class="op">,</span><span class="pp"> cmp</span><span class="op">,</span><span class="pp"> val</span><span class="op">)))</span><span class="pp">                             </span><span class="op">\</span></span>
<span id="cb15-79"><a href="#cb15-79" aria-hidden="true" tabindex="-1"></a><span class="pp">      die</span><span class="op">(</span><span class="st">&quot;allow &quot;</span><span class="pp"> </span><span class="op">#</span><span class="pp">syscall </span><span class="st">&quot; arg failed&quot;</span><span class="op">);</span><span class="pp">                                    </span><span class="op">\</span></span>
<span id="cb15-80"><a href="#cb15-80" aria-hidden="true" tabindex="-1"></a><span class="pp">  </span><span class="op">}</span><span class="pp"> </span><span class="cf">while</span><span class="pp"> </span><span class="op">(</span><span class="dv">0</span><span class="op">)</span></span>
<span id="cb15-81"><a href="#cb15-81" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-82"><a href="#cb15-82" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>rt_sigaction<span class="op">);</span></span>
<span id="cb15-83"><a href="#cb15-83" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>rt_sigprocmask<span class="op">);</span></span>
<span id="cb15-84"><a href="#cb15-84" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>umask<span class="op">);</span></span>
<span id="cb15-85"><a href="#cb15-85" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>rt_sigreturn<span class="op">);</span></span>
<span id="cb15-86"><a href="#cb15-86" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>exit<span class="op">);</span></span>
<span id="cb15-87"><a href="#cb15-87" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>exit_group<span class="op">);</span></span>
<span id="cb15-88"><a href="#cb15-88" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>getpid<span class="op">);</span></span>
<span id="cb15-89"><a href="#cb15-89" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>getppid<span class="op">);</span></span>
<span id="cb15-90"><a href="#cb15-90" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>gettid<span class="op">);</span></span>
<span id="cb15-91"><a href="#cb15-91" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>futex<span class="op">);</span></span>
<span id="cb15-92"><a href="#cb15-92" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>clone<span class="op">);</span></span>
<span id="cb15-93"><a href="#cb15-93" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>set_tid_address<span class="op">);</span></span>
<span id="cb15-94"><a href="#cb15-94" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>set_robust_list<span class="op">);</span></span>
<span id="cb15-95"><a href="#cb15-95" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-96"><a href="#cb15-96" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>clock_gettime<span class="op">);</span></span>
<span id="cb15-97"><a href="#cb15-97" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>clock_nanosleep<span class="op">);</span></span>
<span id="cb15-98"><a href="#cb15-98" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>nanosleep<span class="op">);</span></span>
<span id="cb15-99"><a href="#cb15-99" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>getrandom<span class="op">);</span></span>
<span id="cb15-100"><a href="#cb15-100" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-101"><a href="#cb15-101" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>brk<span class="op">);</span></span>
<span id="cb15-102"><a href="#cb15-102" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>mmap<span class="op">);</span></span>
<span id="cb15-103"><a href="#cb15-103" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>munmap<span class="op">);</span></span>
<span id="cb15-104"><a href="#cb15-104" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>mremap<span class="op">);</span></span>
<span id="cb15-105"><a href="#cb15-105" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>mprotect<span class="op">);</span></span>
<span id="cb15-106"><a href="#cb15-106" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-107"><a href="#cb15-107" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>arch_prctl<span class="op">);</span></span>
<span id="cb15-108"><a href="#cb15-108" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>getuid<span class="op">);</span></span>
<span id="cb15-109"><a href="#cb15-109" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>geteuid<span class="op">);</span></span>
<span id="cb15-110"><a href="#cb15-110" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>getgid<span class="op">);</span></span>
<span id="cb15-111"><a href="#cb15-111" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>getegid<span class="op">);</span></span>
<span id="cb15-112"><a href="#cb15-112" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>prlimit64<span class="op">);</span></span>
<span id="cb15-113"><a href="#cb15-113" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>prctl<span class="op">);</span></span>
<span id="cb15-114"><a href="#cb15-114" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>madvise<span class="op">);</span></span>
<span id="cb15-115"><a href="#cb15-115" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>access<span class="op">);</span></span>
<span id="cb15-116"><a href="#cb15-116" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>faccessat2<span class="op">);</span></span>
<span id="cb15-117"><a href="#cb15-117" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>pread64<span class="op">);</span></span>
<span id="cb15-118"><a href="#cb15-118" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>rseq<span class="op">);</span></span>
<span id="cb15-119"><a href="#cb15-119" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>fadvise64<span class="op">);</span></span>
<span id="cb15-120"><a href="#cb15-120" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-121"><a href="#cb15-121" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>read<span class="op">);</span></span>
<span id="cb15-122"><a href="#cb15-122" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>write<span class="op">);</span></span>
<span id="cb15-123"><a href="#cb15-123" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>writev<span class="op">);</span></span>
<span id="cb15-124"><a href="#cb15-124" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>close<span class="op">);</span></span>
<span id="cb15-125"><a href="#cb15-125" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>lseek<span class="op">);</span></span>
<span id="cb15-126"><a href="#cb15-126" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>getdents64<span class="op">);</span></span>
<span id="cb15-127"><a href="#cb15-127" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>ioctl<span class="op">);</span></span>
<span id="cb15-128"><a href="#cb15-128" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>statx<span class="op">);</span></span>
<span id="cb15-129"><a href="#cb15-129" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>fstat<span class="op">);</span></span>
<span id="cb15-130"><a href="#cb15-130" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>fstatfs<span class="op">);</span></span>
<span id="cb15-131"><a href="#cb15-131" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>newfstatat<span class="op">);</span></span>
<span id="cb15-132"><a href="#cb15-132" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>fcntl<span class="op">);</span></span>
<span id="cb15-133"><a href="#cb15-133" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>dup<span class="op">);</span></span>
<span id="cb15-134"><a href="#cb15-134" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>dup2<span class="op">);</span></span>
<span id="cb15-135"><a href="#cb15-135" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>dup3<span class="op">);</span></span>
<span id="cb15-136"><a href="#cb15-136" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>pipe<span class="op">);</span></span>
<span id="cb15-137"><a href="#cb15-137" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>pipe2<span class="op">);</span></span>
<span id="cb15-138"><a href="#cb15-138" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>readlink<span class="op">);</span></span>
<span id="cb15-139"><a href="#cb15-139" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>readlinkat<span class="op">);</span></span>
<span id="cb15-140"><a href="#cb15-140" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>uname<span class="op">);</span></span>
<span id="cb15-141"><a href="#cb15-141" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>open<span class="op">);</span></span>
<span id="cb15-142"><a href="#cb15-142" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>openat<span class="op">);</span></span>
<span id="cb15-143"><a href="#cb15-143" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-144"><a href="#cb15-144" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>execve<span class="op">);</span></span>
<span id="cb15-145"><a href="#cb15-145" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>execveat<span class="op">);</span></span>
<span id="cb15-146"><a href="#cb15-146" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-147"><a href="#cb15-147" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>socket<span class="op">);</span></span>
<span id="cb15-148"><a href="#cb15-148" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>connect<span class="op">);</span></span>
<span id="cb15-149"><a href="#cb15-149" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>bind<span class="op">);</span></span>
<span id="cb15-150"><a href="#cb15-150" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>listen<span class="op">);</span></span>
<span id="cb15-151"><a href="#cb15-151" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>accept<span class="op">);</span></span>
<span id="cb15-152"><a href="#cb15-152" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>accept4<span class="op">);</span></span>
<span id="cb15-153"><a href="#cb15-153" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>getsockopt<span class="op">);</span></span>
<span id="cb15-154"><a href="#cb15-154" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>setsockopt<span class="op">);</span></span>
<span id="cb15-155"><a href="#cb15-155" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>getsockname<span class="op">);</span></span>
<span id="cb15-156"><a href="#cb15-156" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>getpeername<span class="op">);</span></span>
<span id="cb15-157"><a href="#cb15-157" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>sendto<span class="op">);</span></span>
<span id="cb15-158"><a href="#cb15-158" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>recvfrom<span class="op">);</span></span>
<span id="cb15-159"><a href="#cb15-159" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>sendmsg<span class="op">);</span></span>
<span id="cb15-160"><a href="#cb15-160" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>recvmsg<span class="op">);</span></span>
<span id="cb15-161"><a href="#cb15-161" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>shutdown<span class="op">);</span></span>
<span id="cb15-162"><a href="#cb15-162" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-163"><a href="#cb15-163" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>clone3<span class="op">);</span></span>
<span id="cb15-164"><a href="#cb15-164" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>eventfd2<span class="op">);</span></span>
<span id="cb15-165"><a href="#cb15-165" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>poll<span class="op">);</span></span>
<span id="cb15-166"><a href="#cb15-166" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>statfs<span class="op">);</span></span>
<span id="cb15-167"><a href="#cb15-167" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>getcwd<span class="op">);</span></span>
<span id="cb15-168"><a href="#cb15-168" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>getpgid<span class="op">);</span></span>
<span id="cb15-169"><a href="#cb15-169" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>setpgid<span class="op">);</span></span>
<span id="cb15-170"><a href="#cb15-170" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>stat<span class="op">);</span></span>
<span id="cb15-171"><a href="#cb15-171" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>vfork<span class="op">);</span></span>
<span id="cb15-172"><a href="#cb15-172" aria-hidden="true" tabindex="-1"></a>  ALLOW<span class="op">(</span>wait4<span class="op">);</span></span>
<span id="cb15-173"><a href="#cb15-173" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-174"><a href="#cb15-174" aria-hidden="true" tabindex="-1"></a>  seccomp_rule_add<span class="op">(</span>ctx<span class="op">,</span> SCMP_ACT_KILL<span class="op">,</span> SCMP_SYS<span class="op">(</span>chroot<span class="op">),</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb15-175"><a href="#cb15-175" aria-hidden="true" tabindex="-1"></a>  seccomp_rule_add<span class="op">(</span>ctx<span class="op">,</span> SCMP_ACT_KILL<span class="op">,</span> SCMP_SYS<span class="op">(</span>pivot_root<span class="op">),</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb15-176"><a href="#cb15-176" aria-hidden="true" tabindex="-1"></a>  seccomp_rule_add<span class="op">(</span>ctx<span class="op">,</span> SCMP_ACT_KILL<span class="op">,</span> SCMP_SYS<span class="op">(</span>mount<span class="op">),</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb15-177"><a href="#cb15-177" aria-hidden="true" tabindex="-1"></a>  seccomp_rule_add<span class="op">(</span>ctx<span class="op">,</span> SCMP_ACT_KILL<span class="op">,</span> SCMP_SYS<span class="op">(</span>umount2<span class="op">),</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb15-178"><a href="#cb15-178" aria-hidden="true" tabindex="-1"></a>  seccomp_rule_add<span class="op">(</span>ctx<span class="op">,</span> SCMP_ACT_KILL<span class="op">,</span> SCMP_SYS<span class="op">(</span>open_by_handle_at<span class="op">),</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb15-179"><a href="#cb15-179" aria-hidden="true" tabindex="-1"></a>  seccomp_rule_add<span class="op">(</span>ctx<span class="op">,</span> SCMP_ACT_KILL<span class="op">,</span> SCMP_SYS<span class="op">(</span>name_to_handle_at<span class="op">),</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb15-180"><a href="#cb15-180" aria-hidden="true" tabindex="-1"></a>  seccomp_rule_add<span class="op">(</span>ctx<span class="op">,</span> SCMP_ACT_KILL<span class="op">,</span> SCMP_SYS<span class="op">(</span>bpf<span class="op">),</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb15-181"><a href="#cb15-181" aria-hidden="true" tabindex="-1"></a>  seccomp_rule_add<span class="op">(</span>ctx<span class="op">,</span> SCMP_ACT_KILL<span class="op">,</span> SCMP_SYS<span class="op">(</span>kexec_load<span class="op">),</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb15-182"><a href="#cb15-182" aria-hidden="true" tabindex="-1"></a>  seccomp_rule_add<span class="op">(</span>ctx<span class="op">,</span> SCMP_ACT_KILL<span class="op">,</span> SCMP_SYS<span class="op">(</span>kexec_file_load<span class="op">),</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb15-183"><a href="#cb15-183" aria-hidden="true" tabindex="-1"></a>  seccomp_rule_add<span class="op">(</span>ctx<span class="op">,</span> SCMP_ACT_KILL<span class="op">,</span> SCMP_SYS<span class="op">(</span>ptrace<span class="op">),</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb15-184"><a href="#cb15-184" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-185"><a href="#cb15-185" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>seccomp_load<span class="op">(</span>ctx<span class="op">)</span> <span class="op">!=</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-186"><a href="#cb15-186" aria-hidden="true" tabindex="-1"></a>    seccomp_release<span class="op">(</span>ctx<span class="op">);</span></span>
<span id="cb15-187"><a href="#cb15-187" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;seccomp_load failed&quot;</span><span class="op">);</span></span>
<span id="cb15-188"><a href="#cb15-188" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb15-189"><a href="#cb15-189" aria-hidden="true" tabindex="-1"></a>  seccomp_release<span class="op">(</span>ctx<span class="op">);</span></span>
<span id="cb15-190"><a href="#cb15-190" aria-hidden="true" tabindex="-1"></a><span class="pp">#undef ALLOW</span></span>
<span id="cb15-191"><a href="#cb15-191" aria-hidden="true" tabindex="-1"></a><span class="pp">#undef ALLOW_ARG</span></span></code></pre></div>
<p>And fix up main.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>root <span class="op">=</span> NULL<span class="op">;</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>  uid_t host_uid <span class="op">=</span> geteuid<span class="op">();</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>  gid_t host_gid <span class="op">=</span> getegid<span class="op">();</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> rootless <span class="op">=</span> <span class="op">(</span>host_uid <span class="op">!=</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>  uid_t uid <span class="op">=</span> rootless <span class="op">?</span> <span class="dv">0</span> <span class="op">:</span> <span class="dv">65534</span><span class="op">;</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>  gid_t gid <span class="op">=</span> rootless <span class="op">?</span> <span class="dv">0</span> <span class="op">:</span> <span class="dv">65534</span><span class="op">;</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">1</span><span class="op">;</span> i <span class="op">&lt;</span> argc<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(!</span>strcmp<span class="op">(</span>argv<span class="op">[</span>i<span class="op">],</span> <span class="st">&quot;-r&quot;</span><span class="op">)</span> <span class="op">&amp;&amp;</span> i <span class="op">+</span> <span class="dv">1</span> <span class="op">&lt;</span> argc<span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>      root <span class="op">=</span> argv<span class="op">[++</span>i<span class="op">];</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(!</span>strcmp<span class="op">(</span>argv<span class="op">[</span>i<span class="op">],</span> <span class="st">&quot;-u&quot;</span><span class="op">)</span> <span class="op">&amp;&amp;</span> i <span class="op">+</span> <span class="dv">1</span> <span class="op">&lt;</span> argc<span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a>      uid <span class="op">=</span> <span class="op">(</span>uid_t<span class="op">)</span>strtoul<span class="op">(</span>argv<span class="op">[++</span>i<span class="op">],</span> NULL<span class="op">,</span> <span class="dv">10</span><span class="op">);</span></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(!</span>strcmp<span class="op">(</span>argv<span class="op">[</span>i<span class="op">],</span> <span class="st">&quot;-g&quot;</span><span class="op">)</span> <span class="op">&amp;&amp;</span> i <span class="op">+</span> <span class="dv">1</span> <span class="op">&lt;</span> argc<span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a>      gid <span class="op">=</span> <span class="op">(</span>gid_t<span class="op">)</span>strtoul<span class="op">(</span>argv<span class="op">[++</span>i<span class="op">],</span> NULL<span class="op">,</span> <span class="dv">10</span><span class="op">);</span></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(!</span>strcmp<span class="op">(</span>argv<span class="op">[</span>i<span class="op">],</span> <span class="st">&quot;--&quot;</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>      argv <span class="op">+=</span> i <span class="op">+</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>      argc <span class="op">-=</span> i <span class="op">+</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>argv<span class="op">[</span>i<span class="op">][</span><span class="dv">0</span><span class="op">]</span> <span class="op">==</span> <span class="ch">&#39;-&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true" tabindex="-1"></a>      usage<span class="op">(</span>argv<span class="op">[</span><span class="dv">0</span><span class="op">]);</span></span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb16-23"><a href="#cb16-23" aria-hidden="true" tabindex="-1"></a>      argv <span class="op">+=</span> i<span class="op">;</span></span>
<span id="cb16-24"><a href="#cb16-24" aria-hidden="true" tabindex="-1"></a>      argc <span class="op">-=</span> i<span class="op">;</span></span>
<span id="cb16-25"><a href="#cb16-25" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
<span id="cb16-26"><a href="#cb16-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-27"><a href="#cb16-27" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb16-28"><a href="#cb16-28" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(!</span>root <span class="op">||</span> argc <span class="op">&lt;</span> <span class="dv">1</span><span class="op">)</span></span>
<span id="cb16-29"><a href="#cb16-29" aria-hidden="true" tabindex="-1"></a>    usage<span class="op">(</span><span class="st">&quot;container&quot;</span><span class="op">);</span></span>
<span id="cb16-30"><a href="#cb16-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-31"><a href="#cb16-31" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>rootless <span class="op">&amp;&amp;</span> <span class="op">(</span>uid <span class="op">!=</span> <span class="dv">0</span> <span class="op">||</span> gid <span class="op">!=</span> <span class="dv">0</span><span class="op">))</span></span>
<span id="cb16-32"><a href="#cb16-32" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;non-root users can only use -u/-g 0 (try running as root for other &quot;</span></span>
<span id="cb16-33"><a href="#cb16-33" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;ids)&quot;</span><span class="op">);</span></span>
<span id="cb16-34"><a href="#cb16-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-35"><a href="#cb16-35" aria-hidden="true" tabindex="-1"></a>  setup_user_namespace<span class="op">(</span>host_uid<span class="op">,</span> host_gid<span class="op">,</span> uid<span class="op">,</span> gid<span class="op">);</span></span>
<span id="cb16-36"><a href="#cb16-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-37"><a href="#cb16-37" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>unshare<span class="op">(</span>CLONE_NEWNS<span class="op">)</span> <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb16-38"><a href="#cb16-38" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;unshare(CLONE_NEWNS): </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb16-39"><a href="#cb16-39" aria-hidden="true" tabindex="-1"></a>  make_private_mounts<span class="op">();</span></span>
<span id="cb16-40"><a href="#cb16-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-41"><a href="#cb16-41" aria-hidden="true" tabindex="-1"></a>  bind_mount_self<span class="op">(</span>root<span class="op">);</span></span>
<span id="cb16-42"><a href="#cb16-42" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>chroot<span class="op">(</span>root<span class="op">)</span> <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb16-43"><a href="#cb16-43" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;chroot(</span><span class="sc">%s</span><span class="st">): </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> root<span class="op">,</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb16-44"><a href="#cb16-44" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>chdir<span class="op">(</span><span class="st">&quot;/&quot;</span><span class="op">)</span> <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb16-45"><a href="#cb16-45" aria-hidden="true" tabindex="-1"></a>    die<span class="op">(</span><span class="st">&quot;chdir(/): </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb16-46"><a href="#cb16-46" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-47"><a href="#cb16-47" aria-hidden="true" tabindex="-1"></a>  mkdir<span class="op">(</span><span class="st">&quot;/proc&quot;</span><span class="op">,</span> <span class="bn">0555</span><span class="op">);</span></span>
<span id="cb16-48"><a href="#cb16-48" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>mount<span class="op">(</span><span class="st">&quot;proc&quot;</span><span class="op">,</span> <span class="st">&quot;/proc&quot;</span><span class="op">,</span> <span class="st">&quot;proc&quot;</span><span class="op">,</span> MS_NOSUID <span class="op">|</span> MS_NODEV <span class="op">|</span> MS_NOEXEC<span class="op">,</span> NULL<span class="op">)</span> <span class="op">==</span></span>
<span id="cb16-49"><a href="#cb16-49" aria-hidden="true" tabindex="-1"></a>      <span class="op">-</span><span class="dv">1</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-50"><a href="#cb16-50" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb16-51"><a href="#cb16-51" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-52"><a href="#cb16-52" aria-hidden="true" tabindex="-1"></a>  clearenv<span class="op">();</span></span>
<span id="cb16-53"><a href="#cb16-53" aria-hidden="true" tabindex="-1"></a>  close_all_fds_except_std<span class="op">();</span></span>
<span id="cb16-54"><a href="#cb16-54" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-55"><a href="#cb16-55" aria-hidden="true" tabindex="-1"></a>  drop_privileges<span class="op">(</span>uid<span class="op">,</span> gid<span class="op">);</span></span>
<span id="cb16-56"><a href="#cb16-56" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-57"><a href="#cb16-57" aria-hidden="true" tabindex="-1"></a>  install_sigsys_logger<span class="op">();</span></span>
<span id="cb16-58"><a href="#cb16-58" aria-hidden="true" tabindex="-1"></a>  install_seccomp_allowlist<span class="op">();</span></span>
<span id="cb16-59"><a href="#cb16-59" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-60"><a href="#cb16-60" aria-hidden="true" tabindex="-1"></a>  execvp<span class="op">(</span>argv<span class="op">[</span><span class="dv">0</span><span class="op">],</span> argv<span class="op">);</span></span>
<span id="cb16-61"><a href="#cb16-61" aria-hidden="true" tabindex="-1"></a>  die<span class="op">(</span><span class="st">&quot;execvp(&#39;</span><span class="sc">%s</span><span class="st">&#39;) failed: </span><span class="sc">%s</span><span class="st">&quot;</span><span class="op">,</span> argv<span class="op">[</span><span class="dv">0</span><span class="op">],</span> strerror<span class="op">(</span>errno<span class="op">));</span></span>
<span id="cb16-62"><a href="#cb16-62" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Now with this, we can’t try any <code>ptrace</code> tricks, since
we’ve explicitly disallowed it. As well, we’ve added a helper that lets
us strace a task to see which syscall killed our task (good for
debugging).</p>
<p>I’ve allowed enough syscalls to allow for one last party trick – a
way to call the network (on your own computer).</p>
<p>I spun up an http server serving the <code>container.c</code> file at
<code>127.0.0.1:8080/container.c</code>:</p>
<p>And look, there’s the code.</p>
<div class="sourceCode" id="cb17"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./container_3</span> <span class="at">-r</span> root/ <span class="at">--</span> /bin/dash</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> toybox wget http://127.0.0.1:8080/container.c <span class="at">-O</span> <span class="at">-</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a><span class="co"># the code we&#39;ve been writing today.</span></span></code></pre></div>
<p>If you’re a little too overzealous with the system calls, there’s
probably an escape out, but we can cover the most egregious ones with
the seccomp denylist. You can configure the list how you like and you
can get a passable toy container and play around with
it.</p>]]></description>
</item>
<item>
<title>C vs. Asm</title>
<pubDate>Wed, 12 Nov 2025 13:22:49 +0000</pubDate>
<guid>https://blog/c-vs-asm.html</guid>
<description><![CDATA[<h2 id="its-faster-in-assembly">It’s faster in
Assembly</h2>
<p>A common refrain is if something is slow, to rewrite it in a
<strong>faster</strong> language. For python, if your python is slow, to
write the hot parts in C. For C, to write your code in pure
assembly.</p>
<p>Let’s put that to the test.</p>
<p>I have this code here that defines <code>strnlen</code> from linux’s
m68k tree. This computes <code>strnlen</code> as you would expect.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="kw">inline</span> <span class="dt">size_t</span> strnlen_asm<span class="op">(</span><span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>s<span class="op">,</span> <span class="dt">size_t</span> count<span class="op">)</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>sc <span class="op">=</span> s<span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    asm <span class="dt">volatile</span> <span class="op">(</span><span class="st">&quot;</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;1:     subq.l  #1,%1</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;       jcs     2f</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;       tst.b   (%0)+</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;       jne     1b</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;       subq.l  #1,%0</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;2:&quot;</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">:</span> <span class="st">&quot;+a&quot;</span> <span class="op">(</span>sc<span class="op">),</span> <span class="st">&quot;+d&quot;</span> <span class="op">(</span>count<span class="op">));</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> sc <span class="op">-</span> s<span class="op">;</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The c translation here would look like this:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="kw">inline</span> <span class="dt">size_t</span> strnlen<span class="op">(</span><span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>s<span class="op">,</span> <span class="dt">size_t</span> count<span class="op">)</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>sc <span class="op">=</span> s<span class="op">;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="op">(</span>count<span class="op">--)</span> <span class="op">{</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(*</span>sc<span class="op">++</span> <span class="op">==</span> <span class="ch">&#39;</span><span class="sc">\0</span><span class="ch">&#39;</span><span class="op">)</span> <span class="op">{</span>   </span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>            sc<span class="op">--;</span>              </span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>            <span class="cf">break</span><span class="op">;</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> sc <span class="op">-</span> s<span class="op">;</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Now if we compile with <code>-O0</code>, we’ll see that the asm
version is better, even though functionally, they’re pretty much the
same. The compiler does only a few optimizations in <code>-O0</code>, so
the generated code is quite poor.</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode asm"><code class="sourceCode fasm"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>strnlen_asm<span class="op">(</span>char const<span class="op">*,</span> unsigned long<span class="op">):</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    link<span class="op">.</span>w <span class="op">%</span>fp<span class="op">,#-</span><span class="dv">4</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    move<span class="op">.</span>l <span class="op">%</span>fp<span class="fu">@</span><span class="er">(</span><span class="dv">8</span><span class="op">),%</span>fp<span class="fu">@</span><span class="er">(</span><span class="op">-</span><span class="dv">4</span><span class="op">)</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    move<span class="op">.</span>l <span class="op">%</span>fp<span class="fu">@</span><span class="er">(</span><span class="op">-</span><span class="dv">4</span><span class="op">),%</span>d1</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    move<span class="op">.</span>l <span class="op">%</span>fp<span class="fu">@</span><span class="er">(</span><span class="dv">12</span><span class="op">),%</span>d0</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    movea<span class="op">.</span>l <span class="op">%</span>d1<span class="op">,%</span>a0</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>    subq<span class="op">.</span>l <span class="op">#</span><span class="dv">1</span><span class="op">,%</span>d0</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>    bcss <span class="dv">1</span><span class="er">e</span> <span class="op">&lt;</span>strnlen_asm<span class="op">(</span>char const<span class="op">*,</span> unsigned long<span class="op">)+</span><span class="bn">0x1e</span><span class="op">&gt;</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>    tstb <span class="op">%</span>a0<span class="fu">@</span><span class="er">+</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>    bnes <span class="dv">14</span> <span class="op">&lt;</span>strnlen_asm<span class="op">(</span>char const<span class="op">*,</span> unsigned long<span class="op">)+</span><span class="bn">0x14</span><span class="op">&gt;</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>    subq<span class="op">.</span>l <span class="op">#</span><span class="dv">1</span><span class="op">,%</span>a0</span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>    move<span class="op">.</span>l <span class="op">%</span>a0<span class="op">,%</span>fp<span class="fu">@</span><span class="er">(</span><span class="op">-</span><span class="dv">4</span><span class="op">)</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>    move<span class="op">.</span>l <span class="op">%</span>d0<span class="op">,%</span>fp<span class="fu">@</span><span class="er">(</span><span class="dv">12</span><span class="op">)</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>    move<span class="op">.</span>l <span class="op">%</span>fp<span class="fu">@</span><span class="er">(</span><span class="op">-</span><span class="dv">4</span><span class="op">),%</span>d0</span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>    <span class="bu">sub</span><span class="op">.</span>l <span class="op">%</span>fp<span class="fu">@</span><span class="er">(</span><span class="dv">8</span><span class="op">),%</span>d0</span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>    unlk <span class="op">%</span>fp</span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>    rts</span></code></pre></div>
<div class="sourceCode" id="cb4"><pre
class="sourceCode asm"><code class="sourceCode fasm"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>strnlen<span class="op">(</span>char const<span class="op">*,</span> unsigned long<span class="op">):</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    linkw <span class="op">%</span>fp<span class="op">,#-</span><span class="dv">4</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    move<span class="op">.</span>l <span class="op">%</span>fp<span class="fu">@</span><span class="er">(</span><span class="dv">8</span><span class="op">),%</span>fp<span class="fu">@</span><span class="er">(</span><span class="op">-</span><span class="dv">4</span><span class="op">)</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    bras <span class="dv">5</span><span class="er">a</span> <span class="op">&lt;</span>strnlen<span class="op">(</span>char const<span class="op">*,</span> unsigned long<span class="op">)+</span><span class="bn">0x28</span><span class="op">&gt;</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    move<span class="op">.</span>l <span class="op">%</span>fp<span class="fu">@</span><span class="er">(</span><span class="op">-</span><span class="dv">4</span><span class="op">),%</span>d0</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    move<span class="op">.</span>l <span class="op">%</span>d0<span class="op">,%</span>d1</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    addq<span class="op">.</span>l <span class="op">#</span><span class="dv">1</span><span class="op">,%</span>d1</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>    move<span class="op">.</span>l <span class="op">%</span>d1<span class="op">,%</span>fp<span class="fu">@</span><span class="er">(</span><span class="op">-</span><span class="dv">4</span><span class="op">)</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    movea<span class="op">.</span>l <span class="op">%</span>d0<span class="op">,%</span>a0</span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>    moveb <span class="op">%</span>a0<span class="fu">@</span><span class="er">,</span><span class="op">%</span>d0</span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>    seq <span class="op">%</span>d0</span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>    negb <span class="op">%</span>d0</span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>    beqs <span class="dv">5</span><span class="er">a</span> <span class="op">&lt;</span>strnlen<span class="op">(</span>char const<span class="op">*,</span> unsigned long<span class="op">)+</span><span class="bn">0x28</span><span class="op">&gt;</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>    subq<span class="op">.</span>l <span class="op">#</span><span class="dv">1</span><span class="op">,%</span>fp<span class="fu">@</span><span class="er">(</span><span class="op">-</span><span class="dv">4</span><span class="op">)</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>    bras <span class="dv">6</span><span class="er">e</span> <span class="op">&lt;</span>strnlen<span class="op">(</span>char const<span class="op">*,</span> unsigned long<span class="op">)+</span><span class="bn">0x3c</span><span class="op">&gt;</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>    move<span class="op">.</span>l <span class="op">%</span>fp<span class="fu">@</span><span class="er">(</span><span class="dv">12</span><span class="op">),%</span>d0</span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>    move<span class="op">.</span>l <span class="op">%</span>d0<span class="op">,%</span>d1</span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>    subq<span class="op">.</span>l <span class="op">#</span><span class="dv">1</span><span class="op">,%</span>d1</span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>    move<span class="op">.</span>l <span class="op">%</span>d1<span class="op">,%</span>fp<span class="fu">@</span><span class="er">(</span><span class="dv">12</span><span class="op">)</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a>    tstl <span class="op">%</span>d0</span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a>    sne <span class="op">%</span>d0</span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a>    negb <span class="op">%</span>d0</span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a>    bnes <span class="dv">3</span><span class="er">e</span> <span class="op">&lt;</span>strnlen<span class="op">(</span>char const<span class="op">*,</span> unsigned long<span class="op">)+</span><span class="bn">0xc</span><span class="op">&gt;</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a>    move<span class="op">.</span>l <span class="op">%</span>fp<span class="fu">@</span><span class="er">(</span><span class="op">-</span><span class="dv">4</span><span class="op">),%</span>d0</span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true" tabindex="-1"></a>    <span class="bu">sub</span><span class="op">.</span>l <span class="op">%</span>fp<span class="fu">@</span><span class="er">(</span><span class="dv">8</span><span class="op">),%</span>d0</span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true" tabindex="-1"></a>    unlk <span class="op">%</span>fp</span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true" tabindex="-1"></a>    rts</span></code></pre></div>
<p>However, as soon as we up the optimization for the C version (this
time at <code>-O2</code>), the code looks much better:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode asm"><code class="sourceCode fasm"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>strnlen<span class="op">(</span>char const<span class="op">*,</span> unsigned long<span class="op">)</span> <span class="op">[</span>clone <span class="op">.</span>constprop<span class="op">.</span><span class="dv">0</span><span class="op">]:</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">lea</span> <span class="dv">0</span> <span class="op">&lt;</span>strnlen<span class="op">(</span>char const<span class="op">*,</span> unsigned long<span class="op">)</span> <span class="op">[</span>clone <span class="op">.</span>constprop<span class="op">.</span><span class="dv">0</span><span class="op">]&gt;,%</span>a0</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    tstb <span class="op">%</span>a0<span class="fu">@</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    beqs <span class="dv">14</span> <span class="op">&lt;</span>strnlen<span class="op">(</span>char const<span class="op">*,</span> unsigned long<span class="op">)</span> <span class="op">[</span>clone <span class="op">.</span>constprop<span class="op">.</span><span class="dv">0</span><span class="op">]+</span><span class="bn">0x14</span><span class="op">&gt;</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    addq<span class="op">.</span>l <span class="op">#</span><span class="dv">1</span><span class="op">,%</span>a0</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>    cmpa<span class="op">.</span>l <span class="op">#</span><span class="dv">0</span><span class="op">,%</span>a0</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>    bnes <span class="dv">6</span> <span class="op">&lt;</span>strnlen<span class="op">(</span>char const<span class="op">*,</span> unsigned long<span class="op">)</span> <span class="op">[</span>clone <span class="op">.</span>constprop<span class="op">.</span><span class="dv">0</span><span class="op">]+</span><span class="bn">0x6</span><span class="op">&gt;</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>    move<span class="op">.</span>l <span class="op">%</span>a0<span class="op">,%</span>d0</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>    subi<span class="op">.</span>l <span class="op">#</span><span class="dv">0</span><span class="op">,%</span>d0</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>    rts</span></code></pre></div>
<p>But the assembly version also improves.</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode asm"><code class="sourceCode fasm"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>strnlen_asm<span class="op">(</span>char const<span class="op">*,</span> unsigned long<span class="op">)</span> <span class="op">[</span>clone <span class="op">.</span>constprop<span class="op">.</span><span class="dv">0</span><span class="op">]</span> <span class="op">[</span>clone <span class="op">.</span>isra<span class="op">.</span><span class="dv">0</span><span class="op">]:</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">lea</span> <span class="dv">0</span> <span class="op">&lt;</span>strnlen<span class="op">(</span>char const<span class="op">*,</span> unsigned long<span class="op">)</span> <span class="op">[</span>clone <span class="op">.</span>constprop<span class="op">.</span><span class="dv">0</span><span class="op">]&gt;,%</span>a0</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>       R_68K_32 <span class="op">.</span>rodata<span class="op">.</span>str1<span class="op">.</span><span class="dv">1</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>    move<span class="op">.</span>q <span class="op">#</span><span class="dv">8</span><span class="op">,%</span>d0</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>    subq<span class="op">.</span>l <span class="op">#</span><span class="dv">1</span><span class="op">,%</span>d0</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>    bcss <span class="dv">30</span> <span class="op">&lt;</span>strnlen_asm<span class="op">(</span>char const<span class="op">*,</span> unsigned long<span class="op">)</span> <span class="op">[</span>clone <span class="op">.</span>constprop<span class="op">.</span><span class="dv">0</span><span class="op">]</span> <span class="op">[</span>clone <span class="op">.</span>isra<span class="op">.</span><span class="dv">0</span><span class="op">]+</span><span class="bn">0x12</span><span class="op">&gt;</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>    tstb <span class="op">%</span>a0<span class="fu">@</span><span class="er">+</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>    bnes <span class="dv">26</span> <span class="op">&lt;</span>strnlen_asm<span class="op">(</span>char const<span class="op">*,</span> unsigned long<span class="op">)</span> <span class="op">[</span>clone <span class="op">.</span>constprop<span class="op">.</span><span class="dv">0</span><span class="op">]</span> <span class="op">[</span>clone <span class="op">.</span>isra<span class="op">.</span><span class="dv">0</span><span class="op">]+</span><span class="bn">0x8</span><span class="op">&gt;</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>    subq<span class="op">.</span>l <span class="op">#</span><span class="dv">1</span><span class="op">,%</span>a0</span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>    rts</span></code></pre></div>
<h2 id="but-what-about-at--o3">But what about at <code>-O3</code>?</h2>
<p>However, the real changes happens at <code>-O3</code> which has very
aggressive inlining: let’s say our program is:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> </span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> n <span class="op">=</span> strnlen_asm<span class="op">(</span><span class="st">&quot;hello&quot;</span><span class="op">,</span> <span class="dv">8</span><span class="op">);</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> c <span class="op">=</span> strnlen<span class="op">(</span><span class="st">&quot;hello&quot;</span><span class="op">,</span> <span class="dv">8</span><span class="op">);</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> n <span class="op">+</span> c<span class="op">;</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>What’s the resulting assembly when compiled at <code>-O3</code>?</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode asm"><code class="sourceCode fasm"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="fu">main:</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">lea</span> <span class="op">.</span>LC0<span class="op">,%</span>a0 <span class="op">|</span> <span class="op">&lt;</span> this provides <span class="op">%</span>a0 as the first arg</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>    moveq <span class="op">#</span><span class="dv">8</span><span class="op">,%</span>d0 <span class="op">|</span> <span class="op">&lt;</span> <span class="op">and</span> <span class="dv">8</span> as the second arg</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>#APP <span class="op">|</span> <span class="op">&lt;</span> this is the start of the assembly version</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>| 5 &quot;test<span class="op">.</span>c<span class="st">&quot; 1</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>1:     subq<span class="op">.</span>l  <span class="op">#</span><span class="dv">1</span><span class="op">,%</span>d0</span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>       jcs     <span class="fl">2</span><span class="bn">f</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>       tst<span class="op">.</span>b   <span class="op">(%</span>a0<span class="op">)+</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>       <span class="cf">jne</span>     <span class="bn">1b</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>       subq<span class="op">.</span>l  <span class="op">#</span><span class="dv">1</span><span class="op">,%</span>a0</span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>2:</span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>| 0 &quot;&quot; 2</span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>#NO_APP <span class="op">|</span> <span class="op">&lt;</span> this is the end of the assembly version</span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>    move<span class="op">.</span>l <span class="op">%</span>a0<span class="op">,%</span>d0 <span class="op">|</span> <span class="op">&lt;</span> this stores the result in <span class="op">%</span>d0</span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>    <span class="bu">sub</span><span class="op">.</span>l <span class="op">#.</span>LC0<span class="op">-</span><span class="dv">5</span><span class="op">,%</span>d0 <span class="op">|</span> the var c gets folded into the sub<span class="op">.</span>l to add <span class="fl">5.</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a>    rts</span></code></pre></div>
<p>You’ll note <code>lea</code> to <code>move.l</code> are the assembly
version. So, the C code itself is folded into a constant
<code>5</code>.</p>
<p>In this case, the C version is much better than the assembly
version.</p>
<p>The problem is visibility. The assembly code <strong>can not</strong>
be optimized past what is provided inline + its dependencies (loads in
and stores out). Thus, the optimized assembly version <strong>can
never</strong> be optimized past this:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode asm"><code class="sourceCode fasm"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>    <span class="bu">lea</span> <span class="op">.</span>LC0<span class="op">,%</span>a0</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>    moveq <span class="op">#</span><span class="dv">8</span><span class="op">,%</span>d0</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>1:     subq<span class="op">.</span>l  <span class="op">#</span><span class="dv">1</span><span class="op">,%</span>d0</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>       jcs     <span class="fl">2</span><span class="bn">f</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>       tst<span class="op">.</span>b   <span class="op">(%</span>a0<span class="op">)+</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>       <span class="cf">jne</span>     <span class="bn">1b</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>       subq<span class="op">.</span>l  <span class="op">#</span><span class="dv">1</span><span class="op">,%</span>a0</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>2:</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>    move<span class="op">.</span>l <span class="op">%</span>a0<span class="op">,%</span>d0</span></code></pre></div>
<p>Whereas for the C version, we saw it could range from pretty bad code
to a constant which is folded into a previous instruction, which is as
optimal as can be.</p>
<h2 id="why-this-matters">Why this matters</h2>
<p>This problem comes up a lot in areas other than OS programming – for
a database, you could choose to have a static query plan for a given
query. Since query plans are generally chosen dynamically for a given
query, this gives you stable performance + less overhead per query
because there’s no overhead in having to choose a given query plan.
However, you give up future optimizations – if there’s a new version of
your database that can optimize your query, you’ll lose out on that –
and for databases, this can be much more than a 100x improvement, that
you get for free just by upgrading, that you can’t get with static query
plans.</p>
<p>For compilers, JITs work their magic by having visibility into
running code. If a JIT has to run code that it does not have visibility
into, to maintain correctness, it <strong>must not</strong> optimize
that code in any way. Thus, any optimizing program that has no
visibility into the code it runs <strong>can never</strong> optimize the
program at all, lest it break correctness. Thus, in language design,
there’s a fundamental tension between higher-level and lower-level
constructs. Lower-level constructs are easier to optimize now, because
they’re closer to the machine. Higher-level constructs may have some
overhead now. In the future, however, higher-level constructs may do
better than lower-level constructs – because they can provide the
compiler with more visibility and thus more chances for optimization.
Thus, languages that are higher level tend to do better over time –
think Lisp vs. COBOL – Lisp was much higher level and had much more
overhead at the time, but compilers can optimize most of it away
now.</p>
<p>Declarative languages, like CSS, SQL, and prolog, will probably never
die – the user offloads the complexity of their tasks to the language
implementer, and grants them higher visibility which let the runtime
choose creative paths toward optimization.</p>
<p>Maybe we should all be writing Haskell.</p>]]></description>
</item>
<item>
<title>Writing a VM</title>
<pubDate>Sat, 20 Jul 2024 15:45:44 +0000</pubDate>
<guid>https://blog/writing-a-vm.html</guid>
<description><![CDATA[<p>I promised a while back to learn compilers in
earnest – the programs that turn your high-level code into the low-level
bits that your computer can execute.</p>
<p>I wrote up a few tree-walk interpreters – they would tokenize the
programming language provided, parse it, and then execute the AST
itself, executing the code.</p>
<p>Tree-walk interpreters work pretty well for the most part – they’re
easier to write, and have great introspection (each node has all the
info it needs). But it didn’t really scratch my itch of going all the
way to the metal.</p>
<p>If I write an assembly file to return the number 10, I would
write:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode asm"><code class="sourceCode fasm"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>.globl main</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="fu">main:</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="bu">mov</span> <span class="op">$</span><span class="bn">10</span><span class="op">,</span> <span class="op">%</span><span class="kw">rax</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">ret</span></span></code></pre></div>
<p>I can compile that output:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> gcc test.s <span class="at">-o</span> a.out</span></code></pre></div>
<p>And <code>objdump -d</code> the generated file:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> objdump <span class="at">-d</span> a.out</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="ex">0000000000401106</span> <span class="op">&lt;</span>main<span class="op">&gt;</span>:</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>  <span class="ex">401106:</span>   48 c7 c0 0a 00 00 00    mov    <span class="va">$0</span>xa,%rax</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  <span class="ex">40110d:</span>   c3                      ret</span></code></pre></div>
<p>So our instructions are encoded as
<code>48 c7 c0 0a 00 00 00 c3</code> as bytes.</p>
<p><code>mov $10 %rax</code> corresponds to
<code>48 c7 c0 0a 00 00 00</code>, and <code>ret</code> turns into
<code>c3</code>.</p>
<p>So, our “high-level” assembly that we wrote is turned into those
bytes, and the computer can read those bytes and execute them.</p>
<p>A tree-walk interpreter stops before serializing and deserializing
instructions – it runs the instructions from in-memory, so there’s no
need to dump the state to disk.</p>
<p>To be fair, interpreters have a way to dump the tree that they’re
executing to disk, like running this command:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> clang <span class="at">-Xclang</span> <span class="at">-ast-dump</span><span class="op">=</span>json <span class="at">-fsyntax-only</span> <span class="at">-Wno-visibility</span> test.c</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="co"># emitted JSON here.</span></span></code></pre></div>
<p>So we’d like to do that, by turning our instruction stream from those
high level instructions into bytes, and then being able to read those
bytes back and execute the program from binary.</p>
<p>The way I did was sketching out a VM with a set amount of
instructions. Each instruction would be the first byte (so I had a cap
of 256 instructions), and then the following bytes would be the
arguments.</p>
<p>Next, I had to handle the arity of each instruction. If you have say
<code>mov $10, %rax</code> and <code>mov %rbx, %rax</code>, these have
to be encoded as two distinct instructions – one is an immediate to
register move, and the other is a register to register move, even though
they’re both called <code>mov</code> in the written assembly.</p>
<p>So, I ended up with some 25 instructions, and each instruction would
slurp up the bytes it wanted from a binary, or serialize to those bytes,
and then voila, as long as you had a VM that could take those bytes and
return them to the assembly instructions, you could write any program
you wanted.</p>
<p>An example program, which would print 10 and then exit would look
like this in assembly:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode asm"><code class="sourceCode fasm"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>putreg <span class="dv">10</span> R0</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>printreg R0</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="cf">ret</span></span></code></pre></div>
<p>I could then encode that file as binary:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> cargo r <span class="at">-q</span> <span class="at">--</span> <span class="at">-e</span> print.asm <span class="op">&gt;</span> out.bin</span></code></pre></div>
<p>And look at its contents:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> xxd out.bin</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="ex">00000000:</span> 010a 0000 0900 00                        .......</span></code></pre></div>
<p>And run it from the binary format.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ex">cargo</span> r <span class="at">-q</span> <span class="at">--</span> <span class="at">-d</span> out.bin</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="ex">10</span></span></code></pre></div>
<p>So the program went all the way from the assembly itself, to bytes,
and then was run properly by the VM.</p>
<p>If you’d like to take a look at the VM code on github I’ve linked it
here.</p>
<p><a href="https://github.com/takashiidobe/vm">VM Code</a></p>
<p>Next step – writing a high level language that can emit the bytecode,
so I can go all the way from a high-level language to the bare
metal.</p>]]></description>
</item>
<item>
<title>10 More Predictions</title>
<pubDate>Mon, 11 Mar 2024 12:48:55 +0000</pubDate>
<guid>https://blog/10-more-predictions.html</guid>
<description><![CDATA[<p>Five years ago, in 2019, I made 10 predictions
for the next 10 years (so 2029).</p>
<p>Let’s see how they turned out, halfway through in 2024.</p>
<p>I’ll grade myself out of 10 points for each prediction based on how
good they’re looking at the moment.</p>
<p>Here’s the list:</p>
<ol type="1">
<li>Self-driving cars will still be two years out</li>
</ol>
<p>This one is still true. By self-driving, I meant take a nap as the
driver and leave your life in the hands of your car. Two years out was a
jab at some indefinite future, which I think is also true – people are
still gunning for self-driving cars, but it’ll most likely take longer
than expected. This prediction is looking good, we’ll see in 2029.</p>
<p>Verdict: 10 points.</p>
<ol start="2" type="1">
<li>Rust will become a top 10 language in popularity</li>
</ol>
<p>By 2019, Rust was the most admired language on stack overflow’s
developer survey for four years. In 2024, it’s won that title nine times
in a row. No easy feat, given the amount of programming languages in
common use.</p>
<p>Currently, Rust is the 17th most popular language according to the
TIOBE index, and it has quite a ways to go to crack the top 10. But it’s
got momentum for sure.</p>
<p>Verdict: 5 points.</p>
<ol start="3" type="1">
<li>WebAssembly will kill JavaScript and Desktop Apps</li>
</ol>
<p>In 2019, webassembly was hyped as freeing us from having to write our
front-ends in javascript, but also bringing the browser sandbox with
extra security to the desktop. It had a lot of hype. Five years later,
however, there hasn’t been much progress. Maybe something will change,
but this one is not looking good – few people have replaced their
electron usage with WASM sandboxed apps, and wasm is still struggling by
committee. We’ll see.</p>
<p>Verdict: 2 points.</p>
<ol start="4" type="1">
<li>JSON will be replaced with a Typed Transfer Protocol</li>
</ol>
<p>This is the prediction I regret the most. First of all, protobuf was
already somewhat popular at the time, and there were other protocols
that were typed transfer protocols. On the other hand, it’s gutsy. JSON
had been the interface between the frontend and backend since XHR
requests, so seeing it replaced with something else like it replaced XML
would be an interesting bet. Regardless, this one isn’t looking good
either.</p>
<p>Verdict: 0 points.</p>
<ol start="5" type="1">
<li>Functional Programming will finally become popular</li>
</ol>
<p>By 2019, most languages had adopted functional programming features –
Rust was a popular language that married idioms that allowed for
low-level control and functional programming in a tasteful way, Swift,
Kotlin, and Typescript have all improved mobile and web development with
their adoption of functional programming features as well. But I meant
this prediction to be: We’d all be using languages that were FP first,
like Elixir, Clojure, OCaml, Haskell, etc. It seems like programming
languages are adopting FP features (as they always have) but the
community at large is not using FP languages for development (more than
they used to, at least), so this one is also an easy grade.</p>
<p>Verdict: 0 points.</p>
<ol start="6" type="1">
<li>Microservice hype will wear off</li>
</ol>
<p>In 2019, at the hype of low interest rates, hiring became widespread
and microservice architecture spread like wildfire. At some size of
company, I think it’s inevitable to have lots of services, but that
doesn’t mean every team gets its own set of services, like microservices
implies. In 2024, with interest rates being closer to 4%, companies have
cut hiring and the microservice fad has gone down in hype, with
companies favoring more monolithic approaches to web development. I’m
not sure if it’ll continue on (this is like betting that interest rates
will stay at 4%+ until 2029) but since the hype has worn off once, I’m
assuming it could do so again.</p>
<p>Verdict: 8 points.</p>
<ol start="7" type="1">
<li>Facebook will no longer be a top 10 company</li>
</ol>
<p>(I should’ve been more specific, in my mind I was thinking top 10
American company by market cap)</p>
<p>In 2019, some people (myself included) were seeing Facebook as a one
trick pony. They had three services (Facebook, WhatsApp, Instagram), of
which they bought two, that were overindexed in social media (which was
waning in popularity at the time), and only relied on ad revenue.
Basically, if social media becomes less popular, then Facebook will go
down.</p>
<p>Zuckerberg understood this pretty well, so in 2021, Facebook decided
to change its name to Meta and go all-in on VR technology. This failed
pretty miserably, with Meta’s stock price tanking in response. It’s back
now, but Meta is currently 6th in market cap for American companies and
could be pushed out from the top 10 by some upstarts. We’ll see.</p>
<p>Verdict: 5 points.</p>
<ol start="8" type="1">
<li>An AI startup will become this decade’s hottest startup</li>
</ol>
<p>In 2019, AI was not as hyped as it was, but in 2022, when OpenAI
released Chatgpt, things changed forever. In my opinion, OpenAI
currently holds the title of “hottest startup”, so I think this one was
right, within 3 years.</p>
<p>Verdict: 10 points.</p>
<ol start="9" type="1">
<li>Blockchain will be this decade’s beanie babies</li>
</ol>
<p>Basically every blockchain outside of Bitcoin and Ethereum are
totally useless, just as they were in 2019. So, they haven’t really
become more popular or less popular in 5 years. Easy grade.</p>
<p>Verdict: 0 points.</p>
<ol start="10" type="1">
<li>You and I will host our apps on a new cloud provider (read. not
AWS)</li>
</ol>
<p>I still hate configuring AWS, but with Azure and GCP fumbling the
ball to try and take market share, and AWS releasing more fundamental
services, AWS has maintained its position as market leader. I don’t see
myself (or a lot of other big companies) hosting their software on any
other cloud. This one is also easy to score.</p>
<p>Verdict: 0 points.</p>]]></description>
</item>
<item>
<title>How fast are computers these days</title>
<pubDate>Tue, 16 Jan 2024 13:50:36 +0000</pubDate>
<guid>https://blog/how-fast-are-computers-these-days.html</guid>
<description><![CDATA[<p>I’ve been doing a lot of reading about
distributed systems, but I’ve never known how fast hardware goes these
days. Some common advice like “I/O is slow” or “system calls are slow”
might not matter that much, depending on the performance requirements of
the system that’s using them.</p>
<p>General performance numbers are useful for building distributed
systems – let’s say you have a system with 1PB of data and you want to
backup all that data to one node, where you can write to disk at 1GB/s.
How long does it take to back up the whole node? That would take about
10 days to complete (1PB / 1GB) is 1M, and 1M seconds is about 10 days.
If we were using HDDs from 20 years ago instead of SSDs, where writes
might be closer to 40MB/s, it would take closer to 250 days, which is
really crazy.</p>
<p>Armed with this information, we might say a total outage cannot
happen, or we carefully design the system to partition the data so
backups can happen in parallel, where if we have 1000 nodes, then our 10
day backup might take 10 / 1000 days, or closer to 90 seconds.</p>
<p>For a twist, I decided to benchmark my phone (a Samsung S10) vs my
personal laptop (a Framework laptop with a 12th gen intel i5-1240p
processor, 32GB of DDR4-3200 RAM, and a 2TB Western Digital SN750). The
S10 has a value of about $200 used these days, and the laptop about
$1000. So, we can also see how much money it would cost to build a
system using these parts (although I assume building a system with NUCs
or the like would be much more cost efficient), we can get a ballpark
estimation of how much certain distributed systems would cost to build.
As well, I’ll put down my guesses for how fast I thought each benchmark
would be for my phone and my laptop, and see how far off I was. In the
end, we’ll discuss some in the wild systems and see how feasible it
would be to build them.</p>
<h2 id="http-servers">HTTP Servers</h2>
<p>The communication layer of a service might use HTTP. Thus, I wanted
to benchmark a “hello world” HTTP service to see how fast a networked
service could run, given it does no work.</p>
<p>I assumed my laptop would run about 100k req/s, with around 10
microsecond latency, and my phone would do around 10k req/s, with 100
microsecond latency.</p>
<p>Try to guess how fast each device was:</p>
<p>The computer had these results:</p>
<pre><code>Running 5s test @ http://localhost:3000
  256 goroutine(s) running concurrently
975712 requests in 4.929485946s, 105.15MB read
Requests/sec:       197933.82
Transfer/sec:       21.33MB
Avg Req Time:       1.293361ms
Fastest Request:    21.095µs
Slowest Request:    67.116949ms
Number of Errors:   0</code></pre>
<p>And the phone:</p>
<pre><code>Running 5s test @ http://localhost:3000
  32 goroutine(s) running concurrently
107649 requests in 4.909044953s, 11.29MB read
Requests/sec:       21928.71
Transfer/sec:       2.30MB
Avg Req Time:       1.459274ms
Fastest Request:    85.677µs
Slowest Request:    48.922239ms
Number of Errors:   0</code></pre>
<p>The laptop had about 200k req/s and the phone had about 20k req/s.
Both were about twice as fast as I expected.</p>
<p>So, if we had to create a “Hello world” server and reach 1M req/s, it
would take 50 phones or 5 laptops. The 50 phones would cost $10000, and
the 5 laptops would cost about $5000. Computers are cheaper.</p>
<h2 id="redis">Redis</h2>
<p>What if we put a cache in front of our servers? How fast could it
respond?</p>
<p>Since redis is single-threaded and in-memory, it should have similar
numbers to the HTTP server.</p>
<p>I would assume that it would perform the same as the HTTP servers,
since they’d be doing about the same amount of work: ~200k req/s for the
laptop and ~20k req/s for the phone.</p>
<p>The laptop ran at ~200k for read, write, ping.</p>
<p>The phone ran at ~40k req/s for read, write, ping.</p>
<p>Pretty good – if we could hold our dataset in memory, we could
respond with 200k req/s.</p>
<h2 id="sqlite">Sqlite</h2>
<p>We’ll need a database to store our data. Let’s say we use sqlite, and
benchmark it, using row sizes of 1000B.</p>
<p>I assume that we can write about 50k/second rows on the laptop and
10k rows/second on the phone.</p>
<p>The laptop:</p>
<p>Batching 1000 writes at a time:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> ./sqlite-bench <span class="at">-batch-count</span> 1000 <span class="at">-batch-size</span> 1000 <span class="at">-row-size</span> 1000 <span class="at">-journal-mode</span> wal <span class="at">-synchronous</span> normal ./bench.db</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="ex">Inserts:</span>   1000000 rows</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="ex">Elapsed:</span>   7.824s</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="ex">Rate:</span>      127817.265 insert/sec</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="ex">File</span> size: 1026584576 bytes</span></code></pre></div>
<p>Writing 1 row at a time:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> ./sqlite-bench <span class="at">-batch-count</span> 1000000 <span class="at">-batch-size</span> 1 <span class="at">-row-size</span> 1000 <span class="at">-journal-mode</span> wal <span class="at">-synchronous</span> normal ./bench.db</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="ex">Inserts:</span>   1000000 rows</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="ex">Elapsed:</span>   43.839s</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="ex">Rate:</span>      22810.910 insert/sec</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="ex">File</span> size: 1026584576 bytes</span></code></pre></div>
<p>The phone:</p>
<p>Batching 1000 writes at a time:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> ./sqlite-bench <span class="at">-batch-count</span> 1000 <span class="at">-batch-size</span> 1000 <span class="at">-row-size</span> 1000 <span class="at">-journal-mode</span> wal <span class="at">-synchronous</span> normal ./bench.db</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="ex">Inserts:</span> 1000000 rows</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="ex">Elapsed:</span> 66.006s</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="ex">Rate:</span> 15150.53 insert/sec</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="ex">File</span> size: 1026584576 bytes</span></code></pre></div>
<p>Writing 1 row at a time:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> ./sqlite-bench <span class="at">-batch-count</span> 1000000 <span class="at">-batch-size</span> 1 <span class="at">-row-size</span> 1000 <span class="at">-journal-mode</span> wal <span class="at">-synchronous</span> normal ./bench.db</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="ex">Inserts:</span>   1000000 rows</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="ex">Elapsed:</span>   200.473s</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="ex">Rate:</span>      4884.369 insert/sec</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="ex">File</span> size: 1026584576 bytes</span></code></pre></div>
<p>Here we see the phone’s weakness – its disk. Inserting row by row,
the phone only can write 5k rows/s, whereas the computer can do about
20k rows/s, probably due to the phone having a flash disk and the
computer having an SSD.</p>
<h2 id="disk">Disk</h2>
<p>Since the sqlite bench uncovered the weakness of the phone’s disk,
lets test out some numbers for the file system:</p>
<p>I decided to benchmark sequential reads + writes for both and with
fsync for the writes. Since I used <code>fio</code> as my tool, and it
supports <code>io_uring</code>, I gave that a shot on my laptop. Android
doesn’t support <code>io_uring</code> for security reasons, so I only
ran <code>io_uring</code> on the computer.</p>
<p>I’d expect about 4GB/s read and 3GB/s write on the computer (since
that’s what the SSD is rated at) and maybe 1GB/s read and 200MB/s write
for the phone?</p>
<p>The numbers looked like this, with a blocksize of 1MB and running 8
jobs in parallel, which seemed to be the best, throughput wise:</p>
<p>Computer:</p>
<table>
<colgroup>
<col style="width: 31%" />
<col style="width: 9%" />
<col style="width: 8%" />
<col style="width: 9%" />
<col style="width: 10%" />
<col style="width: 32%" />
</colgroup>
<thead>
<tr>
<th>job name</th>
<th>p50</th>
<th>p90</th>
<th>p99</th>
<th>p99.99</th>
<th>throughput</th>
</tr>
</thead>
<tbody>
<tr>
<td>sync sequential read</td>
<td>113μs</td>
<td>5014μs</td>
<td>33424μs</td>
<td>37487μs</td>
<td>3387MB/s</td>
</tr>
<tr>
<td>sync sequential write - fsync</td>
<td>169μs</td>
<td>529μs</td>
<td>1319μs</td>
<td>333448μs</td>
<td>2830MB/s</td>
</tr>
<tr>
<td>sync sequential write + fsync</td>
<td>775μs</td>
<td>1090μs</td>
<td>1369μs</td>
<td>2147μs</td>
<td>1714MB/s</td>
</tr>
<tr>
<td>sync readwrite - fsync</td>
<td>204μs</td>
<td>416μs</td>
<td>865μs</td>
<td>14222μs</td>
<td>Read: 2556MB/s Write: 2665MB/s</td>
</tr>
<tr>
<td>sync readwrite + fsync</td>
<td>416μs</td>
<td>832μs</td>
<td>2769μs</td>
<td>9372μs</td>
<td>Read: 1052MB/s Write: 1093MB/s</td>
</tr>
</tbody>
</table>
<p>Phone:</p>
<p>With a blocksize of 256k and running 8 jobs in parallel:</p>
<table>
<colgroup>
<col style="width: 31%" />
<col style="width: 9%" />
<col style="width: 9%" />
<col style="width: 9%" />
<col style="width: 10%" />
<col style="width: 32%" />
</colgroup>
<thead>
<tr>
<th>job name</th>
<th>p50</th>
<th>p90</th>
<th>p99</th>
<th>p99.99</th>
<th>throughput</th>
</tr>
</thead>
<tbody>
<tr>
<td>sync sequential read</td>
<td>1549μs</td>
<td>4490μs</td>
<td>4752μs</td>
<td>22152μs</td>
<td>866MB/s</td>
</tr>
<tr>
<td>sync sequential write - fsync</td>
<td>18482μs</td>
<td>39584μs</td>
<td>89654μs</td>
<td>109577μs</td>
<td>100MB/s</td>
</tr>
<tr>
<td>sync sequential write + fsync</td>
<td>510μs</td>
<td>865μs</td>
<td>1729μs</td>
<td>1860μs</td>
<td>86.3MB/s</td>
</tr>
<tr>
<td>sync readwrite - fsync</td>
<td>314μs</td>
<td>1926μs</td>
<td>41681μs</td>
<td>41681μs</td>
<td>Read: 77.4MB/s Write: 75.5MB/s</td>
</tr>
<tr>
<td>sync readwrite + fsync</td>
<td>379μs</td>
<td>717μs</td>
<td>10421μs</td>
<td>10421μs</td>
<td>Read: 38.5MB/s Write: 41.4MB/s</td>
</tr>
</tbody>
</table>
<p>The phone was substantially slower than I expected.</p>
<h2 id="hashing">Hashing</h2>
<p>I was expecting about 400MB/s hashing on the laptop and about 100MB/s
hashing on the phone for a non-cryptographic hash, and ~40MB/s for a
cryptographic hash on a laptop, and 10MB/s on a phone.</p>
<p>Laptop:</p>
<ul>
<li>sha3-256: 56.14 MiB/sec</li>
<li>md5: 404.15 MiB/sec</li>
<li>sha1: 432.36 MiB/sec</li>
<li>xxhash: 1827.80 MiB/sec</li>
<li>murmur3: 1826.07 MiB/sec</li>
<li>jhash: 1542.84 MiB/sec</li>
<li>fnv: 3720.28 MiB/sec</li>
<li>crc32c: 4682.73 MiB/sec</li>
</ul>
<p>Phone:</p>
<ul>
<li>sha3-256: 217.77 MiB/sec</li>
<li>md5: 391.14 MiB/sec</li>
<li>sha1: 334.32 MiB/sec</li>
<li>xxhash: 2037.18 MiB/sec</li>
<li>murmur3: 1328.81 MiB/sec</li>
<li>jhash: 1754.98 MiB/sec</li>
<li>fnv: 2928.83 MiB/sec</li>
<li>crc32c: 14255.49 MiB/sec</li>
</ul>
<p>I could not have been more wrong.</p>
<p>The phone hashes very quickly compared to the laptop, maybe because
of some hardware instructions?</p>
<h2 id="networks">Networks</h2>
<p>The Computer can support 2.5Gbit/s ethernet, and the phone can
support 2000Mb/s DL and 316Mb/s UL, which is pretty fast, even faster
than disk, so network probably won’t be the bottleneck.</p>
<h2 id="talking-about-systems">Talking about Systems</h2>
<p>With some numbers to work with, let’s talk about some famous products
and their requirements.</p>
<h3 id="google-search">Google Search</h3>
<p>In 2006, according to <a
href="http://googlesystem.blogspot.com/2006/09/how-much-data-does-google-store.html">Source</a>,
the google search engine contained about 850TB of information.</p>
<p>Assuming google search needs to handle 100k requests/second, and each
request would return 4KB of data, our bandwidth requirement would be
400MB/s. That’s feasible to handle on a few laptops.</p>
<p>Assuming that we didn’t have an index at all. We would need to
somehow read 850TB of data per request – even with a sequential read
speed of ~3GB/s, each request would take 3 days of compute time to
complete. Since we have to handle 100k reads a second, and each request
takes 3 days of compute time, in one second we would need to spend 866
years of compute time to serve reads. One second of requests would also
require 100,000 computers * the amount of seconds in three days, or
about 250,000, for 2.5B computers required to serve google search. At
$800/computer, this would be $2.5T, 1/10th the GDP of the US. Crazy.</p>
<p>However, if the computer only needed to search a gigabyte of data on
disk to fetch a result, since a laptop’s SSD can read about 3GB/s
sequentially, even having to search on disk for 100MB would take 30ms.
Even worse would be the computer requirement – each machine would only
be able to handle 30 req/s, so 3,000 laptops would be required at any
given time to serve all search requests.</p>
<p>If we can lower the seeking on disk to only 1MB, we could handle
3,000 req/s, and only require 30 laptops – so having a fast index
matters a lot. It would be even better if we could search in RAM, where
memory throughput is closer to 25GB/s. If the entire index was in-memory
and needed to read 1MB of data, each laptop would be able to handle
25,000 req/s, and we’d only need 4 laptops.</p>
<h3 id="amazon-s3">Amazon S3</h3>
<p>According to <a
href="https://www.allthingsdistributed.com/2023/07/building-and-operating-a-pretty-big-storage-system.html">Source</a>
Amazon S3 holds 280 trillion objects, and handles about 100 million
req/s. S3 sends 125 billion events per day (1.25M req/s), and S3 handles
4 billion checksum computations per second.</p>
<p>Assuming that’s 80M reads and 20M writes, each of 1MB, that would
involve 80TB/s of reads, and 20TB/s of writes. For the disk usage alone,
you’d need ~7,000 laptops to handle the writes, and ~27,000 laptops to
handle the reads every second. But assuming we use 2.5Gb internet, at
~300MB/s, we’d need 10 times that amount, or 70,000 laptops to handle
the writes and 270,000 laptops for the reads.</p>
<p>For the hashing, assuming each hash is over 1MB of data, would
require hashing 4PB/s of data. Using xxhash at 2GB/s would require
2,000,000 laptops to just hash the data. Servers can hash xxhash data at
over 100GB/s, so I assume amazon uses those to reduce the computer
requirement to a modest less than 400,000.</p>
<h2 id="conclusion">Conclusion</h2>
<p>While going through this I learned a lot about how fast my computers
are – they can handle hosting lots of services. Also, computers are
really cheap – an 8GB RAM, 80GB SSD instance on hetzner is ~$5/month,
and the equivalent NUC would cost ~$100 to own, and these can handle
thousands of requests per second at the very least, more than enough for
the large majority of services.</p>]]></description>
</item>
<item>
<title>Writing a Small Search Engine</title>
<pubDate>Thu, 27 Jul 2023 11:20:52 +0000</pubDate>
<guid>https://blog/writing-a-small-search-engine.html</guid>
<description><![CDATA[<p>Today we’re going to write a small search
engine in ~70 lines of code:</p>
<pre><code>$ cloc --quiet src/main.rs

github.com/AlDanial/cloc v 1.90  T=0.00 s (271.8 files/s, 22288.4 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Rust                             1             12              1             69
-------------------------------------------------------------------------------</code></pre>
<p>The implementation leans on using a few dependencies from crates.io,
so let’s fetch those first.</p>
<p>Initialize a new rust project:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ex">cargo</span> new tinysearch</span></code></pre></div>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">cargo</span> add anyhow</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="ex">cargo</span> add bincode</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="ex">cargo</span> add glob</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="ex">cargo</span> add patricia_tree <span class="at">--features</span><span class="op">=</span>serde</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="ex">cargo</span> add serde <span class="at">--features</span><span class="op">=</span>derive</span></code></pre></div>
<p>With that, your Cargo.toml should have this for its dependencies.</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode toml"><code class="sourceCode toml"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">[dependencies]</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="dt">anyhow</span> <span class="op">=</span> <span class="st">&quot;1.0.70&quot;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="dt">bincode</span> <span class="op">=</span> <span class="st">&quot;1.3.3&quot;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="dt">glob</span> <span class="op">=</span> <span class="st">&quot;0.3.1&quot;</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="dt">patricia_tree</span> <span class="op">=</span> <span class="op">{ </span><span class="dt">version</span><span class="op"> =</span> <span class="st">&quot;0.5.7&quot;</span><span class="op">, </span><span class="dt">features</span><span class="op"> =</span> <span class="op">[</span><span class="st">&quot;serde&quot;</span><span class="op">] }</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="dt">serde</span> <span class="op">=</span> <span class="op">{ </span><span class="dt">version</span><span class="op"> =</span> <span class="st">&quot;1.0.160&quot;</span><span class="op">, </span><span class="dt">features</span><span class="op"> =</span> <span class="op">[</span><span class="st">&quot;derive&quot;</span><span class="op">] }</span></span></code></pre></div>
<p>Anyhow is used as <code>box&lt;dyn Error&gt;</code>, so it’s not
really necessary, but it’s nice to not have to write.</p>
<p>Bincode is used for serialization and deserialization to disk for
data structures. We’ll need this to store the search index on disk and
fetch it when we do a search.</p>
<p>Glob is for making glob queries, like <code>src/**/*.rs</code> to
fetch all rust files recursively under the <code>src</code>
directory.</p>
<p>Patricia tree is a trie data structure, that has the same ADT as a
map or set. Since this is a trie, and not a hashmap or btree, if there
are redundant prefixes, they are compressed on disk. Since we’re
serializing and deserializing text, which tends to be somewhat
redundant, this potentially saves a lot of memory compared to using a
hash-based or normal tree-based structure.</p>
<p>Serde is used to serialize the tree onto disk and deserialize it, for
bincode.</p>
<h2 id="index-implementation">Index Implementation</h2>
<p>Given the explanation above, your mental model to populate the index
should be something like this:</p>
<ol type="1">
<li>Initialize Trie</li>
<li>Fill Trie with some data (how?)</li>
<li>Save Trie to disk</li>
</ol>
<p>And to read from it:</p>
<ol type="1">
<li>Read the file containing Trie to disk</li>
<li>Deserialize it back to a Trie</li>
<li>Query the trie</li>
</ol>
<p>The open question is what data we fill the Trie with. Obviously it
would be something from our dataset, but if we make a mapping from each
word to its document name, then this works, but we can only query one
word at a time.</p>
<p>With this index, a query like “ice cream” would only be able to query
for either “ice” or “cream”.</p>
<p>To keep it simple, we’ll choose an indexing strategy referred to as
n-grams. N-grams indexes windows of length n. Our previous strategy of
indexing every word could be considered a 1-gram. We’ll go with 5, since
that allows us to query up to 5 words. I queried my search history and
found that 5 word queries just about covers my querying needs.</p>
<p>Let’s get coding:</p>
<p>in <code>src/main.rs</code>, add the imports required:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">std::</span><span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="pp">collections::</span><span class="op">{</span>BTreeSet<span class="op">,</span> HashSet<span class="op">},</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    <span class="pp">fs::</span><span class="op">{</span><span class="kw">self</span><span class="op">,</span> File<span class="op">},</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    <span class="pp">io::</span><span class="op">{</span><span class="bu">BufRead</span><span class="op">,</span> BufReader<span class="op">},</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">patricia_tree::</span>PatriciaMap<span class="op">;</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">anyhow::</span><span class="dt">Result</span><span class="op">;</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">glob::</span>glob<span class="op">;</span></span></code></pre></div>
<p>Next, let’s create the cli flags with the two commands we’ll support,
<code>search</code> and <code>index</code>.</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> main() <span class="op">-&gt;</span> <span class="dt">Result</span><span class="op">&lt;</span>()<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">use</span> <span class="pp">std::env::</span>args<span class="op">;</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">match</span> args()<span class="op">.</span>len() <span class="op">{</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>        <span class="dv">0</span> <span class="op">=&gt;</span> <span class="pp">eprintln!</span>(<span class="st">&quot;Please provide a top level command of search or index&quot;</span>)<span class="op">,</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>        _ <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>            <span class="kw">let</span> arguments<span class="op">:</span> <span class="dt">Vec</span><span class="op">&lt;</span>_<span class="op">&gt;</span> <span class="op">=</span> args()<span class="op">.</span>collect()<span class="op">;</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> args()<span class="op">.</span>len() <span class="op">&gt;</span> <span class="dv">2</span> <span class="op">&amp;&amp;</span> arguments[<span class="dv">1</span>] <span class="op">==</span> <span class="st">&quot;index&quot;</span> <span class="op">{</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>                <span class="kw">let</span> _ <span class="op">=</span> index(<span class="op">&amp;</span>arguments[<span class="dv">2</span>])<span class="op">;</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> args()<span class="op">.</span>len() <span class="op">&gt;</span> <span class="dv">2</span> <span class="op">&amp;&amp;</span> arguments[<span class="dv">1</span>] <span class="op">==</span> <span class="st">&quot;search&quot;</span> <span class="op">{</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>                <span class="kw">let</span> _ <span class="op">=</span> search(<span class="op">&amp;</span>arguments[<span class="dv">2</span><span class="op">..</span>])<span class="op">;</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>                <span class="pp">eprintln!</span>(<span class="st">&quot;Please provide a top level command of search or index&quot;</span>)<span class="op">;</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a>    <span class="cn">Ok</span>(())</span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Next, the function definition and matching patterns based on it.</p>
<p>This code matches a regex provided (like “**/*.rs”), and then returns
all matching files. We then iterate through the files and process each
line.</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> index(pattern<span class="op">:</span> <span class="op">&amp;</span><span class="dt">str</span>) <span class="op">-&gt;</span> <span class="dt">Result</span><span class="op">&lt;</span>()<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> mytrie <span class="op">=</span> <span class="pp">PatriciaMap::</span><span class="kw">default</span>()<span class="op">;</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> entry <span class="kw">in</span> glob(pattern)<span class="op">?</span> <span class="op">{</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> path <span class="op">=</span> entry<span class="op">?;</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> path <span class="op">=</span> path<span class="op">.</span>to_string_lossy()<span class="op">.</span>to_string()<span class="op">;</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> f <span class="op">=</span> <span class="pp">File::</span>open(<span class="op">&amp;*</span>path)<span class="op">?;</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> f <span class="op">=</span> <span class="pp">BufReader::</span>new(f)<span class="op">;</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> line <span class="kw">in</span> f<span class="op">.</span>lines() <span class="op">{</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>            <span class="co">// process each line, the next step</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Next, we want to do something for each line. First, split each line
on whitespace to get a list of words. A production worthy search engine
would do stemming and remove unnecessary punctuation here, but we won’t
worry about that. Finally, we’ll use the <a
href="https://doc.rust-lang.org/std/primitive.slice.html#method.windows"><code>windows</code></a>
function on slices, to return arrays with the length provided (5) across
the entire list. This is n-grams in a nutshell.</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> line <span class="op">=</span> line<span class="op">?;</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> s<span class="op">:</span> <span class="dt">String</span> <span class="op">=</span> line<span class="op">.</span>to_string()<span class="op">;</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> words<span class="op">:</span> <span class="dt">Vec</span><span class="op">&lt;</span><span class="dt">String</span><span class="op">&gt;</span> <span class="op">=</span> s<span class="op">.</span>split_whitespace()<span class="op">.</span>map(<span class="op">|</span>s<span class="op">|</span> s<span class="op">.</span>to_owned())<span class="op">.</span>collect()<span class="op">;</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> word_windows<span class="op">:</span> <span class="dt">Vec</span><span class="op">&lt;</span><span class="dt">String</span><span class="op">&gt;</span> <span class="op">=</span> words<span class="op">.</span>windows(<span class="dv">5</span>)<span class="op">.</span>map(<span class="op">|</span>w<span class="op">|</span> w<span class="op">.</span>join(<span class="st">&quot; &quot;</span>))<span class="op">.</span>collect()<span class="op">;</span></span></code></pre></div>
<p>With that, the next thing to do is to put each five gram as a key to
the trie, with a value of the path of the document. If that fivegram
already exists, we just add the new path to the list of paths it
matches.</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> fivegram <span class="kw">in</span> <span class="op">&amp;</span>word_windows <span class="op">{</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">!</span>mytrie<span class="op">.</span>contains_key(fivegram) <span class="op">{</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> <span class="kw">mut</span> set <span class="op">=</span> <span class="pp">BTreeSet::</span><span class="kw">default</span>()<span class="op">;</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>        set<span class="op">.</span>insert(path<span class="op">.</span>clone())<span class="op">;</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>        mytrie<span class="op">.</span>insert(fivegram<span class="op">,</span> set)<span class="op">;</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>        <span class="co">// we know that the trie contains fivegram, so unwrapping is safe.</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> <span class="kw">mut</span> set<span class="op">:</span> BTreeSet<span class="op">&lt;</span><span class="dt">String</span><span class="op">&gt;</span> <span class="op">=</span> mytrie<span class="op">.</span>get(fivegram)<span class="op">.</span>unwrap()<span class="op">.</span>to_owned()<span class="op">;</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>        set<span class="op">.</span>insert(path<span class="op">.</span>clone())<span class="op">;</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>        mytrie<span class="op">.</span>insert(fivegram<span class="op">,</span> set)<span class="op">;</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Finally, we serialize it and write it to a file:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> encoded <span class="op">=</span> <span class="pp">bincode::</span>serialize(<span class="op">&amp;</span>mytrie)<span class="op">?;</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="pp">fs::</span>write(<span class="st">&quot;./data.index&quot;</span><span class="op">,</span> encoded)<span class="op">?;</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="cn">Ok</span>(())</span></code></pre></div>
<h2 id="searching-our-index">Searching our Index</h2>
<p>Fortunately, searching is easier. We take our list of search words,
and then index into the map. Then, we grab the matches, and we append
them to all matching paths. At the end, we print them out.</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> search(search_words<span class="op">:</span> <span class="op">&amp;</span>[<span class="dt">String</span>]) <span class="op">-&gt;</span> <span class="dt">Result</span><span class="op">&lt;</span>()<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> needle<span class="op">:</span> <span class="dt">Vec</span><span class="op">&lt;</span><span class="dt">u8</span><span class="op">&gt;</span> <span class="op">=</span> <span class="op">{</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> joined <span class="op">=</span> search_words<span class="op">.</span>join(<span class="st">&quot; &quot;</span>)<span class="op">;</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>        joined<span class="op">.</span>bytes()<span class="op">.</span>collect()</span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> index_file <span class="op">=</span> <span class="pp">File::</span>open(<span class="st">&quot;./data.index&quot;</span>)<span class="op">?;</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> decoded<span class="op">:</span> PatriciaMap<span class="op">&lt;</span>BTreeSet<span class="op">&lt;</span><span class="dt">String</span><span class="op">&gt;&gt;</span> <span class="op">=</span> <span class="pp">bincode::</span>deserialize_from(index_file)<span class="op">?;</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> matches<span class="op">:</span> <span class="dt">Vec</span><span class="op">&lt;</span>_<span class="op">&gt;</span> <span class="op">=</span> decoded<span class="op">.</span>iter_prefix(<span class="op">&amp;</span>needle)<span class="op">.</span>collect()<span class="op">;</span></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> paths<span class="op">:</span> HashSet<span class="op">&lt;</span>_<span class="op">&gt;</span> <span class="op">=</span> <span class="pp">HashSet::</span><span class="kw">default</span>()<span class="op">;</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> (_key<span class="op">,</span> val) <span class="kw">in</span> <span class="op">&amp;</span>matches <span class="op">{</span></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a>        paths<span class="op">.</span>extend(val<span class="op">.</span>iter())<span class="op">;</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a>    <span class="pp">println!</span>(<span class="st">&quot;{:#?}&quot;</span><span class="op">,</span> paths)<span class="op">;</span></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a>    <span class="cn">Ok</span>(())</span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And with that, we’re done. A simple search engine.</p>
<h2 id="giving-it-a-test-run">Giving it a test run</h2>
<p>I indexed my notes:</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ex">cargo</span> r <span class="at">-q</span> <span class="at">--</span> index <span class="st">&quot;data/**/*.md&quot;</span></span></code></pre></div>
<p>And then searched for mentions of distributed systems:</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ex">cargo</span> r <span class="at">-q</span> <span class="at">--</span> search distributed system</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="kw">{</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;data/books/system-design-interview-an-insiders-guide-volume-2/distributed-message-queue.md&quot;</span><span class="ex">,</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;data/books/designing-data-intensive-applications/distributed-systems-trouble.md&quot;</span><span class="ex">,</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a><span class="kw">}</span></span></code></pre></div>
<p>Not so bad for 70 lines of code.</p>]]></description>
</item>
<item>
<title>Hardware for development</title>
<pubDate>Wed, 24 May 2023 00:00:51 +0000</pubDate>
<guid>https://blog/hardware.html</guid>
<description><![CDATA[<p>A list of the hardware I’ve used throughout the
years.</p>
<h2 id="current">Current</h2>
<ul>
<li>Framework Laptop: (2022-) $1200
<ul>
<li>i5-1240P processor</li>
<li>32GB DDR4-3200 RAM</li>
<li>2TB NVMe SSD</li>
</ul></li>
<li>Galaxy S10: (2019-) $599
<ul>
<li>Octa-core (1x2.84 GHz Kryo 485 &amp; 3x2.42 GHz Kryo 485 &amp;
4x1.78 GHz Kryo 485)</li>
<li>8GB RAM</li>
<li>128GB SSD</li>
</ul></li>
<li>Remarkable 2: (2020-) $499
<ul>
<li>512MB RAM</li>
<li>8GB SSD</li>
</ul></li>
</ul>
<h2 id="past">Past</h2>
<ul>
<li>Macbook Pro 2017: (2017-2022) $1199
<ul>
<li>2.3GHz dual-core Intel Core i5</li>
<li>8GB LPDDR3-2133MHz RAM</li>
<li>128GB NVMe SSD</li>
</ul></li>
<li>LG Phoenix 2: (2017-2019) $39
<ul>
<li>Qualcomm® MSM8909 1.3 GHz Quad-Core</li>
<li>1.5GB RAM</li>
<li>16GB Flash</li>
</ul></li>
<li>Huawei G7 Plus: (2015-2017) $180
<ul>
<li>Octa-core (4x1.5 GHz Cortex-A53 &amp; 4x1.2 GHz Cortex-A53)</li>
<li>3GB RAM</li>
<li>16GB Flash</li>
</ul></li>
<li>iTouch 4th Gen: (2011-2015) $399
<ul>
<li>ARM Cortex-A8 Apple A4 800 MHz</li>
<li>256MB RAM</li>
<li>16GB Flash</li>
</ul></li>
<li>Windows 7 Desktop: (2009-2013) $450
<ul>
<li>AMD Athlon 64 2.4GHz</li>
<li>4GB DDR3-1066 RAM</li>
<li>1TB HDD</li>
</ul></li>
<li>Windows 2000 Server: (2002-2009) $1500
<ul>
<li>Intel Xeon 1.7GHz</li>
<li>1GB DDR3 RAM</li>
<li>32GB HDD</li>
</ul></li>
<li>Windows 98 Desktop: (1998-2002) $2000
<ul>
<li>300MHz Intel Processor</li>
<li>128MB RAM</li>
<li>4GB HDD</li>
</ul></li>
</ul>]]></description>
</item>
<item>
<title>Offline Rust</title>
<pubDate>Tue, 23 May 2023 22:29:34 +0000</pubDate>
<guid>https://blog/offline-rust.html</guid>
<description><![CDATA[<p>Rust, and its respective package manager,
Cargo, easily allow for programming on the go. You can use
<code>sccache</code> to cache dependencies you’ve already downloaded, so
if you’ve already downloaded them, there’s no need to redownload them
for any other project you use the same dependency for. Sadly, that stops
short when you want to download a new dependency you’ve never downloaded
before. If you’re offline and don’t have that exact dependency cached,
you’re SOL. But we can do better, can’t we?</p>
<p>You probably already know that <code>crates.io</code> is a thin layer
over git. So, you can grep all the crates on it, download their source
code, and host your own local repository that acts as a stand-in for
crates.io. Luckily (if you have ~150GB to spare), there’s already a
project that has done that for us: <code>panamax</code>. After you
install it with <code>cargo (b)install panamax</code>, and initialize
some directory. I initialized one at <code>~/crates</code> with
<code>panamax init ~/crates</code>.</p>
<p>You’ll want to set your config up: I didn’t want to clone any
toolchains since I didn’t need them, so I only cloned down the crates: I
edited my <code>mirror.toml</code> inside the initialized repository to
be the following:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode toml"><code class="sourceCode toml"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">[mirror]</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="dt">retries</span> <span class="op">=</span> <span class="dv">5</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">[rustup]</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="dt">sync</span> <span class="op">=</span> <span class="cn">false</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">[crates]</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="dt">sync</span> <span class="op">=</span> <span class="cn">true</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="dt">download_threads</span> <span class="op">=</span> <span class="dv">64</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="dt">source</span> <span class="op">=</span> <span class="st">&quot;https://crates.io/api/v1/crates&quot;</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="dt">source_index</span> <span class="op">=</span> <span class="st">&quot;https://github.com/rust-lang/crates.io-index&quot;</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="dt">base_url</span> <span class="op">=</span> <span class="st">&quot;http://localhost:27428/crates&quot;</span></span></code></pre></div>
<p>And then I ran <code>panamax sync ~/crates</code> and waited for a
day for the internet to download all the crates.</p>
<p>Once that’s done, we have all the crates we need. Add these lines to
your cargo config (normally at <code>~/.cargo/config.toml)</code> to use
the new repository:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode toml"><code class="sourceCode toml"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">[source.panamax-sparse]</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="dt">registry</span> <span class="op">=</span> <span class="st">&quot;sparse+http://localhost:27428/index/&quot;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">[source.crates-io]</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="dt">replace-with</span> <span class="op">=</span> <span class="st">&quot;panamax-sparse&quot;</span></span></code></pre></div>
<p>Start up the server with
<code>panamax serve ~/crates --port=27428</code> and you’re ready to
code offline in rust.</p>
<p>For maintenance, I sync crates with
<code>panamax sync ~/crates</code> once a week with <code>systemd</code>
and that works for me.</p>]]></description>
</item>
<item>
<title>Writing Your own Libc in Rust</title>
<pubDate>Mon, 22 May 2023 12:58:02 +0000</pubDate>
<guid>https://blog/writing-your-own-libc-in-rust.html</guid>
<description><![CDATA[<p>A few posts ago, we wrote our own <a
href="./writing-your-own-libc.md">libc</a> in C. There was some inline
assembly required to call functions. Lots of languages can call
assembly, but since I mainly use rust, I decided to rewrite most of it
in rust, since there are some nice advantages.</p>
<p>First: <code>cfg</code> definitions are a lot easier to remember. I
can never remember if the <code>#ifdef</code> for linux is
<code>__LINUX__</code> or <code>linux</code> or <code>__linux__</code>,
or the <code>#ifdef</code>s for other platforms. Apple’s is also odd
(<code>__APPLE__</code>), and there are other <code>#ifdef</code>s for
targets: <code>TARGET_OS_IPHONE</code>
<code>TARGET_IPHONE_SIMULATOR</code> <code>TARGET_OS_MAC</code>, and
windows with <code>_WIN_32</code> and <code>_WIN_64</code>. With
android, there’s <code>__ANDROID__</code> and
<code>__ANDROID_API__</code> as well. Getting tired? Well, there’s also
all the architecture related ones, which there are hundreds of, and
they’re slightly different per compiler, so you have to know which
compiler you’re using to even define macros.</p>
<p>There are 3 main wrappers around cfgs which are easy to wrap your
head around. <code>not</code>, which is anything that doesn’t fit inside
the definition, like <code>#[cfg(not(target_arch = "x86_64")))]</code>
means anything that isn’t <code>x86_64</code>. There’s <code>any</code>,
which means for anything that matches an item in the list, like
<code>#[cfg(any(target_arch = "x86_64", target_arch = "i686"))]</code>
for <code>x86_64</code> or <code>i686</code>. There’s <code>all</code>,
which means that all items must match, like
<code>#[cfg(all(target_arch = "aarch64", target_os = "linux"))]</code>
means to only run on aarch64 linux.</p>
<p>Second: the inline <code>asm</code> syntax is much better. You have
three choices: <code>global_asm!</code>, which lets you write code
anywhere, like if you’d like to embed a string into your binary’s text
section, <code>asm!</code>, which goes in the code section, and
<code>llvm_asm!</code>, which is for llvm specific asm. You don’t have
to specify clobbers on x86_64, so the relevant <code>x86_64</code>
syscall code from C:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>asm <span class="dt">volatile</span> <span class="op">(</span>                                                    \</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;syscall</span><span class="sc">\n</span><span class="st">&quot;</span>                                                   \</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <span class="st">&quot;0&quot;</span><span class="op">(</span>_num<span class="op">)</span>                                                   \</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <span class="st">&quot;rcx&quot;</span><span class="op">,</span> <span class="st">&quot;r11&quot;</span><span class="op">,</span> <span class="st">&quot;memory&quot;</span><span class="op">,</span> <span class="st">&quot;cc&quot;</span>                                \</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
<p>In rust would look like this:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="pp">asm!</span>(</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;syscall&quot;</span><span class="op">,</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">in</span>(<span class="st">&quot;rax&quot;</span>) <span class="op">$</span>nr</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>)<span class="op">;</span></span></code></pre></div>
<p>Anyway, let’s get started.</p>
<h2 id="implementation">Implementation</h2>
<p>Create a new rust binary, and call it whatever you like. I called
mine <code>syscalls</code>.</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>cargo new syscalls</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>cd syscalls</span></code></pre></div>
<p>Open up <code>src/main.rs</code> and start off with importing the
standard assembly library.</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">std::arch::</span>asm<span class="op">;</span></span></code></pre></div>
<p>Next, since we’ll be supporting <code>linux</code>, with
<code>x86_64</code> <a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a> and <code>aarch64</code> <a
href="#fn2" class="footnote-ref" id="fnref2"
role="doc-noteref"><sup>2</sup></a>, we can force every other
architecture/OS mix to have a compiler error, so no one will miscompile
and have a runtime error.</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>cfg<span class="at">(</span>not<span class="at">(</span>all<span class="at">(</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    target_os <span class="op">=</span> <span class="st">&quot;linux&quot;</span><span class="op">,</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    any<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="op">,</span> target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="at">)))]</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="pp">compile_error!</span>(<span class="st">&quot;Only works on linux on aarch64 or x86_64&quot;</span>)<span class="op">;</span></span></code></pre></div>
<p>This is really helpful – no more running a library and wondering what
went wrong at runtime.</p>
<p>So, lets start off with the skeleton of the first syscall function,
<code>syscall0</code>. We’ll generate a function with the name of the
syscall, and the syscall’s number. We’ll make a compiler error to start
off with since we haven’t implemented anything yet.</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="pp">macro_rules!</span> syscall0 <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    (<span class="op">$</span>name<span class="op">:</span>ident<span class="op">,</span> <span class="op">$</span>nr<span class="op">:</span>expr) <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="kw">fn</span> $name() <span class="op">{</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>            <span class="kw">unsafe</span> <span class="op">{</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>                <span class="pp">compile_error!</span>(<span class="st">&quot;not implemented&quot;</span>)<span class="op">;</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="arm64">ARM64</h3>
<p>So we’ll start implementing syscalls in <code>ARM64</code> first.</p>
<p>Let’s look at an example of Hello World in ARM64 to familiarize
ourselves with syscalls in ARM64:</p>
<p>Taken from <a
href="https://peterdn.com/post/2020/08/22/hello-world-in-arm64-assembly/"
class="uri">https://peterdn.com/post/2020/08/22/hello-world-in-arm64-assembly/</a></p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode asm"><code class="sourceCode fasm"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>.<span class="bu">data</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>/* <span class="bu">Data</span> segment<span class="op">:</span> define our message string <span class="op">and</span> calculate its length<span class="op">.</span> <span class="op">*/</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="fu">msg:</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>    .ascii        <span class="st">&quot;Hello, ARM64!\n&quot;</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>len <span class="op">=</span> <span class="op">.</span> <span class="op">-</span> msg</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>.text</span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>/* Our application<span class="st">&#39;s entry point. */</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>.globl _start</span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a><span class="fu">_start:</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a>    /* <span class="cf">syscall</span> write<span class="op">(</span>int fd<span class="op">,</span> const void <span class="op">*</span>buf<span class="op">,</span> size_t count<span class="op">)</span> <span class="op">*/</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a>    <span class="bu">mov</span>     x0<span class="op">,</span> <span class="op">#</span><span class="dv">1</span>      <span class="op">/*</span> fd <span class="op">:=</span> STDOUT_FILENO <span class="op">*/</span></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a>    ldr     x1<span class="op">,</span> <span class="op">=</span>msg    <span class="op">/*</span> buf <span class="op">:=</span> msg <span class="op">*/</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a>    ldr     x2<span class="op">,</span> <span class="op">=</span>len    <span class="op">/*</span> count <span class="op">:=</span> len <span class="op">*/</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a>    <span class="bu">mov</span>     w8<span class="op">,</span> <span class="op">#</span><span class="dv">64</span>     <span class="op">/*</span> write is syscall <span class="op">#</span><span class="dv">64</span> <span class="op">*/</span></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true" tabindex="-1"></a>    svc     <span class="op">#</span><span class="dv">0</span>          <span class="op">/*</span> invoke syscall <span class="op">*/</span></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true" tabindex="-1"></a>    /* <span class="cf">syscall</span> exit<span class="op">(</span>int status<span class="op">)</span> <span class="op">*/</span></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true" tabindex="-1"></a>    <span class="bu">mov</span>     x0<span class="op">,</span> <span class="op">#</span><span class="dv">0</span>      <span class="op">/*</span> status <span class="op">:=</span> <span class="dv">0</span> <span class="op">*/</span></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true" tabindex="-1"></a>    <span class="bu">mov</span>     w8<span class="op">,</span> <span class="op">#</span><span class="dv">93</span>     <span class="op">/*</span> exit is syscall <span class="op">#</span><span class="dv">93</span> <span class="op">*/</span></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true" tabindex="-1"></a>    svc     <span class="op">#</span><span class="dv">0</span>          <span class="op">/*</span> invoke syscall <span class="op">*/</span></span></code></pre></div>
<p>To write, we first set <code>x0</code> to the number 1
(<code>#1</code>), to set our <code>fd</code> to stdout. Then, we move
the message to <code>x1</code>, which is write’s second argument, Then
we move the len to <code>x2</code>, which is write’s third argument,
Then we move the number 64 to <code>w8</code>, which is the syscall
number, And then we invoke the syscall with <code>svc</code> and the
number 0.</p>
<p>We do something similar for exit, just without moving any arguments
to <code>x1</code> or <code>x2</code>.</p>
<p>Let’s do that for our first syscall:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)]</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="pp">asm!</span>(</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;mov x0, #0&quot;</span><span class="op">,</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;svc #0&quot;</span><span class="op">,</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">in</span>(<span class="st">&quot;w8&quot;</span>) <span class="op">$</span>nr</span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>)<span class="op">;</span></span></code></pre></div>
<p>with <code>in("w8") $nr</code>, we can pass in our system call
number, represented by <code>$nr</code>, and rust will put it into
<code>w8</code> for us. This is equivalent to <code>mov w8 =$nr</code>,
but we don’t have to remember that syntax, as the rust compiler will
generate it for us.</p>
<p>As well, we’ll set the compiler errors for all architectures that
aren’t <code>aarch64</code> for now.</p>
<p>We repeat the following for the next 6 system calls, with
<code>x0-x5</code> being used as registers to pass in arguments.</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="pp">macro_rules!</span> syscall1 <span class="op">{</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>    (<span class="op">$</span>name<span class="op">:</span>ident<span class="op">,</span> <span class="op">$</span>nr<span class="op">:</span>expr) <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="kw">fn</span> $name(arg1<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;</span>) <span class="op">{</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>            <span class="kw">unsafe</span> <span class="op">{</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)]</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;mov x0, #0&quot;</span><span class="op">,</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;svc #0&quot;</span><span class="op">,</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;w8&quot;</span>) <span class="op">$</span>nr<span class="op">,</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x0&quot;</span>) arg1<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>not<span class="at">(</span>any<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)))]</span></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>                <span class="pp">compile_error!</span>(<span class="st">&quot;not implemented&quot;</span>)<span class="op">;</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true" tabindex="-1"></a><span class="pp">macro_rules!</span> syscall2 <span class="op">{</span></span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true" tabindex="-1"></a>    (<span class="op">$</span>name<span class="op">:</span>ident<span class="op">,</span> <span class="op">$</span>nr<span class="op">:</span>expr) <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true" tabindex="-1"></a>        <span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="kw">fn</span> $name(arg1<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg2<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;</span>) <span class="op">{</span></span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true" tabindex="-1"></a>            <span class="kw">unsafe</span> <span class="op">{</span></span>
<span id="cb9-22"><a href="#cb9-22" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)]</span></span>
<span id="cb9-23"><a href="#cb9-23" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb9-24"><a href="#cb9-24" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;mov x0, #0&quot;</span><span class="op">,</span></span>
<span id="cb9-25"><a href="#cb9-25" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;svc #0&quot;</span><span class="op">,</span></span>
<span id="cb9-26"><a href="#cb9-26" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;w8&quot;</span>) <span class="op">$</span>nr<span class="op">,</span></span>
<span id="cb9-27"><a href="#cb9-27" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x0&quot;</span>) arg1<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-28"><a href="#cb9-28" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x1&quot;</span>) arg2<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-29"><a href="#cb9-29" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb9-30"><a href="#cb9-30" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>not<span class="at">(</span>any<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)))]</span></span>
<span id="cb9-31"><a href="#cb9-31" aria-hidden="true" tabindex="-1"></a>                <span class="pp">compile_error!</span>(<span class="st">&quot;not implemented&quot;</span>)<span class="op">;</span></span>
<span id="cb9-32"><a href="#cb9-32" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb9-33"><a href="#cb9-33" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb9-34"><a href="#cb9-34" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-35"><a href="#cb9-35" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb9-36"><a href="#cb9-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-37"><a href="#cb9-37" aria-hidden="true" tabindex="-1"></a><span class="pp">macro_rules!</span> syscall3 <span class="op">{</span></span>
<span id="cb9-38"><a href="#cb9-38" aria-hidden="true" tabindex="-1"></a>    (<span class="op">$</span>name<span class="op">:</span>ident<span class="op">,</span> <span class="op">$</span>nr<span class="op">:</span>expr) <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb9-39"><a href="#cb9-39" aria-hidden="true" tabindex="-1"></a>        <span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="kw">fn</span> $name(arg1<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg2<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg3<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;</span>) <span class="op">{</span></span>
<span id="cb9-40"><a href="#cb9-40" aria-hidden="true" tabindex="-1"></a>            <span class="kw">unsafe</span> <span class="op">{</span></span>
<span id="cb9-41"><a href="#cb9-41" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)]</span></span>
<span id="cb9-42"><a href="#cb9-42" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb9-43"><a href="#cb9-43" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;mov x0, #0&quot;</span><span class="op">,</span></span>
<span id="cb9-44"><a href="#cb9-44" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;svc #0&quot;</span><span class="op">,</span></span>
<span id="cb9-45"><a href="#cb9-45" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;w8&quot;</span>) <span class="op">$</span>nr<span class="op">,</span></span>
<span id="cb9-46"><a href="#cb9-46" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x0&quot;</span>) arg1<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-47"><a href="#cb9-47" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x1&quot;</span>) arg2<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-48"><a href="#cb9-48" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x2&quot;</span>) arg3<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-49"><a href="#cb9-49" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb9-50"><a href="#cb9-50" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>not<span class="at">(</span>any<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)))]</span></span>
<span id="cb9-51"><a href="#cb9-51" aria-hidden="true" tabindex="-1"></a>                <span class="pp">compile_error!</span>(<span class="st">&quot;not implemented&quot;</span>)<span class="op">;</span></span>
<span id="cb9-52"><a href="#cb9-52" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb9-53"><a href="#cb9-53" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb9-54"><a href="#cb9-54" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-55"><a href="#cb9-55" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb9-56"><a href="#cb9-56" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-57"><a href="#cb9-57" aria-hidden="true" tabindex="-1"></a><span class="pp">macro_rules!</span> syscall4 <span class="op">{</span></span>
<span id="cb9-58"><a href="#cb9-58" aria-hidden="true" tabindex="-1"></a>    (<span class="op">$</span>name<span class="op">:</span>ident<span class="op">,</span> <span class="op">$</span>nr<span class="op">:</span>expr) <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb9-59"><a href="#cb9-59" aria-hidden="true" tabindex="-1"></a>        <span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="kw">fn</span> $name(arg1<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg2<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg3<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg4<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;</span>) <span class="op">{</span></span>
<span id="cb9-60"><a href="#cb9-60" aria-hidden="true" tabindex="-1"></a>            <span class="kw">unsafe</span> <span class="op">{</span></span>
<span id="cb9-61"><a href="#cb9-61" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)]</span></span>
<span id="cb9-62"><a href="#cb9-62" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb9-63"><a href="#cb9-63" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;mov x0, #0&quot;</span><span class="op">,</span></span>
<span id="cb9-64"><a href="#cb9-64" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;svc #0&quot;</span><span class="op">,</span></span>
<span id="cb9-65"><a href="#cb9-65" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;w8&quot;</span>) <span class="op">$</span>nr<span class="op">,</span></span>
<span id="cb9-66"><a href="#cb9-66" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x0&quot;</span>) arg1<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-67"><a href="#cb9-67" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x1&quot;</span>) arg2<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-68"><a href="#cb9-68" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x2&quot;</span>) arg3<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-69"><a href="#cb9-69" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x3&quot;</span>) arg4<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-70"><a href="#cb9-70" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb9-71"><a href="#cb9-71" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>not<span class="at">(</span>any<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)))]</span></span>
<span id="cb9-72"><a href="#cb9-72" aria-hidden="true" tabindex="-1"></a>                <span class="pp">compile_error!</span>(<span class="st">&quot;not implemented&quot;</span>)<span class="op">;</span></span>
<span id="cb9-73"><a href="#cb9-73" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb9-74"><a href="#cb9-74" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb9-75"><a href="#cb9-75" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-76"><a href="#cb9-76" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb9-77"><a href="#cb9-77" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-78"><a href="#cb9-78" aria-hidden="true" tabindex="-1"></a><span class="pp">macro_rules!</span> syscall5 <span class="op">{</span></span>
<span id="cb9-79"><a href="#cb9-79" aria-hidden="true" tabindex="-1"></a>    (<span class="op">$</span>name<span class="op">:</span>ident<span class="op">,</span> <span class="op">$</span>nr<span class="op">:</span>expr) <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb9-80"><a href="#cb9-80" aria-hidden="true" tabindex="-1"></a>        <span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="kw">fn</span> $name(arg1<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg2<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg3<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg4<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg5<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;</span>) <span class="op">{</span></span>
<span id="cb9-81"><a href="#cb9-81" aria-hidden="true" tabindex="-1"></a>            <span class="kw">unsafe</span> <span class="op">{</span></span>
<span id="cb9-82"><a href="#cb9-82" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)]</span></span>
<span id="cb9-83"><a href="#cb9-83" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb9-84"><a href="#cb9-84" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;mov x0, #0&quot;</span><span class="op">,</span></span>
<span id="cb9-85"><a href="#cb9-85" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;svc #0&quot;</span><span class="op">,</span></span>
<span id="cb9-86"><a href="#cb9-86" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;w8&quot;</span>) <span class="op">$</span>nr<span class="op">,</span></span>
<span id="cb9-87"><a href="#cb9-87" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x0&quot;</span>) arg1<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-88"><a href="#cb9-88" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x1&quot;</span>) arg2<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-89"><a href="#cb9-89" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x2&quot;</span>) arg3<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-90"><a href="#cb9-90" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x3&quot;</span>) arg4<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-91"><a href="#cb9-91" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x4&quot;</span>) arg5<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-92"><a href="#cb9-92" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb9-93"><a href="#cb9-93" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>not<span class="at">(</span>any<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)))]</span></span>
<span id="cb9-94"><a href="#cb9-94" aria-hidden="true" tabindex="-1"></a>                <span class="pp">compile_error!</span>(<span class="st">&quot;not implemented&quot;</span>)<span class="op">;</span></span>
<span id="cb9-95"><a href="#cb9-95" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb9-96"><a href="#cb9-96" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb9-97"><a href="#cb9-97" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-98"><a href="#cb9-98" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb9-99"><a href="#cb9-99" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-100"><a href="#cb9-100" aria-hidden="true" tabindex="-1"></a><span class="pp">macro_rules!</span> syscall6 <span class="op">{</span></span>
<span id="cb9-101"><a href="#cb9-101" aria-hidden="true" tabindex="-1"></a>    (<span class="op">$</span>name<span class="op">:</span>ident<span class="op">,</span> <span class="op">$</span>nr<span class="op">:</span>expr) <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb9-102"><a href="#cb9-102" aria-hidden="true" tabindex="-1"></a>        <span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="kw">fn</span> $name(arg1<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg2<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg3<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg4<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg5<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg6<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;</span>) <span class="op">{</span></span>
<span id="cb9-103"><a href="#cb9-103" aria-hidden="true" tabindex="-1"></a>            <span class="kw">unsafe</span> <span class="op">{</span></span>
<span id="cb9-104"><a href="#cb9-104" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)]</span></span>
<span id="cb9-105"><a href="#cb9-105" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb9-106"><a href="#cb9-106" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;mov x0, #0&quot;</span><span class="op">,</span></span>
<span id="cb9-107"><a href="#cb9-107" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;svc #0&quot;</span><span class="op">,</span></span>
<span id="cb9-108"><a href="#cb9-108" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;w8&quot;</span>) <span class="op">$</span>nr<span class="op">,</span></span>
<span id="cb9-109"><a href="#cb9-109" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x0&quot;</span>) arg1<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-110"><a href="#cb9-110" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x1&quot;</span>) arg2<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-111"><a href="#cb9-111" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x2&quot;</span>) arg3<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-112"><a href="#cb9-112" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x3&quot;</span>) arg4<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-113"><a href="#cb9-113" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x4&quot;</span>) arg5<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-114"><a href="#cb9-114" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x5&quot;</span>) arg6<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb9-115"><a href="#cb9-115" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb9-116"><a href="#cb9-116" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>not<span class="at">(</span>any<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)))]</span></span>
<span id="cb9-117"><a href="#cb9-117" aria-hidden="true" tabindex="-1"></a>                <span class="pp">compile_error!</span>(<span class="st">&quot;not implemented&quot;</span>)<span class="op">;</span></span>
<span id="cb9-118"><a href="#cb9-118" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb9-119"><a href="#cb9-119" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb9-120"><a href="#cb9-120" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-121"><a href="#cb9-121" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Note that the functions take <code>impl Into&lt;usize&gt;</code>, and
then the args are converted in the body of the function. That means that
the caller doesn’t have to <code>as usize</code> or
<code>try_into().unwrap()</code> if they don’t pass in a
<code>usize</code>, which is nice, as long as the argument is
convertable to a <code>usize</code>.</p>
<p>Finally, we’re ready to implement some system calls in ARM64!</p>
<p><code>exit</code> takes 0 arguments and has a syscall number of 93,
so we use <code>syscall0!</code> thusly:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)]</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="pp">syscall0!</span>(exit<span class="op">,</span> <span class="dv">93</span>)<span class="op">;</span></span></code></pre></div>
<p>And write takes 3 arguments, the <code>fd</code>, a string, and a
length, and it has a syscall number of 64, so we pass it in:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)]</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="pp">syscall3!</span>(write<span class="op">,</span> <span class="dv">64</span>)<span class="op">;</span></span></code></pre></div>
<p>And finally, we can write hello world:</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>    <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)]</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> string <span class="op">=</span> <span class="st">&quot;Hello ARM64</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">;</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> ptr <span class="op">=</span> string<span class="op">.</span>as_ptr() <span class="kw">as</span> <span class="dt">usize</span><span class="op">;</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> len <span class="op">=</span> string<span class="op">.</span>len()<span class="op">;</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>    write(<span class="dv">1usize</span><span class="op">,</span> ptr<span class="op">,</span> len)<span class="op">;</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>    exit()<span class="op">;</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><code>cargo run</code> your file to see <code>Hello ARM64</code> in
all its glory flash onto the screen.</p>
<p>Now we’re not done yet – let’s do the same for x86_64!</p>
<h3 id="x86_64">x86_64</h3>
<p>So for <code>x86</code>, <code>rax</code> takes in the system call
number, and then the registers are the following: <code>rdi</code>,
<code>rsi</code>, <code>rdx</code>, <code>r10</code>, <code>r9</code>,
<code>r8</code>.</p>
<p>So now we add in those to our syscall macros:</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="pp">macro_rules!</span> syscall0 <span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>    (<span class="op">$</span>name<span class="op">:</span>ident<span class="op">,</span> <span class="op">$</span>nr<span class="op">:</span>expr) <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="kw">fn</span> $name() <span class="op">{</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>            <span class="kw">unsafe</span> <span class="op">{</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)]</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;mov x0, #0&quot;</span><span class="op">,</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;svc #0&quot;</span><span class="op">,</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;w8&quot;</span>) <span class="op">$</span>nr</span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="at">)]</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;syscall&quot;</span><span class="op">,</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rax&quot;</span>) <span class="op">$</span>nr</span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>not<span class="at">(</span>any<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="op">,</span> target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="at">)))]</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a>                <span class="pp">compile_error!</span>(<span class="st">&quot;not implemented&quot;</span>)<span class="op">;</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true" tabindex="-1"></a><span class="pp">macro_rules!</span> syscall1 <span class="op">{</span></span>
<span id="cb13-24"><a href="#cb13-24" aria-hidden="true" tabindex="-1"></a>    (<span class="op">$</span>name<span class="op">:</span>ident<span class="op">,</span> <span class="op">$</span>nr<span class="op">:</span>expr) <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb13-25"><a href="#cb13-25" aria-hidden="true" tabindex="-1"></a>        <span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="kw">fn</span> $name(arg1<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;</span>) <span class="op">{</span></span>
<span id="cb13-26"><a href="#cb13-26" aria-hidden="true" tabindex="-1"></a>            <span class="kw">unsafe</span> <span class="op">{</span></span>
<span id="cb13-27"><a href="#cb13-27" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)]</span></span>
<span id="cb13-28"><a href="#cb13-28" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb13-29"><a href="#cb13-29" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;mov x0, #0&quot;</span><span class="op">,</span></span>
<span id="cb13-30"><a href="#cb13-30" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;svc #0&quot;</span><span class="op">,</span></span>
<span id="cb13-31"><a href="#cb13-31" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;w8&quot;</span>) <span class="op">$</span>nr<span class="op">,</span></span>
<span id="cb13-32"><a href="#cb13-32" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x0&quot;</span>) arg1<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-33"><a href="#cb13-33" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb13-34"><a href="#cb13-34" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="at">)]</span></span>
<span id="cb13-35"><a href="#cb13-35" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb13-36"><a href="#cb13-36" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;syscall&quot;</span><span class="op">,</span></span>
<span id="cb13-37"><a href="#cb13-37" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rax&quot;</span>) <span class="op">$</span>nr<span class="op">,</span></span>
<span id="cb13-38"><a href="#cb13-38" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rdi&quot;</span>) arg1<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-39"><a href="#cb13-39" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb13-40"><a href="#cb13-40" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>not<span class="at">(</span>any<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="op">,</span> target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="at">)))]</span></span>
<span id="cb13-41"><a href="#cb13-41" aria-hidden="true" tabindex="-1"></a>                <span class="pp">compile_error!</span>(<span class="st">&quot;not implemented&quot;</span>)<span class="op">;</span></span>
<span id="cb13-42"><a href="#cb13-42" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb13-43"><a href="#cb13-43" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-44"><a href="#cb13-44" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-45"><a href="#cb13-45" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb13-46"><a href="#cb13-46" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-47"><a href="#cb13-47" aria-hidden="true" tabindex="-1"></a><span class="pp">macro_rules!</span> syscall2 <span class="op">{</span></span>
<span id="cb13-48"><a href="#cb13-48" aria-hidden="true" tabindex="-1"></a>    (<span class="op">$</span>name<span class="op">:</span>ident<span class="op">,</span> <span class="op">$</span>nr<span class="op">:</span>expr) <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb13-49"><a href="#cb13-49" aria-hidden="true" tabindex="-1"></a>        <span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="kw">fn</span> $name(arg1<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg2<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;</span>) <span class="op">{</span></span>
<span id="cb13-50"><a href="#cb13-50" aria-hidden="true" tabindex="-1"></a>            <span class="kw">unsafe</span> <span class="op">{</span></span>
<span id="cb13-51"><a href="#cb13-51" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)]</span></span>
<span id="cb13-52"><a href="#cb13-52" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb13-53"><a href="#cb13-53" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;mov x0, #0&quot;</span><span class="op">,</span></span>
<span id="cb13-54"><a href="#cb13-54" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;svc #0&quot;</span><span class="op">,</span></span>
<span id="cb13-55"><a href="#cb13-55" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;w8&quot;</span>) <span class="op">$</span>nr<span class="op">,</span></span>
<span id="cb13-56"><a href="#cb13-56" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x0&quot;</span>) arg1<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-57"><a href="#cb13-57" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x1&quot;</span>) arg2<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-58"><a href="#cb13-58" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb13-59"><a href="#cb13-59" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="at">)]</span></span>
<span id="cb13-60"><a href="#cb13-60" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb13-61"><a href="#cb13-61" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;syscall&quot;</span><span class="op">,</span></span>
<span id="cb13-62"><a href="#cb13-62" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rax&quot;</span>) <span class="op">$</span>nr<span class="op">,</span></span>
<span id="cb13-63"><a href="#cb13-63" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rdi&quot;</span>) arg1<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-64"><a href="#cb13-64" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rsi&quot;</span>) arg2<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-65"><a href="#cb13-65" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb13-66"><a href="#cb13-66" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>not<span class="at">(</span>any<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="op">,</span> target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="at">)))]</span></span>
<span id="cb13-67"><a href="#cb13-67" aria-hidden="true" tabindex="-1"></a>                <span class="pp">compile_error!</span>(<span class="st">&quot;not implemented&quot;</span>)<span class="op">;</span></span>
<span id="cb13-68"><a href="#cb13-68" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb13-69"><a href="#cb13-69" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-70"><a href="#cb13-70" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-71"><a href="#cb13-71" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb13-72"><a href="#cb13-72" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-73"><a href="#cb13-73" aria-hidden="true" tabindex="-1"></a><span class="pp">macro_rules!</span> syscall3 <span class="op">{</span></span>
<span id="cb13-74"><a href="#cb13-74" aria-hidden="true" tabindex="-1"></a>    (<span class="op">$</span>name<span class="op">:</span>ident<span class="op">,</span> <span class="op">$</span>nr<span class="op">:</span>expr) <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb13-75"><a href="#cb13-75" aria-hidden="true" tabindex="-1"></a>        <span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="kw">fn</span> $name(arg1<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg2<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg3<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;</span>) <span class="op">{</span></span>
<span id="cb13-76"><a href="#cb13-76" aria-hidden="true" tabindex="-1"></a>            <span class="kw">unsafe</span> <span class="op">{</span></span>
<span id="cb13-77"><a href="#cb13-77" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)]</span></span>
<span id="cb13-78"><a href="#cb13-78" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb13-79"><a href="#cb13-79" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;mov x0, #0&quot;</span><span class="op">,</span></span>
<span id="cb13-80"><a href="#cb13-80" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;svc #0&quot;</span><span class="op">,</span></span>
<span id="cb13-81"><a href="#cb13-81" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;w8&quot;</span>) <span class="op">$</span>nr<span class="op">,</span></span>
<span id="cb13-82"><a href="#cb13-82" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x0&quot;</span>) arg1<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-83"><a href="#cb13-83" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x1&quot;</span>) arg2<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-84"><a href="#cb13-84" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x2&quot;</span>) arg3<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-85"><a href="#cb13-85" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb13-86"><a href="#cb13-86" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="at">)]</span></span>
<span id="cb13-87"><a href="#cb13-87" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb13-88"><a href="#cb13-88" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;syscall&quot;</span><span class="op">,</span></span>
<span id="cb13-89"><a href="#cb13-89" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rax&quot;</span>) <span class="op">$</span>nr<span class="op">,</span></span>
<span id="cb13-90"><a href="#cb13-90" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rdi&quot;</span>) arg1<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-91"><a href="#cb13-91" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rsi&quot;</span>) arg2<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-92"><a href="#cb13-92" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rdx&quot;</span>) arg3<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-93"><a href="#cb13-93" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb13-94"><a href="#cb13-94" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>not<span class="at">(</span>any<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="op">,</span> target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="at">)))]</span></span>
<span id="cb13-95"><a href="#cb13-95" aria-hidden="true" tabindex="-1"></a>                <span class="pp">compile_error!</span>(<span class="st">&quot;not implemented&quot;</span>)<span class="op">;</span></span>
<span id="cb13-96"><a href="#cb13-96" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb13-97"><a href="#cb13-97" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-98"><a href="#cb13-98" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-99"><a href="#cb13-99" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb13-100"><a href="#cb13-100" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-101"><a href="#cb13-101" aria-hidden="true" tabindex="-1"></a><span class="pp">macro_rules!</span> syscall4 <span class="op">{</span></span>
<span id="cb13-102"><a href="#cb13-102" aria-hidden="true" tabindex="-1"></a>    (<span class="op">$</span>name<span class="op">:</span>ident<span class="op">,</span> <span class="op">$</span>nr<span class="op">:</span>expr) <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb13-103"><a href="#cb13-103" aria-hidden="true" tabindex="-1"></a>        <span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="kw">fn</span> $name(arg1<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg2<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg3<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg4<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;</span>) <span class="op">{</span></span>
<span id="cb13-104"><a href="#cb13-104" aria-hidden="true" tabindex="-1"></a>            <span class="kw">unsafe</span> <span class="op">{</span></span>
<span id="cb13-105"><a href="#cb13-105" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)]</span></span>
<span id="cb13-106"><a href="#cb13-106" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb13-107"><a href="#cb13-107" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;mov x0, #0&quot;</span><span class="op">,</span></span>
<span id="cb13-108"><a href="#cb13-108" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;svc #0&quot;</span><span class="op">,</span></span>
<span id="cb13-109"><a href="#cb13-109" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;w8&quot;</span>) <span class="op">$</span>nr<span class="op">,</span></span>
<span id="cb13-110"><a href="#cb13-110" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x0&quot;</span>) arg1<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-111"><a href="#cb13-111" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x1&quot;</span>) arg2<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-112"><a href="#cb13-112" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x2&quot;</span>) arg3<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-113"><a href="#cb13-113" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x3&quot;</span>) arg4<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-114"><a href="#cb13-114" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb13-115"><a href="#cb13-115" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="at">)]</span></span>
<span id="cb13-116"><a href="#cb13-116" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb13-117"><a href="#cb13-117" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;syscall&quot;</span><span class="op">,</span></span>
<span id="cb13-118"><a href="#cb13-118" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rax&quot;</span>) <span class="op">$</span>nr<span class="op">,</span></span>
<span id="cb13-119"><a href="#cb13-119" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rdi&quot;</span>) arg1<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-120"><a href="#cb13-120" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rsi&quot;</span>) arg2<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-121"><a href="#cb13-121" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rdx&quot;</span>) arg3<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-122"><a href="#cb13-122" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;r10&quot;</span>) arg4<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-123"><a href="#cb13-123" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb13-124"><a href="#cb13-124" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>not<span class="at">(</span>any<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="op">,</span> target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="at">)))]</span></span>
<span id="cb13-125"><a href="#cb13-125" aria-hidden="true" tabindex="-1"></a>                <span class="pp">compile_error!</span>(<span class="st">&quot;not implemented&quot;</span>)<span class="op">;</span></span>
<span id="cb13-126"><a href="#cb13-126" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb13-127"><a href="#cb13-127" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-128"><a href="#cb13-128" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-129"><a href="#cb13-129" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb13-130"><a href="#cb13-130" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-131"><a href="#cb13-131" aria-hidden="true" tabindex="-1"></a><span class="pp">macro_rules!</span> syscall5 <span class="op">{</span></span>
<span id="cb13-132"><a href="#cb13-132" aria-hidden="true" tabindex="-1"></a>    (<span class="op">$</span>name<span class="op">:</span>ident<span class="op">,</span> <span class="op">$</span>nr<span class="op">:</span>expr) <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb13-133"><a href="#cb13-133" aria-hidden="true" tabindex="-1"></a>        <span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="kw">fn</span> $name(arg1<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg2<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg3<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg4<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg5<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;</span>) <span class="op">{</span></span>
<span id="cb13-134"><a href="#cb13-134" aria-hidden="true" tabindex="-1"></a>            <span class="kw">unsafe</span> <span class="op">{</span></span>
<span id="cb13-135"><a href="#cb13-135" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)]</span></span>
<span id="cb13-136"><a href="#cb13-136" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb13-137"><a href="#cb13-137" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;mov x0, #0&quot;</span><span class="op">,</span></span>
<span id="cb13-138"><a href="#cb13-138" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;svc #0&quot;</span><span class="op">,</span></span>
<span id="cb13-139"><a href="#cb13-139" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;w8&quot;</span>) <span class="op">$</span>nr<span class="op">,</span></span>
<span id="cb13-140"><a href="#cb13-140" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x0&quot;</span>) arg1<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-141"><a href="#cb13-141" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x1&quot;</span>) arg2<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-142"><a href="#cb13-142" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x2&quot;</span>) arg3<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-143"><a href="#cb13-143" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x3&quot;</span>) arg4<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-144"><a href="#cb13-144" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x4&quot;</span>) arg5<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-145"><a href="#cb13-145" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb13-146"><a href="#cb13-146" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="at">)]</span></span>
<span id="cb13-147"><a href="#cb13-147" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb13-148"><a href="#cb13-148" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;syscall&quot;</span><span class="op">,</span></span>
<span id="cb13-149"><a href="#cb13-149" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rax&quot;</span>) <span class="op">$</span>nr<span class="op">,</span></span>
<span id="cb13-150"><a href="#cb13-150" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rdi&quot;</span>) arg1<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-151"><a href="#cb13-151" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rsi&quot;</span>) arg2<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-152"><a href="#cb13-152" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rdx&quot;</span>) arg3<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-153"><a href="#cb13-153" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;r10&quot;</span>) arg4<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-154"><a href="#cb13-154" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;r9&quot;</span>) arg5<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-155"><a href="#cb13-155" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb13-156"><a href="#cb13-156" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>not<span class="at">(</span>any<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="op">,</span> target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="at">)))]</span></span>
<span id="cb13-157"><a href="#cb13-157" aria-hidden="true" tabindex="-1"></a>                <span class="pp">compile_error!</span>(<span class="st">&quot;not implemented&quot;</span>)<span class="op">;</span></span>
<span id="cb13-158"><a href="#cb13-158" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb13-159"><a href="#cb13-159" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-160"><a href="#cb13-160" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-161"><a href="#cb13-161" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb13-162"><a href="#cb13-162" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-163"><a href="#cb13-163" aria-hidden="true" tabindex="-1"></a><span class="pp">macro_rules!</span> syscall6 <span class="op">{</span></span>
<span id="cb13-164"><a href="#cb13-164" aria-hidden="true" tabindex="-1"></a>    (<span class="op">$</span>name<span class="op">:</span>ident<span class="op">,</span> <span class="op">$</span>nr<span class="op">:</span>expr) <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb13-165"><a href="#cb13-165" aria-hidden="true" tabindex="-1"></a>        <span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="kw">fn</span> $name(arg1<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg2<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg3<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg4<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg5<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;,</span> arg6<span class="op">:</span> <span class="kw">impl</span> <span class="bu">Into</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;</span>) <span class="op">{</span></span>
<span id="cb13-166"><a href="#cb13-166" aria-hidden="true" tabindex="-1"></a>            <span class="kw">unsafe</span> <span class="op">{</span></span>
<span id="cb13-167"><a href="#cb13-167" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="at">)]</span></span>
<span id="cb13-168"><a href="#cb13-168" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb13-169"><a href="#cb13-169" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;mov x0, #0&quot;</span><span class="op">,</span></span>
<span id="cb13-170"><a href="#cb13-170" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;svc #0&quot;</span><span class="op">,</span></span>
<span id="cb13-171"><a href="#cb13-171" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;w8&quot;</span>) <span class="op">$</span>nr<span class="op">,</span></span>
<span id="cb13-172"><a href="#cb13-172" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x0&quot;</span>) arg1<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-173"><a href="#cb13-173" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x1&quot;</span>) arg2<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-174"><a href="#cb13-174" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x2&quot;</span>) arg3<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-175"><a href="#cb13-175" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x3&quot;</span>) arg4<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-176"><a href="#cb13-176" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x4&quot;</span>) arg5<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-177"><a href="#cb13-177" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;x5&quot;</span>) arg6<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-178"><a href="#cb13-178" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb13-179"><a href="#cb13-179" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="at">)]</span></span>
<span id="cb13-180"><a href="#cb13-180" aria-hidden="true" tabindex="-1"></a>                <span class="pp">asm!</span>(</span>
<span id="cb13-181"><a href="#cb13-181" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;syscall&quot;</span><span class="op">,</span></span>
<span id="cb13-182"><a href="#cb13-182" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rax&quot;</span>) <span class="op">$</span>nr<span class="op">,</span></span>
<span id="cb13-183"><a href="#cb13-183" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rdi&quot;</span>) arg1<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-184"><a href="#cb13-184" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rsi&quot;</span>) arg2<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-185"><a href="#cb13-185" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;rdx&quot;</span>) arg3<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-186"><a href="#cb13-186" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;r10&quot;</span>) arg4<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-187"><a href="#cb13-187" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;r9&quot;</span>) arg5<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-188"><a href="#cb13-188" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">in</span>(<span class="st">&quot;r8&quot;</span>) arg6<span class="op">.</span>into()<span class="op">,</span></span>
<span id="cb13-189"><a href="#cb13-189" aria-hidden="true" tabindex="-1"></a>                )<span class="op">;</span></span>
<span id="cb13-190"><a href="#cb13-190" aria-hidden="true" tabindex="-1"></a>                <span class="at">#[</span>cfg<span class="at">(</span>not<span class="at">(</span>any<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;aarch64&quot;</span><span class="op">,</span> target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="at">)))]</span></span>
<span id="cb13-191"><a href="#cb13-191" aria-hidden="true" tabindex="-1"></a>                <span class="pp">compile_error!</span>(<span class="st">&quot;not implemented&quot;</span>)<span class="op">;</span></span>
<span id="cb13-192"><a href="#cb13-192" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb13-193"><a href="#cb13-193" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-194"><a href="#cb13-194" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-195"><a href="#cb13-195" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Finally, we’ll implement the system calls:</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="at">)]</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="pp">syscall0!</span>(exit<span class="op">,</span> <span class="dv">60</span>)<span class="op">;</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="at">)]</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a><span class="pp">syscall3!</span>(write<span class="op">,</span> <span class="dv">1</span>)<span class="op">;</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>    <span class="at">#[</span>cfg<span class="at">(</span>target_arch <span class="op">=</span> <span class="st">&quot;x86_64&quot;</span><span class="at">)]</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> string <span class="op">=</span> <span class="st">&quot;Hello x86</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">;</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>    <span class="co">// the same as before</span></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And this time, if run on an <code>x86_64</code> linux machine, you
should see the following when running: <code>Hello x86</code>.</p>
<h2 id="conclusions">Conclusions</h2>
<p>That wasn’t so bad, just like the last blog post – but it was also
much easier, and you wouldn’t have to remember the magic defines that
are compiler dependent. As well, <code>cfg</code> attributes are
extremely powerful – much better than C defines because they’re caught
for you at compile time, and there are a bunch of useful ones already
predefined.</p>
<section id="footnotes" class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1"><p>Also known as <code>amd64</code>. <a
href="https://github.com/golang/go/blob/1176052bb40378272cfbe83d873b65fcc2ed8502/src/go/build/syslist.go#L58">Go</a>
calls it this due to amd coming up with it, whereas intel popularized
it, calling it <code>x86_64</code>.<a href="#fnref1"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2"><p>Also known as <code>ARM64</code>. Apple uses
<code>ARM64</code> whereas others use <code>aarch64</code>.<a
href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>]]></description>
</item>
<item>
<title>Coding on Android</title>
<pubDate>Tue, 16 May 2023 02:33:07 +0000</pubDate>
<guid>https://blog/coding-on-android.html</guid>
<description><![CDATA[<p>I like to tinker. No surprises there. But when
my tinkering made it so my laptop wouldn’t boot, I realized I’d need a
plan B computer for when my laptop was out of business. The solution? My
android phone.</p>
<p>I have a Samsung S10 phone, which is about 4 years old at this point
and gets by just fine – it has 8GB of RAM, with 8 cores, 2.84GHz
processor, and 128GB of disk space. The computer I used growing up had a
200MHz processor, with 64MB of RAM, and a 2GB hard drive. Computers are
really fast these days, and I was wondering how fast my phone would be
as a general computing device.</p>
<p>Thankfully, the people at F-droid and Termux made that easy – F-droid
is an alternative app store for android, which comes with lots of
goodies, including Termux, a unix terminal for your android that doesn’t
require root. I installed both and was off to the races. Termux allows
you to create a symlink to your normal files, so you can still fetch
them from the cli. I also used tailscale to quickly move files between
my computer and my phone, so I could get my ssh keys, and other config
files quickly onto the device.</p>
<p>I then got myself a c compiler and rust compiler and started writing
code. My target triplet for rust is <code>aarch64-linux-android</code>,
which is in tier-2 support for rust, so there would be some rough edges.
There certainly were.</p>
<p>I tried to compile some command line utilities I had wrote for
myself, like <code>host</code>, <code>dig</code>, <code>strace</code>,
and others. The DNS library that the network requests relied upon had a
bug that made them not compile on android. As well,
<code>cargo binstall</code>, a utility which downloads binaries of rust
code for you, would crash at runtime due to a DNS misconfiguration. I
had to recompile the library with a feature flag turned off. But
ignoring all those papercuts, it was mindblowing that a 4 year old phone
that costs ~$200 these days could be “good enough” for writing code, and
you could get by with a $50 or less phone for coding and still have a
great experience (you’d also need a keyboard and a mouse and a USB-2 to
USB-3 converter so you’re not stuck on the default keypad, but that’s
not expensive, the local mart had a pair for $10).</p>
<p>The folks at termux do a really good job packaging code – even though
Termux Android doesn’t follow the unix file specification (there is no
<code>root</code> dir), they repackage debian packages to make them work
anyway. And my neovim config worked flawlessly on the phone. It was a
surreal experience – and one differentiator to apple, who locks down
their devices a lot more.</p>
<p>I even tried briefly hosting my own website and other services on the
internet from my phone by using tailscale. That worked flawlessly, and
I’m sure my phone could serve thousands of concurrent visitors.</p>
<p>The experience made me think of two things: Do I really need a laptop
these days? I’ll keep mine around for tinkering, but a phone is just
about good enough – with a USB-C monitor that can accept a keyboard and
mouse, you could have a desktop setup for your phone, even with just one
USB-C port. And a phone just fits in your pocket, with a great battery
life, so you can take it on the go.</p>
<p>In sum, coding on my phone was a delightful experience. In fact, I
liked it so much, I decided to write this post on my phone and build my
blog on my phone and serve it from there. Given the backdrop of tech
doom these days, it’s hard to find any tech news to feel happy about –
but Termux + Android is so good that it’s mindblowing. If anything, I’m
glad that computing has gotten so cheap – I’m sure there’s lots of young
people learning how to code on hardware just like this, and that’s
something that brings a smile to my face.</p>]]></description>
</item>
<item>
<title>Writing Your own Libc</title>
<pubDate>Thu, 16 Feb 2023 21:05:35 +0000</pubDate>
<guid>https://blog/writing-your-own-libc.html</guid>
<description><![CDATA[<p>Note: This code was taken from Linux’s nolibc:
<a
href="https://github.com/torvalds/linux/tree/master/tools/include/nolibc"
class="uri">https://github.com/torvalds/linux/tree/master/tools/include/nolibc</a>.
Check it out to learn more about implementing libc!</p>
<h1 id="what-are-system-calls">What are System Calls?</h1>
<p>Let’s write some libc functions.</p>
<p>Libc is C’s standard library, which implements a group of functions
that can be used by all C programs. Libc provides wrappers for OS level
constructs, like <code>printf</code>, <code>open</code>,
<code>puts</code>, and so on.</p>
<p>There’s two parts to libc:</p>
<ol type="1">
<li>functions like <code>max</code>, or <code>islower</code>, which
don’t require any system calls.</li>
<li>functions that do require system calls, like <code>write</code>,
<code>read</code>, or <code>open</code>.</li>
</ol>
<p>Functions in the first category can be implemented without calling
into the OS.</p>
<p>For example, <code>max</code> would look like this:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> max<span class="op">(</span><span class="dt">int</span> a<span class="op">,</span> <span class="dt">int</span> b<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> a <span class="op">&gt;</span> b <span class="op">?</span> a <span class="op">:</span> b<span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>or <code>islower</code>:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> islower<span class="op">(</span><span class="dt">int</span> c<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="op">(</span>c <span class="op">&gt;=</span> <span class="ch">&#39;a&#39;</span> <span class="op">&amp;&amp;</span> c <span class="op">&lt;=</span> <span class="ch">&#39;z&#39;</span><span class="op">)</span> <span class="op">?</span> <span class="dv">1</span> <span class="op">:</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>However, when writing our own <code>write</code> or <code>read</code>
or <code>open</code>, we hit a roadblock:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> open<span class="op">(</span><span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> path<span class="op">,</span> <span class="dt">int</span> flags<span class="op">,</span> <span class="op">...)</span> <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">// how do I open a file???</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Open is a system call that needs to manipulate hardware; we need to
ask the OS to do the action for us before being able to read and/or
write to the file.</p>
<p>The OS supports an interface to facilitate that, called
<code>system calls</code>. These system calls allow us to request the OS
to do something on our behalf. These calls normally manipuluate hardware
in some fashion, or have to do with processes.</p>
<p>So <code>open</code> might look like this:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> open<span class="op">(</span><span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> path<span class="op">,</span> <span class="dt">int</span> flags<span class="op">,</span> <span class="op">...)</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> system_call<span class="op">(</span>SYSCALL_OPEN<span class="op">,</span> path<span class="op">,</span> flags<span class="op">,</span> <span class="op">...);</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And we defer to the OS, which takes care of everything for us.</p>
<p>That leaves the question: what should our <code>system_call</code>
function look like? And what is <code>SYSCALL_OPEN</code>?</p>
<h2 id="system-call-numbers">System Call Numbers</h2>
<p>System calls take as their first argument a number, which indicates
what system call the OS should execute. The OS then reads the first
argument from the <code>system_call</code> function, looksup which
system call it corresponds to, and the remaining arguments, and executes
that system call.</p>
<p>Let’s say that we call open, which is the number 2:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#define SYSCALL_OPEN </span><span class="dv">2</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>system_call<span class="op">(</span>SYSCALL_OPEN<span class="op">,</span> path<span class="op">,</span> flags<span class="op">,</span> <span class="op">...);</span></span></code></pre></div>
<p>The OS will then take that number and run the desired code.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#define SYSCALL_OPEN </span><span class="dv">2</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> system_call<span class="op">(</span>SYSCALL syscall<span class="op">,</span> <span class="op">...)</span> <span class="op">{</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span> <span class="op">(</span>syscall<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> SYSCALL_OPEN<span class="op">:</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>      <span class="co">// run code to open up a file in the hardware</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">default</span><span class="op">:</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>We now need a correct list of system calls. Imagine if we thought
<code>SYSCALL_OPEN</code> was <code>3</code>, but the OS thought
<code>3</code> means <code>close</code>:</p>
<p>The computer could crash, our process could crash, anything could
happen.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#define SYSCALL_OPEN </span><span class="dv">3</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>system_call<span class="op">(</span>SYSCALL_OPEN<span class="op">,</span> path<span class="op">,</span> flags<span class="op">,</span> <span class="op">...);</span></span></code></pre></div>
<div class="sourceCode" id="cb8"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#define SYSCALL_OPEN  </span><span class="dv">2</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#define SYSCALL_CLOSE </span><span class="dv">3</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> system_call<span class="op">(</span>SYSCALL syscall<span class="op">,</span> <span class="op">...)</span> <span class="op">{</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span> <span class="op">(</span>syscall<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> SYSCALL_OPEN<span class="op">:</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>      <span class="co">// run code to open up a file in the hardware</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> SYSCALL_CLOSE<span class="op">:</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>      <span class="co">// run code to close  a file</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>      <span class="co">// oops, we called the wrong function</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">default</span><span class="op">:</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>      <span class="cf">break</span><span class="op">;</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>So we need to get that list of system calls:</p>
<p>You can find the system calls in your linux system with
<code>ausyscall</code>:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> ausyscall <span class="at">--dump</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="ex">Using</span> x86_64 syscall table:</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="ex">0</span>       read</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="ex">1</span>       write</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a><span class="ex">2</span>       open</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="ex">3</span>       close</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a><span class="ex">...</span></span></code></pre></div>
<p>This differs per architecture:</p>
<p>for example, on aarch64 (ARM 64 bit):</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> ausyscall aarch64 <span class="at">--dump</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="ex">Using</span> aarch64 syscall table:</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="ex">0</span>       io_setup</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="ex">1</span>       io_destroy</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="ex">2</span>       io_submit</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a><span class="ex">3</span>       io_cancel</span></code></pre></div>
<p>We could define these ourselves, or rely on the system to export them
at <code>asm/unistd.h</code>. I’m going to include it instead of
rewriting it.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;asm/unistd.h&gt;</span></span></code></pre></div>
<h2 id="writing-system-calls-with-assembly">Writing system calls (with
assembly)</h2>
<p>Now that we have the system call number we need, let’s write that
syscall!</p>
<p>We need to know a few things:</p>
<ol type="1">
<li>What the system call function is called, so we can tell the OS we’re
running a system call</li>
<li>Where to put the system call number</li>
<li>Where to put any other arguments required (<code>open</code> needs a
file to open, for example)</li>
<li>Where our return values are placed.</li>
</ol>
<p>What better way to learn than through the manual pages: run
<code>man 2 syscall</code> in the shell to learn more:</p>
<p>First, there’s a table that tells us what a system call is called in
the <code>instruction</code> column. For x86-64, it is called
<code>syscall</code>. Next, the table tells us the register to put the
system call number. In x86-64, it is <code>rax</code>. Finally, the
registers to check for return values, which in x86-64 are
<code>rax</code> and <code>rdx</code>, and the register to check for
errors (in x86-64, no registers store errors after a system call).</p>
<pre><code>Arch/ABI    Instruction           System  Ret  Ret  Error    Notes
                                  call #  val  val2
───────────────────────────────────────────────────────────────────
alpha       callsys               v0      v0   a4   a3       1, 6
arc         trap0                 r8      r0   -    -
arm/OABI    swi NR                -       r0   -    -        2
arm/EABI    swi 0x0               r7      r0   r1   -
arm64       svc #0                w8      x0   x1   -
blackfin    excpt 0x0             P0      R0   -    -
i386        int $0x80             eax     eax  edx  -
ia64        break 0x100000        r15     r8   r9   r10      1, 6
m68k        trap #0               d0      d0   -    -
microblaze  brki r14,8            r12     r3   -    -
mips        syscall               v0      v0   v1   a3       1, 6
nios2       trap                  r2      r2   -    r7
parisc      ble 0x100(%sr2, %r0)  r20     r28  -    -
powerpc     sc                    r0      r3   -    r0       1
powerpc64   sc                    r0      r3   -    cr0.SO   1
riscv       ecall                 a7      a0   a1   -
s390        svc 0                 r1      r2   r3   -        3
s390x       svc 0                 r1      r2   r3   -        3
superh      trapa #31             r3      r0   r1   -        4, 6
sparc/32    t 0x10                g1      o0   o1   psr/csr  1, 6
sparc/64    t 0x6d                g1      o0   o1   psr/csr  1, 6
tile        swint1                R10     R00  -    R01      1
x86-64      syscall               rax     rax  rdx  -        5
x32         syscall               rax     rax  rdx  -        5
xtensa      syscall               a2      a2   -    -</code></pre>
<p>Later down the page, there’s another table that shows where arguments
go.</p>
<p>For x86-64, <code>rdi</code> <code>rsi</code> <code>rdx</code>
<code>r10</code> <code>r8</code> <code>r9</code> are the registers to
put arguments in order, with <code>rax</code> being the system call
number.</p>
<p>An interesting thing to note: <code>mips/o32</code> here only
supports 4 arguments in registers. That doesn’t necessarily mean it only
supports system calls with 4 or less arguments – arguments 5 through 8
are placed on the stack and read when the system call instruction is
executed.</p>
<pre><code>Arch/ABI      arg1  arg2  arg3  arg4  arg5  arg6  arg7  Notes
──────────────────────────────────────────────────────────────
alpha         a0    a1    a2    a3    a4    a5    -
arc           r0    r1    r2    r3    r4    r5    -
arm/OABI      r0    r1    r2    r3    r4    r5    r6
arm/EABI      r0    r1    r2    r3    r4    r5    r6
arm64         x0    x1    x2    x3    x4    x5    -
blackfin      R0    R1    R2    R3    R4    R5    -
i386          ebx   ecx   edx   esi   edi   ebp   -
ia64          out0  out1  out2  out3  out4  out5  -
m68k          d1    d2    d3    d4    d5    a0    -
microblaze    r5    r6    r7    r8    r9    r10   -
mips/o32      a0    a1    a2    a3    -     -     -     1
mips/n32,64   a0    a1    a2    a3    a4    a5    -
nios2         r4    r5    r6    r7    r8    r9    -
parisc        r26   r25   r24   r23   r22   r21   -
powerpc       r3    r4    r5    r6    r7    r8    r9
powerpc64     r3    r4    r5    r6    r7    r8    -
riscv         a0    a1    a2    a3    a4    a5    -
s390          r2    r3    r4    r5    r6    r7    -
s390x         r2    r3    r4    r5    r6    r7    -
superh        r4    r5    r6    r7    r0    r1    r2
sparc/32      o0    o1    o2    o3    o4    o5    -
sparc/64      o0    o1    o2    o3    o4    o5    -
tile          R00   R01   R02   R03   R04   R05   -
x86-64        rdi   rsi   rdx   r10   r8    r9    -
x32           rdi   rsi   rdx   r10   r8    r9    -
xtensa        a6    a3    a4    a5    a8    a9    -</code></pre>
<p>With all that information out of the way, we want to write a function
that does the following:</p>
<ol type="1">
<li>Write out the system call instruction in assembly
(<code>syscall</code> for x86).</li>
<li>Set the <code>rax</code> register to the system call we want to
call.</li>
<li>Read the register has the return value and return it.</li>
</ol>
<p>On x86, the registers <code>rcx</code>, <code>r11</code>,
<code>cc</code>, and <code>memory</code> are clobbered by the syscall,
so our assembly call must include them in the last line of the syscall
instruction. The last line notes the clobbered registers that are
overwritten by the OS, as well as other directives.</p>
<p>For an explanation why <code>rcx</code> and <code>r11</code> are
clobbered.</p>
<ul>
<li><code>rcx</code></li>
</ul>
<blockquote>
<p><code>rcx</code> is clobbered to store the address of the next
instruction to return to.</p>
</blockquote>
<ul>
<li><code>r11</code></li>
</ul>
<blockquote>
<p><code>r11</code> is clobbered to store the value of the rflags
register.</p>
</blockquote>
<p>And for <code>cc</code> and <code>memory</code>, from: <a
href="https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Extended-Asm"
class="uri">https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Extended-Asm</a></p>
<ul>
<li><code>cc</code></li>
</ul>
<blockquote>
<p>The <code>cc</code> clobber indicates that the assembler code
modifies the flags register. On some machines, GCC represents the
condition codes as a specific hardware register; “cc” serves to name
this register. On other machines, condition code handling is different,
and specifying “cc” has no effect. But it is valid no matter what the
target.</p>
</blockquote>
<ul>
<li><code>memory</code></li>
</ul>
<blockquote>
<p>The <code>memory</code> clobber tells the compiler that the assembly
code performs memory reads or writes to items other than those listed in
the input and output operands (for example, accessing the memory pointed
to by one of the input parameters). To ensure memory contains correct
values, GCC may need to flush specific register values to memory before
executing the asm. Further, the compiler does not assume that any values
read from memory before an asm remain unchanged after that asm; it
reloads them as needed. Using the “memory” clobber effectively forms a
read/write memory barrier for the compiler.</p>
</blockquote>
<blockquote>
<p>Note that this clobber does not prevent the processor from doing
speculative reads past the asm statement. To prevent that, you need
processor-specific fence instructions.</p>
</blockquote>
<p>So on x86, a system call will look like:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#define syscall0</span><span class="op">(</span><span class="pp">num</span><span class="op">)</span><span class="pp">                     </span><span class="op">\</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="op">({</span><span class="pp">                                        </span><span class="op">\</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">long</span><span class="pp"> _ret</span><span class="op">;</span><span class="pp">                              </span><span class="op">\</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _num  asm</span><span class="op">(</span><span class="st">&quot;rax&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="pp">num</span><span class="op">);</span><span class="pp"> </span><span class="op">\</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a><span class="pp">                                            </span><span class="op">\</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a><span class="pp">    asm </span><span class="dt">volatile</span><span class="pp"> </span><span class="op">(</span><span class="pp">                          </span><span class="op">\</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="st">&quot;syscall</span><span class="sc">\n</span><span class="st">&quot;</span><span class="pp">                           </span><span class="op">\</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;=a&quot;</span><span class="op">(</span><span class="pp">_ret</span><span class="op">)</span><span class="pp">                          </span><span class="op">\</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;0&quot;</span><span class="op">(</span><span class="pp">_num</span><span class="op">)</span><span class="pp">                           </span><span class="op">\</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;rcx&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;r11&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;memory&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;cc&quot;</span><span class="pp">        </span><span class="op">\</span></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="op">);</span><span class="pp">                                      </span><span class="op">\</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a><span class="pp">    _ret</span><span class="op">;</span><span class="pp">                                   </span><span class="op">\</span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a><span class="op">})</span></span></code></pre></div>
<p>For the Arm64 (aarch64) version:</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#define syscall0</span><span class="op">(</span><span class="pp">num</span><span class="op">)</span><span class="pp">                    </span><span class="op">\</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="op">({</span><span class="pp">                                       </span><span class="op">\</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _num  asm</span><span class="op">(</span><span class="st">&quot;x8&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="pp">num</span><span class="op">);</span><span class="pp"> </span><span class="op">\</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _arg1 asm</span><span class="op">(</span><span class="st">&quot;x0&quot;</span><span class="op">);</span><span class="pp">         </span><span class="op">\</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a><span class="pp">                                           </span><span class="op">\</span></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a><span class="pp">    asm </span><span class="dt">volatile</span><span class="pp"> </span><span class="op">(</span><span class="pp">                         </span><span class="op">\</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="st">&quot;svc #0</span><span class="sc">\n</span><span class="st">&quot;</span><span class="pp">                           </span><span class="op">\</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;=r&quot;</span><span class="op">(</span><span class="pp">_arg1</span><span class="op">)</span><span class="pp">                        </span><span class="op">\</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;r&quot;</span><span class="op">(</span><span class="pp">_num</span><span class="op">)</span><span class="pp">                          </span><span class="op">\</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;memory&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;cc&quot;</span><span class="pp">                     </span><span class="op">\</span></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="op">);</span><span class="pp">                                     </span><span class="op">\</span></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a><span class="pp">    _arg1</span><span class="op">;</span><span class="pp">                                 </span><span class="op">\</span></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a><span class="op">})</span></span></code></pre></div>
<h2 id="writing-a-c-function-that-makes-a-system-call">Writing a C
Function that makes a system call</h2>
<p>Let’s write our first libc function, <code>getpid</code>.</p>
<p><code>getpid</code> returns the <code>pid</code> of the current
process.</p>
<p>It has a signature of <code>pid_t getpid(void);</code>, where
<code>pid_t</code> is <code>int</code>.</p>
<p>All we have to do is to make the right system call to the OS and
return it.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">typedef</span> <span class="dt">int</span> pid_t<span class="op">;</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>pid_t getpid<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> syscall0<span class="op">(</span>__NR_getpid<span class="op">);</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This should return your pid, and we’re done creating a libc function
that calls into the kernel.</p>
<h2 id="putting-it-all-together">Putting it all together</h2>
<p>To put it all together, we need to write the <code>_start</code>
function of our program, since we are going to link to our own libc.</p>
<p>For x86, that means adding this code to the top of your file:</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>asm<span class="op">(</span><span class="st">&quot;.section .text</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;.weak _start</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;.global _start</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;_start:</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;pop %rdi</span><span class="sc">\n</span><span class="st">&quot;</span>                <span class="co">// argc   (first arg, %rdi)</span></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;mov %rsp, %rsi</span><span class="sc">\n</span><span class="st">&quot;</span>          <span class="co">// argv[] (second arg, %rsi)</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;lea 8(%rsi,%rdi,8),%rdx</span><span class="sc">\n</span><span class="st">&quot;</span> <span class="co">// then a NULL then envp (third arg, %rdx)</span></span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;xor </span><span class="sc">%e</span><span class="st">bp, </span><span class="sc">%e</span><span class="st">bp</span><span class="sc">\n</span><span class="st">&quot;</span>          <span class="co">// zero the stack frame</span></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;and $-16, %rsp</span><span class="sc">\n</span><span class="st">&quot;</span>          <span class="co">// x86 ABI : esp must be 16-byte aligned before call</span></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;call main</span><span class="sc">\n</span><span class="st">&quot;</span>               <span class="co">// main() returns the status code, we&#39;ll exit with it.</span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;mov </span><span class="sc">%e</span><span class="st">ax, </span><span class="sc">%e</span><span class="st">di</span><span class="sc">\n</span><span class="st">&quot;</span>          <span class="co">// retrieve exit code (32 bit)</span></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;mov $60, </span><span class="sc">%e</span><span class="st">ax</span><span class="sc">\n</span><span class="st">&quot;</span>           <span class="co">// NR_exit == 60</span></span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;syscall</span><span class="sc">\n</span><span class="st">&quot;</span>                 <span class="co">// really exit</span></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;hlt</span><span class="sc">\n</span><span class="st">&quot;</span>                     <span class="co">// ensure it does not return</span></span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;&quot;</span><span class="op">);</span></span></code></pre></div>
<p>This sets up everything main needs to run.</p>
<p>For ARM64 (aarch64):</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>asm<span class="op">(</span><span class="st">&quot;.section .text</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;.weak _start</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;.global _start</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;_start:</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;ldr x0, [sp]</span><span class="sc">\n</span><span class="st">&quot;</span>              <span class="co">// argc (x0) was in the stack</span></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;add x1, sp, 8</span><span class="sc">\n</span><span class="st">&quot;</span>             <span class="co">// argv (x1) = sp</span></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;lsl x2, x0, 3</span><span class="sc">\n</span><span class="st">&quot;</span>             <span class="co">// envp (x2) = 8*argc ...</span></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;add x2, x2, 8</span><span class="sc">\n</span><span class="st">&quot;</span>             <span class="co">//           + 8 (skip null)</span></span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;add x2, x2, x1</span><span class="sc">\n</span><span class="st">&quot;</span>            <span class="co">//           + argv</span></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;and sp, x1, -16</span><span class="sc">\n</span><span class="st">&quot;</span>           <span class="co">// sp must be 16-byte aligned in the callee</span></span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;bl main</span><span class="sc">\n</span><span class="st">&quot;</span>                   <span class="co">// main() returns the status code, we&#39;ll exit with it.</span></span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;mov x8, 93</span><span class="sc">\n</span><span class="st">&quot;</span>                <span class="co">// NR_exit == 93</span></span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;svc #0</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;&quot;</span><span class="op">);</span></span></code></pre></div>
<p>And aggregating that together:</p>
<p>For x86:</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;asm/unistd.h&gt;</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#define syscall0</span><span class="op">(</span><span class="pp">num</span><span class="op">)</span><span class="pp">                     </span><span class="op">\</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a><span class="op">({</span><span class="pp">                                        </span><span class="op">\</span></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">long</span><span class="pp"> _ret</span><span class="op">;</span><span class="pp">                              </span><span class="op">\</span></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _num  asm</span><span class="op">(</span><span class="st">&quot;rax&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="pp">num</span><span class="op">);</span><span class="pp"> </span><span class="op">\</span></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a><span class="pp">                                            </span><span class="op">\</span></span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a><span class="pp">    asm </span><span class="dt">volatile</span><span class="pp"> </span><span class="op">(</span><span class="pp">                          </span><span class="op">\</span></span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="st">&quot;syscall</span><span class="sc">\n</span><span class="st">&quot;</span><span class="pp">                           </span><span class="op">\</span></span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;=a&quot;</span><span class="op">(</span><span class="pp">_ret</span><span class="op">)</span><span class="pp">                          </span><span class="op">\</span></span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;0&quot;</span><span class="op">(</span><span class="pp">_num</span><span class="op">)</span><span class="pp">                           </span><span class="op">\</span></span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;rcx&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;r11&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;memory&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;cc&quot;</span><span class="pp">        </span><span class="op">\</span></span>
<span id="cb19-13"><a href="#cb19-13" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="op">);</span><span class="pp">                                      </span><span class="op">\</span></span>
<span id="cb19-14"><a href="#cb19-14" aria-hidden="true" tabindex="-1"></a><span class="pp">    _ret</span><span class="op">;</span><span class="pp">                                   </span><span class="op">\</span></span>
<span id="cb19-15"><a href="#cb19-15" aria-hidden="true" tabindex="-1"></a><span class="op">})</span></span>
<span id="cb19-16"><a href="#cb19-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-17"><a href="#cb19-17" aria-hidden="true" tabindex="-1"></a>asm<span class="op">(</span><span class="st">&quot;.section .text</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb19-18"><a href="#cb19-18" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;.weak _start</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb19-19"><a href="#cb19-19" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;.global _start</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb19-20"><a href="#cb19-20" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;_start:</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb19-21"><a href="#cb19-21" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;pop %rdi</span><span class="sc">\n</span><span class="st">&quot;</span>                <span class="co">// argc   (first arg, %rdi)</span></span>
<span id="cb19-22"><a href="#cb19-22" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;mov %rsp, %rsi</span><span class="sc">\n</span><span class="st">&quot;</span>          <span class="co">// argv[] (second arg, %rsi)</span></span>
<span id="cb19-23"><a href="#cb19-23" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;lea 8(%rsi,%rdi,8),%rdx</span><span class="sc">\n</span><span class="st">&quot;</span> <span class="co">// then a NULL then envp (third arg, %rdx)</span></span>
<span id="cb19-24"><a href="#cb19-24" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;xor </span><span class="sc">%e</span><span class="st">bp, </span><span class="sc">%e</span><span class="st">bp</span><span class="sc">\n</span><span class="st">&quot;</span>          <span class="co">// zero the stack frame</span></span>
<span id="cb19-25"><a href="#cb19-25" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;and $-16, %rsp</span><span class="sc">\n</span><span class="st">&quot;</span>          <span class="co">// x86 ABI : esp must be 16-byte aligned before call</span></span>
<span id="cb19-26"><a href="#cb19-26" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;call main</span><span class="sc">\n</span><span class="st">&quot;</span>               <span class="co">// main() returns the status code, we&#39;ll exit with it.</span></span>
<span id="cb19-27"><a href="#cb19-27" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;mov </span><span class="sc">%e</span><span class="st">ax, </span><span class="sc">%e</span><span class="st">di</span><span class="sc">\n</span><span class="st">&quot;</span>          <span class="co">// retrieve exit code (32 bit)</span></span>
<span id="cb19-28"><a href="#cb19-28" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;mov $60, </span><span class="sc">%e</span><span class="st">ax</span><span class="sc">\n</span><span class="st">&quot;</span>           <span class="co">// NR_exit == 60</span></span>
<span id="cb19-29"><a href="#cb19-29" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;syscall</span><span class="sc">\n</span><span class="st">&quot;</span>                 <span class="co">// really exit</span></span>
<span id="cb19-30"><a href="#cb19-30" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;hlt</span><span class="sc">\n</span><span class="st">&quot;</span>                     <span class="co">// ensure it does not return</span></span>
<span id="cb19-31"><a href="#cb19-31" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;&quot;</span><span class="op">);</span></span>
<span id="cb19-32"><a href="#cb19-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-33"><a href="#cb19-33" aria-hidden="true" tabindex="-1"></a><span class="kw">typedef</span> <span class="dt">int</span> pid_t<span class="op">;</span></span>
<span id="cb19-34"><a href="#cb19-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-35"><a href="#cb19-35" aria-hidden="true" tabindex="-1"></a>pid_t getpid<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-36"><a href="#cb19-36" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> syscall0<span class="op">(</span>__NR_getpid<span class="op">);</span></span>
<span id="cb19-37"><a href="#cb19-37" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb19-38"><a href="#cb19-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-39"><a href="#cb19-39" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb19-40"><a href="#cb19-40" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> getpid<span class="op">();</span></span>
<span id="cb19-41"><a href="#cb19-41" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>For ARM64 (aarch64):</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#define syscall0</span><span class="op">(</span><span class="pp">num</span><span class="op">)</span><span class="pp">                    </span><span class="op">\</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a><span class="op">({</span><span class="pp">                                       </span><span class="op">\</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _num  asm</span><span class="op">(</span><span class="st">&quot;x8&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="pp">num</span><span class="op">);</span><span class="pp"> </span><span class="op">\</span></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _arg1 asm</span><span class="op">(</span><span class="st">&quot;x0&quot;</span><span class="op">);</span><span class="pp">         </span><span class="op">\</span></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a><span class="pp">                                           </span><span class="op">\</span></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a><span class="pp">    asm </span><span class="dt">volatile</span><span class="pp"> </span><span class="op">(</span><span class="pp">                         </span><span class="op">\</span></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="st">&quot;svc #0</span><span class="sc">\n</span><span class="st">&quot;</span><span class="pp">                           </span><span class="op">\</span></span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;=r&quot;</span><span class="op">(</span><span class="pp">_arg1</span><span class="op">)</span><span class="pp">                        </span><span class="op">\</span></span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;r&quot;</span><span class="op">(</span><span class="pp">_num</span><span class="op">)</span><span class="pp">                          </span><span class="op">\</span></span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;memory&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;cc&quot;</span><span class="pp">                     </span><span class="op">\</span></span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="op">);</span><span class="pp">                                     </span><span class="op">\</span></span>
<span id="cb20-12"><a href="#cb20-12" aria-hidden="true" tabindex="-1"></a><span class="pp">    _arg1</span><span class="op">;</span><span class="pp">                                 </span><span class="op">\</span></span>
<span id="cb20-13"><a href="#cb20-13" aria-hidden="true" tabindex="-1"></a><span class="op">})</span></span>
<span id="cb20-14"><a href="#cb20-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-15"><a href="#cb20-15" aria-hidden="true" tabindex="-1"></a>asm<span class="op">(</span><span class="st">&quot;.section .text</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb20-16"><a href="#cb20-16" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;.weak _start</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb20-17"><a href="#cb20-17" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;.global _start</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb20-18"><a href="#cb20-18" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;_start:</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb20-19"><a href="#cb20-19" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;ldr x0, [sp]</span><span class="sc">\n</span><span class="st">&quot;</span>              <span class="co">// argc (x0) was in the stack</span></span>
<span id="cb20-20"><a href="#cb20-20" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;add x1, sp, 8</span><span class="sc">\n</span><span class="st">&quot;</span>             <span class="co">// argv (x1) = sp</span></span>
<span id="cb20-21"><a href="#cb20-21" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;lsl x2, x0, 3</span><span class="sc">\n</span><span class="st">&quot;</span>             <span class="co">// envp (x2) = 8*argc ...</span></span>
<span id="cb20-22"><a href="#cb20-22" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;add x2, x2, 8</span><span class="sc">\n</span><span class="st">&quot;</span>             <span class="co">//           + 8 (skip null)</span></span>
<span id="cb20-23"><a href="#cb20-23" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;add x2, x2, x1</span><span class="sc">\n</span><span class="st">&quot;</span>            <span class="co">//           + argv</span></span>
<span id="cb20-24"><a href="#cb20-24" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;and sp, x1, -16</span><span class="sc">\n</span><span class="st">&quot;</span>           <span class="co">// sp must be 16-byte aligned in the callee</span></span>
<span id="cb20-25"><a href="#cb20-25" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;bl main</span><span class="sc">\n</span><span class="st">&quot;</span>                   <span class="co">// main() returns the status code, we&#39;ll exit with it.</span></span>
<span id="cb20-26"><a href="#cb20-26" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;mov x8, 93</span><span class="sc">\n</span><span class="st">&quot;</span>                <span class="co">// NR_exit == 93</span></span>
<span id="cb20-27"><a href="#cb20-27" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;svc #0</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb20-28"><a href="#cb20-28" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;&quot;</span><span class="op">);</span></span>
<span id="cb20-29"><a href="#cb20-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-30"><a href="#cb20-30" aria-hidden="true" tabindex="-1"></a><span class="kw">typedef</span> <span class="dt">int</span> pid_t<span class="op">;</span></span>
<span id="cb20-31"><a href="#cb20-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-32"><a href="#cb20-32" aria-hidden="true" tabindex="-1"></a>pid_t getpid<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-33"><a href="#cb20-33" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> syscall0<span class="op">(</span>__NR_getpid<span class="op">);</span></span>
<span id="cb20-34"><a href="#cb20-34" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb20-35"><a href="#cb20-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-36"><a href="#cb20-36" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb20-37"><a href="#cb20-37" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> getpid<span class="op">();</span></span>
<span id="cb20-38"><a href="#cb20-38" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Now to compile this program, we can’t link to libc, so, assuming the
c file is called <code>main.c</code></p>
<div class="sourceCode" id="cb21"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> gcc <span class="at">-static</span> <span class="at">-lgcc</span> <span class="at">-nostdlib</span> <span class="at">-g</span> main.c <span class="at">-o</span> main</span></code></pre></div>
<p>to compile it, and run it:</p>
<div class="sourceCode" id="cb22"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> ./main</span></code></pre></div>
<p>Grab the exit status of the binary:</p>
<div class="sourceCode" id="cb23"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="va">$?</span> <span class="co"># some random number</span></span></code></pre></div>
<p>And we’re done with implementing <code>getpid</code>!</p>
<h2 id="reading-and-writing-to-files">Reading and writing to files</h2>
<p><code>getpid</code> is a fine starting function, but we want to be
able to read and write to files.</p>
<p>Let’s start by defining the system calls that take 1 argument to 3
arguments:</p>
<p>In x86-64:</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#define syscall1</span><span class="op">(</span><span class="pp">num</span><span class="op">,</span><span class="pp"> arg1</span><span class="op">)</span><span class="pp">                      </span><span class="op">\</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a><span class="op">({</span><span class="pp">                                               </span><span class="op">\</span></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">long</span><span class="pp"> _ret</span><span class="op">;</span><span class="pp">                                     </span><span class="op">\</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _num  asm</span><span class="op">(</span><span class="st">&quot;rax&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="pp">num</span><span class="op">);</span><span class="pp">        </span><span class="op">\</span></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _arg1 asm</span><span class="op">(</span><span class="st">&quot;rdi&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="dt">long</span><span class="op">)(</span><span class="pp">arg1</span><span class="op">);</span><span class="pp"> </span><span class="op">\</span></span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a><span class="pp">                                                   </span><span class="op">\</span></span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a><span class="pp">    asm </span><span class="dt">volatile</span><span class="pp"> </span><span class="op">(</span><span class="pp">                                 </span><span class="op">\</span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="st">&quot;syscall</span><span class="sc">\n</span><span class="st">&quot;</span><span class="pp">                                  </span><span class="op">\</span></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;=a&quot;</span><span class="op">(</span><span class="pp">_ret</span><span class="op">)</span><span class="pp">                                 </span><span class="op">\</span></span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;r&quot;</span><span class="op">(</span><span class="pp">_arg1</span><span class="op">),</span><span class="pp">                                </span><span class="op">\</span></span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a><span class="pp">          </span><span class="st">&quot;0&quot;</span><span class="op">(</span><span class="pp">_num</span><span class="op">)</span><span class="pp">                                  </span><span class="op">\</span></span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;rcx&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;r11&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;memory&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;cc&quot;</span><span class="pp">               </span><span class="op">\</span></span>
<span id="cb24-13"><a href="#cb24-13" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="op">);</span><span class="pp">                                             </span><span class="op">\</span></span>
<span id="cb24-14"><a href="#cb24-14" aria-hidden="true" tabindex="-1"></a><span class="pp">    _ret</span><span class="op">;</span><span class="pp">                                          </span><span class="op">\</span></span>
<span id="cb24-15"><a href="#cb24-15" aria-hidden="true" tabindex="-1"></a><span class="op">})</span></span>
<span id="cb24-16"><a href="#cb24-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-17"><a href="#cb24-17" aria-hidden="true" tabindex="-1"></a><span class="pp">#define syscall2</span><span class="op">(</span><span class="pp">num</span><span class="op">,</span><span class="pp"> arg1</span><span class="op">,</span><span class="pp"> arg2</span><span class="op">)</span><span class="pp">                </span><span class="op">\</span></span>
<span id="cb24-18"><a href="#cb24-18" aria-hidden="true" tabindex="-1"></a><span class="op">({</span><span class="pp">                                               </span><span class="op">\</span></span>
<span id="cb24-19"><a href="#cb24-19" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">long</span><span class="pp"> _ret</span><span class="op">;</span><span class="pp">                                     </span><span class="op">\</span></span>
<span id="cb24-20"><a href="#cb24-20" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _num  asm</span><span class="op">(</span><span class="st">&quot;rax&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="pp">num</span><span class="op">);</span><span class="pp">        </span><span class="op">\</span></span>
<span id="cb24-21"><a href="#cb24-21" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _arg1 asm</span><span class="op">(</span><span class="st">&quot;rdi&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="dt">long</span><span class="op">)(</span><span class="pp">arg1</span><span class="op">);</span><span class="pp"> </span><span class="op">\</span></span>
<span id="cb24-22"><a href="#cb24-22" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _arg2 asm</span><span class="op">(</span><span class="st">&quot;rsi&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="dt">long</span><span class="op">)(</span><span class="pp">arg2</span><span class="op">);</span><span class="pp"> </span><span class="op">\</span></span>
<span id="cb24-23"><a href="#cb24-23" aria-hidden="true" tabindex="-1"></a><span class="pp">                                                   </span><span class="op">\</span></span>
<span id="cb24-24"><a href="#cb24-24" aria-hidden="true" tabindex="-1"></a><span class="pp">    asm </span><span class="dt">volatile</span><span class="pp"> </span><span class="op">(</span><span class="pp">                                 </span><span class="op">\</span></span>
<span id="cb24-25"><a href="#cb24-25" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="st">&quot;syscall</span><span class="sc">\n</span><span class="st">&quot;</span><span class="pp">                                  </span><span class="op">\</span></span>
<span id="cb24-26"><a href="#cb24-26" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;=a&quot;</span><span class="op">(</span><span class="pp">_ret</span><span class="op">)</span><span class="pp">                                 </span><span class="op">\</span></span>
<span id="cb24-27"><a href="#cb24-27" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;r&quot;</span><span class="op">(</span><span class="pp">_arg1</span><span class="op">),</span><span class="pp"> </span><span class="st">&quot;r&quot;</span><span class="op">(</span><span class="pp">_arg2</span><span class="op">),</span><span class="pp">                    </span><span class="op">\</span></span>
<span id="cb24-28"><a href="#cb24-28" aria-hidden="true" tabindex="-1"></a><span class="pp">          </span><span class="st">&quot;0&quot;</span><span class="op">(</span><span class="pp">_num</span><span class="op">)</span><span class="pp">                                  </span><span class="op">\</span></span>
<span id="cb24-29"><a href="#cb24-29" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;rcx&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;r11&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;memory&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;cc&quot;</span><span class="pp">               </span><span class="op">\</span></span>
<span id="cb24-30"><a href="#cb24-30" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="op">);</span><span class="pp">                                             </span><span class="op">\</span></span>
<span id="cb24-31"><a href="#cb24-31" aria-hidden="true" tabindex="-1"></a><span class="pp">    _ret</span><span class="op">;</span><span class="pp">                                          </span><span class="op">\</span></span>
<span id="cb24-32"><a href="#cb24-32" aria-hidden="true" tabindex="-1"></a><span class="op">})</span></span>
<span id="cb24-33"><a href="#cb24-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-34"><a href="#cb24-34" aria-hidden="true" tabindex="-1"></a><span class="pp">#define syscall3</span><span class="op">(</span><span class="pp">num</span><span class="op">,</span><span class="pp"> arg1</span><span class="op">,</span><span class="pp"> arg2</span><span class="op">,</span><span class="pp"> arg3</span><span class="op">)</span><span class="pp">          </span><span class="op">\</span></span>
<span id="cb24-35"><a href="#cb24-35" aria-hidden="true" tabindex="-1"></a><span class="op">({</span><span class="pp">                                               </span><span class="op">\</span></span>
<span id="cb24-36"><a href="#cb24-36" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">long</span><span class="pp"> _ret</span><span class="op">;</span><span class="pp">                                     </span><span class="op">\</span></span>
<span id="cb24-37"><a href="#cb24-37" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _num  asm</span><span class="op">(</span><span class="st">&quot;rax&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="pp">num</span><span class="op">);</span><span class="pp">        </span><span class="op">\</span></span>
<span id="cb24-38"><a href="#cb24-38" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _arg1 asm</span><span class="op">(</span><span class="st">&quot;rdi&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="dt">long</span><span class="op">)(</span><span class="pp">arg1</span><span class="op">);</span><span class="pp"> </span><span class="op">\</span></span>
<span id="cb24-39"><a href="#cb24-39" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _arg2 asm</span><span class="op">(</span><span class="st">&quot;rsi&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="dt">long</span><span class="op">)(</span><span class="pp">arg2</span><span class="op">);</span><span class="pp"> </span><span class="op">\</span></span>
<span id="cb24-40"><a href="#cb24-40" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _arg3 asm</span><span class="op">(</span><span class="st">&quot;rdx&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="dt">long</span><span class="op">)(</span><span class="pp">arg3</span><span class="op">);</span><span class="pp"> </span><span class="op">\</span></span>
<span id="cb24-41"><a href="#cb24-41" aria-hidden="true" tabindex="-1"></a><span class="pp">                                                   </span><span class="op">\</span></span>
<span id="cb24-42"><a href="#cb24-42" aria-hidden="true" tabindex="-1"></a><span class="pp">    asm </span><span class="dt">volatile</span><span class="pp"> </span><span class="op">(</span><span class="pp">                                 </span><span class="op">\</span></span>
<span id="cb24-43"><a href="#cb24-43" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="st">&quot;syscall</span><span class="sc">\n</span><span class="st">&quot;</span><span class="pp">                                  </span><span class="op">\</span></span>
<span id="cb24-44"><a href="#cb24-44" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;=a&quot;</span><span class="op">(</span><span class="pp">_ret</span><span class="op">)</span><span class="pp">                                 </span><span class="op">\</span></span>
<span id="cb24-45"><a href="#cb24-45" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;r&quot;</span><span class="op">(</span><span class="pp">_arg1</span><span class="op">),</span><span class="pp"> </span><span class="st">&quot;r&quot;</span><span class="op">(</span><span class="pp">_arg2</span><span class="op">),</span><span class="pp"> </span><span class="st">&quot;r&quot;</span><span class="op">(</span><span class="pp">_arg3</span><span class="op">),</span><span class="pp">        </span><span class="op">\</span></span>
<span id="cb24-46"><a href="#cb24-46" aria-hidden="true" tabindex="-1"></a><span class="pp">          </span><span class="st">&quot;0&quot;</span><span class="op">(</span><span class="pp">_num</span><span class="op">)</span><span class="pp">                                  </span><span class="op">\</span></span>
<span id="cb24-47"><a href="#cb24-47" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;rcx&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;r11&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;memory&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;cc&quot;</span><span class="pp">               </span><span class="op">\</span></span>
<span id="cb24-48"><a href="#cb24-48" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="op">);</span><span class="pp">                                             </span><span class="op">\</span></span>
<span id="cb24-49"><a href="#cb24-49" aria-hidden="true" tabindex="-1"></a><span class="pp">    _ret</span><span class="op">;</span><span class="pp">                                          </span><span class="op">\</span></span>
<span id="cb24-50"><a href="#cb24-50" aria-hidden="true" tabindex="-1"></a><span class="op">})</span></span></code></pre></div>
<p>In ARM64 (aarch64):</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#define syscall1</span><span class="op">(</span><span class="pp">num</span><span class="op">,</span><span class="pp"> arg1</span><span class="op">)</span><span class="pp">                       </span><span class="op">\</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a><span class="op">({</span><span class="pp">                                                </span><span class="op">\</span></span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _num  asm</span><span class="op">(</span><span class="st">&quot;x8&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="pp">num</span><span class="op">);</span><span class="pp">          </span><span class="op">\</span></span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _arg1 asm</span><span class="op">(</span><span class="st">&quot;x0&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="dt">long</span><span class="op">)(</span><span class="pp">arg1</span><span class="op">);</span><span class="pp">   </span><span class="op">\</span></span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a><span class="pp">                                                    </span><span class="op">\</span></span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a><span class="pp">    asm </span><span class="dt">volatile</span><span class="pp"> </span><span class="op">(</span><span class="pp">                                  </span><span class="op">\</span></span>
<span id="cb25-7"><a href="#cb25-7" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="st">&quot;svc #0</span><span class="sc">\n</span><span class="st">&quot;</span><span class="pp">                                    </span><span class="op">\</span></span>
<span id="cb25-8"><a href="#cb25-8" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;=r&quot;</span><span class="op">(</span><span class="pp">_arg1</span><span class="op">)</span><span class="pp">                                 </span><span class="op">\</span></span>
<span id="cb25-9"><a href="#cb25-9" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;r&quot;</span><span class="op">(</span><span class="pp">_arg1</span><span class="op">),</span><span class="pp">                                 </span><span class="op">\</span></span>
<span id="cb25-10"><a href="#cb25-10" aria-hidden="true" tabindex="-1"></a><span class="pp">          </span><span class="st">&quot;r&quot;</span><span class="op">(</span><span class="pp">_num</span><span class="op">)</span><span class="pp">                                   </span><span class="op">\</span></span>
<span id="cb25-11"><a href="#cb25-11" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;memory&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;cc&quot;</span><span class="pp">                              </span><span class="op">\</span></span>
<span id="cb25-12"><a href="#cb25-12" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="op">);</span><span class="pp">                                              </span><span class="op">\</span></span>
<span id="cb25-13"><a href="#cb25-13" aria-hidden="true" tabindex="-1"></a><span class="pp">    _arg1</span><span class="op">;</span><span class="pp">                                          </span><span class="op">\</span></span>
<span id="cb25-14"><a href="#cb25-14" aria-hidden="true" tabindex="-1"></a><span class="op">})</span></span>
<span id="cb25-15"><a href="#cb25-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-16"><a href="#cb25-16" aria-hidden="true" tabindex="-1"></a><span class="pp">#define syscall2</span><span class="op">(</span><span class="pp">num</span><span class="op">,</span><span class="pp"> arg1</span><span class="op">,</span><span class="pp"> arg2</span><span class="op">)</span><span class="pp">                 </span><span class="op">\</span></span>
<span id="cb25-17"><a href="#cb25-17" aria-hidden="true" tabindex="-1"></a><span class="op">({</span><span class="pp">                                                </span><span class="op">\</span></span>
<span id="cb25-18"><a href="#cb25-18" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _num  asm</span><span class="op">(</span><span class="st">&quot;x8&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="pp">num</span><span class="op">);</span><span class="pp">          </span><span class="op">\</span></span>
<span id="cb25-19"><a href="#cb25-19" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _arg1 asm</span><span class="op">(</span><span class="st">&quot;x0&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="dt">long</span><span class="op">)(</span><span class="pp">arg1</span><span class="op">);</span><span class="pp">   </span><span class="op">\</span></span>
<span id="cb25-20"><a href="#cb25-20" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _arg2 asm</span><span class="op">(</span><span class="st">&quot;x1&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="dt">long</span><span class="op">)(</span><span class="pp">arg2</span><span class="op">);</span><span class="pp">   </span><span class="op">\</span></span>
<span id="cb25-21"><a href="#cb25-21" aria-hidden="true" tabindex="-1"></a><span class="pp">                                                    </span><span class="op">\</span></span>
<span id="cb25-22"><a href="#cb25-22" aria-hidden="true" tabindex="-1"></a><span class="pp">    asm </span><span class="dt">volatile</span><span class="pp"> </span><span class="op">(</span><span class="pp">                                  </span><span class="op">\</span></span>
<span id="cb25-23"><a href="#cb25-23" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="st">&quot;svc #0</span><span class="sc">\n</span><span class="st">&quot;</span><span class="pp">                                    </span><span class="op">\</span></span>
<span id="cb25-24"><a href="#cb25-24" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;=r&quot;</span><span class="op">(</span><span class="pp">_arg1</span><span class="op">)</span><span class="pp">                                 </span><span class="op">\</span></span>
<span id="cb25-25"><a href="#cb25-25" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;r&quot;</span><span class="op">(</span><span class="pp">_arg1</span><span class="op">),</span><span class="pp"> </span><span class="st">&quot;r&quot;</span><span class="op">(</span><span class="pp">_arg2</span><span class="op">),</span><span class="pp">                     </span><span class="op">\</span></span>
<span id="cb25-26"><a href="#cb25-26" aria-hidden="true" tabindex="-1"></a><span class="pp">          </span><span class="st">&quot;r&quot;</span><span class="op">(</span><span class="pp">_num</span><span class="op">)</span><span class="pp">                                   </span><span class="op">\</span></span>
<span id="cb25-27"><a href="#cb25-27" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;memory&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;cc&quot;</span><span class="pp">                              </span><span class="op">\</span></span>
<span id="cb25-28"><a href="#cb25-28" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="op">);</span><span class="pp">                                              </span><span class="op">\</span></span>
<span id="cb25-29"><a href="#cb25-29" aria-hidden="true" tabindex="-1"></a><span class="pp">    _arg1</span><span class="op">;</span><span class="pp">                                          </span><span class="op">\</span></span>
<span id="cb25-30"><a href="#cb25-30" aria-hidden="true" tabindex="-1"></a><span class="op">})</span></span>
<span id="cb25-31"><a href="#cb25-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-32"><a href="#cb25-32" aria-hidden="true" tabindex="-1"></a><span class="pp">#define syscall3</span><span class="op">(</span><span class="pp">num</span><span class="op">,</span><span class="pp"> arg1</span><span class="op">,</span><span class="pp"> arg2</span><span class="op">,</span><span class="pp"> arg3</span><span class="op">)</span><span class="pp">           </span><span class="op">\</span></span>
<span id="cb25-33"><a href="#cb25-33" aria-hidden="true" tabindex="-1"></a><span class="op">({</span><span class="pp">                                                </span><span class="op">\</span></span>
<span id="cb25-34"><a href="#cb25-34" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _num  asm</span><span class="op">(</span><span class="st">&quot;x8&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="pp">num</span><span class="op">);</span><span class="pp">          </span><span class="op">\</span></span>
<span id="cb25-35"><a href="#cb25-35" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _arg1 asm</span><span class="op">(</span><span class="st">&quot;x0&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="dt">long</span><span class="op">)(</span><span class="pp">arg1</span><span class="op">);</span><span class="pp">   </span><span class="op">\</span></span>
<span id="cb25-36"><a href="#cb25-36" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _arg2 asm</span><span class="op">(</span><span class="st">&quot;x1&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="dt">long</span><span class="op">)(</span><span class="pp">arg2</span><span class="op">);</span><span class="pp">   </span><span class="op">\</span></span>
<span id="cb25-37"><a href="#cb25-37" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">register</span><span class="pp"> </span><span class="dt">long</span><span class="pp"> _arg3 asm</span><span class="op">(</span><span class="st">&quot;x2&quot;</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="dt">long</span><span class="op">)(</span><span class="pp">arg3</span><span class="op">);</span><span class="pp">   </span><span class="op">\</span></span>
<span id="cb25-38"><a href="#cb25-38" aria-hidden="true" tabindex="-1"></a><span class="pp">                                                    </span><span class="op">\</span></span>
<span id="cb25-39"><a href="#cb25-39" aria-hidden="true" tabindex="-1"></a><span class="pp">    asm </span><span class="dt">volatile</span><span class="pp"> </span><span class="op">(</span><span class="pp">                                  </span><span class="op">\</span></span>
<span id="cb25-40"><a href="#cb25-40" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="st">&quot;svc #0</span><span class="sc">\n</span><span class="st">&quot;</span><span class="pp">                                    </span><span class="op">\</span></span>
<span id="cb25-41"><a href="#cb25-41" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;=r&quot;</span><span class="op">(</span><span class="pp">_arg1</span><span class="op">)</span><span class="pp">                                 </span><span class="op">\</span></span>
<span id="cb25-42"><a href="#cb25-42" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;r&quot;</span><span class="op">(</span><span class="pp">_arg1</span><span class="op">),</span><span class="pp"> </span><span class="st">&quot;r&quot;</span><span class="op">(</span><span class="pp">_arg2</span><span class="op">),</span><span class="pp"> </span><span class="st">&quot;r&quot;</span><span class="op">(</span><span class="pp">_arg3</span><span class="op">),</span><span class="pp">         </span><span class="op">\</span></span>
<span id="cb25-43"><a href="#cb25-43" aria-hidden="true" tabindex="-1"></a><span class="pp">          </span><span class="st">&quot;r&quot;</span><span class="op">(</span><span class="pp">_num</span><span class="op">)</span><span class="pp">                                   </span><span class="op">\</span></span>
<span id="cb25-44"><a href="#cb25-44" aria-hidden="true" tabindex="-1"></a><span class="pp">        </span><span class="op">:</span><span class="pp"> </span><span class="st">&quot;memory&quot;</span><span class="op">,</span><span class="pp"> </span><span class="st">&quot;cc&quot;</span><span class="pp">                              </span><span class="op">\</span></span>
<span id="cb25-45"><a href="#cb25-45" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="op">);</span><span class="pp">                                              </span><span class="op">\</span></span>
<span id="cb25-46"><a href="#cb25-46" aria-hidden="true" tabindex="-1"></a><span class="pp">    _arg1</span><span class="op">;</span><span class="pp">                                          </span><span class="op">\</span></span>
<span id="cb25-47"><a href="#cb25-47" aria-hidden="true" tabindex="-1"></a><span class="op">})</span></span></code></pre></div>
<p>Next, some definitions that the libc functions will use:</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="kw">typedef</span> <span class="dt">int</span> pid_t<span class="op">;</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a><span class="kw">typedef</span> <span class="dt">int</span> mode_t<span class="op">;</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a><span class="kw">typedef</span> <span class="dt">int</span> <span class="dt">ssize_t</span><span class="op">;</span></span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a><span class="kw">typedef</span> <span class="dt">unsigned</span> <span class="dt">long</span> <span class="dt">long</span> <span class="dt">size_t</span><span class="op">;</span></span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a><span class="pp">#define STDIN_FILENO  </span><span class="dv">0</span></span>
<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a><span class="pp">#define STDOUT_FILENO </span><span class="dv">1</span></span>
<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a><span class="pp">#define STDERR_FILENO </span><span class="dv">2</span></span></code></pre></div>
<p>And flags for calls to <code>open</code>:</p>
<p>For x86-64:</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_RDONLY            </span><span class="dv">0</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_WRONLY            </span><span class="dv">1</span></span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_RDWR              </span><span class="dv">2</span></span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_CREAT          </span><span class="bn">0x40</span></span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_EXCL           </span><span class="bn">0x80</span></span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_NOCTTY        </span><span class="bn">0x100</span></span>
<span id="cb27-7"><a href="#cb27-7" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_TRUNC         </span><span class="bn">0x200</span></span>
<span id="cb27-8"><a href="#cb27-8" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_APPEND        </span><span class="bn">0x400</span></span>
<span id="cb27-9"><a href="#cb27-9" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_NONBLOCK      </span><span class="bn">0x800</span></span>
<span id="cb27-10"><a href="#cb27-10" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_DIRECTORY   </span><span class="bn">0x10000</span></span></code></pre></div>
<p>For Arm64 (aarch64):</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_RDONLY            </span><span class="dv">0</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_WRONLY            </span><span class="dv">1</span></span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_RDWR              </span><span class="dv">2</span></span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_CREAT          </span><span class="bn">0x40</span></span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_EXCL           </span><span class="bn">0x80</span></span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_NOCTTY        </span><span class="bn">0x100</span></span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_TRUNC         </span><span class="bn">0x200</span></span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_APPEND        </span><span class="bn">0x400</span></span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_NONBLOCK      </span><span class="bn">0x800</span></span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a><span class="pp">#define O_DIRECTORY    </span><span class="bn">0x4000</span></span></code></pre></div>
<p>Finally, let’s define the functions we’ll use:</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="dt">ssize_t</span> close<span class="op">(</span><span class="dt">int</span> fd<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> syscall1<span class="op">(</span>__NR_close<span class="op">,</span> fd<span class="op">);</span></span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> fsync<span class="op">(</span><span class="dt">int</span> fd<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> syscall1<span class="op">(</span>__NR_fsync<span class="op">,</span> fd<span class="op">);</span></span>
<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a><span class="dt">ssize_t</span> read<span class="op">(</span><span class="dt">int</span> fd<span class="op">,</span> <span class="dt">void</span> <span class="op">*</span>buf<span class="op">,</span> <span class="dt">size_t</span> count<span class="op">)</span></span>
<span id="cb29-10"><a href="#cb29-10" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb29-11"><a href="#cb29-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> syscall3<span class="op">(</span>__NR_read<span class="op">,</span> fd<span class="op">,</span> buf<span class="op">,</span> count<span class="op">);</span></span>
<span id="cb29-12"><a href="#cb29-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb29-13"><a href="#cb29-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-14"><a href="#cb29-14" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> open<span class="op">(</span><span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>path<span class="op">,</span> <span class="dt">int</span> flags<span class="op">,</span> mode_t mode<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-15"><a href="#cb29-15" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> syscall3<span class="op">(</span>__NR_open<span class="op">,</span> path<span class="op">,</span> flags<span class="op">,</span> mode<span class="op">);</span></span>
<span id="cb29-16"><a href="#cb29-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb29-17"><a href="#cb29-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-18"><a href="#cb29-18" aria-hidden="true" tabindex="-1"></a><span class="dt">ssize_t</span> write<span class="op">(</span><span class="dt">int</span> fd<span class="op">,</span> <span class="dt">const</span> <span class="dt">void</span> <span class="op">*</span>buf<span class="op">,</span> <span class="dt">size_t</span> count<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-19"><a href="#cb29-19" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> syscall3<span class="op">(</span>__NR_write<span class="op">,</span> fd<span class="op">,</span> buf<span class="op">,</span> count<span class="op">);</span></span>
<span id="cb29-20"><a href="#cb29-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And a helper function, <code>strlen</code>:</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="dt">size_t</span> strlen<span class="op">(</span><span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>str<span class="op">)</span> <span class="op">{</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> len<span class="op">;</span></span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span>len <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> str<span class="op">[</span>len<span class="op">];</span> len<span class="op">++)</span></span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a>        asm<span class="op">(</span><span class="st">&quot;&quot;</span><span class="op">);</span></span>
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> len<span class="op">;</span></span>
<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Finally, we can start writing a main function that uses this
code:</p>
<div class="sourceCode" id="cb31"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> text <span class="op">=</span> <span class="st">&quot;hello world</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">;</span> <span class="co">// text to write</span></span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>  write<span class="op">(</span>STDOUT_FILENO<span class="op">,</span> text<span class="op">,</span> strlen<span class="op">(</span>text<span class="op">));</span> <span class="co">// write text to stdout</span></span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a>  fsync<span class="op">(</span>STDOUT_FILENO<span class="op">);</span> <span class="co">// flush stdout</span></span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> file_text <span class="op">=</span> <span class="st">&quot;Hello from file&quot;</span><span class="op">;</span> <span class="co">// text to write to file</span></span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> fd <span class="op">=</span> open<span class="op">(</span><span class="st">&quot;hello.txt&quot;</span><span class="op">,</span> O_CREAT <span class="op">|</span> O_TRUNC <span class="op">|</span> O_RDWR<span class="op">,</span> <span class="bn">0666</span><span class="op">);</span> <span class="co">// open, truncate, create file hello.txt</span></span>
<span id="cb31-8"><a href="#cb31-8" aria-hidden="true" tabindex="-1"></a>  write<span class="op">(</span>fd<span class="op">,</span> file_text<span class="op">,</span> strlen<span class="op">(</span>file_text<span class="op">));</span> <span class="co">// write the file text to file</span></span>
<span id="cb31-9"><a href="#cb31-9" aria-hidden="true" tabindex="-1"></a>  fsync<span class="op">(</span>fd<span class="op">);</span> <span class="co">// flush hello.txt</span></span>
<span id="cb31-10"><a href="#cb31-10" aria-hidden="true" tabindex="-1"></a>  close<span class="op">(</span>fd<span class="op">);</span> <span class="co">// close hello.txt</span></span>
<span id="cb31-11"><a href="#cb31-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-12"><a href="#cb31-12" aria-hidden="true" tabindex="-1"></a>  fd <span class="op">=</span> open<span class="op">(</span><span class="st">&quot;hello.txt&quot;</span><span class="op">,</span> O_RDONLY<span class="op">,</span> <span class="bn">0666</span><span class="op">);</span> <span class="co">// open the file hello.txt for reading</span></span>
<span id="cb31-13"><a href="#cb31-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-14"><a href="#cb31-14" aria-hidden="true" tabindex="-1"></a>  <span class="dt">char</span> read_from_file<span class="op">[</span>strlen<span class="op">(</span>file_text<span class="op">)</span> <span class="op">+</span> <span class="dv">1</span><span class="op">];</span> <span class="co">// the buffer to read into</span></span>
<span id="cb31-15"><a href="#cb31-15" aria-hidden="true" tabindex="-1"></a>  read<span class="op">(</span>fd<span class="op">,</span> <span class="op">(</span><span class="dt">void</span> <span class="op">*)</span>read_from_file<span class="op">,</span> strlen<span class="op">(</span>file_text<span class="op">));</span> <span class="co">// read from hello.txt to the buffer</span></span>
<span id="cb31-16"><a href="#cb31-16" aria-hidden="true" tabindex="-1"></a>  read_from_file<span class="op">[</span>strlen<span class="op">(</span>file_text<span class="op">)]</span> <span class="op">=</span> <span class="ch">&#39;</span><span class="sc">\n</span><span class="ch">&#39;</span><span class="op">;</span> <span class="co">// add a new line to the buffer</span></span>
<span id="cb31-17"><a href="#cb31-17" aria-hidden="true" tabindex="-1"></a>  write<span class="op">(</span>STDOUT_FILENO<span class="op">,</span> read_from_file<span class="op">,</span> strlen<span class="op">(</span>read_from_file<span class="op">));</span> <span class="co">// write the buffer to stdout</span></span>
<span id="cb31-18"><a href="#cb31-18" aria-hidden="true" tabindex="-1"></a>  fsync<span class="op">(</span>STDOUT_FILENO<span class="op">);</span> <span class="co">// flush stdout</span></span>
<span id="cb31-19"><a href="#cb31-19" aria-hidden="true" tabindex="-1"></a>  close<span class="op">(</span>fd<span class="op">);</span> <span class="co">// close hello.txt</span></span>
<span id="cb31-20"><a href="#cb31-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>After compiling it as above, you should have the following text:</p>
<div class="sourceCode" id="cb32"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="ex">hello</span> world</span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a><span class="ex">Hello</span> from file</span></code></pre></div>
<p>With <code>hello.txt</code> containing
<code>Hello from file</code>.</p>
<p>Writing some simple libc code isn’t that hard!</p>]]></description>
</item>
<item>
<title>A Guide to RSS</title>
<pubDate>Wed, 08 Feb 2023 13:15:00 +0000</pubDate>
<guid>https://blog/a-guide-to-rss.html</guid>
<description><![CDATA[<p>At the start of the year I decided to read more
quality stuff instead of mindlessly doom scrolling the internet. An
internet diet. I believe in discussing tools + methods to solve
problems, so here are some findings I had setting up an RSS feed,
reading from it, and some of the challenges along the way.</p>
<h2 id="setup">Setup</h2>
<p>If you’re like me, you want a few things:</p>
<ol type="1">
<li>Offline reading</li>
<li>Syncing</li>
<li>Caching</li>
<li>Mobile + Terminal + Web + Desktop clients</li>
</ol>
<p>To feasibly implement syncing across multiple devices, we’ll need a
server to host our RSS feed. I self-host <a
href="https://github.com/FreshRSS/FreshRSS">FreshRSS</a>, which acts as
both a web client and the server. It allows for syncing from many
clients, which is great, and it has an easy docker-compose file to pull
in all necessary dependencies. FreshRSS exposes an API as well as a
Google Reader compatible API, which most clients support. This supports
authentication, which is a nice feature for locking down your
server.</p>
<p>Finally, we’ll need clients that implement offline reading and heavy
caching for good performance, for mobile, the terminal, and the
desktop.</p>
<p>I use an Samsung S10 as my phone, which runs android. The app I use
on mobile is FeedMe, hooked up to my FreshRSS server through the Google
Reader API. This heavily caches and works well offline, so on the go I
can read some feeds.</p>
<p>For a desktop client, I run a linux laptop, so I use Newsflash.
Newsflash is similar to FeedMe, with support for the Google Reader API,
and good offline capabilities. I tried a few other services, but they
couldn’t parse my large RSS feed.</p>
<p>For a terminal client, I use newsboat. Newsboat is a curses-based
text only feed, so RSS feeds that don’t send over the full article
content are a bad reading experience on newsboat. To deal with this, I
use <code>morss</code>, which scrapes the link provided by the RSS feed,
and then generates a new RSS feed with the content of the blog
included.</p>
<p><a href="https://github.com/pictuga/morss">morss</a> can be
downloaded with <code>pip</code>.</p>
<p>Now you should have everything set up, and can add some feeds to your
server, pull them down to your clients, and are ready to go.</p>
<p>But what if you’re new to this RSS game, and want to read some older
posts?</p>
<h2 id="reading-older-rss-posts">Reading Older RSS Posts</h2>
<p>Did you know that RSS can support older posts, and that blog
platforms like wordpress, blogger, and blogspot have those capabilities
built in? For example, let’s say I wanted to read James Clear’s old
posts. His current feed, located at
<code>https://jamesclear.com/feed</code> has 10 of his most recent blog
posts. But he’s published 300 more.</p>
<p>His blog actually has those old posts in RSS form for us, we just
have to find it.</p>
<p>Some blog sites’ RSS supports the <code>paged</code> query parameter.
<code>paged=1</code> means the first page, and <code>paged=2</code>
means the second page. In Jamesclear’s case, we just have to binary
search to find the last RSS feed supported by the website.</p>
<p>We could start out at
<code>https://jamesclear.com/feed?paged=100</code>, realize that doesn’t
work, try <code>https://jamesclear.com/feed?paged=50</code>, realize
that doesn’t work, go to
<code>https://jamesclear.com/feed?paged=25</code>, see that works, and
then figure out the last page, which as of now is page 30.</p>
<p>We can then download all of those rss feeds with a handy dandy bash
script:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">#!/usr/bin/env bash</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> num <span class="kw">in</span> <span class="va">$(</span><span class="fu">seq</span> 1 30<span class="va">)</span><span class="kw">;</span> <span class="cf">do</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  <span class="fu">wget</span> <span class="st">&quot;https://jamesclear.com/feed?paged=</span><span class="va">$num</span><span class="st">&quot;</span> <span class="at">-O</span> <span class="va">$num</span>.rss</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="cf">done</span></span></code></pre></div>
<p>And then we can download the 30 rss feeds.</p>
<p>We now have 30 rss feeds that have the content we want to read. But
having to add 30 entries to our RSS client is a bit of a pain: let’s
aggregate them.</p>
<p>I wrote a little script that would batch these into feeds with 150
posts each, using <code>feedgen</code> and <code>feedparser</code>.</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode python"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co">#!/usr/bin/env python3</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> feedparser</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> feedgen.feed <span class="im">import</span> FeedGenerator</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> glob <span class="im">import</span> glob</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>files <span class="op">=</span> glob(<span class="st">&#39;*.rss&#39;</span>)</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>file_count <span class="op">=</span> <span class="bu">len</span>(files)</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>file_generators <span class="op">=</span> []</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>((file_count <span class="op">//</span> <span class="dv">15</span>) <span class="op">+</span> <span class="dv">1</span>):</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>    fg <span class="op">=</span> FeedGenerator()</span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>    fg.<span class="bu">id</span>(<span class="st">&#39;https://jamesclear.com/&#39;</span>)</span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>    fg.title(<span class="ss">f&#39;James Clear Page </span><span class="sc">{</span>file_count <span class="op">//</span> <span class="dv">15</span> <span class="op">-</span> i <span class="op">+</span> <span class="dv">1</span><span class="sc">}</span><span class="ss">&#39;</span>)</span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>    fg.link(href<span class="op">=</span><span class="st">&#39;https://jamesclear.com/&#39;</span>)</span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>    fg.author( {<span class="st">&#39;name&#39;</span>:<span class="st">&#39;James Clear&#39;</span>,<span class="st">&#39;email&#39;</span>:<span class="st">&#39;jamesclear@gmail.com&#39;</span>} )</span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>    fg.link(href<span class="op">=</span><span class="st">&#39;https://jamesclear.com/&#39;</span>, rel<span class="op">=</span><span class="st">&#39;alternate&#39;</span> )</span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>    fg.logo(<span class="st">&#39;https://jamesclear.com/favicon.ico&#39;</span>)</span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>    fg.subtitle(<span class="st">&#39;An Easy &amp; Proven Way to Build Good Habits &amp; Break Bad Ones&#39;</span>)</span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>    fg.link(href<span class="op">=</span><span class="st">&#39;https://jamesclear.com/feed&#39;</span>, rel<span class="op">=</span><span class="st">&#39;self&#39;</span> )</span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>    fg.language(<span class="st">&#39;en&#39;</span>)</span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>    file_generators.append(fg)</span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> index, file_name <span class="kw">in</span> <span class="bu">enumerate</span>(files):</span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a>    file_generator_index <span class="op">=</span> index <span class="op">//</span> <span class="dv">15</span></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a>    <span class="cf">with</span> <span class="bu">open</span>(file_name) <span class="im">as</span> f:</span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a>        xml <span class="op">=</span> f.read()</span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a>        d <span class="op">=</span> feedparser.parse(xml)</span>
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> entry <span class="kw">in</span> d.entries:</span>
<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a>            fe <span class="op">=</span> file_generators[file_generator_index].add_entry()</span>
<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a>            fe.<span class="bu">id</span>(entry[<span class="st">&#39;link&#39;</span>])</span>
<span id="cb2-32"><a href="#cb2-32" aria-hidden="true" tabindex="-1"></a>            fe.title(entry[<span class="st">&#39;title&#39;</span>])</span>
<span id="cb2-33"><a href="#cb2-33" aria-hidden="true" tabindex="-1"></a>            fe.link(href<span class="op">=</span>entry[<span class="st">&#39;link&#39;</span>])</span>
<span id="cb2-34"><a href="#cb2-34" aria-hidden="true" tabindex="-1"></a>            fe.content(entry[<span class="st">&#39;content&#39;</span>][<span class="dv">0</span>][<span class="st">&#39;value&#39;</span>])</span>
<span id="cb2-35"><a href="#cb2-35" aria-hidden="true" tabindex="-1"></a>            fe.description(entry[<span class="st">&#39;summary&#39;</span>])</span>
<span id="cb2-36"><a href="#cb2-36" aria-hidden="true" tabindex="-1"></a>            fe.author(entry[<span class="st">&#39;authors&#39;</span>][<span class="dv">0</span>])</span>
<span id="cb2-37"><a href="#cb2-37" aria-hidden="true" tabindex="-1"></a>            fe.guid(entry[<span class="st">&#39;link&#39;</span>])</span>
<span id="cb2-38"><a href="#cb2-38" aria-hidden="true" tabindex="-1"></a>            fe.pubDate(entry[<span class="st">&#39;published&#39;</span>])</span>
<span id="cb2-39"><a href="#cb2-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-40"><a href="#cb2-40" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> index, fg <span class="kw">in</span> <span class="bu">enumerate</span>(<span class="bu">reversed</span>(file_generators)):</span>
<span id="cb2-41"><a href="#cb2-41" aria-hidden="true" tabindex="-1"></a>    fg.rss_file(<span class="ss">f&quot;../site/james-clear-</span><span class="sc">{</span>index <span class="op">+</span> <span class="dv">1</span><span class="sc">}</span><span class="ss">.rss&quot;</span>)</span></code></pre></div>
<p>We can then aggregate these rss feeds into two rss feeds, and then
put them in a folder. I host my RSS feeds on the web using netlify,
<code>https://takashis-rss.netlify.app/</code> so that my RSS server can
pull these feeds and get the content from them.</p>
<p>You can use any web hosting service you like, or self-host it. It’s
up to you, it just needs to be online for the RSS server to be able to
pull down.</p>
<h2 id="what-about-atom">What about Atom?</h2>
<p>Not all feeds are RSS feeds, some are Atom feeds. Take
https://blog.computationalcomplexity.org/ for example. Atom doesn’t
support the <code>paged</code> query parameter. But it supports
something even better. We’ll first download their feed at
https://blog.computationalcomplexity.org/feeds/posts/default and open it
up in a text editor. Inside, we should be able to find that it has 2980
articles, and they can be queried with a different query paramter,
called <code>start-index</code>.</p>
<p>So
https://blog.computationalcomplexity.org/feeds/posts/default?start-index=100
fetches the 100th - 125th blog post. We want to do this until we hit the
2980th article:</p>
<p>To do that, we edit the previous script a bit:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co">#!/usr/bin/env bash</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> num <span class="kw">in</span> <span class="va">$(</span><span class="fu">seq</span> 1 25 2980<span class="va">)</span><span class="kw">;</span> <span class="cf">do</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  <span class="fu">wget</span> <span class="st">&quot;https://blog.computationalcomplexity.org/feeds/posts/default?start-index=</span><span class="va">$num</span><span class="st">&quot;</span> <span class="at">-O</span> <span class="va">$num</span>.rss</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="cf">done</span></span></code></pre></div>
<p>And we can fetch all the posts, and aggregate them much the same way
as above.</p>
<h2 id="rendering-more-content-with-morss">Rendering more content with
morss</h2>
<p>This is good enough for some feeds, but some feeds only show a little
bit of content, which is undesirable for terminal readers like
<code>newsboat</code>, which don’t fetch the entire article, just the
RSS content.</p>
<p>We can download <code>morss</code> with <code>pip</code> and run this
script, which renders the feed with a web browser and scrapes it into an
RSS feed.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="co">#!/usr/bin/env bash</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> num <span class="kw">in</span> <span class="va">$(</span><span class="fu">seq</span> 1 37<span class="va">)</span><span class="kw">;</span> <span class="cf">do</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  <span class="va">LIM_ITEM</span><span class="op">=</span>-1 <span class="va">MAX_ITEM</span><span class="op">=</span>-1 <span class="ex">morss</span> <span class="st">&quot;https://travelfreak.com/feed?paged=</span><span class="va">$num</span><span class="st">&quot;</span> <span class="op">&gt;</span> <span class="va">$num</span>.rss</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="cf">done</span></span></code></pre></div>
<p>This lets us get around those pesky feeds with no content and just a
link.</p>]]></description>
</item>
<item>
<title>How to index your library</title>
<pubDate>Mon, 23 Jan 2023 13:34:32 +0000</pubDate>
<guid>https://blog/how-to-index-your-library.html</guid>
<description><![CDATA[<p>Books are nice. They make transferring
knowledge easy, and are a way to record things for the future. What’s
not nice is searching through them. Who uses a glossary nowadays?</p>
<p>Another problem: my collection of books is too large to put in my
tiny apartment:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> find . <span class="at">-type</span> f <span class="at">-name</span> <span class="st">&quot;*.pdf&quot;</span> <span class="kw">|</span> <span class="fu">wc</span> <span class="at">-l</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ex">223</span></span></code></pre></div>
<p>But if I have these books, I might as well index them, so I can
search for them quickly:</p>
<p>First, since pdfs are binary, we’ll have to extract their textual
content to a file:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co">#!/usr/bin/env bash</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="fu">title_case()</span> <span class="kw">{</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  <span class="fu">sed</span> <span class="st">&#39;s/.*/\L&amp;/; s/[a-z]*/\u&amp;/g&#39;</span> <span class="op">&lt;&lt;&lt;</span> <span class="va">$1</span> <span class="kw">|</span> <span class="fu">tr</span> <span class="st">&#39;-&#39;</span> <span class="st">&#39; &#39;</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">}</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> f <span class="kw">in</span> <span class="va">$(</span><span class="fu">find</span> . <span class="at">-type</span> f <span class="at">-name</span> <span class="st">&quot;*.pdf&quot;</span><span class="va">)</span><span class="kw">;</span> <span class="cf">do</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>  <span class="va">based_name</span><span class="op">=</span><span class="va">$(</span><span class="fu">basename</span> <span class="va">$f</span> .pdf<span class="va">)</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>  <span class="va">txt_name</span><span class="op">=</span><span class="st">&quot;</span><span class="va">${f</span><span class="op">%</span>.<span class="pp">*</span><span class="va">}</span><span class="st">.txt&quot;</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="kw">[[</span> <span class="ot">-f</span> <span class="st">&quot;</span><span class="va">$txt_name</span><span class="st">&quot;</span> <span class="kw">]];</span> <span class="cf">then</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>    <span class="bu">echo</span> <span class="st">&quot;</span><span class="va">$txt_name</span><span class="st"> exists.&quot;</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">continue</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>  <span class="cf">fi</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>  <span class="ex">pdftotext</span> <span class="va">$f</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>  <span class="va">title_cased_name</span><span class="op">=</span><span class="va">$(</span><span class="ex">title_case</span> <span class="va">$based_name)</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>  <span class="bu">echo</span> <span class="at">-e</span> <span class="st">&quot;</span><span class="va">$title_cased_name</span><span class="st">\n\n&quot;</span> <span class="kw">|</span> <span class="fu">cat</span> <span class="at">-</span> <span class="va">$txt_name</span> <span class="kw">|</span> <span class="ex">sponge</span> <span class="va">$txt_name</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a><span class="cf">done</span></span></code></pre></div>
<p>Next, we have to index the actual content. To do that, we’ll put our
text content into a search engine, like <a
href="https://github.com/valeriansaliou/sonic">sonic</a>.</p>
<p>Grab the binary and set it up.</p>
<p>Next, we’ll grab a client to pass data to sonic:</p>
<p>Create a Gemfile in a directory:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode rb"><code class="sourceCode ruby"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>source <span class="vs">&#39;https://rubygems.org&#39;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>gem <span class="vs">&#39;sonic-ruby&#39;</span></span></code></pre></div>
<p>Bundle install the gem:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> bundle install</span></code></pre></div>
<p>Next, create a file called <code>ingest.rb</code>. This will ingest
your textual data:</p>
<p>Since the client I’m using right now doesn’t have throttling, it
causes a panic caused by a buffer overflow on the search engine by
shoving too much data too quickly. To fix this, I overwrite that method
in the file and use it.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode rb"><code class="sourceCode ruby"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">require</span> <span class="vs">&#39;sonic-ruby&#39;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="cf">module</span> <span class="dt">Sonic</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">module</span> <span class="dt">Channels</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    <span class="fu">refine</span> <span class="dt">Ingest</span> <span class="cf">do</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>      <span class="cf">def</span> push(collection, bucket, object, text, lang <span class="op">=</span> <span class="dv">nil</span>)</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>        <span class="fu">puts</span> <span class="st">&quot;processing </span><span class="sc">#{</span>object<span class="sc">}</span><span class="st">&quot;</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>        text_size <span class="op">=</span> text<span class="at">.size</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>        text <span class="op">=</span> text<span class="at">.encode</span>(<span class="vs">&#39;UTF-8&#39;</span>, <span class="wa">:invalid</span> <span class="op">=&gt;</span> <span class="wa">:replace</span>, <span class="wa">:undef</span> <span class="op">=&gt;</span> <span class="wa">:replace</span>)</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>        right <span class="op">=</span> <span class="dv">5000</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>        left <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>        <span class="fu">loop</span> <span class="cf">do</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>          <span class="cf">break</span> <span class="cf">if</span> right <span class="op">&gt;</span> text_size</span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>          arr <span class="op">=</span> <span class="kw">[</span>collection, bucket, object, quote(text<span class="kw">[</span>left<span class="op">...</span>right<span class="kw">]</span><span class="at">.gsub</span>(<span class="ch">&#39;&quot;&#39;</span>, <span class="vs">&#39;&#39;</span>))<span class="kw">]</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>          arr <span class="op">&lt;&lt;</span> <span class="st">&quot;LANG(</span><span class="sc">#{</span>lang<span class="sc">}</span><span class="st">)&quot;</span> <span class="cf">if</span> lang</span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a>          execute(<span class="vs">&#39;PUSH&#39;</span>, <span class="op">*</span>arr)</span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a>          right <span class="op">+=</span> <span class="dv">5000</span></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a>          left <span class="op">+=</span> <span class="dv">5000</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a>        <span class="cf">end</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true" tabindex="-1"></a>      <span class="cf">end</span></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true" tabindex="-1"></a>    <span class="cf">end</span></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true" tabindex="-1"></a>  <span class="cf">end</span></span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true" tabindex="-1"></a><span class="cf">end</span></span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-28"><a href="#cb5-28" aria-hidden="true" tabindex="-1"></a><span class="fu">using</span> <span class="dt">Sonic</span><span class="op">:</span><span class="wa">:Channels</span></span>
<span id="cb5-29"><a href="#cb5-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-30"><a href="#cb5-30" aria-hidden="true" tabindex="-1"></a><span class="co"># Connect to the Sonic server on localhost:1491</span></span>
<span id="cb5-31"><a href="#cb5-31" aria-hidden="true" tabindex="-1"></a>client <span class="op">=</span> <span class="dt">Sonic</span><span class="op">::</span><span class="dt">Client</span><span class="at">.new</span>(<span class="vs">&#39;localhost&#39;</span>, <span class="dv">1491</span>, <span class="vs">&#39;SecretPassword&#39;</span>)</span>
<span id="cb5-32"><a href="#cb5-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-33"><a href="#cb5-33" aria-hidden="true" tabindex="-1"></a><span class="co"># Connect to the ingest channel</span></span>
<span id="cb5-34"><a href="#cb5-34" aria-hidden="true" tabindex="-1"></a>ingest <span class="op">=</span> client<span class="at">.channel</span>(<span class="wa">:ingest</span>)</span>
<span id="cb5-35"><a href="#cb5-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-36"><a href="#cb5-36" aria-hidden="true" tabindex="-1"></a><span class="dt">Dir</span><span class="at">.glob</span>(<span class="st">&quot;$PATH_TO_FILES/**/*.txt&quot;</span>) <span class="cf">do</span> <span class="op">|</span>f<span class="op">|</span></span>
<span id="cb5-37"><a href="#cb5-37" aria-hidden="true" tabindex="-1"></a>  pdf_name <span class="op">=</span> f<span class="kw">[</span><span class="dv">0</span><span class="op">..-</span><span class="dv">3</span><span class="kw">]</span> <span class="op">+</span> <span class="vs">&#39;pdf&#39;</span></span>
<span id="cb5-38"><a href="#cb5-38" aria-hidden="true" tabindex="-1"></a>  text <span class="op">=</span> <span class="cn">IO</span><span class="at">.read</span>(f)</span>
<span id="cb5-39"><a href="#cb5-39" aria-hidden="true" tabindex="-1"></a>  ingest<span class="at">.push</span>(<span class="vs">&#39;books&#39;</span>, <span class="vs">&#39;all&#39;</span>, pdf_name, text)</span>
<span id="cb5-40"><a href="#cb5-40" aria-hidden="true" tabindex="-1"></a><span class="cf">end</span></span></code></pre></div>
<p>Run that script with:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ex">ruby</span> ingest.rb</span></code></pre></div>
<p>And then lets get searching! Create this file as
<code>search.rb</code>:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode rb"><code class="sourceCode ruby"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="fu">require</span> <span class="vs">&#39;sonic-ruby&#39;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="cn">ARGV</span><span class="at">.length</span> <span class="op">!=</span> <span class="dv">1</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>  <span class="fu">puts</span> <span class="st">&quot;Too many names ... or not enough name?&quot;</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>  <span class="fu">exit</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="cf">else</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>  name <span class="op">=</span> <span class="cn">ARGV</span><span class="kw">[</span><span class="dv">0</span><span class="kw">]</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a><span class="cf">end</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a><span class="co"># Connect to the Sonic server on localhost:1491</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>client <span class="op">=</span> <span class="dt">Sonic</span><span class="op">::</span><span class="dt">Client</span><span class="at">.new</span>(<span class="vs">&#39;localhost&#39;</span>, <span class="dv">1491</span>, <span class="vs">&#39;SecretPassword&#39;</span>)</span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a><span class="co"># Connect to the search channel</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a>search <span class="op">=</span> client<span class="at">.channel</span>(<span class="wa">:search</span>)</span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a><span class="fu">puts</span> <span class="st">&quot;searching for </span><span class="sc">#{</span>name<span class="sc">}</span><span class="st">&quot;</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true" tabindex="-1"></a><span class="co"># Search for a matching name and return ID</span></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true" tabindex="-1"></a>search<span class="at">.query</span>(<span class="vs">&#39;books&#39;</span>, <span class="vs">&#39;all&#39;</span>, name, <span class="dv">100</span>)<span class="at">.split</span>(<span class="ch">&#39; &#39;</span>)<span class="at">.each</span> <span class="cf">do</span> <span class="op">|</span>doc<span class="op">|</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true" tabindex="-1"></a>  <span class="fu">puts</span> doc</span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true" tabindex="-1"></a><span class="cf">end</span></span></code></pre></div>
<p>And then run a search:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> ruby search.rb <span class="st">&quot;Oysters&quot;</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="ex">searching</span> for Oysters</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="ex">/books/programming-languages/python/effective-python.pdf</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="ex">/books/math/probability-theory-the-logic-of-science.pdf</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="ex">/books/algorithms/programming-pearls.pdf</span></span></code></pre></div>
<p>And that’s it. How to index your books in 15 minutes or less,
guaranteed or your money back.</p>]]></description>
</item>
<item>
<title>Recommended Resources</title>
<pubDate>Thu, 19 Jan 2023 02:39:20 +0000</pubDate>
<guid>https://blog/recommended-resources.html</guid>
<description><![CDATA[<p>Here’s a list of resources I enjoyed, with a
few comments.</p>
<h2 id="papers">Papers</h2>
<ul>
<li><a
href="https://www.cs.utexas.edu/users/mckinley/papers/asplos-2000.pdf">Hoard:
A Scalable Memory Allocator for Multithreaded Applications</a>: Hoard is
a parallel memory allocator that avoids fragmentation and false sharing
by hoarding memory from the single-threaded system memory allocators and
giving it out in parallel for better performance.</li>
<li><a href="https://dl.acm.org/doi/pdf/10.1145/358549.358561">The
Emperor’s Old Clothes</a>: Hoare, of quicksort and ALGOL fame, explains
why simplicitly is a virtue, and how a committee can destroy a language.
He mentions how bounds checking was implemented in ALGOL, and
composition allowed it to grow to become a simple yet powerful
language.</li>
<li><a
href="https://www.cs.virginia.edu/~evans/cs655/readings/steele.pdf">Growing
a Language</a>: A paper about how to build a language to grow – a
language should be flexible, have a welcoming community, have generics
and operator overloading, and worse is better.</li>
<li><a
href="http://alexander.shen.free.fr/library/Kolmogorov65_Three-Approaches-to-Information.pdf">Three
Approaches to the Quantitative Definition of Information</a>: This paper
formulates what’s now called Kolmogorov complexity, which states that
the entropy of an object is determined by the smallest possible
programming language that can express said information. This explains
compression, signal processing, and many other things in CS in just 5
pages.</li>
<li><a href="https://cseweb.ucsd.edu/~wgg/smli_ps-1.pdf">Technology and
Courage</a>: A paper by technology pioneer, Ivan Sutherland, who was on
the team at MIT who built the first tablet. This paper goes into his
high level thoughts about business, software, and life.</li>
<li><a
href="https://www.cs.cmu.edu/~rdriley/487/papers/Thompson_1984_ReflectionsonTrustingTrust.pdf">Reflections
on Trusting Trust</a>: A classic paper on how software isn’t really
trustable unless you examine both the tools to build it and the code
itself. This paper was surprisngly prescient, given the security
problems we have now with software.</li>
<li><a href="https://ieeexplore.ieee.org/document/1291819">Hazard
Pointers: Safe Memory Reclamation for Lock-Free Objects</a>: It was
thought for a long time that garbage collection was a prerequisite to
fast concurrent data structures, due to the lack of efficient
bookkeeping for when to free parts of a data structure correctly. This
paper discusses hazard pointers, a way to mark parts of a data structure
as freeable even without garbage collection.</li>
<li><a
href="https://people.csail.mit.edu/shanir/publications/Lazy_Concurrent.pdf">A
Lazy Concurrent List-Based Set Algorithm</a>: This paper details
concurrent Skip Lists, which was implemented in the java collections
library in Java 1.6.</li>
<li><a
href="http://www.usenix.org/events/hotos03/tech/full_papers/candea/candea.pdf">Crash
Only Software</a>: A paper on explaining why crash-only software is
good, and a classification of such software.</li>
<li><a href="https://arxiv.org/pdf/1603.06549.pdf">Better bitmap
performance with Roaring bitmaps</a>: Roaring bitmaps, a faster data
structure and more storage efficient data structure for bitmaps, by
using both run-length encoding and array packing.</li>
<li><a href="https://hypirion.com/pdf/RMTrees.pdf">RRB-Trees: Efficient
Immutable Vectors</a>: RRB-Trees, the Relaxed Radix Balanced Tree, is a
purely functional data structure that is an improved version of the
HAMT, the Hash Array Mapped Trie, which is the vector data structure in
Scala and Clojure.</li>
<li><a href="https://people.csail.mit.edu/rivest/pubs/BFPRT73.pdf">Time
Bounds for Selection</a>: A paper that explains the <code>PICK</code>
selection algorithm, which can select the ith smallest of n numbers in
O(n) time. This algorithm is more commonly known as quickselect.</li>
<li><a
href="https://academic.oup.com/comjnl/article-pdf/5/1/10/1111445/050010.pdf">Quicksort</a>:
A paper that explains the classic quicksort algorithm, the first O(n log
n) sorting algorithm that took sublinear memory.</li>
<li><a
href="https://web.mit.edu/Saltzer/www/publications/endtoend/endtoend.pdf">End
to End Arguments in System Design</a>: A paper on a design principle,
the “End to End” argument, that explains why having functionality at the
lower levels of a system may be redundant or useless compared to putting
them at a higher level of a system.</li>
<li><a href="https://arxiv.org/abs/2106.05123">Pattern Defeating
Quicksort</a>: A sorting algorithm for the Dutch National flag problem,
which can solve it in O(nk) time. This is the current unstable sort
algorithm in rust, with an ~5-10% better performance over the current
rust stable sort, timsort.</li>
</ul>
<h2 id="links">Links</h2>
<ul>
<li><a href="https://beej.us/guide/bgnet/html/">Beej’s Guide to Network
Programming</a> Learn how to program network sockets in C.</li>
</ul>
<h2 id="courses">Courses</h2>
<ul>
<li><a
href="https://ocw.mit.edu/courses/6-172-performance-engineering-of-software-systems-fall-2018/">MIT
Performance Engineering of Software Systems</a>: A good course to learn
more about computer architecture and what’s going on under the hood when
you execute code.</li>
<li><a
href="https://www.cs.umd.edu/class/fall2022/cmsc430/index.html">Design
and Implementation of Programming Languages</a>: A course that
incrementally introduces compilers, by implementing a compiler that
emits x86 assembly.</li>
<li><a href="https://web.stanford.edu/class/cs168/index.html">The Modern
Algorithmic Toolbox</a>: A course that thoroughly explains useful
algorithms and what they can be used for, with lots of real world
examples.</li>
<li><a
href="https://15445.courses.cs.cmu.edu/fall2019/schedule.html">Database
Systems</a>: A course all about databases, explaining algorithms and
data structures for indexes, storage, logging, locking, and concurrency
protocols, like MVCC and 2PL.</li>
</ul>
<h2 id="books">Books</h2>
<ul>
<li><a
href="https://www.amazon.com/ARM-System-Developers-Guide-Architecture/dp/1558608745">ARM
System Developer’s Guide</a>: Details the ARM ISA. A bit dated at this
point, but covers the fundamentals.</li>
<li><a
href="https://www.amazon.com/Algorithms-Data-Structures-Massive-Datasets/dp/1617298034">Algorithms
and Data Structures for Massive Datasets</a>: Algorithms and data
structures that scale to meet the demands of large datasets.</li>
<li><a href="https://en.algorithmica.org/hpc/">Algorithms for Modern
Hardware</a>: A great resource for learning about performance
engineering.</li>
<li><a
href="https://www.amazon.com/Antifragile-Things-That-Disorder-Incerto/dp/0812979680">Antifragile</a>:
A sequel to the Black Swan, focusing on things that get stronger when
put under stress, and how to build systems that do the same.</li>
<li><a
href="https://www.amazon.com/Behind-Deep-Blue-Building-Computer/dp/0691118183">Behind
Deep Blue</a>: A book about the team that built deep blue, the first
computer to defeat the world chess champion.</li>
<li><a
href="https://www.amazon.com/Algorithms-Data-Structures-Massive-Datasets/dp/1617298034">Computational
Geometry</a>: a book that looks at algorithms geometrically. There’s
sections on calculating nearest neighbors, object collision, mapping
algorithms, dimension reduction, graphs, and even querying a database. I
didn’t know computational geometry had so many applications!</li>
<li><a href="https://craftinginterpreters.com/">Crafting
Interpreters</a>: Learn about compilers by implementing two interpreters
for a full featured language named lox.</li>
<li><a href="https://www.databass.dev/">Database Internals: A Deep
Dive</a>: A book that teaches databases in two parts: storage engines,
and then as distributed databases.</li>
<li><a
href="https://www.amazon.com/Designing-Data-Intensive-Applications-Reliable-Maintainable/dp/1449373321">Designing
Data Driven Databases</a>: The best book for learning about distributed
systems.</li>
<li><a href="https://gameprogrammingpatterns.com/">Game Programming
Patterns</a>: A book about Design Patterns for game development. The
examples are in C++, and focused on games, but can be applied to many
domains outside of it.</li>
<li><a
href="https://www.amazon.com/High-Performance-MySQL-Optimization-Replication/dp/1449314287">High
Performance MySQL</a>: Learn about how to use and deploy MySQL, while
squeezing as much performance as possible while dodging pitfalls.</li>
<li><a
href="http://www.irrationalexuberance.com/main.html?src=%2F">Irrational
Exuberance</a>: A book about economic bubbles and regression to the
mean.</li>
<li><a
href="https://www.amazon.com/Kill-Fire-Manage-Computer-Systems/dp/1718501188">Kill
it with Fire</a>: explains how to maintain and extend legacy systems,
with notes on leading teams and driving change.</li>
<li><a href="http://learnyouahaskell.com/">Learn you a Haskell for Great
Good!</a>: An introduction to haskell, a statically and strongly typed
functional programming language.</li>
<li><a href="https://learnyousomeerlang.com/">Learn you some Erlang for
Great Good!</a>: An introductory book to Erlang/OTP, a functional
programming language with lots of libraries suited for web
programming.</li>
<li><a
href="https://www.amazon.com/Kill-Fire-Manage-Computer-Systems/dp/1718501188">Meditations</a>:
A classic book by Marcus Aurelius on the stoic philosophy, with gems
that still ring true today.</li>
<li><a href="https://pages.cs.wisc.edu/~remzi/OSTEP/">Operating Systems,
Three Easy Pieces</a>: A book that tackles teaching operating systems in
three pieces: virtualization, concurrency, and persistence.</li>
<li><a
href="https://www.amazon.com/Probabilistic-Data-Structures-Algorithms-Applications/dp/3748190484">Probabilistic
Data Structures and Algorithms for Big Data Applications</a>: A book on
probabilistic data structures that are useful for big data. The six
chapters cover many data structures for each problem.</li>
<li><a
href="https://www.amazon.com/Programming-Pearls-2nd-Jon-Bentley/dp/0201657880">Programming
Pearls</a>: Algorithms and data structures that Jon Bentely, the creator
of kd-trees explains in succint prose. There’s a lot of great exercises
and the author’s storytelling makes the book an entertaining and fast
read.</li>
<li><a
href="https://www.amazon.com/Designing-Data-Intensive-Applications-Reliable-Maintainable/dp/1449373321">Proofs:
A long form Mathematics Textbook</a>: An approachable book on proofs
with lots of problems and stories. Proofs and being able to read
mathematical notation are much more useful than I would’ve thought.</li>
<li><a
href="https://www.amazon.com/Purely-Functional-Data-Structures-Okasaki/dp/0521663504">Purely
Functional Data Structures</a>: A book on data structures for functional
languages, like SML.</li>
<li><a href="https://sql-performance-explained.com/">SQL Performance
Explained</a>: The book that made indexes click for me, with
accompanying SQL code in many dialects of SQL, like SQL Server, Oracle,
MySQL, and Postgres.</li>
<li><a
href="https://www.amazon.com/Probabilistic-Data-Structures-Algorithms-Applications/dp/3748190484">Seven
Concurrency Models in Seven Weeks</a>: concurrency models in many
different languages, including java, clojure, and erlang, and how they
differ, with quick explanations on the pros and cons of each.</li>
<li><a
href="https://www.amazon.com/Probabilistic-Data-Structures-Algorithms-Applications/dp/3748190484">Seven
Databases in Seven Weeks</a>: a whirlwind tour of some common NoSQL
databases, like Redis, Neo4j, DynamoDB, and Hbase.</li>
<li><a
href="https://www.brendangregg.com/blog/2020-07-15/systems-performance-2nd-edition.html">Systems
Performance: Enterprise and the Cloud</a>: Learn how to profile and
improve performance and observability of systems. A must have for
anybody learning in a big tech company.</li>
<li><a
href="https://www.amazon.com/Art-Multiprocessor-Programming-Revised-Reprint/dp/0123973376">The
Art of Multiprocessor Programming</a>: A book that goes into great depth
about concurrent programming, with thorough exercises.</li>
<li><a
href="https://www.amazon.com/Black-Swan-Improbable-Robustness-Fragility/dp/081297381X">The
Black Swan</a>: An options trader explains why outlier events are
actually quite common and hard to hedge against. I picked this up for
the nod to Popper, but stayed for the thoughts on the market.</li>
<li><a
href="https://www.amazon.com/Innovators-Dilemma-Revolutionary-Change-Business/dp/0062060244">The
Innovator’s Dilemma</a>: How companies adjust (and don’t adjust) to
change, and how incumbents lose market share to new competitors.</li>
<li><a href="https://man7.org/tlpi/">The Linux Programming
Interface</a>: a book on the linux OS, glibc, and system calls. Waiting
for a second edition soemday to cover io_uring, cgroups, and other
things.</li>
<li><a
href="https://www.amazon.com/Kill-Fire-Manage-Computer-Systems/dp/1718501188">The
Little Book of Semaphores</a>: A gentle introduction to mutual exclusion
by introducing semaphores, the basis of almost all concurrent
algorithms.</li>
</ul>
<h2 id="utilities">Utilities</h2>
<ul>
<li><a href="https://fishshell.com/">fish</a>: A shell with completions
and sane scripting</li>
<li><a href="https://github.com/CloudCannon/pagefind">pagefind</a>:
Static search that works offline without needing to run a local
server</li>
<li><a href="https://pandoc.org/">pandoc</a>: A universal document
converter</li>
<li><a href="https://github.com/clulab/pdf2txt">pdf2txt</a>: Reading
pdfs as plain text</li>
<li><a href="https://github.com/BurntSushi/ripgrep">ripgrep</a>: Grep
but faster</li>
<li><a href="https://github.com/plasma-umass/scalene">scalene</a>: To
diagnose python performance problems</li>
<li><a href="https://termux.dev/en/">termux</a>: Run a unix terminal on
your android phone</li>
<li><a href="https://github.com/panamax-rs/panamax">panamax</a>: Mirror
crates.io locally</li>
</ul>]]></description>
</item>
<item>
<title>The agora and the hivemind</title>
<pubDate>Sun, 12 Jun 2022 00:53:26 +0000</pubDate>
<guid>https://blog/the-agora-and-the-hivemind.html</guid>
<description><![CDATA[<p>Have you ever felt like there’s so much to do,
but you never make any progress? When I worked as an office worker, my
manager drilled it into us that to remain competitive in an increasingly
connected global economy, workers would have to be able to multitask –
handle many requests in flight concurrently and work on them in
parallel, bringing together stakeholders to build consensus.</p>
<p>As a line cook in a restaurant, it was expected that cooks would be
able to do any role in the restaurant – order ingredients, clean dishes,
serve customers, prep ingredients, the whole shebang, especially in
parallel.</p>
<p>As a warehouse worker, we were expected to be able to handle a larger
number of requests every month, with the same or smaller team, mentally
juggling many POs at the same time to meet tighter deadlines for the
sake of efficiency.</p>
<p>As a tech worker, we were expected to exceed for our customers –
answer pings at 3 a.m, make sure our service was free of security
defects, make a bi-weekly “agile” show and tell, and work on our project
while having 7 hours of meetings a day.</p>
<p>All these jobs had disastrous consequences – the office workers
became so unproductive that they quit in droves, many of the line cooks
suffered physical injury, including losing a finger, and the warehouse
workers, well, many of them had to go on disability. Many of the tech
workers quit as well, tired of being unproductive and overworked.</p>
<p>I could pontificate about how shareholder capitalism is at odds with
labor, but I’ll leave that for another time. Instead, I’ll talk about
how overstimulation via the internet is leading to an increase in
multitasking, crippling our one true superpower – the ability to
concentrate.</p>
<p>Lots has been said about increasing productivity in the workplace
(it’s been a hot topic for over a century now), but I’ve noticed in
myself and others that we can’t concentrate as well as we used to. We
turn to our phones for diet entertainment, forgoing the relaxation and
concentration of past times.</p>
<p>Sustenance farmers did it best, I think. When I lived on a farm, the
schedule was simple – wake up at 5 or so, before the sun rises to get
washed up, eat a small meal, and dressed to tackle the day’s work.</p>
<p>You’d work slowly, maybe handling some maintenance tasks like setting
up a net so the animals don’t eat your crops, or patching holes in rice
paddies so those dang beavers don’t drain all the water from your patch.
In the summer, it’d get too hot by 11 or so, so you’d retire back home,
eat a small lunch, and take a nap – four, five hours.</p>
<p>After that, you’d set out again after the heat cooled off, finishing
off your tasks for the day, maybe leaving some tools outside for
tomorrow, taking note of what needs to be done, before retiring to eat
dinner, wash up and sleep for the next day.</p>
<p>Sometimes you needed your plots to lay fallow, or sometimes the other
people in your village would share tools, or maybe someone needed to be
a substitute teacher for the little ones because the only teacher in
town had a family emergency. You wouldn’t think of things in terms of
money – you’d repay each other with favors and do the right thing (most
of the time). You could borrow someone else’s plot that hasn’t been used
in a while, maybe in exchange for something like crops or tools or a
service, like fixing up their house’s roof. We’d congregate at the town
center, asking for favors, doing favors, and building up the shared
community. People were happy, for the most part.</p>
<p>Most of us used to lead that kind of life, until the businesspeople
lured us over to factories with the promise of <em>wages</em> and
<em>benefits</em>, promising us milk and honey but leaving us with
regrets and sadness.</p>
<p>Thanks for nothing, capitalists.</p>
<p>Industrialization was one game changer, but the internet was another.
Instead of having a set of town centers, one for each town or
thereabouts, we can now have a town center in our own houses (or pocket,
with cell phones).</p>
<p>With this kind of super power, we should be able to use it to our own
benefit. And we did, kind of. There’s lots of nice services these days
that make our lives easier, but they don’t make our lives more
fulfilling.</p>
<p>And in exchange, we’ve lost our ability to focus, robbing us of one
of the paths to fulfillment.</p>
<p>We’ve all become part of the hivemind.</p>
<p>It’s impossible to have all of us disconnect. There will only be a
few people who want to build their own house off the grid and grow their
own crops and maintain a solar panel for electricity.</p>
<p>For the rest of us, we can only set boundaries – but I implore you to
think about the agora model – where we only go to town a few days out of
the week at most. We don’t always have to be connected. A slower pace of
life isn’t bad.</p>
<p>For me, as a programmer, that means downloading the resources I need
to work offline. On my personal computer, I have a copy of the
documentation of all the tools I work with, books, papers, and
syllabuses for courses I’d like to learn from, and offline copies of
interesting websites that I could learn a lot from (mainly in the form
of rss, but a recursive wget does the trick for sites that don’t have an
rss feed), copies of music I like listening to.</p>
<p>I only need to go online sometimes, since I’ll always have something
to enjoy.</p>
<p>One side effect is that you won’t hate the airplane as much – I just
open up a paper I’ve wanted to read, a textbook, a course, and jump
right in. It’s a wonderful way to pass the time and really feel
productive by the end.</p>]]></description>
</item>
<item>
<title>Learn Computer Science</title>
<pubDate>Sun, 12 Jun 2022 00:50:29 +0000</pubDate>
<guid>https://blog/learn-computer-science.html</guid>
<description><![CDATA[<p>I have a confession to make. I, (and most of
us) have been stuck on fad diets for CS. It’s so nice to read easy
books, like learn C++ in 21 days, or doing some leetcode problems. You
learn a bit, feel that warm glow of getting smarter, and trick yourself
into feeling productive.</p>
<p>You’re not really getting any better, without learning the
fundamentals.</p>
<p>I decided to cobble up a set of resources to go through, as a fusion
of <a href="https://teachyourselfcs.com/">Teach Yourself Computer
Science</a> and <a
href="https://www.youtube.com/watch?v=Q4Y6ERYAwqw">Steve Yegge</a>’s
recommendations.</p>
<p>Teach Yourself CS has a detailed list of good resources for the more
practical aspects of CS, whereas Steve Yegge’s recommendations focus
more on the mathematical side – the first four courses he recommends
are: discrete math, linear algebra, statistics, and theory of
computation.</p>
<p>Steve Yegge’s list omits Computer Architecture, which is a glaring
omission – an Operating Systems course doesn’t have enough time to cover
all the interesting parts of concurrency, parallelism, and optimization
that a computer architecture course would.</p>
<p>Teach Yourself CS doesn’t mention Theory of Computation, and is
lighter on the math background, giving one resource for math. Theory of
Computation is a bit more dated (swallowed up by all the other fields),
but is still useful for its applications.</p>
<p>To that end, I’ve fused them both, and skimmed some resources to put
on this list.</p>
<p>This list is incomplete and changing all the time, but hey, isn’t
that what agile development is all about?</p>
<h2 id="programming">Programming</h2>
<h3 id="textbooks">Textbooks</h3>
<ol type="1">
<li>Structure and Interpretation of Computer Programs</li>
</ol>
<h3 id="courses">Courses</h3>
<h3 id="papers">Papers</h3>
<h3 id="projects">Projects</h3>
<h2 id="discrete-math">Discrete Math</h2>
<h3 id="textbooks-1">Textbooks</h3>
<ol type="1">
<li>Discrete Mathematics, an open introduction</li>
</ol>
<h2 id="linear-algebra">Linear Algebra</h2>
<h3 id="textbooks-2">Textbooks</h3>
<ol type="1">
<li>No bullshit guide to linear Algebra, Savov</li>
</ol>
<h2 id="statistics">Statistics</h2>
<h3 id="textbooks-3">Textbooks</h3>
<ol type="1">
<li>Statistics fourth ed, Friedman et. al</li>
<li>Think stats, Downey</li>
<li>Think Bayes, Downey</li>
</ol>
<h2 id="theory-of-computation">Theory of Computation</h2>
<h3 id="textbooks-4">Textbooks</h3>
<ol type="1">
<li>Theory of Computation, Hefferon</li>
<li>Computational Complexity, Arora and Barak</li>
</ol>
<h2 id="computer-architecture">Computer Architecture</h2>
<h3 id="textbooks-5">Textbooks</h3>
<ol type="1">
<li>Computer Architecture, a Programmers Perspective</li>
<li>Computer Architecture, Patterson and Hennessey</li>
</ol>
<h3 id="resources">Resources</h3>
<ol type="1">
<li>Some Assembly Required</li>
</ol>
<h2 id="algorithms-and-data-structures">Algorithms and Data
Structures</h2>
<h3 id="textbooks-6">Textbooks</h3>
<ol type="1">
<li>The Algorithm Design Manual, Skiena</li>
<li>The Art of Multiprocessor programming</li>
</ol>
<h2 id="operating-systems">Operating Systems</h2>
<h3 id="textbooks-7">Textbooks</h3>
<ol type="1">
<li>Operating Systems, Three Easy Pieces</li>
</ol>
<h2 id="networking">Networking</h2>
<h3 id="textbooks-8">Textbooks</h3>
<ol type="1">
<li>Computer Networks, a Systems approach</li>
</ol>
<h3 id="projects-1">Projects</h3>
<ol type="1">
<li>Chitcp</li>
</ol>
<h2 id="databases">Databases</h2>
<h3 id="textbooks-9">Textbooks</h3>
<ol type="1">
<li>Database Internals</li>
</ol>
<h3 id="projects-2">Projects</h3>
<ol type="1">
<li>Chidb</li>
</ol>
<h2 id="compilers">Compilers</h2>
<h3 id="textbooks-10">Textbooks</h3>
<ol type="1">
<li>Crafting Interpreters</li>
</ol>
<h3 id="resources-1">Resources</h3>
<ol type="1">
<li><a href="https://github.com/rui314/chibicc">Chibicc</a></li>
</ol>
<h2 id="distributed-systems">Distributed Systems</h2>
<h3 id="textbooks-11">Textbooks</h3>
<ol type="1">
<li>Designing Data Intensive Applications</li>
</ol>]]></description>
</item>
<item>
<title>Writing Compilers</title>
<pubDate>Mon, 10 Jan 2022 22:48:22 +0000</pubDate>
<guid>https://blog/writing-compilers.html</guid>
<description><![CDATA[<p>In his post “Rich Programmer Food”, Steve Yegge
explains why you should learn compilers:</p>
<blockquote>
<p>If you don’t know how compilers work, then you don’t know how
computers work. If you’re not 100% sure whether you know how compilers
work, then you don’t know how they work.</p>
</blockquote>
<p>Throughout this post, Steve has some witticisms and some harsh
realizations:</p>
<blockquote>
<p>If you don’t take compilers then you run the risk of forever being on
the programmer B-list: the kind of eager young architect who becomes a
saturnine old architect who spends a career building large systems and
being damned proud of it.</p>
</blockquote>
<p>While I wouldn’t say the article <strong>wholly</strong> convinced me
to learn about compilers, I do agree that compilation problems are
everywhere.</p>
<p>In front-end work, where I started off, there’s a glut of frameworks.
React, Angular, Vue, Svelte, with some tooling like webpack, parcel,
esbuild, babel and browserify.</p>
<p>What do they all have in common? They’re all compilers. React takes
JSX and turns it into HTML and JS.</p>
<p>Angular launched Typescript, which is a language that compiles to
Javascript.</p>
<p>Vue has <code>.vue</code> templates, which compile to HTML, CSS, and
JS.</p>
<p>Svelte has its own <code>.svelte</code> files.</p>
<p>All the other build tools I mentioned take javascript, minify it,
tree-shake it (dead-code elimination) and bundle it for you so it can be
served on the internet.</p>
<p>All of these are compiler problems.</p>
<p>My favorite language, Rust, has a great deal of compiler work in the
core language and design tradeoffs to make it easy for new people to
adopt and experienced people to enjoy.</p>
<p>In Mobile, Kotlin and Swift, as well as many libraries, all reduce to
compiler problems – they end up manipulating ASTs to produce better
code, or compile to some bytecode that is executed on the target
platform.</p>
<p>Compiler problems really are everywhere.</p>
<p>Here’s another quote from Ras Bodik:</p>
<blockquote>
<p>Don’t be a boilerplate programmer. Instead, build tools for users and
other programmers. Take historical note of textile and steel industries:
do you want to build machines and tools, or do you want to operate those
machines?</p>
</blockquote>
<p>Got the message? Compilers are really important. Or so I think. But
how does one learn compilers? Well, let’s scour the internet.</p>
<h2 id="a-plan-of-attack">A Plan of Attack</h2>
<p>There’s no shortage of great materials on compilers on the internet,
but I want to focus on three resources I’m currently using to learn
compilers, since I think they run the gamut: One’s a great starting
resource, another is a great medium level resource, and one is extremely
hard but rewarding.</p>
<p>The Resources:</p>
<ol type="1">
<li><a href="https://keleshev.com/compiling-to-assembly-from-scratch/"
class="uri">https://keleshev.com/compiling-to-assembly-from-scratch/</a></li>
<li><a href="https://craftinginterpreters.com/"
class="uri">https://craftinginterpreters.com/</a></li>
<li><a href="https://github.com/rui314/chibicc"
class="uri">https://github.com/rui314/chibicc</a></li>
</ol>
<h2 id="compiling-to-assembly-from-scratch">Compiling to Assembly from
Scratch</h2>
<p>Compiling to Assembly from Scratch is the first resource I looked at
to start my compiler writing journey. It’s a short book on how to write
a small ARM32 emitting compiler in Typescript. It does this by parsing
using a parser combinator, and then emitting simple ARM32 code using the
visitor pattern.</p>
<p>Parser combinators are a technique for parsing that’s been picking up
steam recently. Because Typescript has first-class regex, this technique
really fits well here.</p>
<p>The book also goes over basic ARM32 instructions, and at the end of
this pretty short book (~200 pages), you have a working compiler that
turns a subset of javascript into ARM32.</p>
<p>Worth every penny.</p>
<h2 id="crafting-interpreters">Crafting Interpreters</h2>
<p>Crafting Interpreters is a great book – the first half of the book
covers writing a tree-walk interpreter in Java, while the second half of
the book involves writing a bytecode VM in C for a non-trivial language
called “Lox”.</p>
<p>Bob Nystrom really knows his stuff – the prose is clean, and every
line of code written is well explained.</p>
<p>That being said, for the first part, I didn’t really want to write
any Java (sorry Oracle), so I found a transcription of the first part of
the book’s code in Rust <a href="https://github.com/jeschkies/lox-rs"
class="uri">https://github.com/jeschkies/lox-rs</a> and used that code
as the basis for the first part of the book.</p>
<p>At the end of the first part of the book, I really felt as though I
got the hang of the basics of compiler writing.</p>
<p>I still need to go through the second part, but I’m really enjoying
it so far!</p>
<h2 id="chibicc">ChibiCC</h2>
<p>This resource is a bit different: It’s a git repo by the creator of
mold (the new LLVM linker) to create a C Compiler (CC) in C.</p>
<p>This repository follows the paper “An Incremental Approach to
Compiler Construction” by Ghuloum, <a
href="http://scheme2006.cs.uchicago.edu/11-ghuloum.pdf"
class="uri">http://scheme2006.cs.uchicago.edu/11-ghuloum.pdf</a> which
advocates writing a simple compiler step by step and adding
functionality little by little.</p>
<p>Rui Ueyama, the author of this repo, writes clean C code for every
commit, and each message details adding a new feature to the C compiler.
There’s no accompanying instructional material, so you’re on your own to
read the diffs and try to ascribe meaning to them, but it is important
to read lots of code, and what better way to start than in such a
structured format?</p>
<h2 id="conclusion">Conclusion</h2>
<p>After going through a few resources for compiler construction, I’m
starting to get a better understanding of compilers, and seeing those
kinds of problems crop up all the time. Writing compilers has also
motivated me to read more code, and I’m hoping to be able to read code
from larger projects to write better code in the
future!</p>]]></description>
</item>
<item>
<title>Writing Portable C</title>
<pubDate>Mon, 15 Nov 2021 23:06:09 +0000</pubDate>
<guid>https://blog/writing-portable-c.html</guid>
<description><![CDATA[<p>On my free time I’ve been hacking away on <a
href="https://github.com/Takashiidobe/unix-utils">unix-utils</a>, a
project that implements some common unix utilities. In order to test how
portable C really is for the average programmer, I decided to lean on
open source to see how many platforms I could target my C with. I wanted
to write the most portable code I could (that meant targeting only
POSIX) functions and using a minimalistic stdlib that tried its best to
adhere to the standards (musl). This let me write C code for about 50
targets. Let’s go deeper into the background and how that was all
possible:</p>
<h2 id="posix-and-sus">POSIX and SUS</h2>
<p>In the 70s, C was made at AT&amp;T. In the 80s, it escaped, becoming
more popular, before eventually becoming standardized by ANSI (C89). But
what about standards for Operating Systems? Enter POSIX (the Portable
Operating System Interface), a standard for operating system interfaces.
In 1988, the first version of POSIX was released by the IEEE, which
detailed common interfaces, like Signals, pipes, and the C standard
library.</p>
<p>The POSIX standards were fairly minimalistic in the 80s, adding some
extensions (like real time programming) and thread extensions) in the
early 90s before being subsumed by the Austin Group, a committee that
designed the Single Unix Specification. The Austin Group has steered the
POSIX standards since 1997, creating standards like (POSIX 1997/SUS v2),
(POSIX 2001/SUS v3), and (POSIX 2008/SUS v4).</p>
<p>Since 2008, there have been two minor corrections to the POSIX
standards (one in 2011 and 2017), but the two most common POSIX
standards in use are POSIX 2001 and 2008, which is where we’ll be
directing most of our attention to.</p>
<p>POSIX compliance in particular ends up being extremely important,
because most Operating Systems have at least some level of POSIX
compliance. Linux, the BSDs, Mac OS, and Windows all do to some extent.
That means that our C code can target all of them by following the
standards, which makes our code more flexible.</p>
<p>This is so important that GCC (GNU’s C Compiler) ended up
implementing a flag that checks for strict compliance to the POSIX
standard of your choice.</p>
<p>In my Makefile, I have this line, which says to compile my code
strictly according to the standard.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode numberSource make numberLines"><code class="sourceCode"><span id="cb1-1"><a href="#cb1-1"></a>CFLAGS = -std=c99 -D_POSIX_C_SOURCE=200809L</span></code></pre></div>
<p>Since I wrote the first draft of my utilities on a Mac OS computer
with no POSIX compatibility flags, you can imagine there was a lot of
breakage. As to why there was so much breakage, well, that requires
another history lesson.</p>
<h2 id="gcc-vs-musl">GCC vs MUSL</h2>
<p>In the 80s, the Free Software Foundation (FSF) wanted to create the
ideal “Free” programming environment. To do so, they were going to start
from the top-down, by implementing the user space (a C compiler, a
shell, the POSIX shell utilities, etc), and then build an OS kernel (GNU
Hurd). GNU succeeded at one part of their mission, by providing the most
common userspace tools to date (GCC, Bash, and the GNU utils). However,
GNU’s kernel lost out to Linux, and the rest is history.</p>
<p>Linux started out only supporting GCC tools for its userspace, but
now it can support a wide variety of C standard libraries (libc for
short). One of those ends up being Musl, the standard library of this
article.</p>
<p>The choice of standard library would end up being entirely
inconsequential if not for one detail: Musl supports static linking, and
GCC does not.</p>
<p>Sure GCC supports a lot of non-standard extensions, and sure GCC
executables are more bloaty than their musl counterparts, but static
linking lets us execute our binaries without having installed a libc on
the platform.</p>
<p>That means our code can reach even more users!</p>
<p>Much blood has been spilt on static vs dynamic linking, so I will
spare you the carnage by simply saying that static linking tends to be
more convenient for the end user (they require less dependencies on
their side to run the code), which is good for us, the application
builders.</p>
<h2 id="what-sacrifices-were-made">What Sacrifices were made?</h2>
<h3 id="how-do-you-make-static-binaries">How do you make static
binaries?</h3>
<p>Going back to building some unix utilities, I downloaded a musl-gcc
compiler, logged into my linux VM and started compiling.</p>
<p>The first issue I ran into was that musl-gcc didn’t compile static
binaries.</p>
<p>I added the flag <code>-static</code> to my build, but
<code>file</code> and <code>ldd</code> ended up telling me that my
binary was still dynamically linked.</p>
<p>I dug through troves of documentation. Eventually, I discovered that
it wasn’t enough just to provide the <code>-static</code> flag, because
GCC can ignore it. You have to provide another flag,
<code>--static</code> as well. Oh, and if that wasn’t enough, that still
didn’t compile static binaries. You had to disable <code>pie</code>, or
<code>position independent executables</code> with the flag
<code>-no-pie</code> as well.</p>
<p>Finally, I had compiled a hello world binary statically. Time to move
on!</p>
<h3 id="dont-name-your-functions-_init">Don’t name your functions
<code>_init</code></h3>
<p>I then tried to compile my utilities. I wanted to decrease
duplication so I wrote a header file with a function called
<code>_init</code>. This ended up causing a duplicate symbol error (musl
defines this function in crti.o first).</p>
<p>Of course, GCC never complained, so I had to rename this
function.</p>
<h3 id="getopt_long-doesnt-exist"><code>getopt_long</code> doesn’t
exist</h3>
<p>Next up, <code>getopt_long</code> (Get options with long flags) isn’t
POSIX standard. Unshocking. POSIX only specifies the normal
<code>getopt</code>, which supports short options only. Long options
like <code>--file</code> or <code>--color</code> are a GNUism.</p>
<p>I ended up finding a copy of <code>getopt_long</code> online and
rewriting my header file includes for my utilities.</p>
<h3 id="sysctl-isnt-standard">Sysctl isn’t standard</h3>
<p>Next up, I had a compiler error where my implementation of
<code>uptime</code> failed to compile. <code>&lt;sys/sysctl.h&gt;</code>
is a Macism, and not part of POSIX. Linux offers it up in
<code>&lt;linux/sysctl.h&gt;</code> for convenience, but as its name
might indicate, it’s not portable.</p>
<p>Next!</p>
<h3 id="lstat-has-optional-fields">lstat has optional fields</h3>
<p>In my implementation of stat, I used the functions
<code>major</code>, <code>minor</code> and <code>ctime</code>, none of
which are POSIX compliant. They’re useful on mac os, so I can gate them
behind an <code>__APPLE__</code> macro, but that makes the code less
succinct. Oh well.</p>
<h3 id="ni_maxhost-isnt-defined"><code>NI_MAXHOST</code> isn’t
defined</h3>
<p>As an oddity, musl doesn’t define <code>NI_MAXHOST</code> at all.
This is useful for <code>dig</code>, which returns the ip address for a
given address. I ended up defining it if it wasn’t already defined.</p>
<h2 id="getting-the-toolchains">Getting the Toolchains</h2>
<p>With all these changes made, our code will now compile for Linux +
musl, thankfully. The next problem was actually getting our
toolchains.</p>
<p>Luckily, after some googling, I found out about &lt;musl.cc&gt;, a
website which releases versions of musl-gcc toolchains.</p>
<p>Now, since I didn’t want to create an undue amount of load onto this
website, I created a mirror of it: <a
href="https://github.com/Takashiidobe/muslcc"
class="uri">https://github.com/Takashiidobe/muslcc</a>.</p>
<p>Next, I had to create a github action that would fetch the compiler
required, set it up properly, compile all of the binaries, strip the
debug information, tar them into one directory, and release them on a
push to tags. Phew!</p>
<p>This part turned out to be a lot of guesswork and letting it run, so
I’ll leave the final results here:</p>
<p><a
href="https://github.com/Takashiidobe/unix-utils/blob/master/.github/workflows/release.yml"
class="uri">https://github.com/Takashiidobe/unix-utils/blob/master/.github/workflows/release.yml</a></p>
<p>And the repo here:</p>
<p><a href="https://github.com/Takashiidobe/unix-utils"
class="uri">https://github.com/Takashiidobe/unix-utils</a></p>
<h2 id="in-short">In Short</h2>
<p>It’s amazing that you can write code that targets so many
architectures, and compile to them easily, all for free, with the power
of open source (and Microsoft’s wallet, thanks Github Actions).</p>
<p>With this, I was able to build for 52 architectures and release code
for them (I ended up adding in support for x86_64 Darwin and arm64
Darwin).</p>
<p>Viva portable code.</p>]]></description>
</item>
<item>
<title>Building Rust binaries for different platforms</title>
<pubDate>Wed, 03 Nov 2021 14:24:46 +0000</pubDate>
<guid>https://blog/building-rust-binaries-for-different-platforms.html</guid>
<description><![CDATA[<p>Rust has great support for cross compilation,
with <code>cross</code>, you can install the required c toolchain +
linker and cross compile your rust code to a binary that runs on your
targeted platform. Sweet!</p>
<p>If you’d like to look at the code and results, it’s in this repo
here: <a
href="https://github.com/Takashiidobe/rust-build-binary-github-actions"
class="uri">https://github.com/Takashiidobe/rust-build-binary-github-actions</a></p>
<p>Rust library writers use this feature to build and test for other
platforms than their own: <a
href="https://github.com/sharkdp/hyperfine/releases/tag/v1.12.0">hyperfine</a>
for example builds for 11 different platforms.</p>
<p>The <a
href="https://doc.rust-lang.org/stable/rustc/platform-support.html">rustc
book</a> has a page on targets and tiers of support. Tier 1 supports 8
targets:</p>
<table>
<thead>
<tr>
<th>Tier 1</th>
</tr>
</thead>
<tbody>
<tr>
<td>aarch64-unknown-linux-gnu</td>
</tr>
<tr>
<td>i686-pc-windows-gnu</td>
</tr>
<tr>
<td>i686-unknown-linux-gnu</td>
</tr>
<tr>
<td>i686-pc-windows-msvc</td>
</tr>
<tr>
<td>x86_64-apple-darwin</td>
</tr>
<tr>
<td>x86_64-pc-windows-gnu</td>
</tr>
<tr>
<td>x86_64-pc-windows-msvc</td>
</tr>
<tr>
<td>x86_64-unknown-linux-gnu</td>
</tr>
</tbody>
</table>
<p>Tier 2 with Host tools supports 21 targets.</p>
<table>
<thead>
<tr>
<th>Tier 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>aarch64-apple-darwin</td>
</tr>
<tr>
<td>aarch64-pc-windows-msvc</td>
</tr>
<tr>
<td>aarch64-unknown-linux-musl</td>
</tr>
<tr>
<td>arm-unknown-linux-gnueabi</td>
</tr>
<tr>
<td>arm-unknown-linux-gnueabihf</td>
</tr>
<tr>
<td>armv7-unknown-linux-gnueabihf</td>
</tr>
<tr>
<td>mips-unknown-linux-gnu</td>
</tr>
<tr>
<td>mips64-unknown-linux-gnuabi64</td>
</tr>
<tr>
<td>mips64el-unknown-linux-gnuabi64</td>
</tr>
<tr>
<td>mipsel-unknown-linux-gnuabi</td>
</tr>
<tr>
<td>powerpc-unknown-linux-gnu</td>
</tr>
<tr>
<td>powerpc64-unknown-linux-gnu</td>
</tr>
<tr>
<td>powerpc64le-unknown-linux-gnu</td>
</tr>
<tr>
<td>riscv64gc-unknown-linux-gnu</td>
</tr>
<tr>
<td>s390x-unknown-linux-gnu</td>
</tr>
<tr>
<td>x86_64-unknown-freebsd</td>
</tr>
<tr>
<td>x86_64-unknown-illumos</td>
</tr>
<tr>
<td>arm-unknown-linux-musleabihf</td>
</tr>
<tr>
<td>i686-unknown-linux-musl</td>
</tr>
<tr>
<td>x86_64-unknown-linux-musl</td>
</tr>
<tr>
<td>x86_64-unknown-netbsd</td>
</tr>
</tbody>
</table>
<p>Let’s try to build a binary for all 29 targets.</p>
<h2 id="a-note-on-targets">A Note on Targets</h2>
<p>The Rust RFC for Target support: <a
href="https://rust-lang.github.io/rfcs/0131-target-specification.html"
class="uri">https://rust-lang.github.io/rfcs/0131-target-specification.html</a></p>
<p>A target is defined in three or four parts:</p>
<p><code>$architecture-$vendor-$os-$environment</code></p>
<p>The environment is optional, so some targets have three parts and
some have four.</p>
<p>Let’s take <code>x86_64-apple-darwin</code> for example.</p>
<ul>
<li><code>x86_64</code> is the architecture</li>
<li><code>apple</code> is the vendor</li>
<li><code>darwin</code> is the os</li>
</ul>
<p>You’ll notice here that there is no <code>$environment</code>. This
target assumes the environment, which is most likely to be
<code>gnu</code>.</p>
<p>Let’s take one with four parts:
<code>i686-pc-windows-msvc</code>.</p>
<ul>
<li><code>i686</code> is the architecture</li>
<li><code>pc</code> is the vendor</li>
<li><code>windows</code> is the os</li>
<li><code>msvc</code> is the environment</li>
</ul>
<p>In this target, the environment is specified as <code>msvc</code>,
the microsoft C compiler. This is the most popular compiler for windows,
but it need not be: if you look in the same tier 1 table, there’s this
target: <code>i686-pc-windows-gnu</code>.</p>
<p>The only thing that’s changed is the environment is now
<code>gnu</code>. Windows can use <code>gcc</code> instead of
<code>msvc</code>, so building for this target uses the <code>gcc</code>
instead of <code>msvc</code>.</p>
<h3 id="architectures">Architectures</h3>
<table>
<thead>
<tr>
<th>Architecture</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td>aarch64</td>
<td>ARM 64 bit</td>
</tr>
<tr>
<td>i686</td>
<td>Intel 32 bit</td>
</tr>
<tr>
<td>x86_64</td>
<td>Intel 64 bit</td>
</tr>
<tr>
<td>arm</td>
<td>ARM 32 bit</td>
</tr>
<tr>
<td>armv7</td>
<td>ARMv7 32 bit</td>
</tr>
<tr>
<td>mips</td>
<td>MIPS 32 bit</td>
</tr>
<tr>
<td>mips64</td>
<td>MIPS 64 bit</td>
</tr>
<tr>
<td>mips64el</td>
<td>MIPS 64 bit Little Endian</td>
</tr>
<tr>
<td>mipsel</td>
<td>MIPS 32 bit Little Endian</td>
</tr>
<tr>
<td>powerpc</td>
<td>IBM 32 bit</td>
</tr>
<tr>
<td>powerpc64</td>
<td>IBM 64 bit</td>
</tr>
<tr>
<td>rsicv64gc</td>
<td>RISC-V 64 bit</td>
</tr>
<tr>
<td>s390x</td>
<td>IBM Z 32 bit</td>
</tr>
</tbody>
</table>
<h3 id="vendors">Vendors</h3>
<table>
<thead>
<tr>
<th>Vendor</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td>pc</td>
<td>Microsoft</td>
</tr>
<tr>
<td>apple</td>
<td>Apple</td>
</tr>
<tr>
<td>unknown</td>
<td>Unknown</td>
</tr>
</tbody>
</table>
<h3 id="operating-systems">Operating Systems</h3>
<table>
<thead>
<tr>
<th>Operating System</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td>darwin</td>
<td>Apple’s OS</td>
</tr>
<tr>
<td>linux</td>
<td>Linux OS</td>
</tr>
<tr>
<td>windows</td>
<td>Microsoft’s OS</td>
</tr>
<tr>
<td>freebsd</td>
<td>FreeBSD OS</td>
</tr>
<tr>
<td>netbsd</td>
<td>NetBSD OS</td>
</tr>
<tr>
<td>illumos</td>
<td>Illumos OS, a Solaris derivative</td>
</tr>
</tbody>
</table>
<h3 id="environments">Environments</h3>
<table>
<thead>
<tr>
<th>Environment</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td>musl</td>
<td>Musl C library</td>
</tr>
<tr>
<td>gnu</td>
<td>GNU’s C library</td>
</tr>
<tr>
<td>msvc</td>
<td>Microsoft Visual C library</td>
</tr>
<tr>
<td>freebsd</td>
<td>FreeBSD’s C library</td>
</tr>
<tr>
<td>netbsd</td>
<td>NetBSD’s C library</td>
</tr>
<tr>
<td>illumos</td>
<td>Illumos’ C library</td>
</tr>
</tbody>
</table>
<p>When you go to the releases tab to download a particular binary,
you’ll need to know these four things to download a binary that runs on
your system.</p>
<p>Now, let’s start building for all these systems.</p>
<h2 id="building-binaries-for-30-targets">Building Binaries for ~30
Targets</h2>
<p>We’re going to use Github Actions, a task runner on github.com to
build our binaries. Our binary is a simple <code>hello world</code>
binary.</p>
<p>If you’d just like to look at the github actions file, it’s located
here: <a
href="https://github.com/Takashiidobe/rust-build-binary-github-actions/blob/master/.github/workflows/release.yml"
class="uri">https://github.com/Takashiidobe/rust-build-binary-github-actions/blob/master/.github/workflows/release.yml</a></p>
<p>Conceptually, we’d like to do the following:</p>
<ul>
<li>Set up our target environments.</li>
<li>Download the C compiler (environment) we need.</li>
<li>Download a docker image of the OS we require.</li>
<li>Download the rust toolchain onto docker container.</li>
<li>Build the binary.</li>
<li><em>Optionally</em> strip debug symbols.</li>
<li>Publish it to the github releases tab.</li>
</ul>
<p>We’ll first start out by defining our github action and setting up
the target environments:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode numberSource yml numberLines"><code class="sourceCode yaml"><span id="cb1-1"><a href="#cb1-1"></a><span class="fu">name</span><span class="kw">:</span><span class="at"> release</span></span>
<span id="cb1-2"><a href="#cb1-2"></a></span>
<span id="cb1-3"><a href="#cb1-3"></a><span class="fu">env</span><span class="kw">:</span></span>
<span id="cb1-4"><a href="#cb1-4"></a><span class="at">  </span><span class="fu">MIN_SUPPORTED_RUST_VERSION</span><span class="kw">:</span><span class="at"> </span><span class="st">&quot;1.56.0&quot;</span></span>
<span id="cb1-5"><a href="#cb1-5"></a><span class="at">  </span><span class="fu">CICD_INTERMEDIATES_DIR</span><span class="kw">:</span><span class="at"> </span><span class="st">&quot;_cicd-intermediates&quot;</span></span>
<span id="cb1-6"><a href="#cb1-6"></a></span>
<span id="cb1-7"><a href="#cb1-7"></a><span class="fu">on</span><span class="kw">:</span></span>
<span id="cb1-8"><a href="#cb1-8"></a><span class="at">  </span><span class="fu">push</span><span class="kw">:</span></span>
<span id="cb1-9"><a href="#cb1-9"></a><span class="at">    </span><span class="fu">tags</span><span class="kw">:</span></span>
<span id="cb1-10"><a href="#cb1-10"></a><span class="at">      </span><span class="kw">-</span><span class="at"> </span><span class="st">&#39;*&#39;</span></span>
<span id="cb1-11"><a href="#cb1-11"></a></span>
<span id="cb1-12"><a href="#cb1-12"></a><span class="fu">jobs</span><span class="kw">:</span></span>
<span id="cb1-13"><a href="#cb1-13"></a><span class="at">  </span><span class="fu">build</span><span class="kw">:</span></span>
<span id="cb1-14"><a href="#cb1-14"></a><span class="at">    </span><span class="fu">name</span><span class="kw">:</span><span class="at"> ${{ matrix.job.target }} (${{ matrix.job.os }})</span></span>
<span id="cb1-15"><a href="#cb1-15"></a><span class="at">    </span><span class="fu">runs-on</span><span class="kw">:</span><span class="at"> ${{ matrix.job.os }}</span></span>
<span id="cb1-16"><a href="#cb1-16"></a><span class="at">    </span><span class="fu">strategy</span><span class="kw">:</span></span>
<span id="cb1-17"><a href="#cb1-17"></a><span class="at">      </span><span class="fu">fail-fast</span><span class="kw">:</span><span class="at"> </span><span class="ch">false</span></span>
<span id="cb1-18"><a href="#cb1-18"></a><span class="at">      </span><span class="fu">matrix</span><span class="kw">:</span></span>
<span id="cb1-19"><a href="#cb1-19"></a><span class="at">        </span><span class="fu">job</span><span class="kw">:</span></span>
<span id="cb1-20"><a href="#cb1-20"></a><span class="co">          # Tier 1</span></span>
<span id="cb1-21"><a href="#cb1-21"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> aarch64-unknown-linux-gnu      </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-22"><a href="#cb1-22"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> i686-pc-windows-gnu            </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> windows-2019                  </span><span class="kw">}</span></span>
<span id="cb1-23"><a href="#cb1-23"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> i686-unknown-linux-gnu         </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-24"><a href="#cb1-24"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> i686-pc-windows-msvc           </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> windows-2019                  </span><span class="kw">}</span></span>
<span id="cb1-25"><a href="#cb1-25"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> x86_64-apple-darwin            </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> macos-10.15                   </span><span class="kw">}</span></span>
<span id="cb1-26"><a href="#cb1-26"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> x86_64-pc-windows-gnu          </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> windows-2019                  </span><span class="kw">}</span></span>
<span id="cb1-27"><a href="#cb1-27"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> x86_64-pcwindows-msvc          </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> windows-2019                  </span><span class="kw">}</span></span>
<span id="cb1-28"><a href="#cb1-28"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> x86_64-unknown-linux-gnu       </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04                  </span><span class="kw">}</span></span>
<span id="cb1-29"><a href="#cb1-29"></a><span class="co">          # Tier 2 with Host Tools</span></span>
<span id="cb1-30"><a href="#cb1-30"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> aarch64-apple-darwin           </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> macos-11.0                    </span><span class="kw">}</span></span>
<span id="cb1-31"><a href="#cb1-31"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> aarch64-pc-windows-msvc        </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> windows-2019                  </span><span class="kw">}</span></span>
<span id="cb1-32"><a href="#cb1-32"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> aarch64-unknown-linux-musl     </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-33"><a href="#cb1-33"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> arm-unknown-linux-gnueabi      </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-34"><a href="#cb1-34"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> arm-unknown-linux-gnueabihf    </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-35"><a href="#cb1-35"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> armv7-unknown-linux-gnueabihf  </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-36"><a href="#cb1-36"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> mips-unknown-linux-gnu         </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-37"><a href="#cb1-37"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> mips64-unknown-linux-gnuabi64  </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-38"><a href="#cb1-38"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> mips64el-unknown-linux-gnuabi64</span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-39"><a href="#cb1-39"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> mipsel-unknown-linux-gnu       </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-40"><a href="#cb1-40"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> powerpc-unknown-linux-gnu      </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-41"><a href="#cb1-41"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> powerpc64-unknown-linux-gnu    </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-42"><a href="#cb1-42"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> powerpc64le-unknown-linux-gnu  </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-43"><a href="#cb1-43"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> riscv64gc-unknown-linux-gnu    </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-44"><a href="#cb1-44"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> s390x-unknown-linux-gnu        </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-45"><a href="#cb1-45"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> x86_64-unknown-freebsd         </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-46"><a href="#cb1-46"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> x86_64-unknown-illumos         </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-47"><a href="#cb1-47"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> arm-unknown-linux-musleabihf   </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-48"><a href="#cb1-48"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> i686-unknown-linux-musl        </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-49"><a href="#cb1-49"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> x86_64-unknown-linux-musl      </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span>
<span id="cb1-50"><a href="#cb1-50"></a><span class="at">          </span><span class="kw">-</span><span class="at"> </span><span class="kw">{</span><span class="at"> </span><span class="fu">target</span><span class="kw">:</span><span class="at"> x86_64-unknown-netbsd          </span><span class="kw">,</span><span class="at"> </span><span class="fu">os</span><span class="kw">:</span><span class="at"> ubuntu-20.04</span><span class="kw">,</span><span class="at"> </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span><span class="at"> </span><span class="kw">}</span></span></code></pre></div>
<h3 id="checking-out-our-code">Checking out our code:</h3>
<div class="sourceCode" id="cb2"><pre
class="sourceCode numberSource yml numberLines"><code class="sourceCode yaml"><span id="cb2-1"><a href="#cb2-1"></a><span class="at">    </span><span class="fu">steps</span><span class="kw">:</span></span>
<span id="cb2-2"><a href="#cb2-2"></a><span class="at">    </span><span class="kw">-</span><span class="at"> </span><span class="fu">name</span><span class="kw">:</span><span class="at"> Checkout source code</span></span>
<span id="cb2-3"><a href="#cb2-3"></a><span class="at">      </span><span class="fu">uses</span><span class="kw">:</span><span class="at"> actions/checkout@v2</span></span></code></pre></div>
<h3 id="downloading-the-c-compiler">Downloading the C compiler</h3>
<p>Most of the time, the C compiler we need is already installed, but in
some cases it’ll be overriden by another compiler.</p>
<p>We’ll need to download the correct suitable C compiler in that case:
(i686-pc-windows-gnu has gcc, but it’s not on the $PATH).</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode numberSource yml numberLines"><code class="sourceCode yaml"><span id="cb3-1"><a href="#cb3-1"></a><span class="at">    </span><span class="kw">-</span><span class="at"> </span><span class="fu">name</span><span class="kw">:</span><span class="at"> Install prerequisites</span></span>
<span id="cb3-2"><a href="#cb3-2"></a><span class="at">      </span><span class="fu">shell</span><span class="kw">:</span><span class="at"> bash</span></span>
<span id="cb3-3"><a href="#cb3-3"></a><span class="fu">      run</span><span class="kw">: </span><span class="ch">|</span></span>
<span id="cb3-4"><a href="#cb3-4"></a>        case ${{ matrix.job.target }} in</span>
<span id="cb3-5"><a href="#cb3-5"></a>          arm-unknown-linux-*) sudo apt-get -y update ; sudo apt-get -y install gcc-arm-linux-gnueabihf ;;</span>
<span id="cb3-6"><a href="#cb3-6"></a>          aarch64-unknown-linux-gnu) sudo apt-get -y update ; sudo apt-get -y install gcc-aarch64-linux-gnu ;;</span>
<span id="cb3-7"><a href="#cb3-7"></a>          i686-pc-windows-gnu) echo &quot;C:\msys64\mingw32\bin&quot; &gt;&gt; $GITHUB_PATH</span>
<span id="cb3-8"><a href="#cb3-8"></a>        esac</span></code></pre></div>
<h3 id="installing-the-rust-toolchain">Installing the Rust
toolchain</h3>
<div class="sourceCode" id="cb4"><pre
class="sourceCode numberSource yml numberLines"><code class="sourceCode yaml"><span id="cb4-1"><a href="#cb4-1"></a><span class="at">    </span><span class="kw">-</span><span class="at"> </span><span class="fu">name</span><span class="kw">:</span><span class="at"> Install Rust toolchain</span></span>
<span id="cb4-2"><a href="#cb4-2"></a><span class="at">      </span><span class="fu">uses</span><span class="kw">:</span><span class="at"> actions-rs/toolchain@v1</span></span>
<span id="cb4-3"><a href="#cb4-3"></a><span class="at">      </span><span class="fu">with</span><span class="kw">:</span></span>
<span id="cb4-4"><a href="#cb4-4"></a><span class="at">        </span><span class="fu">toolchain</span><span class="kw">:</span><span class="at"> stable</span></span>
<span id="cb4-5"><a href="#cb4-5"></a><span class="at">        </span><span class="fu">target</span><span class="kw">:</span><span class="at"> ${{ matrix.job.target }}</span></span>
<span id="cb4-6"><a href="#cb4-6"></a><span class="at">        </span><span class="fu">override</span><span class="kw">:</span><span class="at"> </span><span class="ch">true</span></span>
<span id="cb4-7"><a href="#cb4-7"></a><span class="at">        </span><span class="fu">profile</span><span class="kw">:</span><span class="at"> minimal</span><span class="co"> # minimal component installation (ie, no documentation)</span></span></code></pre></div>
<h3 id="building-the-executable">Building the executable</h3>
<div class="sourceCode" id="cb5"><pre
class="sourceCode numberSource yml numberLines"><code class="sourceCode yaml"><span id="cb5-1"><a href="#cb5-1"></a><span class="at">    </span><span class="kw">-</span><span class="at"> </span><span class="fu">name</span><span class="kw">:</span><span class="at"> Build</span></span>
<span id="cb5-2"><a href="#cb5-2"></a><span class="at">      </span><span class="fu">uses</span><span class="kw">:</span><span class="at"> actions-rs/cargo@v1</span></span>
<span id="cb5-3"><a href="#cb5-3"></a><span class="at">      </span><span class="fu">with</span><span class="kw">:</span></span>
<span id="cb5-4"><a href="#cb5-4"></a><span class="at">        </span><span class="fu">use-cross</span><span class="kw">:</span><span class="at"> ${{ matrix.job.use-cross }}</span></span>
<span id="cb5-5"><a href="#cb5-5"></a><span class="at">        </span><span class="fu">command</span><span class="kw">:</span><span class="at"> build</span></span>
<span id="cb5-6"><a href="#cb5-6"></a><span class="at">        </span><span class="fu">args</span><span class="kw">:</span><span class="at"> --locked --release --target=${{ matrix.job.target }}</span></span></code></pre></div>
<h3 id="stripping-debug-information-from-binary">Stripping debug
information from binary</h3>
<div class="sourceCode" id="cb6"><pre
class="sourceCode numberSource yml numberLines"><code class="sourceCode yaml"><span id="cb6-1"><a href="#cb6-1"></a><span class="at">    </span><span class="kw">-</span><span class="at"> </span><span class="fu">name</span><span class="kw">:</span><span class="at"> Strip debug information from executable</span></span>
<span id="cb6-2"><a href="#cb6-2"></a><span class="at">      </span><span class="fu">id</span><span class="kw">:</span><span class="at"> strip</span></span>
<span id="cb6-3"><a href="#cb6-3"></a><span class="at">      </span><span class="fu">shell</span><span class="kw">:</span><span class="at"> bash</span></span>
<span id="cb6-4"><a href="#cb6-4"></a><span class="fu">      run</span><span class="kw">: </span><span class="ch">|</span></span>
<span id="cb6-5"><a href="#cb6-5"></a>        # Figure out suffix of binary</span>
<span id="cb6-6"><a href="#cb6-6"></a>        EXE_suffix=&quot;&quot;</span>
<span id="cb6-7"><a href="#cb6-7"></a>        case ${{ matrix.job.target }} in</span>
<span id="cb6-8"><a href="#cb6-8"></a>          *-pc-windows-*) EXE_suffix=&quot;.exe&quot; ;;</span>
<span id="cb6-9"><a href="#cb6-9"></a>        esac;</span>
<span id="cb6-10"><a href="#cb6-10"></a>        # Figure out what strip tool to use if any</span>
<span id="cb6-11"><a href="#cb6-11"></a>        STRIP=&quot;strip&quot;</span>
<span id="cb6-12"><a href="#cb6-12"></a>        case ${{ matrix.job.target }} in</span>
<span id="cb6-13"><a href="#cb6-13"></a>          arm-unknown-linux-*) STRIP=&quot;arm-linux-gnueabihf-strip&quot; ;;</span>
<span id="cb6-14"><a href="#cb6-14"></a>          aarch64-pc-*) STRIP=&quot;&quot; ;;</span>
<span id="cb6-15"><a href="#cb6-15"></a>          aarch64-unknown-*) STRIP=&quot;&quot; ;;</span>
<span id="cb6-16"><a href="#cb6-16"></a>          armv7-unknown-*) STRIP=&quot;&quot; ;;</span>
<span id="cb6-17"><a href="#cb6-17"></a>          mips-unknown-*) STRIP=&quot;&quot; ;;</span>
<span id="cb6-18"><a href="#cb6-18"></a>          mips64-unknown-*) STRIP=&quot;&quot; ;;</span>
<span id="cb6-19"><a href="#cb6-19"></a>          mips64el-unknown-*) STRIP=&quot;&quot; ;;</span>
<span id="cb6-20"><a href="#cb6-20"></a>          mipsel-unknown-*) STRIP=&quot;&quot; ;;</span>
<span id="cb6-21"><a href="#cb6-21"></a>          powerpc-unknown-*) STRIP=&quot;&quot; ;;</span>
<span id="cb6-22"><a href="#cb6-22"></a>          powerpc64-unknown-*) STRIP=&quot;&quot; ;;</span>
<span id="cb6-23"><a href="#cb6-23"></a>          powerpc64le-unknown-*) STRIP=&quot;&quot; ;;</span>
<span id="cb6-24"><a href="#cb6-24"></a>          riscv64gc-unknown-*) STRIP=&quot;&quot; ;;</span>
<span id="cb6-25"><a href="#cb6-25"></a>          s390x-unknown-*) STRIP=&quot;&quot; ;;</span>
<span id="cb6-26"><a href="#cb6-26"></a>          x86_64-unknown-freebsd) STRIP=&quot;&quot; ;;</span>
<span id="cb6-27"><a href="#cb6-27"></a>          x86_64-unknown-illumos) STRIP=&quot;&quot; ;;</span>
<span id="cb6-28"><a href="#cb6-28"></a>        esac;</span>
<span id="cb6-29"><a href="#cb6-29"></a>        # Setup paths</span>
<span id="cb6-30"><a href="#cb6-30"></a>        BIN_DIR=&quot;${{ env.CICD_INTERMEDIATES_DIR }}/stripped-release-bin/&quot;</span>
<span id="cb6-31"><a href="#cb6-31"></a>        mkdir -p &quot;${BIN_DIR}&quot;</span>
<span id="cb6-32"><a href="#cb6-32"></a>        BIN_NAME=&quot;${{ env.PROJECT_NAME }}${EXE_suffix}&quot;</span>
<span id="cb6-33"><a href="#cb6-33"></a>        BIN_PATH=&quot;${BIN_DIR}/${BIN_NAME}&quot;</span>
<span id="cb6-34"><a href="#cb6-34"></a>        TRIPLET_NAME=&quot;${{ matrix.job.target }}&quot;</span>
<span id="cb6-35"><a href="#cb6-35"></a>        # Copy the release build binary to the result location</span>
<span id="cb6-36"><a href="#cb6-36"></a>        cp &quot;target/$TRIPLET_NAME/release/${BIN_NAME}&quot; &quot;${BIN_DIR}&quot;</span>
<span id="cb6-37"><a href="#cb6-37"></a>        # Also strip if possible</span>
<span id="cb6-38"><a href="#cb6-38"></a>        if [ -n &quot;${STRIP}&quot; ]; then</span>
<span id="cb6-39"><a href="#cb6-39"></a>          &quot;${STRIP}&quot; &quot;${BIN_PATH}&quot;</span>
<span id="cb6-40"><a href="#cb6-40"></a>        fi</span>
<span id="cb6-41"><a href="#cb6-41"></a>        # Let subsequent steps know where to find the (stripped) bin</span>
<span id="cb6-42"><a href="#cb6-42"></a>        echo ::set-output name=BIN_PATH::${BIN_PATH}</span>
<span id="cb6-43"><a href="#cb6-43"></a>        echo ::set-output name=BIN_NAME::${BIN_NAME}</span></code></pre></div>
<h3 id="and-uploading-to-github">And uploading to Github</h3>
<div class="sourceCode" id="cb7"><pre
class="sourceCode numberSource yml numberLines"><code class="sourceCode yaml"><span id="cb7-1"><a href="#cb7-1"></a><span class="at">    </span><span class="kw">-</span><span class="at"> </span><span class="fu">name</span><span class="kw">:</span><span class="at"> Create tarball</span></span>
<span id="cb7-2"><a href="#cb7-2"></a><span class="at">      </span><span class="fu">id</span><span class="kw">:</span><span class="at"> package</span></span>
<span id="cb7-3"><a href="#cb7-3"></a><span class="at">      </span><span class="fu">shell</span><span class="kw">:</span><span class="at"> bash</span></span>
<span id="cb7-4"><a href="#cb7-4"></a><span class="fu">      run</span><span class="kw">: </span><span class="ch">|</span></span>
<span id="cb7-5"><a href="#cb7-5"></a>        PKG_suffix=&quot;.tar.gz&quot; ; case ${{ matrix.job.target }} in *-pc-windows-*) PKG_suffix=&quot;.zip&quot; ;; esac;</span>
<span id="cb7-6"><a href="#cb7-6"></a>        PKG_BASENAME=${PROJECT_NAME}-v${PROJECT_VERSION}-${{ matrix.job.target }}</span>
<span id="cb7-7"><a href="#cb7-7"></a>        PKG_NAME=${PKG_BASENAME}${PKG_suffix}</span>
<span id="cb7-8"><a href="#cb7-8"></a>        echo ::set-output name=PKG_NAME::${PKG_NAME}</span>
<span id="cb7-9"><a href="#cb7-9"></a>        PKG_STAGING=&quot;${{ env.CICD_INTERMEDIATES_DIR }}/package&quot;</span>
<span id="cb7-10"><a href="#cb7-10"></a>        ARCHIVE_DIR=&quot;${PKG_STAGING}/${PKG_BASENAME}/&quot;</span>
<span id="cb7-11"><a href="#cb7-11"></a>        mkdir -p &quot;${ARCHIVE_DIR}&quot;</span>
<span id="cb7-12"><a href="#cb7-12"></a>        mkdir -p &quot;${ARCHIVE_DIR}/autocomplete&quot;</span>
<span id="cb7-13"><a href="#cb7-13"></a>        # Binary</span>
<span id="cb7-14"><a href="#cb7-14"></a>        cp &quot;${{ steps.strip.outputs.BIN_PATH }}&quot; &quot;$ARCHIVE_DIR&quot;</span>
<span id="cb7-15"><a href="#cb7-15"></a>        # base compressed package</span>
<span id="cb7-16"><a href="#cb7-16"></a>        pushd &quot;${PKG_STAGING}/&quot; &gt;/dev/null</span>
<span id="cb7-17"><a href="#cb7-17"></a>        case ${{ matrix.job.target }} in</span>
<span id="cb7-18"><a href="#cb7-18"></a>          *-pc-windows-*) 7z -y a &quot;${PKG_NAME}&quot; &quot;${PKG_BASENAME}&quot;/* | tail -2 ;;</span>
<span id="cb7-19"><a href="#cb7-19"></a>          *) tar czf &quot;${PKG_NAME}&quot; &quot;${PKG_BASENAME}&quot;/* ;;</span>
<span id="cb7-20"><a href="#cb7-20"></a>        esac;</span>
<span id="cb7-21"><a href="#cb7-21"></a>        popd &gt;/dev/null</span>
<span id="cb7-22"><a href="#cb7-22"></a>        # Let subsequent steps know where to find the compressed package</span>
<span id="cb7-23"><a href="#cb7-23"></a>        echo ::set-output name=PKG_PATH::&quot;${PKG_STAGING}/${PKG_NAME}&quot;</span>
<span id="cb7-24"><a href="#cb7-24"></a><span class="at">    </span><span class="kw">-</span><span class="at"> </span><span class="fu">name</span><span class="kw">:</span><span class="at"> </span><span class="st">&quot;Artifact upload: tarball&quot;</span></span>
<span id="cb7-25"><a href="#cb7-25"></a><span class="at">      </span><span class="fu">uses</span><span class="kw">:</span><span class="at"> actions/upload-artifact@master</span></span>
<span id="cb7-26"><a href="#cb7-26"></a><span class="at">      </span><span class="fu">with</span><span class="kw">:</span></span>
<span id="cb7-27"><a href="#cb7-27"></a><span class="at">        </span><span class="fu">name</span><span class="kw">:</span><span class="at"> ${{ steps.package.outputs.PKG_NAME }}</span></span>
<span id="cb7-28"><a href="#cb7-28"></a><span class="at">        </span><span class="fu">path</span><span class="kw">:</span><span class="at"> ${{ steps.package.outputs.PKG_PATH }}</span></span>
<span id="cb7-29"><a href="#cb7-29"></a></span>
<span id="cb7-30"><a href="#cb7-30"></a><span class="at">    </span><span class="kw">-</span><span class="at"> </span><span class="fu">name</span><span class="kw">:</span><span class="at"> Check for release</span></span>
<span id="cb7-31"><a href="#cb7-31"></a><span class="at">      </span><span class="fu">id</span><span class="kw">:</span><span class="at"> is-release</span></span>
<span id="cb7-32"><a href="#cb7-32"></a><span class="at">      </span><span class="fu">shell</span><span class="kw">:</span><span class="at"> bash</span></span>
<span id="cb7-33"><a href="#cb7-33"></a><span class="fu">      run</span><span class="kw">: </span><span class="ch">|</span></span>
<span id="cb7-34"><a href="#cb7-34"></a>        unset IS_RELEASE ; if [[ $GITHUB_REF =~ ^refs/tags/v[0-9].* ]]; then IS_RELEASE=&#39;true&#39; ; fi</span>
<span id="cb7-35"><a href="#cb7-35"></a>        echo ::set-output name=IS_RELEASE::${IS_RELEASE}</span>
<span id="cb7-36"><a href="#cb7-36"></a><span class="at">    </span><span class="kw">-</span><span class="at"> </span><span class="fu">name</span><span class="kw">:</span><span class="at"> Publish archives and packages</span></span>
<span id="cb7-37"><a href="#cb7-37"></a><span class="at">      </span><span class="fu">uses</span><span class="kw">:</span><span class="at"> softprops/action-gh-release@v1</span></span>
<span id="cb7-38"><a href="#cb7-38"></a><span class="at">      </span><span class="fu">if</span><span class="kw">:</span><span class="at"> steps.is-release.outputs.IS_RELEASE</span></span>
<span id="cb7-39"><a href="#cb7-39"></a><span class="at">      </span><span class="fu">with</span><span class="kw">:</span></span>
<span id="cb7-40"><a href="#cb7-40"></a><span class="fu">        files</span><span class="kw">: </span><span class="ch">|</span></span>
<span id="cb7-41"><a href="#cb7-41"></a>          ${{ steps.package.outputs.PKG_PATH }}</span>
<span id="cb7-42"><a href="#cb7-42"></a><span class="at">      </span><span class="fu">env</span><span class="kw">:</span></span>
<span id="cb7-43"><a href="#cb7-43"></a><span class="at">        </span><span class="fu">GITHUB_TOKEN</span><span class="kw">:</span><span class="at"> ${{ secrets.GITHUB_TOKEN }} </span></span></code></pre></div>
<p>And after building this github actions file, we find that… 3 targets
fail to build.</p>
<p><code>x86_64-unknown-freebsd</code>,
<code>x86_64-unknown-illumos</code>,
<code>powerpc-unknown-linux-gnu</code>.</p>
<p>Luckily, the error message that cross provides gives us a clear
indication of what to fix. Cross does not provide a proper image, so it
gets confused, defaults to the toolchain it’s running on (ubuntu 20.04),
and the linker cannot find the proper libraries required. Easy to fix:
Add a <code>Cross.toml</code> file to the root of the project with
docker images for the particular targets, and build again.</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode numberSource toml numberLines"><code class="sourceCode toml"><span id="cb8-1"><a href="#cb8-1"></a><span class="kw">[target.x86_64-unknown-freebsd]</span></span>
<span id="cb8-2"><a href="#cb8-2"></a><span class="dt">image</span> <span class="op">=</span> <span class="st">&quot;svenstaro/cross-x86_64-unknown-freebsd&quot;</span></span>
<span id="cb8-3"><a href="#cb8-3"></a></span>
<span id="cb8-4"><a href="#cb8-4"></a><span class="kw">[target.powerpc64-unknown-linux-gnu]</span></span>
<span id="cb8-5"><a href="#cb8-5"></a><span class="dt">image</span> <span class="op">=</span> <span class="st">&quot;japaric/powerpc64-unknown-linux-gnu&quot;</span></span></code></pre></div>
<p>You’ll notice that illumos is missing here – I couldn’t find a
suitable docker image to build it on docker hub, so I gave up. If you
find one, let me know and i’ll update this article.</p>
<h2 id="results">Results</h2>
<p>Out of the 29 architectures provided in Tier 1 and Tier 2 with host
tools, it was easy enough to build a binary for 28 architectures (We
only need a solaris/illumos docker image to build for the last one).</p>
<p>That’s pretty good, given that this only took a couple of hours to
test out. I hope Rust continues to support this many architectures into
the future, and Github Actions keeps being a good platform to make
releases for.</p>
<p>If you’d like to take the repo for yourself to build rust binaries on
releases for 28 architectures, feel free to clone/fork the repo here: <a
href="https://github.com/Takashiidobe/rust-build-binary-github-actions"
class="uri">https://github.com/Takashiidobe/rust-build-binary-github-actions</a></p>]]></description>
</item>
<item>
<title>Offline e-mail in the terminal</title>
<pubDate>Wed, 27 Oct 2021 14:44:59 +0000</pubDate>
<guid>https://blog/offline-email.html</guid>
<description><![CDATA[<p>I like putting stuff in the terminal. Let’s
roll back the clock 30 years and go back to terminal e-mail.</p>
<p>Let’s start with installing an e-mail client.</p>
<p>I like <a href="https://aerc-mail.org/">aerc</a>. I also use mac OS,
so it can be installed with a simple <code>brew install aerc</code>.</p>
<h2 id="setting-up-aerc">Setting up Aerc</h2>
<p>Here’s another guide for that: <a
href="https://oren.github.io/articles/text-based-gmail/">Text based
gmail</a></p>
<p>I personally use a gmail, so I had to create a gmail app password to
provide to aerc.</p>
<p>On first startup, aerc has a startup wizard that helps you set up
your account. Nice! Put in your information and enjoy e-mail in the
terminal.</p>
<p>My <code>aerc/accounts.conf</code> looks something like this:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1"></a><span class="ex">[Personal]</span></span>
<span id="cb1-2"><a href="#cb1-2"></a><span class="bu">source</span>        = imap://me@gmail.com:password@imap.gmail.com:993</span>
<span id="cb1-3"><a href="#cb1-3"></a><span class="ex">outgoing</span>      = smtp+plain://me@gmail.com:<span class="va">$APP_PASSWORD_HERE</span>@smtp.gmail.com:587</span>
<span id="cb1-4"><a href="#cb1-4"></a><span class="ex">smtp-starttls</span> = yes</span>
<span id="cb1-5"><a href="#cb1-5"></a><span class="ex">from</span>          = Me <span class="op">&lt;</span>me@gmail.com<span class="op">&gt;</span></span>
<span id="cb1-6"><a href="#cb1-6"></a><span class="ex">copy-to</span>       = Sent</span></code></pre></div>
<p>As well, I wanted to change up some of the defaults:</p>
<p>I set my <code>aerc/aerc.conf</code> like so: this sets my pager to
<code>bat</code> instead of <code>less -R</code>, and prefers to display
the HTML portion of an email first if possible, then falling back to the
plain text version.</p>
<p>To be able to read HTML e-mail, I uncommented the line for text/html,
and use the html filter that’s provided by aerc. This requires
<code>w3m</code> and <code>dante</code>, so I brew installed both:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1"></a><span class="ex">brew</span> install w3m</span>
<span id="cb2-2"><a href="#cb2-2"></a><span class="ex">brew</span> install dante</span></code></pre></div>
<div class="sourceCode" id="cb3"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1"></a><span class="ex">[viewer]</span></span>
<span id="cb3-2"><a href="#cb3-2"></a><span class="va">pager</span><span class="op">=</span>/usr/local/bin/bat</span>
<span id="cb3-3"><a href="#cb3-3"></a><span class="va">alternatives</span><span class="op">=</span>text/html,text/plain</span>
<span id="cb3-4"><a href="#cb3-4"></a></span>
<span id="cb3-5"><a href="#cb3-5"></a><span class="ex">[filters]</span></span>
<span id="cb3-6"><a href="#cb3-6"></a><span class="ex">subject,~^\[PATCH=awk</span> <span class="at">-f</span> @SHAREDIR@/filters/hldiff</span>
<span id="cb3-7"><a href="#cb3-7"></a><span class="ex">text/html=bash</span> /usr/local/share/aerc/filters/html</span>
<span id="cb3-8"><a href="#cb3-8"></a><span class="ex">text/*=awk</span> <span class="at">-f</span> /usr/local/share/aerc/filters/plaintext</span></code></pre></div>
<p>Great! Now we’re all set up with aerc.</p>
<h2 id="offline-support">Offline Support</h2>
<p>This is great and all, but try to run <code>aerc</code> without
internet connection. It hangs. That’s not acceptable! Let’s fix
that.</p>
<p>Drew DeVault, the original author of <code>aerc</code> published a
guide on making <code>aerc</code> work offline <a
href="https://drewdevault.com/2021/05/17/aerc-with-mbsync-postfix.html"
class="uri">https://drewdevault.com/2021/05/17/aerc-with-mbsync-postfix.html</a>.
We’ll follow this guide a bit, but I use gmail instead of
<code>migadu</code>, and ended up using <code>msmtp</code> instead of
<code>postfix</code>, so there’ll be a few changes.</p>
<h3 id="mbsync-for-reading-e-mail-offline">Mbsync for reading e-mail
offline</h3>
<p>Let’s start off installing <code>mbsync</code>. On Mac OS it is
listed as its previous name, <code>isync</code>. So run
<code>brew install isync</code> to install it.</p>
<p>We’ll then set it up – the config file is at
<code>~/.mbsyncrc</code>, so create that and fill it with this:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1"></a><span class="ex">IMAPStore</span> gmail-remote</span>
<span id="cb4-2"><a href="#cb4-2"></a><span class="ex">Host</span> imap.gmail.com</span>
<span id="cb4-3"><a href="#cb4-3"></a><span class="ex">AuthMechs</span> LOGIN</span>
<span id="cb4-4"><a href="#cb4-4"></a><span class="ex">User</span> you@gmail.com</span>
<span id="cb4-5"><a href="#cb4-5"></a><span class="ex">Pass</span> <span class="va">$APP_PASSWORD_HERE</span></span>
<span id="cb4-6"><a href="#cb4-6"></a><span class="ex">SSLType</span> IMAPS</span>
<span id="cb4-7"><a href="#cb4-7"></a></span>
<span id="cb4-8"><a href="#cb4-8"></a><span class="ex">MaildirStore</span> gmail-local</span>
<span id="cb4-9"><a href="#cb4-9"></a><span class="ex">Path</span> ~/mail/gmail/</span>
<span id="cb4-10"><a href="#cb4-10"></a><span class="ex">Inbox</span> ~/mail/gmail/INBOX</span>
<span id="cb4-11"><a href="#cb4-11"></a><span class="ex">Subfolders</span> Verbatim</span>
<span id="cb4-12"><a href="#cb4-12"></a></span>
<span id="cb4-13"><a href="#cb4-13"></a><span class="ex">Channel</span> gmail</span>
<span id="cb4-14"><a href="#cb4-14"></a><span class="ex">Far</span> :gmail-remote:</span>
<span id="cb4-15"><a href="#cb4-15"></a><span class="ex">Near</span> :gmail-local:</span>
<span id="cb4-16"><a href="#cb4-16"></a><span class="ex">Expunge</span> Both</span>
<span id="cb4-17"><a href="#cb4-17"></a><span class="ex">Patterns</span> <span class="pp">*</span> !<span class="st">&quot;[Gmail]/All Mail&quot;</span> !<span class="st">&quot;[Gmail]/Important&quot;</span> !<span class="st">&quot;[Gmail]/Starred&quot;</span> !<span class="st">&quot;[Gmail]/Bin&quot;</span></span>
<span id="cb4-18"><a href="#cb4-18"></a><span class="ex">SyncState</span> <span class="pp">*</span></span></code></pre></div>
<p>If you don’t already have a <code>~/mail/gmail/INBOX</code> folder,
create it with <code>mkdir -p ~/mail/gmail/INBOX</code>.</p>
<p>Now, if you run <code>mbsync gmail</code>, all of your e-mail will be
synced to your <code>~/mail/gmail</code> folder.</p>
<p>Now, we just need aerc to pull locally instead of from gmails
servers.</p>
<p>Go back to <code>aerc/accounts.conf</code>, and edit the source under
the [Personal] tag to point to <code>maildir://~/mail</code>. This will
let aerc read your e-mail locally instead of from gmail’s servers.</p>
<p>As well, set the default to <code>gmail/INBOX</code> to land in your
inbox folder on start.</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1"></a><span class="ex">[Personal]</span></span>
<span id="cb5-2"><a href="#cb5-2"></a><span class="bu">source</span>        = maildir://~/mail</span>
<span id="cb5-3"><a href="#cb5-3"></a><span class="ex">outgoing</span>      = smtp+plain://me@gmail.com:<span class="va">$APP_PASSWORD_HERE</span>@smtp.gmail.com:587</span>
<span id="cb5-4"><a href="#cb5-4"></a><span class="ex">default</span>       = gmail/INBOX</span>
<span id="cb5-5"><a href="#cb5-5"></a><span class="ex">smtp-starttls</span> = yes</span>
<span id="cb5-6"><a href="#cb5-6"></a><span class="ex">from</span>          = Me <span class="op">&lt;</span>me@gmail.com<span class="op">&gt;</span></span>
<span id="cb5-7"><a href="#cb5-7"></a><span class="ex">copy-to</span>       = Sent</span></code></pre></div>
<p>Turn off your internet and run <code>aerc</code>. Now you can read
your e-mail offline! We’ll want to always keep our mailbox in sync, so
we’ll want to run <code>mbsync</code> frequently to keep our mailbox in
sync.</p>
<p>First, we’ll need a program called <code>chronic</code>, which is
provided in <code>moreutils</code>. Download it with
<code>brew install moreutils</code>.</p>
<p>Run <code>crontab -e</code> to edit your local crontab, and put this
in it.</p>
<p>This will have cron execute <code>mbsync gmail</code> every minute,
keeping your mailbox in sync with google’s servers.</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1"></a><span class="va">MAILTO</span><span class="op">=</span><span class="st">&quot;&quot;</span></span>
<span id="cb6-2"><a href="#cb6-2"></a><span class="va">PATH</span><span class="op">=</span>YOUR_PATH_HERE</span>
<span id="cb6-3"><a href="#cb6-3"></a><span class="ex">*</span> <span class="pp">*</span> <span class="pp">*</span> <span class="pp">*</span> <span class="pp">*</span> chronic mbsync gmail</span></code></pre></div>
<h3 id="sending-e-mail-offline">Sending E-mail offline</h3>
<p>If you try to send e-mail while offline on aerc currently, the e-mail
will never send. What we’d like is some queue where the e-mail is sent
immediately if we’re online, otherwise, to save that message in a queue,
and send out all messages immediately as we regain connectivity.</p>
<p>We’ll use <code>msmtp</code> for that.</p>
<p>Install it with <code>brew install msmtp</code>.</p>
<p>msmtp’s config file is called <code>~/.msmtprc</code>. Fill that file
with this:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1"></a><span class="ex">defaults</span></span>
<span id="cb7-2"><a href="#cb7-2"></a><span class="ex">tls</span> on</span>
<span id="cb7-3"><a href="#cb7-3"></a></span>
<span id="cb7-4"><a href="#cb7-4"></a><span class="ex">account</span> gmail</span>
<span id="cb7-5"><a href="#cb7-5"></a><span class="ex">auth</span> on</span>
<span id="cb7-6"><a href="#cb7-6"></a><span class="ex">host</span> smtp.gmail.com</span>
<span id="cb7-7"><a href="#cb7-7"></a><span class="ex">port</span> 587</span>
<span id="cb7-8"><a href="#cb7-8"></a><span class="ex">user</span> me</span>
<span id="cb7-9"><a href="#cb7-9"></a><span class="ex">from</span> me@gmail.com</span>
<span id="cb7-10"><a href="#cb7-10"></a><span class="ex">password</span> APP_PASSWORD_HERE</span>
<span id="cb7-11"><a href="#cb7-11"></a></span>
<span id="cb7-12"><a href="#cb7-12"></a><span class="ex">account</span> default: gmail</span></code></pre></div>
<p>Now we can send e-mail from the command line. This isn’t super useful
yet, since aerc has this functionality already. Next, we need to
implement the queueing capability we discussed. You’ll want to download
two bash scripts that do this for us: <code>msmtpq</code> and
<code>msmtp-queue</code>. These can be found here: <a
href="https://github.com/tpn/msmtp/tree/master/scripts/msmtpq"
class="uri">https://github.com/tpn/msmtp/tree/master/scripts/msmtpq</a>.
Make them executable and place them somewhere on your path (I chose
<code>/usr/local/bin</code>). This implements the queueing that be
discussed.</p>
<p>Finally, we’ll have to hook up <code>aerc</code> to use this
capability in <code>accounts.conf</code>.</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1"></a><span class="ex">[Personal]</span></span>
<span id="cb8-2"><a href="#cb8-2"></a><span class="bu">source</span>        = maildir://~/mail</span>
<span id="cb8-3"><a href="#cb8-3"></a><span class="ex">outgoing</span>      = /usr/local/bin/msmtpq</span>
<span id="cb8-4"><a href="#cb8-4"></a><span class="ex">default</span>       = gmail/INBOX</span>
<span id="cb8-5"><a href="#cb8-5"></a><span class="ex">smtp-starttls</span> = yes</span>
<span id="cb8-6"><a href="#cb8-6"></a><span class="ex">from</span>          = Me <span class="op">&lt;</span>me@gmail.com<span class="op">&gt;</span></span>
<span id="cb8-7"><a href="#cb8-7"></a><span class="ex">copy-to</span>       = Sent</span></code></pre></div>
<p>Finally, we’ll want to be able to execute the queueing functionality
of <code>msmtpq</code> every minute as well. Edit your crontab to look
like this:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1"></a><span class="va">MAILTO</span><span class="op">=</span><span class="st">&quot;&quot;</span></span>
<span id="cb9-2"><a href="#cb9-2"></a><span class="va">PATH</span><span class="op">=</span>YOUR_PATH_HERE</span>
<span id="cb9-3"><a href="#cb9-3"></a><span class="ex">*</span> <span class="pp">*</span> <span class="pp">*</span> <span class="pp">*</span> <span class="pp">*</span> chronic mbsync gmail</span>
<span id="cb9-4"><a href="#cb9-4"></a><span class="ex">*</span> <span class="pp">*</span> <span class="pp">*</span> <span class="pp">*</span> <span class="pp">*</span> chronic msmtp-queue <span class="at">-r</span></span></code></pre></div>
<p>And with that, we’re done! We can now read e-mail offline, which
syncs every minute when online, and send e-mail offline, which will get
queued, and sent as soon as we’re back online
again.</p>]]></description>
</item>
<item>
<title>Work Offline</title>
<pubDate>Fri, 08 Oct 2021 01:43:45 +0000</pubDate>
<guid>https://blog/work-offline.html</guid>
<description><![CDATA[<p>In my last post, I discussed the tradeoffs of
various languages with regards to software longevity – I wanted to pick
a language to use that would make long lasting software.</p>
<p>In this post, I want to discuss working offline – why that
interleaves with the choice of language to use, and how to use tooling
to make that accessible.</p>
<p>Joe Nelson, of PostgREST fame, wrote a series of posts that resonated
with me – starting with <a
href="https://begriffs.com/posts/2015-04-20-going-write-only.html">“Going
‘Write Only’”</a> where he starts off with quoting Joey Hess, a person
who “Lives in a cabin and programs Haskell on a drastically
under-powered netbook”, where he harvests all of his electricity from
the sun, and works using a distributed workflow, much like a git
workflow.</p>
<p>He then goes on to explain his motivation of going “write-only”
thusly:</p>
<blockquote>
<p>These people’s thoughts are not idle for me. They contain a reproach,
a warning that one can be very busy and yet do unproductive things,
hamartia. I want to focus on doing the right thing. Actually focus is
the wrong word. Focusing my thoughts would imply the same thoughts but
sharper, whereas I want to change the way I think.</p>
</blockquote>
<p>He then went on to publish more blog posts focused on creating
software that lasts:</p>
<ul>
<li><a
href="https://begriffs.com/posts/2017-04-13-longterm-computing-reading.html">Good
books for deep hacks</a></li>
<li><a
href="https://begriffs.com/posts/2019-01-19-inside-c-standard-lib.html">Inside
the C Standard Library</a></li>
<li><a
href="https://begriffs.com/posts/2020-08-31-portable-stable-software.html">Tips
for stable and portable Software</a></li>
<li><a
href="https://begriffs.com/posts/2021-07-04-shared-libraries.html">Dynamic
linking best practices</a></li>
</ul>
<p>Which are all great reads, and inspired me to write this post about
how I work offline, and what I use to make that happen.</p>
<h2 id="tools-of-the-trade">Tools of the Trade</h2>
<h3 id="git"><a href="https://git-scm.com/">Git</a></h3>
<p>It’s a no-brainer to use git for this kind of workflow. You can go
offline for weeks at a time, hacking away at your branch, and when
you’re back online, merge back to the main branch, fetch what you
missed, and go back to hacking away offline. Since you have a copy of
all the history of the repo on your hard disk, if you need to look at
changes from the past, you can do just that. Git enables this workflow,
while other centralized systems require constant connectivity.</p>
<h3 id="man-pages"><a href="https://www.kernel.org/doc/man-pages/">Man
Pages</a></h3>
<p>Man pages (and info pages) predate the internet, so of course they
work well offline. Unfortunately for Mac, Man pages are pretty sparse
(basically scavenged off of old BSD manuals), and they aren’t always the
most descriptive when it comes to using cli tools, so I tend to use
<code>tldr</code> for that case.</p>
<p>To pay it forward, I tend to bundle man pages with utilities that I
make, like <code>rvim</code> or <code>simplestats</code> on cargo, even
though rust docs are more common in rust land.</p>
<h3 id="tldr"><a href="https://github.com/tldr-pages/tldr">Tldr</a></h3>
<p>Ever remember how to use <code>tar</code>? Me neither. Tldr is a man
pages complement, offering examples for cli applications just by typing
<code>tldr $keyword</code>. I personally really like it, because it’s
like having a concise stackoverflow at your fingertips.</p>
<h3 id="zim-files"><a href="https://wiki.openzim.org/wiki/OpenZIM">ZIM
files</a></h3>
<p>When I tell people about working offline, they ask “but what about X
website?”. Well, if you want to look up a question on wikipedia or
stackoverflow, you’d surely need online access, right?</p>
<p>That’s where ZIM files come in – offline archives of whole websites.
The kiwix project (sponsored by wikipedia) offers downloads and torrents
for ZIM files for sites like wikipedia and stackoverflow, which you can
wholesale download over an internet connection, and then search through
to your hearts content. So if you ever forget how to reverse a linked
list in your favorite language, you can search through stackoverflow to
find out.</p>
<ul>
<li><a href="https://dumps.wikimedia.org/other/kiwix/zim/wikipedia/"
class="uri">https://dumps.wikimedia.org/other/kiwix/zim/wikipedia/</a></li>
<li><a href="https://ftp.fau.de/kiwix/zim/stack_exchange/"
class="uri">https://ftp.fau.de/kiwix/zim/stack_exchange/</a></li>
</ul>
<p>You can also download wikipedia’s own ZIM file archiver and archive
other sites that you like.</p>
<h3 id="devdocs"><a href="https://devdocs.io/">DevDocs</a></h3>
<p>Not all languages/projects have offline documentation, but most of
them have documentation on the web. DevDocs is a project that allows you
to download and search through that documentation in a convenient way
offline. Every time you get back online, you can sync the documentation
of the projects you like to follow. Nifty.</p>
<h3 id="e-books">E-books</h3>
<p>E-Books are really great too, in both PDF and epub format. You can
keep a copy of them on your hard disk and search through them too
without going to the internet.</p>
<h3 id="papers">Papers</h3>
<p><a href="https://arxiv.org/">Arxiv</a> is a repository of open access
articles in the sciences and maths. You can download papers off there
for free, and read them at your leisure. There’s a treasure trove of
papers to read!</p>
<h3 id="rustup-cargo"><a href="https://www.rust-lang.org/learn">Rustup +
Cargo</a></h3>
<p>Rust has a strong focus on offline work – cargo allows you to turn
docstring comments into HTML documentation with search, and
<code>rustup</code> comes with its own offline documentation, by virtue
of <code>rustup docs</code>.</p>
<p>Cargo also allows one to force offline mode by adding the
<code>--offline</code> command line flag – this forces cargo to use
downloaded crates instead of going to <code>crates.io</code>.</p>
<h2 id="hardware">Hardware</h2>
<p>Currently, I work off of a Macbook pro 2017, which only has 128GB of
hard disk space. If I want to supplant that with extra hard disk space,
I have an external SSD that I carry around with me (with ZIM files for
offline use). That being said, it is getting a bit old in 2022, and I
may replace it in the coming years for a <a
href="https://frame.work">framework laptop</a>, as the company is very
devoted to right to repair.</p>]]></description>
</item>
<item>
<title>Software that lasts Offline</title>
<pubDate>Sat, 02 Oct 2021 04:05:13 +0000</pubDate>
<guid>https://blog/software-that-lasts-offline.html</guid>
<description><![CDATA[<p>It seems like every day software gets outdated.
It’s so hard to build software that lasts for 3 years, let alone 30. Yet
the houses we live in have seen much longer lives, with just a bit of
refurbishing here and there. Why can’t our software be the same way?
_why the lucky stiff said something that resounds with me as a
programmer as he left the internet.</p>
<blockquote>
<p>To Program anymore was pointless.</p>
<p>My programs would never live as long as the trial.</p>
<p>A computer will never live as long as the trial.</p>
<p>What if Amerika was only written for 32-bit power pc?</p>
<p>Can an unfinished program be reconstructed??</p>
<p>Can I write a program and go, “Ah, Well, You get the gist of it.”</p>
</blockquote>
<p>Our software doesn’t last as long as the written word. It’s a very
defeating thing to think that most of our code doesn’t last that long. I
wondered if it had to be this way, or if it was something to do with how
we approached software writing. C code has lasted for a few decades, and
could last a few more – there’s lots of COBOL and FORTRAN code in the
wild that’s 50 years old. Software that lasts is both high-level and
low-level at the same time – assembly would never last because it’s tied
to its platform.</p>
<p>A higher-level language need not be tied to any specific
architecture. Yet the need for compatibility with architectures, past,
present, and future makes it so the language must only build off of
low-level primitives. A contradiction.</p>
<p>I want a language that has offline documentation, that is robust, has
wide compatibility in the past, present, and future, has standards, has
multiple implementations, is fast, and is easy to develop for. Here’s a
short list of the languages I looked at, with some pros and cons for
each in making software that lasts.</p>
<h2 id="javascript">Javascript</h2>
<p>Javascript is well specified (by committee), with multiple
implementations, and a strong commitment to backwards compatibility –
but that’s about where the pros end. Even though I coded professionally
in Javascript for a few years, things about the language still trip me
up – I sometimes forget to check for nulls, or I get different types
than what I’m expecting when I use the standard library. As well, I know
those things will never be fixed, because the web is the most popular
for programming. Therefore, fundamentally, the language will never be
able to smooth out its warts.</p>
<h2 id="typescript">Typescript</h2>
<p>Typescript smooths out <em>most</em> of the usability issues of
Javascript, and gives it static typing, generics, and new constructs
(enums, interfaces, types). It compiles to Javascript quickly, and
considering how accessible Javascript is, it shares most of its
accessibility pros. That being said, Typescript has more lax backwards
compatibility requirements, but with its compatibility to Javascript,
won’t be able to fix the language’s warts.</p>
<h2 id="wasm">WASM</h2>
<p>Web Assembly is a new contender for web language of the future
<em>TM</em>. It’s a minimalistic language with S-expressions (like
lisps) and is meant to be an easy compiler target. Go, C, C++, Rust, and
others can compile down to it, targeting the WASM capabilities of the
browser. As well, WASI seems like a portable way to run sandboxed
applications in the future.</p>
<p>It’s too low-level for productive use, but is an interesting foray
into fixing the kludge of the web.</p>
<h2 id="ruby">Ruby</h2>
<p>Ruby is the most OOP language I can think of – message passing,
everything is an object, and GC pauses ad nauseum. It’s a language with
a lot of expressiveness, and a lot of elegance. It has strong C
bindings, so it has good interop with system libraries – and pretty good
backwards compatibility.</p>
<p>That being said, it’s slow and clunky to write. The philosophy of
expressiveness means that everybody writes ruby code differently, and
there’s a huge divide between ruby programmers, who are more restrictive
with what functionality they use, and rails programmers, who are more
keen on monkey-patching everything they can find for usability reasons.
Not to say one side is right, but the language’s stewardship has been on
appeasing many camps, and that leads to fragmentation.</p>
<h2 id="python">Python</h2>
<p>Python is also very OOP, but contrary to ruby, it even comes with its
own Zen, which you can read by entering <code>import this</code> at the
REPL.</p>
<p>Beautiful is better than ugly. Explicit is better than implicit.
Simple is better than complex. Complex is better than complicated. Flat
is better than nested. Sparse is better than dense. Readability counts.
There should be one– and preferably only one –obvious way to do it.</p>
<p>Python prefers fewer ways to do one thing, but that zen has been
wearing off, with a huge standard library, which makes it hard to commit
to backwards compatibility. Python has some system dependencies that are
less than stellar when it comes to backwards compatibility, and the
large surface area can make it hard for the language to keep stable.</p>
<p>Oh yeah, and remember Python3?</p>
<h2 id="ocaml">OCaml</h2>
<p>OCaml is an interesting language; it has a bytecode interpreter,
cross compilation, and compilation to native, just like Haskell. It’s
relatively fast to compile, but has issues with backwards compatibility
and footguns. As well, the standard library has been reimplemented by
many, including by Jane Street, twice (Base and Core).</p>
<p>It’s a clear language with some baggage (Few people use the “Object
Oriented” or “O” features of “OCaml”). For loops and classes are often
struck down in code review as anti-patterns. Best to be functional, all
the time.</p>
<p>It is relatively fast, with a good ecosystem (Dune makes building
OCaml apps pretty nice in 2021) but it’s still a relatively small
ecosystem, fighting against Haskell to become Typed Functional
Programming’s main language.</p>
<p>Offline Documentation is great, and the standard library has few
wants of its environment, but it lacks multicore support – in an
increasingly parallel world, that’s a deal-breaker. It’s looking like a
reimplementation of the standard library with async might require a
major version bump, to (5.X).</p>
<h2 id="jvm-languages-java-scala-clojure">JVM languages (Java, Scala,
Clojure)</h2>
<p>JVM languages are pretty strong, with the JVM allowing users to
target many platforms with their code (since the JVM runs on many
things). That being said, the JVM offers some penalty, because the
runtimes can be quite hefty and difficult to port. It’s not quite as
easy as sending someone a binary and they can run it, or easy to
containerize JVM apps, unlike those that offer native binaries.</p>
<h2 id="clr-languages-c-f">CLR languages (C#, F#)</h2>
<p>Same as the JVM languages, although I have to say that F# and C# are
pretty fun to program in.</p>
<h2 id="go">Go</h2>
<p>Go was the first <em>serious</em> language in the list I considered
learning – simple like C, with a strong standard library for the modern
era with a focus on async + web programming. Sounds like a dream. Oh,
and fast compile times and cross-compilation. Woah. Relatively small
native binaries that don’t rely on libc? Doable in Go.</p>
<p>Lots of big projects have been done in go, like most hashicorp stuff,
docker, kubernetes, and a wealth of devops/cloud tools. It’s a
productive language, and one that nudges you to sane defaults.</p>
<p>But it’s not all sunshine and roses – the package managing story has
been a nightmare, there are no generics (Hello casting to Interface{})
and I don’t understand why a GC’ed language should have pointers and
references explicitly? You get a lot for free, just by using Go, but you
pay for it with complexity – I rarely miss generics as an application
developer, until I’m slapped with complexity because the library
developer decided to hand over the complexity to me. Go also has one
standard implementation and stewardship led by Google, which makes it a
bit odd – Google has never been one for backwards compatibility, and it
seems like Go might be due for a Go 2.0, which could be an ecosystem and
binary break for Go. Only time will tell if Go can survive the blow, or
if it’ll go with the route of holding onto the choices of the past.</p>
<h2 id="c">C++</h2>
<p>C++ is the first language on this list with no Garbage Collection, it
has a specification that’s ISO standardized, with many committees, and
with many implementations. It has functionality for OOP, Functional
Programming, Generics, async, with the promise of being as fast as C
while staying easier to use.</p>
<p>It mostly capitalizes on that promise. With the advent of modern C++,
even though C++ has added many features, it has had a strong promise
towards backwards compatibility (it keeps ABI compatibility for a long
time, only recently breaking ABI in C++11), and only removing clearly
broken functionality (auto_ptr, anyone?) But it can be hard to use –
(the iterator API is one frustrating example), and it can be hard to see
the runtime cost of the abstractions you use – Even though C++ follows
the “Zero-Cost Abstractions” principle, where you don’t pay for what you
don’t use, and what you do use you couldn’t hand-code any better, it
breaks down somewhat – <code>std::map</code> is extremely slow on
certain workloads, because it’s just implemented incorrectly – and
Iterators are a good example of an API footgun (remember to always check
for <code>.end()</code>!).</p>
<p>The complexity is never really ever paid off – you have to litter
your code with extra keywords like const to the left and right of your
functions, along with noexcept, and final, and override. You have to
remember what is and what isn’t virtual, and use keywords accordingly,
and you have to always generate move constructors, copy constructors,
and remember which one is which – why are there so many ways to
initialize an object, and why are there so many things to remember when
you write your own class?</p>
<p>Oh, and what’s the difference between struct and class? Who
knows?</p>
<p>C++ is a language with lots of promises but it has run into the
limits of its promises – backwards compatibility, ease of use,
performance, and expressiveness are all in tension, and C++ is the
language you can see that in the most.</p>
<h2 id="c-1">C</h2>
<p>Meanwhile, C is much more minimalistic than C++. You get nothing – no
expanding arrays, no hashmaps, no trees, no graphs, no async, no
unicode, nothing.</p>
<p>It’s a very bare language. That helps it with portability (C is the
most portable language on this list by far) but it pays that price by
doing almost nothing for you.</p>
<p>It’s a high-level language that makes few choices for you and leaves
you in a sandbox of your own creation. That can make code-sharing hard,
since it’s bound to its environment – if you want to make a cross
platform library, you have to be careful about which libraries you use,
since different OSes have different system libraries.</p>
<p>It has a static type system and is speedy, for sure – but it can be
clunky and unsafe as well.</p>
<h2 id="rust-every-day-for-3-years">Rust Every Day (For 3 years)</h2>
<p>With all that being said, I’ve decided to pick Rust as my language of
choice for the next 3 years for as many programming related tasks as I
can. Rust is pleasant to develop for, has pledged backwards
compatibility since 2015, targets a wide variety of architectures
(thanks mainly to LLVM) and I’m convinced is a language for the rest of
my career; it has a great team working on it, with a unique governance
structure that makes it resilient to being steered by one interest
group.</p>
<p>It’s taken some great ideas from functional programming (Tagged
Unions, Sum Types, iterators) while keeping the runtime promises of more
imperative languages. It’s a great language to learn for the future, and
one that I’m sure will keep on growing, and for that, I’m throwing my
weight behind it.</p>
<p>Rust every day. For 3 years. Then I’ll revisit this and see what’s
changed, but I’d like to use Rust for the next 10 years, at
least.</p>]]></description>
</item>
<item>
<title>Implementing Iterators</title>
<pubDate>Sun, 19 Sep 2021 02:41:43 +0000</pubDate>
<guid>https://blog/implementing-iterators.html</guid>
<description><![CDATA[<p>Let’s talk about implementing iterators: a way
to visit every item in a collection. We’ll use C as an implementation
language because it’s simpler than other languages, and we’ll implement
C++’s iterator API. This is the same in most mainstream programming
languages, like Rust, C++, Python, Ruby, JavaScript, Java, C#, and PHP,
with a few small implementation differences.</p>
<h2 id="the-api">The API</h2>
<p>The API we’ll create is simple. A <code>int* next(int* it)</code>
function that takes an iterator and returns its next element, or a
<code>NULL</code> pointer if nothing comes next, and a
<code>bool has_next(int* it)</code> that returns <code>true</code> if it
has a next item, or <code>false</code> if it does not.</p>
<p>The C++ iterator API needs a few functions that give you an iterator
to a collection. These are called <code>begin()</code> and
<code>end()</code>, which return a pointer to the first item in the
collection, and one past the end of the collection. This is a dangerous
API, since if we dereference <code>end()</code> we automatically cause
Undefined Behavior, but our APIs become a bit cleaner. Tradeoffs, I
guess.</p>
<p>We’ll elide the details of begin in our example and implement it
ourselves.</p>
<p>Let’s start by defining our collection: an array of ints from 1 -
5.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1"></a><span class="dt">int</span> items<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span><span class="dv">1</span><span class="op">,</span> <span class="dv">2</span><span class="op">,</span> <span class="dv">3</span><span class="op">,</span> <span class="dv">4</span><span class="op">,</span> <span class="dv">5</span><span class="op">};</span></span></code></pre></div>
<p>Let’s say we want to print them: no need for iterators, of
course.</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb2-2"><a href="#cb2-2"></a></span>
<span id="cb2-3"><a href="#cb2-3"></a><span class="dt">int</span> items<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span><span class="dv">1</span><span class="op">,</span> <span class="dv">2</span><span class="op">,</span> <span class="dv">3</span><span class="op">,</span> <span class="dv">4</span><span class="op">,</span> <span class="dv">5</span><span class="op">};</span></span>
<span id="cb2-4"><a href="#cb2-4"></a></span>
<span id="cb2-5"><a href="#cb2-5"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">5</span><span class="op">;</span> i<span class="op">++)</span> </span>
<span id="cb2-7"><a href="#cb2-7"></a>        printf<span class="op">(</span><span class="st">&quot;</span><span class="sc">%d</span><span class="st"> &quot;</span><span class="op">,</span> items<span class="op">[</span>i<span class="op">]);</span>  </span>
<span id="cb2-8"><a href="#cb2-8"></a><span class="op">}</span></span></code></pre></div>
<p>But we have to initialize and increment a variable and use it as an
index to our collection… We want a clearer way of expressing a loop
through all the items in a collection, and that’s where iterators come
in.</p>
<p>Let’s start by defining the begin and end iterators.</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1"></a><span class="dt">int</span><span class="op">*</span> begin <span class="op">=</span> <span class="op">&amp;</span>items<span class="op">[</span><span class="dv">0</span><span class="op">];</span></span>
<span id="cb3-2"><a href="#cb3-2"></a><span class="dt">int</span><span class="op">*</span> end <span class="op">=</span> <span class="op">&amp;</span>items<span class="op">[</span><span class="dv">5</span><span class="op">];</span></span></code></pre></div>
<p>Remember, the begin points to the first item of the collection, and
end points to one past the end. We can’t dereference end, so keep that
in mind.</p>
<p>Now, to create the <code>next()</code> function, we want to take an
iterator and move to the next item if we aren’t already at the end
iterator.</p>
<p>Let’s do that:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1"></a><span class="dt">int</span><span class="op">*</span> next<span class="op">(</span><span class="dt">int</span><span class="op">*</span> it<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2"></a>    <span class="cf">if</span> <span class="op">(</span>it <span class="op">!=</span> end<span class="op">)</span> </span>
<span id="cb4-3"><a href="#cb4-3"></a>        <span class="cf">return</span> it <span class="op">+</span> <span class="kw">sizeof</span><span class="op">(</span><span class="dt">int</span><span class="op">);</span></span>
<span id="cb4-4"><a href="#cb4-4"></a>    <span class="cf">return</span> NULL<span class="op">;</span></span>
<span id="cb4-5"><a href="#cb4-5"></a><span class="op">}</span></span></code></pre></div>
<p>Since we know that our iterator is an (int) pointer, we want to
increment the iterator four bytes (the result of sizeof(int) on my
computer). This works, but there’s a shorthand that most C compilers
will let you do, called pointer arithmetic. In this case, the compiler
knows that this is an int pointer, and so it’s overloaded additions and
subtractions to move forward and backwards by the sizeof an int.</p>
<p>We can rewrite the above as:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1"></a><span class="dt">int</span><span class="op">*</span> next<span class="op">(</span><span class="dt">int</span><span class="op">*</span> it<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2"></a>    <span class="cf">if</span> <span class="op">(</span>it <span class="op">!=</span> end<span class="op">)</span> </span>
<span id="cb5-3"><a href="#cb5-3"></a>        <span class="cf">return</span> <span class="op">++</span>it<span class="op">;</span></span>
<span id="cb5-4"><a href="#cb5-4"></a>    <span class="cf">return</span> NULL<span class="op">;</span></span>
<span id="cb5-5"><a href="#cb5-5"></a><span class="op">}</span></span></code></pre></div>
<p>Next, we want to write <code>has_next</code>. <code>has_next</code>
should return a <code>bool</code> <code>true</code> if the iterator can
be incremented, or <code>false</code> if not. We know that an iterator
has a next item if it’s not in the last item in the collection, which is
just before the end pointer. Thus, we can define <code>has_next</code>
thusly:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb6-1"><a href="#cb6-1"></a><span class="dt">int</span> has_next<span class="op">(</span><span class="dt">int</span><span class="op">*</span> it<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2"></a>    <span class="cf">return</span> it <span class="op">!=</span> end <span class="op">-</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb6-3"><a href="#cb6-3"></a><span class="op">}</span></span></code></pre></div>
<p>Let’s use our iterators thus far to traverse our collection:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb7-1"><a href="#cb7-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb7-2"><a href="#cb7-2"></a></span>
<span id="cb7-3"><a href="#cb7-3"></a><span class="dt">int</span> items<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span><span class="dv">1</span><span class="op">,</span> <span class="dv">2</span><span class="op">,</span> <span class="dv">3</span><span class="op">,</span> <span class="dv">4</span><span class="op">,</span> <span class="dv">5</span><span class="op">};</span></span>
<span id="cb7-4"><a href="#cb7-4"></a></span>
<span id="cb7-5"><a href="#cb7-5"></a><span class="dt">int</span><span class="op">*</span> begin <span class="op">=</span> <span class="op">&amp;</span>items<span class="op">[</span><span class="dv">0</span><span class="op">];</span></span>
<span id="cb7-6"><a href="#cb7-6"></a><span class="dt">int</span><span class="op">*</span> end <span class="op">=</span> <span class="op">&amp;</span>items<span class="op">[</span><span class="dv">5</span><span class="op">];</span></span>
<span id="cb7-7"><a href="#cb7-7"></a></span>
<span id="cb7-8"><a href="#cb7-8"></a><span class="dt">int</span><span class="op">*</span> next<span class="op">(</span><span class="dt">int</span><span class="op">*</span> it<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-9"><a href="#cb7-9"></a>    <span class="cf">if</span> <span class="op">(</span>it <span class="op">!=</span> end<span class="op">)</span> </span>
<span id="cb7-10"><a href="#cb7-10"></a>        <span class="cf">return</span> <span class="op">++</span>it<span class="op">;</span></span>
<span id="cb7-11"><a href="#cb7-11"></a>    <span class="cf">return</span> NULL<span class="op">;</span></span>
<span id="cb7-12"><a href="#cb7-12"></a><span class="op">}</span></span>
<span id="cb7-13"><a href="#cb7-13"></a></span>
<span id="cb7-14"><a href="#cb7-14"></a><span class="dt">int</span> has_next<span class="op">(</span><span class="dt">int</span><span class="op">*</span> it<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-15"><a href="#cb7-15"></a>    <span class="cf">return</span> it <span class="op">!=</span> end <span class="op">-</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb7-16"><a href="#cb7-16"></a><span class="op">}</span></span>
<span id="cb7-17"><a href="#cb7-17"></a></span>
<span id="cb7-18"><a href="#cb7-18"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-19"><a href="#cb7-19"></a>    puts<span class="op">(</span><span class="st">&quot;Printing forwards&quot;</span><span class="op">);</span></span>
<span id="cb7-20"><a href="#cb7-20"></a>    <span class="dt">int</span><span class="op">*</span> it <span class="op">=</span> begin<span class="op">;</span></span>
<span id="cb7-21"><a href="#cb7-21"></a>    <span class="cf">while</span> <span class="op">(</span>it <span class="op">!=</span> end<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-22"><a href="#cb7-22"></a>        printf<span class="op">(</span><span class="st">&quot;</span><span class="sc">%d</span><span class="st"> has next? &quot;</span><span class="op">,</span> <span class="op">*</span>it<span class="op">);</span></span>
<span id="cb7-23"><a href="#cb7-23"></a>        puts<span class="op">(</span>has_next<span class="op">(</span>it<span class="op">)</span> <span class="op">?</span> <span class="st">&quot;true&quot;</span> <span class="op">:</span> <span class="st">&quot;false&quot;</span><span class="op">);</span></span>
<span id="cb7-24"><a href="#cb7-24"></a>        it <span class="op">=</span> next<span class="op">(</span>it<span class="op">);</span></span>
<span id="cb7-25"><a href="#cb7-25"></a>    <span class="op">}</span></span>
<span id="cb7-26"><a href="#cb7-26"></a><span class="op">}</span></span></code></pre></div>
<p>This should print out:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode numberSource bash numberLines"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1"></a><span class="ex">Printing</span> forwards</span>
<span id="cb8-2"><a href="#cb8-2"></a><span class="ex">1</span> has next<span class="pp">?</span> true</span>
<span id="cb8-3"><a href="#cb8-3"></a><span class="ex">2</span> has next<span class="pp">?</span> true</span>
<span id="cb8-4"><a href="#cb8-4"></a><span class="ex">3</span> has next<span class="pp">?</span> true</span>
<span id="cb8-5"><a href="#cb8-5"></a><span class="ex">4</span> has next<span class="pp">?</span> true</span>
<span id="cb8-6"><a href="#cb8-6"></a><span class="ex">5</span> has next<span class="pp">?</span> false</span></code></pre></div>
<h2 id="why-use-iterators">Why use Iterators?</h2>
<p>If this seems like a lot of ceremony for iterating through an array,
it is. It’s totally unnecessary. It gives us nothing more powerful than
what a raw for loop would give us. But what happens if our collection
isn’t linear? What happens if we traverse a sorted map, or a graph?</p>
<p>With a for loop, we must ask the caller to understand how the data
structure is implemented. With an iterator, we can provide a definition
of next, and has next, and the user can call it without knowing
<strong>anything about the underlying collection</strong> outside of the
fact that it is iterable.</p>
<p>This allows us to wrap graphs, trees, hash tables, ranges (finite and
infinite), and circular data structures in a friendly API for our
users.</p>
<p>As well, language features allow us to reward usage of iterators by
making syntax more terse: In C++, Rust, Java, C#, Ruby, Python, and
JavaScript, if you implement the iterable API in each language, you can
do something along these lines:</p>
<pre><code>for (item in collection)
  do something to item</code></pre>
<p>And the language takes care of the rest. In C, we can’t do that, but
in other languages, the language gives us some reward for doing so for
our own types, as our types get to behave like library defined
types.</p>
<h2 id="next-steps">Next Steps</h2>
<p>Now that we can implement iterators in C, try giving it a shot in
your favorite language and seeing what the iterator protocol is for it.
It’s loads of fun, I swear.</p>
<p>I tried it myself in C when writing a resizable array type too:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb10-1"><a href="#cb10-1"></a><span class="kw">typedef</span> <span class="kw">struct</span> Vector <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2"></a>  <span class="dt">size_t</span> len<span class="op">;</span></span>
<span id="cb10-3"><a href="#cb10-3"></a>  <span class="dt">size_t</span> capacity<span class="op">;</span></span>
<span id="cb10-4"><a href="#cb10-4"></a>  <span class="dt">int</span> <span class="op">*</span>items<span class="op">;</span></span>
<span id="cb10-5"><a href="#cb10-5"></a><span class="op">}</span> Vector<span class="op">;</span></span>
<span id="cb10-6"><a href="#cb10-6"></a></span>
<span id="cb10-7"><a href="#cb10-7"></a><span class="co">// Allow the user to set their own alloc/free</span></span>
<span id="cb10-8"><a href="#cb10-8"></a><span class="dt">static</span> <span class="dt">void</span> <span class="op">*(*</span>__vector_malloc<span class="op">)(</span><span class="dt">size_t</span><span class="op">)</span> <span class="op">=</span> malloc<span class="op">;</span></span>
<span id="cb10-9"><a href="#cb10-9"></a><span class="dt">static</span> <span class="dt">void</span> <span class="op">*(*</span>__vector_realloc<span class="op">)(</span><span class="dt">void</span> <span class="op">*,</span> <span class="dt">size_t</span><span class="op">)</span> <span class="op">=</span> realloc<span class="op">;</span></span>
<span id="cb10-10"><a href="#cb10-10"></a><span class="dt">static</span> <span class="dt">void</span> <span class="op">(*</span>__vector_free<span class="op">)(</span><span class="dt">void</span> <span class="op">*)</span> <span class="op">=</span> free<span class="op">;</span></span>
<span id="cb10-11"><a href="#cb10-11"></a></span>
<span id="cb10-12"><a href="#cb10-12"></a><span class="dt">void</span> vector_set_alloc<span class="op">(</span><span class="dt">void</span> <span class="op">*(</span>malloc<span class="op">)(</span><span class="dt">size_t</span><span class="op">),</span> <span class="dt">void</span> <span class="op">*(</span>realloc<span class="op">)(</span><span class="dt">void</span> <span class="op">*,</span> <span class="dt">size_t</span><span class="op">),</span></span>
<span id="cb10-13"><a href="#cb10-13"></a>                      <span class="dt">void</span> <span class="op">(*</span>free<span class="op">)(</span><span class="dt">void</span> <span class="op">*))</span> <span class="op">{</span></span>
<span id="cb10-14"><a href="#cb10-14"></a>  __vector_malloc <span class="op">=</span> malloc<span class="op">;</span></span>
<span id="cb10-15"><a href="#cb10-15"></a>  __vector_realloc <span class="op">=</span> realloc<span class="op">;</span></span>
<span id="cb10-16"><a href="#cb10-16"></a>  __vector_free <span class="op">=</span> free<span class="op">;</span></span>
<span id="cb10-17"><a href="#cb10-17"></a><span class="op">}</span></span>
<span id="cb10-18"><a href="#cb10-18"></a></span>
<span id="cb10-19"><a href="#cb10-19"></a>Vector <span class="op">*</span>vector_new<span class="op">(</span><span class="dt">const</span> <span class="dt">size_t</span> len<span class="op">,</span> <span class="op">...)</span> <span class="op">{</span></span>
<span id="cb10-20"><a href="#cb10-20"></a>  Vector <span class="op">*</span>v <span class="op">=</span> __vector_malloc<span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span>Vector<span class="op">));</span></span>
<span id="cb10-21"><a href="#cb10-21"></a>  <span class="dt">int</span> capacity <span class="op">=</span> <span class="dv">8</span><span class="op">;</span></span>
<span id="cb10-22"><a href="#cb10-22"></a>  capacity <span class="op">=</span> max<span class="op">(</span>pow<span class="op">(</span><span class="dv">2</span><span class="op">,</span> ceil<span class="op">(</span>log<span class="op">(</span>len<span class="op">)</span> <span class="op">/</span> log<span class="op">(</span><span class="dv">2</span><span class="op">))),</span> capacity<span class="op">);</span></span>
<span id="cb10-23"><a href="#cb10-23"></a></span>
<span id="cb10-24"><a href="#cb10-24"></a>  v<span class="op">-&gt;</span>items <span class="op">=</span> __vector_malloc<span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span><span class="dt">int</span><span class="op">)</span> <span class="op">*</span> capacity<span class="op">);</span></span>
<span id="cb10-25"><a href="#cb10-25"></a>  v<span class="op">-&gt;</span>len <span class="op">=</span> len<span class="op">;</span></span>
<span id="cb10-26"><a href="#cb10-26"></a>  v<span class="op">-&gt;</span>capacity <span class="op">=</span> capacity<span class="op">;</span></span>
<span id="cb10-27"><a href="#cb10-27"></a></span>
<span id="cb10-28"><a href="#cb10-28"></a>  <span class="cf">if</span> <span class="op">(</span>len <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-29"><a href="#cb10-29"></a>    <span class="dt">va_list</span> argp<span class="op">;</span></span>
<span id="cb10-30"><a href="#cb10-30"></a>    va_start<span class="op">(</span>argp<span class="op">,</span> len<span class="op">);</span></span>
<span id="cb10-31"><a href="#cb10-31"></a></span>
<span id="cb10-32"><a href="#cb10-32"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> len<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb10-33"><a href="#cb10-33"></a>      v<span class="op">-&gt;</span>items<span class="op">[</span>i<span class="op">]</span> <span class="op">=</span> va_arg<span class="op">(</span>argp<span class="op">,</span> <span class="dt">int</span><span class="op">);</span></span>
<span id="cb10-34"><a href="#cb10-34"></a>    <span class="op">}</span></span>
<span id="cb10-35"><a href="#cb10-35"></a></span>
<span id="cb10-36"><a href="#cb10-36"></a>    va_end<span class="op">(</span>argp<span class="op">);</span></span>
<span id="cb10-37"><a href="#cb10-37"></a>  <span class="op">}</span></span>
<span id="cb10-38"><a href="#cb10-38"></a></span>
<span id="cb10-39"><a href="#cb10-39"></a>  <span class="cf">return</span> v<span class="op">;</span></span>
<span id="cb10-40"><a href="#cb10-40"></a><span class="op">}</span></span>
<span id="cb10-41"><a href="#cb10-41"></a></span>
<span id="cb10-42"><a href="#cb10-42"></a><span class="dt">void</span> vector_free<span class="op">(</span>Vector <span class="op">*</span>v<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-43"><a href="#cb10-43"></a>  __vector_free<span class="op">(</span>v<span class="op">-&gt;</span>items<span class="op">);</span></span>
<span id="cb10-44"><a href="#cb10-44"></a>  __vector_free<span class="op">(</span>v<span class="op">);</span></span>
<span id="cb10-45"><a href="#cb10-45"></a><span class="op">}</span></span>
<span id="cb10-46"><a href="#cb10-46"></a></span>
<span id="cb10-47"><a href="#cb10-47"></a><span class="dt">int</span> vector_get<span class="op">(</span>Vector <span class="op">*</span>v<span class="op">,</span> <span class="dt">size_t</span> index<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-48"><a href="#cb10-48"></a>  assert<span class="op">(</span>index <span class="op">&gt;=</span> <span class="dv">0</span> <span class="op">&amp;&amp;</span> index <span class="op">&lt;</span> v<span class="op">-&gt;</span>len<span class="op">);</span></span>
<span id="cb10-49"><a href="#cb10-49"></a>  <span class="cf">return</span> v<span class="op">-&gt;</span>items<span class="op">[</span>index<span class="op">];</span></span>
<span id="cb10-50"><a href="#cb10-50"></a><span class="op">}</span></span>
<span id="cb10-51"><a href="#cb10-51"></a></span>
<span id="cb10-52"><a href="#cb10-52"></a><span class="dt">void</span> vector_set<span class="op">(</span>Vector <span class="op">*</span>v<span class="op">,</span> <span class="dt">size_t</span> index<span class="op">,</span> <span class="dt">int</span> val<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-53"><a href="#cb10-53"></a>  assert<span class="op">(</span>index <span class="op">&gt;=</span> <span class="dv">0</span> <span class="op">&amp;&amp;</span> index <span class="op">&lt;</span> v<span class="op">-&gt;</span>len<span class="op">);</span></span>
<span id="cb10-54"><a href="#cb10-54"></a>  v<span class="op">-&gt;</span>items<span class="op">[</span>index<span class="op">]</span> <span class="op">=</span> val<span class="op">;</span></span>
<span id="cb10-55"><a href="#cb10-55"></a><span class="op">}</span></span>
<span id="cb10-56"><a href="#cb10-56"></a></span>
<span id="cb10-57"><a href="#cb10-57"></a><span class="dt">int</span> vector_empty<span class="op">(</span>Vector <span class="op">*</span>v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> v<span class="op">-&gt;</span>len <span class="op">==</span> <span class="dv">0</span><span class="op">;</span> <span class="op">}</span></span>
<span id="cb10-58"><a href="#cb10-58"></a></span>
<span id="cb10-59"><a href="#cb10-59"></a><span class="dt">void</span> vector_push<span class="op">(</span>Vector <span class="op">*</span>v<span class="op">,</span> <span class="dt">int</span> val<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-60"><a href="#cb10-60"></a>  <span class="cf">if</span> <span class="op">(</span>v<span class="op">-&gt;</span>len <span class="op">==</span> v<span class="op">-&gt;</span>capacity<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-61"><a href="#cb10-61"></a>    v<span class="op">-&gt;</span>capacity <span class="op">*=</span> <span class="dv">2</span><span class="op">;</span></span>
<span id="cb10-62"><a href="#cb10-62"></a>    v<span class="op">-&gt;</span>items <span class="op">=</span> __vector_realloc<span class="op">(</span>v<span class="op">-&gt;</span>items<span class="op">,</span> <span class="kw">sizeof</span><span class="op">(</span><span class="dt">int</span><span class="op">)</span> <span class="op">*</span> v<span class="op">-&gt;</span>capacity<span class="op">);</span></span>
<span id="cb10-63"><a href="#cb10-63"></a>  <span class="op">}</span></span>
<span id="cb10-64"><a href="#cb10-64"></a>  v<span class="op">-&gt;</span>items<span class="op">[</span>v<span class="op">-&gt;</span>len<span class="op">]</span> <span class="op">=</span> val<span class="op">;</span></span>
<span id="cb10-65"><a href="#cb10-65"></a>  v<span class="op">-&gt;</span>len<span class="op">++;</span></span>
<span id="cb10-66"><a href="#cb10-66"></a><span class="op">}</span></span>
<span id="cb10-67"><a href="#cb10-67"></a></span>
<span id="cb10-68"><a href="#cb10-68"></a><span class="dt">int</span> <span class="op">*</span>vector_begin<span class="op">(</span>Vector <span class="op">*</span>v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">&amp;</span>v<span class="op">-&gt;</span>items<span class="op">[</span><span class="dv">0</span><span class="op">];</span> <span class="op">}</span></span>
<span id="cb10-69"><a href="#cb10-69"></a></span>
<span id="cb10-70"><a href="#cb10-70"></a><span class="dt">int</span> <span class="op">*</span>vector_end<span class="op">(</span>Vector <span class="op">*</span>v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">&amp;</span>v<span class="op">-&gt;</span>items<span class="op">[</span>v<span class="op">-&gt;</span>len<span class="op">];</span> <span class="op">}</span></span>
<span id="cb10-71"><a href="#cb10-71"></a></span>
<span id="cb10-72"><a href="#cb10-72"></a><span class="dt">int</span> <span class="op">*</span>vector_next<span class="op">(</span>Vector <span class="op">*</span>v<span class="op">,</span> <span class="dt">int</span> <span class="op">*</span>it<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-73"><a href="#cb10-73"></a>  <span class="cf">if</span> <span class="op">(</span>it <span class="op">!=</span> vector_end<span class="op">(</span>v<span class="op">))</span></span>
<span id="cb10-74"><a href="#cb10-74"></a>    <span class="cf">return</span> <span class="op">++</span>it<span class="op">;</span></span>
<span id="cb10-75"><a href="#cb10-75"></a>  <span class="cf">return</span> NULL<span class="op">;</span></span>
<span id="cb10-76"><a href="#cb10-76"></a><span class="op">}</span></span>
<span id="cb10-77"><a href="#cb10-77"></a></span>
<span id="cb10-78"><a href="#cb10-78"></a><span class="dt">void</span> vector_for_each<span class="op">(</span>Vector <span class="op">*</span>v<span class="op">,</span> <span class="dt">int</span> <span class="op">(*</span>fn<span class="op">)(</span><span class="dt">int</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb10-79"><a href="#cb10-79"></a>  <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> v<span class="op">-&gt;</span>len<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb10-80"><a href="#cb10-80"></a>    v<span class="op">-&gt;</span>items<span class="op">[</span>i<span class="op">]</span> <span class="op">=</span> <span class="op">(*</span>fn<span class="op">)(</span>v<span class="op">-&gt;</span>items<span class="op">[</span>i<span class="op">]);</span></span>
<span id="cb10-81"><a href="#cb10-81"></a>  <span class="op">}</span></span>
<span id="cb10-82"><a href="#cb10-82"></a><span class="op">}</span></span>
<span id="cb10-83"><a href="#cb10-83"></a></span>
<span id="cb10-84"><a href="#cb10-84"></a><span class="dt">int</span> vector_pop<span class="op">(</span>Vector <span class="op">*</span>v<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-85"><a href="#cb10-85"></a>  assert<span class="op">(</span>v<span class="op">-&gt;</span>len <span class="op">&gt;</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb10-86"><a href="#cb10-86"></a>  <span class="dt">int</span> top <span class="op">=</span> v<span class="op">-&gt;</span>items<span class="op">[</span>v<span class="op">-&gt;</span>len <span class="op">-</span> <span class="dv">1</span><span class="op">];</span></span>
<span id="cb10-87"><a href="#cb10-87"></a>  v<span class="op">-&gt;</span>len<span class="op">--;</span></span>
<span id="cb10-88"><a href="#cb10-88"></a>  <span class="cf">return</span> top<span class="op">;</span></span>
<span id="cb10-89"><a href="#cb10-89"></a><span class="op">}</span></span></code></pre></div>]]></description>
</item>
<item>
<title>Desert Island Discs</title>
<pubDate>Tue, 07 Sep 2021 03:47:22 +0000</pubDate>
<guid>https://blog/desert-island-discs.html</guid>
<description><![CDATA[<p>What would be the eight software programs you
would take to a deserted island? To me, I’d need the following: an OS,
libc, a C compiler, a shell, a database, a networking stack, unix utils,
a lisp interpreter, and an editor. I’ve decided to try my hand at
writing these to get better at low-level programming, and learn the
stack a bit better. It’s a good challenge, but in the interest of time
and sanity I will be putting lots of asterisks next to each disc.</p>
<h2 id="an-operating-system">An Operating System</h2>
<p>I’m not going to write an OS. Maybe I’ll write some signals and
system calls, but that’s about it.</p>
<h2 id="a-c-compiler">A C Compiler</h2>
<p>I’ll write a C Compiler that implements <strong>most</strong> of C89,
that emits assembly of the computer I’m working on.</p>
<h2 id="libc">Libc</h2>
<p>A limited subset of libc would be nice. Plauger has a good book on
implementing a C89 compliant libc, which I will most likely follow,
along with looking at some code from musl.</p>
<p>As well, I’ll be writing some crypto and data structures to help with
other tasks down the road.</p>
<h2 id="a-shell">A shell</h2>
<p>Nothing like bash. I’ve decided to write a small shell and relegate
the rest to the shell I’m currently working on.</p>
<h2 id="a-database">A Database</h2>
<p>A simple serializable Key-Value database should suffice. Will need to
learn B-Trees, though.</p>
<h2 id="a-networking-stack">A Networking Stack</h2>
<p>I’ll learn how to write an HTTP Client and Server using the sockets
library.</p>
<h2 id="unix-utils">Unix Utils</h2>
<p>I’ll write some basic unix utils, striving for some partial POSIX
compliance.</p>
<h2 id="a-lisp-interpreter">A Lisp Interpreter</h2>
<p>Lisp, being one of the simplest languages, allows me to write a
higher level language from C. That makes it a great target for an
interpreter to learn from.</p>
<h2 id="a-text-editor">A Text Editor</h2>
<p>Vim is my text editor of choice; it’d be nice to be able to write an
editor with some similar functionality.</p>]]></description>
</item>
<item>
<title>The Expression Problem And Operations On Matricies</title>
<pubDate>Tue, 22 Jun 2021 12:52:01 +0000</pubDate>
<guid>https://blog/the-expression-problem-and-operations-on-matricies.html</guid>
<description><![CDATA[<p>I’ve heard the sentiment that technical
interviews focus on the wrong things; technical aptitude in data
structures and algorithms isn’t a great measure of people’s on the job
performance. I agree. That being said, there are some small problems
where cursory knowledge in them can help you out.</p>
<p>I’m going to use an example I encountered recently, where I wanted to
aggregate my personal finances into monthly, quarterly, and yearly
reports, with columns for earnings, spend, and cashflow (earnings -
spend).</p>
<p>I downloaded the relevant CSVs and went to work parsing them.</p>
<h2 id="parsing">Parsing</h2>
<p>The first problem came with cleaning up some transactions that were
unnecessary – banks tend to charge a maintenance fee, but they end up
crediting you if you meet certain criteria. Even though this balances
out, I didn’t want this to count in my earnings and spend, so I wrote a
<code>sed</code> regex to delete these lines. Likewise, I wanted to
remove some of my investments that I had made (I don’t consider these to
be spending, and I wanted to track these another way). Another
<code>sed</code> regex it is. Eventually this became a pain, so I made a
bash function to combine the regexes in an array to parse the CSV. You
just add regexes and it’ll remove the related transactions. Easy
enough.</p>
<h2 id="the-problem">The problem</h2>
<p>If you visualize the problem at hand, you’ll get this matrix.</p>
<table>
<thead>
<tr>
<th style="text-align: center;"></th>
<th style="text-align: center;">Monthly</th>
<th>Quarterly</th>
<th>Yearly</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">Earnings</td>
<td style="text-align: center;">Monthly Earnings</td>
<td>Quarterly Earnings</td>
<td>Yearly Earnings</td>
</tr>
<tr>
<td style="text-align: center;">Spend</td>
<td style="text-align: center;">Monthly Spend</td>
<td>Quarterly Spend</td>
<td>Yearly Spend</td>
</tr>
<tr>
<td style="text-align: center;">Cashflow</td>
<td style="text-align: center;">Monthly Cashflow</td>
<td>Quarterly Cashflow</td>
<td>Yearly Cashflow</td>
</tr>
</tbody>
</table>
<p>We have an (m * n) problem, where if we had a new row or column, we
add (m) or (n) more things we need to calculate.</p>
<p>Let’s get solving.</p>
<h2 id="naive-approach">Naive Approach</h2>
<p>The Naive approach is the O(m * n) solution, where you create a
function that deals with a particular cell of this matrix. Take Monthly
Earnings. You would write a function that does the logic for dividing
the CSV into months, and then applying the logic for Earnings to it.</p>
<p>You would repeat this eight times, to get 9 different functions.</p>
<p>When calling this logic, you would have a switch-case that would
select the logic required.</p>
<p>This isn’t very dry, and very tedious, even with only 9 cells. I
wanted something better. This is due to the runtime of matricies.</p>
<h1 id="the-expression-problem">The Expression problem</h1>
<p>The <a
href="https://craftinginterpreters.com/representing-code.html#the-expression-problem">expression
problem</a> is a fundamental problem in writing functions that work on
types and vice versa.</p>
<p>OOP Languages like Java make it easy to create new types that have
operations on data. But let’s say you want to add a new method to all
your classes. You now need to add a new method to all of your existing
and future classes.</p>
<p>ML type languages use pattern matching, which allows you to easily
add new operations to a function. But to apply that operation to all
existing types, you have to add a new case to all of the pattern
matches.</p>
<p>Let’s say I add a new time period, “bi-yearly” to denote half a year
chunks. Well, if we go by the naive case, we’d have to add new cases for
bi-yearly + cashflow, bi-yearly + earnings, bi-yearly + spend. That’s 3
new functions for one new time period. Ouch.</p>
<p>Let’s say I want a new category that only counts purchases that are
larger than $100, and call these “large purchases”. If so, I would have
to add logic to count for monthly, quarterly, bi-yearly, and yearly time
periods. That’s 4 new functions for a new category.</p>
<p>Let’s say I want to add a new dimension. I want to split my purchases
for all of the above categories and time periods between my credit card
and debit card. That’s 4 * 4, or 16 new functions I’d need to
implement.</p>
<p>Big O notation would say this grows linearly with regards to the size
of each dimension.</p>
<p>If we have 4 monetary categories and 4 time periods, we have 4 * 4 or
16 functions to implement. If we have 4 monetary categories, 4 time
periods, and 2 types of credit cards, we have 4 * 4 * 2, or 32 functions
to implement.</p>
<p>Our first proposed matrix is a 2D square, and we’re calculating its
area. A square with a length of four and a height of 4 has an area of
16.</p>
<p>Our second proposed matrix is a 3D square (a cube). To calculate the
area of a cube, you multiply its length, width, and height. We have a
length of 4, a width of 4, and a height of 2, totalling 32.</p>
<p>As we add new fields to our rows and columns, and new dimensions to
our matrix, we’ll soon see that this becomes untenable. (What happens if
I also want to count my investment accounts, of which I have many? I’d
have to add more and more dimensions, and the amount of functions to
implement increases quite a lot.</p>
<h2 id="improving-the-naive-approach">Improving the Naive Approach</h2>
<p>In the interest of clean code, I wanted to create small composable
functions that would calculate the each category.</p>
<p>The Earnings function would only calculate transactions with a
positive amount The Spend function would only calculate transactions
with a negative amount The Cashflow function would calculate all
transactions.</p>
<p>The Monthly function would divide the CSV into months, and apply a
function to each range. The Quarterly function would divide the CSV into
quarters, and apply a function to each range. The Yearly function would
divide the CSV into years, and apply a function to each range.</p>
<p>But the problem is how to set this up properly.</p>
<p>We need some way to signal to the main function that we want to
calculate a row * column pairing (a cell). If we add a new dimension, we
don’t want to break previous code.</p>
<h2 id="using-a-pair">Using a pair</h2>
<p>One way to signal this is to use a pair of enums that are captured in
a pair as (row, col). This works well enough if we stick to two
dimensions. If we add a 3rd dimension, though, this will create
incorrect code. If we’re strict on requiring a pair, then we can’t add
the 3rd dimension at all without breaking all of our existing code. If
we’re looser (allow any tuple, and unpack the first, second and third
values) this will work, but our code will be a bit confusing in order to
maintain backwards compatibility (some code will check the first and
second fields of a 3-tuple, even though it should be checking all
three).</p>
<h2 id="using-a-flag">Using a flag</h2>
<p>Another way to signal this is to use a Flag enum. A flag enum is an
enum that has values corresponding to powers of 2.</p>
<p>For example:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1"></a><span class="kw">typedef</span> <span class="kw">enum</span> Color <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2"></a>  RED <span class="op">=</span> <span class="dv">1</span><span class="op">,</span></span>
<span id="cb1-3"><a href="#cb1-3"></a>  GREEN <span class="op">=</span> <span class="dv">2</span><span class="op">,</span></span>
<span id="cb1-4"><a href="#cb1-4"></a>  BLUE <span class="op">=</span> <span class="dv">4</span></span>
<span id="cb1-5"><a href="#cb1-5"></a><span class="op">}</span> Color<span class="op">;</span></span></code></pre></div>
<p>(Some people prefer to write it like this, to be explicit that this
is a flag):</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1"></a><span class="kw">typedef</span> <span class="kw">enum</span> Color <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2"></a>  RED <span class="op">=</span> <span class="dv">1</span> <span class="op">&lt;&lt;</span> <span class="dv">0</span><span class="op">,</span> <span class="co">// 1 </span></span>
<span id="cb2-3"><a href="#cb2-3"></a>  GREEN <span class="op">=</span> <span class="dv">1</span> <span class="op">&lt;&lt;</span> <span class="dv">1</span><span class="op">,</span> <span class="co">// 2</span></span>
<span id="cb2-4"><a href="#cb2-4"></a>  BLUE <span class="op">=</span> <span class="dv">1</span> <span class="op">&lt;&lt;</span> <span class="dv">2</span><span class="op">,</span> <span class="co">// 4</span></span>
<span id="cb2-5"><a href="#cb2-5"></a><span class="op">}</span> Color<span class="op">;</span></span></code></pre></div>
<p>This has the nice property that we can use bitwise or to denote more
than one state, and bitwise and to check if the enum is one or more or a
particular state.</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1"></a>Color color <span class="op">=</span> RED <span class="op">|</span> GREEN<span class="op">;</span> <span class="co">// this color is Red and Green</span></span>
<span id="cb3-2"><a href="#cb3-2"></a>Color Black <span class="op">=</span> RED <span class="op">|</span> GREEN <span class="op">|</span> BLUE<span class="op">;</span> <span class="co">// this color, black, is all the colors</span></span>
<span id="cb3-3"><a href="#cb3-3"></a></span>
<span id="cb3-4"><a href="#cb3-4"></a><span class="cf">if</span> <span class="op">(</span>color <span class="op">&amp;</span> RED<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-5"><a href="#cb3-5"></a>  <span class="co">// this color has red, do some logic in the red case</span></span>
<span id="cb3-6"><a href="#cb3-6"></a><span class="op">}</span></span>
<span id="cb3-7"><a href="#cb3-7"></a><span class="cf">if</span> <span class="op">(</span>color <span class="op">&amp;</span> GREEN<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-8"><a href="#cb3-8"></a>  <span class="co">// this color has green, do some logic in the green case</span></span>
<span id="cb3-9"><a href="#cb3-9"></a><span class="op">}</span></span>
<span id="cb3-10"><a href="#cb3-10"></a><span class="cf">if</span> <span class="op">(</span>color <span class="op">&amp;</span> BLUE<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-11"><a href="#cb3-11"></a>  <span class="co">// this color has blue, do some logic in the blue case</span></span>
<span id="cb3-12"><a href="#cb3-12"></a><span class="op">}</span></span></code></pre></div>
<p>In C, since enums are stored as an unsigned int, you can store up to
32 fields (rows + columns + dimensions, in our case). Sometimes this
isn’t enough, and you’ll have to find another way, but in our case, it
works fine.</p>
<h2 id="the-final-implementation">The final implementation</h2>
<p>Finally to solve the problem, we want to provide a flag enum, and get
the CSV that we’re applying it to. First, we want to slice the CSV into
the range provided, and then apply some category (Earning, Spend,
Cashflow) to it, and then save the CSV.</p>
<p>That can be done something like this:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1"></a><span class="kw">typedef</span> <span class="kw">enum</span> Categories <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2"></a>  MONTHLY <span class="op">=</span> <span class="dv">1</span> <span class="op">&lt;&lt;</span> <span class="dv">0</span><span class="op">,</span></span>
<span id="cb4-3"><a href="#cb4-3"></a>  QUARTERLY <span class="op">=</span> <span class="dv">1</span> <span class="op">&lt;&lt;</span> <span class="dv">1</span><span class="op">,</span></span>
<span id="cb4-4"><a href="#cb4-4"></a>  YEARLY <span class="op">=</span> <span class="dv">1</span> <span class="op">&lt;&lt;</span> <span class="dv">2</span><span class="op">,</span></span>
<span id="cb4-5"><a href="#cb4-5"></a>  EARNINGS <span class="op">=</span> <span class="dv">1</span> <span class="op">&lt;&lt;</span> <span class="dv">3</span><span class="op">,</span></span>
<span id="cb4-6"><a href="#cb4-6"></a>  SPEND <span class="op">=</span> <span class="dv">1</span> <span class="op">&lt;&lt;</span> <span class="dv">4</span><span class="op">,</span></span>
<span id="cb4-7"><a href="#cb4-7"></a>  CASHFLOW <span class="op">=</span> <span class="dv">1</span> <span class="op">&lt;&lt;</span> <span class="dv">5</span><span class="op">,</span></span>
<span id="cb4-8"><a href="#cb4-8"></a><span class="op">}</span> Categories<span class="op">;</span></span>
<span id="cb4-9"><a href="#cb4-9"></a></span>
<span id="cb4-10"><a href="#cb4-10"></a><span class="dt">void</span> generateCsvs<span class="op">(</span>Category category<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-11"><a href="#cb4-11"></a>  <span class="cf">if</span> <span class="op">(</span>category <span class="op">&amp;</span> MONTHLY<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-12"><a href="#cb4-12"></a>    doMonthlyLogic<span class="op">();</span></span>
<span id="cb4-13"><a href="#cb4-13"></a>  <span class="op">}</span></span>
<span id="cb4-14"><a href="#cb4-14"></a>  <span class="cf">if</span> <span class="op">(</span>category <span class="op">&amp;</span> QUARTERLY<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-15"><a href="#cb4-15"></a>    doQuarterlyLogic<span class="op">();</span></span>
<span id="cb4-16"><a href="#cb4-16"></a>  <span class="op">}</span></span>
<span id="cb4-17"><a href="#cb4-17"></a>  <span class="cf">if</span> <span class="op">(</span>category <span class="op">&amp;</span> YEARLY<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-18"><a href="#cb4-18"></a>    doYearlyLogic<span class="op">();</span></span>
<span id="cb4-19"><a href="#cb4-19"></a>  <span class="op">}</span></span>
<span id="cb4-20"><a href="#cb4-20"></a>  <span class="cf">if</span> <span class="op">(</span>category <span class="op">&amp;</span> EARNINGS<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-21"><a href="#cb4-21"></a>    doEarningsLogic<span class="op">();</span></span>
<span id="cb4-22"><a href="#cb4-22"></a>  <span class="op">}</span></span>
<span id="cb4-23"><a href="#cb4-23"></a>  <span class="cf">if</span> <span class="op">(</span>category <span class="op">&amp;</span> SPEND<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-24"><a href="#cb4-24"></a>    doSpendLogic<span class="op">();</span></span>
<span id="cb4-25"><a href="#cb4-25"></a>  <span class="op">}</span></span>
<span id="cb4-26"><a href="#cb4-26"></a>  <span class="cf">if</span> <span class="op">(</span>category <span class="op">&amp;</span> CASHFLOW<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-27"><a href="#cb4-27"></a>    doCashflowLogic<span class="op">();</span></span>
<span id="cb4-28"><a href="#cb4-28"></a>  <span class="op">}</span></span>
<span id="cb4-29"><a href="#cb4-29"></a><span class="op">}</span></span></code></pre></div>
<p>We can generate our CSVs just like that. Nice. If we add a new
dimension, like Credit card vs debit card, all we have to do is add it
to our enum and our main function. This only adds two new enums and two
new cases. We’ve gone from adding (m * n) functions for our logic to
just (m + n). Big O strikes again.</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1"></a><span class="kw">typedef</span> <span class="kw">enum</span> Categories <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2"></a>  MONTHLY <span class="op">=</span> <span class="dv">1</span> <span class="op">&lt;&lt;</span> <span class="dv">0</span><span class="op">,</span></span>
<span id="cb5-3"><a href="#cb5-3"></a>  QUARTERLY <span class="op">=</span> <span class="dv">1</span> <span class="op">&lt;&lt;</span> <span class="dv">1</span><span class="op">,</span></span>
<span id="cb5-4"><a href="#cb5-4"></a>  YEARLY <span class="op">=</span> <span class="dv">1</span> <span class="op">&lt;&lt;</span> <span class="dv">2</span><span class="op">,</span></span>
<span id="cb5-5"><a href="#cb5-5"></a>  EARNINGS <span class="op">=</span> <span class="dv">1</span> <span class="op">&lt;&lt;</span> <span class="dv">3</span><span class="op">,</span></span>
<span id="cb5-6"><a href="#cb5-6"></a>  SPEND <span class="op">=</span> <span class="dv">1</span> <span class="op">&lt;&lt;</span> <span class="dv">4</span><span class="op">,</span></span>
<span id="cb5-7"><a href="#cb5-7"></a>  CASHFLOW <span class="op">=</span> <span class="dv">1</span> <span class="op">&lt;&lt;</span> <span class="dv">5</span><span class="op">,</span></span>
<span id="cb5-8"><a href="#cb5-8"></a>  CREDIT <span class="op">=</span> <span class="dv">1</span> <span class="op">&lt;&lt;</span> <span class="dv">6</span><span class="op">,</span></span>
<span id="cb5-9"><a href="#cb5-9"></a>  DEBIT <span class="op">=</span> <span class="dv">1</span> <span class="op">&lt;&lt;</span> <span class="dv">7</span><span class="op">,</span></span>
<span id="cb5-10"><a href="#cb5-10"></a><span class="op">}</span> Categories<span class="op">;</span></span>
<span id="cb5-11"><a href="#cb5-11"></a></span>
<span id="cb5-12"><a href="#cb5-12"></a><span class="dt">void</span> generateCsvs<span class="op">(</span>Categories category<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-13"><a href="#cb5-13"></a>  <span class="cf">if</span> <span class="op">(</span>category <span class="op">&amp;</span> CREDIT<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-14"><a href="#cb5-14"></a>    doCreditLogic<span class="op">();</span></span>
<span id="cb5-15"><a href="#cb5-15"></a>  <span class="op">}</span></span>
<span id="cb5-16"><a href="#cb5-16"></a>  <span class="cf">if</span> <span class="op">(</span>category <span class="op">&amp;</span> DEBIT<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-17"><a href="#cb5-17"></a>    doDebitLogic<span class="op">();</span></span>
<span id="cb5-18"><a href="#cb5-18"></a>  <span class="op">}</span></span>
<span id="cb5-19"><a href="#cb5-19"></a>  <span class="cf">if</span> <span class="op">(</span>category <span class="op">&amp;</span> MONTHLY<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-20"><a href="#cb5-20"></a>    doMonthlyLogic<span class="op">();</span></span>
<span id="cb5-21"><a href="#cb5-21"></a>  <span class="op">}</span></span>
<span id="cb5-22"><a href="#cb5-22"></a>  <span class="cf">if</span> <span class="op">(</span>category <span class="op">&amp;</span> QUARTERLY<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-23"><a href="#cb5-23"></a>    doQuarterlyLogic<span class="op">();</span></span>
<span id="cb5-24"><a href="#cb5-24"></a>  <span class="op">}</span></span>
<span id="cb5-25"><a href="#cb5-25"></a>  <span class="cf">if</span> <span class="op">(</span>category <span class="op">&amp;</span> YEARLY<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-26"><a href="#cb5-26"></a>    doYearlyLogic<span class="op">();</span></span>
<span id="cb5-27"><a href="#cb5-27"></a>  <span class="op">}</span></span>
<span id="cb5-28"><a href="#cb5-28"></a>  <span class="cf">if</span> <span class="op">(</span>category <span class="op">&amp;</span> EARNINGS<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-29"><a href="#cb5-29"></a>    doEarningsLogic<span class="op">();</span></span>
<span id="cb5-30"><a href="#cb5-30"></a>  <span class="op">}</span></span>
<span id="cb5-31"><a href="#cb5-31"></a>  <span class="cf">if</span> <span class="op">(</span>category <span class="op">&amp;</span> SPEND<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-32"><a href="#cb5-32"></a>    doSpendLogic<span class="op">();</span></span>
<span id="cb5-33"><a href="#cb5-33"></a>  <span class="op">}</span></span>
<span id="cb5-34"><a href="#cb5-34"></a>  <span class="cf">if</span> <span class="op">(</span>category <span class="op">&amp;</span> CASHFLOW<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-35"><a href="#cb5-35"></a>    doCashflowLogic<span class="op">();</span></span>
<span id="cb5-36"><a href="#cb5-36"></a>  <span class="op">}</span></span>
<span id="cb5-37"><a href="#cb5-37"></a><span class="op">}</span></span></code></pre></div>
<p>If we wanted more than 31 categories, we could still do that using a
struct instead of an enum. This creates a struct where every member is a
boolean flag, and we’re checking if it’s set in our generateCsvs
code.</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb6-1"><a href="#cb6-1"></a><span class="kw">typedef</span> <span class="kw">struct</span> Categories <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2"></a>  <span class="dt">int</span> MONTHLY <span class="op">:</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb6-3"><a href="#cb6-3"></a>  <span class="dt">int</span> QUARTERLY <span class="op">:</span> <span class="dv">1</span><span class="op">;</span> </span>
<span id="cb6-4"><a href="#cb6-4"></a>  <span class="dt">int</span> YEARLY <span class="op">:</span> <span class="dv">1</span><span class="op">;</span> </span>
<span id="cb6-5"><a href="#cb6-5"></a>  <span class="dt">int</span> EARNINGS <span class="op">:</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb6-6"><a href="#cb6-6"></a>  <span class="dt">int</span> SPEND <span class="op">:</span> <span class="dv">1</span><span class="op">;</span> </span>
<span id="cb6-7"><a href="#cb6-7"></a>  <span class="dt">int</span> CASHFLOW <span class="op">:</span> <span class="dv">1</span><span class="op">;</span> </span>
<span id="cb6-8"><a href="#cb6-8"></a>  <span class="dt">int</span> CREDIT <span class="op">:</span> <span class="dv">1</span><span class="op">;</span> </span>
<span id="cb6-9"><a href="#cb6-9"></a>  <span class="dt">int</span> DEBIT <span class="op">:</span> <span class="dv">1</span><span class="op">;</span> </span>
<span id="cb6-10"><a href="#cb6-10"></a><span class="op">}</span> Categories<span class="op">;</span></span>
<span id="cb6-11"><a href="#cb6-11"></a></span>
<span id="cb6-12"><a href="#cb6-12"></a>Categories category <span class="op">=</span> <span class="op">{</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">1</span> <span class="op">};</span> <span class="co">// MONTHLY and EARNINGS are set, everything else is zero-initialized.</span></span>
<span id="cb6-13"><a href="#cb6-13"></a></span>
<span id="cb6-14"><a href="#cb6-14"></a><span class="co">// or this:</span></span>
<span id="cb6-15"><a href="#cb6-15"></a>Categories category <span class="op">=</span> <span class="op">{};</span></span>
<span id="cb6-16"><a href="#cb6-16"></a>category<span class="op">.</span>MONTHLY <span class="op">=</span> <span class="dv">1</span><span class="op">;</span> <span class="co">// set MONTHLY;</span></span>
<span id="cb6-17"><a href="#cb6-17"></a>category<span class="op">.</span>EARNINGS <span class="op">=</span> <span class="dv">1</span><span class="op">;</span> <span class="co">// set EARNINGS; </span></span>
<span id="cb6-18"><a href="#cb6-18"></a></span>
<span id="cb6-19"><a href="#cb6-19"></a><span class="dt">void</span> generateCsvs<span class="op">(</span>Categories category<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-20"><a href="#cb6-20"></a>  <span class="cf">if</span> <span class="op">(</span>category<span class="op">.</span>MONTHLY<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-21"><a href="#cb6-21"></a>    doMonthlyLogic<span class="op">();</span></span>
<span id="cb6-22"><a href="#cb6-22"></a>  <span class="op">}</span></span>
<span id="cb6-23"><a href="#cb6-23"></a>  <span class="co">// etc.</span></span>
<span id="cb6-24"><a href="#cb6-24"></a><span class="op">}</span></span></code></pre></div>
<h2 id="a-note-on-associativity">A note on Associativity</h2>
<p>But wait, there’s something we can improve upon in our solution:</p>
<p>You might’ve noticed that we’re coupling our code based on time.
Since we’ve decided to cut up the CSV first by time and then calculate
the monetary category, you’ve noticed that if we flip the order of them,
we might get a different result. This is bad, because refactoring tends
to reorder things, and code that is coupled throughout time tends to
lead to messier code.</p>
<p>To improve this, we need to add a few restrictions.</p>
<p>But first, a review on associativity and composition.</p>
<p>Associativity means that the order a function is applied in doesn’t
matter.</p>
<p>Let’s take the multiplication function. You’ll notice that we can
apply them in any order and the function is still correct.</p>
<blockquote>
<p>4 * 3 * 2 == (4 * 3) * 2 == 4 * (3 * 2)</p>
</blockquote>
<p>Whereas division is not associative, because:</p>
<blockquote>
<p>(12 / 2) / 3 != 12 / (2 / 3).</p>
</blockquote>
<p>What we did above was like division, where we must apply the
functions in some order, so they are coupled in time (the parentheses
denote this). What we really want is a mulitiplicative (associative)
function, because no matter how many changes we make to the code, it
will only grow in complexity linearly, not polynomially.</p>
<p>Thus, if we guarantee that our operations are associative, then we
don’t have to worry about how we lay out our main function at all.</p>
<p>To do this, we’ll have to write our functions in a way that they take
a CSV and return a CSV after doing some to work them. These CSVs must
work on every other CSV that any other step in the main function can
produce. So, we’ll change our main function to be like this, where every
function takes the CSV and returns a CSV.</p>
<p>We’ll use the flag enum to make sure that we’re applying just the
functions that we want.</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb7-1"><a href="#cb7-1"></a><span class="dt">void</span> generateCsvs<span class="op">(</span>Categories category<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2"></a>  csv <span class="op">=</span> <span class="op">{};</span> </span>
<span id="cb7-3"><a href="#cb7-3"></a>  <span class="co">// assume the CSV is an array</span></span>
<span id="cb7-4"><a href="#cb7-4"></a>  <span class="cf">if</span> <span class="op">(</span>category <span class="op">&amp;</span> CREDIT<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-5"><a href="#cb7-5"></a>    csv <span class="op">=</span> doCreditLogic<span class="op">(</span>csv<span class="op">);</span></span>
<span id="cb7-6"><a href="#cb7-6"></a>  <span class="op">}</span></span>
<span id="cb7-7"><a href="#cb7-7"></a>  <span class="cf">if</span> <span class="op">(</span>category <span class="op">&amp;</span> DEBIT<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-8"><a href="#cb7-8"></a>    csv <span class="op">=</span> doDebitLogic<span class="op">(</span>csv<span class="op">);</span></span>
<span id="cb7-9"><a href="#cb7-9"></a>  <span class="op">}</span></span>
<span id="cb7-10"><a href="#cb7-10"></a>  <span class="co">// etc</span></span>
<span id="cb7-11"><a href="#cb7-11"></a>  writeToCsv<span class="op">(</span>csv<span class="op">);</span></span>
<span id="cb7-12"><a href="#cb7-12"></a><span class="op">}</span></span>
<span id="cb7-13"><a href="#cb7-13"></a><span class="co">// this is the same function </span></span>
<span id="cb7-14"><a href="#cb7-14"></a><span class="dt">void</span> generateCsvs<span class="op">(</span>Categories category<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-15"><a href="#cb7-15"></a>  csv <span class="op">=</span> <span class="op">{};</span> </span>
<span id="cb7-16"><a href="#cb7-16"></a>  <span class="co">// We&#39;ve flipped the order, but it still works </span></span>
<span id="cb7-17"><a href="#cb7-17"></a>  <span class="cf">if</span> <span class="op">(</span>category <span class="op">&amp;</span> DEBIT<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-18"><a href="#cb7-18"></a>    csv <span class="op">=</span> doDebitLogic<span class="op">(</span>csv<span class="op">);</span></span>
<span id="cb7-19"><a href="#cb7-19"></a>  <span class="op">}</span></span>
<span id="cb7-20"><a href="#cb7-20"></a>  <span class="cf">if</span> <span class="op">(</span>category <span class="op">&amp;</span> CREDIT<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-21"><a href="#cb7-21"></a>    csv <span class="op">=</span> doCreditLogic<span class="op">(</span>csv<span class="op">);</span></span>
<span id="cb7-22"><a href="#cb7-22"></a>  <span class="op">}</span></span>
<span id="cb7-23"><a href="#cb7-23"></a>  <span class="co">// etc</span></span>
<span id="cb7-24"><a href="#cb7-24"></a>  writeToCsv<span class="op">(</span>csv<span class="op">);</span></span>
<span id="cb7-25"><a href="#cb7-25"></a><span class="op">}</span></span></code></pre></div>
<h2 id="conclusion">Conclusion</h2>
<p>We’ve seen how we can use flag enums, combined with some logic, to
cut down the amount of functions we have to write in order to calculate
the cell of a matrix. While I won’t agree big tech interviews are the
best way to assess candidates, sometimes these problems crop up, and
people have been grappling with them for a long time (like the
expression problem).</p>]]></description>
</item>
<item>
<title>Write RFCs</title>
<pubDate>Fri, 04 Jun 2021 01:00:10 +0000</pubDate>
<guid>https://blog/write-rfcs.html</guid>
<description><![CDATA[<p>RFCs are <code>Requests for Comments</code>,
popularized by the Internet Engineering Task Force (IETF) which develops
and promotes standards for the internet.</p>
<h2 id="defining-an-rfc">Defining an RFC</h2>
<p>Much has been said about RFCs (Including <a
href="https://datatracker.ietf.org/doc/html/rfc3">RFC 3</a> which
outlines how to write an RFC for the IETF), but let’s read through the
main points of RFC 3.</p>
<ul>
<li>RFCs can be on thoughts, suggestions, etc. relating to the subject
(The internet in this case)</li>
<li>RFCs should be timely, rather than polished</li>
<li>RFCs do not require examples</li>
<li>RFCs can be as short or as long as needed</li>
</ul>
<p>According to RFC 3, RFCs should have the following information:</p>
<ol type="1">
<li>“Network Working Group Request for Comments:” X (where X is the
number of the RFC)</li>
<li>Author and Affiliation</li>
<li>Date</li>
<li>Title (Does not need to be unique)</li>
</ol>
<h2 id="benefits-of-rfcs">Benefits of RFCs</h2>
<p>According to <a
href="https://buriti.ca/6-lessons-i-learned-while-implementing-technical-rfcs-as-a-management-tool-34687dbf46cb">6
Lessons I learned while implementing technical RFCs as a decision making
tool</a>, After implementing RFCs in his organization, Juan Pablo
Buriticá picked RFCs for the following reasons:</p>
<ul>
<li>enable individual contributors to make decisions for systems they’re
responsible for</li>
<li>allow domain experts to have input in decisions when they’re not
directly involved in building a particular system</li>
<li>manage the risk of decisions made</li>
<li>include team members without it becoming design by committee</li>
<li>have a snapshot of context for the future</li>
<li>be asynchronous</li>
<li>work on multiple projects in parallel</li>
</ul>
<p>In my company, RFCs allow us to propose ideas to improve processes,
development experience, the product, with low risk of retribution and
without the anxiety of giving a presentation. Q &amp; A is relaxed for
both the author of the RFC and those writing comments, as they are
allowed to proceed asynchronously, without either party feeling
pressured to have all the answers right away. They’re also a written
record of the thoughts of the authors and reviewers throughout the
lifecycle of the proposal, and serve as a historical artifact for
reflection (if a proposal that sounded good didn’t turn out so well, why
didn’t it work out?)</p>
<h2 id="implementing-rfcs">Implementing RFCs</h2>
<p>Oxide Computer explained how they do RFCs (which they call RFDs,
Requests for Discussions) here: <a
href="https://oxide.computer/blog/rfd-1-requests-for-discussion">RFDs at
Oxide Computer</a></p>
<p>At Oxide, RFDs are appropriate for the following cases:</p>
<ul>
<li>Add or change a company process</li>
<li>An architectural or design decision for hardware or software</li>
<li>Change to an API or command-line tool used by customers</li>
<li>Change to an internal API or tool</li>
<li>Change to an internal process</li>
<li>A design for testing</li>
</ul>
<p>Oxide has a few twists, like adding a state as metadata (an RFD can
be in the Prediscussion, Ideation, Discussion, Published, Committed, or
Abandoned state), and go into detail about integrating their RFD system
into git.</p>
<h2 id="a-template-for-rfcs">A Template for RFCs</h2>
<p>Following what Oxide did, I made a template repository for RFCs.</p>
<p>You can find it here: <a
href="https://github.com/Takashiidobe/rfcs">Template RFC
Repository</a></p>]]></description>
</item>
<item>
<title>Learning Recursion</title>
<pubDate>Thu, 03 Jun 2021 15:30:55 +0000</pubDate>
<guid>https://blog/learning-recursion.html</guid>
<description><![CDATA[<p>It’s been said that the only way to learn
recursion is to learn recursion. So let’s get started!</p>
<p>Recursion is defined by the repeated application of a procedure.
There are three distinct parts to creating a recursive function:</p>
<ol type="1">
<li>A terminating base case</li>
<li>Continuing the recursion</li>
<li>Making progress towards the base case</li>
</ol>
<p>Let’s look at all of them while applying them to a problem:</p>
<blockquote>
<p>Given an array of integers, return the sum of their values.</p>
</blockquote>
<h2 id="a-terminating-base-case">A terminating base case</h2>
<p>We need a terminating base case, because otherwise a recursive
function will continue forever.</p>
<p>We’ll start backwards (trying to find the case that terminates the
algorithm) and work our way from there.</p>
<p>Let’s say we have an empty array: well, that would look like this: If
the array is empty, then it makes sense that its sum is 0.</p>
<p>Let’s start writing some code to express that:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1"></a><span class="dt">int</span> sum_empty_arr<span class="op">(</span><span class="dt">int</span> arr<span class="op">*,</span> <span class="dt">size_t</span> len<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2"></a>  <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3"></a><span class="op">}</span></span>
<span id="cb1-4"><a href="#cb1-4"></a></span>
<span id="cb1-5"><a href="#cb1-5"></a><span class="dt">int</span> sum<span class="op">(</span><span class="dt">int</span> arr<span class="op">*,</span> <span class="dt">size_t</span> len<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-6"><a href="#cb1-6"></a>  <span class="cf">if</span> <span class="op">(</span>len <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-7"><a href="#cb1-7"></a>    <span class="cf">return</span> sum_empty_arr<span class="op">(</span>arr<span class="op">,</span> len<span class="op">);</span></span>
<span id="cb1-8"><a href="#cb1-8"></a>  <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb1-9"><a href="#cb1-9"></a>    <span class="co">// In the next section!</span></span>
<span id="cb1-10"><a href="#cb1-10"></a>  <span class="op">}</span></span>
<span id="cb1-11"><a href="#cb1-11"></a><span class="op">}</span></span></code></pre></div>
<p>And hey, that’s the only base case.</p>
<h2 id="continuing-the-recursion">Continuing the Recursion</h2>
<p>To continue the recursion, let’s continue thinking: if we have a one
item array, what do we do?</p>
<p>A one item array’s sum can be expressed like this:</p>
<p><code>arr[0] + 0</code>.</p>
<p>Let’s take <code>{1, 2}</code> as our array. Well, the sum of the
array <code>{1, 2}</code> can be expressed like this:</p>
<p><code>arr[0] + sum({2})</code></p>
<p>Similarly, if we have a 3 item array like <code>{1, 2, 3}</code>, the
sum of the array can be expressed like this:</p>
<p><code>arr[0] + sum({2, 3})</code></p>
<p>This formula works on arrays with any length.</p>
<p>Our key insight here is to take the first item of the array, and sum
it with the result of the sum of the rest of the items in the array.
We’ve found a way to continue the recursion.</p>
<p>Next, we’ll have to think about how to make progress towards the base
case.</p>
<h2 id="making-progress-towards-the-base-case">Making progress towards
the base case</h2>
<p>In our formula, we’ve found a way to continue the recursion. But are
we making progress towards the base case?</p>
<p>Our base case will terminate when it is provided an array with a
length of 0.</p>
<p>In every recursive call, we reduce the length of the array we provide
to <code>sum</code> by 1. Thus, as long as our array length is positive
(which we can safely assume), we’ll make progress towards the base case.
Nice! We won’t recurse forever.</p>
<h2 id="implementation">Implementation</h2>
<p>We can turn our idea into code like so (I’m doing a bit of pointer
arithmetic to move the pointer past the first item and decrementing the
length before calling <code>sum</code> again).</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1"></a><span class="dt">int</span> sum<span class="op">(</span><span class="dt">int</span> <span class="op">*</span>arr<span class="op">,</span> <span class="dt">size_t</span> len<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2"></a>    <span class="cf">if</span> <span class="op">(</span>len <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3"></a>        <span class="cf">return</span> sum_empty_arr<span class="op">(</span>arr<span class="op">,</span> len<span class="op">);</span></span>
<span id="cb2-4"><a href="#cb2-4"></a>    <span class="op">}</span>  <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb2-5"><a href="#cb2-5"></a>        <span class="dt">int</span> head <span class="op">=</span> arr<span class="op">[</span><span class="dv">0</span><span class="op">];</span></span>
<span id="cb2-6"><a href="#cb2-6"></a>        len<span class="op">--;</span> <span class="co">// decrement the length</span></span>
<span id="cb2-7"><a href="#cb2-7"></a>        arr<span class="op">++;</span> <span class="co">// move past the first item</span></span>
<span id="cb2-8"><a href="#cb2-8"></a>        <span class="cf">return</span> head <span class="op">+</span> sum<span class="op">(</span>arr<span class="op">,</span> len<span class="op">);</span></span>
<span id="cb2-9"><a href="#cb2-9"></a>    <span class="op">}</span></span>
<span id="cb2-10"><a href="#cb2-10"></a><span class="op">}</span></span></code></pre></div>
<p>And hey, if we run it:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2"></a>    <span class="dt">int</span> arr<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span><span class="dv">1</span><span class="op">,</span><span class="dv">2</span><span class="op">,</span><span class="dv">3</span><span class="op">,</span><span class="dv">4</span><span class="op">};</span></span>
<span id="cb3-3"><a href="#cb3-3"></a>    <span class="dt">int</span> total <span class="op">=</span> sum<span class="op">(</span>arr<span class="op">,</span> <span class="dv">4</span><span class="op">);</span></span>
<span id="cb3-4"><a href="#cb3-4"></a></span>
<span id="cb3-5"><a href="#cb3-5"></a>    printf<span class="op">(</span><span class="st">&quot;</span><span class="sc">%d\n</span><span class="st">&quot;</span><span class="op">,</span> total<span class="op">);</span> <span class="co">// 10</span></span>
<span id="cb3-6"><a href="#cb3-6"></a><span class="op">}</span></span></code></pre></div>
<p>And we get the correct result.</p>
<p>We can clean this code up a bit:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1"></a><span class="dt">int</span> sum<span class="op">(</span><span class="dt">int</span> <span class="op">*</span>arr<span class="op">,</span> <span class="dt">size_t</span> len<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2"></a>    <span class="cf">if</span> <span class="op">(</span>len <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3"></a>        <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb4-4"><a href="#cb4-4"></a>    <span class="op">}</span>  <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5"></a>        <span class="cf">return</span> arr<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">+</span> sum<span class="op">(++</span>arr<span class="op">,</span> <span class="op">--</span>len<span class="op">);</span></span>
<span id="cb4-6"><a href="#cb4-6"></a>    <span class="op">}</span></span>
<span id="cb4-7"><a href="#cb4-7"></a><span class="op">}</span></span></code></pre></div>
<p>Interestingly enough, even though python has a slicing operator, the
implementation is similar in length:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode numberSource py numberLines"><code class="sourceCode python"><span id="cb5-1"><a href="#cb5-1"></a><span class="kw">def</span> list_sum(arr):</span>
<span id="cb5-2"><a href="#cb5-2"></a>  <span class="cf">if</span> <span class="bu">len</span>(arr) <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb5-3"><a href="#cb5-3"></a>    <span class="cf">return</span> <span class="dv">0</span></span>
<span id="cb5-4"><a href="#cb5-4"></a>  <span class="cf">else</span>:</span>
<span id="cb5-5"><a href="#cb5-5"></a>    <span class="cf">return</span> arr[<span class="dv">0</span>] <span class="op">+</span> list_sum(arr[<span class="dv">1</span>:])</span></code></pre></div>
<p>Similarly, in a language like OCaml, where recursion is the idiomatic
way to express algorithms:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode numberSource ml numberLines"><code class="sourceCode ocaml"><span id="cb6-1"><a href="#cb6-1"></a><span class="kw">let</span> <span class="kw">rec</span> sum = <span class="kw">function</span></span>
<span id="cb6-2"><a href="#cb6-2"></a>  | [] -&gt; <span class="dv">0</span> <span class="co">(* if the array is empty, return 0 *)</span></span>
<span id="cb6-3"><a href="#cb6-3"></a>  | h::t -&gt; h + (sum t) <span class="co">(* otherwise, return the value of the head + sum of the rest of the elements. *)</span></span></code></pre></div>
<p>Let’s try another problem:</p>
<blockquote>
<p>Given a binary tree, calculate the sum of the values of all nodes in
the binary tree.</p>
</blockquote>
<p>Let’s go through the steps again.</p>
<h2 id="finding-a-base-case">Finding a base case</h2>
<p>Let’s ask ourselves what the possible cases are:</p>
<p>If there is no node, because the node is null, clearly it shouldn’t
count. Much like in the empty array case, let’s return 0.</p>
<p>If there is a node, let’s return its value.</p>
<p>Great, we’ve got all our base cases covered. Let’s express them
before we continue on:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb7-1"><a href="#cb7-1"></a><span class="dt">int</span> sum<span class="op">(</span>TreeNode <span class="op">*</span>node<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2"></a>  <span class="cf">if</span> <span class="op">(</span>node <span class="op">==</span> NULL<span class="op">)</span></span>
<span id="cb7-3"><a href="#cb7-3"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb7-4"><a href="#cb7-4"></a>  <span class="cf">else</span></span>
<span id="cb7-5"><a href="#cb7-5"></a>    <span class="cf">return</span> node<span class="op">-&gt;</span>val<span class="op">;</span></span>
<span id="cb7-6"><a href="#cb7-6"></a><span class="op">}</span></span></code></pre></div>
<p>But how do we continue the recursion?</p>
<h2 id="continuing-the-recursion-1">Continuing the Recursion</h2>
<p>To continue the recursion, we can apply the function we’ve created to
its left and right node. But how? Well, thinking back to the previous
problem, the sum of an array is the sum of the current value (the head)
+ the rest of the items in the array. Likewise, for a binary tree, we
need to find the sum of the left items and the sum of the right
items.</p>
<p>Since we know that a null node can’t point to anything, we can leave
that case be, and express the sum of the binary tree as its current
value + the sum of its left child + the sum of its right child.</p>
<p>Let’s do that:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb8-1"><a href="#cb8-1"></a><span class="dt">int</span> sum<span class="op">(</span>TreeNode <span class="op">*</span>node<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-2"><a href="#cb8-2"></a>  <span class="cf">if</span> <span class="op">(</span>node <span class="op">==</span> NULL<span class="op">)</span></span>
<span id="cb8-3"><a href="#cb8-3"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb8-4"><a href="#cb8-4"></a>  <span class="cf">else</span></span>
<span id="cb8-5"><a href="#cb8-5"></a>    <span class="cf">return</span> node<span class="op">-&gt;</span>val <span class="op">+</span> sum<span class="op">(</span>node<span class="op">-&gt;</span>left<span class="op">)</span> <span class="op">+</span> sum<span class="op">(</span>node<span class="op">-&gt;</span>right<span class="op">);</span></span>
<span id="cb8-6"><a href="#cb8-6"></a><span class="op">}</span></span></code></pre></div>
<h2 id="making-progress">Making Progress</h2>
<p>Are we making progress? We must be: for every node, we move onto its
child nodes. Child nodes (hopefully) eventually return null, in the case
of a finite binary tree (of course, we can’t calculate the sum of an
infinitely large binary tree).</p>
<p>We did it! We can take this same idea and apply it to linked lists
and graphs as well. That’ll be an exercise for the reader, but the idea
is very similar.</p>
<h2 id="appendix">Appendix</h2>
<p>Full code to sum of the nodes of a binary tree:</p>
<p>In C:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2"></a></span>
<span id="cb9-3"><a href="#cb9-3"></a><span class="kw">typedef</span> <span class="kw">struct</span> TreeNode <span class="op">{</span></span>
<span id="cb9-4"><a href="#cb9-4"></a>  <span class="dt">int</span> val<span class="op">;</span></span>
<span id="cb9-5"><a href="#cb9-5"></a>  <span class="kw">struct</span> TreeNode <span class="op">*</span>left<span class="op">;</span></span>
<span id="cb9-6"><a href="#cb9-6"></a>  <span class="kw">struct</span> TreeNode <span class="op">*</span>right<span class="op">;</span></span>
<span id="cb9-7"><a href="#cb9-7"></a><span class="op">}</span> TreeNode<span class="op">;</span></span>
<span id="cb9-8"><a href="#cb9-8"></a></span>
<span id="cb9-9"><a href="#cb9-9"></a><span class="dt">int</span> sum<span class="op">(</span>TreeNode <span class="op">*</span>node<span class="op">)</span> <span class="op">{</span></span>
<span id="cb9-10"><a href="#cb9-10"></a>  <span class="cf">if</span> <span class="op">(</span>node <span class="op">==</span> NULL<span class="op">)</span></span>
<span id="cb9-11"><a href="#cb9-11"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb9-12"><a href="#cb9-12"></a>  <span class="cf">else</span></span>
<span id="cb9-13"><a href="#cb9-13"></a>    <span class="cf">return</span> node<span class="op">-&gt;</span>val <span class="op">+</span> sum<span class="op">(</span>node<span class="op">-&gt;</span>left<span class="op">)</span> <span class="op">+</span> solve<span class="op">(</span>node<span class="op">-&gt;</span>right<span class="op">);</span></span>
<span id="cb9-14"><a href="#cb9-14"></a><span class="op">}</span></span></code></pre></div>
<p>In Java:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode numberSource java numberLines"><code class="sourceCode java"><span id="cb10-1"><a href="#cb10-1"></a><span class="kw">class</span> Solution <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2"></a>  <span class="kw">record</span> <span class="bu">TreeNode</span><span class="op">(</span><span class="dt">int</span> val<span class="op">,</span> <span class="bu">TreeNode</span> left<span class="op">,</span> <span class="bu">TreeNode</span> right<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb10-3"><a href="#cb10-3"></a></span>
<span id="cb10-4"><a href="#cb10-4"></a>  <span class="kw">public</span> <span class="dt">int</span> <span class="fu">sum</span><span class="op">(</span><span class="bu">TreeNode</span> node<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-5"><a href="#cb10-5"></a>    <span class="cf">if</span> <span class="op">(</span>node <span class="op">==</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-6"><a href="#cb10-6"></a>      <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb10-7"><a href="#cb10-7"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb10-8"><a href="#cb10-8"></a>      <span class="cf">return</span> node<span class="op">.</span><span class="fu">val</span> <span class="op">+</span> <span class="fu">sum</span><span class="op">(</span>node<span class="op">.</span><span class="fu">left</span><span class="op">)</span> <span class="op">+</span> <span class="fu">sum</span><span class="op">(</span>node<span class="op">.</span><span class="fu">right</span><span class="op">);</span></span>
<span id="cb10-9"><a href="#cb10-9"></a>    <span class="op">}</span></span>
<span id="cb10-10"><a href="#cb10-10"></a>  <span class="op">}</span></span>
<span id="cb10-11"><a href="#cb10-11"></a><span class="op">}</span></span></code></pre></div>
<p>In OCaml:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode numberSource ml numberLines"><code class="sourceCode ocaml"><span id="cb11-1"><a href="#cb11-1"></a><span class="kw">type</span> &#39;a tree =</span>
<span id="cb11-2"><a href="#cb11-2"></a>  | Node <span class="kw">of</span> &#39;a tree * &#39;a * &#39;a tree</span>
<span id="cb11-3"><a href="#cb11-3"></a>  | Leaf;;</span>
<span id="cb11-4"><a href="#cb11-4"></a></span>
<span id="cb11-5"><a href="#cb11-5"></a><span class="kw">let</span> <span class="kw">rec</span> fold_tree f a t =</span>
<span id="cb11-6"><a href="#cb11-6"></a>    <span class="kw">match</span> t <span class="kw">with</span></span>
<span id="cb11-7"><a href="#cb11-7"></a>      | Leaf -&gt; a</span>
<span id="cb11-8"><a href="#cb11-8"></a>      | Node (l, x, r) -&gt; f x (fold_tree f a l) (fold_tree f a r);;</span></code></pre></div>]]></description>
</item>
<item>
<title>Pack Enums in C</title>
<pubDate>Sat, 29 May 2021 04:16:07 +0000</pubDate>
<guid>https://blog/pack-enums-in-c.html</guid>
<description><![CDATA[<p>What’s the default size of enums in C? Well
it’s int. We can see that by using <code>sizeof</code> in an example
program:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb1-2"><a href="#cb1-2"></a></span>
<span id="cb1-3"><a href="#cb1-3"></a><span class="kw">typedef</span> <span class="kw">enum</span> Example <span class="op">{</span></span>
<span id="cb1-4"><a href="#cb1-4"></a>    One <span class="op">=</span> <span class="dv">1</span><span class="op">,</span></span>
<span id="cb1-5"><a href="#cb1-5"></a>    Two <span class="op">=</span> <span class="dv">2</span><span class="op">,</span></span>
<span id="cb1-6"><a href="#cb1-6"></a><span class="op">}</span> Example<span class="op">;</span></span>
<span id="cb1-7"><a href="#cb1-7"></a></span>
<span id="cb1-8"><a href="#cb1-8"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-9"><a href="#cb1-9"></a>    printf<span class="op">(</span><span class="st">&quot;The size of Example is: </span><span class="sc">%d\n</span><span class="st">&quot;</span><span class="op">,</span> <span class="kw">sizeof</span><span class="op">(</span>Example<span class="op">));</span></span>
<span id="cb1-10"><a href="#cb1-10"></a><span class="op">}</span></span></code></pre></div>
<p>Which prints out 4.</p>
<p>This is noted by the standard: enums should be able to hold
4-bytes.</p>
<p>But 4 bytes seems wasteful, especially in this case: if we have an
enum with two choices, we only need a bit to represent it.</p>
<p>In GCC and Clang, there’s support for <code>__attribute__</code>
modifiers. Let’s use the <code>((__packed__))</code> modifier to tell
the compiler to use the smallest type it can for our enum.</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb2-2"><a href="#cb2-2"></a></span>
<span id="cb2-3"><a href="#cb2-3"></a><span class="kw">typedef</span> <span class="kw">enum</span> Example <span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4"></a>    One <span class="op">=</span> <span class="dv">1</span><span class="op">,</span></span>
<span id="cb2-5"><a href="#cb2-5"></a>    Two <span class="op">=</span> <span class="dv">2</span><span class="op">,</span></span>
<span id="cb2-6"><a href="#cb2-6"></a><span class="op">}</span> __attribute__ <span class="op">((</span>__packed__<span class="op">))</span> Example<span class="op">;</span></span>
<span id="cb2-7"><a href="#cb2-7"></a></span>
<span id="cb2-8"><a href="#cb2-8"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-9"><a href="#cb2-9"></a>    printf<span class="op">(</span><span class="st">&quot;The size of Example is: </span><span class="sc">%d\n</span><span class="st">&quot;</span><span class="op">,</span> <span class="kw">sizeof</span><span class="op">(</span>Example<span class="op">));</span></span>
<span id="cb2-10"><a href="#cb2-10"></a><span class="op">}</span></span></code></pre></div>
<p>Which prints out 1. (our enum is now represented by an unsigned
char).</p>
<p>If you want to make enums more dense in memory, this is the way to
go.</p>]]></description>
</item>
<item>
<title>Unix Environment Variables</title>
<pubDate>Mon, 24 May 2021 22:58:40 +0000</pubDate>
<guid>https://blog/unix-environment-variables.html</guid>
<description><![CDATA[<p>Let’s talk about some popular unix environment
variables:</p>
<ul>
<li><code>$USER</code> - The current user</li>
<li><code>$PAGER</code> - the program that accepts page by page input.
<code>less</code> and <code>more</code> are good examples.</li>
<li><code>$VISUAL</code> - A full screen editor (like <code>vi</code>,
<code>emacs</code>, and <code>nano</code>).</li>
<li><code>$EDITOR</code> - A line by line editor (<code>ed</code> or
<code>ex</code> work).</li>
<li><code>$PWD</code> - the current working directory</li>
<li><code>$HOME</code> - the home directory</li>
<li><code>$LANG</code> - the language you use, with an optional
encoding.</li>
<li><code>$MANPATH</code> - the list of directories to search for manual
pages.</li>
<li><code>$MAIL</code> - where mail goes</li>
<li><code>$SHELL</code> - path to shell binary you use
(e.g. <code>/bin/bash</code>, <code>/bin/ksh</code>,
<code>/bin/sh</code>, <code>/bin/zsh</code>)</li>
</ul>
<p>The most important one is probably <code>$PATH</code>, which is where
the OS looks for binaries. It goes from the beginning to the end,
executing the first binary it finds.</p>
<p>Let’s say my <code>$PATH</code> is like this:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode numberSource bash numberLines"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1"></a><span class="ex">/usr/local/bin:/usr/bin</span></span></code></pre></div>
<p>Which instructs the OS to look into <code>/usr/local/bin</code> to
find a valid binary. Then <code>/usr/bin</code>.</p>
<p>The <code>/bin</code> directory contains binaries for sysadmins and
users, but are required when there’s no filesystem in use.</p>
<p>The <code>/usr/bin</code> and was meant to contain executable
programs that were part of the OS</p>
<p>and <code>/usr/local/bin</code> is for software that the user
installs.</p>
<p>There directories where superuser binaries should be located which
follow the same scheme:</p>
<ul>
<li><code>/sbin</code></li>
<li><code>/usr/sbin</code></li>
<li><code>/usr/local/sbin</code></li>
</ul>
<p>As well, <code>/usr/share/bin</code> is for binaries used for web
servers and clients.</p>
<p>If you find that a command doesn’t work, double-check to make sure
that your <code>$PATH</code> is set up properly to find the correct
binary.</p>]]></description>
</item>
<item>
<title>The Central Limit Theorem</title>
<pubDate>Wed, 19 May 2021 23:55:46 +0000</pubDate>
<guid>https://blog/the-central-limit-theorem.html</guid>
<description><![CDATA[<p>The central limit theory (CLT) states that when
<strong>independent</strong> random variables are added, their properly
normalized sum tends toward a normal distribution (a bell curve) even if
the original variables themselves are not normally distributed. ~
Wikipedia</p>
<p>One constraint is that we must have finite variance, as that lowers
the amount of outliers we see.</p>
<p>Let’s roll a dice 1000 times and see what that gets us:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode numberSource python numberLines"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1"></a><span class="im">from</span> collections <span class="im">import</span> Counter</span>
<span id="cb1-2"><a href="#cb1-2"></a><span class="im">import</span> random</span>
<span id="cb1-3"><a href="#cb1-3"></a></span>
<span id="cb1-4"><a href="#cb1-4"></a><span class="kw">def</span> r():</span>
<span id="cb1-5"><a href="#cb1-5"></a>    <span class="cf">return</span> random.randrange(<span class="dv">1</span>, <span class="dv">7</span>)</span>
<span id="cb1-6"><a href="#cb1-6"></a></span>
<span id="cb1-7"><a href="#cb1-7"></a></span>
<span id="cb1-8"><a href="#cb1-8"></a>rolls <span class="op">=</span> Counter()</span>
<span id="cb1-9"><a href="#cb1-9"></a></span>
<span id="cb1-10"><a href="#cb1-10"></a><span class="cf">for</span> _ <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">1000</span>):</span>
<span id="cb1-11"><a href="#cb1-11"></a>    rolls[r()] <span class="op">+=</span> <span class="dv">1</span></span>
<span id="cb1-12"><a href="#cb1-12"></a></span>
<span id="cb1-13"><a href="#cb1-13"></a>sorted_dict <span class="op">=</span> {k: rolls[k] <span class="cf">for</span> k <span class="kw">in</span> <span class="bu">sorted</span>(rolls)}</span></code></pre></div>
<p>Running it I get this:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1"></a><span class="ex">{1:</span> 156, 2: 168, 3: 192, 4: 143, 5: 170, 6: 171}</span></code></pre></div>
<ul>
<li>1 was rolled 156 times</li>
<li>2 was rolled 168 times</li>
<li>3 was rolled 192 times</li>
<li>4 was rolled 143 times</li>
<li>5 was rolled 170 times</li>
<li>6 was rolled 171 times</li>
</ul>
<figure>
<img src="../assets/output.png" alt="Output" />
<figcaption aria-hidden="true">Output</figcaption>
</figure>
<p>You’ll see that there’s some variance, but we get a good enough
result.</p>
<p>To test the central limit theorem, let’s try to roll two dice at the
same time 1000 times and plot it.</p>
<p>Change this line to this:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode numberSource python numberLines"><code class="sourceCode python"><span id="cb3-1"><a href="#cb3-1"></a><span class="cf">for</span> _ <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">1000</span>):</span>
<span id="cb3-2"><a href="#cb3-2"></a>    rolls[r() <span class="op">+</span> r()] <span class="op">+=</span> <span class="dv">1</span></span></code></pre></div>
<p>Here were the rolls:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1"></a><span class="ex">{2:</span> 22, 3: 59, 4: 81, 5: 110, 6: 149, 7: 174, 8: 144, 9: 101, 10: 77, 11: 53, 12: 30}</span></code></pre></div>
<p>And here’s the distribution:</p>
<figure>
<img src="../assets/two-dice.png" alt="Two Dice Rolls" />
<figcaption aria-hidden="true">Two Dice Rolls</figcaption>
</figure>
<p>You’ll notice it’s starting to converge on 6 and 7, but 2 and 12 were
fairly unlikely.</p>
<p>We’re starting to get a normal distribution!</p>
<p>Let’s do 5 dice rolls.</p>
<p>Change the line below:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode numberSource python numberLines"><code class="sourceCode python"><span id="cb5-1"><a href="#cb5-1"></a><span class="cf">for</span> _ <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">1000</span>):</span>
<span id="cb5-2"><a href="#cb5-2"></a>    rolls[r() <span class="op">+</span> r() <span class="op">+</span> r() <span class="op">+</span> r() <span class="op">+</span> r()] <span class="op">+=</span> <span class="dv">1</span></span></code></pre></div>
<p>Here’s the outcome:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1"></a><span class="ex">{7:</span> 2, 8: 8, 9: 8, 10: 14, 11: 33, 12: 35, 13: 54, 14: 72, 15: 61, 16: 85, 17: 94, 18: 93, 19: 108, 20: 88, 21: 82, 22: 65, 23: 37, 24: 22, 25: 17, 26: 11, 27: 8, 28: 2, 29: 1}</span></code></pre></div>
<p>And the five dice rolls.</p>
<figure>
<img src="../assets/five-dice.png" alt="Five Dice Rolls" />
<figcaption aria-hidden="true">Five Dice Rolls</figcaption>
</figure>
<p>We get closer to a normal distribution.</p>
<p>Let’s do it a million times:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode numberSource python numberLines"><code class="sourceCode python"><span id="cb7-1"><a href="#cb7-1"></a><span class="cf">for</span> _ <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">1000000</span>):</span>
<span id="cb7-2"><a href="#cb7-2"></a>    rolls[r() <span class="op">+</span> r() <span class="op">+</span> r() <span class="op">+</span> r() <span class="op">+</span> r()] <span class="op">+=</span> <span class="dv">1</span></span></code></pre></div>
<p>Here’s the outcome:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1"></a><span class="ex">{5:</span> 147, 6: 600, 7: 1890, 8: 4469, 9: 9147, 10: 16052, 11: 26310, 12: 39423, 13: 54070, 14: 69536, 15: 83228, 16: 94310, 17: 99997, 18: 100488, 19: 94484, 20: 83745, 21: 69777, 22: 53880, 23: 39506, 24: 26489, 25: 16144, 26: 9076, 27: 4547, 28: 1900, 29: 649, 30: 136}</span></code></pre></div>
<p>And hey look, that looks like a normal distribution to me!</p>
<figure>
<img src="../assets/million-rolls.png" alt="Million rolls" />
<figcaption aria-hidden="true">Million rolls</figcaption>
</figure>]]></description>
</item>
<item>
<title>File Io</title>
<pubDate>Wed, 19 May 2021 20:41:02 +0000</pubDate>
<guid>https://blog/file-io.html</guid>
<description><![CDATA[<p>File I/O is slow: but how slow is it really?
Are there any ways we can make it faster? Let’s find out!</p>
<p>First let’s start out by writing the character <code>a</code> to a
file in python:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode numberSource python numberLines"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1"></a><span class="im">import</span> timeit</span>
<span id="cb1-2"><a href="#cb1-2"></a></span>
<span id="cb1-3"><a href="#cb1-3"></a></span>
<span id="cb1-4"><a href="#cb1-4"></a><span class="kw">def</span> test():</span>
<span id="cb1-5"><a href="#cb1-5"></a>    <span class="cf">with</span> <span class="bu">open</span>(<span class="ss">f&#39;output.txt&#39;</span>, <span class="st">&#39;w+&#39;</span>) <span class="im">as</span> f:</span>
<span id="cb1-6"><a href="#cb1-6"></a>        f.write(<span class="st">&#39;a&#39;</span>)</span>
<span id="cb1-7"><a href="#cb1-7"></a></span>
<span id="cb1-8"><a href="#cb1-8"></a></span>
<span id="cb1-9"><a href="#cb1-9"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&quot;__main__&quot;</span>:</span>
<span id="cb1-10"><a href="#cb1-10"></a>    <span class="bu">print</span>(</span>
<span id="cb1-11"><a href="#cb1-11"></a>        <span class="ss">f&#39;This took </span><span class="sc">{</span>timeit<span class="sc">.</span>timeit(<span class="st">&quot;test()&quot;</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">locals</span>(), number<span class="op">=</span><span class="dv">1</span>)<span class="sc">}</span><span class="ss"> seconds.&#39;</span>)</span></code></pre></div>
<p>On my machine, this prints out:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1"></a><span class="ex">This</span> took 0.0002999180000000032 seconds.</span></code></pre></div>
<p>Makes sense. Since it’s hard to look at such small numbers, let’s
bump our number of repetitions up to <code>10000</code>.</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode numberSource python numberLines"><code class="sourceCode python"><span id="cb3-1"><a href="#cb3-1"></a><span class="im">import</span> timeit</span>
<span id="cb3-2"><a href="#cb3-2"></a></span>
<span id="cb3-3"><a href="#cb3-3"></a></span>
<span id="cb3-4"><a href="#cb3-4"></a><span class="kw">def</span> test():</span>
<span id="cb3-5"><a href="#cb3-5"></a>    <span class="cf">with</span> <span class="bu">open</span>(<span class="ss">f&#39;output.txt&#39;</span>, <span class="st">&#39;w+&#39;</span>) <span class="im">as</span> f:</span>
<span id="cb3-6"><a href="#cb3-6"></a>        f.write(<span class="st">&#39;a&#39;</span>)</span>
<span id="cb3-7"><a href="#cb3-7"></a></span>
<span id="cb3-8"><a href="#cb3-8"></a></span>
<span id="cb3-9"><a href="#cb3-9"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&quot;__main__&quot;</span>:</span>
<span id="cb3-10"><a href="#cb3-10"></a>    <span class="bu">print</span>(</span>
<span id="cb3-11"><a href="#cb3-11"></a>        <span class="ss">f&#39;This took </span><span class="sc">{</span>timeit<span class="sc">.</span>timeit(<span class="st">&quot;test()&quot;</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">locals</span>(), number<span class="op">=</span><span class="dv">10000</span>)<span class="sc">}</span><span class="ss"> seconds.&#39;</span>)</span></code></pre></div>
<p>On my machine, this prints out:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1"></a><span class="ex">This</span> took 4.582478715000001 seconds.</span></code></pre></div>
<p>Let’s try something similar but in memory. Let’s add the string
<code>a</code> to an empty string and return it:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode numberSource python numberLines"><code class="sourceCode python"><span id="cb5-1"><a href="#cb5-1"></a><span class="im">import</span> timeit</span>
<span id="cb5-2"><a href="#cb5-2"></a></span>
<span id="cb5-3"><a href="#cb5-3"></a></span>
<span id="cb5-4"><a href="#cb5-4"></a><span class="kw">def</span> test():</span>
<span id="cb5-5"><a href="#cb5-5"></a>    s <span class="op">=</span> <span class="st">&#39;&#39;</span></span>
<span id="cb5-6"><a href="#cb5-6"></a>    s <span class="op">+=</span> <span class="st">&#39;a&#39;</span></span>
<span id="cb5-7"><a href="#cb5-7"></a>    <span class="cf">return</span> s</span>
<span id="cb5-8"><a href="#cb5-8"></a></span>
<span id="cb5-9"><a href="#cb5-9"></a></span>
<span id="cb5-10"><a href="#cb5-10"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&quot;__main__&quot;</span>:</span>
<span id="cb5-11"><a href="#cb5-11"></a>    <span class="bu">print</span>(</span>
<span id="cb5-12"><a href="#cb5-12"></a>        <span class="ss">f&#39;This took </span><span class="sc">{</span>timeit<span class="sc">.</span>timeit(<span class="st">&quot;test()&quot;</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">locals</span>(), number<span class="op">=</span><span class="dv">10000</span>)<span class="sc">}</span><span class="ss"> seconds.&#39;</span>)</span></code></pre></div>
<p>On my machine, this prints out:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1"></a><span class="ex">This</span> took 0.0009243260000000031 seconds.</span></code></pre></div>
<p>Doing some math, writing to a file 10000 times is 5000x slower than
writing to a string 10000 times in memory.</p>
<p>So our intuition (and our Operating Systems textbooks) are correct.
Let’s dig deeper to see if we can find anything else.</p>
<h2 id="intuition">Intuition</h2>
<p>Since all we’re doing is opening a file, writing to it, closing the
file 10000 times, maybe there’s some way to speed up this operation.</p>
<p>Let’s build a mental model for how python writes to a file:</p>
<ol type="1">
<li>Open <code>output.txt</code>.</li>
<li>Write the character <code>a</code> to <code>output.txt</code>.</li>
<li>Close the file.</li>
</ol>
<h2 id="suggestion-1">Suggestion 1:</h2>
<p>Since we’re opening and closing the same file, what if we had some
abstraction that represented the file? Let’s say we had some integer
that would represent the file (a file descriptor) and we kept track of
its state inside of our program. Whenever we need to save our changes to
disk, we notify the OS.</p>
<p>So instead of doing:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode numberSource python numberLines"><code class="sourceCode python"><span id="cb7-1"><a href="#cb7-1"></a>repeat <span class="dv">10000</span> times:</span>
<span id="cb7-2"><a href="#cb7-2"></a>  <span class="bu">open</span> `output.txt`</span>
<span id="cb7-3"><a href="#cb7-3"></a>  clear the contents of `output.txt`</span>
<span id="cb7-4"><a href="#cb7-4"></a>  write `a` to output.txt</span>
<span id="cb7-5"><a href="#cb7-5"></a>  close `output.txt`</span></code></pre></div>
<p>Which would require us to open the same file 10000 times:</p>
<p>We try this:</p>
<pre><code>file_contents = {}
file_contents[&#39;output.txt&#39;] = &#39;a&#39;
open file
clear the contents of `output.txt`
write file_contents[&#39;output.txt&#39;] to `output.txt`
close `output.txt`</code></pre>
<p>Which would only require 1 call to the OS to open the file, 1 call to
the OS to write to the file, and 1 call to the OS to close the file.</p>
<p>Python does this to some degree out of the box: the interpreter keeps
a dictionary of file_descriptor -&gt; changes and when it deems
necessary, it gives the file changes to the OS.</p>
<p>To make python commit its buffer to the OS, use the
<code>flush()</code> function.</p>
<h2 id="suggestion-2">Suggestion 2:</h2>
<p>What if the OS had a cache too? Since there are many processes trying
to access the OS’ resources, the OS has a chance to reconcile file
writes and batch them in a way that is more efficient.</p>
<p>Let’s say we ran the same python program twice at exactly the same
time. If we only employed caching at the python level, we’d have to
write to the same file twice with the character <code>a</code>. Of
course, the OS can reconcile those changes and make it so there’s only 1
open-write-close cycle required.</p>
<p>It turns out both of these suggestions are implemented.</p>
<p>To force the OS to propagate a change, you can use the
<code>os.fsync(f.fileno())</code> function. When called, python asks the
OS persist the changes in file descriptor <code>f</code> to
disk.</p>]]></description>
</item>
<item>
<title>Const Correctness</title>
<pubDate>Mon, 17 May 2021 23:32:39 +0000</pubDate>
<guid>https://blog/const-correctness.html</guid>
<description><![CDATA[<p>Const correctness means marking all items you
can <code>const</code> to prevent unwanted mutation. Let’s say you want
to grab a few options from a <code>settings</code> map that you’ve
created.</p>
<p>Let’s say you want the time to live value and the created at from a
map.</p>
<p>Does this compile?</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode numberSource cpp numberLines"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1"></a><span class="dt">void</span> setTimeToLive<span class="op">(</span><span class="dt">int</span> ttl<span class="op">)</span> <span class="op">{</span><span class="co">/* implementation here */</span><span class="op">}</span></span>
<span id="cb1-2"><a href="#cb1-2"></a><span class="dt">void</span> setCreatedAt<span class="op">(</span><span class="dt">int</span> createdAt<span class="op">)</span> <span class="op">{</span><span class="co">/* implementation here */</span><span class="op">}</span></span>
<span id="cb1-3"><a href="#cb1-3"></a></span>
<span id="cb1-4"><a href="#cb1-4"></a><span class="dt">void</span> getOptions<span class="op">(</span><span class="at">const</span> <span class="bu">std::</span>map<span class="op">&lt;</span><span class="at">const</span> <span class="dt">char</span><span class="op">*,</span> <span class="dt">int</span><span class="op">&gt;</span> <span class="op">&amp;</span>m<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5"></a>  <span class="at">const</span> <span class="kw">auto</span> ttl <span class="op">=</span> m<span class="op">[</span><span class="st">&quot;ttl&quot;</span><span class="op">];</span></span>
<span id="cb1-6"><a href="#cb1-6"></a>  <span class="at">const</span> <span class="kw">auto</span> createdAt <span class="op">=</span> m<span class="op">[</span><span class="st">&quot;createdAt&quot;</span><span class="op">];</span></span>
<span id="cb1-7"><a href="#cb1-7"></a>  setTimeToLive<span class="op">(</span>ttl<span class="op">);</span></span>
<span id="cb1-8"><a href="#cb1-8"></a>  setCreatedAt<span class="op">(</span>createdAt<span class="op">);</span></span>
<span id="cb1-9"><a href="#cb1-9"></a><span class="op">}</span></span></code></pre></div>
<p>Nope: since <code>map[]</code> will insert in the case that it
doesn’t find a matching key, this doesn’t compile. We can’t insert into
a map marked const.</p>
<p>Let’s say we didn’t mark the map as <code>const</code>:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode numberSource cpp numberLines"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1"></a><span class="dt">void</span> setTimeToLive<span class="op">(</span><span class="dt">int</span> ttl<span class="op">)</span> <span class="op">{</span><span class="co">/* implementation here */</span><span class="op">}</span></span>
<span id="cb2-2"><a href="#cb2-2"></a><span class="dt">void</span> setCreatedAt<span class="op">(</span><span class="dt">int</span> createdAt<span class="op">)</span> <span class="op">{</span><span class="co">/* implementation here */</span><span class="op">}</span></span>
<span id="cb2-3"><a href="#cb2-3"></a></span>
<span id="cb2-4"><a href="#cb2-4"></a><span class="dt">void</span> getOptions<span class="op">(</span><span class="bu">std::</span>map<span class="op">&lt;</span><span class="at">const</span> <span class="dt">char</span><span class="op">*,</span> <span class="dt">int</span><span class="op">&gt;</span> <span class="op">&amp;</span>m<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb2-5"><a href="#cb2-5"></a>  <span class="at">const</span> <span class="kw">auto</span> ttl <span class="op">=</span> m<span class="op">[</span><span class="st">&quot;tttl&quot;</span><span class="op">];</span> <span class="co">// oops, typo</span></span>
<span id="cb2-6"><a href="#cb2-6"></a>  <span class="at">const</span> <span class="kw">auto</span> createdAt <span class="op">=</span> m<span class="op">[</span><span class="st">&quot;createdAt&quot;</span><span class="op">];</span></span>
<span id="cb2-7"><a href="#cb2-7"></a>  setTimeToLive<span class="op">(</span>ttl<span class="op">);</span></span>
<span id="cb2-8"><a href="#cb2-8"></a>  setCreatedAt<span class="op">(</span>createdAt<span class="op">);</span></span>
<span id="cb2-9"><a href="#cb2-9"></a><span class="op">}</span></span></code></pre></div>
<p>This compiles now, but oh no, what’s the value of ttl?
<code>0</code>. When we access a map’s key that doesn’t exist, we get
some default value. In our case, a value of 0.</p>
<p>So we’re at a crossroads. We want our code to compile, be correct,
and still allow the map to be <code>const</code>.</p>
<p>Let’s let that happen:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode numberSource cpp numberLines"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1"></a><span class="dt">void</span> setTimeToLive<span class="op">(</span><span class="dt">int</span> ttl<span class="op">)</span> <span class="op">{</span><span class="co">/* implementation here */</span><span class="op">}</span></span>
<span id="cb3-2"><a href="#cb3-2"></a><span class="dt">void</span> setCreatedAt<span class="op">(</span><span class="dt">int</span> createdAt<span class="op">)</span> <span class="op">{</span><span class="co">/* implementation here */</span><span class="op">}</span></span>
<span id="cb3-3"><a href="#cb3-3"></a></span>
<span id="cb3-4"><a href="#cb3-4"></a><span class="dt">void</span> getOptions<span class="op">(</span><span class="at">const</span> <span class="bu">std::</span>map<span class="op">&lt;</span><span class="at">const</span> <span class="dt">char</span><span class="op">*,</span> <span class="dt">int</span><span class="op">&gt;</span> <span class="op">&amp;</span>m<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-5"><a href="#cb3-5"></a>  <span class="at">const</span> <span class="kw">auto</span> ttl <span class="op">=</span> m<span class="op">.</span>at<span class="op">(</span><span class="st">&quot;tttl&quot;</span><span class="op">);</span> <span class="co">// oops, typo</span></span>
<span id="cb3-6"><a href="#cb3-6"></a>  <span class="at">const</span> <span class="kw">auto</span> createdAt <span class="op">=</span> m<span class="op">.</span>at<span class="op">(</span><span class="st">&quot;createdAt&quot;</span><span class="op">);</span></span>
<span id="cb3-7"><a href="#cb3-7"></a>  setTimeToLive<span class="op">(</span>ttl<span class="op">);</span></span>
<span id="cb3-8"><a href="#cb3-8"></a>  setCreatedAt<span class="op">(</span>createdAt<span class="op">);</span></span>
<span id="cb3-9"><a href="#cb3-9"></a><span class="op">}</span></span></code></pre></div>
<p>We replace <code>map::[]</code> with <code>map::at</code>.
<code>map::at</code> does a checked get in the map. If it doesn’t find
the key, it throws an exception.</p>
<p>We remove our <code>noexcept</code> from the function because this
function can throw and we move on with our lives.</p>
<p>Const correctness saves lives.</p>]]></description>
</item>
<item>
<title>Virtual Functions</title>
<pubDate>Mon, 17 May 2021 01:28:00 +0000</pubDate>
<guid>https://blog/virtual-functions.html</guid>
<description><![CDATA[<p>While learning Java, I came across this line of
code:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode numberSource java numberLines"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1"></a><span class="bu">List</span><span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;</span> array <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayList</span><span class="op">();</span></span></code></pre></div>
<p>As someone who knows C++, this is somewhat confusing –
<code>List</code> is an interface that <code>ArrayList</code>
implements. But if we treat <code>ArrayList</code> as a list, then when
we call <code>List.add()</code> we must use dynamic dispatch to find the
right implementation, since the implementation of <code>add</code> isn’t
on the list interface.</p>
<p>That involves a <code>virtual</code> function lookup.</p>
<p>In Java, most function calls are <code>virtual</code>, unless a
method is declared as <code>final</code> (which means it cannot be
overriden).</p>
<p>By doing this, we get an advantage – if we decide to change our
<code>array</code> variable from an <code>ArrayList</code> to another
<code>List</code> interface conforming type, we can do so without
breaking any code.</p>
<p>In exchange, we cannot use any <code>ArrayList</code> specific
methods without casting to <code>ArrayList</code>, which nullifies this
benefit.</p>
<p>We have information that both ArrayList and LinkedList implement the
List interface, so we can treat them as such in a collection.</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode numberSource java numberLines"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1"></a><span class="bu">ArrayList</span><span class="op">&lt;</span><span class="bu">List</span><span class="op">&gt;</span> lists <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayList</span><span class="op">&lt;</span><span class="bu">List</span><span class="op">&gt;();</span></span>
<span id="cb2-2"><a href="#cb2-2"></a>lists<span class="op">.</span><span class="fu">add</span><span class="op">(</span><span class="kw">new</span> <span class="bu">ArrayList</span><span class="op">());</span></span>
<span id="cb2-3"><a href="#cb2-3"></a>lists<span class="op">.</span><span class="fu">add</span><span class="op">(</span><span class="kw">new</span> <span class="bu">LinkedList</span><span class="op">());</span></span>
<span id="cb2-4"><a href="#cb2-4"></a></span>
<span id="cb2-5"><a href="#cb2-5"></a><span class="cf">for</span> <span class="op">(</span><span class="bu">List</span><span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;</span> l <span class="op">:</span> lists<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6"></a>    l<span class="op">.</span><span class="fu">add</span><span class="op">(</span><span class="dv">10</span><span class="op">);</span> <span class="co">// defer to each lists&#39; implementation for add</span></span>
<span id="cb2-7"><a href="#cb2-7"></a><span class="op">}</span></span></code></pre></div>
<p>Since we know that Java uses virtual functions for interface
implementations, everything works as expected. <code>l.add(10)</code>
defers to the implementation of <code>ArrayList</code> and
<code>LinkedList</code>, and each list is added a <code>10</code>.</p>
<p>A full example of virtual functions might look something like
this:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode numberSource java numberLines"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1"></a><span class="kw">public</span> <span class="kw">class</span> Animal <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2"></a>  <span class="dt">void</span> <span class="fu">move</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">printf</span><span class="op">(</span><span class="st">&quot;walk </span><span class="sc">%s\n</span><span class="st">&quot;</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">name</span><span class="op">());</span></span>
<span id="cb3-4"><a href="#cb3-4"></a>  <span class="op">}</span></span>
<span id="cb3-5"><a href="#cb3-5"></a></span>
<span id="cb3-6"><a href="#cb3-6"></a>  <span class="bu">String</span> <span class="fu">name</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-7"><a href="#cb3-7"></a>    <span class="cf">return</span> <span class="st">&quot;Animal&quot;</span><span class="op">;</span></span>
<span id="cb3-8"><a href="#cb3-8"></a>  <span class="op">}</span></span>
<span id="cb3-9"><a href="#cb3-9"></a></span>
<span id="cb3-10"><a href="#cb3-10"></a>  <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-11"><a href="#cb3-11"></a>    Animal animals<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span><span class="kw">new</span> <span class="fu">Animal</span><span class="op">(),</span> <span class="kw">new</span> <span class="fu">Bird</span><span class="op">(),</span> <span class="kw">new</span> <span class="fu">Elephant</span><span class="op">()};</span></span>
<span id="cb3-12"><a href="#cb3-12"></a></span>
<span id="cb3-13"><a href="#cb3-13"></a>    <span class="cf">for</span> <span class="op">(</span>Animal animal <span class="op">:</span> animals<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-14"><a href="#cb3-14"></a>      animal<span class="op">.</span><span class="fu">move</span><span class="op">();</span></span>
<span id="cb3-15"><a href="#cb3-15"></a>    <span class="op">}</span></span>
<span id="cb3-16"><a href="#cb3-16"></a>  <span class="op">}</span></span>
<span id="cb3-17"><a href="#cb3-17"></a><span class="op">}</span></span>
<span id="cb3-18"><a href="#cb3-18"></a></span>
<span id="cb3-19"><a href="#cb3-19"></a><span class="kw">class</span> Bird <span class="kw">extends</span> Animal <span class="op">{</span></span>
<span id="cb3-20"><a href="#cb3-20"></a>  <span class="at">@Override</span></span>
<span id="cb3-21"><a href="#cb3-21"></a>  <span class="dt">void</span> <span class="fu">move</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-22"><a href="#cb3-22"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">printf</span><span class="op">(</span><span class="st">&quot;fly </span><span class="sc">%s\n</span><span class="st">&quot;</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">name</span><span class="op">());</span></span>
<span id="cb3-23"><a href="#cb3-23"></a>  <span class="op">}</span></span>
<span id="cb3-24"><a href="#cb3-24"></a></span>
<span id="cb3-25"><a href="#cb3-25"></a>  <span class="at">@Override</span></span>
<span id="cb3-26"><a href="#cb3-26"></a>  <span class="bu">String</span> <span class="fu">name</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-27"><a href="#cb3-27"></a>    <span class="cf">return</span> <span class="st">&quot;Bird&quot;</span><span class="op">;</span></span>
<span id="cb3-28"><a href="#cb3-28"></a>  <span class="op">}</span></span>
<span id="cb3-29"><a href="#cb3-29"></a><span class="op">}</span></span>
<span id="cb3-30"><a href="#cb3-30"></a></span>
<span id="cb3-31"><a href="#cb3-31"></a><span class="kw">class</span> Elephant <span class="kw">extends</span> Animal <span class="op">{</span></span>
<span id="cb3-32"><a href="#cb3-32"></a>  <span class="at">@Override</span></span>
<span id="cb3-33"><a href="#cb3-33"></a>  <span class="bu">String</span> <span class="fu">name</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-34"><a href="#cb3-34"></a>    <span class="cf">return</span> <span class="st">&quot;Elephant&quot;</span><span class="op">;</span></span>
<span id="cb3-35"><a href="#cb3-35"></a>  <span class="op">}</span></span>
<span id="cb3-36"><a href="#cb3-36"></a><span class="op">}</span></span></code></pre></div>
<p>Running this prints this out:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1"></a><span class="ex">walk</span> Animal</span>
<span id="cb4-2"><a href="#cb4-2"></a><span class="ex">fly</span> Bird</span>
<span id="cb4-3"><a href="#cb4-3"></a><span class="ex">walk</span> Elephant</span></code></pre></div>
<p>Here we create a base class, <code>Animal</code>, which has two
methods, <code>name</code> and <code>move</code>. This class is
instantiable because it has default implementations for both methods.
The Bird class overrides the move method, since it flies instead of
walks, and the Elephant only overrides the name. When we collect them
into an array and call the <code>move()</code> method on each animal as
an animal, Java does the virtual function lookup and calls the correct
overriden method as we expect.</p>
<p>It turns out that not every language does this, mainly because there
is a runtime cost in dynamic dispatch.</p>
<p>In C++, you must designate a function as <code>virtual</code> which
labels a function as overridable by an inherited class.</p>
<p>A roughly word for word translation of the above java program would
look like this:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode numberSource cpp numberLines"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb5-2"><a href="#cb5-2"></a></span>
<span id="cb5-3"><a href="#cb5-3"></a><span class="kw">struct</span> Animal <span class="op">{</span></span>
<span id="cb5-4"><a href="#cb5-4"></a>  <span class="kw">virtual</span> <span class="at">const</span> <span class="dt">char</span> <span class="op">*</span>name<span class="op">()</span> <span class="at">const</span> <span class="op">{</span> <span class="cf">return</span> <span class="st">&quot;Animal&quot;</span><span class="op">;</span> <span class="op">}</span></span>
<span id="cb5-5"><a href="#cb5-5"></a>  <span class="kw">virtual</span> <span class="dt">void</span> move<span class="op">()</span> <span class="at">const</span> <span class="op">{</span> printf<span class="op">(</span><span class="st">&quot;walk </span><span class="sc">%s\n</span><span class="st">&quot;</span><span class="op">,</span> name<span class="op">());</span> <span class="op">}</span></span>
<span id="cb5-6"><a href="#cb5-6"></a>  <span class="kw">virtual</span> <span class="op">~</span>Animal<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb5-7"><a href="#cb5-7"></a><span class="op">};</span></span>
<span id="cb5-8"><a href="#cb5-8"></a></span>
<span id="cb5-9"><a href="#cb5-9"></a><span class="kw">struct</span> Bird <span class="op">:</span> <span class="kw">public</span> Animal <span class="op">{</span></span>
<span id="cb5-10"><a href="#cb5-10"></a>  <span class="kw">virtual</span> <span class="dt">void</span> move<span class="op">()</span> <span class="at">const</span> <span class="kw">override</span> <span class="op">{</span> printf<span class="op">(</span><span class="st">&quot;fly </span><span class="sc">%s\n</span><span class="st">&quot;</span><span class="op">,</span> name<span class="op">());</span> <span class="op">}</span></span>
<span id="cb5-11"><a href="#cb5-11"></a>  <span class="kw">virtual</span> <span class="at">const</span> <span class="dt">char</span> <span class="op">*</span>name<span class="op">()</span> <span class="at">const</span> <span class="kw">override</span> <span class="op">{</span> <span class="cf">return</span> <span class="st">&quot;Bird&quot;</span><span class="op">;</span> <span class="op">}</span></span>
<span id="cb5-12"><a href="#cb5-12"></a><span class="op">};</span></span>
<span id="cb5-13"><a href="#cb5-13"></a></span>
<span id="cb5-14"><a href="#cb5-14"></a><span class="kw">struct</span> Elephant <span class="op">:</span> <span class="kw">public</span> Animal <span class="op">{</span></span>
<span id="cb5-15"><a href="#cb5-15"></a>  <span class="kw">virtual</span> <span class="at">const</span> <span class="dt">char</span> <span class="op">*</span>name<span class="op">()</span> <span class="at">const</span> <span class="kw">override</span> <span class="op">{</span> <span class="cf">return</span> <span class="st">&quot;Elephant&quot;</span><span class="op">;</span> <span class="op">}</span></span>
<span id="cb5-16"><a href="#cb5-16"></a><span class="op">};</span></span>
<span id="cb5-17"><a href="#cb5-17"></a></span>
<span id="cb5-18"><a href="#cb5-18"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-19"><a href="#cb5-19"></a>  <span class="at">const</span> Animal <span class="op">*</span>animals<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span><span class="kw">new</span> Animal<span class="op">(),</span> <span class="kw">new</span> Bird<span class="op">(),</span> <span class="kw">new</span> Elephant<span class="op">()};</span></span>
<span id="cb5-20"><a href="#cb5-20"></a></span>
<span id="cb5-21"><a href="#cb5-21"></a>  <span class="cf">for</span> <span class="op">(</span><span class="at">const</span> <span class="kw">auto</span> <span class="op">&amp;</span>animal <span class="op">:</span> animals<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-22"><a href="#cb5-22"></a>    animal<span class="op">-&gt;</span>move<span class="op">();</span></span>
<span id="cb5-23"><a href="#cb5-23"></a>  <span class="op">}</span></span>
<span id="cb5-24"><a href="#cb5-24"></a><span class="op">}</span></span></code></pre></div>
<p>This returns:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1"></a><span class="ex">walk</span> Animal</span>
<span id="cb6-2"><a href="#cb6-2"></a><span class="ex">fly</span> Bird</span>
<span id="cb6-3"><a href="#cb6-3"></a><span class="ex">walk</span> Elephant</span></code></pre></div>
<p>In the Java version it isn’t apparent to the programmer that there is
a runtime cost, but C++ puts it front and center. Since we used the
<code>new</code> keyword, everything is placed on the heap. When we try
to call the <code>move()</code> method, we have to do it with the
<code>-&gt;</code> operator, which calls an object on the heap, rather
than on the stack.</p>
<p>Let’s say we don’t use the <code>new</code> operator, and don’t use a
pointer lookup:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode numberSource cpp numberLines"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2"></a>  <span class="at">const</span> Animal animals<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span>Animal<span class="op">(),</span> Bird<span class="op">(),</span> Elephant<span class="op">()};</span></span>
<span id="cb7-3"><a href="#cb7-3"></a></span>
<span id="cb7-4"><a href="#cb7-4"></a>  <span class="cf">for</span> <span class="op">(</span><span class="at">const</span> <span class="kw">auto</span> <span class="op">&amp;</span>animal <span class="op">:</span> animals<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-5"><a href="#cb7-5"></a>    animal<span class="op">.</span>move<span class="op">();</span></span>
<span id="cb7-6"><a href="#cb7-6"></a>  <span class="op">}</span></span>
<span id="cb7-7"><a href="#cb7-7"></a><span class="op">}</span></span></code></pre></div>
<p>This prints out:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1"></a><span class="ex">walk</span> Animal</span>
<span id="cb8-2"><a href="#cb8-2"></a><span class="ex">walk</span> Animal</span>
<span id="cb8-3"><a href="#cb8-3"></a><span class="ex">walk</span> Animal</span></code></pre></div>
<p>Since we are literally treating each animal as an <code>Animal</code>
type, <code>animal.move()</code> calls the default <code>Animal</code>
implementation of move. If we choose to have no runtime cost, we get
less desirable behavior. But C++ gives you the choice upfront.</p>
<p>Let’s dig deeper.</p>
<p>C doesn’t have any language support for <code>virtual</code>
functions, but we can still emulate them.</p>
<p>A (very) rough translation of the java program might look like
this:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2"></a></span>
<span id="cb9-3"><a href="#cb9-3"></a><span class="kw">typedef</span> <span class="kw">struct</span> Animal <span class="op">{</span></span>
<span id="cb9-4"><a href="#cb9-4"></a>  <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>name<span class="op">;</span></span>
<span id="cb9-5"><a href="#cb9-5"></a>  <span class="dt">void</span> <span class="op">(*</span>move<span class="op">)(</span><span class="dt">const</span> <span class="kw">struct</span> Animal <span class="op">*);</span></span>
<span id="cb9-6"><a href="#cb9-6"></a><span class="op">}</span> Animal_t<span class="op">;</span></span>
<span id="cb9-7"><a href="#cb9-7"></a></span>
<span id="cb9-8"><a href="#cb9-8"></a><span class="dt">void</span> fly<span class="op">(</span><span class="dt">const</span> Animal_t <span class="op">*</span>a<span class="op">)</span> <span class="op">{</span> printf<span class="op">(</span><span class="st">&quot;fly </span><span class="sc">%s\n</span><span class="st">&quot;</span><span class="op">,</span> a<span class="op">-&gt;</span>name<span class="op">);</span> <span class="op">}</span></span>
<span id="cb9-9"><a href="#cb9-9"></a><span class="dt">void</span> walk<span class="op">(</span><span class="dt">const</span> Animal_t <span class="op">*</span>a<span class="op">)</span> <span class="op">{</span> printf<span class="op">(</span><span class="st">&quot;walk </span><span class="sc">%s\n</span><span class="st">&quot;</span><span class="op">,</span> a<span class="op">-&gt;</span>name<span class="op">);</span> <span class="op">}</span></span>
<span id="cb9-10"><a href="#cb9-10"></a><span class="dt">void</span> animal_move<span class="op">(</span><span class="dt">const</span> Animal_t <span class="op">*</span>a<span class="op">)</span> <span class="op">{</span> a<span class="op">-&gt;</span>move <span class="op">?</span> a<span class="op">-&gt;</span>move<span class="op">(</span>a<span class="op">)</span> <span class="op">:</span> walk<span class="op">(</span>a<span class="op">);</span> <span class="op">}</span></span>
<span id="cb9-11"><a href="#cb9-11"></a></span>
<span id="cb9-12"><a href="#cb9-12"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb9-13"><a href="#cb9-13"></a>  <span class="dt">const</span> Animal_t animals<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span></span>
<span id="cb9-14"><a href="#cb9-14"></a>      <span class="op">{.</span>name <span class="op">=</span> <span class="st">&quot;Animal&quot;</span><span class="op">},</span> <span class="op">{.</span>name <span class="op">=</span> <span class="st">&quot;Bird&quot;</span><span class="op">,</span> <span class="op">.</span>move <span class="op">=</span> fly<span class="op">},</span> <span class="op">{.</span>name <span class="op">=</span> <span class="st">&quot;Elephant&quot;</span><span class="op">}};</span></span>
<span id="cb9-15"><a href="#cb9-15"></a>  <span class="dt">const</span> <span class="dt">size_t</span> animals_len <span class="op">=</span> <span class="kw">sizeof</span><span class="op">(</span>animals<span class="op">)</span> <span class="op">/</span> <span class="kw">sizeof</span><span class="op">(</span>Animal_t<span class="op">);</span></span>
<span id="cb9-16"><a href="#cb9-16"></a></span>
<span id="cb9-17"><a href="#cb9-17"></a>  <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> animals_len<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb9-18"><a href="#cb9-18"></a>    <span class="dt">const</span> Animal_t animal <span class="op">=</span> animals<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb9-19"><a href="#cb9-19"></a>    animal_move<span class="op">(&amp;</span>animal<span class="op">);</span></span>
<span id="cb9-20"><a href="#cb9-20"></a>  <span class="op">}</span></span>
<span id="cb9-21"><a href="#cb9-21"></a><span class="op">}</span></span></code></pre></div>
<p>C actually lets us do some interesting things here: It allows us to
allocate our <code>animals</code> on the stack. As well, we create an
<code>animal_move</code> function that asks the struct passed in if it
has a function pointer for <code>move</code>. If it does, then it defers
to that, otherwise it calls a default implementation. If we do choose to
use a more specific version of <code>move</code>, then we do have the
pointer lookup cost, but if not, there is no cost.</p>
<p>Predictably, this prints:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode numberSource sh numberLines"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1"></a><span class="ex">walk</span> Animal</span>
<span id="cb10-2"><a href="#cb10-2"></a><span class="ex">fly</span> Bird</span>
<span id="cb10-3"><a href="#cb10-3"></a><span class="ex">walk</span> Elephant</span></code></pre></div>
<p>Digging a little up, we find that Rust has a similar concept, but it
does away with using keywords like <code>virtual</code> or
<code>final</code> to designate dynamic dispatch.</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode numberSource rs numberLines"><code class="sourceCode rust"><span id="cb11-1"><a href="#cb11-1"></a><span class="kw">pub</span> <span class="kw">trait</span> Animal <span class="op">{</span></span>
<span id="cb11-2"><a href="#cb11-2"></a>    <span class="kw">fn</span> name(<span class="op">&amp;</span><span class="kw">self</span>) <span class="op">-&gt;</span> <span class="dt">String</span> <span class="op">{</span></span>
<span id="cb11-3"><a href="#cb11-3"></a>        <span class="st">&quot;Animal&quot;</span><span class="op">.</span>to_string()</span>
<span id="cb11-4"><a href="#cb11-4"></a>    <span class="op">}</span></span>
<span id="cb11-5"><a href="#cb11-5"></a>    <span class="kw">fn</span> act(<span class="op">&amp;</span><span class="kw">self</span>) <span class="op">{</span></span>
<span id="cb11-6"><a href="#cb11-6"></a>        <span class="pp">println!</span>(<span class="st">&quot;walk {}&quot;</span><span class="op">,</span> <span class="kw">self</span><span class="op">.</span>name())<span class="op">;</span></span>
<span id="cb11-7"><a href="#cb11-7"></a>    <span class="op">}</span></span>
<span id="cb11-8"><a href="#cb11-8"></a><span class="op">}</span></span>
<span id="cb11-9"><a href="#cb11-9"></a></span>
<span id="cb11-10"><a href="#cb11-10"></a><span class="kw">struct</span> GenericAnimal <span class="op">{}</span></span>
<span id="cb11-11"><a href="#cb11-11"></a><span class="kw">impl</span> Animal <span class="cf">for</span> GenericAnimal <span class="op">{}</span></span>
<span id="cb11-12"><a href="#cb11-12"></a></span>
<span id="cb11-13"><a href="#cb11-13"></a><span class="kw">struct</span> Bird <span class="op">{}</span></span>
<span id="cb11-14"><a href="#cb11-14"></a><span class="kw">impl</span> Animal <span class="cf">for</span> Bird <span class="op">{</span></span>
<span id="cb11-15"><a href="#cb11-15"></a>    <span class="kw">fn</span> name(<span class="op">&amp;</span><span class="kw">self</span>) <span class="op">-&gt;</span> <span class="dt">String</span> <span class="op">{</span></span>
<span id="cb11-16"><a href="#cb11-16"></a>        <span class="st">&quot;Bird&quot;</span><span class="op">.</span>to_string()</span>
<span id="cb11-17"><a href="#cb11-17"></a>    <span class="op">}</span></span>
<span id="cb11-18"><a href="#cb11-18"></a>    <span class="kw">fn</span> act(<span class="op">&amp;</span><span class="kw">self</span>) <span class="op">{</span></span>
<span id="cb11-19"><a href="#cb11-19"></a>        <span class="pp">println!</span>(<span class="st">&quot;fly {}&quot;</span><span class="op">,</span> <span class="kw">self</span><span class="op">.</span>name())<span class="op">;</span></span>
<span id="cb11-20"><a href="#cb11-20"></a>    <span class="op">}</span></span>
<span id="cb11-21"><a href="#cb11-21"></a><span class="op">}</span></span>
<span id="cb11-22"><a href="#cb11-22"></a></span>
<span id="cb11-23"><a href="#cb11-23"></a><span class="kw">struct</span> Elephant <span class="op">{}</span></span>
<span id="cb11-24"><a href="#cb11-24"></a><span class="kw">impl</span> Animal <span class="cf">for</span> Elephant <span class="op">{</span></span>
<span id="cb11-25"><a href="#cb11-25"></a>    <span class="kw">fn</span> name(<span class="op">&amp;</span><span class="kw">self</span>) <span class="op">-&gt;</span> <span class="dt">String</span> <span class="op">{</span></span>
<span id="cb11-26"><a href="#cb11-26"></a>        <span class="st">&quot;Elephant&quot;</span><span class="op">.</span>to_string()</span>
<span id="cb11-27"><a href="#cb11-27"></a>    <span class="op">}</span></span>
<span id="cb11-28"><a href="#cb11-28"></a><span class="op">}</span></span>
<span id="cb11-29"><a href="#cb11-29"></a></span>
<span id="cb11-30"><a href="#cb11-30"></a></span>
<span id="cb11-31"><a href="#cb11-31"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
<span id="cb11-32"><a href="#cb11-32"></a>    <span class="kw">let</span> animals<span class="op">:</span> <span class="dt">Vec</span><span class="op">&lt;&amp;</span><span class="kw">dyn</span> Animal<span class="op">&gt;</span> <span class="op">=</span> <span class="pp">vec!</span>[<span class="op">&amp;</span>GenericAnimal<span class="op">{},</span> <span class="op">&amp;</span>Bird<span class="op">{},</span> <span class="op">&amp;</span>Elephant<span class="op">{}</span>]<span class="op">;</span></span>
<span id="cb11-33"><a href="#cb11-33"></a>    <span class="cf">for</span> animal <span class="kw">in</span> animals <span class="op">{</span></span>
<span id="cb11-34"><a href="#cb11-34"></a>        animal<span class="op">.</span>act()<span class="op">;</span></span>
<span id="cb11-35"><a href="#cb11-35"></a>    <span class="op">}</span></span>
<span id="cb11-36"><a href="#cb11-36"></a><span class="op">}</span></span></code></pre></div>
<p>We create a <code>trait</code> of animal (kind of like an interface,
but supercharged) and then we create an instantiable version of it
(<code>GenericAnimal</code>) that just takes the default implementation.
Then we implement our <code>Bird</code> and <code>Elephant</code> and we
collect them into a vector and properly call the method on them. The
compiler assumes that we want dynamic dispatch by default and does it
for us. If not, we can call the parent classes’ method:</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode numberSource rs numberLines"><code class="sourceCode rust"><span id="cb12-1"><a href="#cb12-1"></a><span class="pp">Animal::</span>act(<span class="op">&amp;</span>Bird)<span class="op">;</span> <span class="co">// this calls the Animal version of `act` with a bird.</span></span></code></pre></div>
<p>This is similar to C++:</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode numberSource cpp numberLines"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1"></a><span class="at">const</span> Bird<span class="op">*</span> bird <span class="op">=</span> <span class="kw">new</span> Bird<span class="op">();</span></span>
<span id="cb13-2"><a href="#cb13-2"></a>bird<span class="op">-&gt;</span>Animal<span class="op">::</span>move<span class="op">();</span> <span class="co">// calls Animal::move with bird.</span></span></code></pre></div>
<p>In short, here’s a history of virtual functions and their syntax,
starting from C and ending with Rust:</p>
<p>In C, there’s a rough way to emulate virtuals, but it takes some
effort since it’s not built into the language.</p>
<p>In C++, virtual functions were deemed useful enough to be built into
the language. This led to a terser syntax for overriding, but led to
more cognitive load on the programmer, since they had to choose
<code>virtual</code> or non-virtual implementations.</p>
<p>In Java, most methods are by default virtual, so the implementation
details are hidden from the programmer. Java allows you to declare
non-overridable methods as <code>final</code>, so <code>final</code>
methods have no runtime cost, and all <code>@Override</code> methods
have runtime cost, which is a fair tradeoff.</p>
<p>In Rust, the compiler figures out if you want a <code>virtual</code>
or normal method call through your trait implementations, but allows you
to call the base method through a subclass if you so choose. This allows
for having even less cognitive load than in Java (no
<code>@Override</code> or <code>final</code> necessary), but with an
escape hatch to call the base class method in an overriden type (as C++
allows).</p>]]></description>
</item>
<item>
<title>The Strong Force and Weak Force of Companies</title>
<pubDate>Tue, 18 Aug 2020 18:19:06 +0000</pubDate>
<guid>https://blog/the-strong-force-and-weak-force-of-companies.html</guid>
<description><![CDATA[<p>There are four fundamental interactions in
physics; gravity, electromagnetism, the strong force, and the weak
force. Particles are affected by all four of these – hence why they are
fundamental to understanding physics. The strong force holds the nucleus
of an atom together. The weak force tries to tear the nucleus of an atom
apart, creating radioactivity.</p>
<p>The strong force is a million times stronger than the weak force at
small distances, up to 10 angstroms. However, as you add more protons
and neutrons to the nucleus of an atom, the atom gets bigger - and the
weak force becomes stronger and stronger, until eventually the nucleus
of an atom is too big to be kept together by the strong force, and the
weak force tears the atom apart, resulting in a radioactive atom.
Companies follow the same trajectory.</p>
<p>Companies are a lot like atoms; at first, growth is key – you want to
extend your revenue by having people buy the service you offer them. How
do you build a better service? By hiring. So you hire people to improve
your service. At first, this works excellently. Your first few hires
have great impact at the company, and they lay the foundation for hires
in the future. Of course, it’s not all roses – they make some mistakes,
and put in guardrails to make sure future employees don’t make the same
mistakes. But at this point of the curve, it is worth way more to you as
a company to continue hiring, since each hire gives you more value than
you pay them. But as time passes and you hire more people, each hire has
less impact. They’re encumbered by the communication cost of talking to
multitudes of stakeholders, and the cost of checking all of the
guardrails their predecessors laid down for them. Eventually work slides
to a snail’s pace, and it shows – the product doesn’t improve very much,
if at all – features that might take a few days take months at a time
now, and your revenue doesn’t increase as much as it used to. You’ve hit
your first slope. Your competitive advantage, your strong force is
fading. Everyone else is coming for you. The weak force is
strengthening.</p>
<p>You have a few ways of delaying the inevitable – maybe you find a
novel way to manage resources so you become better than the competition.
Maybe you realize that some of the rules you’ve enshrined don’t do much
for you, so you cut excess baggage. Maybe you can’t do the above, and
you cut excess resources in the form of employees. You’ve managed to
keep the competition at bay, but your strong force weakens as you do
this. If you manage resources to become better than the competition,
what stops the competition from copying you? If you cut excess baggage,
you run the risk of cutting out rules that were well-intentioned and
protected you from damage. You run the risk of plunging your company
into a dark age, where the employees have to rediscover the practices
that were purged from the annals of history to resume work. If you cut
employees, you risk the loss of morale that keeps your company churning.
If the company is willing to axe some people, what stops it from axing
the rest of them? Each time you do this, you come closer to your doom by
the hands of the weak force.</p>
<p>A company that keeps delaying the inevitable soon falls to its own
forces. It blows up, metaphorically. People stop wanting to work at the
firm because there’s too much bureaucracy. The product stop dominating
the market, and revenues fall. The consumers drop you for your
competition. Your company blows up, becoming a waste zone.</p>
<p>Business is all about keeping the weak force away. As we’ve made
progress in business, we’ve learned how to do this better. Companies
find ways to make more revenue with fewer people, and do more with less.
But this too shall pass – the companies of yesteryear will soon be left
in the dust. And so on and so forth. I wonder what the future of
organization has in store for the rest of us?</p>]]></description>
</item>
<item>
<title>The Business Curve</title>
<pubDate>Sat, 08 Aug 2020 15:25:54 +0000</pubDate>
<guid>https://blog/the-business-curve.html</guid>
<description><![CDATA[<p>In <code>Zero to One</code>, Peter Thiel
proclaims “Competition is for losers.” – if you can make a monopoly, you
should, because you can extract far more profit from it than if you
participated in an open market.</p>
<p>In a free market, with perfect competition, you face this supply and
demand curve below. You have to sell the good at the price where supply
meets demand, and you can sell up to but not more than quantity where
demand meets supply. Assuming you’re not the only seller of the good,
you have to settle for some chunk of the market.</p>
<p><img src="../assets/supply-and-demand-curve.png" /></p>
<p>Assume there are 5 merchants, and the amount of revenue you can bring
in is the square created by the area of where supply meets demand, you
get something like this:</p>
<p><img src="../assets/supply-and-demand-curve-for-firms.png" /></p>
<p>All of you split the market somewhat equally, and you make 0
<em>economic</em> profit. Nobody can sell the good for more than it’s
worth (opportunity cost + cost of production), and nobody will buy the
good for more than it’s worth (opportunity cost + cost of production).
The perfectly free market makes buyers and sellers equally well off.</p>
<p><img src="../assets/utility-for-buyers-and-sellers.png" /></p>
<p>This assumes that the first few products that a firm sells on the
open market are the <em>cheapest</em> for it to produce, and that there
are buyers that are willing to pay <em>more</em> for the product than
others, because it is inherently worth more to them. The firms get to
sell the goods that cost less for them to make at a higher price, and
the buyers who would’ve bought the good at a higher price to get to pay
less for the good. Everyone wins a little bit.</p>
<p>But firms want to make <em>economic</em> profit. This is where the
real money comes in. You can do this in many ways; organizations like
OPEC (the Organization of the Petroleum Exporting Countries) band
together every year and restrict the supply of oil on the open market.
This lets them charge more for their good (oil), since artificial
scarcity drives up the price of oil.</p>
<p>Because of this, the market for oil looks something like this:</p>
<p><img src="../assets/opec-oil-curve.png" /></p>
<p>The utility that both sides get is:</p>
<p><img src="../assets/opec-utility-gain.png" /></p>
<p>Nice! We’ve made <em>economic</em> profit. What we’ve done here is
taken a large slice of the pie for ourselves; the buyers lose some
utility, but in exchange the sellers get more utility. However, we’ve
lost some <em>total</em> utility. The area to the right of the seller’s
utility gain is now white. That’s utility that we’ve <em>lost</em>. This
is called <em>Deadweight Loss</em>, because OPEC has now made some
utility inherent to the market unreachable. The market as a whole could
be better off and capture that white area if OPEC decided to sell oil at
the market competitive price.</p>
<p>OPEC made the market better for the sellers, in exchange for hurting
the buyers, and worse for the economy as a whole.</p>
<p>In this case, OPEC is an oligopoly, or a case where there are only a
few sellers of a good. A monopoly is when there’s only one, and a
duopoly is when there are only two. All of these traditionally generate
deadweight loss, generating less utility for the buyer and more for the
seller(s). This is why you hear how monopolies and oligopolies are
<em>bad</em> and should be broken up by the government.</p>
<p>But OPEC isn’t a maintainable oligopoly. Saudi Arabia doesn’t trust
the other members of OPEC. Russia doesn’t trust OPEC. In fact, OPEC
doesn’t trust itself. The reason is simple: As a seller, you could make
more money if you undercut the market and sell more oil at a lower
price. If I sell oil at a lower price than the other countries, I get
all of the profits. That entire red rhombus I had to share with the
other sellers? All mine. And I expand it a little bit too. The rhombus
gets fatter for me, at the expense of all of the other sellers.
Oligopolies have a cooperation problem – the economy cannot enforce its
sellers to sell a good at a higher price than it values said good. So
Russia, Venezuela, Saudi, and so forth go to each OPEC meeting wondering
if this is the time the other countries backstab them and make off with
all the gold. In OPEC’s case, all of the countries have to be well armed
too, because they don’t know when the other countries might come to
capture their oil to increase their profits. Cooperation works worst
when all parties are paranoid.</p>
<p>The problem with this model of economics is that it only somewhat
applies to some goods in some places. This assumes we have symmetric
information – that sellers know just as much as buyers. This also
assumes that our goods are private and no different than each other. But
really, every good is somewhat different; coke isn’t exactly the same as
pepsi, even though they are similar products. This model also doesn’t
count network effects, where making a good become more popular has
benefits to all of its users and its overall utility.</p>
<p>If I wanted to buy some British soda, I would have to import that
soda to the US in order to buy it. That costs me both time and money;
and so the soda costs more than it would if I simply wanted a coke. If I
wanted a coke, I could just walk down the street since every grocery
store carries it, because of its popularity. Coke is cheaper than this
British soda, Iron Bru.</p>
<p>A service like Uber really wants a monopoly for that reason; because
if it had a monopoly, it would be able to have all of the drivers on its
platform available to serve all of the riders, and thus be able to get
economic profit. Alas, Lyft exists; and so, there are only half the
available drivers on Uber and half the available riders on Uber. Uber
and Lyft are then also forced to price their service lower and lower to
beat each other out and win the loyalty of their riders. Buyers win
here, but the sellers are engaged in a race to the bottom. And only one
will survive, a la highlander.</p>
<p>If we assume that a monopoly is the only way to go to gain
monopolistic profits, we need to find a way to do so, without using
force (because that breeds paranoia). The only way out is by making a
better product. If we make a better product, we can create a market that
didn’t exist before, and gain monopolistic profits from that market. If
this product cannot be replicated, then there is no incentive to stop
the monopoly; because the market will only be worse off. Thus, no use of
force in any way can stop us from gaining monopoly profits. But building
the next Google is hard. Incredibly so.</p>
<p>You can, however, build a product that has differentiation in some
way. You must have a feature that is <em>hard</em> and <em>useful</em>,
and you too can ride a smaller but also profitable monopoly curve for
profit.</p>]]></description>
</item>
<item>
<title>Language Pessimism and Optimism</title>
<pubDate>Fri, 24 Apr 2020 21:31:51 +0000</pubDate>
<guid>https://blog/language-pessimism-and-optimism.html</guid>
<description><![CDATA[<p>Let’s talk languages. Not languages like
Swahili or Latin, but languages like C or Java. Programming languages. I
would argue that the programming language you use day to day is the most
important tool you use in programming – if you use a modern language, it
offers a lot of punch compared to something like assembly. The
programming languages of today are cross platform, which gives you
<em>compatibility</em>, meaning you don’t have to worry about writing
your code for every platform or architecture, because your language
takes care of it for you. It gives you <em>abstraction</em>, because you
can write code that takes a different shape than the way the machine
sees it. Machines can’t understand for loops or if statements, or even
really anything more than 0s and 1s. We made up things like functions
and classes and interfaces and stuff like that. And these abstractions
are really good. I’ve never wondered when a for loop or if statement
didn’t work as intended in the language. Programming languages also give
you <em>safety</em> – they prevent you from doing bad things with your
program. If I try to cast to a non-compatible type, my compiler might
catch that – if I try to write to some memory I don’t own, my language
or Operating system will stop that. And that’s just scratching the
surface – there’s plenty more to love about languages. Higher order
functions! Algebraic Data Types! Optimizations! Syntactic Sugar! It’s a
joyride all the way down. But we’re not going to talk about the
nitty-gritty type theory of languages, no, today we’re going to be
talking about how people view languages in programming, by doing
everybody’s favorite thing – dividing people into two kinds of people,
the x’s and the y’s, or the pessimists and optimists.</p>
<h2 id="the-pessimists">The Pessimists</h2>
<p>The pessimists tend to say something along these lines quite often:
“Good code can be written in any language, and bad code can be written
in any language. It’s all about discipline when writing code.” COBOL is
as good as Java. People made great systems in COBOL, just like they made
great systems in Java. And it’s true. Much underpinning financial
systems were written in COBOL. Many COBOL systems are still out in the
wild running, decades after they were written. And to the pessimists’
credit, they work just fine. After all, if a language is Turing
complete, it is <em>as powerful</em> as any other language. Basically
all popular languages are Turing complete, so they’re theoretically
equivalent in power. Some languages are just better at certain things,
but they can all <em>express</em> the same things.</p>
<h2 id="the-optimists">The Optimists</h2>
<p>The optimists might say that languages are different. An optimist
might say that they prefer C++ to C because it has collections and
Object Orientation. An optimist might enjoy using smart pointers to aid
in memory management. An optimist might like the way that python handles
iterable collections. These all aid in code readability, because the
abstraction is easy to understand and encapsulates more functionality in
fewer lines. Maybe an optimist likes static types, because they make it
explicit what types of data a function or method might return, or make
it easier to understand the way data transforms throughout its
lifecycle. In the optimists’ eyes, there are abstractions which aid in
the expression of code, and since different languages choose different
abstractions to make the expression of some types of programs harder and
some easier, there are some differences between languages. You can
program in an object oriented style in C. You can program in a generic
style in C. These are all far less compact than their equivalent C++.
There is an aesthetic difference, if not theoretical difference.</p>
<h2 id="a-twist">A Twist</h2>
<p>If you follow my points up above, I’m promoting the idea that
language optimists prefer the aesthetics of a language, whereas the
language pessimists prefer the theoretical power of a language.
Theoretical power of a language is not bounded by expressiveness,
however. If it took you 100 lines of code to read from a file in a toy
language (let’s call this language Airplane), but 1 line of code to read
from a file in another language (let’s call this language Ship), Ship
and Airplane would be theoretically equal in power. But in practice,
most people would prefer to use Ship for reading files. 1 line of code
is 100x less than 100. If this was the case for everything (let’s say it
took 100x more lines to write any possible program in Airplane than in
Ship), you would probably prefer Ship. In terms of expressiveness, Ship
is better than airplane.</p>
<p>Ship is still not more <em>powerful</em> than Airplane; it is simply
more expressive.</p>
<p>But that’s still just aesthetics; what if there was a class of
problems that Ship did not suffer from that airplane suffered from.
Let’s say that Airplane and Ship are both Web programming languages, and
if you fail to write “safe” Airplane code, you might allow some users to
read information that belongs to another user’s. Let’s say in Ship, this
problem doesn’t exist – Ship wouldn’t let our code compile if it could
detect the possibility of this bug.</p>
<p>Even with this added on, Ship is still not <em>theoretically</em>
more safe than Airplane; a correctly written Airplane program is <em>as
safe</em> as a Ship program that compiles. But I would say in this case,
most programmers would prefer Ship. Even though Airplane is
<em>theoretically</em> <em>as safe</em> as Ship, a language that
provably lacks a class of errors is at least marginally better than a
language that may probabilistically have a class of errors.</p>
<p>Now the twist is, is Ship in a different class of language compared
to Airplane? Does safety matter?</p>
<h2 id="choose-your-own-adventure">Choose your own adventure</h2>
<p>It’s up to you. Theoretically safety doesn’t play a part in
programming. God awful safety vulnerabilities and memory leaks don’t
matter because, while they cause us and our users to be sad, and might
even cause us to go to jail, they don’t make our program any less
powerful. A program doesn’t care if you go to jail or not, actually, and
neither does math. If you are concerned with this definition of power,
then Airplane and Ship are indeed equivalent. But maybe you have a more
practical bent. If so, Ship is probably the better language – hey, you
can express yourself with 100x less code and it has more safety built in
that Airplane.</p>
<h2 id="is-safety-preference">Is Safety Preference?</h2>
<p>That leads me to my last point. Is Safety Preference? Is a safer
language a categorically different language than one that an unsafe
language? I would argue so. Most programmers these days will probably
never touch a memory unsafe language (C and C++ being the most popular
of these). There’s a whole extra class of errors to account for in these
two languages, and when you choose a garbage collected language, most of
the time you don’t have to worry about memory. That helps you out with
delivering better safe software. And that’s great. It makes you more
productive. But maybe you need to have performance instead of safety,
and this is where most people go for performance. Safety comes at some
cost, and you can’t always have safety. But if you can have safety, you
might as well buy into it, since it lessens your cognitive
load.</p>]]></description>
</item>
<item>
<title>Performance Matters</title>
<pubDate>Sun, 29 Mar 2020 18:51:41 +0000</pubDate>
<guid>https://blog/performance-matters.html</guid>
<description><![CDATA[<p>Asking programmers about performance generally
leads to two trains of thought. Either it doesn’t matter, and there are
other metrics to chase, or performance matters. Most of the time, those
who think that performance matters can be broken down into two different
streams of thought. One group thinks that performance matters because it
saves money – if your server costs are a million dollars a month and you
make the whole system 10% more efficient, you’ve reduced server costs by
about a hundred thousand dollars. It’s nice to save that money. The
other group is more intense about it – performance is the only thing
that matters because it allows us to create programs that solve problems
that other (less efficient) programs would simply not allow us to.
Plenty of hot-path code is written in low-level highly optimized
languages.</p>
<p>All three ways are true in sometimes: sometimes you don’t need to
look at code under a microscope because the underlying runtime will
optimize it, sometimes saving money may save the company, and sometimes
performance is the only thing that matters. But I’m going to say that
performance has and always will matter because of the fact that hardware
will always get smaller, and we want to do more with less. It turns out
that there is a great analogue for this in chemistry already.</p>
<p>In chemistry, atoms are held together by gravitational forces. But
there are two forces at work, the <code>strong</code> and
<code>weak</code> force. The <code>strong force</code> keeps the nucleus
of an atom together, whereas the <code>weak force</code> tries to
disperse the protons and neutrons of the atom. As you’d expect, the
<code>strong force</code> is stronger than the <code>weak force</code>
for smaller elements. But this begins to break down as atoms get bigger
– the <code>strong force</code> is not asymptotically stronger than the
<code>weak force</code>. As such, there are radioactive elements like
Uranium-235, where the <code>weak force</code> overpowers the
<code>strong force</code> and causes the element to become radioactive.
Radioactive elements eventually tear themselves apart, and split into
smaller elements at the end of their half-life.</p>
<p>Hardware has historically (and I don’t think this will change much)
been the same way. At first, computers like the ENIAC were the size of a
house, (wikipedia says 1,800 sq ft), and consumed 150kW of electricity
to perform a whopping three square root operations per second. At first,
this is wholly insufficient for most of the work needed to be done on a
computer. So research was done to optimize hardware to the point where
it was able to be made smaller. That led to the micro-computer, a
computer the size of a desk, which could do some interesting tasks like
word processing or simple text games. Eventually we found that we had
enough performance that we could stick a micro-computer into a smaller
computer, one that was portable, and that was called a laptop. Then the
hardware advanced to the point where it could fit into your pocket, and
that became the smart phone. Tablets branched out to be in the middle of
size (and therefore compute) of a laptop and a smart phone. Our need for
smaller and more efficient hardware has made it so we couldn’t throw
performance by the wayside; every time performance was “good enough”,
the hardware got smaller until performance mattered again.</p>
<p>If you believe history will continue, then we’ll have even smaller
devices with even more strict real time capabilities. Doctors have been
asking for more efficient tools to treat patients with for a very long
time, for good reason. More portable and cheaper tools for doctors allow
them to treat more patients at less cost. More powerful tools allow for
doctors to find signs that they might’ve missed with less powerful
tools. A new generation of video gamers want to bring their games on the
go – as such, the mobile video game industry has blossomed apart from
the traditional console based games. VR headsets are now being used for
therapy, and this is extremely performance sensitive – if the program on
a VR headset is slow by even milliseconds, the user may become fatigued
or nauseous, which defeats the purpose of the technology.</p>
<p>History has always been about doing more with less, and I don’t see
that changing for the near future. Maybe when Moore’s law stops becoming
true?</p>]]></description>
</item>
<item>
<title>Who Gets Stuff Done</title>
<pubDate>Thu, 12 Mar 2020 16:52:45 +0000</pubDate>
<guid>https://blog/who-gets-stuff-done.html</guid>
<description><![CDATA[<p>Software developers are generalists. Ask the
average software developer questions about networking, databases,
compilers, operating systems, data structures, distributed systems, and
9 out of 10 will tell you that they know something about them. But this
generalist mentality begins to break down once you acknowledge one of
the most fundamental things rules of life:</p>
<ol type="1">
<li>Nobody can be an expert at everything.</li>
</ol>
<p>And if nobody can be an expert at everything, we eventually must have
roles for our field. One mechanic alone cannot create a high performing
and standards compliant car these days. It’s just too hard. Likewise,
software development is too hard for any one person to keep the whole
field in their head. And that’s a good thing. It means that we have
roles for who does what, and that helps teams move quickly, without
getting bogged down in the minutae.</p>
<p>So we have well defined roles for the work that we do on our teams,
like Front-End developer, Back-End developer, DevOps, SysAdmin,
Designer, Product Manager. All is dandy in the world. Well, all would be
dandy if there wasn’t a question of what makes an developer a
developer.</p>
<p>Once a field becomes sufficiently mature, the practioners of the
craft, (the real intense ones anyway) start sharing a common idea of the
ideal practioner. First this starts out as vague and easy to achieve
ideals, like “a real developer would be able to answer fizzbuzz in 30
seconds”, or “a developer should be able to understand one programming
language well”, which is all hunky dory. And soon, a regulatory body of
practioners, filled with the people who subscribe to that ideal the best
is borne, and they create norms and disseminate them to the rest of the
practicing population. Psychologists in America have the APA, doctors to
pass a board certification, and lawyers have to pass the bar in each
state. I’ll call the idea of the ideal practioner the “soul” of the
field, and the regulatory body (a la APA, bar, or other) the “body”. If
all is in harmony, the “body” and “soul” are in alignment – the
practioners agree with the higher ups on what should be taught, and what
constitutes a “real” practioner.</p>
<p>The system I’ve described above works great when “body” and “soul”
are in tune – there is buy-in from both sides of the table. But
programming has never had that. And it’s because the field is too
varied, one that should’ve been split up (and probably will be) in the
coming decades. You see, development doesn’t fit so neatly like other
professions do in this model, because at large, there aren’t two groups
of programmers. There are three. Academics, Systems Programmers, and
Application Programmers.</p>
<p>In computer science, academics do research on problems that are
remarkably forward thinking – as you read this, papers are being
published for increasing the speed of low-level hardware, operating
system calls, database reads and writes, distributed systems,
programming langauges, AI, statistics, quantum computing, cryptography,
what have you. These all have wide impact, maybe even decades later –
Barbara Liskov (of the Liskov substitution principle) was working on
object oriented languages in the 60s, some 30 years before they made it
to the mainstream for practioners in the form of java. Liskov as well as
Lampert made long lasting contributions to distributed systems research,
which has changed the way practioners have built their infrastructure,
and has allowed companies like google and amazon to become global
companies. RSA encryption, made in the 70s, is widely used today. There
is a long tail of important and groundbreaking research, but you get the
gist – Academics do important research.</p>
<p>Systems Programmers are the ones who, when they see a reason to,
implement the academic’s work. Linux implements some of the cutting edge
of operating systems research. Zookeeper implements the consensus
algorithms that academics envisioned from the 70s. OpenSSL implements
RSA encryption, and many others. System programmers transfer the
abstract, theoretical world of theorems and proofs into libraries and
packages for the rest of us to use.</p>
<p>Application programmers are the ones who take the work of System
Programmers and create products and applications that are used by the
world at large (read: not tech-savvy people). They deal with the nitty
gritty of presentation and User Experience, and find creative ways to
use the tools they have to make products that require very little
in-depth knowledge of the product to use.</p>
<p>With these three camps, it is impossible to have either a “soul” or
“body” for programmers. I’ll list out the ideal “body” and “soul” for
each of the three camps.</p>
<p>Academics:</p>
<ul>
<li>Body:
<ul>
<li>An academic body that tests developers on the rigor of their proofs
and theoretical knowledge.</li>
</ul></li>
<li>Soul:
<ul>
<li>A practioner that thinks from first-principles to expand the rigor
and breadth of the field.</li>
</ul></li>
<li>Education:
<ul>
<li>A higher education (Masters or PhD)</li>
</ul></li>
</ul>
<p>Systems Programmers:</p>
<ul>
<li>Body:
<ul>
<li>A coalition of workers who stress low-level (in code) fundamentals,
and tool building for performance.</li>
</ul></li>
<li>Soul:
<ul>
<li>A practioner who doesn’t necessarily need to produce academic
research, but can pick up academic works and translate them to libraries
and packages.</li>
</ul></li>
<li>Education:
<ul>
<li>A degree in the field (Undergrad, Masters, or PhD)</li>
</ul></li>
</ul>
<p>Application Programmers:</p>
<ul>
<li>Body:
<ul>
<li>A group of programmers who build products for the general
population.</li>
</ul></li>
<li>Soul:
<ul>
<li>A practioner who can pick up a wide variety of tools, and knows how
to use them to quickly create the required product.</li>
</ul></li>
<li>Education:
<ul>
<li>Varied.</li>
</ul></li>
</ul>
<p>All three groups are in constant conflict, and this leads to the
chaotic state of software development – at one end, the Academics aren’t
even implementing software – and at the other end, Application
programmers stress a high-level knowledge of a variety of areas.
Agreement isn’t necessary in this case, but it is something that would
benefit largely in one area. Interviews.</p>
<h2 id="the-hiring-bar">The Hiring Bar</h2>
<p>After being interviewed for days by Bell Labs, a young up-start
computer scientist named Bjarne Stroustrup found a job at one of the
most coveted research labs in the nation.</p>
<p>After being interviewed for weeks by an Unnamed Big Firm, a young
up-start new graduate named ${GENERIC_NAME} found a job at one of the
most coveted firms in the nation.</p>
<p>See any relation? You should, because I made it painfully obvious.
Big firms subject prospective candidates to a brutal interview loop,
constituting of knowledge of low-level operating systems, compiler
theory, algorithms and data structures, distributed system design, and
others. This all makes sense if you want a software developer who will
work on all of these areas, but most firms do not actually need their
candidates to know this knowledge on the job – it is abstracted away
from them by the work of Systems Programmers who provide (mainly) good
libraries to base work off of. Maybe Untitled Big Firm has does have
problems of scale – but your average start-up does not. And yet, the
hiring process continues this way.</p>
<p>The big firms might be justified for want of unicorn talent (after
all, they’re willing to pay for it), but most firms simply cannot afford
to pay the compensation that these developers are worth these days. And
yet, the hiring process continues, and I hear companies complain on
LinkedIn about how hard it is to hire and retain good developer talent.
To those companies, I only have a few choice words: buck the norms, and
fix your interview process.</p>
<p>I’ve heard countless stories of acquaintances not passing an
interview because they were asked questions that were outside of their
specialization, which matched the job. One acquaintance with an interest
in robotics and hardware was asked about implementing a Todo CRUD app.
He failed. Another friend was asked about low-level disk write system
calls for a React position.</p>
<p>I think this happens because companies have a mistaken perspective of
“who gets stuff done”, A.K.A “10x engineers”. They assume that to be a
“great” developer, you must understand everything about your computer,
and that translates to great code. That is not true. A good developer
knows the appropriate level of abstraction for the task at hand. Asking
a systems programmer about application programming, or vice-versa, is a
surefire way to destroy your hiring pipeline. The best companies know
this, so they don’t do that. They hire “1x” engineers, and make it to
market “10x” as fast as the other firms. Those firms win. The product
people love the devs because they crank out bug-free code in record
time, and the customers love those companies because they make genuinely
good products.</p>
<p>Always value getting stuff done.</p>]]></description>
</item>
<item>
<title>10 Predictions</title>
<pubDate>Fri, 27 Dec 2019 00:56:17 +0000</pubDate>
<guid>https://blog/10-predictions.html</guid>
<description><![CDATA[<p>In a few more days, the 2010s will be over.
Lots has changed in the programming world – Java is no longer king, but
JavaScript, being the most popular language (according to stack
overflow) for 7 years straight. NoSQL databases like MongoDB, Redis, and
Cassandra have become exceedingly popular, as well as front end web
technologies such as Angular, React, and Vue. Kotlin has become the
preferred language for Android development, along with Swift for iOS.
SaaS companies are ubiquitous, and Marc Andreessen’s prediction of
“software eating the world” rings even more true today.</p>
<p>Let’s hope that the 20s are an even wilder ride for software
development, and to that end, here I’ve decided to compile ten
predictions for the next decade as a fun little exercise. As a reader of
this article, I encourage you to do the same (I’m looking forward to
seeing how our predictions are different or similar!)</p>
<p>Most of these predictions will be wildly incorrect, but I think this
is a good excuse to think about what could be coming in the future.</p>
<h2 id="self-driving-cars-will-still-be-two-years-out">1. Self-driving
cars will still be two years out</h2>
<p>Before anyone asks, I’m talking about level 5 meaning fully
autonomous, you could take a nap in the backseat of the car with no
driver autonomous. There is a lot of interest in this space, and for
good reason – Large companies like Uber, Lyft, Waymo, and Tesla have
been researching self driving cars for the good part of this decade.
There are many technical concerns regarding self-driving cars, but I’m
actually fairly sure they’ll be solved this decade. Legality is a huge
gray area. Should self-driving cars never have an accident? If that
blocks general availability, self-driving cars will never make it on the
road. But if the government allows self-driving cars as long as they
have less accidents than human drivers, I think there’s a shot they make
it this decade. But I think the real problem is that regulation will be
lagging behind.</p>
<h2 id="rust-will-become-a-top-10-language-in-popularity">2. Rust will
become a top 10 language in popularity</h2>
<p>According to 2019’s Stack overflow’s developer survey, the tenth most
popular language is TypeScript, which has 21.2% of respondents
professing usage. Right above that is C++ at 23.5%, and right below is C
at 20.6%. Rust is currently at 3.2%, sitting just below Scala. Of the
ten languages, Typescript is the only one younger than a decade, but it
has already edged out C in popularity. Rust is the only language that
can save us from C and C++ supremacy in high performance computing. It
has a couple of famous backers (like Mozilla and Amazon), and it has won
most loved language for 4 years running on Stack Overflow. Allowing
access to low level computing without unsafe abstractions is a real
treat. Every generation of programmers flocks to a new way of doing
computing – C saved us from assembly, and C++ followed to tack on object
oriented programming and RAII. Java popularized garbage collection, and
languages such as Javascript, Python, and Ruby added higher level
functional abstractions to the mainstream. I think this next decade will
see the rise of Swift, Kotlin, Go, and Rust to the top 10 of
languages.</p>
<h2 id="webassembly-will-kill-javascript-and-desktop-apps">3.
WebAssembly will kill JavaScript and Desktop Apps</h2>
<p>I don’t mean kill kill, like how C did away with Fortran. I expect to
see JavaScript as a top 5 language still by the end of this decade, but
I think WASM is too much of a game changer to ignore. Applications with
higher performance requirements are gated from the web because
JavaScript is the only front-end programming language – you simply can’t
have a garbage collected interpreted language be high performance.
WebAssembly changes all of that. Compile Rust, Go, C or C++ for the
front end. Games, exiled to desktops after the death of flash, can come
back to the web. Developers with high CPU requirements (like AI/ML apps)
will most likely find their home on the web this decade. I expect
something similar to npm popping up, but for all kinds of packages in
all kinds of languages, widening the range of the web.</p>
<h2 id="json-will-be-replaced-with-a-typed-transfer-protocol">4. JSON
will be replaced with a Typed Transfer Protocol</h2>
<p>JSON has been around for 20 years – but I don’t expect it to be
popular for another 20. While I enjoy working with JSON APIs, I think
that choosing a JavaScript based transfer protocol is a double edged
sword. Sure, it rose in popularity because it’s just like Javascript,
but JavaScript is fast and loose, something not all programmers
appreciate. Tools to facilitate typing and strictness have popped up for
JSON, but sometimes it’s better to start from the ground up. I expect
something like YAML with strict typing becoming more of the standard by
2030.</p>
<h2 id="functional-programming-will-finally-become-popular">5.
Functional Programming will finally become popular</h2>
<p>Programming in a functional style has become all the rage recently,
but people still haven’t adopted functional languages into their
toolkit. Of the three tenets of functional programming, most mainstream
languages have accepted two, functions as first class citizens, and
stronger typing. Immutability is hard to implement if all of your data
structures are mutable, so that’s a non-starter. I just want to be able
to talk about algebraic data types at a meetup without being an outcast,
darn it!</p>
<h2 id="microservice-hype-will-wear-off">6. Microservice hype will wear
off</h2>
<p>This one will probably seem crazy to half of the readers, and obvious
to half of the readers. Microservices are great because they encourage
looser coupling. Unfortunately, looser coupling also requires more code.
And the worst thing you could do to your codebase is increase the amount
of code it has. If monoliths create tech debt gradually by entangling
everything in their grasp, the sheer amount of code microservices
introduce will blanket your entire organization.</p>
<h2 id="facebook-will-no-longer-be-a-top-10-company">7. Facebook will no
longer be a top 10 company</h2>
<p>Facebook made one good product 15 years ago. The other two products
driving most of their profits, Instagram and WhatsApp were acquisitions.
Among the youth, Facebook is unhip and ancient. You know, just like
commodores are artifacts of a bygone epoch. Zuckerberg is smart, but I
don’t think good acquisitions (which saved Facebook this decade) will
save them the next decade. We’ll see though.</p>
<h2 id="an-ai-startup-will-become-this-decades-hottest-startup">8. An AI
startup will become this decade’s hottest startup</h2>
<p>Last decade’s hottest startups, like Uber, or Lyft, or AirBnB created
the gig economy. I expect AI to try to coax the gig economy into its
coffin.</p>
<h2 id="blockchain-will-be-this-decades-beanie-babies">9. Blockchain
will be this decade’s beanie babies</h2>
<p>Blockchain has been gaining ubiquity as a secure new way to exchange
funds, but I don’t see it taking off just yet - It strikes me as an idea
that is too early for its current decade.</p>
<h2
id="you-and-i-will-host-our-apps-on-a-new-cloud-provider-read.-not-aws">10.
You and I will host our apps on a new cloud provider (read. not
AWS)</h2>
<p>AWS became <em>extremely</em> popular this decade - and I don’t
expect the service to die this decade. While it’s great for enterprise
by thinning the IT department, it’s not made for you and me. It’s
confusing, for one, with configuration hiding behind every corner, ready
to jump out and spook you. Oh yeah, and it costs a
lot.</p>]]></description>
</item>
<item>
<title>Why are there so many Software Engineers?</title>
<pubDate>Sun, 14 Apr 2019 20:56:58 +0000</pubDate>
<guid>https://blog/software-engineering.html</guid>
<description><![CDATA[<h2 id="hardware-vs.-software">Hardware
vs. Software</h2>
<p>Have you ever wondered why so many people are software developers
instead of hardware developers these days? I certainly have. And even if
you haven’t, I’ll go ahead and give you a cut and dry example of why
that is, and why software is considered to be the way of the future (for
now). I’ve never studied anything about either hardware or software, to
be fair – hardware is black magic and software is a black box, so take
my narrative and reasoning with a grain of salt.</p>
<h2 id="what-is-software">What is Software</h2>
<p>First off, we’ll have to define what software is. I really don’t have
a great definition to give you, but I’m sure you know what software is
anyway – it’s anything above hardware, and hardware is anything below
software. I jest, of course. Software is defined as operating
information used by a computer. These days, any kind of programming that
builds on an operating system (OS) is software programming. To me,
operating systems are the proverbial line drawn in the sand between
hardware and software – an OS takes your instructions and etches them
into the hardware. It turns software actions into hardware truth, a sort
of bridge between hardware and software.</p>
<h2 id="what-is-hardware">What is Hardware</h2>
<p>This time I’m better prepared to read out the definition of hardware!
Put down your pitchforks. Ahem. Hardware is “the machines, wiring, and
other physical components of a computer or other electronic system.”
Sound good? Hardware is all around us. I’m writing this article on a
Macbook Pro, I ride the bus to and from work, and I even use a microwave
from time to time (a lot of the time, actually). These are all examples
of hardware with software interfaces that expose an interactive API.
When I click the button to reheat my pizza, the microwave sends
instructions to the hardware of the microwave (turn on, use this much
electricity, start spinning, turn off, etc). Hardware is everywhere
around us.</p>
<h2 id="why-software">Why Software</h2>
<p>Now that we have some definitions out of the way, let’s take a trip
down memory lane. Long, long ago there were not that many computers and
hardware was very expensive. One of the first popular programming
languages was Fortran, which ran on the IBM 704 mainframe computer.
Computers were the size of rooms back then, and this super computer
packed a whopping punch. It had a jaw-dropping memory of about 18KB and
weighed 10 tons. Whoo wee. We’ve come a long way, haven’t we? Anyway,
given the cost of these computers and the amount of electricity they
consumed (thousands of dollars worth an hour), it made sense that it was
important to optimize for hardware time, not programmer time. See, a
team at IBM had access to one of these. That means a team of smart,
capable individuals would all have to share one computer. They’d fuss
for hours about making faster algorithms, because it mattered. A lot.
Most people programmed in pure machine code in those days because a
compiler couldn’t come close to the amount of optimization a team of
super smart people would be able to do. Clearly, hardware was the
constraining factor here, not labor. And for many years that was true –
interpreted languages (such as lisp) were looked over because they ran
thousands of times slower than native machine code. Needless to say,
most everyone programmed in machine code, and that was the way things
were.</p>
<p>But eventually, that changed. Think about Moore’s law. The number of
transistors in a circuit doubles every two years. With the increase in
computing power of hardware, programmers were freed from having to use
machine code for everything. Eventually they used assembly, and then
higher level languages like C, and nowadays, extremely high level
languages like Python, Ruby, and Javascript have risen to prominence.
Sure, Javascript runs many orders of times slower than machine language
or assembly, but with every passing year, higher level languages rise in
popularity. Every year, our hardware gets better. That means every year,
hardware costs less. Thus, programmers are freed from having to optimize
every facet of their program. Oddly enough, programmers are incredibly
cheap to hire these days. Give them a $1500 computer, two monitors, a
keyboard and mouse, a chair and desk. That’s about $3000 for all the
hardware they need. But the company needs to pay their salary, which can
range quite heavily, but it sure costs a lot more than $3000 a year, let
me tell you.</p>
<p>So the trend is quite apparent for right now. Hardware costs less and
less with each passing year, whereas software costs more and more.
Software took over hardware as the restricting factor in development,
and ever since then, there’s been a boom in software jobs and more of a
glut in hardware jobs. And it doesn’t seem to be stopping anytime soon.
Steve Jobs famously told Barack Obama to lower barriers in immigration
because Apple just couldn’t hire enough talented software engineers.
Salaries have skyrocketed for software developers, and it looks like
they won’t be falling back to earth soon, as long as companies have too
much demand for software developers with far too little supply.</p>
<h2 id="conclusion">Conclusion</h2>
<p>So the trend seems to be that we’ll need more and more software
engineers, and maybe hardware won’t grow as fast. Even with the
explosion in mobile devices in the past decade, there can be thousands
of apps on one phone. That means there’s one team of hardware engineers
for every thousand or so teams of software engineers. So, perhaps, the
direction from now on will be more software-oriented instead of
hardware-oriented. Or, perhaps, there’ll be another change. Maybe
hardware will see a revival when we all become cyborgs in the near
future. Who really knows?</p>]]></description>
</item>
<item>
<title>Progressing in Programming</title>
<pubDate>Thu, 11 Apr 2019 20:41:20 +0000</pubDate>
<guid>https://blog/progressing-in-programming.html</guid>
<description><![CDATA[<p>I’ve always wondered what the power of
journaling was – I’d never been the type to write all of my goals in a
journal, and plan meticulously about what I was going to do – I took
everything at face value and jumped on every opportunity as it came. But
no longer! It’s time to begin blogging about progress. We’re going to
make some gains. (Not of the gym kind, of course).</p>
<p>Before we begin to do any growing, we have to know what to grow in!
So we take this big goal and shrink it down into bite-sized pieces. So
my goal is to become a better software developer by the end of the year.
My reasoning is that understanding more about the basics of programming
languages will help me out on the day to day, helping me understand what
I need to do in order to become a better software developer.</p>
<p>So then, what is there to learn? Well, too much. But I’d like to
improve at certain parts of programming that are ubiquitous in the
field.</p>
<h2 id="c-programming">C Programming</h2>
<p>Ah, C. The language of Unix, the programming language that runs Unix,
the most influential Operating System of all time. Such a powerful
language, with just 32 reserved words, you too can build your own kernel
in just a few thousand lines using this wildly expressive language. So C
pretty much is the de facto language for compilers and Operating Systems
(since they’re both built in C), and this makes it a great first
language to sink my teeth into. The way I’ll do it is by reading through
Programming in C (4th edition), which should be coming in the mail soon.
I’ll be littering this blog with some tidbits I learn from that book,
and summarizing the key concepts there.</p>
<h2 id="operating-systems">Operating Systems</h2>
<p>You’ve noticed I’ve mentioned operating systems in the section above.
And of course, operating systems are invaluable to us. No one these days
interacts with a computer without an operating system. So of course,
learning about Operating systems should be a high priority – especially
Unix based ones. For that, I’ve picked up a copy of OSTEP (Operating
Systems: Three Easy Pieces) to help aid in learning about virtualization
(the act of taking the physical hardware and making a virtual API to
interact with it, like writing to files, or editing files, spawning
processes), concurrency (the act of turning this single threaded
computer into one that can run multiple processes at once), and
persistence (finally saving our actions to a hard disk, so they won’t be
overwritten on next boot up). Operating systems are considered to be a
hard topic, so I’m looking forward to the challenge! Maybe as a final
project, it would be cool to make a small OS that could support file IO
or do something like that.</p>
<h2 id="compilers">Compilers</h2>
<p>Next up is Compilers, that thing that compiles your code and turns it
into machine language. I don’t know too much about compilers (hey, I’m a
JavaScript(JS) guy, I use an interpreter), but I’ve always been keen on
compilers ever since Babel entered the scene. If you don’t know what
Babel is, you’ll have to know a bit about front-end web development. One
of the pain points of front-end development is that we, as front-end
developers, have to support fairly old browsers, and they support
different features of HTML, CSS, and JS. For example, IE8 supports
HTML4, CSS 2.1 (that means no media queries) and ES3 (the version of
JavaScript that was standardized in 1999…). Currently, Google Chrome
supports HTML5, CSS3, and ES10 (the version of JavaScript that was
standardized in 2019). So of course, we could all painfully write our
ES5 JavaScript to be backwards compatible with IE8, or we could ditch
browser support for IE8 (a lot of firms have), but there’s still a large
user base that uses IE11, so it’s a hard sell to drop support for that.
IE11 supports HTML5, CSS3, and ES5, which is the 2009 standard of
JavaScript. You get the idea. Lots of browsers to target, but to target
them all, we’d have to use some subset of JavaScript from 10 years ago.
Not very fun. Many years ago, a solution named Babel was released – it
takes the JavaScript that you write, and turns it into valid es5
JavaScript code. It’s a compiler for JavaScript, but really, it’s
perhaps the best open source project out there in the JavaScript
ecosystem. And to understand Babel, you have to understand compilers.
Cue the JavaScript music (Babel actually has a theme song, a cover of
Jeff Buckley’s Hallelujah). I’d like to write my own small language too,
preferably in C, so I can understand the nitty gritty of creating a
compiler, and getting closer to the metal, if you will.</p>
<h2 id="c-programming-1">C++ Programming</h2>
<p>Ah, C++. When you program in C++, every problem looks like your
thumb, and every goto leads you to a black hole. I’m kidding, by the
way, I don’t have any experience writing C++, so I can’t tell you much
about the language. It’s also very popular, with uses in pretty much all
industries, but especially in game development. It’s an excellent way to
learn about Object Oriented Programming, something I’m really lacking,
and it has a wide standard library (again, something that JavaScript is
sorely lacking), which handles plenty of use cases, such as
std::vector&lt;T, T&gt; for lists, and std::array&lt;T, T&gt; for
arrays. What more could you ask for?</p>
<h2 id="java-programming">Java Programming</h2>
<p>Java is the best and worst thing that’s happened to programming in
the past 20 years. Any takers on that statement? Steve Yegge said it.
But it’s interesting, you see, because when one refers to Java, it’s
kind of hard to see if someone’s referring to Java or the Java Virtual
Machine(JVM). Java has so many people who live and die by it (in more of
the metaphoric sense), it has so many zealots that swear by it and
nothing else, and become exalted to memetic heights – the old timey
people used to tell me about how Java saved them from environment
dependent variables and worrying about memory management and pointers.
And it’s true that Java, specifically the JVM is amazing at abstracting
away all the stuff that we really shouldn’t be managing anyway, but one
concern is that Java is just such a slow moving language – it was in the
Sun Microsystems days, and it still kind of is in the Oracle Days. But
still, Java is a key language to at least know the basics of, and I
myself still admire how forward thihnking the Sun Microsystems team were
in developing both the JVM and Java. Truly wonderful. A+ Language
indeed.</p>
<h2 id="go-programming">Go Programming</h2>
<p>Golang is the best programming language to come out in the past 10
years. How many takers do I have for that statement? Go reminds of C,
but brought into the 21st century – it has garbage collection (yay!), it
can be run or compiled (the best of both worlds), the compiler can
assume what types you’re using, so you can say <code>x := 5</code>
instead of the slightly more verbose <code>int x = 5;</code>, there are
no semicolons (the compiler adds them at the end of each line for you),
and it has a very small API, with a more modern standard library so that
you can do what you need to, without having to know every nook and
cranny of some arcane language (see: C++, Java, JavaScript). And it has
a cute mascot. That’s the real kicker, to be honest. Java’s mascot, the
Java Duke, looks like its from a 17th century sketchbook. Python doesn’t
have a mascot, just like JavaScript or C. Chalk a win up for the boys
and girls at Google, their marketing is superb.</p>
<h2 id="python-programming">Python Programming</h2>
<p>Python is one of the most loved languages these days – and I will say
without a doubt, that it is an amazing language. Guido really outdid
himself. But one thing I don’t get is why there’s a fork in the
language. Why is there Python2 (which this Mac runs) and Python3 (which
this blogger uses)? And the syntax is a bit different from the usual C
derivative language syntax, but I guess that’s a good thing about
python, it has so many great things about it (such as lambdas from
1994), and comprehensions (everyone’s favorite feature of functional
programming), and a killer ecosystem (I instinctively etch
<code>import numpy as np</code> for almost every .py file I write). And
it’s a scripting language that can automate everything from emails, to
file moving, to web development, to even cars. Why don’t people like
scripting languages more?</p>
<h2 id="data-structures-and-algorithms">Data Structures and
Algorithms</h2>
<p>Data Structures and Algorithms are perhaps the most sought after
concept in interviews, which has led a lot of people to discount the
process entirely, but you know, I don’t blame tech firms for using data
structures and algorithms questions to hire applicants, and here’s why.
Let’s say you want to hire for a back-end software engineer, and your
stack is in python’s django, for example. Almost no one will have prior
python django programming experience, so you have two choices. Either
you hire and test all applicants for python django knowledge (which
could take your team a year to fill those three vacancies on your team)
or you could simply test on concepts that are familiar to backend
development – ask them questions like “what does MVC mean? How would you
handle real time communication needs in an app?”, or even easier, say
you don’t even have to write any code, we’ll test you on ideas. And
that’s really the core of what the Data Structures and Algorithms
technical interview does, it tests some common knowledge among all
developers. So you know, it’s not so bad. To get better at Data
Structures and Algorithms, I’ve got Elements of Programming Interviews
(EPI in Python), Daily Coding Problem, and Algorithms by Skiena all
lined up and ready to go. Hopefully by the end of the year I’ll be a
better problem solver then.</p>
<p>Well, those are the areas I’ll be covering, and maybe documenting
here and there through this blog. Hopefully I’ll be a better software
developer, and maybe I’ve encouraged you to be a better
developer.</p>]]></description>
</item>
</channel></rss>
