Workers and isolated heaps
spawn square(...) starts native work on another thread. The worker receives copied arguments in a separate Luce runtime, and wait() copies its result back to the caller.
Follow one spawned function
MIR marks the spawn and wait explicitly. LLVM lowers them to the worker runtime. ARM64 prepares the function identity and copied arguments, calls the spawn service, then joins the task and checks the returned status.
Luce source. Names and indentation describe the program for a reader.
open source file
func square(value: i64) -> i64:
return value * value
func main(args: list[str]):
let work = spawn square(len(args) + 2)
print(str(work.wait()))
Luce MIR. Types, registers, blocks, calls, and lifetime operations form the instruction plan sent to the LLVM backend.
open MIR fileMIR instruction guide hover, focus, or tap dotted terms
r7 is one typed intermediate value, %2 is a local storage slot, and b1 is a basic block. Read each block from top to bottom, then follow its final control-flow instruction.
Hover or focus a dotted term in the file for its explanation. On a touch screen, tap a term to keep the note open and tap elsewhere to close it. The list includes the operations that appear in this file.
func …- Starts one MIR function and lists the source-level parameters with their resolved types.
local %N- Reserves a typed local slot. The slot gives later blocks a stable place to read or replace.
b0, b1, …- Names a basic block. Control enters at the label and runs until a branch, jump, trap, or return chooses what happens next.
r0, r1, …- Names one typed intermediate result. Each register is assigned once, which makes data flow explicit.
local_get- Reads a local slot into a fresh MIR register so this use has a precise value and type.
local_set- Writes a register into a local slot. Later blocks read that slot after control-flow paths join.
const- Creates a typed literal such as 2 or 10 inside the instruction stream.
add.i64- Adds two signed 64-bit integers. The type suffix selects the overflow and representation rules.
multiply.i64- Multiplies signed 64-bit integers and carries Luce's overflow behavior into the backend.
intrinsic NAME- Invokes a language operation with runtime rules recorded by the compiler. The name identifies the operation.
intrinsic len- Reads the logical length defined by the value's type, such as argument count or Unicode-scalar count.
intrinsic str_value- Converts a typed value into owned text through Luce's string conversion rules.
intrinsic print- Sends text through the installed host output capability.
intrinsic release- Removes one strong owner and runs destruction when the count reaches zero.
intrinsic drop_storage- Releases any reference held by a temporary value and leaves that temporary in its empty state.
intrinsic task_wait- Waits for a worker result and transfers the returned value into this runtime.
spawn- Copies sendable arguments into a worker runtime and starts the declared function there.
ret- Returns the current function's result to its caller and closes the current control-flow path.
func square(value: i64) -> i64
b0:
r0 = local_get %0
r1 = local_get %0
r2 = multiply.i64 r0, r1
ret r2
func main(args: list[str]) -> None
local %1 (temporary): task[i64]
local %2 work: task[i64]
local %3 (temporary): str
b0:
r0 = local_get %0
r1 = intrinsic len, r0
r2 = const 2
r3 = add.i64 r1, r2
r4 = spawn square, r3
local_set %2, r4
r6 = local_get %2
r7 = intrinsic task_wait, r6
r8 = intrinsic str_value, r7
local_set %3, r8
intrinsic print, r8
r11 = local_get %3
r12 = intrinsic drop_storage, r11
local_set %3, r12
r14 = local_get %2
intrinsic release, r14
ret
LLVM IR. The backend expands MIR into typed memory operations, calls, checks, and control-flow blocks for LLVM.
open LLVM IR fileLLVM IR instruction guide hover, focus, or tap dotted terms
%7 is an SSA value, i64 is a 64-bit integer type, ptr is a pointer, and @name is a module symbol. Numbered labels divide the function into basic blocks.
Hover or focus a dotted term in the file for its explanation. On a touch screen, tap a term to keep the note open and tap elsewhere to close it. The list includes the operations that appear in this file.
@name = …- Defines module data such as text constants, source positions, function records, and the artifact identity tag.
define … @name- Begins a generated function. The parameter attributes tell LLVM which pointers are valid, writable, or read-only.
declare … @name- Declares a runtime or LLVM helper whose body is provided elsewhere.
numeric label- Starts an LLVM basic block. Every branch names one of these labels as its destination.
%0, %1, …- Names an SSA value. Each name is assigned once, allowing LLVM to trace definitions and uses directly.
alloca- Reserves a stack slot for a local value, return area, or temporary aggregate.
getelementptr- Calculates the address of a field or indexed element while preserving LLVM's type and bounds information.
load- Copies a typed value from memory into an SSA value.
store- Copies an SSA value into a stack slot, object field, return area, or runtime structure.
icmp- Compares integers or pointers and produces the one-bit condition consumed by a branch or select.
br- Transfers control to another block. With an
i1operand it chooses between two destinations. select- Chooses one of two SSA values from a condition, which can become a branch-free machine instruction.
switch- Dispatches an integer tag to several blocks, commonly for a union case or match.
call- Invokes a generated function, a runtime helper, a host callback, or an LLVM intrinsic.
extractvalue- Reads one field from an SSA aggregate, such as the result and overflow bit returned together.
insertvalue- Builds an SSA aggregate one field at a time.
ptrtoint- Encodes a pointer as an integer field inside Luce's uniform runtime value representation.
inttoptr- Recovers a pointer from the integer field of Luce's uniform runtime value representation.
zext- Widens an unsigned value by filling the new high bits with zero.
trunc- Keeps the low bits while converting to a narrower integer representation.
lshr- Shifts bits right and fills the high side with zero; this is useful for unpacking handle fields.
and- Combines or masks bits, often to inspect a flag in a packed handle or status value.
or- Sets or combines bits in a packed value.
mul- Multiplies integers after the language-specific checks have been represented.
ret- Returns a status or value and ends the current basic block.
@llvm.smul.with.overflow.i64- Returns the signed product and a one-bit overflow result together. Luce branches to its overflow trap when that bit is set.
@llvm.sadd.with.overflow.i64- Returns a signed sum together with the overflow bit required by checked addition.
@llvm.memcpy.inline- Copies a small fixed-size value representation; LLVM can expand it directly for the target.
@luce_rt_open- Creates the per-run runtime state and installs the table used to turn function numbers into source-aware traces.
@luce_rt_close- Closes the per-run runtime state after the final status and reports have been collected.
@luce_rt_args_list- Builds the owned
list[str]passed tomainfrom the host's argument callbacks. @luce_rt_status- Combines the generated function result with runtime trap, error, exhaustion, and exit state.
@luce_rt_report_error- Sends an uncaught recoverable error through the host's error-report callback.
@luce_rt_report- Sends the completed trap report through the host callback selected by the entry wrapper.
@luce_rt_leaked- Reads the live-object count used to detect references that remain after program cleanup.
@luce_rt_exhaust- Records allocation exhaustion in the current run so the entry wrapper returns the corresponding status.
@luce_rt_raise- Records a source-aware trap in the runtime so every execution path reports the same code and location.
@luce_rt_unwound- Adds one generated function frame while a trap or uncaught error travels toward the entry point.
@luce_rt_release- Removes a strong owner and triggers destruction at zero.
@luce_rt_drop_storage- Releases reference-bearing fields in a temporary runtime value.
@luce_rt_str- Converts a uniform runtime value into owned UTF-8 text.
@luce_rt_spawn- Creates a worker runtime, transfers its arguments, and starts the worker function.
@luce_rt_task_wait- Joins a worker task and transfers its result into the waiting runtime.
@luce_rt_effects_enter- Acquires the runtime effect gate before a worker enters a serialized host callback.
@luce_rt_effects_leave- Releases the runtime effect gate after the host callback returns.
@luce_rt_files_install- Copies file-related callbacks from the host table into the current runtime context.
@luce_rt_sockets_install- Copies network callbacks from the host table into the current runtime context.
@luce_rt_graphics_install- Copies window and graphics callbacks from the host table into the current runtime context.
@luce_rt_workers_install- Installs worker callbacks plus the generated worker dispatcher used by
spawn. !prof- Attaches branch-probability metadata so LLVM can place common and failure paths efficiently.
; ModuleID = '/Users/sedov/Dev/luciaos/www/lucelang/examples/workers.luc'
source_filename = "/Users/sedov/Dev/luciaos/www/lucelang/examples/workers.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 [24 x i8] c"host service unavailable"
@luce.text.5 = private unnamed_addr constant [6 x i8] c"square"
@luce.text.6 = private unnamed_addr constant [58 x i8] c"/Users/sedov/Dev/luciaos/www/lucelang/examples/workers.luc"
@luce.origins.0 = private constant [4 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 }]
@luce.text.7 = private unnamed_addr constant [4 x i8] c"main"
@luce.origins.1 = private constant [17 x { i32, i32 }] [{ i32, i32 } { i32 5, i32 5 }, { i32, i32 } { i32 5, i32 5 }, { i32, i32 } { i32 5, i32 5 }, { i32, i32 } { i32 5, i32 5 }, { i32, i32 } { i32 5, i32 5 }, { i32, i32 } { i32 5, i32 5 }, { i32, i32 } { i32 6, i32 5 }, { i32, i32 } { i32 6, i32 5 }, { i32, i32 } { i32 6, i32 5 }, { i32, i32 } { i32 6, i32 5 }, { i32, i32 } { i32 6, i32 5 }, { i32, i32 } { i32 6, i32 5 }, { i32, i32 } { i32 6, i32 5 }, { i32, i32 } { i32 6, i32 5 }, { i32, i32 } { i32 6, i32 5 }, { i32, i32 } { i32 6, i32 5 }, { i32, i32 } { i32 6, i32 5 }]
@luce.functions = private constant [2 x { ptr, i64, ptr, i64, ptr, i64 }] [{ ptr, i64, ptr, i64, ptr, i64 } { ptr @luce.text.5, i64 6, ptr @luce.text.6, i64 58, ptr @luce.origins.0, i64 4 }, { ptr, i64, ptr, i64, ptr, i64 } { ptr @luce.text.7, i64 4, ptr @luce.text.6, i64 58, ptr @luce.origins.1, i64 17 }]
@luce.text.8 = private unnamed_addr constant [19 x i8] c"call depth exceeded"
@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.square(ptr align 8 nocapture readonly nonnull dereferenceable(472) noundef %0, ptr align 8 nocapture nonnull noundef %1, i64 noundef %2, i64 %3, ptr align 8 nocapture nonnull dereferenceable(8) writeonly noundef %4) {
5:
%6 = alloca i64, align 8
store i64 %3, ptr %6, align 8
br label %7
7:
%8 = load i64, ptr %6, align 8
%9 = load i64, ptr %6, align 8
%10 = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 %8, i64 %9)
%11 = extractvalue { i64, i1 } %10, 0
%12 = extractvalue { i64, i1 } %10, 1
br i1 %12, label %13, label %16, !prof !0
13:
%14 = extractvalue { ptr, i64 } { ptr @luce.text.0, i64 16 }, 0
%15 = extractvalue { ptr, i64 } { ptr @luce.text.0, i64 16 }, 1
call void @luce_rt_raise(ptr %1, i32 0, ptr %14, i64 %15)
call void @luce_rt_unwound(ptr %1, i32 0, i32 2)
ret i32 1
16:
store i64 %11, ptr %4, align 8
ret i32 0
}
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 i64, align 8
%7 = alloca i64, align 8
%8 = alloca { i8, i8, [6 x i8], i64, i64 }, align 8
store i64 %3, ptr %5, align 8
store i64 4294967295, ptr %6, align 8
store i64 4294967295, ptr %7, align 8
%9 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %8, i32 0, i32 0
store i8 4, ptr %9, align 1
%10 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %8, i32 0, i32 1
store i8 -1, ptr %10, align 1
%11 = extractvalue { ptr, i64 } { ptr @luce.text.1, i64 0 }, 0
%12 = ptrtoint ptr %11 to i64
%13 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %8, i32 0, i32 3
store i64 %12, ptr %13, align 8
%14 = extractvalue { ptr, i64 } { ptr @luce.text.1, i64 0 }, 1
%15 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %8, i32 0, i32 4
store i64 %14, ptr %15, align 8
%16 = alloca { i8, i8, [6 x i8], i64, i64 },i64 1, align 8
%17 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %16, i64 0
%18 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %17, i32 0, i32 0
store i8 2, ptr %18, align 1
%19 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %17, i32 0, i32 4
store i64 0, ptr %19, align 8
%20 = alloca { i8, i8, [6 x i8], i64, i64 }, align 8
%21 = alloca { i8, i8, [6 x i8], i64, i64 }, align 8
%22 = alloca { i8, i8, [6 x i8], i64, i64 }, align 8
%23 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %22, i32 0, i32 0
store i8 6, ptr %23, align 1
%24 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %22, i32 0, i32 4
store i64 0, ptr %24, align 8
%25 = alloca { i8, i8, [6 x i8], i64, i64 }, align 8
%26 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %25, i32 0, i32 0
store i8 2, ptr %26, align 1
%27 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %25, i32 0, i32 4
store i64 0, ptr %27, align 8
%28 = alloca { i8, i8, [6 x i8], i64, i64 }, align 8
%29 = alloca { i8, i8, [6 x i8], i64, i64 }, align 8
%30 = alloca { i8, i8, [6 x i8], i64, i64 }, align 8
%31 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %30, i32 0, i32 0
store i8 6, ptr %31, align 1
%32 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %30, i32 0, i32 4
store i64 0, ptr %32, align 8
br label %33
33:
%34 = load i64, ptr %5, align 8
%35 = trunc i64 %34 to i32
%36 = lshr i64 %34, 32
%37 = trunc i64 %36 to i32
%38 = icmp eq i32 %35, -1
br i1 %38, label %39, label %42, !prof !0
39:
%40 = extractvalue { ptr, i64 } { ptr @luce.text.2, i64 21 }, 0
%41 = extractvalue { ptr, i64 } { ptr @luce.text.2, i64 21 }, 1
call void @luce_rt_raise(ptr %1, i32 14, ptr %40, i64 %41)
call void @luce_rt_unwound(ptr %1, i32 1, i32 1)
ret i32 1
42:
%43 = getelementptr inbounds i8, ptr %1, i64 96
%44 = load ptr, ptr %43, align 8!alias.scope !1, !noalias !2
%45 = zext i32 %35 to i64
%46 = mul nsw i64 %45, 112
%47 = getelementptr inbounds i8, ptr %44, i64 %46
%48 = getelementptr inbounds i8, ptr %47, i64 96
%49 = load i32, ptr %48, align 4, !alias.scope !1, !noalias !2
%50 = icmp ne i32 %49, %37
br i1 %50, label %51, label %54, !prof !0
51:
%52 = extractvalue { ptr, i64 } { ptr @luce.text.3, i64 22 }, 0
%53 = extractvalue { ptr, i64 } { ptr @luce.text.3, i64 22 }, 1
call void @luce_rt_raise(ptr %1, i32 13, ptr %52, i64 %53)
call void @luce_rt_unwound(ptr %1, i32 1, i32 1)
ret i32 1
54:
%55 = and i32 %49, 1
%56 = icmp ne i32 %55, 0
br i1 %56, label %57, label %60, !prof !0
57:
%58 = extractvalue { ptr, i64 } { ptr @luce.text.3, i64 22 }, 0
%59 = extractvalue { ptr, i64 } { ptr @luce.text.3, i64 22 }, 1
call void @luce_rt_raise(ptr %1, i32 13, ptr %58, i64 %59)
call void @luce_rt_unwound(ptr %1, i32 1, i32 1)
ret i32 1
60:
%61 = getelementptr inbounds i8, ptr %47, i64 16
%62 = load i64, ptr %61, align 8!alias.scope !1, !noalias !2
%63 = load ptr, ptr %47, align 8, !alias.scope !1, !noalias !2
%64 = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 %62, i64 2)
%65 = extractvalue { i64, i1 } %64, 0
%66 = extractvalue { i64, i1 } %64, 1
br i1 %66, label %67, label %70, !prof !0
67:
%68 = extractvalue { ptr, i64 } { ptr @luce.text.0, i64 16 }, 0
%69 = extractvalue { ptr, i64 } { ptr @luce.text.0, i64 16 }, 1
call void @luce_rt_raise(ptr %1, i32 0, ptr %68, i64 %69)
call void @luce_rt_unwound(ptr %1, i32 1, i32 3)
ret i32 1
70:
%71 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %17, i32 0, i32 3
store i64 %65, ptr %71, align 8
%72 = call i32 @luce_rt_spawn(ptr %1, i64 0, ptr %16, i64 1, ptr %20)
%73 = icmp ne i32 %72, 0
br i1 %73, label %74, label %75, !prof !0
74:
call void @luce_rt_unwound(ptr %1, i32 1, i32 4)
ret i32 1
75:
%76 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %20, i32 0, i32 3
%77 = load i64, ptr %76, align 8
store i64 %77, ptr %7, align 8
%78 = load i64, ptr %7, align 8
%79 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %22, i32 0, i32 3
store i64 %78, ptr %79, align 8
%80 = call i32 @luce_rt_task_wait(ptr %1, ptr %22, ptr %21)
%81 = icmp ne i32 %80, 0
br i1 %81, label %82, label %83, !prof !0
82:
call void @luce_rt_unwound(ptr %1, i32 1, i32 7)
ret i32 1
83:
%84 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %21, i32 0, i32 3
%85 = load i64, ptr %84, align 8
%86 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %25, i32 0, i32 3
store i64 %85, ptr %86, align 8
%87 = call i32 @luce_rt_str(ptr %1, ptr %25, ptr %28)
%88 = icmp ne i32 %87, 0
br i1 %88, label %89, label %90, !prof !0
89:
call void @luce_rt_unwound(ptr %1, i32 1, i32 8)
ret i32 1
90:
%91 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %28, i32 0, i32 3
%92 = load i64, ptr %91, align 8
%93 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %28, i32 0, i32 1
%94 = load i8, ptr %93, align 1
%95 = icmp eq i8 %94, -1
%96 = inttoptr i64 %92 to ptr
%97 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %28, i32 0, i32 2
%98 = select i1 %95, ptr %96, ptr %97
%99 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %28, i32 0, i32 4
%100 = load i64, ptr %99, align 8
%101 = zext i8 %94 to i64
%102 = select i1 %95, i64 %100, i64 %101
%103 = insertvalue { ptr, i64 } poison, ptr %98, 0
%104 = insertvalue { ptr, i64 } %103, i64 %102, 1
call void @llvm.memcpy.inline.p0.p0.i64(ptr align 8 %8, ptr align 8 %28, i64 24, i1 false)
%105 = extractvalue { ptr, i64 } %104, 0
%106 = extractvalue { ptr, i64 } %104, 1
call void @luce_rt_effects_enter(ptr %1)
%107 = 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
%108 = load ptr, ptr %107, align 8
%109 = icmp eq ptr %108, null
br i1 %109, label %110, label %113, !prof !0
110:
%111 = extractvalue { ptr, i64 } { ptr @luce.text.4, i64 24 }, 0
%112 = extractvalue { ptr, i64 } { ptr @luce.text.4, i64 24 }, 1
call void @luce_rt_raise(ptr %1, i32 9, ptr %111, i64 %112)
call void @luce_rt_unwound(ptr %1, i32 1, i32 10)
ret i32 1
113:
%114 = 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
%115 = load ptr, ptr %114, align 8
%116 = call i32 %108(ptr %115, ptr %105, i64 %106)
call void @luce_rt_effects_leave(ptr %1)
%117 = icmp eq i32 %116, -1
br i1 %117, label %118, label %119, !prof !0
118:
call void @luce_rt_exhaust(ptr %1)
ret i32 1
119:
%120 = icmp ne i32 %116, 0
%121 = icmp ne i32 %116, 1
%122 = and i1 %120, %121
br i1 %122, label %123, label %126, !prof !0
123:
%124 = extractvalue { ptr, i64 } { ptr @luce.text.4, i64 24 }, 0
%125 = extractvalue { ptr, i64 } { ptr @luce.text.4, i64 24 }, 1
call void @luce_rt_raise(ptr %1, i32 9, ptr %124, i64 %125)
call void @luce_rt_unwound(ptr %1, i32 1, i32 10)
ret i32 1
126:
%127 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %8, i32 0, i32 3
%128 = load i64, ptr %127, align 8
%129 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %8, i32 0, i32 1
%130 = load i8, ptr %129, align 1
%131 = icmp eq i8 %130, -1
%132 = inttoptr i64 %128 to ptr
%133 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %8, i32 0, i32 2
%134 = select i1 %131, ptr %132, ptr %133
%135 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %8, i32 0, i32 4
%136 = load i64, ptr %135, align 8
%137 = zext i8 %130 to i64
%138 = select i1 %131, i64 %136, i64 %137
%139 = insertvalue { ptr, i64 } poison, ptr %134, 0
%140 = insertvalue { ptr, i64 } %139, i64 %138, 1
call void @luce_rt_drop_storage(ptr %1, ptr %8, ptr %29)
%141 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %29, i32 0, i32 3
%142 = load i64, ptr %141, align 8
%143 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %29, i32 0, i32 1
%144 = load i8, ptr %143, align 1
%145 = icmp eq i8 %144, -1
%146 = inttoptr i64 %142 to ptr
%147 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %29, i32 0, i32 2
%148 = select i1 %145, ptr %146, ptr %147
%149 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %29, i32 0, i32 4
%150 = load i64, ptr %149, align 8
%151 = zext i8 %144 to i64
%152 = select i1 %145, i64 %150, i64 %151
%153 = insertvalue { ptr, i64 } poison, ptr %148, 0
%154 = insertvalue { ptr, i64 } %153, i64 %152, 1
call void @llvm.memcpy.inline.p0.p0.i64(ptr align 8 %8, ptr align 8 %29, i64 24, i1 false)
%155 = load i64, ptr %7, align 8
%156 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %30, i32 0, i32 3
store i64 %155, ptr %156, align 8
%157 = call i32 @luce_rt_release(ptr %1, ptr %30)
%158 = icmp ne i32 %157, 0
br i1 %158, label %159, label %160, !prof !0
159:
call void @luce_rt_unwound(ptr %1, i32 1, i32 15)
ret i32 1
160:
ret i32 0
}
define internal i32 @luce.worker(ptr %0, ptr %1, i64 %2, ptr %3, i64 %4, ptr %5, i64 %6) {
7:
%8 = alloca i64, align 8
switch i64 %2, label %9 [
i64 0, label %10
]
9:
ret i32 1
10:
%11 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %3, i64 0
%12 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %11, i32 0, i32 3
%13 = load i64, ptr %12, align 8
%14 = call i32 @luce.0.square(ptr %0, ptr %1, i64 %6, i64 %13, ptr %8)
%15 = icmp eq i32 %14, 0
br i1 %15, label %16, label %21, !prof !3
16:
%17 = load i64, ptr %8, align 8
%18 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %5, i32 0, i32 0
store i8 2, ptr %18, align 1
%19 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %5, i32 0, i32 4
store i64 0, ptr %19, align 8
%20 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %5, i32 0, i32 3
store i64 %17, ptr %20, align 8
br label %21
21:
ret i32 %14
}
; 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 speculatable willreturn nofree nosync nocallback memory(none)
declare { i64, i1 } @llvm.sadd.with.overflow.i64(i64 %0, i64 %1) #0
; Function Attrs: nounwind memory(readwrite)
declare i32 @luce_rt_spawn(ptr nocapture nonnull noundef %0, i64 %1, ptr %2, i64 %3, ptr align 8 nocapture nonnull dereferenceable(24) writeonly noundef %4) #2
; Function Attrs: nounwind memory(readwrite)
declare i32 @luce_rt_task_wait(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 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) #3
; 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) #4
; Function Attrs: nounwind memory(readwrite)
declare void @luce_rt_effects_enter(ptr nocapture nonnull noundef %0) #2
; Function Attrs: nounwind willreturn memory(readwrite)
declare void @luce_rt_effects_leave(ptr nocapture nonnull noundef %0) #5
; Function Attrs: nounwind cold willreturn memory(argmem: write)
declare void @luce_rt_exhaust(ptr nocapture nonnull noundef %0) #6
; 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) #7
; 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) #2
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 = 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 33
%64 = load ptr, ptr %63, align 8
%65 = 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 34
%66 = load ptr, ptr %65, align 8
call void @luce_rt_workers_install(ptr %13, ptr %5, ptr %64, ptr %66, ptr %0, ptr @luce.worker, i64 %12)
%67 = icmp slt i64 %12, 1
br i1 %67, label %68, label %69, !prof !0
68:
call void @luce_rt_raise(ptr %13, i32 6, ptr @luce.text.8, i64 19)
store i32 1, ptr %3, align 8
br label %77
69:
%70 = alloca { i8, i8, [6 x i8], i64, i64 }, align 8
%71 = 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
%72 = load ptr, ptr %71, align 8
%73 = 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
%74 = load ptr, ptr %73, align 8
%75 = call i32 @luce_rt_args_list(ptr %13, ptr %5, ptr %72, ptr %74, ptr %70)
%76 = icmp ne i32 %75, 0
br i1 %76, label %81, label %82, !prof !0
77:
%78 = load i32, ptr %3, align 8
%79 = icmp eq i32 %78, 1
%80 = icmp eq i32 %78, 2
br i1 %79, label %87, label %90, !prof !0
81:
store i32 1, ptr %3, align 8
br label %77
82:
%83 = getelementptr inbounds { i8, i8, [6 x i8], i64, i64 }, ptr %70, i32 0, i32 3
%84 = load i64, ptr %83, align 8
%85 = call i32 @luce.1.main(ptr %0, ptr %13, i64 %12, i64 %84)
store i32 %85, ptr %3, align 8
%86 = call i32 @luce_rt_release(ptr %13, ptr %70)
br label %77
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 2
%89 = load ptr, ptr %88, align 8
call void @luce_rt_report(ptr %13, ptr %5, ptr %89)
br label %90
90:
br i1 %80, label %91, label %94, !prof !0
91:
%92 = 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
%93 = load ptr, ptr %92, align 8
call void @luce_rt_report_error(ptr %13, ptr %5, ptr %93)
br label %94
94:
%95 = call i32 @luce_rt_status(ptr %13, i32 %78)
%96 = icmp eq i32 %95, 2
%97 = 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
%98 = load ptr, ptr %97, align 8
%99 = icmp eq ptr %98, null
%100 = or i1 %99, %96
br i1 %100, label %101, label %102
101:
call void @luce_rt_close(ptr %13)
ret i32 %95
102:
%103 = call i64 @luce_rt_leaked(ptr %13)
call void %98(ptr %5, i64 %103)
br label %101
}
; Function Attrs: nounwind willreturn memory(argmem: read, inaccessiblemem: readwrite)
declare noalias ptr @luce_rt_open(ptr readonly %0, i64 %1) #8
; 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) #9
; 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) #5
; 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) #9
; Function Attrs: nounwind willreturn memory(argmem: readwrite)
declare void @luce_rt_workers_install(ptr nocapture nonnull noundef %0, ptr %1, ptr %2, ptr %3, ptr %4, ptr %5, i64 %6) #9
; 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) #2
; 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) #2
attributes #0 = { nounwind speculatable willreturn nofree nosync nocallback memory(none) }
attributes #1 = { nounwind cold willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) }
attributes #2 = { nounwind memory(readwrite) }
attributes #3 = { nounwind willreturn memory(read, argmem: readwrite, inaccessiblemem: readwrite) }
attributes #4 = { nounwind willreturn nofree nocallback memory(argmem: readwrite) }
attributes #5 = { nounwind willreturn memory(readwrite) }
attributes #6 = { nounwind cold willreturn memory(argmem: write) }
attributes #7 = { nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) }
attributes #8 = { nounwind willreturn memory(argmem: read, inaccessiblemem: readwrite) }
attributes #9 = { nounwind willreturn memory(argmem: readwrite) }
attributes #10 = { cold }
attributes #11 = { nounwind willreturn memory(argmem: read) }
!0 = !{!"branch_weights", i32 1, i32 2000}
!1 = !{!4}
!2 = !{!5}
!3 = !{!"branch_weights", i32 2000, i32 1}
!4 = !{!"luce.rows", !6}
!5 = !{!"luce.elements", !6}
!6 = !{!"luce.alias"}
ARM64 object code. LLVM selected these instructions, registers, calls, and branch conditions for this target.
open assembly fileARM64 instruction guide hover, focus, or tap dotted terms
x8 is a 64-bit register; w8 is its low 32 bits. A leading # marks a constant, brackets describe a memory address, and conditional instructions read the processor flags set by the preceding arithmetic or comparison.
Hover or focus a dotted term in the file for its explanation. On a touch screen, tap a term to keep the note open and tap elsewhere to close it. The list includes the operations that appear in this file.
mov- Copies a register value or loads a small constant. Calls also use it to place arguments in the required registers.
add- Adds registers or a constant. Address setup and stack restoration frequently use this instruction.
sub- Subtracts registers or a constant. Function prologues use it to reserve stack space.
adds- Adds and updates the negative, zero, carry, and overflow flags for a following conditional instruction.
cmp- Performs a subtraction solely to set condition flags; a following branch or select consumes those flags.
cmn- Performs an addition solely to set condition flags. The checked multiply-by-two path uses it to recognize unsafe inputs.
csel- Selects one of two registers from the current condition flags. The clamp uses it to choose the doubled value or limit.
ldr- Loads a register from memory using a scaled address offset.
str- Stores one register into memory using a scaled address offset.
ldp- Loads two adjacent registers, often restoring saved registers or reading neighboring fields.
stp- Stores two adjacent registers, often saving the caller's registers in a function prologue.
ldur- Loads from an unscaled byte offset, which is useful for stack slots below the frame pointer.
stur- Stores to an unscaled byte offset, which is useful for stack slots below the frame pointer.
strb- Stores the low byte of a register.
ldurb- Loads one byte using an unscaled byte offset.
sturb- Stores one byte using an unscaled byte offset.
adrp- Loads the page address of a symbol. The linker fills in the final page-relative relocation.
bl- Calls a direct target and records the return address in
x30. blr- Calls the function address held in a register, as required for host callbacks and function values.
b- Jumps to another instruction address.
b.eq- Branches when the previous comparison reported equality.
b.ne- Branches when the previous comparison reported different values.
b.le- Branches when the signed left operand was smaller or equal.
b.hs- Branches when an unsigned comparison found higher-or-same, represented by a set carry flag.
b.vs- Branches when the arithmetic overflow flag is set.
cbz- Compares a register with zero and branches when it is zero.
cbnz- Compares a register with zero and branches when it contains a nonzero value.
tbnz- Tests one selected bit and branches when that bit is set; packed runtime flags use this form.
lsr- Shifts bits right and fills with zero, often extracting the upper field of a packed handle.
mul- Multiplies the low 64-bit operands and writes the low 64-bit result.
smulh- Returns the upper half of a signed 128-bit product, which helps verify signed multiplication overflow.
umaddl- Widens two 32-bit unsigned operands, multiplies them, and adds a 64-bit base address.
orr- Combines bits, commonly setting tag or flag bits in a packed value.
ret- Returns to the address in
x30and ends the current machine function.
/Users/sedov/Dev/luciaos/www/lucelang/out/traces/workers.o: file format mach-o arm64
Disassembly of section __TEXT,__text:
0000000000000000 <ltmp0>:
; luce.worker():
0: cbz x2, 0xc <ltmp0+0xc>
4: mov w0, #0x1 ; =1
8: ret
c: ldr x9, [x3, #0x8]
10: mul x8, x9, x9
14: smulh x9, x9, x9
18: cmp x9, x8, asr #63
1c: b.ne 0x34 <ltmp0+0x34>
20: mov w0, wzr
24: mov w9, #0x2 ; =2
28: stp x8, xzr, [x5, #0x8]
2c: strb w9, [x5]
30: ret
34: stp x20, x19, [sp, #-0x20]!
38: adrp x2, 0x0 <ltmp0>
3c: add x2, x2, #0x0
40: mov x0, x1
44: mov x19, x1
48: mov w1, wzr
4c: mov w3, #0x10 ; =16
50: stp x29, x30, [sp, #0x10]
54: bl 0x54 <ltmp0+0x54>
58: mov x0, x19
5c: mov w1, wzr
60: mov w2, #0x2 ; =2
64: bl 0x64 <ltmp0+0x64>
68: ldp x29, x30, [sp, #0x10]
6c: mov w0, #0x1 ; =1
70: ldp x20, x19, [sp], #0x20
74: ret
0000000000000078 <_luce_main>:
; luce_main():
78: stp x28, x27, [sp, #-0x60]!
7c: stp x26, x25, [sp, #0x10]
80: stp x24, x23, [sp, #0x20]
84: stp x22, x21, [sp, #0x30]
88: stp x20, x19, [sp, #0x40]
8c: stp x29, x30, [sp, #0x50]
90: add x29, sp, #0x50
94: sub sp, sp, #0xe0
98: ldr x8, [x0, #0x70]
9c: ldr x19, [x0]
a0: mov x20, x0
a4: cbz x8, 0xd0 <_luce_main+0x58>
a8: mov x0, x19
ac: blr x8
b0: mov x22, x0
b4: adrp x0, 0x0 <ltmp0>
b8: add x0, x0, #0x0
bc: mov w1, #0x2 ; =2
c0: mov w23, #0x2 ; =2
c4: bl 0xc4 <_luce_main+0x4c>
c8: cbnz x0, 0xec <_luce_main+0x74>
cc: b 0x330 <_luce_main+0x2b8>
d0: mov w22, #0x100 ; =256
d4: adrp x0, 0x0 <ltmp0>
d8: add x0, x0, #0x0
dc: mov w1, #0x2 ; =2
e0: mov w23, #0x2 ; =2
e4: bl 0xe4 <_luce_main+0x6c>
e8: cbz x0, 0x330 <_luce_main+0x2b8>
ec: ldp x3, x4, [x20, #0x1b0]
f0: mov x21, x0
f4: ldp x5, x6, [x20, #0x1c0]
f8: ldr x2, [x20, #0xe0]
fc: ldp x8, x9, [x20, #0xf8]
100: ldr x7, [x20, #0x1d0]
104: ldur q0, [x20, #0xe8]
108: sub sp, sp, #0x20
10c: mov x1, x19
110: stp x8, x9, [sp, #0x10]
114: str q0, [sp]
118: bl 0x118 <_luce_main+0xa0>
11c: add sp, sp, #0x20
120: ldp x2, x3, [x20, #0x180]
124: mov x0, x21
128: ldp x4, x5, [x20, #0x190]
12c: mov x1, x19
130: ldr x6, [x20, #0x1a0]
134: bl 0x134 <_luce_main+0xbc>
138: ldp x8, x9, [x20, #0x170]
13c: ldp x2, x3, [x20, #0x140]
140: ldp x4, x5, [x20, #0x150]
144: ldp x6, x7, [x20, #0x160]
148: stp x8, x9, [sp, #-0x10]!
14c: mov x0, x21
150: mov x1, x19
154: bl 0x154 <_luce_main+0xdc>
158: add sp, sp, #0x10
15c: ldp x2, x3, [x20, #0x108]
160: adrp x5, 0x0 <ltmp0>
164: add x5, x5, #0x0
168: mov x0, x21
16c: mov x1, x19
170: mov x4, x20
174: mov x6, x22
178: bl 0x178 <_luce_main+0x100>
17c: cmp x22, #0x0
180: b.le 0x394 <_luce_main+0x31c>
184: sub x22, sp, #0x20
188: mov sp, x22
18c: ldp x2, x3, [x20, #0x20]
190: mov x0, x21
194: mov x1, x19
198: mov x4, x22
19c: bl 0x19c <_luce_main+0x124>
1a0: cbnz w0, 0x458 <_luce_main+0x3e0>
1a4: mov w9, #0x2 ; =2
1a8: ldr x8, [x22, #0x8]
1ac: mov w10, #0x6 ; =6
1b0: sturb w9, [x29, #-0x88]
1b4: sturb w9, [x29, #-0xe8]
1b8: sub x9, x29, #0x30
1bc: cmn w8, #0x1
1c0: sturb w10, [x9, #-0x100]
1c4: sub x9, x29, #0x20
1c8: stur xzr, [x29, #-0x78]
1cc: sturb w10, [x29, #-0xd0]
1d0: stur xzr, [x29, #-0xc0]
1d4: stur xzr, [x29, #-0xd8]
1d8: stur xzr, [x9, #-0x100]
1dc: b.eq 0x3b0 <_luce_main+0x338>
1e0: mov w9, #0x70 ; =112
1e4: ldr x10, [x21, #0x60]
1e8: umaddl x9, w8, w9, x10
1ec: lsr x8, x8, #32
1f0: ldr w10, [x9, #0x60]
1f4: cmp w10, w8
1f8: b.ne 0x354 <_luce_main+0x2dc>
1fc: tbnz w8, #0x0, 0x354 <_luce_main+0x2dc>
200: ldr x8, [x9, #0x10]
204: adds x8, x8, #0x2
208: b.vs 0x3d8 <_luce_main+0x360>
20c: sub x2, x29, #0x88
210: sub x4, x29, #0xa0
214: mov x0, x21
218: mov x1, xzr
21c: mov w3, #0x1 ; =1
220: stur x8, [x29, #-0x80]
224: bl 0x224 <_luce_main+0x1ac>
228: cbnz w0, 0x400 <_luce_main+0x388>
22c: ldur x24, [x29, #-0x98]
230: sub x1, x29, #0xd0
234: sub x2, x29, #0xb8
238: mov x0, x21
23c: stur x24, [x29, #-0xc8]
240: bl 0x240 <_luce_main+0x1c8>
244: cbnz w0, 0x410 <_luce_main+0x398>
248: ldur x8, [x29, #-0xb0]
24c: sub x1, x29, #0xe8
250: sub x2, x29, #0x100
254: mov x0, x21
258: stur x8, [x29, #-0xe0]
25c: bl 0x25c <_luce_main+0x1e4>
260: cbnz w0, 0x420 <_luce_main+0x3a8>
264: ldp x23, x25, [x29, #-0xf8]
268: mov x0, x21
26c: ldur q0, [x29, #-0x100]
270: ldurb w26, [x29, #-0xff]
274: stur q0, [x29, #-0x70]
278: stur x25, [x29, #-0x60]
27c: bl 0x27c <_luce_main+0x204>
280: ldr x8, [x20, #0x8]
284: cbz x8, 0x36c <_luce_main+0x2f4>
288: sub x9, x29, #0x100
28c: cmp w26, #0xff
290: ldr x0, [x20]
294: orr x9, x9, #0x2
298: csel x2, x25, x26, eq
29c: csel x1, x23, x9, eq
2a0: blr x8
2a4: mov w23, w0
2a8: mov x0, x21
2ac: bl 0x2ac <_luce_main+0x234>
2b0: cmn w23, #0x1
2b4: b.eq 0x430 <_luce_main+0x3b8>
2b8: cmp w23, #0x2
2bc: b.hs 0x36c <_luce_main+0x2f4>
2c0: sub x1, x29, #0x70
2c4: sub x2, x29, #0x118
2c8: mov x0, x21
2cc: bl 0x2cc <_luce_main+0x254>
2d0: sub x8, x29, #0x28
2d4: sub x1, x29, #0x130
2d8: mov x0, x21
2dc: stur x24, [x8, #-0x100]
2e0: bl 0x2e0 <_luce_main+0x268>
2e4: cbnz w0, 0x43c <_luce_main+0x3c4>
2e8: mov x0, x21
2ec: mov x1, x22
2f0: bl 0x2f0 <_luce_main+0x278>
2f4: mov w1, wzr
2f8: mov x0, x21
2fc: bl 0x2fc <_luce_main+0x284>
300: mov w23, w0
304: cmp w0, #0x2
308: b.eq 0x328 <_luce_main+0x2b0>
30c: ldr x20, [x20, #0x18]
310: cbz x20, 0x328 <_luce_main+0x2b0>
314: mov x0, x21
318: bl 0x318 <_luce_main+0x2a0>
31c: mov x1, x0
320: mov x0, x19
324: blr x20
328: mov x0, x21
32c: bl 0x32c <_luce_main+0x2b4>
330: mov w0, w23
334: sub sp, x29, #0x50
338: ldp x29, x30, [sp, #0x50]
33c: ldp x20, x19, [sp, #0x40]
340: ldp x22, x21, [sp, #0x30]
344: ldp x24, x23, [sp, #0x20]
348: ldp x26, x25, [sp, #0x10]
34c: ldp x28, x27, [sp], #0x60
350: ret
354: adrp x2, 0x0 <ltmp0>
358: add x2, x2, #0x0
35c: mov x0, x21
360: mov w1, #0xd ; =13
364: mov w3, #0x16 ; =22
368: b 0x3c4 <_luce_main+0x34c>
36c: adrp x2, 0x0 <ltmp0>
370: add x2, x2, #0x0
374: mov x0, x21
378: mov w1, #0x9 ; =9
37c: mov w3, #0x18 ; =24
380: bl 0x380 <_luce_main+0x308>
384: mov x0, x21
388: mov w1, #0x1 ; =1
38c: mov w2, #0xa ; =10
390: b 0x448 <_luce_main+0x3d0>
394: adrp x2, 0x0 <ltmp0>
398: add x2, x2, #0x0
39c: mov x0, x21
3a0: mov w1, #0x6 ; =6
3a4: mov w3, #0x13 ; =19
3a8: bl 0x3a8 <_luce_main+0x330>
3ac: b 0x458 <_luce_main+0x3e0>
3b0: adrp x2, 0x0 <ltmp0>
3b4: add x2, x2, #0x0
3b8: mov x0, x21
3bc: mov w1, #0xe ; =14
3c0: mov w3, #0x15 ; =21
3c4: bl 0x3c4 <_luce_main+0x34c>
3c8: mov x0, x21
3cc: mov w1, #0x1 ; =1
3d0: mov w2, #0x1 ; =1
3d4: b 0x448 <_luce_main+0x3d0>
3d8: adrp x2, 0x0 <ltmp0>
3dc: add x2, x2, #0x0
3e0: mov x0, x21
3e4: mov w1, wzr
3e8: mov w3, #0x10 ; =16
3ec: bl 0x3ec <_luce_main+0x374>
3f0: mov x0, x21
3f4: mov w1, #0x1 ; =1
3f8: mov w2, #0x3 ; =3
3fc: b 0x448 <_luce_main+0x3d0>
400: mov x0, x21
404: mov w1, #0x1 ; =1
408: mov w2, #0x4 ; =4
40c: b 0x448 <_luce_main+0x3d0>
410: mov x0, x21
414: mov w1, #0x1 ; =1
418: mov w2, #0x7 ; =7
41c: b 0x448 <_luce_main+0x3d0>
420: mov x0, x21
424: mov w1, #0x1 ; =1
428: mov w2, #0x8 ; =8
42c: b 0x448 <_luce_main+0x3d0>
430: mov x0, x21
434: bl 0x434 <_luce_main+0x3bc>
438: b 0x44c <_luce_main+0x3d4>
43c: mov x0, x21
440: mov w1, #0x1 ; =1
444: mov w2, #0xf ; =15
448: bl 0x448 <_luce_main+0x3d0>
44c: mov x0, x21
450: mov x1, x22
454: bl 0x454 <_luce_main+0x3dc>
458: ldr x2, [x20, #0x10]
45c: mov x0, x21
460: mov x1, x19
464: bl 0x464 <_luce_main+0x3ec>
468: mov w1, #0x1 ; =1
46c: mov x0, x21
470: bl 0x470 <_luce_main+0x3f8>
474: mov w23, w0
478: cmp w0, #0x2
47c: b.ne 0x30c <_luce_main+0x294>
480: b 0x328 <_luce_main+0x2b0>
Two heaps connected by value transfer
caller runtime
points twice at nested list B
handles in table 1worker runtime
both edges point at one copied B′
handles in table 2The copier preserves aliases and cycles inside the transferred snapshot through a source-to-destination map. The caller retains its independent graph. Each object row belongs to one heap and one thread, which prevents the two copies from participating in the same data race.
What can cross
Sendable
Scalars, text/bytes values, structs/enums/unions built from permitted fields, and list/map/array graphs of permitted values.
Runtime-local values
Classes, resources, tasks, function/interface values, closure environments, weak storage, and values containing any of them stay in their original runtime.
The check is transitive and static. A struct is sendable when every field eventually reaches only permitted value types. A field that reaches a class or weak handle keeps the containing value in its original runtime.
The spawn lifecycle
- Check declared target
spawnstarts a declared function, so the copied arguments fully describe the worker's input. - Create worker runtimeAllocate a private heap, nursery entry, and call-depth budget.
- Copy argumentsRebuild the permitted graph with rollback if allocation fails.
- Run and capture outcomeSuccess values, recoverable errors, traps, and exit state are recorded for the task.
- Transfer permitted resultThe answer is copied back into the waiting runtime under the same boundary.
Task is an ARC resource
spawn returns a task[...] reference. Aliases share one one-shot result state. wait() observes it once. If the last task reference disappears while the worker is unfinished and unobserved, last release joins it and completes the task lifecycle.
Host effects remain explicit
A worker can use installed host capabilities through its own run context. The runtime's effect lock serializes the host channel where required. Classes, closures, and resources created by the worker remain in its local heap and are released there before the worker runtime closes.
The programming model created by isolation
Parallelism begins at spawn. Communication consists of value transfer and task completion, and each heap is accessed by its owning thread. The language therefore exposes spawn, transferred values, and wait() as its concurrency model.