Files
sx/issues/0086-vector-lane-store-unresolved-panic.md
agra 7238eea084 docs(issues): file 0086 — Vector lane store panics (discovered, pre-existing)
While fixing 0083 (attempt 5) noticed a distinct, pre-existing bug:
writing to a Vector component (`v.x = 1.0`) aborts with "unresolved type
reached LLVM emission" in emitStore. Reading a lane works; a literal lane
count triggers it, so it is NOT the lane-count class. Confirmed
reproducible on the pristine pre-attempt-5 compiler (not introduced by
the lane-count fix). The standard vector idiom (`.[…]` construction +
component reads / arithmetic, examples/1500) is unaffected. Filed for a
separate session; not worked around here.
2026-06-04 11:32:31 +03:00

2.8 KiB

0086 — writing to a Vector lane (v.x = …) panics with "unresolved type reached LLVM emission"

Symptom

Assigning to a component of a Vector local — v.x = 1.0 (also .y / .z / .w) — aborts the compiler with the internal panic:

thread … panic: unresolved type reached LLVM emission — a type resolution
failure was not diagnosed/aborted
  src/backend/llvm/types.zig:175  toLLVMTypeInfo  (.unresolved arm @panic)
  src/backend/llvm/ops.zig:358    emitStore       (.pointer => toLLVMType(p.pointee))

READING a lane (x := v.x) is fine; only the STORE side hits it. The init form (= --- undefined vs = .[…] literal) does not matter — both panic once a lane is written. A literal lane count (Vector(3, f32)) triggers it, so this is NOT the lane-count resolution class (issue 0083); it is a distinct bug in the vector-lane store path, where the store's pointee type resolves to the .unresolved sentinel instead of the lane element type.

Discovered while fixing issue 0083 (attempt 5). It is pre-existing and orthogonal — confirmed by reproducing on the pristine pre-0083-attempt-5 compiler — so it was NOT introduced by the lane-count fix. The standard vector idiom (construct via a .[…] literal / a constructor function returning .[…], then read components or use vector arithmetic, as in examples/1500-vectors-vector-math.sx) is unaffected; only component ASSIGNMENT is broken.

Reproduction

#import "modules/std.sx";
main :: () {
    v : Vector(3, f32) = .[0.0, 0.0, 0.0];
    v.x = 1.0;                    // panic here
    print("x={}\n", v.x);
}

./zig-out/bin/sx run panics. Removing the v.x = 1.0 line (read-only) prints x=0.000000 and exits 0.

Investigation prompt

A store to a Vector lane (v.x = …) lowers a pointer-to-lane whose pointee type reaches LLVM as .unresolved, so emitStore (src/backend/llvm/ops.zig:358, the .pointer => toLLVMType(p.pointee) arm) hits the .unresolved tripwire panic in src/backend/llvm/types.zig:175. The lane READ path computes the lane element type correctly, so compare the lvalue/store lowering for a vector-component assignment against the rvalue/load path — the component-write path is likely building the lane pointer's pointee from a vector .x/.y/.z/.w field resolution that returns .unresolved (or a vector field-access that resolves the element type on load but not on store). Find where a Vector swizzle/component assignment lowers its destination pointer (grep for vector component handling in lower.zig assignment lowering and in the LLVM emitStore GEP path) and resolve the lane element type there the same way the load path does. Verify with the repro (expect x=1.000000) plus a .[…]-init write and a write to each of .x/.y/.z/.w on a 4-lane vector, then zig build && zig build test && bash tests/run_examples.sh green.