Renderingen-US

LLVM IR

MIR staging text for external LLVM tools. Also the route CUDA device programs take, via NVVM → PTX.

Part of the MIR lane. Every panel below is compiler output.

How to read it#

The widest ratio on the site, and the least surprising one: SSA form names every intermediate. Read it for what the compiler knows about your program, not as something to maintain.

Measured support#

CapableAnalyzableCoverage
33437390%

From the target matrix: how many corpus exempla lower to this target. Coverage is not a quality score — an emitter can lower a term and still erase a distinction.

Not fully supported#

Terms the matrix records as partial, planned, or unsupported for this target. A term here is a measured gap, not an omission.

CategoryTerms
Keywords — systems lane<a id="atomic"></a>atomic, <a id="clausura"></a>lambda, <a id="ex"></a>from, <a id="genus"></a>class, <a id="itera"></a>for, <a id="lista"></a>list, <a id="matrix"></a>matrix, <a id="numerus"></a>int, <a id="tensor"></a>tensor, <a id="vector"></a>vector
Operators — systems lane·, ⊗, ⊙, ![, !., !(, ↦, ?[, ?., ?(

Typed tensors#

Builds two shaped matrices, multiplies them, and reduces the product to a scalar. Exercises shape-bearing types and a reduction.

Faber source

reader locale
faber convert --to en — English reader surface
main {
    const list<f32> flat_a ← [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
    const list<f32> flat_b ← [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0]
    const tf32[] seed ← empty
    const tf32[2, 3] a ← seed.from_flat(flat_a, [2, 3])
    const tf32[3, 4] b ← seed.from_flat(flat_b, [3, 4])
    const tf32[2, 4] product ← a.matmul(b)
    const f32 mean ← product.mean()
    print mean
}
faber convert --to la — canonical Faber
incipit {
    fixum lista<f32> flat_a ← [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
    fixum lista<f32> flat_b ← [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0]
    fixum tf32[] seed ← vacua
    fixum tf32[2, 3] a ← seed.strue(flat_a, [2, 3])
    fixum tf32[3, 4] b ← seed.strue(flat_b, [3, 4])
    fixum tf32[2, 4] product ← a.matmul(b)
    fixum f32 mean ← product.media()
    nota mean
}
faber convert --to th-TH — Thai
เริ่ม {
    คงที่ รายการ<f32> flat_a ← [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
    คงที่ รายการ<f32> flat_b ← [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0]
    คงที่ tf32[] seed ← เซตว่าง
    คงที่ tf32[2, 3] a ← seed.สร้างจากข้อมูลแบน(flat_a, [2, 3])
    คงที่ tf32[3, 4] b ← seed.สร้างจากข้อมูลแบน(flat_b, [3, 4])
    คงที่ tf32[2, 4] product ← a.คูณเมทริกซ์(b)
    คงที่ f32 mean ← product.ค่าเฉลี่ย()
    บันทึก mean
}
faber convert --to zh-Hans — Simplified Chinese
入口 {
    常量 列表<f32> flat_a ← [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
    常量 列表<f32> flat_b ← [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0]
    常量 tf32[] seed ← 空集
    常量 tf32[2, 3] a ← seed.由扁平构造(flat_a, [2, 3])
    常量 tf32[3, 4] b ← seed.由扁平构造(flat_b, [3, 4])
    常量 tf32[2, 4] product ← a.矩阵乘法(b)
    常量 f32 mean ← product.均值()
    显示 mean
}
faber convert --to zh-Hant — Traditional Chinese
入口 {
    定值 列表<f32> flat_a ← [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
    定值 列表<f32> flat_b ← [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0]
    定值 tf32[] seed ← 空集
    定值 tf32[2, 3] a ← seed.由扁平建構(flat_a, [2, 3])
    定值 tf32[3, 4] b ← seed.由扁平建構(flat_b, [3, 4])
    定值 tf32[2, 4] product ← a.矩陣乘法(b)
    定值 f32 mean ← product.平均值()
    註記 mean
}
faber convert --to vi — Vietnamese
bắt_đầu {
    hằng danh_sách<f32> flat_a ← [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
    hằng danh_sách<f32> flat_b ← [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0]
    hằng tf32[] seed ← tập_rỗng
    hằng tf32[2, 3] a ← seed.dựng_từ_phẳng(flat_a, [2, 3])
    hằng tf32[3, 4] b ← seed.dựng_từ_phẳng(flat_b, [3, 4])
    hằng tf32[2, 4] product ← a.nhân_ma_trận(b)
    hằng f32 mean ← product.trung_bình()
    ghi_chú mean
}
faber convert --to ar — Arabic
بداية {
    ثابت قائمة<f32> flat_a ← [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
    ثابت قائمة<f32> flat_b ← [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0]
    ثابت tf32[] seed ← فارغ
    ثابت tf32[2, 3] a ← seed.ابن_من_مسطح(flat_a, [2, 3])
    ثابت tf32[3, 4] b ← seed.ابن_من_مسطح(flat_b, [3, 4])
    ثابت tf32[2, 4] product ← a.ضرب_المصفوفات(b)
    ثابت f32 mean ← product.المتوسط()
    اعرض mean
}
faber convert --to hi — Hindi
आरंभ {
    स्थिर सूची<f32> flat_a ← [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
    स्थिर सूची<f32> flat_b ← [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0]
    स्थिर tf32[] seed ← खाली
    स्थिर tf32[2, 3] a ← seed.समतल_से_बनाओ(flat_a, [2, 3])
    स्थिर tf32[3, 4] b ← seed.समतल_से_बनाओ(flat_b, [3, 4])
    स्थिर tf32[2, 4] product ← a.आव्यूह_गुणन(b)
    स्थिर f32 mean ← product.माध्य()
    दिखाओ mean
}

LLVM IR — 10 lines in, 356 out (35.6×)

; Generated by radix MIR LLVM IR probe - experimental artifact.
%FaberRtSliceV1 = type { ptr, i64 }
%FaberRtExitV1 = type i64
%FaberRtPtrResultV1 = type { i32, ptr }
%FaberRtStatusV1 = type { i32 }
@__faber_rt_v1_context = linkonce_odr global ptr null
@__faber_rt_v1_status = linkonce_odr global i32 0
declare void @__faber_rt_v1_fatal(ptr, %FaberRtSliceV1) noreturn
declare void @__faber_rt_v1_numerus_overflow(ptr) noreturn


declare ptr @__faber_aggregate_array_2_i64_i64(i64, i64)
; @runtime __faber_rt_v1_array_new category=core-semantics
declare %FaberRtPtrResultV1 @__faber_rt_v1_array_new(ptr, i32)
; @runtime __faber_rt_v1_array_push category=core-semantics
declare i32 @__faber_rt_v1_array_push(ptr, ptr, i32, ptr)
; @runtime __faber_rt_v1_diagnostic_nota_f32 category=host-integration
declare i32 @__faber_rt_v1_diagnostic_nota_f32(ptr, float)
; @runtime __faber_rt_v1_tensor_from_flat category=core-semantics
declare %FaberRtPtrResultV1 @__faber_rt_v1_tensor_from_flat(ptr, i32, ptr, ptr)
; @runtime __faber_rt_v1_tensor_matmul category=core-semantics
declare %FaberRtPtrResultV1 @__faber_rt_v1_tensor_matmul(ptr, ptr, ptr)
; @runtime __faber_rt_v1_tensor_mean category=core-semantics
declare i32 @__faber_rt_v1_tensor_mean(ptr, ptr, i32, ptr)
; @runtime __faber_rt_v1_tensor_new category=core-semantics
declare %FaberRtPtrResultV1 @__faber_rt_v1_tensor_new(ptr, i32)

define void @main() {
    entry:
      %l0.addr = alloca ptr
      %l1.addr = alloca ptr
      %l2.addr = alloca ptr
      %l3.addr = alloca ptr
      %l4.addr = alloca ptr
      %l5.addr = alloca ptr
      %l6.addr = alloca float
      %t0.addr = alloca float
      %t1.addr = alloca float
      %t2.addr = alloca float
      %t3.addr = alloca float
      %t4.addr = alloca float
      %t5.addr = alloca float
      %t6.addr = alloca ptr
      %t7.addr = alloca float
      %t8.addr = alloca float
      %t9.addr = alloca float
      %t10.addr = alloca float
      %t11.addr = alloca float
      %t12.addr = alloca float
      %t13.addr = alloca float
      %t14.addr = alloca float
      %t15.addr = alloca float
      %t16.addr = alloca float
      %t17.addr = alloca float
      %t18.addr = alloca float
      %t19.addr = alloca ptr
      %t20.addr = alloca ptr
      %t21.addr = alloca ptr
      %t22.addr = alloca ptr
      %t23.addr = alloca ptr
      %t24.addr = alloca ptr
      %t25.addr = alloca ptr
      %t26.addr = alloca float
      br label %b0
    b0:
      %cast0 = fptrunc double 1.0 to float
      store float %cast0, ptr %t0.addr
      %cast1 = fptrunc double 2.0 to float
      store float %cast1, ptr %t1.addr
      %cast2 = fptrunc double 3.0 to float
      store float %cast2, ptr %t2.addr
      %cast3 = fptrunc double 4.0 to float
      store float %cast3, ptr %t3.addr
      %cast4 = fptrunc double 5.0 to float
      store float %cast4, ptr %t4.addr
      %cast5 = fptrunc double 6.0 to float
      store float %cast5, ptr %t5.addr
      %faber.context6 = load ptr, ptr @__faber_rt_v1_context
      %faber.array.result6 = call %FaberRtPtrResultV1 @__faber_rt_v1_array_new(ptr %faber.context6, i32 5)
      %faber.array.status6 = extractvalue %FaberRtPtrResultV1 %faber.array.result6, 0
      %faber.array.handle6 = extractvalue %FaberRtPtrResultV1 %faber.array.result6, 1
      %faber.old.status6 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error6 = icmp ne i32 %faber.old.status6, 0
      %faber.latched.status6 = select i1 %faber.has.error6, i32 %faber.old.status6, i32 %faber.array.status6
      store i32 %faber.latched.status6, ptr @__faber_rt_v1_status
      %load8 = load float, ptr %t0.addr
      %faber.array.value7 = alloca float
      store float %load8, ptr %faber.array.value7
      %faber.array.status7 = call i32 @__faber_rt_v1_array_push(ptr %faber.context6, ptr %faber.array.handle6, i32 5, ptr %faber.array.value7)
      %faber.old.status7 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error7 = icmp ne i32 %faber.old.status7, 0
      %faber.latched.status7 = select i1 %faber.has.error7, i32 %faber.old.status7, i32 %faber.array.status7
      store i32 %faber.latched.status7, ptr @__faber_rt_v1_status
      %load10 = load float, ptr %t1.addr
      %faber.array.value9 = alloca float
      store float %load10, ptr %faber.array.value9
      %faber.array.status9 = call i32 @__faber_rt_v1_array_push(ptr %faber.context6, ptr %faber.array.handle6, i32 5, ptr %faber.array.value9)
      %faber.old.status9 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error9 = icmp ne i32 %faber.old.status9, 0
      %faber.latched.status9 = select i1 %faber.has.error9, i32 %faber.old.status9, i32 %faber.array.status9
      store i32 %faber.latched.status9, ptr @__faber_rt_v1_status
      %load12 = load float, ptr %t2.addr
      %faber.array.value11 = alloca float
      store float %load12, ptr %faber.array.value11
      %faber.array.status11 = call i32 @__faber_rt_v1_array_push(ptr %faber.context6, ptr %faber.array.handle6, i32 5, ptr %faber.array.value11)
      %faber.old.status11 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error11 = icmp ne i32 %faber.old.status11, 0
      %faber.latched.status11 = select i1 %faber.has.error11, i32 %faber.old.status11, i32 %faber.array.status11
      store i32 %faber.latched.status11, ptr @__faber_rt_v1_status
      %load14 = load float, ptr %t3.addr
      %faber.array.value13 = alloca float
      store float %load14, ptr %faber.array.value13
      %faber.array.status13 = call i32 @__faber_rt_v1_array_push(ptr %faber.context6, ptr %faber.array.handle6, i32 5, ptr %faber.array.value13)
      %faber.old.status13 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error13 = icmp ne i32 %faber.old.status13, 0
      %faber.latched.status13 = select i1 %faber.has.error13, i32 %faber.old.status13, i32 %faber.array.status13
      store i32 %faber.latched.status13, ptr @__faber_rt_v1_status
      %load16 = load float, ptr %t4.addr
      %faber.array.value15 = alloca float
      store float %load16, ptr %faber.array.value15
      %faber.array.status15 = call i32 @__faber_rt_v1_array_push(ptr %faber.context6, ptr %faber.array.handle6, i32 5, ptr %faber.array.value15)
      %faber.old.status15 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error15 = icmp ne i32 %faber.old.status15, 0
      %faber.latched.status15 = select i1 %faber.has.error15, i32 %faber.old.status15, i32 %faber.array.status15
      store i32 %faber.latched.status15, ptr @__faber_rt_v1_status
      %load18 = load float, ptr %t5.addr
      %faber.array.value17 = alloca float
      store float %load18, ptr %faber.array.value17
      %faber.array.status17 = call i32 @__faber_rt_v1_array_push(ptr %faber.context6, ptr %faber.array.handle6, i32 5, ptr %faber.array.value17)
      %faber.old.status17 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error17 = icmp ne i32 %faber.old.status17, 0
      %faber.latched.status17 = select i1 %faber.has.error17, i32 %faber.old.status17, i32 %faber.array.status17
      store i32 %faber.latched.status17, ptr @__faber_rt_v1_status
      store ptr %faber.array.handle6, ptr %t6.addr
      %load19 = load ptr, ptr %t6.addr
      store ptr %load19, ptr %l0.addr
      %cast20 = fptrunc double 1.0 to float
      store float %cast20, ptr %t7.addr
      %cast21 = fptrunc double 2.0 to float
      store float %cast21, ptr %t8.addr
      %cast22 = fptrunc double 3.0 to float
      store float %cast22, ptr %t9.addr
      %cast23 = fptrunc double 4.0 to float
      store float %cast23, ptr %t10.addr
      %cast24 = fptrunc double 5.0 to float
      store float %cast24, ptr %t11.addr
      %cast25 = fptrunc double 6.0 to float
      store float %cast25, ptr %t12.addr
      %cast26 = fptrunc double 7.0 to float
      store float %cast26, ptr %t13.addr
      %cast27 = fptrunc double 8.0 to float
      store float %cast27, ptr %t14.addr
      %cast28 = fptrunc double 9.0 to float
      store float %cast28, ptr %t15.addr
      %cast29 = fptrunc double 10.0 to float
      store float %cast29, ptr %t16.addr
      %cast30 = fptrunc double 11.0 to float
      store float %cast30, ptr %t17.addr
      %cast31 = fptrunc double 12.0 to float
      store float %cast31, ptr %t18.addr
      %faber.context32 = load ptr, ptr @__faber_rt_v1_context
      %faber.array.result32 = call %FaberRtPtrResultV1 @__faber_rt_v1_array_new(ptr %faber.context32, i32 5)
      %faber.array.status32 = extractvalue %FaberRtPtrResultV1 %faber.array.result32, 0
      %faber.array.handle32 = extractvalue %FaberRtPtrResultV1 %faber.array.result32, 1
      %faber.old.status32 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error32 = icmp ne i32 %faber.old.status32, 0
      %faber.latched.status32 = select i1 %faber.has.error32, i32 %faber.old.status32, i32 %faber.array.status32
      store i32 %faber.latched.status32, ptr @__faber_rt_v1_status
      %load34 = load float, ptr %t7.addr
      %faber.array.value33 = alloca float
      store float %load34, ptr %faber.array.value33
      %faber.array.status33 = call i32 @__faber_rt_v1_array_push(ptr %faber.context32, ptr %faber.array.handle32, i32 5, ptr %faber.array.value33)
      %faber.old.status33 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error33 = icmp ne i32 %faber.old.status33, 0
      %faber.latched.status33 = select i1 %faber.has.error33, i32 %faber.old.status33, i32 %faber.array.status33
      store i32 %faber.latched.status33, ptr @__faber_rt_v1_status
      %load36 = load float, ptr %t8.addr
      %faber.array.value35 = alloca float
      store float %load36, ptr %faber.array.value35
      %faber.array.status35 = call i32 @__faber_rt_v1_array_push(ptr %faber.context32, ptr %faber.array.handle32, i32 5, ptr %faber.array.value35)
      %faber.old.status35 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error35 = icmp ne i32 %faber.old.status35, 0
      %faber.latched.status35 = select i1 %faber.has.error35, i32 %faber.old.status35, i32 %faber.array.status35
      store i32 %faber.latched.status35, ptr @__faber_rt_v1_status
      %load38 = load float, ptr %t9.addr
      %faber.array.value37 = alloca float
      store float %load38, ptr %faber.array.value37
      %faber.array.status37 = call i32 @__faber_rt_v1_array_push(ptr %faber.context32, ptr %faber.array.handle32, i32 5, ptr %faber.array.value37)
      %faber.old.status37 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error37 = icmp ne i32 %faber.old.status37, 0
      %faber.latched.status37 = select i1 %faber.has.error37, i32 %faber.old.status37, i32 %faber.array.status37
      store i32 %faber.latched.status37, ptr @__faber_rt_v1_status
      %load40 = load float, ptr %t10.addr
      %faber.array.value39 = alloca float
      store float %load40, ptr %faber.array.value39
      %faber.array.status39 = call i32 @__faber_rt_v1_array_push(ptr %faber.context32, ptr %faber.array.handle32, i32 5, ptr %faber.array.value39)
      %faber.old.status39 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error39 = icmp ne i32 %faber.old.status39, 0
      %faber.latched.status39 = select i1 %faber.has.error39, i32 %faber.old.status39, i32 %faber.array.status39
      store i32 %faber.latched.status39, ptr @__faber_rt_v1_status
      %load42 = load float, ptr %t11.addr
      %faber.array.value41 = alloca float
      store float %load42, ptr %faber.array.value41
      %faber.array.status41 = call i32 @__faber_rt_v1_array_push(ptr %faber.context32, ptr %faber.array.handle32, i32 5, ptr %faber.array.value41)
      %faber.old.status41 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error41 = icmp ne i32 %faber.old.status41, 0
      %faber.latched.status41 = select i1 %faber.has.error41, i32 %faber.old.status41, i32 %faber.array.status41
      store i32 %faber.latched.status41, ptr @__faber_rt_v1_status
      %load44 = load float, ptr %t12.addr
      %faber.array.value43 = alloca float
      store float %load44, ptr %faber.array.value43
      %faber.array.status43 = call i32 @__faber_rt_v1_array_push(ptr %faber.context32, ptr %faber.array.handle32, i32 5, ptr %faber.array.value43)
      %faber.old.status43 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error43 = icmp ne i32 %faber.old.status43, 0
      %faber.latched.status43 = select i1 %faber.has.error43, i32 %faber.old.status43, i32 %faber.array.status43
      store i32 %faber.latched.status43, ptr @__faber_rt_v1_status
      %load46 = load float, ptr %t13.addr
      %faber.array.value45 = alloca float
      store float %load46, ptr %faber.array.value45
      %faber.array.status45 = call i32 @__faber_rt_v1_array_push(ptr %faber.context32, ptr %faber.array.handle32, i32 5, ptr %faber.array.value45)
      %faber.old.status45 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error45 = icmp ne i32 %faber.old.status45, 0
      %faber.latched.status45 = select i1 %faber.has.error45, i32 %faber.old.status45, i32 %faber.array.status45
      store i32 %faber.latched.status45, ptr @__faber_rt_v1_status
      %load48 = load float, ptr %t14.addr
      %faber.array.value47 = alloca float
      store float %load48, ptr %faber.array.value47
      %faber.array.status47 = call i32 @__faber_rt_v1_array_push(ptr %faber.context32, ptr %faber.array.handle32, i32 5, ptr %faber.array.value47)
      %faber.old.status47 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error47 = icmp ne i32 %faber.old.status47, 0
      %faber.latched.status47 = select i1 %faber.has.error47, i32 %faber.old.status47, i32 %faber.array.status47
      store i32 %faber.latched.status47, ptr @__faber_rt_v1_status
      %load50 = load float, ptr %t15.addr
      %faber.array.value49 = alloca float
      store float %load50, ptr %faber.array.value49
      %faber.array.status49 = call i32 @__faber_rt_v1_array_push(ptr %faber.context32, ptr %faber.array.handle32, i32 5, ptr %faber.array.value49)
      %faber.old.status49 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error49 = icmp ne i32 %faber.old.status49, 0
      %faber.latched.status49 = select i1 %faber.has.error49, i32 %faber.old.status49, i32 %faber.array.status49
      store i32 %faber.latched.status49, ptr @__faber_rt_v1_status
      %load52 = load float, ptr %t16.addr
      %faber.array.value51 = alloca float
      store float %load52, ptr %faber.array.value51
      %faber.array.status51 = call i32 @__faber_rt_v1_array_push(ptr %faber.context32, ptr %faber.array.handle32, i32 5, ptr %faber.array.value51)
      %faber.old.status51 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error51 = icmp ne i32 %faber.old.status51, 0
      %faber.latched.status51 = select i1 %faber.has.error51, i32 %faber.old.status51, i32 %faber.array.status51
      store i32 %faber.latched.status51, ptr @__faber_rt_v1_status
      %load54 = load float, ptr %t17.addr
      %faber.array.value53 = alloca float
      store float %load54, ptr %faber.array.value53
      %faber.array.status53 = call i32 @__faber_rt_v1_array_push(ptr %faber.context32, ptr %faber.array.handle32, i32 5, ptr %faber.array.value53)
      %faber.old.status53 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error53 = icmp ne i32 %faber.old.status53, 0
      %faber.latched.status53 = select i1 %faber.has.error53, i32 %faber.old.status53, i32 %faber.array.status53
      store i32 %faber.latched.status53, ptr @__faber_rt_v1_status
      %load56 = load float, ptr %t18.addr
      %faber.array.value55 = alloca float
      store float %load56, ptr %faber.array.value55
      %faber.array.status55 = call i32 @__faber_rt_v1_array_push(ptr %faber.context32, ptr %faber.array.handle32, i32 5, ptr %faber.array.value55)
      %faber.old.status55 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error55 = icmp ne i32 %faber.old.status55, 0
      %faber.latched.status55 = select i1 %faber.has.error55, i32 %faber.old.status55, i32 %faber.array.status55
      store i32 %faber.latched.status55, ptr @__faber_rt_v1_status
      store ptr %faber.array.handle32, ptr %t19.addr
      %load57 = load ptr, ptr %t19.addr
      store ptr %load57, ptr %l1.addr
      %faber.context58 = load ptr, ptr @__faber_rt_v1_context
      %faber.tensor.result58 = call %FaberRtPtrResultV1 @__faber_rt_v1_tensor_new(ptr %faber.context58, i32 5)
      %faber.tensor.status58 = extractvalue %FaberRtPtrResultV1 %faber.tensor.result58, 0
      %faber.tensor.value58 = extractvalue %FaberRtPtrResultV1 %faber.tensor.result58, 1
      %faber.old.status58 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error58 = icmp ne i32 %faber.old.status58, 0
      %faber.latched.status58 = select i1 %faber.has.error58, i32 %faber.old.status58, i32 %faber.tensor.status58
      store i32 %faber.latched.status58, ptr @__faber_rt_v1_status
      store ptr %faber.tensor.value58, ptr %t20.addr
      %load59 = load ptr, ptr %t20.addr
      store ptr %load59, ptr %l2.addr
      %agg60 = call ptr @__faber_aggregate_array_2_i64_i64(i64 2, i64 3)
      store ptr %agg60, ptr %t21.addr
      %load62 = load ptr, ptr %l2.addr
      %faber.context61 = load ptr, ptr @__faber_rt_v1_context
      %load63 = load ptr, ptr %l0.addr
      %load64 = load ptr, ptr %t21.addr
      %faber.tensor.result61 = call %FaberRtPtrResultV1 @__faber_rt_v1_tensor_from_flat(ptr %faber.context61, i32 5, ptr %load63, ptr %load64)
      %faber.tensor.status61 = extractvalue %FaberRtPtrResultV1 %faber.tensor.result61, 0
      %faber.tensor.value61 = extractvalue %FaberRtPtrResultV1 %faber.tensor.result61, 1
      %faber.old.status61 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error61 = icmp ne i32 %faber.old.status61, 0
      %faber.latched.status61 = select i1 %faber.has.error61, i32 %faber.old.status61, i32 %faber.tensor.status61
      store i32 %faber.latched.status61, ptr @__faber_rt_v1_status
      store ptr %faber.tensor.value61, ptr %t22.addr
      %load65 = load ptr, ptr %t22.addr
      store ptr %load65, ptr %l3.addr
      %agg66 = call ptr @__faber_aggregate_array_2_i64_i64(i64 3, i64 4)
      store ptr %agg66, ptr %t23.addr
      %load68 = load ptr, ptr %l2.addr
      %faber.context67 = load ptr, ptr @__faber_rt_v1_context
      %load69 = load ptr, ptr %l1.addr
      %load70 = load ptr, ptr %t23.addr
      %faber.tensor.result67 = call %FaberRtPtrResultV1 @__faber_rt_v1_tensor_from_flat(ptr %faber.context67, i32 5, ptr %load69, ptr %load70)
      %faber.tensor.status67 = extractvalue %FaberRtPtrResultV1 %faber.tensor.result67, 0
      %faber.tensor.value67 = extractvalue %FaberRtPtrResultV1 %faber.tensor.result67, 1
      %faber.old.status67 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error67 = icmp ne i32 %faber.old.status67, 0
      %faber.latched.status67 = select i1 %faber.has.error67, i32 %faber.old.status67, i32 %faber.tensor.status67
      store i32 %faber.latched.status67, ptr @__faber_rt_v1_status
      store ptr %faber.tensor.value67, ptr %t24.addr
      %load71 = load ptr, ptr %t24.addr
      store ptr %load71, ptr %l4.addr
      %load73 = load ptr, ptr %l3.addr
      %faber.context72 = load ptr, ptr @__faber_rt_v1_context
      %load74 = load ptr, ptr %l4.addr
      %faber.tensor.result72 = call %FaberRtPtrResultV1 @__faber_rt_v1_tensor_matmul(ptr %faber.context72, ptr %load73, ptr %load74)
      %faber.tensor.status72 = extractvalue %FaberRtPtrResultV1 %faber.tensor.result72, 0
      %faber.tensor.value72 = extractvalue %FaberRtPtrResultV1 %faber.tensor.result72, 1
      %faber.old.status72 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error72 = icmp ne i32 %faber.old.status72, 0
      %faber.latched.status72 = select i1 %faber.has.error72, i32 %faber.old.status72, i32 %faber.tensor.status72
      store i32 %faber.latched.status72, ptr @__faber_rt_v1_status
      store ptr %faber.tensor.value72, ptr %t25.addr
      %load75 = load ptr, ptr %t25.addr
      store ptr %load75, ptr %l5.addr
      %load77 = load ptr, ptr %l5.addr
      %faber.context76 = load ptr, ptr @__faber_rt_v1_context
      %faber.tensor.reduce.out76 = alloca float
      store float 0.0, ptr %faber.tensor.reduce.out76
      %faber.tensor.status76 = call i32 @__faber_rt_v1_tensor_mean(ptr %faber.context76, ptr %load77, i32 5, ptr %faber.tensor.reduce.out76)
      %faber.tensor.reduce76 = load float, ptr %faber.tensor.reduce.out76
      %faber.old.status76 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error76 = icmp ne i32 %faber.old.status76, 0
      %faber.latched.status76 = select i1 %faber.has.error76, i32 %faber.old.status76, i32 %faber.tensor.status76
      store i32 %faber.latched.status76, ptr @__faber_rt_v1_status
      store float %faber.tensor.reduce76, ptr %t26.addr
      %load78 = load float, ptr %t26.addr
      store float %load78, ptr %l6.addr
      %load79 = load float, ptr %l6.addr
      %faber.context80 = load ptr, ptr @__faber_rt_v1_context
      %faber.diag.status80 = call i32 @__faber_rt_v1_diagnostic_nota_f32(ptr %faber.context80, float %load79)
      %faber.old.status80 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error80 = icmp ne i32 %faber.old.status80, 0
      %faber.latched.status80 = select i1 %faber.has.error80, i32 %faber.old.status80, i32 %faber.diag.status80
      store i32 %faber.latched.status80, ptr @__faber_rt_v1_status
      ret void
}

define %FaberRtExitV1 @__faber_program_entry_v1(ptr %context) {
    entry:
      store ptr %context, ptr @__faber_rt_v1_context
      call void @main()
      %faber.entry.status = load i32, ptr @__faber_rt_v1_status
      %faber.entry.status.ext = zext i32 %faber.entry.status to i64
      %faber.entry.shifted = shl i64 %faber.entry.status.ext, 32
      %faber.entry.packed = or i64 0, %faber.entry.shifted
      ret %FaberRtExitV1 %faber.entry.packed
}

The error channel#

A function that may fail, and a caller that catches. Shows how the ⇥ channel becomes each target's own error idiom.

Faber source

reader locale
faber convert --to en — English reader surface
fn divide(int a, int b) → int ⇥ string {
    if b ≡ 0 {
        throw "division by zero"
    }
    return a / b
}

main {
    do {
        print divide(10, 2)
    }
    catch err {
        warn err
    }
}
faber convert --to la — canonical Faber
functio divide(numerus a, numerus b) → numerus ⇥ textus {
    si b ≡ 0 {
        iace "division by zero"
    }
    redde a / b
}

incipit {
    fac {
        nota divide(10, 2)
    }
    cape err {
        mone err
    }
}
faber convert --to th-TH — Thai
ฟังก์ชัน divide(จำนวน a, จำนวน b) → จำนวน ⇥ ข้อความ {
    ถ้า b ≡ 0 {
        โยน "division by zero"
    }
    คืน a / b
}

เริ่ม {
    ทำ {
        บันทึก divide(10, 2)
    }
    จับ err {
        เตือน err
    }
}
faber convert --to zh-Hans — Simplified Chinese
函数 divide(整数 a, 整数 b) → 整数 ⇥ 文本 {
    如果 b ≡ 0 {
        抛错 "division by zero"
    }
    返回 a / b
}

入口 {
    执行 {
        显示 divide(10, 2)
    }
    捕获 err {
        警告 err
    }
}
faber convert --to zh-Hant — Traditional Chinese
函式 divide(整數 a, 整數 b) → 整數 ⇥ 文字 {
    若 b ≡ 0 {
        拋出 "division by zero"
    }
    傳回 a / b
}

入口 {
    執行 {
        註記 divide(10, 2)
    }
    捕捉 err {
        警告 err
    }
}
faber convert --to vi — Vietnamese
hàm divide(số a, số b) → số ⇥ văn_bản {
    nếu b ≡ 0 {
        ném "division by zero"
    }
    trả a / b
}

bắt_đầu {
    làm {
        ghi_chú divide(10, 2)
    }
    bắt err {
        cảnh_báo err
    }
}
faber convert --to ar — Arabic
دالة divide(عدد a, عدد b) → عدد ⇥ نص {
    إذا b ≡ 0 {
        ارم "division by zero"
    }
    أعد a / b
}

بداية {
    افعل {
        اعرض divide(10, 2)
    }
    التقط err {
        نبه err
    }
}
faber convert --to hi — Hindi
फलन divide(संख्या a, संख्या b) → संख्या ⇥ पाठ {
    यदि b ≡ 0 {
        इधरफेंको "division by zero"
    }
    लौटाओ a / b
}

आरंभ {
    करो {
        दिखाओ divide(10, 2)
    }
    पकड़ो err {
        चेताओ err
    }
}

LLVM IR — 13 lines in, 198 out (15.2×)

; Generated by radix MIR LLVM IR probe - experimental artifact.
%FaberRtSliceV1 = type { ptr, i64 }
%FaberRtExitV1 = type i64
%FaberRtPtrResultV1 = type { i32, ptr }
%FaberRtStatusV1 = type { i32 }
@__faber_rt_v1_context = linkonce_odr global ptr null
@__faber_rt_v1_status = linkonce_odr global i32 0
declare void @__faber_rt_v1_fatal(ptr, %FaberRtSliceV1) noreturn
declare void @__faber_rt_v1_numerus_overflow(ptr) noreturn
; @literal-data __faber_text_literal_text_16_64_69_76_69_73_69_6f_6e_20_62_79_20_7a_65_72_6f family=text family_index=0 family_index_count=1 family_count=1 representation=static-byte-data representation_index=0 representation_index_count=1 representation_count=1 byte_data_schema_version=1 encoding=utf8 byte_data_schema_version_index=0 byte_data_schema_version_index_count=1 encoding_index=0 encoding_index_count=1 byte_data_schema_version_count=1 encoding_count=1 layout="[17 x i8]" bytes=17 payload_bytes=16 layout_index=0 layout_index_count=1 payload_byte_index=0 payload_byte_index_count=1 payload_byte_count=1 layout_count=1 byte_length_count=1 terminator_bytes=1 terminator_byte_index=0 terminator_byte_index_count=1 terminator_byte_count=1 terminator_policy_index=0 terminator_policy_index_count=1 terminator_policy_count=1 null_terminated_index=0 null_terminated_index_count=1 null_terminated=true null_terminated_count=1 mutability_index=0 mutability_index_count=1 mutability="constant" mutability_count=1 pointer_policy_index=0 pointer_policy_index_count=1 pointer_policy="gep-nonempty-direct-empty" pointer_policy_count=1 linkage_index=0 linkage_index_count=1 linkage="linkonce_odr unnamed_addr constant" linkage_count=1 alignment_index=0 alignment_index_count=1 alignment="align 1" alignment_count=1
@__faber_text_literal_text_16_64_69_76_69_73_69_6f_6e_20_62_79_20_7a_65_72_6f = linkonce_odr unnamed_addr constant [17 x i8] c"division by zero\00", align 1
; @literal-object __faber_text_literal_text_16_64_69_76_69_73_69_6f_6e_20_62_79_20_7a_65_72_6f_object family=text family_index=0 family_index_count=1 family_count=1 representation=static-descriptor representation_count=1 descriptor_schema_version=1 descriptor_schema_version_count=1 layout="{ ptr, i64 }" layout_count=1 byte_len=16 byte_len_count=1 abi_align=8 abi_align_count=1 field_types=ptr,i64 field_type_count=2 field_sizes=8,8 field_size_count=2 field_alignments=8,8 field_alignment_count=2 field_offsets=0,8 field_offset_count=2 field_end_offsets=8,16 field_end_offset_count=2 pointer_fields=data pointer_field_indexes=data:0 pointer_field_index_count=1 pointer_field_count=1 pointer_address_spaces=data:0 pointer_address_space_count=1 pointer_target_families=data:unknown pointer_target_family_indexes=data:0:unknown pointer_target_family_index_count=1 pointer_target_family_count=1 pointer_target_terminators=none pointer_target_terminator_indexes=none pointer_target_terminator_index_count=0 pointer_target_terminator_count=0 pointer_target_byte_lens=none pointer_target_byte_len_indexes=none pointer_target_byte_len_index_count=0 pointer_target_byte_len_count=0 length_fields=none length_field_indexes=none length_field_index_count=0 length_field_count=0 pointer_length_fields=none pointer_length_field_indexes=none pointer_length_field_index_count=0 pointer_length_field_count=0 fields=data,len field_indexes=data:0,len:1 field_index_count=2 field_count=2 nullable_fields=none nullable_field_indexes=none nullable_field_index_count=0 nullable_field_count=0 null_sentinels=none null_sentinel_indexes=none null_sentinel_index_count=0 null_sentinel_count=0 pointer_policy="direct-global-symbol" pointer_policy_count=1 storage_policy="static-descriptor-global" storage_policy_count=1 mutability="constant" mutability_count=1 linkage="linkonce_odr unnamed_addr constant" linkage_count=1 alignment="align 8" alignment_count=1
@__faber_text_literal_text_16_64_69_76_69_73_69_6f_6e_20_62_79_20_7a_65_72_6f_object = linkonce_odr unnamed_addr constant { ptr, i64 } { ptr getelementptr inbounds ([17 x i8], ptr @__faber_text_literal_text_16_64_69_76_69_73_69_6f_6e_20_62_79_20_7a_65_72_6f, i64 0, i64 0), i64 16 }, align 8


; @runtime __faber_rt_v1_diagnostic_mone_text category=host-integration
declare i32 @__faber_rt_v1_diagnostic_mone_text(ptr, ptr)
; @runtime __faber_rt_v1_diagnostic_nota_i64 category=host-integration
declare i32 @__faber_rt_v1_diagnostic_nota_i64(ptr, i64)

define { i1, i64, ptr } @divide(i64 %l0, i64 %l1) {
    entry:
      %l0.addr = alloca i64
      %l1.addr = alloca i64
      %t0.addr = alloca i1
      %t1.addr = alloca ptr
      %t2.addr = alloca i128
      %t3.addr = alloca i64
      store i64 %l0, ptr %l0.addr
      store i64 %l1, ptr %l1.addr
      br label %b0
    b0:
      %load0 = load i64, ptr %l1.addr
      %v0 = icmp eq i64 %load0, 0
      store i1 %v0, ptr %t0.addr
      %load1 = load i1, ptr %t0.addr
      br i1 %load1, label %b1, label %b2
    b1:
      store ptr @__faber_text_literal_text_16_64_69_76_69_73_69_6f_6e_20_62_79_20_7a_65_72_6f_object, ptr %t1.addr
      %load2 = load ptr, ptr %t1.addr
      %ret3 = insertvalue { i1, i64, ptr } undef, i1 false, 0
      %ret4 = insertvalue { i1, i64, ptr } %ret3, i64 0, 1
      %ret5 = insertvalue { i1, i64, ptr } %ret4, ptr %load2, 2
      ret { i1, i64, ptr } %ret5
    b2:
      %load6 = load i64, ptr %l0.addr
      %ex.w7 = sext i64 %load6 to i128
      %load8 = load i64, ptr %l1.addr
      %ex.w9 = sext i64 %load8 to i128
      %ex.zero10 = icmp eq i128 %ex.w9, 0
      br i1 %ex.zero10, label %ex.trap11, label %ex.ok11
    ex.trap11:
      %ex.ctx11 = load ptr, ptr @__faber_rt_v1_context
      call void @__faber_rt_v1_fatal(ptr %ex.ctx11, %FaberRtSliceV1 { ptr getelementptr inbounds ([23 x i8], ptr @__faber_trap_msg_6e756d65727573206469766973696f6e206661696c6564, i64 0, i64 0), i64 23 })
      unreachable
    ex.ok11:
      %ex.neg12 = icmp slt i128 %ex.w7, 0
      %ex.flip13 = sub i128 0, %ex.w7
      %ex.mag14 = select i1 %ex.neg12, i128 %ex.flip13, i128 %ex.w7
      %ex.neg15 = icmp slt i128 %ex.w9, 0
      %ex.flip16 = sub i128 0, %ex.w9
      %ex.mag17 = select i1 %ex.neg15, i128 %ex.flip16, i128 %ex.w9
      %ex.at18 = trunc i128 %ex.mag14 to i64
      %ex.bt19 = trunc i128 %ex.mag17 to i64
      %ex.q20 = udiv i64 %ex.at18, %ex.bt19
      %ex.r21 = urem i64 %ex.at18, %ex.bt19
      %ex.qz22 = zext i64 %ex.q20 to i128
      %ex.sgn23 = xor i1 %ex.neg12, %ex.neg15
      %ex.rem24 = icmp ne i64 %ex.r21, 0
      %ex.adj25 = and i1 %ex.sgn23, %ex.rem24
      %ex.bump26 = add i128 %ex.qz22, 1
      %ex.qmag27 = select i1 %ex.adj25, i128 %ex.bump26, i128 %ex.qz22
      %ex.qneg28 = sub i128 0, %ex.qmag27
      %ex.floor29 = select i1 %ex.sgn23, i128 %ex.qneg28, i128 %ex.qmag27
      %ex.cb30 = add i128 %ex.floor29, 9223372036854775808
      %ex.cbad31 = icmp ugt i128 %ex.cb30, 27670116110564327423
      br i1 %ex.cbad31, label %ex.trap32, label %ex.ok32
    ex.trap32:
      %ex.ctx32 = load ptr, ptr @__faber_rt_v1_context
      call void @__faber_rt_v1_numerus_overflow(ptr %ex.ctx32)
      unreachable
    ex.ok32:
      store i128 %ex.floor29, ptr %t2.addr
      %ex.wl33 = load i128, ptr %t2.addr
      %ex.store34 = trunc i128 %ex.wl33 to i64
      %ex.back35 = sext i64 %ex.store34 to i128
      %ex.bad36 = icmp ne i128 %ex.back35, %ex.wl33
      br i1 %ex.bad36, label %ex.trap37, label %ex.ok37
    ex.trap37:
      call void @__faber_trap_store(i128 %ex.wl33, ptr getelementptr inbounds ([31 x i8], ptr @__faber_trap_msg_20646f6573206e6f742066697420696e206069363460202872657475726e29, i64 0, i64 0), i64 31)
      unreachable
    ex.ok37:
      store i64 %ex.store34, ptr %t3.addr
      %ret38 = insertvalue { i1, i64, ptr } undef, i1 true, 0
      %load39 = load i64, ptr %t3.addr
      %ret40 = insertvalue { i1, i64, ptr } %ret38, i64 %load39, 1
      %ret41 = insertvalue { i1, i64, ptr } %ret40, ptr null, 2
      ret { i1, i64, ptr } %ret41
}

define void @main() {
    entry:
      %l0.addr = alloca ptr
      %t0.addr = alloca i64
      br label %b0
    b0:
      %try0 = call { i1, i64, ptr } @divide(i64 10, i64 2)
      %try_tag1 = extractvalue { i1, i64, ptr } %try0, 0
      br i1 %try_tag1, label %try_ok2, label %try_error3
    try_ok2:
      %try_success4 = extractvalue { i1, i64, ptr } %try0, 1
      store i64 %try_success4, ptr %t0.addr
      br label %b4
    try_error3:
      %try_error_value5 = extractvalue { i1, i64, ptr } %try0, 2
      store ptr %try_error_value5, ptr %l0.addr
      br label %b1
    b1:
      %load6 = load ptr, ptr %l0.addr
      %faber.context7 = load ptr, ptr @__faber_rt_v1_context
      %faber.diag.status7 = call i32 @__faber_rt_v1_diagnostic_mone_text(ptr %faber.context7, ptr %load6)
      %faber.old.status7 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error7 = icmp ne i32 %faber.old.status7, 0
      %faber.latched.status7 = select i1 %faber.has.error7, i32 %faber.old.status7, i32 %faber.diag.status7
      store i32 %faber.latched.status7, ptr @__faber_rt_v1_status
      br label %b2
    b2:
      ret void
    b3:
      br label %b2
    b4:
      %load8 = load i64, ptr %t0.addr
      %faber.context9 = load ptr, ptr @__faber_rt_v1_context
      %faber.diag.status9 = call i32 @__faber_rt_v1_diagnostic_nota_i64(ptr %faber.context9, i64 %load8)
      %faber.old.status9 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error9 = icmp ne i32 %faber.old.status9, 0
      %faber.latched.status9 = select i1 %faber.has.error9, i32 %faber.old.status9, i32 %faber.diag.status9
      store i32 %faber.latched.status9, ptr @__faber_rt_v1_status
      br label %b3
}

define %FaberRtExitV1 @__faber_program_entry_v1(ptr %context) {
    entry:
      store ptr %context, ptr @__faber_rt_v1_context
      call void @main()
      %faber.entry.status = load i32, ptr @__faber_rt_v1_status
      %faber.entry.status.ext = zext i32 %faber.entry.status to i64
      %faber.entry.shifted = shl i64 %faber.entry.status.ext, 32
      %faber.entry.packed = or i64 0, %faber.entry.shifted
      ret %FaberRtExitV1 %faber.entry.packed
}
@__faber_trap_msg_20646f6573206e6f742066697420696e206069363460202872657475726e29 = linkonce_odr unnamed_addr constant [31 x i8] c" does not fit in \60i64\60 \28return\29", align 1
@__faber_trap_msg_6e756d65727573206469766973696f6e206661696c6564 = linkonce_odr unnamed_addr constant [23 x i8] c"numerus division failed", align 1

declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)
define linkonce_odr void @__faber_trap_store(i128 %v, ptr %sfx, i64 %n) noreturn {
entry:
  %ctx = load ptr, ptr @__faber_rt_v1_context
  %cap = add i64 %n, 24
  %buf = alloca i8, i64 %cap
  %digits = alloca [24 x i8]
  %neg = icmp slt i128 %v, 0
  %negv = sub i128 0, %v
  %mag128 = select i1 %neg, i128 %negv, i128 %v
  %mag = trunc i128 %mag128 to i64
  br label %loop
loop:
  %i = phi i64 [ 24, %entry ], [ %i2, %loop ]
  %m = phi i64 [ %mag, %entry ], [ %q, %loop ]
  %r = urem i64 %m, 10
  %q = udiv i64 %m, 10
  %c = add i64 %r, 48
  %c8 = trunc i64 %c to i8
  %i2 = sub i64 %i, 1
  %p = getelementptr i8, ptr %digits, i64 %i2
  store i8 %c8, ptr %p
  %done = icmp eq i64 %q, 0
  br i1 %done, label %copy, label %loop
copy:
  %len = sub i64 24, %i2
  %signlen = zext i1 %neg to i64
  br i1 %neg, label %sign, label %body
sign:
  store i8 45, ptr %buf
  br label %body
body:
  %dst = getelementptr i8, ptr %buf, i64 %signlen
  %src = getelementptr i8, ptr %digits, i64 %i2
  call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 %len, i1 false)
  %off = add i64 %signlen, %len
  %dst2 = getelementptr i8, ptr %buf, i64 %off
  call void @llvm.memcpy.p0.p0.i64(ptr %dst2, ptr %sfx, i64 %n, i1 false)
  %total = add i64 %off, %n
  %s0 = insertvalue %FaberRtSliceV1 undef, ptr %buf, 0
  %s1 = insertvalue %FaberRtSliceV1 %s0, i64 %total, 1
  call void @__faber_rt_v1_fatal(ptr %ctx, %FaberRtSliceV1 %s1)
  unreachable
}

Collections and iteration#

A list folded to a total with for from. The plainest possible read on how loops lower.

Faber source

fn sum(list<int> numeri) → int {
    var int total ← 0
    for from numeri const n {
        total ← total + n
    }
    return total
}

main {
    const list<int> valores ← [1, 2, 3, 4, 5]
    print sum(valores)
}

LLVM IR — 12 lines in, 250 out (20.8×)

; Generated by radix MIR LLVM IR probe - experimental artifact.
%FaberRtSliceV1 = type { ptr, i64 }
%FaberRtExitV1 = type i64
%FaberRtPtrResultV1 = type { i32, ptr }
%FaberRtStatusV1 = type { i32 }
@__faber_rt_v1_context = linkonce_odr global ptr null
@__faber_rt_v1_status = linkonce_odr global i32 0
declare void @__faber_rt_v1_fatal(ptr, %FaberRtSliceV1) noreturn
declare void @__faber_rt_v1_numerus_overflow(ptr) noreturn


; @runtime __faber_rt_v1_array_get category=core-semantics
declare i32 @__faber_rt_v1_array_get(ptr, ptr, i64, i32, ptr)
; @runtime __faber_rt_v1_array_length category=core-semantics
declare i32 @__faber_rt_v1_array_length(ptr, ptr, ptr)
; @runtime __faber_rt_v1_array_new category=core-semantics
declare %FaberRtPtrResultV1 @__faber_rt_v1_array_new(ptr, i32)
; @runtime __faber_rt_v1_array_push category=core-semantics
declare i32 @__faber_rt_v1_array_push(ptr, ptr, i32, ptr)
; @runtime __faber_rt_v1_diagnostic_nota_i64 category=host-integration
declare i32 @__faber_rt_v1_diagnostic_nota_i64(ptr, i64)

define i64 @sum(ptr %l0) {
    entry:
      %l0.addr = alloca ptr
      %l1.addr = alloca i64
      %l2.addr = alloca i64
      %l3.addr = alloca i64
      %t0.addr = alloca i64
      %t1.addr = alloca i1
      %t2.addr = alloca i128
      %t3.addr = alloca i64
      %t4.addr = alloca i128
      store ptr %l0, ptr %l0.addr
      br label %b0
    b0:
      store i64 0, ptr %l1.addr
      store i64 0, ptr %l2.addr
      %load0 = load ptr, ptr %l0.addr
      %faber.array.length.out1 = alloca i64
      store i64 0, ptr %faber.array.length.out1
      %faber.context1 = load ptr, ptr @__faber_rt_v1_context
      %faber.array.length.status1 = call i32 @__faber_rt_v1_array_length(ptr %faber.context1, ptr %load0, ptr %faber.array.length.out1)
      %faber.array.length1 = load i64, ptr %faber.array.length.out1
      %faber.old.status1 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error1 = icmp ne i32 %faber.old.status1, 0
      %faber.latched.status1 = select i1 %faber.has.error1, i32 %faber.old.status1, i32 %faber.array.length.status1
      store i32 %faber.latched.status1, ptr @__faber_rt_v1_status
      store i64 %faber.array.length1, ptr %t0.addr
      br label %b1
    b1:
      %load2 = load i64, ptr %l2.addr
      %load3 = load i64, ptr %t0.addr
      %v2 = icmp slt i64 %load2, %load3
      store i1 %v2, ptr %t1.addr
      %load4 = load i1, ptr %t1.addr
      br i1 %load4, label %b2, label %b4
    b2:
      %load5 = load ptr, ptr %l0.addr
      %load6 = load i64, ptr %l2.addr
      %faber.array.get.out7 = alloca i64
      store i64 0, ptr %faber.array.get.out7
      %faber.context7 = load ptr, ptr @__faber_rt_v1_context
      %faber.array.get.status7 = call i32 @__faber_rt_v1_array_get(ptr %faber.context7, ptr %load5, i64 %load6, i32 4, ptr %faber.array.get.out7)
      %faber.array.get.value7 = load i64, ptr %faber.array.get.out7
      %faber.old.status7 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error7 = icmp ne i32 %faber.old.status7, 0
      %faber.latched.status7 = select i1 %faber.has.error7, i32 %faber.old.status7, i32 %faber.array.get.status7
      store i32 %faber.latched.status7, ptr @__faber_rt_v1_status
      store i64 %faber.array.get.value7, ptr %l3.addr
      %load8 = load i64, ptr %l1.addr
      %ex.w9 = sext i64 %load8 to i128
      %load10 = load i64, ptr %l3.addr
      %ex.w11 = sext i64 %load10 to i128
      %ex.add12 = add i128 %ex.w9, %ex.w11
      %ex.cb13 = add i128 %ex.add12, 9223372036854775808
      %ex.cbad14 = icmp ugt i128 %ex.cb13, 27670116110564327423
      br i1 %ex.cbad14, label %ex.trap15, label %ex.ok15
    ex.trap15:
      %ex.ctx15 = load ptr, ptr @__faber_rt_v1_context
      call void @__faber_rt_v1_numerus_overflow(ptr %ex.ctx15)
      unreachable
    ex.ok15:
      store i128 %ex.add12, ptr %t2.addr
      %ex.wl16 = load i128, ptr %t2.addr
      %ex.store17 = trunc i128 %ex.wl16 to i64
      %ex.back18 = sext i64 %ex.store17 to i128
      %ex.bad19 = icmp ne i128 %ex.back18, %ex.wl16
      br i1 %ex.bad19, label %ex.trap20, label %ex.ok20
    ex.trap20:
      call void @__faber_trap_store(i128 %ex.wl16, ptr getelementptr inbounds ([46 x i8], ptr @__faber_trap_msg_20646f6573206e6f742066697420696e206069363460202861737369676e6d656e7420746f2060746f74616c6029, i64 0, i64 0), i64 46)
      unreachable
    ex.ok20:
      store i64 %ex.store17, ptr %t3.addr
      %load21 = load i64, ptr %t3.addr
      store i64 %load21, ptr %l1.addr
      br label %b3
    b3:
      %load22 = load i64, ptr %l2.addr
      %ex.w23 = sext i64 %load22 to i128
      %ex.w24 = sext i64 1 to i128
      %ex.add25 = add i128 %ex.w23, %ex.w24
      %ex.cb26 = add i128 %ex.add25, 9223372036854775808
      %ex.cbad27 = icmp ugt i128 %ex.cb26, 27670116110564327423
      br i1 %ex.cbad27, label %ex.trap28, label %ex.ok28
    ex.trap28:
      %ex.ctx28 = load ptr, ptr @__faber_rt_v1_context
      call void @__faber_rt_v1_numerus_overflow(ptr %ex.ctx28)
      unreachable
    ex.ok28:
      store i128 %ex.add25, ptr %t4.addr
      %ex.wl29 = load i128, ptr %t4.addr
      %ex.nr30 = trunc i128 %ex.wl29 to i64
      %ex.back31 = sext i64 %ex.nr30 to i128
      %ex.bad32 = icmp ne i128 %ex.back31, %ex.wl29
      br i1 %ex.bad32, label %ex.trap33, label %ex.ok33
    ex.trap33:
      %ex.ctx33 = load ptr, ptr @__faber_rt_v1_context
      call void @__faber_rt_v1_numerus_overflow(ptr %ex.ctx33)
      unreachable
    ex.ok33:
      store i64 %ex.nr30, ptr %l2.addr
      br label %b1
    b4:
      %load34 = load i64, ptr %l1.addr
      ret i64 %load34
}

define void @main() {
    entry:
      %l0.addr = alloca ptr
      %t0.addr = alloca ptr
      %t1.addr = alloca i64
      br label %b0
    b0:
      %faber.context0 = load ptr, ptr @__faber_rt_v1_context
      %faber.array.result0 = call %FaberRtPtrResultV1 @__faber_rt_v1_array_new(ptr %faber.context0, i32 4)
      %faber.array.status0 = extractvalue %FaberRtPtrResultV1 %faber.array.result0, 0
      %faber.array.handle0 = extractvalue %FaberRtPtrResultV1 %faber.array.result0, 1
      %faber.old.status0 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error0 = icmp ne i32 %faber.old.status0, 0
      %faber.latched.status0 = select i1 %faber.has.error0, i32 %faber.old.status0, i32 %faber.array.status0
      store i32 %faber.latched.status0, ptr @__faber_rt_v1_status
      %faber.array.value1 = alloca i64
      store i64 1, ptr %faber.array.value1
      %faber.array.status1 = call i32 @__faber_rt_v1_array_push(ptr %faber.context0, ptr %faber.array.handle0, i32 4, ptr %faber.array.value1)
      %faber.old.status1 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error1 = icmp ne i32 %faber.old.status1, 0
      %faber.latched.status1 = select i1 %faber.has.error1, i32 %faber.old.status1, i32 %faber.array.status1
      store i32 %faber.latched.status1, ptr @__faber_rt_v1_status
      %faber.array.value2 = alloca i64
      store i64 2, ptr %faber.array.value2
      %faber.array.status2 = call i32 @__faber_rt_v1_array_push(ptr %faber.context0, ptr %faber.array.handle0, i32 4, ptr %faber.array.value2)
      %faber.old.status2 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error2 = icmp ne i32 %faber.old.status2, 0
      %faber.latched.status2 = select i1 %faber.has.error2, i32 %faber.old.status2, i32 %faber.array.status2
      store i32 %faber.latched.status2, ptr @__faber_rt_v1_status
      %faber.array.value3 = alloca i64
      store i64 3, ptr %faber.array.value3
      %faber.array.status3 = call i32 @__faber_rt_v1_array_push(ptr %faber.context0, ptr %faber.array.handle0, i32 4, ptr %faber.array.value3)
      %faber.old.status3 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error3 = icmp ne i32 %faber.old.status3, 0
      %faber.latched.status3 = select i1 %faber.has.error3, i32 %faber.old.status3, i32 %faber.array.status3
      store i32 %faber.latched.status3, ptr @__faber_rt_v1_status
      %faber.array.value4 = alloca i64
      store i64 4, ptr %faber.array.value4
      %faber.array.status4 = call i32 @__faber_rt_v1_array_push(ptr %faber.context0, ptr %faber.array.handle0, i32 4, ptr %faber.array.value4)
      %faber.old.status4 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error4 = icmp ne i32 %faber.old.status4, 0
      %faber.latched.status4 = select i1 %faber.has.error4, i32 %faber.old.status4, i32 %faber.array.status4
      store i32 %faber.latched.status4, ptr @__faber_rt_v1_status
      %faber.array.value5 = alloca i64
      store i64 5, ptr %faber.array.value5
      %faber.array.status5 = call i32 @__faber_rt_v1_array_push(ptr %faber.context0, ptr %faber.array.handle0, i32 4, ptr %faber.array.value5)
      %faber.old.status5 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error5 = icmp ne i32 %faber.old.status5, 0
      %faber.latched.status5 = select i1 %faber.has.error5, i32 %faber.old.status5, i32 %faber.array.status5
      store i32 %faber.latched.status5, ptr @__faber_rt_v1_status
      store ptr %faber.array.handle0, ptr %t0.addr
      %load6 = load ptr, ptr %t0.addr
      store ptr %load6, ptr %l0.addr
      %load7 = load ptr, ptr %l0.addr
      %call8 = call i64 @sum(ptr %load7)
      store i64 %call8, ptr %t1.addr
      %load9 = load i64, ptr %t1.addr
      %faber.context10 = load ptr, ptr @__faber_rt_v1_context
      %faber.diag.status10 = call i32 @__faber_rt_v1_diagnostic_nota_i64(ptr %faber.context10, i64 %load9)
      %faber.old.status10 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error10 = icmp ne i32 %faber.old.status10, 0
      %faber.latched.status10 = select i1 %faber.has.error10, i32 %faber.old.status10, i32 %faber.diag.status10
      store i32 %faber.latched.status10, ptr @__faber_rt_v1_status
      ret void
}

define %FaberRtExitV1 @__faber_program_entry_v1(ptr %context) {
    entry:
      store ptr %context, ptr @__faber_rt_v1_context
      call void @main()
      %faber.entry.status = load i32, ptr @__faber_rt_v1_status
      %faber.entry.status.ext = zext i32 %faber.entry.status to i64
      %faber.entry.shifted = shl i64 %faber.entry.status.ext, 32
      %faber.entry.packed = or i64 0, %faber.entry.shifted
      ret %FaberRtExitV1 %faber.entry.packed
}
@__faber_trap_msg_20646f6573206e6f742066697420696e206069363460202861737369676e6d656e7420746f2060746f74616c6029 = linkonce_odr unnamed_addr constant [46 x i8] c" does not fit in \60i64\60 \28assignment to \60total\60\29", align 1

declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)
define linkonce_odr void @__faber_trap_store(i128 %v, ptr %sfx, i64 %n) noreturn {
entry:
  %ctx = load ptr, ptr @__faber_rt_v1_context
  %cap = add i64 %n, 24
  %buf = alloca i8, i64 %cap
  %digits = alloca [24 x i8]
  %neg = icmp slt i128 %v, 0
  %negv = sub i128 0, %v
  %mag128 = select i1 %neg, i128 %negv, i128 %v
  %mag = trunc i128 %mag128 to i64
  br label %loop
loop:
  %i = phi i64 [ 24, %entry ], [ %i2, %loop ]
  %m = phi i64 [ %mag, %entry ], [ %q, %loop ]
  %r = urem i64 %m, 10
  %q = udiv i64 %m, 10
  %c = add i64 %r, 48
  %c8 = trunc i64 %c to i8
  %i2 = sub i64 %i, 1
  %p = getelementptr i8, ptr %digits, i64 %i2
  store i8 %c8, ptr %p
  %done = icmp eq i64 %q, 0
  br i1 %done, label %copy, label %loop
copy:
  %len = sub i64 24, %i2
  %signlen = zext i1 %neg to i64
  br i1 %neg, label %sign, label %body
sign:
  store i8 45, ptr %buf
  br label %body
body:
  %dst = getelementptr i8, ptr %buf, i64 %signlen
  %src = getelementptr i8, ptr %digits, i64 %i2
  call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 %len, i1 false)
  %off = add i64 %signlen, %len
  %dst2 = getelementptr i8, ptr %buf, i64 %off
  call void @llvm.memcpy.p0.p0.i64(ptr %dst2, ptr %sfx, i64 %n, i1 false)
  %total = add i64 %off, %n
  %s0 = insertvalue %FaberRtSliceV1 undef, ptr %buf, 0
  %s1 = insertvalue %FaberRtSliceV1 %s0, i64 %total, 1
  call void @__faber_rt_v1_fatal(ptr %ctx, %FaberRtSliceV1 %s1)
  unreachable
}

---

All targets · Measured support per term