Resources and the host boundary
Files, clocks, terminals, processes, networks, and graphics belong to the program's host. Luce reaches them through a versioned table of callbacks. A standard-library wrapper requests one named capability, and an absent capability produces host_unavailable.
Follow one host call
print is the smallest visible host effect. MIR names the intrinsic. LLVM loads the print callback from the host table and handles its status. ARM64 performs the indirect call with blr; the operating system work remains outside generated code.
Luce source. Names and indentation describe the program for a reader.
open source file
func main():
print("hello from the host")
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.
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.
const- Creates a typed literal such as 2 or 10 inside the instruction stream.
intrinsic NAME- Invokes a language operation with runtime rules recorded by the compiler. The name identifies the operation.
intrinsic print- Sends text through the installed host output capability.
ret- Returns the current function's result to its caller and closes the current control-flow path.
func main() -> None
b0:
r0 = const data#0
intrinsic print, r0
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. 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.
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.
ret- Returns a status or value and ends the current basic block.
@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_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_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.
!prof- Attaches branch-probability metadata so LLVM can place common and failure paths efficiently.
; ModuleID = '/Users/sedov/Dev/luciaos/www/lucelang/examples/host.luc'
source_filename = "/Users/sedov/Dev/luciaos/www/lucelang/examples/host.luc"
target triple = "arm64-apple-darwin24.6.0"
@luce.text.0 = private unnamed_addr constant [19 x i8] c"hello from the host"
@luce.text.1 = private unnamed_addr constant [24 x i8] c"host service unavailable"
@luce.text.2 = private unnamed_addr constant [4 x i8] c"main"
@luce.text.3 = private unnamed_addr constant [55 x i8] c"/Users/sedov/Dev/luciaos/www/lucelang/examples/host.luc"
@luce.origins.0 = private constant [3 x { i32, i32 }] [{ i32, i32 } { i32 2, i32 5 }, { i32, i32 } { i32 2, i32 5 }, { i32, i32 } { i32 2, i32 5 }]
@luce.functions = private constant [1 x { ptr, i64, ptr, i64, ptr, i64 }] [{ ptr, i64, ptr, i64, ptr, i64 } { ptr @luce.text.2, i64 4, ptr @luce.text.3, i64 55, ptr @luce.origins.0, i64 3 }]
@luce.text.4 = 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.main(ptr align 8 nocapture readonly nonnull dereferenceable(472) noundef %0, ptr align 8 nocapture nonnull noundef %1, i64 noundef %2) {
3:
br label %4
4:
%5 = extractvalue { ptr, i64 } { ptr @luce.text.0, i64 19 }, 0
%6 = extractvalue { ptr, i64 } { ptr @luce.text.0, i64 19 }, 1
%7 = 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
%8 = load ptr, ptr %7, align 8
%9 = icmp eq ptr %8, null
br i1 %9, label %10, label %13, !prof !0
10:
%11 = extractvalue { ptr, i64 } { ptr @luce.text.1, i64 24 }, 0
%12 = extractvalue { ptr, i64 } { ptr @luce.text.1, i64 24 }, 1
call void @luce_rt_raise(ptr %1, i32 9, ptr %11, i64 %12)
call void @luce_rt_unwound(ptr %1, i32 0, i32 1)
ret i32 1
13:
%14 = 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
%15 = load ptr, ptr %14, align 8
%16 = call i32 %8(ptr %15, ptr %5, i64 %6)
%17 = icmp eq i32 %16, -1
br i1 %17, label %18, label %19, !prof !0
18:
call void @luce_rt_exhaust(ptr %1)
ret i32 1
19:
%20 = icmp ne i32 %16, 0
%21 = icmp ne i32 %16, 1
%22 = and i1 %20, %21
br i1 %22, label %23, label %26, !prof !0
23:
%24 = extractvalue { ptr, i64 } { ptr @luce.text.1, i64 24 }, 0
%25 = extractvalue { ptr, i64 } { ptr @luce.text.1, i64 24 }, 1
call void @luce_rt_raise(ptr %1, i32 9, ptr %24, i64 %25)
call void @luce_rt_unwound(ptr %1, i32 0, i32 1)
ret i32 1
26:
ret i32 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) #0
; Function Attrs: nounwind cold willreturn memory(argmem: readwrite, inaccessiblemem: readwrite)
declare void @luce_rt_unwound(ptr nocapture nonnull noundef %0, i32 %1, i32 %2) #0
; Function Attrs: nounwind cold willreturn memory(argmem: write)
declare void @luce_rt_exhaust(ptr nocapture nonnull noundef %0) #1
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 1)
%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 %67
65:
%66 = call i32 @luce.0.main(ptr %0, ptr %13, i64 %12)
store i32 %66, ptr %3, align 8
br label %67
67:
%68 = load i32, ptr %3, align 8
%69 = icmp eq i32 %68, 1
%70 = icmp eq i32 %68, 2
br i1 %69, label %71, label %74, !prof !0
71:
%72 = 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
%73 = load ptr, ptr %72, align 8
call void @luce_rt_report(ptr %13, ptr %5, ptr %73)
br label %74
74:
br i1 %70, label %75, label %78, !prof !0
75:
%76 = 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
%77 = load ptr, ptr %76, align 8
call void @luce_rt_report_error(ptr %13, ptr %5, ptr %77)
br label %78
78:
%79 = call i32 @luce_rt_status(ptr %13, i32 %68)
%80 = icmp eq i32 %79, 2
%81 = 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
%82 = load ptr, ptr %81, align 8
%83 = icmp eq ptr %82, null
%84 = or i1 %83, %80
br i1 %84, label %85, label %86
85:
call void @luce_rt_close(ptr %13)
ret i32 %79
86:
%87 = call i64 @luce_rt_leaked(ptr %13)
call void %82(ptr %5, i64 %87)
br label %85
}
; Function Attrs: nounwind willreturn memory(argmem: read, inaccessiblemem: readwrite)
declare noalias ptr @luce_rt_open(ptr readonly %0, i64 %1) #2
; 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) #3
; 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) #4
; 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) #3
; Function Attrs: cold
declare void @luce_rt_report(ptr nocapture nonnull noundef %0, ptr %1, ptr %2) #5
; Function Attrs: cold
declare void @luce_rt_report_error(ptr nocapture nonnull noundef %0, ptr %1, ptr %2) #5
; Function Attrs: nounwind willreturn memory(argmem: read)
declare i32 @luce_rt_status(ptr nocapture nonnull noundef %0, i32 %1) #6
; Function Attrs: nounwind willreturn memory(argmem: read)
declare i64 @luce_rt_leaked(ptr nocapture nonnull noundef %0) #6
; Function Attrs: nounwind memory(readwrite)
declare void @luce_rt_close(ptr nocapture nonnull noundef %0) #7
attributes #0 = { nounwind cold willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) }
attributes #1 = { nounwind cold willreturn memory(argmem: write) }
attributes #2 = { nounwind willreturn memory(argmem: read, inaccessiblemem: readwrite) }
attributes #3 = { nounwind willreturn memory(argmem: readwrite) }
attributes #4 = { nounwind willreturn memory(readwrite) }
attributes #5 = { cold }
attributes #6 = { nounwind willreturn memory(argmem: read) }
attributes #7 = { nounwind memory(readwrite) }
!0 = !{!"branch_weights", i32 1, i32 2000}
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.
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.
cset- Writes 1 or 0 according to a condition, producing a Boolean value from processor flags.
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.
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.hs- Branches when an unsigned comparison found higher-or-same, represented by a set carry flag.
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.
ret- Returns to the address in
x30and ends the current machine function.
/Users/sedov/Dev/luciaos/www/lucelang/out/traces/host.o: file format mach-o arm64
Disassembly of section __TEXT,__text:
0000000000000000 <ltmp0>:
; luce_main():
0: sub sp, sp, #0x50
4: stp x22, x21, [sp, #0x20]
8: stp x20, x19, [sp, #0x30]
c: stp x29, x30, [sp, #0x40]
10: ldr x8, [x0, #0x70]
14: ldr x19, [x0]
18: mov x20, x0
1c: cbz x8, 0x12c <ltmp0+0x12c>
20: mov x0, x19
24: blr x8
28: cmp x0, #0x1
2c: cset w22, lt
30: adrp x0, 0x0 <ltmp0>
34: add x0, x0, #0x0
38: mov w1, #0x1 ; =1
3c: bl 0x3c <ltmp0+0x3c>
40: cbz x0, 0x144 <ltmp0+0x144>
44: ldp x3, x4, [x20, #0x1b0]
48: mov x1, x19
4c: ldp x5, x6, [x20, #0x1c0]
50: mov x21, x0
54: ldp x8, x9, [x20, #0xf8]
58: ldr x2, [x20, #0xe0]
5c: ldr x7, [x20, #0x1d0]
60: ldur q0, [x20, #0xe8]
64: stp x8, x9, [sp, #0x10]
68: str q0, [sp]
6c: bl 0x6c <ltmp0+0x6c>
70: ldp x2, x3, [x20, #0x180]
74: mov x0, x21
78: ldp x4, x5, [x20, #0x190]
7c: mov x1, x19
80: ldr x6, [x20, #0x1a0]
84: bl 0x84 <ltmp0+0x84>
88: ldp x2, x3, [x20, #0x140]
8c: mov x0, x21
90: ldp x4, x5, [x20, #0x150]
94: mov x1, x19
98: ldp x6, x7, [x20, #0x160]
9c: ldp x8, x9, [x20, #0x170]
a0: stp x8, x9, [sp]
a4: bl 0xa4 <ltmp0+0xa4>
a8: cbnz w22, 0x18c <ltmp0+0x18c>
ac: ldr x8, [x20, #0x8]
b0: cbz x8, 0x160 <ltmp0+0x160>
b4: ldr x0, [x20]
b8: adrp x1, 0x0 <ltmp0>
bc: add x1, x1, #0x0
c0: mov w2, #0x13 ; =19
c4: blr x8
c8: cmn w0, #0x1
cc: b.eq 0x1a8 <ltmp0+0x1a8>
d0: cmp w0, #0x2
d4: b.hs 0x160 <ltmp0+0x160>
d8: mov w1, wzr
dc: mov x0, x21
e0: bl 0xe0 <ltmp0+0xe0>
e4: mov w22, w0
e8: cmp w0, #0x2
ec: b.eq 0x10c <ltmp0+0x10c>
f0: ldr x20, [x20, #0x18]
f4: cbz x20, 0x10c <ltmp0+0x10c>
f8: mov x0, x21
fc: bl 0xfc <ltmp0+0xfc>
100: mov x1, x0
104: mov x0, x19
108: blr x20
10c: mov x0, x21
110: bl 0x110 <ltmp0+0x110>
114: mov w0, w22
118: ldp x29, x30, [sp, #0x40]
11c: ldp x20, x19, [sp, #0x30]
120: ldp x22, x21, [sp, #0x20]
124: add sp, sp, #0x50
128: ret
12c: mov w22, wzr
130: adrp x0, 0x0 <ltmp0>
134: add x0, x0, #0x0
138: mov w1, #0x1 ; =1
13c: bl 0x13c <ltmp0+0x13c>
140: cbnz x0, 0x44 <ltmp0+0x44>
144: mov w22, #0x2 ; =2
148: mov w0, w22
14c: ldp x29, x30, [sp, #0x40]
150: ldp x20, x19, [sp, #0x30]
154: ldp x22, x21, [sp, #0x20]
158: add sp, sp, #0x50
15c: ret
160: adrp x2, 0x0 <ltmp0>
164: add x2, x2, #0x0
168: mov x0, x21
16c: mov w1, #0x9 ; =9
170: mov w3, #0x18 ; =24
174: bl 0x174 <ltmp0+0x174>
178: mov x0, x21
17c: mov w1, wzr
180: mov w2, #0x1 ; =1
184: bl 0x184 <ltmp0+0x184>
188: b 0x1b0 <ltmp0+0x1b0>
18c: adrp x2, 0x0 <ltmp0>
190: add x2, x2, #0x0
194: mov x0, x21
198: mov w1, #0x6 ; =6
19c: mov w3, #0x13 ; =19
1a0: bl 0x1a0 <ltmp0+0x1a0>
1a4: b 0x1b0 <ltmp0+0x1b0>
1a8: mov x0, x21
1ac: bl 0x1ac <ltmp0+0x1ac>
1b0: ldr x2, [x20, #0x10]
1b4: mov x0, x21
1b8: mov x1, x19
1bc: bl 0x1bc <ltmp0+0x1bc>
1c0: mov w1, #0x1 ; =1
1c4: mov x0, x21
1c8: bl 0x1c8 <ltmp0+0x1c8>
1cc: mov w22, w0
1d0: cmp w0, #0x2
1d4: b.ne 0xf0 <ltmp0+0xf0>
1d8: b 0x10c <ltmp0+0x10c>
From public API to the world
std.filespublic fallible Luce API and File resource classBuiltinsynthetic names accepted only inside embedded standard sourceLuceHostoptional function slots installed by loom or standalone startHow embedded modules request host operations
Hosted standard modules use synthetic Builtin.NAME operations. Semantics recognizes those names only while compiling embedded standard-library source and lowers them to specific host-table operations. Project and package code uses the public std API, which keeps callback layout and raw handles behind library types.
What happens when a service is absent
Each effect slot in LuceHost is optional except the channels used to report how a run ended. Calling an absent slot traps host_unavailable. This makes the installed table the complete list of effects available to that run.
A host-free run performs pure computation. Any attempted file, clock, terminal, process, network, or graphics operation reports host_unavailable.
Raw handles stay behind library classes
The standard library represents a native descriptor with a private handle. Programs see files.File, network connections, windows, surfaces, processes, and similar library classes. Their private handle field follows ordinary ARC. The final strong release closes or releases the descriptor exactly once.
Service results have one convention
Fallible host services distinguish success, an ordinary service refusal, and allocation exhaustion. Returned text is borrowed for the callback only and copied into run-owned storage. A missing optional value clears out-parameters before the call, preventing an absent answer from reading uninitialized stack bytes.
How generated code and the host stay compatible
The host table's current version is 29, inserted from codegen/abi.zig. Field order determines the in-memory layout. Adding, removing, reordering, or changing the meaning or signature of a slot updates every host and generated access together and bumps the version. An artifact carrying an older ABI tag is rebuilt or rejected before it runs.