Each row is something that was run in this checkout. Confidence is about the claim, not about the general future of Mojo.

idhypothesiscommandobservedinterpretationconfidencesource
E1The pinned BEAM is OTP 28 / erts 16.2 and Elixir 1.20.2.scripts/doctor.shelixir 1.20.2, erlang 28 erts-16.2, mojo Mojo 1.1.0 (8189361e), Darwin arm64 26.5Toolchain matches the pin.highdoctor output
E2Mojo 1.1.0 can emit a shared library.mojo build experiments/abi/01_export_add/add.mojo --emit shared-libnm -gU shows T _mojoler_add. otool -L lists the dylib, @rpath/libKGENCompilerRTShared.dylib, and libSystem.B.dylib.A C ABI export works. The Mojo compiler runtime is a real dynamic dependency.highexperiments/abi/OBSERVED.txt
E3The export lowers to a C integer function.mojo build ... --emit llvmdefine dso_local i64 @mojoler_add(i64 noundef %0, i64 noundef %1) then add and ret. Target arm64-apple-darwin25.5.0, CPU apple-m1.Arguments and the return use the integer registers. This is an add, not a NIF.highexperiments/abi/01_export_add/add.ll
E4fn is gone in this compiler.mojo build of a file that used fnerror: 'fn' has been removed; use 'def' insteadTutorials that still show fn do not match 1.1.0.highcompiler diagnostic
E5OTP 28.3.1 NIF version is 2.17 and ERL_NIF_TERM is 8 bytes.clang of experiments/abi/diagnostic/layout.c, then run itERL_NIF_MAJOR=2 ERL_NIF_MINOR=17, long=8, ERL_NIF_TERM size=8, ErlNifFunc sizeof=32, ErlNifEntry sizeof=96, ErlNifResourceTypeInit sizeof=40Field offsets in 05-otp-abi-map.md come from this run, not from a guess.highdiagnostic program
E6enif_get_int64 is not a symbol on this OTP.nm -gU of beam.smp; read erl_nif_api_funcs.h_enif_get_long, _enif_make_long, _enif_make_badarg are defined. SIZEOF_LONG is 8, and the header macros enif_get_int64 to enif_get_long.A NIF must call enif_get_long / enif_make_long.highheader and beam.smp
E7Mojo struct layout matches those offsets.mojo experiments/abi/03_layout/layout.mojoNifFunc sizeof 32, fields at 0, 8, 16, 24. NifEntry sizeof 96, fields at 0, 4, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88. optional_none_or 0.RegisterPassable plus std.ffi integer aliases reproduced the C layout. None is a NULL pointer.highOBSERVED.txt
E8A thin function is an 8-byte code pointer.mojo experiments/abi/02_pointers/callback.mojosizeof 8, result 42Safe to store in ErlNifFunc.fptr. Pointer(to=cb) was rejected as a technique after LLVM showed it takes the address of a stack slot.highIR of an earlier probe; this program's printout
E9There is no module-level mutable global.compile a file-scope varerror: global variables are not supportednif_init uses calloc for the entry and the function table.highcompiler diagnostic
E10Literal C strings survive calloc.mojo experiments/abi/04_lifetime/calloc_entry.mojoprinted add and arity 2ImmStaticOrigin pointers can be stored in the descriptor.highOBSERVED.txt
E11The built NIF exports only nif_init and imports the long-sized enif symbols.scripts/inspect-abi.shT _nif_init. Undefined: _abort, _calloc, _enif_get_long, _enif_make_badarg, _enif_make_long, dyld_stub_binder. otool -L shows KGEN and libSystem. rpath is the venv modular/lib.Link line -Xlinker -undefined -Xlinker dynamic_lookup left enif_* for dyld to bind inside beam.smp.highinspect-abi output
E12LLVM for the NIF calls those symbols directly.mojo build native/poc.mojo --emit llvmcall i32 @enif_get_long, call i64 @enif_make_long, call i64 @enif_make_badarg, declare lines for those plus calloc and abort. Also compiler-inserted write, dup, fdopen, fflush, fclose, KGEN_CompilerRT_AlignedFree.The NIF body is a direct call, not a C wrapper. The compiler also emits libc calls of its own.high/tmp/poc.ll from the recorded build
E13The BEAM loads the library and add(20, 22) is 42.mix test11 passedIncludes negatives, overflow, non-integers, arity, 200 repeats, 40 concurrent tasks, a fresh OS process, and the nm assertions.highExUnit
E14A second load is refused by OTP, not by Mojo.Mojoler.POC.reload() inside ExUnit{:error, {:reload, 'NIF library already loaded (reload disallowed since OTP 20).'}}load, reload, and upgrade are NULL. OTP refuses the second load_nif before those callbacks would matter.hightest/poc_test.exs
E15initialize_runtime() can run inside nif_init.build experiments/abi/05_runtime/rtnif.mojo and load_nif itruntime ping 7 after two calls to initialize_runtime()Idempotent enough to call twice during init in this process. The add NIF does not need it. parallelize was not available without the max package.mediumelixir one-shot
E16Small-int Elixir addition is cheaper than this NIF.mix run --no-start -e with warmup 10_000, 5 trials of 100_000NIF microseconds [38188, 37250, 36213, 34686, 36222] (about 347–382 ns/call including the Elixir loop). Elixir + [24655, 24961, 23204, 23876, 23806] (about 232–250 ns/call).The loop is inside both measurements. This is not a pure boundary cost, and it is not a reason to prefer the NIF.mediumone process, no isolation between trials
E17A one-element GPU add can return 42 through a NIF on this Mac..venv/bin/mojo experiments/gpu/add_host.mojo, then mojo build experiments/gpu/gpu_nif.mojo --emit shared-lib and elixir -e loading experiments/gpu/libgpuHost program printed gpu_add 42.0. Fresh BEAM printed gpu_nif 42 and exited 0. nm -gU shows only _nif_init. otool -L lists libKGENCompilerRTShared.dylib, libAsyncRTMojoBindings.dylib, and libSystem.B.dylib.Mojo 1.1.0 plus MAX 26.6.0. std.gpu is not in this stdlib; the kernel is max.gpu. vector_addition adds one float32, grid_dim=1, block_dim=1. DeviceContext copies the float back and Int(result) becomes enif_make_long. The callback calls initialize_runtime() first. The entry name is Elixir.Mojoler.GPUProbe, function sum/0, library experiments/gpu/libgpu.so (OTP appends .so). has_accelerator() did not take the "no GPU" branch. One call, one process, Apple GPU. Not NVIDIA, not concurrent, not a long kernel, and not part of Mojoler.POC.add/2.highthis machine, Apple GPU
E18The NIF struct layout is the same on Linux x86-64.Actions run 39451722783, job nif, scripts/doctor.sh then scripts/run-abi-experiments.sh on ubuntu-24.04doctor: ready. Linux x86_64, Elixir 1.20.2, Erlang 28 erts-16.2, Ubuntu clang 18.1.3, Mojo 1.1.0 (8189361e). T mojoler_add with no leading underscore. Mojo layout: NifFunc 32 at 0, 8, 16, 24; NifEntry 96 at 0, 4, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88; optional_none_or 0. Clang diagnostic: long=8, ERL_NIF_TERM size=8, the same offsets, ErlNifResourceTypeInit sizeof=40. runtime ping 7.LP64 ELF matches the Darwin measurement. ELF exports have no underscore. ldd of the add-only library printed statically linked. Crashpad's "Failed to initialize Crashpad" is the Mojo driver; the script still exited 0.highjob 118727989464, commit e6728ea
E19Mojoler.POC.add(20, 22) == 42 on that Linux runner, and the KGEN runtime is not a dynamic dependency of libpoc.so.same run, scripts/test-isolated.sh; the ldd text is from the preceding red run 39428236198, whose only failure was the assertion that expected libKGENCompilerRTSharedGreen run: Result: 11 passed in 0.6 seconds. Red run's ldd of priv/native/libpoc.so: linux-vdso.so.1, libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6, /lib64/ld-linux-x86-64.so.2. No libKGENCompilerRTShared. Doctor on the green run still finds that .so inside the venv. Link line that produced the library: -Xlinker --unresolved-symbols=ignore-all and -Xlinker -z -Xlinker undefs. The earlier flag --unresolved-symbols=ignore-in-shared-libs failed in 39365275751 with undefined reference to enif_make_long.The CPU NIF loads under ld.so on Ubuntu 24.04 and the ExUnit suite passes, including the fresh OS process. Undefined enif_* symbols bind when beam.smp loads the library. On Linux this add image does not DT_NEEDED the KGEN shared library, unlike the Darwin otool -L result in E11. The workflow has no GPU.highgreen log plus the ldd printed by run 39428236198
E20The generated ABI matches this Mac's headers, and a misspelled import is rejected.scripts/check-abi.shExit 0. abi mojo: matches, layout ok, unexpected undefined symbol: enif_make_lonq, misspelled import rejected, imports ok for libpoc, libtwice, libterm, libown, libsched, libdsl_arith, libdsl_bytes, libdsl_box, provenance ok, dirty flags ok.One LP64 Mojo file matches Apple clang's layout of the allowlisted structs. Linux has not been re-run for this generator.highthis Mac, Darwin arm64
E21The ExUnit suite for stages 1–7 passes in one VM.mix testResult: 43 passed in 4.8 seconds.Includes add/2, double/1, term edges, ownership, the heartbeat script, DSL rejection, and the abort probe.highthis Mac
E22A dirty-CPU burn lets a one-scheduler VM heartbeat; the same burn on the normal scheduler does not.scripts/measure-heartbeat.shbeats 18 elapsed 200 then beats 0 elapsed 200, then heartbeat ok dirty=18 normal=0.Flags come from abi_dirty_cpu() (1) and c_uint(0). The normal library is built in a temp directory. Elixir Task.yield returning nil did not stop burn/1.highthis Mac, elixir --erl "+S 1"
E23An external app, an umbrella child, and a copied release all get 42.scripts/release-candidate.shConsumer 1 passed, again after mix clean, umbrella child 1 passed, release 42, release ok.The Mix compiler built the dependency. The copied release still resolved the venv rpath on this machine. KGEN was not bundled.highthis Mac
E24CPU demo oracles match Elixir.scripts/demo-cpu.shoracle 42, copy {:ok, <<1, 2, 3>>, 3}, borrow {:ok, 32, 1}, frozen <<4, 9>> token 1, retained <<7, 7>>, dirty_burn_us 49568, warm_add_us 4.The warm number is one call, not a throughput claim. add/2 is not presented as faster than Elixir.highthis Mac
E25The historical GPU NIF still returns 42, and a 4-wide batch returns 110, including a repeat and two concurrent calls.scripts/gpu-batch.sh, then a second Elixir process for the concurrent linegpu_nif 42, gpu_batch 110, gpu_batch_repeat 110. Concurrent inspect printed ~c"nn", which is the charlist [110, 110].CPU reference is 1+10+2+20+3+30+4+40. The batch NIF uses abi_dirty_cpu(). experiments/gpu/gpu_nif.mojo was not edited. No-device was not observed. NVIDIA and Linux GPU were not run.highthis Mac, Apple GPU, MAX 26.6.0
E26An aborting NIF takes down only the child BEAM.scripts/probe-abort.sh inside mix testThe probe test passed. The script exits 0 only when the child exits non-zero.This is abort, not a Mojo raise inside safe arithmetic. Product NIFs do not call it.highthis Mac

Unknowns still open: NVIDIA, any GPU call on Linux, the {:error, :no_device} branch on a machine that actually has no accelerator, macOS ARM64 in Actions (no runner is configured), and the Linux workflow for stages 1–10 (the file is updated; this commit has not been executed there). Mojoler.Own frees its private box in unload. The entry and function-table calloc blocks are still not freed, because OTP retains the entry; a second load_nif is rejected, so that residue is one pair of blocks per loaded module per process. Upgrade returns 1 and was not invoked.