Files
sx/issues/0155-scalar-pointer-index-llvm-panic.md
agra 8367ad18b1 fibers: M:1 scheduler core + suspending fiber-task async (B1.5a, B1.4a)
library/modules/std/sched.sx: a generic Fiber + Scheduler over the
proven naked swap_context on guarded mmap stacks --
init/spawn/yield_now/suspend_self/wake/run (B1.5a), then Task($R) +
go/wait/cancel, a truly-suspending nullary-thunk async layer (B1.4a).
go(work) runs a thunk as a real fiber; wait() parks the caller until it
completes. Self-contained in sched.sx (io.sx importing it would
duplicate the _fib_tramp global asm).

Hardened per adversarial review: wake guarded on .suspended (FIFO
corruption), suspend_self/yield_now guard a null current, loud
mmap/mprotect/OOM/deadlock bails, cancel skips not-yet-run work.
Closure-env + heap-Task leaks documented (bounded, default-GPA-invisible).

Examples: 1811 (round-robin), 1812 (suspend/wake + spurious-wake guard),
1813 (async interleave + await-suspend + cancel). Also files issue 0155
(scalar-pointer index panics codegen -- non-blocking, found in review).
2026-06-21 18:44:03 +03:00

2.5 KiB

issue 0155 — indexing a scalar pointer (pc[0], pc: *i64) panics at LLVM emission

OPEN. Found incidentally during an adversarial review of the fiber scheduler (a review probe used pc[0] on a *i64). NOT a fibers-stream blocker — the scheduler uses array-field indexing (ctx.regs[i]) and pointer deref (p.*), never scalar-pointer indexing — so it is filed for its own fix session, not fixed inline.

Symptom

Indexing a pointer-to-scalar value with [i] crashes the compiler:

thread … panic: unresolved type reached LLVM emission — a type resolution
failure was not diagnosed/aborted
  src/backend/llvm/types.zig:196:28  toLLVMTypeInfo  (.unresolved arm)
  src/backend/llvm/types.zig:38      toLLVMType
  src/ir/emit_llvm.zig:2564          toLLVMType

Observed: compiler panic (no diagnostic). Expected: either lower pc[i] as *(pc + i) (C semantics), or emit a clean diagnostic that a bare *T is not indexable (deref with .*, or use a slice []T). A .unresolved TypeId reaching LLVM emission is unconditionally a compiler bug (a resolution failure that was neither diagnosed nor aborted).

Reproduction

#import "modules/std.sx";
main :: () -> i64 {
    x : i64 = 5;
    pc : *i64 = @x;
    return pc[0];   // panics the compiler
}

(repro: issues/0155-scalar-pointer-index-llvm-panic.sx)

Investigation prompt

The sx compiler panics ("unresolved type reached LLVM emission", src/backend/llvm/types.zig:196) when an index expression pc[i] is applied to a value of pointer-to-scalar type *T (repro: issues/0155-scalar-pointer-index-llvm-panic.sx). Trace emitIndexGet (src/backend/llvm/ops.zig ~1988) and the index-expr lowering in src/ir/lower/ (the .index_expr arm): for a *T object, the element type resolves to .unresolved instead of T. Decide the intended semantics first (consult specs.md for whether a bare *T is indexable): if pc[i] should mean *(pc + i), fix the index-expr type resolver to yield the pointee type T for a *T object (mirror the slice/array-pointer arm — see ptrToArrayElem / getElementType in src/ir/lower/), and verify codegen emits a GEP + load. If a bare *T is intentionally NOT indexable, emit a diagnostic at the lowering site ("cannot index *T; deref with .* or use a slice") and never let .unresolved reach emission. Verify: sx run the repro — expect either 5 (if indexable) or a clean compile error, never a panic. Then promote the repro to a regression test under examples/.