LLVM code generation
Code generation translates every verified MIR instruction into LLVM IR. For checked multiplication, that means a product plus an overflow bit and an explicit branch to Luce’s trap path.
Compare MIR, LLVM IR, and assembly
The middle two tabs show the exact boundary this page explains. MIR says multiply.i64. LLVM expands the check with llvm.smul.with.overflow.i64. The final ARM64 performs the same check with flags and a branch.
What you wrote. Names and indentation still carry the meaning.
open source
func clamp_double(value: i64, limit: i64) -> i64:
let doubled = value * 2
if doubled > limit:
return limit
return doubled
func main(args: list[str]):
print(str(clamp_double(len(args), 10)))
What Luce decided. Types, registers, blocks, calls, and lifetime operations are explicit. This is the IR before LLVM.
open complete MIR
func clamp_double(value: i64, limit: i64) -> i64
local %2 doubled: i64
b0:
r0 = local_get %0
r1 = const 2
r2 = multiply.i64 r0, r1
local_set %2, r2
r4 = local_get %2
r5 = local_get %1
r6 = greater.i64 r4, r5
branch r6, b1, b2
b1:
r8 = local_get %1
ret r8
b2:
r10 = local_get %2
ret r10
func main(args: list[str]) -> None
local %1 (temporary): str
b0:
r0 = local_get %0
r1 = intrinsic len, r0
r2 = const 10
r3 = call clamp_double, r1, r2
r4 = intrinsic str_value, r3
local_set %1, r4
intrinsic print, r4
r7 = local_get %1
r8 = intrinsic drop_storage, r7
local_set %1, r8
ret
What the backend handed to LLVM. This is the real textual module before LLVM performs its general optimization and instruction selection.
open complete LLVM IR
; ModuleID = '/Users/sedov/Dev/luciaos/www/lucelang/examples/journey.luc'
source_filename = "/Users/sedov/Dev/luciaos/www/lucelang/examples/journey.luc"
target triple = "arm64-apple-darwin24.6.0"
@luce.text.0 = private unnamed_addr constant [16 x i8] c"integer overflow"
@luce.text.1 = private unnamed_addr constant [0 x i8] zeroinitializer
@luce.text.2 = private unnamed_addr constant [21 x i8] c"null object reference"
@luce.text.3 = private unnamed_addr constant [22 x i8] c"object used after free"
@luce.text.4 = private unnamed_addr constant [19 x i8] c"call depth exceeded"
@luce.text.5 = private unnamed_addr constant [24 x i8] c"host service unavailable"
@luce.text.6 = private unnamed_addr constant [12 x i8] c"clamp_double"
@luce.text.7 = private unnamed_addr constant [58 x i8] c"/Users/sedov/Dev/luciaos/www/lucelang/examples/journey.luc"
@luce.origins.0 = private constant [12 x { i32, i32 }] [{ i32, i32 } { i32 2, i32 5 }, { i32, i32 } { i32 2, i32 5 }, { i32, i32 } { i32 2, i32 5 }, { i32, i32 } { i32 2, i32 5 }, { i32, i32 } { i32 3, i32 5 }, { i32, i32 } { i32 3, i32 5 }, { i32, i32 } { i32 3, i32 5 }, { i32, i32 } { i32 3, i32 5 }, { i32, i32 } { i32 4, i32 9 }, { i32, i32 } { i32 4, i32 9 }, { i32, i32 } { i32 5, i32 5 }, { i32, i32 } { i32 5, i32 5 }]
@luce.text.8 = private unnamed_addr constant [4 x i8] c"main"
@luce.origins.1 = private constant [11 x { i32, i32 }] [{ i32, i32 } { i32 8, i32 5 }, { i32, i32 } { i32 8, i32 5 }, { i32, i32 } { i32 8, i32 5 }, { i32, i32 } { i32 8, i32 5 }, { i32, i32 } { i32 8, i32 5 }, { i32, i32 } { i32 8, i32 5 }, { i32, i32 } { i32 8, i32 5 }, { i32, i32 } { i32 8, i32 5 }, { i32, i32 } { i32 8, i32 5 }, { i32, i32 } { i32 8, i32 5 }, { i32, i32 } { i32 8, i32 5 }]
@luce.functions = private constant [2 x { ptr, i64, ptr, i64, ptr, i64 }] [{ ptr, i64, ptr, i64, ptr, i64 } { ptr @luce.text.6, i64 12, ptr @luce.text.7, i64 58, ptr @luce.origins.0, i64 12 }, { ptr, i64, ptr, i64, ptr, i64 } { ptr @luce.text.8, i64 4, ptr @luce.text.7, i64 58, ptr @luce.origins.1, i64 11 }]
@luce_artifact = constant { i64, i64, i64, i32, i32, i32, i32, { i32, [52 x i8] } } { i64 23734338332087628, i64 0, i64 -7092229304759745108, i32 3, i32 29, i32 1, i32 0, { i32, [52 x i8] } { i32 18, [52 x i8] c"aarch64-macos-none\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00" } }
define internal i32 @luce.0.clamp_double(ptr align 8 nocapture readonly nonnull dereferenceable(472) noundef %0, ptr align 8 nocapture nonnull noundef %1, i64 noundef %2, i64 %3, i64 %4, ptr align 8 nocapture nonnull dereferenceable(8) writeonly noundef %5) {
6:
%7 = alloca i64, align 8
%8 = alloca i64, align 8
%9 = alloca i64, align 8
store i64 %3, ptr %7, align 8
store i64 %4, ptr %8, align 8
store i64 0, ptr %9, align 8
br label %10
10:
%11 = load i64, ptr %7, align 8
%12 = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 %11, i64 2)
%13 = extractvalue { i64, i1 } %12, 0
%14 = extractvalue { i64, i1 } %12, 1
br i1 %14, label %19, label %22, !prof !0
15:
%16 = load i64, ptr %8, align 8
store i64 %16, ptr %5, align 8
ret i32 0
17:
%18 = load i64, ptr %9, align 8
store i64 %18, ptr %5, align 8
ret i32 0
19:
%20 = extractvalue { ptr, i64 } { ptr @luce.text.0, i64 16 }, 0
%21 = extractvalue { ptr, i64 } { ptr @luce.text.0, i64 16 }, 1
call void @luce_rt_raise(ptr %1, i32 0, ptr %20, i64 %21)
call void @luce_rt_unwound(ptr %1, i32 0, i32 2)
ret i32 1
22:
store i64 %13, ptr %9, align 8
%23 = load i64, ptr %9, align 8
%24 = load i64, ptr %8, align 8
%25 = icmp sgt i64 %23, %24
br i1 %25, label %15, label %17
}
define internal i32 @luce.1.main(ptr align 8 nocapture readonly nonnull dereferenceable(472) noundef %0, ptr align 8 nocapture nonnull noundef %1, i64 noundef %2, i64 %3) {
4:
%5 = alloca i64, align 8
%6 = alloca { i8, i8, [6 x i8], i64, i64 }, align 8
store i64 %3, ptr %5, align 8
%7 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %6, i32 0, i32 0
store i8 4, ptr %7, align 1
%8 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %6, i32 0, i32 1
store i8 -1, ptr %8, align 1
%9 = extractvalue { ptr, i64 } { ptr @luce.text.1, i64 0 }, 0
%10 = ptrtoint ptr %9 to i64
%11 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %6, i32 0, i32 3
store i64 %10, ptr %11, align 8
%12 = extractvalue { ptr, i64 } { ptr @luce.text.1, i64 0 }, 1
%13 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %6, i32 0, i32 4
store i64 %12, ptr %13, align 8
%14 = sub nsw i64 %2, 1
%15 = alloca i64, align 8
%16 = alloca { i8, i8, [6 x i8], i64, i64 }, align 8
%17 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %16, i32 0, i32 0
store i8 2, ptr %17, align 1
%18 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %16, i32 0, i32 4
store i64 0, ptr %18, align 8
%19 = alloca { i8, i8, [6 x i8], i64, i64 }, align 8
%20 = alloca { i8, i8, [6 x i8], i64, i64 }, align 8
br label %21
21:
%22 = load i64, ptr %5, align 8
%23 = trunc i64 %22 to i32
%24 = lshr i64 %22, 32
%25 = trunc i64 %24 to i32
%26 = icmp eq i32 %23, -1
br i1 %26, label %27, label %30, !prof !0
27:
%28 = extractvalue { ptr, i64 } { ptr @luce.text.2, i64 21 }, 0
%29 = extractvalue { ptr, i64 } { ptr @luce.text.2, i64 21 }, 1
call void @luce_rt_raise(ptr %1, i32 14, ptr %28, i64 %29)
call void @luce_rt_unwound(ptr %1, i32 1, i32 1)
ret i32 1
30:
%31 = getelementptr inbounds i8, ptr %1, i64 96
%32 = load ptr, ptr %31, align 8!alias.scope !1, !noalias !2
%33 = zext i32 %23 to i64
%34 = mul nsw i64 %33, 112
%35 = getelementptr inbounds i8, ptr %32, i64 %34
%36 = getelementptr inbounds i8, ptr %35, i64 96
%37 = load i32, ptr %36, align 4, !alias.scope !1, !noalias !2
%38 = icmp ne i32 %37, %25
br i1 %38, label %39, label %42, !prof !0
39:
%40 = extractvalue { ptr, i64 } { ptr @luce.text.3, i64 22 }, 0
%41 = extractvalue { ptr, i64 } { ptr @luce.text.3, i64 22 }, 1
call void @luce_rt_raise(ptr %1, i32 13, ptr %40, i64 %41)
call void @luce_rt_unwound(ptr %1, i32 1, i32 1)
ret i32 1
42:
%43 = and i32 %37, 1
%44 = icmp ne i32 %43, 0
br i1 %44, label %45, label %48, !prof !0
45:
%46 = extractvalue { ptr, i64 } { ptr @luce.text.3, i64 22 }, 0
%47 = extractvalue { ptr, i64 } { ptr @luce.text.3, i64 22 }, 1
call void @luce_rt_raise(ptr %1, i32 13, ptr %46, i64 %47)
call void @luce_rt_unwound(ptr %1, i32 1, i32 1)
ret i32 1
48:
%49 = getelementptr inbounds i8, ptr %35, i64 16
%50 = load i64, ptr %49, align 8!alias.scope !1, !noalias !2
%51 = load ptr, ptr %35, align 8, !alias.scope !1, !noalias !2
%52 = icmp slt i64 %14, 1
br i1 %52, label %53, label %56, !prof !0
53:
%54 = extractvalue { ptr, i64 } { ptr @luce.text.4, i64 19 }, 0
%55 = extractvalue { ptr, i64 } { ptr @luce.text.4, i64 19 }, 1
call void @luce_rt_raise(ptr %1, i32 6, ptr %54, i64 %55)
call void @luce_rt_unwound(ptr %1, i32 1, i32 3)
ret i32 1
56:
%57 = call i32 @luce.0.clamp_double(ptr %0, ptr %1, i64 %14, i64 %50, i64 10, ptr %15)
%58 = icmp ne i32 %57, 0
br i1 %58, label %59, label %60, !prof !0
59:
call void @luce_rt_unwound(ptr %1, i32 1, i32 3)
ret i32 1
60:
%61 = load i64, ptr %15, align 8
%62 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %16, i32 0, i32 3
store i64 %61, ptr %62, align 8
%63 = call i32 @luce_rt_str(ptr %1, ptr %16, ptr %19)
%64 = icmp ne i32 %63, 0
br i1 %64, label %65, label %66, !prof !0
65:
call void @luce_rt_unwound(ptr %1, i32 1, i32 4)
ret i32 1
66:
%67 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %19, i32 0, i32 3
%68 = load i64, ptr %67, align 8
%69 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %19, i32 0, i32 1
%70 = load i8, ptr %69, align 1
%71 = icmp eq i8 %70, -1
%72 = inttoptr i64 %68 to ptr
%73 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %19, i32 0, i32 2
%74 = select i1 %71, ptr %72, ptr %73
%75 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %19, i32 0, i32 4
%76 = load i64, ptr %75, align 8
%77 = zext i8 %70 to i64
%78 = select i1 %71, i64 %76, i64 %77
%79 = insertvalue { ptr, i64 } poison, ptr %74, 0
%80 = insertvalue { ptr, i64 } %79, i64 %78, 1
call void @llvm.memcpy.inline.p0.p0.i64(ptr align 8 %6, ptr align 8 %19, i64 24, i1 false)
%81 = extractvalue { ptr, i64 } %80, 0
%82 = extractvalue { ptr, i64 } %80, 1
%83 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 1
%84 = load ptr, ptr %83, align 8
%85 = icmp eq ptr %84, null
br i1 %85, label %86, label %89, !prof !0
86:
%87 = extractvalue { ptr, i64 } { ptr @luce.text.5, i64 24 }, 0
%88 = extractvalue { ptr, i64 } { ptr @luce.text.5, i64 24 }, 1
call void @luce_rt_raise(ptr %1, i32 9, ptr %87, i64 %88)
call void @luce_rt_unwound(ptr %1, i32 1, i32 6)
ret i32 1
89:
%90 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 0
%91 = load ptr, ptr %90, align 8
%92 = call i32 %84(ptr %91, ptr %81, i64 %82)
%93 = icmp eq i32 %92, -1
br i1 %93, label %94, label %95, !prof !0
94:
call void @luce_rt_exhaust(ptr %1)
ret i32 1
95:
%96 = icmp ne i32 %92, 0
%97 = icmp ne i32 %92, 1
%98 = and i1 %96, %97
br i1 %98, label %99, label %102, !prof !0
99:
%100 = extractvalue { ptr, i64 } { ptr @luce.text.5, i64 24 }, 0
%101 = extractvalue { ptr, i64 } { ptr @luce.text.5, i64 24 }, 1
call void @luce_rt_raise(ptr %1, i32 9, ptr %100, i64 %101)
call void @luce_rt_unwound(ptr %1, i32 1, i32 6)
ret i32 1
102:
%103 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %6, i32 0, i32 3
%104 = load i64, ptr %103, align 8
%105 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %6, i32 0, i32 1
%106 = load i8, ptr %105, align 1
%107 = icmp eq i8 %106, -1
%108 = inttoptr i64 %104 to ptr
%109 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %6, i32 0, i32 2
%110 = select i1 %107, ptr %108, ptr %109
%111 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %6, i32 0, i32 4
%112 = load i64, ptr %111, align 8
%113 = zext i8 %106 to i64
%114 = select i1 %107, i64 %112, i64 %113
%115 = insertvalue { ptr, i64 } poison, ptr %110, 0
%116 = insertvalue { ptr, i64 } %115, i64 %114, 1
call void @luce_rt_drop_storage(ptr %1, ptr %6, ptr %20)
%117 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %20, i32 0, i32 3
%118 = load i64, ptr %117, align 8
%119 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %20, i32 0, i32 1
%120 = load i8, ptr %119, align 1
%121 = icmp eq i8 %120, -1
%122 = inttoptr i64 %118 to ptr
%123 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %20, i32 0, i32 2
%124 = select i1 %121, ptr %122, ptr %123
%125 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %20, i32 0, i32 4
%126 = load i64, ptr %125, align 8
%127 = zext i8 %120 to i64
%128 = select i1 %121, i64 %126, i64 %127
%129 = insertvalue { ptr, i64 } poison, ptr %124, 0
%130 = insertvalue { ptr, i64 } %129, i64 %128, 1
call void @llvm.memcpy.inline.p0.p0.i64(ptr align 8 %6, ptr align 8 %20, i64 24, i1 false)
ret i32 0
}
; Function Attrs: nounwind speculatable willreturn nofree nosync nocallback memory(none)
declare { i64, i1 } @llvm.smul.with.overflow.i64(i64 %0, i64 %1) #0
; Function Attrs: nounwind cold willreturn memory(argmem: readwrite, inaccessiblemem: readwrite)
declare void @luce_rt_raise(ptr nocapture nonnull noundef %0, i32 %1, ptr nocapture readonly %2, i64 %3) #1
; Function Attrs: nounwind cold willreturn memory(argmem: readwrite, inaccessiblemem: readwrite)
declare void @luce_rt_unwound(ptr nocapture nonnull noundef %0, i32 %1, i32 %2) #1
; Function Attrs: nounwind willreturn memory(read, argmem: readwrite, inaccessiblemem: readwrite)
declare i32 @luce_rt_str(ptr nocapture nonnull noundef %0, ptr align 8 nocapture readonly nonnull dereferenceable(24) noundef %1, ptr align 8 nocapture nonnull dereferenceable(24) writeonly noundef %2) #2
; Function Attrs: nounwind willreturn nofree nocallback memory(argmem: readwrite)
declare void @llvm.memcpy.inline.p0.p0.i64(ptr noalias nocapture writeonly %0, ptr noalias nocapture readonly %1, i64 %2, i1 immarg %3) #3
; Function Attrs: nounwind cold willreturn memory(argmem: write)
declare void @luce_rt_exhaust(ptr nocapture nonnull noundef %0) #4
; Function Attrs: nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite)
declare void @luce_rt_drop_storage(ptr nocapture nonnull noundef %0, ptr align 8 nocapture readonly nonnull dereferenceable(24) noundef %1, ptr align 8 nocapture nonnull dereferenceable(24) writeonly noundef %2) #5
define i32 @luce_main(ptr align 8 nocapture readonly nonnull dereferenceable(472) noundef %0) {
1:
%2 = alloca i64, align 8
%3 = alloca i32, align 8
store i64 256, ptr %2, align 8
%4 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 0
%5 = load ptr, ptr %4, align 8
%6 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 14
%7 = load ptr, ptr %6, align 8
%8 = icmp eq ptr %7, null
br i1 %8, label %11, label %9
9:
%10 = call i64 %7(ptr %5)
store i64 %10, ptr %2, align 8
br label %11
11:
%12 = load i64, ptr %2, align 8
%13 = call ptr @luce_rt_open(ptr @luce.functions, i64 2)
%14 = icmp eq ptr %13, null
br i1 %14, label %15, label %16, !prof !0
15:
ret i32 2
16:
%17 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 28
%18 = load ptr, ptr %17, align 8
%19 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 54
%20 = load ptr, ptr %19, align 8
%21 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 55
%22 = load ptr, ptr %21, align 8
%23 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 56
%24 = load ptr, ptr %23, align 8
%25 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 57
%26 = load ptr, ptr %25, align 8
%27 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 58
%28 = load ptr, ptr %27, align 8
%29 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 29
%30 = load ptr, ptr %29, align 8
%31 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 30
%32 = load ptr, ptr %31, align 8
%33 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 31
%34 = load ptr, ptr %33, align 8
%35 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 32
%36 = load ptr, ptr %35, align 8
call void @luce_rt_files_install(ptr %13, ptr %5, ptr %18, ptr %20, ptr %22, ptr %24, ptr %26, ptr %28, ptr %30, ptr %32, ptr %34, ptr %36)
%37 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 48
%38 = load ptr, ptr %37, align 8
%39 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 49
%40 = load ptr, ptr %39, align 8
%41 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 50
%42 = load ptr, ptr %41, align 8
%43 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 51
%44 = load ptr, ptr %43, align 8
%45 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 52
%46 = load ptr, ptr %45, align 8
call void @luce_rt_sockets_install(ptr %13, ptr %5, ptr %38, ptr %40, ptr %42, ptr %44, ptr %46)
%47 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 40
%48 = load ptr, ptr %47, align 8
%49 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 41
%50 = load ptr, ptr %49, align 8
%51 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 42
%52 = load ptr, ptr %51, align 8
%53 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 43
%54 = load ptr, ptr %53, align 8
%55 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 44
%56 = load ptr, ptr %55, align 8
%57 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 45
%58 = load ptr, ptr %57, align 8
%59 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 46
%60 = load ptr, ptr %59, align 8
%61 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 47
%62 = load ptr, ptr %61, align 8
call void @luce_rt_graphics_install(ptr %13, ptr %5, ptr %48, ptr %50, ptr %52, ptr %54, ptr %56, ptr %58, ptr %60, ptr %62)
%63 = icmp slt i64 %12, 1
br i1 %63, label %64, label %65, !prof !0
64:
call void @luce_rt_raise(ptr %13, i32 6, ptr @luce.text.4, i64 19)
store i32 1, ptr %3, align 8
br label %73
65:
%66 = alloca { i8, i8, [6 x i8], i64, i64 }, align 8
%67 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 4
%68 = load ptr, ptr %67, align 8
%69 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 5
%70 = load ptr, ptr %69, align 8
%71 = call i32 @luce_rt_args_list(ptr %13, ptr %5, ptr %68, ptr %70, ptr %66)
%72 = icmp ne i32 %71, 0
br i1 %72, label %77, label %78, !prof !0
73:
%74 = load i32, ptr %3, align 8
%75 = icmp eq i32 %74, 1
%76 = icmp eq i32 %74, 2
br i1 %75, label %83, label %86, !prof !0
77:
store i32 1, ptr %3, align 8
br label %73
78:
%79 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %66, i32 0, i32 3
%80 = load i64, ptr %79, align 8
%81 = call i32 @luce.1.main(ptr %0, ptr %13, i64 %12, i64 %80)
store i32 %81, ptr %3, align 8
%82 = call i32 @luce_rt_release(ptr %13, ptr %66)
br label %73
83:
%84 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 2
%85 = load ptr, ptr %84, align 8
call void @luce_rt_report(ptr %13, ptr %5, ptr %85)
br label %86
86:
br i1 %76, label %87, label %90, !prof !0
87:
%88 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 15
%89 = load ptr, ptr %88, align 8
call void @luce_rt_report_error(ptr %13, ptr %5, ptr %89)
br label %90
90:
%91 = call i32 @luce_rt_status(ptr %13, i32 %74)
%92 = icmp eq i32 %91, 2
%93 = getelementptr inbounds { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }, ptr %0, i32 0, i32 3
%94 = load ptr, ptr %93, align 8
%95 = icmp eq ptr %94, null
%96 = or i1 %95, %92
br i1 %96, label %97, label %98
97:
call void @luce_rt_close(ptr %13)
ret i32 %91
98:
%99 = call i64 @luce_rt_leaked(ptr %13)
call void %94(ptr %5, i64 %99)
br label %97
}
; Function Attrs: nounwind willreturn memory(argmem: read, inaccessiblemem: readwrite)
declare noalias ptr @luce_rt_open(ptr readonly %0, i64 %1) #6
; Function Attrs: nounwind willreturn memory(argmem: readwrite)
declare void @luce_rt_files_install(ptr nocapture nonnull noundef %0, ptr %1, ptr %2, ptr %3, ptr %4, ptr %5, ptr %6, ptr %7, ptr %8, ptr %9, ptr %10, ptr %11) #7
; Function Attrs: nounwind willreturn memory(readwrite)
declare void @luce_rt_sockets_install(ptr nocapture nonnull noundef %0, ptr %1, ptr %2, ptr %3, ptr %4, ptr %5, ptr %6) #8
; Function Attrs: nounwind willreturn memory(argmem: readwrite)
declare void @luce_rt_graphics_install(ptr nocapture nonnull noundef %0, ptr %1, ptr %2, ptr %3, ptr %4, ptr %5, ptr %6, ptr %7, ptr %8, ptr %9) #7
; Function Attrs: nounwind memory(readwrite)
declare i32 @luce_rt_args_list(ptr nocapture nonnull noundef %0, ptr %1, ptr %2, ptr %3, ptr align 8 nocapture nonnull dereferenceable(24) writeonly noundef %4) #9
; Function Attrs: nounwind memory(readwrite)
declare i32 @luce_rt_release(ptr nocapture nonnull noundef %0, ptr align 8 nocapture readonly nonnull dereferenceable(24) noundef %1) #9
; Function Attrs: cold
declare void @luce_rt_report(ptr nocapture nonnull noundef %0, ptr %1, ptr %2) #10
; Function Attrs: cold
declare void @luce_rt_report_error(ptr nocapture nonnull noundef %0, ptr %1, ptr %2) #10
; Function Attrs: nounwind willreturn memory(argmem: read)
declare i32 @luce_rt_status(ptr nocapture nonnull noundef %0, i32 %1) #11
; Function Attrs: nounwind willreturn memory(argmem: read)
declare i64 @luce_rt_leaked(ptr nocapture nonnull noundef %0) #11
; Function Attrs: nounwind memory(readwrite)
declare void @luce_rt_close(ptr nocapture nonnull noundef %0) #9
attributes #0 = { nounwind speculatable willreturn nofree nosync nocallback memory(none) }
attributes #1 = { nounwind cold willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) }
attributes #2 = { nounwind willreturn memory(read, argmem: readwrite, inaccessiblemem: readwrite) }
attributes #3 = { nounwind willreturn nofree nocallback memory(argmem: readwrite) }
attributes #4 = { nounwind cold willreturn memory(argmem: write) }
attributes #5 = { nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) }
attributes #6 = { nounwind willreturn memory(argmem: read, inaccessiblemem: readwrite) }
attributes #7 = { nounwind willreturn memory(argmem: readwrite) }
attributes #8 = { nounwind willreturn memory(readwrite) }
attributes #9 = { nounwind memory(readwrite) }
attributes #10 = { cold }
attributes #11 = { nounwind willreturn memory(argmem: read) }
!0 = !{!"branch_weights", i32 1, i32 2000}
!1 = !{!3}
!2 = !{!4}
!3 = !{!"luce.rows", !5}
!4 = !{!"luce.elements", !5}
!5 = !{!"luce.alias"}
What reached the object file. The platform disassembler shows the optimized ARM64 instructions, including inlining and trap branches.
open complete assembly
/Users/sedov/Dev/luciaos/www/lucelang/out/traces/journey.o: file format mach-o arm64
Disassembly of section __TEXT,__text:
0000000000000000 <ltmp0>:
; luce_main():
0: stp x24, x23, [sp, #-0x40]!
4: stp x22, x21, [sp, #0x10]
8: stp x20, x19, [sp, #0x20]
c: stp x29, x30, [sp, #0x30]
10: add x29, sp, #0x30
14: sub sp, sp, #0x70
18: ldr x8, [x0, #0x70]
1c: ldr x19, [x0]
20: mov x20, x0
24: cbz x8, 0x50 <ltmp0+0x50>
28: mov x0, x19
2c: blr x8
30: mov x23, x0
34: adrp x0, 0x0 <ltmp0>
38: add x0, x0, #0x0
3c: mov w1, #0x2 ; =2
40: mov w22, #0x2 ; =2
44: bl 0x44 <ltmp0+0x44>
48: cbnz x0, 0x6c <ltmp0+0x6c>
4c: b 0x21c <ltmp0+0x21c>
50: mov w23, #0x100 ; =256
54: adrp x0, 0x0 <ltmp0>
58: add x0, x0, #0x0
5c: mov w1, #0x2 ; =2
60: mov w22, #0x2 ; =2
64: bl 0x64 <ltmp0+0x64>
68: cbz x0, 0x21c <ltmp0+0x21c>
6c: ldp x3, x4, [x20, #0x1b0]
70: mov x21, x0
74: ldp x5, x6, [x20, #0x1c0]
78: ldr x2, [x20, #0xe0]
7c: ldp x8, x9, [x20, #0xf8]
80: ldr x7, [x20, #0x1d0]
84: ldur q0, [x20, #0xe8]
88: sub sp, sp, #0x20
8c: mov x1, x19
90: stp x8, x9, [sp, #0x10]
94: str q0, [sp]
98: bl 0x98 <ltmp0+0x98>
9c: add sp, sp, #0x20
a0: ldp x2, x3, [x20, #0x180]
a4: mov x0, x21
a8: ldp x4, x5, [x20, #0x190]
ac: mov x1, x19
b0: ldr x6, [x20, #0x1a0]
b4: bl 0xb4 <ltmp0+0xb4>
b8: ldp x8, x9, [x20, #0x170]
bc: ldp x2, x3, [x20, #0x140]
c0: ldp x4, x5, [x20, #0x150]
c4: ldp x6, x7, [x20, #0x160]
c8: stp x8, x9, [sp, #-0x10]!
cc: mov x0, x21
d0: mov x1, x19
d4: bl 0xd4 <ltmp0+0xd4>
d8: add sp, sp, #0x10
dc: cmp x23, #0x0
e0: b.le 0x278 <ltmp0+0x278>
e4: sub x22, sp, #0x20
e8: mov sp, x22
ec: ldp x2, x3, [x20, #0x20]
f0: mov x0, x21
f4: mov x1, x19
f8: mov x4, x22
fc: bl 0xfc <ltmp0+0xfc>
100: cbnz w0, 0x32c <ltmp0+0x32c>
104: ldr x8, [x22, #0x8]
108: mov w9, #0x2 ; =2
10c: stur xzr, [x29, #-0x58]
110: sturb w9, [x29, #-0x68]
114: cmn w8, #0x1
118: b.eq 0x294 <ltmp0+0x294>
11c: mov w9, #0x70 ; =112
120: ldr x10, [x21, #0x60]
124: umaddl x9, w8, w9, x10
128: lsr x8, x8, #32
12c: ldr w10, [x9, #0x60]
130: cmp w10, w8
134: b.ne 0x238 <ltmp0+0x238>
138: tbnz w8, #0x0, 0x238 <ltmp0+0x238>
13c: cmp x23, #0x1
140: b.eq 0x2bc <ltmp0+0x2bc>
144: ldr x8, [x9, #0x10]
148: mov x9, #0x4000000000000000 ; =4611686018427387904
14c: cmn x8, x9
150: b.mi 0x2d8 <ltmp0+0x2d8>
154: lsl x8, x8, #1
158: mov w9, #0xa ; =10
15c: sub x1, x29, #0x68
160: sub x2, x29, #0x80
164: mov x0, x21
168: cmp x8, #0xa
16c: csel x8, x8, x9, lt
170: stur x8, [x29, #-0x60]
174: bl 0x174 <ltmp0+0x174>
178: cbnz w0, 0x310 <ltmp0+0x310>
17c: ldp x9, x10, [x29, #-0x78]
180: ldur q0, [x29, #-0x80]
184: ldr x8, [x20, #0x8]
188: ldurb w11, [x29, #-0x7f]
18c: stur q0, [x29, #-0x50]
190: stur x10, [x29, #-0x40]
194: cbz x8, 0x250 <ltmp0+0x250>
198: sub x12, x29, #0x80
19c: cmp w11, #0xff
1a0: ldr x0, [x20]
1a4: orr x12, x12, #0x2
1a8: csel x2, x10, x11, eq
1ac: csel x1, x9, x12, eq
1b0: blr x8
1b4: cmn w0, #0x1
1b8: b.eq 0x358 <ltmp0+0x358>
1bc: cmp w0, #0x2
1c0: b.hs 0x250 <ltmp0+0x250>
1c4: sub x1, x29, #0x50
1c8: sub x2, x29, #0x98
1cc: mov x0, x21
1d0: bl 0x1d0 <ltmp0+0x1d0>
1d4: mov x0, x21
1d8: mov x1, x22
1dc: bl 0x1dc <ltmp0+0x1dc>
1e0: mov w1, wzr
1e4: mov x0, x21
1e8: bl 0x1e8 <ltmp0+0x1e8>
1ec: mov w22, w0
1f0: cmp w0, #0x2
1f4: b.eq 0x214 <ltmp0+0x214>
1f8: ldr x20, [x20, #0x18]
1fc: cbz x20, 0x214 <ltmp0+0x214>
200: mov x0, x21
204: bl 0x204 <ltmp0+0x204>
208: mov x1, x0
20c: mov x0, x19
210: blr x20
214: mov x0, x21
218: bl 0x218 <ltmp0+0x218>
21c: mov w0, w22
220: sub sp, x29, #0x30
224: ldp x29, x30, [sp, #0x30]
228: ldp x20, x19, [sp, #0x20]
22c: ldp x22, x21, [sp, #0x10]
230: ldp x24, x23, [sp], #0x40
234: ret
238: adrp x2, 0x0 <ltmp0>
23c: add x2, x2, #0x0
240: mov x0, x21
244: mov w1, #0xd ; =13
248: mov w3, #0x16 ; =22
24c: b 0x2a8 <ltmp0+0x2a8>
250: adrp x2, 0x0 <ltmp0>
254: add x2, x2, #0x0
258: mov x0, x21
25c: mov w1, #0x9 ; =9
260: mov w3, #0x18 ; =24
264: bl 0x264 <ltmp0+0x264>
268: mov x0, x21
26c: mov w1, #0x1 ; =1
270: mov w2, #0x6 ; =6
274: b 0x31c <ltmp0+0x31c>
278: adrp x2, 0x0 <ltmp0>
27c: add x2, x2, #0x0
280: mov x0, x21
284: mov w1, #0x6 ; =6
288: mov w3, #0x13 ; =19
28c: bl 0x28c <ltmp0+0x28c>
290: b 0x32c <ltmp0+0x32c>
294: adrp x2, 0x0 <ltmp0>
298: add x2, x2, #0x0
29c: mov x0, x21
2a0: mov w1, #0xe ; =14
2a4: mov w3, #0x15 ; =21
2a8: bl 0x2a8 <ltmp0+0x2a8>
2ac: mov x0, x21
2b0: mov w1, #0x1 ; =1
2b4: mov w2, #0x1 ; =1
2b8: b 0x31c <ltmp0+0x31c>
2bc: adrp x2, 0x0 <ltmp0>
2c0: add x2, x2, #0x0
2c4: mov x0, x21
2c8: mov w1, #0x6 ; =6
2cc: mov w3, #0x13 ; =19
2d0: bl 0x2d0 <ltmp0+0x2d0>
2d4: b 0x300 <ltmp0+0x300>
2d8: adrp x2, 0x0 <ltmp0>
2dc: add x2, x2, #0x0
2e0: mov x0, x21
2e4: mov w1, wzr
2e8: mov w3, #0x10 ; =16
2ec: bl 0x2ec <ltmp0+0x2ec>
2f0: mov x0, x21
2f4: mov w1, wzr
2f8: mov w2, #0x2 ; =2
2fc: bl 0x2fc <ltmp0+0x2fc>
300: mov x0, x21
304: mov w1, #0x1 ; =1
308: mov w2, #0x3 ; =3
30c: b 0x31c <ltmp0+0x31c>
310: mov x0, x21
314: mov w1, #0x1 ; =1
318: mov w2, #0x4 ; =4
31c: bl 0x31c <ltmp0+0x31c>
320: mov x0, x21
324: mov x1, x22
328: bl 0x328 <ltmp0+0x328>
32c: ldr x2, [x20, #0x10]
330: mov x0, x21
334: mov x1, x19
338: bl 0x338 <ltmp0+0x338>
33c: mov w1, #0x1 ; =1
340: mov x0, x21
344: bl 0x344 <ltmp0+0x344>
348: mov w22, w0
34c: cmp w0, #0x2
350: b.ne 0x1f8 <ltmp0+0x1f8>
354: b 0x214 <ltmp0+0x214>
358: mov x0, x21
35c: bl 0x35c <ltmp0+0x35c>
360: b 0x320 <ltmp0+0x320>
The backend pipeline
Every instruction has an arm
The switches over MIR instructions and intrinsics name every tag. There is no catch-all else that could silently accept a newly added instruction, and there is no unreachable standing in for unfinished work. A missing lowering is a named unsupported result; forged impossible IR is refused.
Why totality matters: adding one MIR instruction must make code generation fail to compile until its native meaning is implemented. Wrong code cannot hide behind a default branch.
Runtime calls and inline work
Generated code keeps plain scalar control and representation work inline where that is both safe and visible to LLVM. Dynamic language semantics call libluce_rt: ARC, heap resolution, container mutation, text storage, checked operators, workers, resources, and trap construction.
Inline LLVM
Branches, arithmetic where the exact trap edge is emitted, loads and stores, stack slots, optional tags, direct and indirect calls.
Runtime boundary
Heap identity, reference counts, moving container buffers, UTF-8 storage, host-backed handles, worker transfer, and shared trap state.
Telling LLVM the truth
Opaque runtime calls can make a compiler assume that every call reads and writes everything. runtime_effects.zig describes the real signatures, memory behavior, return behavior, and unwind properties of the C exports. Tests compare that description with the actual Zig declarations so an incorrect LLVM declaration cannot drift silently.
The host is not the runtime
Lists, strings, ARC, and arithmetic are language semantics and therefore runtime calls. Console, files, clocks, terminals, processes, sockets, windows, and other outside effects arrive through the versioned LuceHost table. Each optional service fails closed when absent.
Why loom carries no LLVM
LLVM IR construction uses a vendored pure-Zig builder. Only codegen/emit.zig calls libLLVM, and only the luce compiler imports that emission module. loom loads existing machine code; when it needs a cold compile, it invokes the sibling luce binary rather than becoming a compiler.
Continue through object linking, artifact validation, and luce_main →