# Building self-hosted from the original C++ implementation

**URL:** <https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607>\
**Category:** Help\
**Tags:** compiler\
**Created:** [October 30, 2024, 10:47pm UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607 "2024-10-30T22:47:28Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![motiejus](https://ziggit.dev/user_avatar/ziggit.dev/motiejus/32/3681_2.png) [@motiejus](https://ziggit.dev/u/motiejus)\
**Post date:** [October 30, 2024, 10:47pm UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/1 "2024-10-30T22:47:28Z")

</div>

Context: I am trying to walk Andrew’s steps [in this PR](https://github.com/ziglang/zig/pull/13560) and build a contemporary `zig.wasm` down from the original C++ codebase.

Attempted steps:

1. Build zig from `28514476ef8c824c3d189d98f23d0f8d23e496ea~1` (`bf316e550671cc71eb498b3cf799493627bb0fdc`, i.e. the last commit before `-fstage1` was removed).
2. Copy binary and lib somewhere else: `mkdir ~/dist; cp -r build/zig2 lib ~/dist`
3. Check out to [`db023b98a4deef527d4c70d146009f754e9b168d` build: introduce -Dwasi-bootstrap option](https://github.com/ziglang/zig/pull/13560/commits/db023b98a4deef527d4c70d146009f754e9b168d).
4. `~/dist/zig build -Dwasi-bootstrap`. I expect this to build a `zig.wasm` file, but this panics:

```zig
Semantic Analysis [4879] deleteTreeMinStackSizeWithKindHint... thread 2882 panic: reached unreachable code
/x/zig/lib/std/debug.zig:278:14: 0x563455062cd6 in std.debug.assert (zig2)
    if (!ok) unreachable; // assertion failure
             ^
/x/zig/src/type.zig:2478:37: 0x56345540447c in type.Type.hasRuntimeBitsAdvanced (zig2)
                    .eager => assert(struct_obj.haveFieldTypes()),
                                    ^
/x/zig/src/type.zig:2695:38: 0x56345542b12d in type.Type.hasRuntimeBitsIgnoreComptime (zig2)
        return hasRuntimeBitsAdvanced(ty, true, .eager) catch unreachable;
                                     ^
/x/zig/src/codegen/llvm.zig:3190:57: 0x5634556d8b5a in codegen.llvm.DeclGen.lowerPtrElemTy (zig2)
            else => elem_ty.hasRuntimeBitsIgnoreComptime(),
                                                        ^
/x/zig/src/codegen/llvm.zig:2781:59: 0x563455445723 in codegen.llvm.DeclGen.lowerTypeInner (zig2)
                const llvm_elem_ty = try dg.lowerPtrElemTy(ptr_info.pointee_type);
                                                          ^
/x/zig/src/codegen/llvm.zig:2722:43: 0x56345543f431 in codegen.llvm.DeclGen.lowerType (zig2)
        const llvm_ty = try lowerTypeInner(dg, t);
                                          ^
/x/zig/src/codegen/llvm.zig:2771:41: 0x56345544550d in codegen.llvm.DeclGen.lowerTypeInner (zig2)
                        try dg.lowerType(ptr_type),
                                        ^
/x/zig/src/codegen/llvm.zig:2722:43: 0x56345543f431 in codegen.llvm.DeclGen.lowerType (zig2)
        const llvm_ty = try lowerTypeInner(dg, t);
                                          ^
/x/zig/src/codegen/llvm.zig:2985:59: 0x5634554472d3 in codegen.llvm.DeclGen.lowerTypeInner (zig2)
                    const field_llvm_ty = try dg.lowerType(field.ty);
                                                          ^
/x/zig/src/codegen/llvm.zig:2722:43: 0x56345543f431 in codegen.llvm.DeclGen.lowerType (zig2)
        const llvm_ty = try lowerTypeInner(dg, t);
                                          ^
/x/zig/src/codegen/llvm.zig:2985:59: 0x5634554472d3 in codegen.llvm.DeclGen.lowerTypeInner (zig2)
                    const field_llvm_ty = try dg.lowerType(field.ty);
                                                          ^
/x/zig/src/codegen/llvm.zig:2722:43: 0x56345543f431 in codegen.llvm.DeclGen.lowerType (zig2)
        const llvm_ty = try lowerTypeInner(dg, t);
                                          ^
/x/zig/src/codegen/llvm.zig:3193:29: 0x5634556d8bc4 in codegen.llvm.DeclGen.lowerPtrElemTy (zig2)
            try dg.lowerType(elem_ty)
                            ^
/x/zig/src/codegen/llvm.zig:2781:59: 0x563455445723 in codegen.llvm.DeclGen.lowerTypeInner (zig2)
                const llvm_elem_ty = try dg.lowerPtrElemTy(ptr_info.pointee_type);
                                                          ^
/x/zig/src/codegen/llvm.zig:2722:43: 0x56345543f431 in codegen.llvm.DeclGen.lowerType (zig2)
        const llvm_ty = try lowerTypeInner(dg, t);
                                          ^
/x/zig/src/codegen/llvm.zig:5930:45: 0x56345589f607 in codegen.llvm.FuncGen.airFieldParentPtr (zig2)
        const res_ty = try self.dg.lowerType(self.air.getRefType(ty_pl.ty));
                                            ^
/x/zig/src/codegen/llvm.zig:4633:64: 0x56345586a21b in codegen.llvm.FuncGen.genBody (zig2)
                .field_parent_ptr => try self.airFieldParentPtr(inst),
                                                               ^
/x/zig/src/codegen/llvm.zig:5474:29: 0x563455884af6 in codegen.llvm.FuncGen.airSwitchBr (zig2)
            try self.genBody(case_body);
                            ^
/x/zig/src/codegen/llvm.zig:4555:56: 0x563455867fed in codegen.llvm.FuncGen.genBody (zig2)
                .switch_br => try self.airSwitchBr(inst),
                                                       ^
/x/zig/src/codegen/llvm.zig:1208:19: 0x563455863038 in codegen.llvm.Object.updateFunc (zig2)
        fg.genBody(air.getMainBody()) catch |err| switch (err) {
                  ^
/x/zig/src/link/Wasm.zig:876:74: 0x5634555c53d7 in link.Wasm.updateFunc (zig2)
    }
                                                                         ^
/x/zig/src/link.zig:566:77: 0x5634553921d5 in link.File.updateFunc (zig2)
            .plan9 => return @fieldParentPtr(Plan9, "base", base).updateFunc(module, func, air, liveness),
                                                                            ^
/x/zig/src/Module.zig:4385:37: 0x563455371e41 in Module.ensureFuncBodyAnalyzed (zig2)
            comp.bin_file.updateFunc(mod, func, air, liveness) catch |err| switch (err) {
                                    ^
/x/zig/src/Compilation.zig:3154:42: 0x56345521fcc3 in Compilation.processOneJob (zig2)
                    const fwd_decl = &decl_emit_h.fwd_decl;
                                         ^
/x/zig/src/Compilation.zig:3092:30: 0x56345520d01f in Compilation.performAllTheWork (zig2)
                .outdated => unreachable,
                             ^
/x/zig/src/Compilation.zig:2401:31: 0x563455205387 in Compilation.update (zig2)
            const decl = module.declPtr(decl_index);
                              ^
/x/zig/src/main.zig:3376:20: 0x5634551935af in main.updateModule (zig2)
    defer errors.deinit(comp.gpa);
                   ^
/x/zig/src/main.zig:3043:17: 0x5634550da3a1 in main.buildOutputType (zig2)
    };
                ^
/x/zig/src/main.zig:230:31: 0x5634550710ab in main.mainArgs (zig2)

                              ^
/x/zig/src/stage1.zig:56:24: 0x563455070a05 in main (zig2)
        stage2.mainArgs(gpa, arena, args) catch unreachable;
                       ^
error: zig...
error: The following command terminated unexpectedly:
/x/zig/build/dist/zig build-exe --stack 33554432 /x/zig/src/main.zig -OReleaseSmall --cache-dir /x/zig/zig-cache --global-cache-dir /root/.cache/zig --name zig -target wasm32-wasi -mcpu generic --pkg-begin build_options /x/zig/zig-cache/options/jivNPNwbviGnCnscXAfCJDcbRqydjv3fwLQrouIYsELM7P7rVuhILPn0WH6mZ9HL --pkg-end -fno-build-id --enable-cache
error: the following build command failed with exit code 6:
/x/zig/zig-cache/o/3ea3dbe97768319770e9733a3257a50a/build /x/zig/build/dist/zig /x/zig /x/zig/zig-cache /root/.cache/zig -Dwasi-bootstrap

```

I also attempted to build `zig.c` from `28514476ef8c824c3d189d98f23d0f8d23e496ea` (the commit that removes `-fstage1`), but yielded a quite clearly bogus `zig.c`, so I guess that wasn’t a thing back then.

Any pointers how to proceed from `db023b98a4deef527d4c70d146009f754e9b168d` `build: introduce -Dwasi-bootstrap option`?

---

<div class="post-metadata">

**Author:** ![andrewrk](https://ziggit.dev/user_avatar/ziggit.dev/andrewrk/32/7011_2.png) [@andrewrk](https://ziggit.dev/u/andrewrk)\
**Post date:** [October 31, 2024, 1:58am UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/2 "2024-10-31T01:58:23Z")

</div>

The last thing I did in that branch before merging it was build a fresh zig1.wasm with the latest tip of the branch, so the commit order is not necessarily correct there for the purposes of reproducing.

You probably need one of the other fixes from the branch in order to avoid tripping that bug, particularly the one in Sema.zig that adds the line:

```zig
try sema.queueFullTypeResolution(result_ptr);

```

This is the case for many of the branches if you are trying to create a bootstrap chain. You might need to solve a little puzzle in each branch to figure out how to rebuild zig1.wasm.

For the real world purposes of bootstrapping, the best solution is for a third party to implement a zig interpreter that assumes `-target wasm32-wasi` and uses `pub const dev = .bootstrap;` in the config options in order to produce zig2.c and continue the build from there. This interpreter could be written in Lua or Lisp for example, and only needs to be able to interpret exactly the latest tagged release of Zig. Any tricky one-off functions could be hacked around in this interpreter since it is a bespoke interpreter for this one codebase. Such hacks would not compromise the goal of the interpreter, which is to ensure that zig1.wasm has no hidden logic.

---

<div class="post-metadata">

**Author:** ![motiejus](https://ziggit.dev/user_avatar/ziggit.dev/motiejus/32/3681_2.png) [@motiejus](https://ziggit.dev/u/motiejus)\
**Post date:** [October 31, 2024, 7:55am UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/3 "2024-10-31T07:55:50Z")

</div>

> [@andrewrk](#):
>
> For the real world purposes of bootstrapping, the best solution is for a third party to implement a zig interpreter that assumes `-target wasm32-wasi` and uses `pub const dev = .bootstrap;` in the config options in order to produce zig2.c and continue the build from there.

I agree this would be the ideal scenario for easy bootstrapping. However, that entails _writing an interpreter_, which is more than a few early mornings worth of work.

My goal is to write a script that massages zig repository and creates `zig1.wasm` from source-only (or using artifacts that it built during the process) _without writing an interpreter_. Then anyone can run it and confirm that the hash matches whatever is in whatever version they are interested at.

> [@andrewrk](#):
>
> This is the case for many of the branches if you are trying to create a bootstrap chain. You might need to solve a little puzzle in each branch to figure out how to rebuild zig1.wasm.

It’s good to know the commit order is not necessarily correct, thank you for the tip. I will now attempt at solving the puzzle. 🙂

---

<div class="post-metadata">

**Author:** ![mlugg](https://ziggit.dev/user_avatar/ziggit.dev/mlugg/32/437_2.png) [@mlugg](https://ziggit.dev/u/mlugg)\
**Post date:** [November 3, 2024, 6:04am UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/4 "2024-11-03T06:04:48Z")

</div>

This is an interesting little project, good luck getting it working! I don’t envy you; `zig1.wasm` updates can sometimes be quite tricky to get right even on our end, most often because the compiler depends on `std.builtin` both when building the compiler and when using the compiler, so breaking changes to `std.builtin` often need to be done in slightly complicated ways (such as my recent changes to `std.builtin.CallingConvention`; [this commit](https://github.com/ziglang/zig/pull/21697/commits/51706af908e0c6acb822ef36760b7fe31faf62a6) explains what I had to do there). That said, I suppose that _shouldn’t_ impact you too much. So long as we’ve not done _too_ much nasty stuff before, like requiring a specific intermediate commit to build a new `zig1.wasm`, or reordering commits to perform a `zig1.wasm` update “before” the corresponding changes, or even just running `update-zig1` with uncommitted changes… so long as we’ve not committed too many of those sins, hopefully the commit history can get you most of the way there?

Feel free to ping me here if you have questions about any specific `zig1.wasm` update in the history which is causing you trouble.

---

<div class="post-metadata">

**Author:** ![motiejus](https://ziggit.dev/user_avatar/ziggit.dev/motiejus/32/3681_2.png) [@motiejus](https://ziggit.dev/u/motiejus)\
**Post date:** [November 3, 2024, 11:12am UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/5 "2024-11-03T11:12:54Z")

</div>

> [@mlugg](#):
>
> This is an interesting little project, good luck getting it working! I don’t envy you; `zig1.wasm` updates can sometimes be quite tricky to get right even on our end, most often because the compiler depends on `std.builtin` both when building the compiler and when using the compiler, so breaking changes to `std.builtin` often need to be done in slightly complicated ways (such as my recent changes to `std.builtin.CallingConvention`; [this commit](https://github.com/ziglang/zig/pull/21697/commits/51706af908e0c6acb822ef36760b7fe31faf62a6) explains what I had to do there). That said, I suppose that _shouldn’t_ impact you too much. So long as we’ve not done _too_ much nasty stuff before, like requiring a specific intermediate commit to build a new `zig1.wasm`, or reordering commits to perform a `zig1.wasm` update “before” the corresponding changes, or even just running `update-zig1` with uncommitted changes… so long as we’ve not committed too many of those sins, hopefully the commit history can get you most of the way there?

I was able to build the first one `zig1.wasm.zst` quite easily (will post the script later after cleanup). And yes, I got the sense that building `zig1.wasm` is/was a free reign, assuming the end result is correct. 🙂

> [@mlugg](#):
>
> Feel free to ping me here if you have questions about any specific `zig1.wasm` update in the history which is causing you trouble.

Your offer for help is spot-on! 😃 I feel/hope that after being guided through a few of those incompatibilities, I will be able to proceed myself.

The first issue updating `zig1.wasm` is [Eliminate `BoundFn` type from the language](https://github.com/ziglang/zig/commit/9d93b2ccf11f584320a2c5209dd2d94705167695). Excerpt from the build log:

```zig
motiejus@3b3ad0b7b0ab:/x/zig$ build/stage3/bin/zig build                                                                                                                                                            
src/Sema.zig:21970:5: error: switch must handle all possibilities                                                                                                                                                   
    switch (ty.zigTypeTag()) {                                                                                                                                                                                      
    ^ ~~~~~                                                                                                                                                                                                          
build/stage3/lib/zig/std/builtin.zig:213:5: note: unhandled enumeration value: 'BoundFn'                                                                                                                            
    BoundFn: Fn,                                                                                                                                                                                                    
    ^ ~~~~~~~~~~                                                                                                                                                                                                     
build/stage3/lib/zig/std/builtin.zig:193:18: note: enum '@typeInfo(builtin.Type).Union.tag_type.?' declared here                                                                                                    
pub const Type = union(enum) {                                                                                                                                                                                      
                 ^ ~~~~                                                                                                                                                                                              
referenced by:                                                                                                                                                                                                      
    analyzeExport: src/Sema.zig:5460:18                                                                                                                                                                             
    semaDecl: src/Module.zig:4727:25                                                                                                                                                                                
    remaining reference traces hidden; use '-freference-trace' to see all reference traces                                                                                                                          

```

And this is exactly what happens here: `BoundFn` was removed from the builtins, but the `zig1.wasm`, with which I am trying to build a new one, still has it.

@mlugg open for tips.

---

<div class="post-metadata">

**Author:** ![mlugg](https://ziggit.dev/user_avatar/ziggit.dev/mlugg/32/437_2.png) [@mlugg](https://ziggit.dev/u/mlugg)\
**Post date:** [November 3, 2024, 11:27am UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/6 "2024-11-03T11:27:19Z")

</div>

Oh, this one’s easy – you just need to pass `--zig-lib-dir lib` here. This is nothing to do with what’s in your `zig1.wasm`, since there’s nothing particularly special about the standard library, we’re always just treating it like normal source code, so if you’re not _using_ `zig1`, there aren’t any traces of it left in the compiler you _are_ using! The error message shows the `BoundFn: BoundFn` field existing in `build/stage3/lib`, which is the case because that’s an outdated `lib` directory. So, just pass it `--zig-lib-dir lib` to use the up-to-date `lib` directory (i.e. as of this commit) in the repo root.

You’ll probably need to pass `--zig-lib-dir` like that more often than not; I’d suggest treating it as your default strategy.

---

<div class="post-metadata">

**Author:** ![motiejus](https://ziggit.dev/user_avatar/ziggit.dev/motiejus/32/3681_2.png) [@motiejus](https://ziggit.dev/u/motiejus)\
**Post date:** [November 3, 2024, 5:19pm UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/7 "2024-11-03T17:19:43Z")

</div>

> [@mlugg](#):
>
> You’ll probably need to pass `--zig-lib-dir` like that more often than not; I’d suggest treating it as your default strategy.

Thanks. That was my default (and the only) strategy. 😃 I got a different compiler error, which looked similar enough, so I didn’t report that. Here we go:

```zig
$ build/stage3/bin/zig build --zig-lib-dir $PWD/lib
thread 49 panic: attempt to use null value
Analyzing /x/zig/lib/std/log.zig: log.zig:scoped
      %430 = enum_literal("EnumLiteral") 
    > %431 = extended(reify(%430)) 
      %432 = break_inline(%433, %431)
    For full context, use the command
      zig ast-check -t /x/zig/lib/std/log.zig

  in /x/zig/lib/std/log.zig: log.zig:scoped
    > %433 = param_comptime("scope", {%430..%432}) 
  in /x/zig/lib/std/log.zig: log.zig:default
    > %548 = decl_val("scoped") 
  in /x/zig/lib/std/log.zig: log.zig:warn
    > %559 = decl_val("default") 
  in /x/zig/lib/std/build.zig: build.zig:Builder.addUserInputOption
    > %5774 = field_call_bind(%5772, "warn") 
  in /x/zig/lib/std/build.zig: build.zig:Builder.addUserInputOption
    > %5769 = block({%5770..%5786}) 
  in /x/zig/lib/std/build.zig: build.zig:Builder.addUserInputOption
    > %5616 = switch_block(%5613,
        %5619 => {%5617..%5706},
        %5709 => {%5707..%5765},
        %5767 => {%5768..%5789}) 
  in /x/zig/lib/std/build.zig: build.zig:Builder.addUserInputOption
    > %5526 = block({%5527..%5796}) 
  in /x/zig/lib/build_runner.zig: build_runner.zig:main
    > %496 = try(%493, {%497..%502}) 
  in /x/zig/lib/build_runner.zig: build_runner.zig:main
    > %505 = block({%490..%504}) 
  in /x/zig/lib/build_runner.zig: build_runner.zig:main
    > %476 = block({%477..%528}) 
  in /x/zig/lib/build_runner.zig: build_runner.zig:main
    > %471 = condbr(%470, {%473..%573}, {%530..%574}) 
  in /x/zig/lib/build_runner.zig: build_runner.zig:main
    > %472 = block({%461..%471}) 
  in /x/zig/lib/build_runner.zig: build_runner.zig:main
    > %410 = block({%411..%578}) 
  in /x/zig/lib/build_runner.zig: build_runner.zig:main
    > %407 = condbr(%406, {%409..%2286}, {%580..%2287}) 
  in /x/zig/lib/build_runner.zig: build_runner.zig:main
    > %408 = block({%397..%407}) 
  in /x/zig/lib/build_runner.zig: build_runner.zig:main
    > %394 = block({%395..%2291}) 
  in /x/zig/lib/build_runner.zig: build_runner.zig:main
    > %388 = block({%393..%2292}) 
  in /x/zig/lib/build_runner.zig: build_runner.zig:main
    > %385 = condbr(%384, {%390..%2293}, {%2294}) 
  in /x/zig/lib/build_runner.zig: build_runner.zig:main
    > %386 = block({%377..%385}) 
  in /x/zig/lib/build_runner.zig: build_runner.zig:main
    > %376 = loop({%386, %389}) 
  in /x/zig/lib/build_runner.zig: build_runner.zig:main
    > %41 = block({%42..%2434}) 
  in /x/zig/lib/std/start.zig: start.zig:callMain
    > %3051 = is_non_err(%3050) 
  in /x/zig/lib/std/start.zig: start.zig:callMain
    > %3053 = block({%3046..%3052}) 
  in /x/zig/lib/std/start.zig: start.zig:callMain
    > %3043 = block({%3044..%3184}) 
  in /x/zig/lib/std/start.zig: start.zig:callMain
    > %2953 = switch_block(%2950,
        else => {%3187..%3190},
        %2955 => {%2956..%2969},
        %2971 => {%2972..%2989},
        %2992 => {%2990..%3039},
        %3041 => {%3042..%3186}) 
  in /x/zig/lib/std/start.zig: start.zig:callMain
    > %2937 = block({%2938..%3195}) 
  in /x/zig/lib/std/start.zig: start.zig:initEventLoopAndCallMain
    > %2657 = builtin_call(%2655, %2656, @Zir.Inst.Ref.empty_struct) 
  in /x/zig/lib/std/start.zig: start.zig:initEventLoopAndCallMain
    > %2501 = block({%2502..%2662}) 
  in /x/zig/lib/std/start.zig: start.zig:callMainWithArgs
    > %2288 = call(.auto, %2286, []) 
  in /x/zig/lib/std/start.zig: start.zig:callMainWithArgs
    > %2257 = block({%2258..%2293}) 
  in /x/zig/lib/std/start.zig: start.zig:posixCallMainAndExit
    > %2122 = builtin_call(%2119, %2120, %2121) 
  in /x/zig/lib/std/start.zig: start.zig:posixCallMainAndExit
    > %2114 = call(nodiscard .auto, %2112, [
        {%2115..%2123},
      ]) 
  in /x/zig/lib/std/start.zig: start.zig:posixCallMainAndExit
    > %1750 = block({%1751..%2126}) 

/x/zig/src/Sema.zig:17957:65: 0xf6ca46 in zirReify (zig)
            const child_ty = child_val.toType(&buffer);
                                                                ^
/x/zig/src/Sema.zig:1147:64: 0xca021b in analyzeBodyInner (zig)
                    .reify => try sema.zirReify( block, extended, inst),
                                                               ^
/x/zig/src/Sema.zig:815:45: 0xaceaa1 in analyzeBodyBreak (zig)
    const break_inst = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                                            ^
/x/zig/src/Sema.zig:765:50: 0x12f1f73 in resolveBody (zig)
    const break_data = (try sema.analyzeBodyBreak(block, body)) orelse
                                                 ^
/x/zig/src/Sema.zig:8778:33: 0xf84061 in zirParam (zig)
            if (sema.resolveBody(block, body, inst)) |param_ty_inst| {
                                ^
/x/zig/src/Sema.zig:1321:34: 0xca274a in analyzeBodyInner (zig)
                try sema.zirParam(block, inst, true);
                                 ^
/x/zig/src/Sema.zig:815:45: 0xaceaa1 in analyzeBodyBreak (zig)
    const break_inst = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                                            ^
/x/zig/src/Module.zig:4635:50: 0xacabaf in semaDecl (zig)
    const result_ref = (try sema.analyzeBodyBreak(&block_scope, body)).?.operand;
                                                 ^
/x/zig/src/Module.zig:4256:38: 0x948079 in ensureDeclAnalyzed (zig)
    const type_changed = mod.semaDecl(decl_index) catch |err| switch (err) {
                                     ^
/x/zig/src/Sema.zig:27544:32: 0x133c832 in ensureDeclAnalyzed (zig)
        } else {
                               ^
/x/zig/src/Sema.zig:27586:32: 0xfac831 in analyzeDeclRef (zig)
    return sema.addConstant(
                               ^
/x/zig/src/Sema.zig:27514:45: 0x1305404 in analyzeDeclVal (zig)
    decl_index: Decl.Index,
                                            ^
/x/zig/src/Sema.zig:5729:31: 0xecb146 in zirDeclVal (zig)
    return sema.analyzeDeclVal(block, src, decl);
                              ^
/x/zig/src/Sema.zig:926:65: 0xc95551 in analyzeBodyInner (zig)
            .decl_val => try sema.zirDeclVal(block, inst),
                                                                ^
/x/zig/src/Sema.zig:815:45: 0xaceaa1 in analyzeBodyBreak (zig)
    const break_inst = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                                            ^
/x/zig/src/Module.zig:4635:50: 0xacabaf in semaDecl (zig)
    const result_ref = (try sema.analyzeBodyBreak(&block_scope, body)).?.operand;
                                                 ^
/x/zig/src/Module.zig:4256:38: 0x948079 in ensureDeclAnalyzed (zig)
    const type_changed = mod.semaDecl(decl_index) catch |err| switch (err) {
                                     ^
/x/zig/src/Sema.zig:27544:32: 0x133c832 in ensureDeclAnalyzed (zig)
        } else {
                               ^
/x/zig/src/Sema.zig:27586:32: 0xfac831 in analyzeDeclRef (zig)
    return sema.addConstant(
                               ^
/x/zig/src/Sema.zig:27514:45: 0x1305404 in analyzeDeclVal (zig)
    decl_index: Decl.Index,
                                            ^
/x/zig/src/Sema.zig:5729:31: 0xecb146 in zirDeclVal (zig)
    return sema.analyzeDeclVal(block, src, decl);
                              ^
/x/zig/src/Sema.zig:926:65: 0xc95551 in analyzeBodyInner (zig)
            .decl_val => try sema.zirDeclVal(block, inst),
                                                                ^
/x/zig/src/Sema.zig:815:45: 0xaceaa1 in analyzeBodyBreak (zig)
    const break_inst = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                                            ^
/x/zig/src/Module.zig:4635:50: 0xacabaf in semaDecl (zig)
    const result_ref = (try sema.analyzeBodyBreak(&block_scope, body)).?.operand;
                                                 ^
/x/zig/src/Module.zig:4256:38: 0x948079 in ensureDeclAnalyzed (zig)
    const type_changed = mod.semaDecl(decl_index) catch |err| switch (err) {
                                     ^
/x/zig/src/Sema.zig:27544:32: 0x133c832 in ensureDeclAnalyzed (zig)
        } else {
                               ^
/x/zig/src/Sema.zig:27586:32: 0xfac831 in analyzeDeclRef (zig)
    return sema.addConstant(
                               ^
/x/zig/src/Sema.zig:27514:45: 0x1305404 in analyzeDeclVal (zig)
    decl_index: Decl.Index,
                                            ^
/x/zig/src/Sema.zig:23164:35: 0x165753a in namespaceLookupVal (zig)

                                  ^
/x/zig/src/Sema.zig:22678:56: 0x1308e6f in fieldVal (zig)
                    return sema.failWithOwnedErrorMsg(msg);
                                                       ^
/x/zig/src/Sema.zig:22997:37: 0x130aa55 in fieldCallBind (zig)
                        decl_type.fnParamLen() >= 1)
                                    ^
/x/zig/src/Sema.zig:9007:30: 0xed1517 in zirFieldCallBind (zig)
    return sema.fieldCallBind(block, src, object_ptr, field_name, field_name_src);
                             ^
/x/zig/src/Sema.zig:948:71: 0xc9686e in analyzeBodyInner (zig)
            .field_call_bind => try sema.zirFieldCallBind(block, inst),
                                                                      ^
/x/zig/src/Sema.zig:5240:34: 0x1336a09 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/x/zig/src/Sema.zig:5223:85: 0xf894cc in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                                                                    ^
/x/zig/src/Sema.zig:1449:69: 0xca40e1 in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirBlock(block, inst);
                                                                    ^
/x/zig/src/Sema.zig:779:30: 0x1331e4b in analyzeBodyRuntimeBreak (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/x/zig/src/Sema.zig:10567:45: 0xeea8fc in zirSwitchBlock (zig)

                                            ^
/x/zig/src/Sema.zig:981:69: 0xc9852b in analyzeBodyInner (zig)
            .switch_block => try sema.zirSwitchBlock(block, inst),
                                                                    ^
/x/zig/src/Sema.zig:5240:34: 0x1336a09 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/x/zig/src/Sema.zig:5223:85: 0xf894cc in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                                                                    ^
/x/zig/src/Sema.zig:1449:69: 0xca40e1 in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirBlock(block, inst);
                                                                    ^
/x/zig/src/Sema.zig:798:30: 0xe7ade8 in analyzeBody (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/x/zig/src/Module.zig:5659:43: 0xc76eca in analyzeFnBody (zig)
    sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) {
                                          ^
/x/zig/src/Module.zig:4342:40: 0xaae07d in ensureFuncBodyAnalyzed (zig)
            var air = mod.analyzeFnBody(func, sema_arena) catch |err| switch (err) {
                                       ^
/x/zig/src/Sema.zig:27555:36: 0x13c4827 in ensureFuncBodyAnalyzed (zig)
        try ty.copy(anon_decl.arena()),
                                   ^
/x/zig/src/Sema.zig:29908:44: 0xfc1fa9 in resolveInferredErrorSet (zig)
    }
                                           ^
/x/zig/src/Sema.zig:27834:49: 0xf8dc11 in analyzeIsNonErrComptimeOnly (zig)
        } else {
                                                ^
/x/zig/src/Sema.zig:16392:60: 0xf8cc0d in zirTry (zig)
        // no breaks from the body possible, and that the body is noreturn.
                                                           ^
/x/zig/src/Sema.zig:1603:67: 0xca6b43 in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirTry(block, inst);
                                                                  ^
/x/zig/src/Sema.zig:5240:34: 0x1336a09 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/x/zig/src/Sema.zig:5223:85: 0xf894cc in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                                                                    ^
/x/zig/src/Sema.zig:1449:69: 0xca40e1 in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirBlock(block, inst);
                                                                    ^
/x/zig/src/Sema.zig:5240:34: 0x1336a09 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/x/zig/src/Sema.zig:5223:85: 0xf894cc in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                                                                    ^
/x/zig/src/Sema.zig:1449:69: 0xca40e1 in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirBlock(block, inst);
                                                                    ^
/x/zig/src/Sema.zig:779:30: 0x1331e4b in analyzeBodyRuntimeBreak (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/x/zig/src/Sema.zig:16341:37: 0xf8bb31 in zirCondbr (zig)

                                    ^
/x/zig/src/Sema.zig:1557:61: 0xca5577 in analyzeBodyInner (zig)
                if (!block.is_comptime) break sema.zirCondbr(block, inst);
                                                            ^
/x/zig/src/Sema.zig:5240:34: 0x1336a09 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/x/zig/src/Sema.zig:5223:85: 0xf894cc in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                                                                    ^
/x/zig/src/Sema.zig:1449:69: 0xca40e1 in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirBlock(block, inst);
                                                                    ^
/x/zig/src/Sema.zig:5240:34: 0x1336a09 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/x/zig/src/Sema.zig:5223:85: 0xf894cc in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                                                                    ^
/x/zig/src/Sema.zig:1449:69: 0xca40e1 in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirBlock(block, inst);
                                                                    ^
/x/zig/src/Sema.zig:779:30: 0x1331e4b in analyzeBodyRuntimeBreak (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/x/zig/src/Sema.zig:16341:37: 0xf8bb31 in zirCondbr (zig)

                                    ^
/x/zig/src/Sema.zig:1557:61: 0xca5577 in analyzeBodyInner (zig)
                if (!block.is_comptime) break sema.zirCondbr(block, inst);
                                                            ^
/x/zig/src/Sema.zig:5240:34: 0x1336a09 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/x/zig/src/Sema.zig:5223:85: 0xf894cc in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                                                                    ^
/x/zig/src/Sema.zig:1449:69: 0xca40e1 in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirBlock(block, inst);
                                                                    ^
/x/zig/src/Sema.zig:5240:34: 0x1336a09 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/x/zig/src/Sema.zig:5223:85: 0xf894cc in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                                                                    ^
/x/zig/src/Sema.zig:1449:69: 0xca40e1 in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirBlock(block, inst);
                                                                    ^
/x/zig/src/Sema.zig:5240:34: 0x1336a09 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/x/zig/src/Sema.zig:5223:85: 0xf894cc in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                                                                    ^
/x/zig/src/Sema.zig:1449:69: 0xca40e1 in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirBlock(block, inst);
                                                                    ^
/x/zig/src/Sema.zig:779:30: 0x1331e4b in analyzeBodyRuntimeBreak (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/x/zig/src/Sema.zig:16341:37: 0xf8bb31 in zirCondbr (zig)

                                    ^
/x/zig/src/Sema.zig:1557:61: 0xca5577 in analyzeBodyInner (zig)
                if (!block.is_comptime) break sema.zirCondbr(block, inst);
                                                            ^
/x/zig/src/Sema.zig:5240:34: 0x1336a09 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/x/zig/src/Sema.zig:5223:85: 0xf894cc in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                                                                    ^
/x/zig/src/Sema.zig:1449:69: 0xca40e1 in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirBlock(block, inst);
                                                                    ^
/x/zig/src/Sema.zig:798:30: 0xe7ade8 in analyzeBody (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/x/zig/src/Sema.zig:5065:25: 0xf88908 in zirLoop (zig)
    try sema.analyzeBody(&loop_block, body);
                        ^
/x/zig/src/Sema.zig:1435:68: 0xca3b60 in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirLoop(block, inst);
                                                                   ^
/x/zig/src/Sema.zig:5240:34: 0x1336a09 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/x/zig/src/Sema.zig:5223:85: 0xf894cc in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                                                                    ^
/x/zig/src/Sema.zig:1449:69: 0xca40e1 in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirBlock(block, inst);
                                                                    ^
/x/zig/src/Sema.zig:798:30: 0xe7ade8 in analyzeBody (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/x/zig/src/Module.zig:5659:43: 0xc76eca in analyzeFnBody (zig)
    sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) {
                                          ^
/x/zig/src/Module.zig:4342:40: 0xaae07d in ensureFuncBodyAnalyzed (zig)
            var air = mod.analyzeFnBody(func, sema_arena) catch |err| switch (err) {
                                       ^
/x/zig/src/Sema.zig:27555:36: 0x13c4827 in ensureFuncBodyAnalyzed (zig)
        try ty.copy(anon_decl.arena()),
                                   ^
/x/zig/src/Sema.zig:29908:44: 0xfc1fa9 in resolveInferredErrorSet (zig)
    }
                                           ^
/x/zig/src/Sema.zig:27834:49: 0xf8dc11 in analyzeIsNonErrComptimeOnly (zig)
        } else {
                                                ^
/x/zig/src/Sema.zig:27861:56: 0x13123bc in analyzeIsNonErr (zig)
) CompileError!Air.Inst.Ref {
                                                       ^
/x/zig/src/Sema.zig:16290:53: 0xed6e5b in zirIsNonErr (zig)
    const inst_data = sema.code.instructions.items(.data)[inst].un_node;
                                                    ^
/x/zig/src/Sema.zig:959:66: 0xc97201 in analyzeBodyInner (zig)
            .is_non_err => try sema.zirIsNonErr(block, inst),
                                                                 ^
/x/zig/src/Sema.zig:5240:34: 0x1336a09 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/x/zig/src/Sema.zig:5223:85: 0xf894cc in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                                                                    ^
/x/zig/src/Sema.zig:1449:69: 0xca40e1 in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirBlock(block, inst);
                                                                    ^
/x/zig/src/Sema.zig:5240:34: 0x1336a09 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/x/zig/src/Sema.zig:5223:85: 0xf894cc in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                                                                    ^
/x/zig/src/Sema.zig:1449:69: 0xca40e1 in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirBlock(block, inst);
                                                                    ^
/x/zig/src/Sema.zig:5240:34: 0x1336a09 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/x/zig/src/Sema.zig:10434:49: 0xee769a in zirSwitchBlock (zig)
        {
                                                ^
/x/zig/src/Sema.zig:981:69: 0xc9852b in analyzeBodyInner (zig)
            .switch_block => try sema.zirSwitchBlock(block, inst),
                                                                    ^
/x/zig/src/Sema.zig:5240:34: 0x1336a09 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/x/zig/src/Sema.zig:5223:85: 0xf894cc in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                                                                    ^
/x/zig/src/Sema.zig:1449:69: 0xca40e1 in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirBlock(block, inst);
                                                                    ^
/x/zig/src/Sema.zig:798:30: 0xe7ade8 in analyzeBody (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/x/zig/src/Sema.zig:6597:55: 0x12fb37f in analyzeCall (zig)
                sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) {
                                                      ^
/x/zig/src/Sema.zig:20881:28: 0xf292b1 in zirBuiltinCall (zig)
    const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
                           ^
/x/zig/src/Sema.zig:1038:69: 0xc9b6fc in analyzeBodyInner (zig)
            .builtin_call => try sema.zirBuiltinCall(block, inst),
                                                                    ^
/x/zig/src/Sema.zig:5240:34: 0x1336a09 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/x/zig/src/Sema.zig:5223:85: 0xf894cc in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                                                                    ^
/x/zig/src/Sema.zig:1449:69: 0xca40e1 in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirBlock(block, inst);
                                                                    ^
/x/zig/src/Sema.zig:798:30: 0xe7ade8 in analyzeBody (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/x/zig/src/Sema.zig:6597:55: 0x12fb37f in analyzeCall (zig)
                sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) {
                                                      ^
/x/zig/src/Sema.zig:6145:32: 0xec6817 in zirCall (zig)
        return sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src);
                               ^
/x/zig/src/Sema.zig:916:62: 0xc94c28 in analyzeBodyInner (zig)
            .call => try sema.zirCall(block, inst),
                                                             ^
/x/zig/src/Sema.zig:5240:34: 0x1336a09 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/x/zig/src/Sema.zig:5223:85: 0xf894cc in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                                                                    ^
/x/zig/src/Sema.zig:1449:69: 0xca40e1 in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirBlock(block, inst);
                                                                    ^
/x/zig/src/Sema.zig:798:30: 0xe7ade8 in analyzeBody (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/x/zig/src/Sema.zig:6597:55: 0x12fb37f in analyzeCall (zig)
                sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) {
                                                      ^
/x/zig/src/Sema.zig:20881:28: 0xf292b1 in zirBuiltinCall (zig)
    const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
                           ^
/x/zig/src/Sema.zig:1038:69: 0xc9b6fc in analyzeBodyInner (zig)
            .builtin_call => try sema.zirBuiltinCall(block, inst),
                                                                    ^
/x/zig/src/Sema.zig:815:45: 0xaceaa1 in analyzeBodyBreak (zig)
    const break_inst = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                                            ^
/x/zig/src/Sema.zig:765:50: 0x12f1f73 in resolveBody (zig)
    const break_data = (try sema.analyzeBodyBreak(block, body)) orelse
                                                 ^
/x/zig/src/Sema.zig:6094:63: 0xec6332 in zirCall (zig)
        const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);
                                                              ^
/x/zig/src/Sema.zig:916:62: 0xc94c28 in analyzeBodyInner (zig)
            .call => try sema.zirCall(block, inst),
                                                             ^
/x/zig/src/Sema.zig:5240:34: 0x1336a09 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/x/zig/src/Sema.zig:5223:85: 0xf894cc in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                                                                    ^
/x/zig/src/Sema.zig:1449:69: 0xca40e1 in analyzeBodyInner (zig)
                if (!block.is_comptime) break :blk try sema.zirBlock(block, inst);
                                                                    ^
/x/zig/src/Sema.zig:798:30: 0xe7ade8 in analyzeBody (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/x/zig/src/Module.zig:5659:43: 0xc76eca in analyzeFnBody (zig)
    sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) {
                                          ^
/x/zig/src/Module.zig:4342:40: 0xaae07d in ensureFuncBodyAnalyzed (zig)
            var air = mod.analyzeFnBody(func, sema_arena) catch |err| switch (err) {
                                       ^
/x/zig/src/Compilation.zig:3098:42: 0xaabbfc in processOneJob (zig)
            module.ensureFuncBodyAnalyzed(func) catch |err| switch (err) {
                                         ^
/x/zig/src/Compilation.zig:3036:30: 0x98c3a4 in performAllTheWork (zig)
            try processOneJob(comp, work_item);
                             ^
/x/zig/src/Compilation.zig:2360:31: 0x987e63 in update (zig)
    try comp.performAllTheWork(main_progress_node);
                              ^
/x/zig/src/main.zig:3423:20: 0x9b661d in updateModule (zig)
    try comp.update();
                   ^
/x/zig/src/main.zig:4027:21: 0x8a0869 in cmdBuild (zig)
        updateModule(gpa, comp, .none) catch |err| switch (err) {
                    ^
/x/zig/src/main.zig:286:24: 0x87253d in mainArgs (zig)
        return cmdBuild(gpa, arena, cmd_args);
                       ^
/x/zig/src/main.zig:199:20: 0x871135 in main (zig)
    return mainArgs(gpa, arena, args);
                   ^
/x/zig/lib/std/start.zig:614:37: 0x873767 in main (zig)
            const result = root.main() catch |err| {
                                    ^

```

Stack trace seems to point [here](https://github.com/ziglang/zig/blob/9d93b2ccf11f584320a2c5209dd2d94705167695/src/Sema.zig#L17957), but the reason/remedy are far from obvious. 🙂

---

<div class="post-metadata">

**Author:** ![mlugg](https://ziggit.dev/user_avatar/ziggit.dev/mlugg/32/437_2.png) [@mlugg](https://ziggit.dev/u/mlugg)\
**Post date:** [November 3, 2024, 6:07pm UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/8 "2024-11-03T18:07:59Z")

</div>

Where did the `stage3` we’re using here come from?

What’s happening here is that since `BoundFn` was removed, the following tags in `std.builtin.Type` had their indices shifted. That mostly doesn’t matter, since the ones after it mostly aren’t exercised by the compiler build process – however, it looks like the build system is doing `@Type(.EnumLiteral)`, and that tag does indeed come after `.BoundFn`.

I don’t think the actual `build-exe` of the compiler will care about that tag being offset, since AFAICT we didn’t do `@Type(.EnumLiteral)` anywhere in the compiler itself in that version (we used the slightly sillier `@TypeOf(.EnumLiteral)` instead). So, if you bypass the build system to get a post-change build of Zig, it’ll probably work. The easiest way to do that is to take your latest `zig1.wasm`, and run a full bootstrap on this commit (with the CMake script), since that has a fixed `build-exe` command for the initial `zig2` build. In general, running the bootstrap process (i.e. `zig1.wasm` → `zig1.c` → `zig1` which produces `zig2.c` → `zig2` which produces `zig3`) is what’s most likely to work when you have issues, because it exercises a much smaller amount of compiler functionality; it bypasses the build system entirely for the initial build, and only builds a quite limited compiler.

So, here’s what I think should work:

- Have a `zig1.wasm` from whenever the last update was before this one
- With this `BoundFn` commit checked out, run the full CMake bootstrap
- With the generated `stage3/bin/zig`, recreate `zig1.wasm`

---

<div class="post-metadata">

**Author:** ![motiejus](https://ziggit.dev/user_avatar/ziggit.dev/motiejus/32/3681_2.png) [@motiejus](https://ziggit.dev/u/motiejus)\
**Post date:** [November 3, 2024, 8:22pm UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/9 "2024-11-03T20:22:05Z")

</div>

Thank you for the explanation. Indeed I needed to do a few, tweaks (not that I could come up with them without your tips!) to the compiler:

```zig
 lib/std/log.zig | 4 ++--
 src/link/strtab.zig | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/std/log.zig b/lib/std/log.zig
index 9ebe85c004..f174946565 100644
--- a/lib/std/log.zig
+++ b/lib/std/log.zig
@@ -121,7 +121,7 @@ else
 
 fn log(
     comptime message_level: Level,
- comptime scope: @Type(.EnumLiteral),
+ comptime scope: @TypeOf(.EnumLiteral),
     comptime format: []const u8,
     args: anytype,
 ) void {
@@ -167,7 +167,7 @@ pub fn defaultLog(
 
 /// Returns a scoped logging namespace that logs all messages using the scope
 /// provided here.
-pub fn scoped(comptime scope: @Type(.EnumLiteral)) type {
+pub fn scoped(comptime scope: @TypeOf(.EnumLiteral)) type {
     return struct {
         /// Log an error message. This log level is intended to be used
         /// when something has gone wrong. This might be recoverable or might
diff --git a/src/link/strtab.zig b/src/link/strtab.zig
index abb58defef..2048aa216e 100644
--- a/src/link/strtab.zig
+++ b/src/link/strtab.zig
@@ -5,7 +5,7 @@ const Allocator = mem.Allocator;
 const StringIndexAdapter = std.hash_map.StringIndexAdapter;
 const StringIndexContext = std.hash_map.StringIndexContext;
 
-pub fn StringTable(comptime log_scope: @Type(.EnumLiteral)) type {
+pub fn StringTable(comptime log_scope: @TypeOf(.EnumLiteral)) type {
     return struct {
         const Self = @This();
 
-- 
2.44.1

```

And now I am past `BoundFn` stage. Thanks!

Onwards!

---

<div class="post-metadata">

**Author:** ![motiejus](https://ziggit.dev/user_avatar/ziggit.dev/motiejus/32/3681_2.png) [@motiejus](https://ziggit.dev/u/motiejus)\
**Post date:** [November 3, 2024, 9:43pm UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/10 "2024-11-03T21:43:37Z")

</div>

I am past `BoundFn` stage, [then another one](https://github.com/ziglang/zig/commit/d10fd78d46), and now ended up here:

```zig
commit 7b2a936173165002105ba5e76bed69654e132fea
Author: Veikka Tuominen <git@vexu.eu>
Date: 2022-12-12T15:32:37+02:00

    remove `stack` option from `@call`

```

If I try to build `zig1.wasm` with full bootstrap (`cmake ..; make -j`), it will fail this way:

```zig
motiejus@7e8111f66616:/x/zig-0.10.0-747-g7b2a936173/build$ make -j$(nproc)
[10%] Built target zig-wasm2c
[50%] Built target zigcpp
[70%] Built target zig1
[75%] Running zig1.wasm to produce /x/zig-0.10.0-747-g7b2a936173/build/zig2.c
lib/std/builtin.zig is corrupt and missing 'CallOptions'Aborted (core dumped)
make[2]: *** [CMakeFiles/zig2.dir/build.make:490: zig2.c] Error 134
make[2]: *** Deleting file 'zig2.c'
make[1]: *** [CMakeFiles/Makefile2:169: CMakeFiles/zig2.dir/all] Error 2
make: *** [Makefile:136: all] Error 2

```

Which makes sense, since, well, `CallOptions` were removed in that commit (as well as completely changed `@call` semantics).

Looking forward to the next tip. 🙂

---

<div class="post-metadata">

**Author:** ![mlugg](https://ziggit.dev/user_avatar/ziggit.dev/mlugg/32/437_2.png) [@mlugg](https://ziggit.dev/u/mlugg)\
**Post date:** [November 5, 2024, 12:54am UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/11 "2024-11-05T00:54:13Z")

</div>

For that one I think you can do the following:

- Check out `7b2a936173165002105ba5e76bed69654e132fea`
- Add the following declaration to `lib/std/builtin.zig`:

```zig
pub const CallOptions = struct {
    modifier: CallModifier = .auto,
    stack: ?[]align(std.Target.stack_align) u8 = null,
};

```

- Update `zig1.wasm`
- All done (you can revert the change)

The trick here is that since a type was _removed_ rather than _changed_, you can just include both declarations in `std.builtin` when building the compiler here. You want `7b2a936173165002105ba5e76bed69654e132fea` rather than `08b2d491bcd8c79c68495267cc71967661caea1e` because the compiler you’re **using** to build `zig1.wasm` expects the old usage, so we want the commit before usages were changed.

(By the way, I hope you’re noting down what you had to do for each of these; it’d be nice to have a way to reproduce the full bootstrap path!)

---

<div class="post-metadata">

**Author:** ![motiejus](https://ziggit.dev/user_avatar/ziggit.dev/motiejus/32/3681_2.png) [@motiejus](https://ziggit.dev/u/motiejus)\
**Post date:** [November 5, 2024, 4:44am UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/12 "2024-11-05T04:44:49Z")

</div>

> [@mlugg](#):
>
> For that one I think you can do the following:
> 
> \<…\>

This was very helpful! I needed another silly fix for zig3 in callsites, akin to:

```zig
    if (@import("builtin").zig_backend == .stage2_c) {
        return @call(.{ .modifier = .always_inline }, callMain, .{});
    } else {
        return @call(.always_inline, callMain, .{});
    }

```

> [@mlugg](#):
>
> (By the way, I hope you’re noting down what you had to do for each of these; it’d be nice to have a way to reproduce the full bootstrap path!)

Sure! It’s all here: [motiejus/zig-repro - zig-repro - gitea: Gitea Service](https://git.jakstys.lt/motiejus/zig-repro)

---

<div class="post-metadata">

**Author:** ![mlugg](https://ziggit.dev/user_avatar/ziggit.dev/mlugg/32/437_2.png) [@mlugg](https://ziggit.dev/u/mlugg)\
**Post date:** [November 5, 2024, 5:22am UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/13 "2024-11-05T05:22:03Z")

</div>

> I needed another silly fix for `zig3` in callsites

Hm, that shouldn’t be necessary with the right order of operations. Let me be a little more specific:

- Have `zig3` from some commit \<= `7b2a936173165002105ba5e76bed69654e132fea`
- With that commit checked out, apply my patch
- Update `zig1.wasm`
- Before building another `zig3`, check out, at a minimum, `08b2d491bcd8c79c68495267cc71967661caea1e` to update the usages

Because just _updating_ `zig1.wasm` won’t use the C backend, your patch shouldn’t be necessary; you can just let the next commit update all the usages before you try to make any updated `zig3`.

> Sure! It’s all here:

Amazing, thanks for the link!

---

<div class="post-metadata">

**Author:** ![motiejus](https://ziggit.dev/user_avatar/ziggit.dev/motiejus/32/3681_2.png) [@motiejus](https://ziggit.dev/u/motiejus)\
**Post date:** [November 9, 2024, 10:38pm UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/14 "2024-11-09T22:38:17Z")

</div>

[I’ve got 0.11.0](https://git.jakstys.lt/motiejus/zig-repro/src/commit/e8767d2b76ca8880f74e7c3826c36e0c28253e1c/run#L753-L777), so I will be closing this.

My end-goal is 0.13.0. Once I get there, I will compare the upstream’s `zig1.wasm` to the one that my script generates, and will report findings somewhere in this forum.

Thanks @mlugg , your help was invaluable to get this off the ground!

---

<div class="post-metadata">

**Author:** ![mlugg](https://ziggit.dev/user_avatar/ziggit.dev/mlugg/32/437_2.png) [@mlugg](https://ziggit.dev/u/mlugg)\
**Post date:** [November 10, 2024, 12:04am UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/15 "2024-11-10T00:04:47Z")

</div>

Nice! Hopefully you won’t have long to go before you reach `master`; I had a quick glance over the commit log and it doesn’t look like there are too many updates past this point. Let me know if you hit any more issues!

---

<div class="post-metadata">

**Author:** ![motiejus](https://ziggit.dev/user_avatar/ziggit.dev/motiejus/32/3681_2.png) [@motiejus](https://ziggit.dev/u/motiejus)\
**Post date:** [November 11, 2024, 9:15am UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/16 "2024-11-11T09:15:44Z")

</div>

EDIT: scratch that, I was able to reconstruct the cmdline arguments from building the older branches. 🙂

---

<div class="post-metadata">

**Author:** ![motiejus](https://ziggit.dev/user_avatar/ziggit.dev/motiejus/32/3681_2.png) [@motiejus](https://ziggit.dev/u/motiejus)\
**Post date:** [November 12, 2024, 2:09pm UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/17 "2024-11-12T14:09:07Z")

</div>

Hilton Chain from guix took my PoC and made a Guix package with it. WIP branch:

[https://git.savannah.gnu.org/cgit/guix.git/tree/gnu/packages/zig.scm?h=wip-zig-bootstrap](https://git.savannah.gnu.org/cgit/guix.git/tree/gnu/packages/zig.scm?h=wip-zig-bootstrap)

I built it myself with guix, confirmed that it never involved `zig1.wasm(.zst)?`. So I will be putting my effort on hold until Hilton merges his; at which point it will be trivial for anyone to make `zig1.wasm` of master.

---

<div class="post-metadata">

**Author:** ![mnemnion](https://ziggit.dev/user_avatar/ziggit.dev/mnemnion/32/2478_2.png) [@mnemnion](https://ziggit.dev/u/mnemnion)\
**Post date:** [November 12, 2024, 3:25pm UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/18 "2024-11-12T15:25:28Z")

</div>

Just want to say that this was a great idea, thanks @motiejus for taking it on.

---

<div class="post-metadata">

**Author:** ![motiejus](https://ziggit.dev/user_avatar/ziggit.dev/motiejus/32/3681_2.png) [@motiejus](https://ziggit.dev/u/motiejus)\
**Post date:** [November 13, 2024, 5:01am UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/19 "2024-11-13T05:01:35Z")

</div>

Here is a write-up: [Zig Reproduced Without Binaries - Motiejus Jakštys Public Record](https://jakstys.lt/2024/zig-reproduced-without-binaries/)

---

<div class="post-metadata">

**Author:** ![mlugg](https://ziggit.dev/user_avatar/ziggit.dev/mlugg/32/437_2.png) [@mlugg](https://ziggit.dev/u/mlugg)\
**Post date:** [November 13, 2024, 2:37pm UTC](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607/20 "2024-11-13T14:37:30Z")

</div>

Pleased to hear @andrewrk hasn’t snuck in a supply chain attack while nobody was looking!

[Next page](https://ziggit.dev/t/building-self-hosted-from-the-original-c-implementation/6607.md?page=2)
