fix(ir): vector lane store resolves lane element type [F0.5]
Writing a Vector lane (`v.x = …`, `.y/.z/.w` + colour aliases) panicked with "unresolved type reached LLVM emission". The store path had no vector branch: a `.field_access` target on a Vector fell through to struct-field lookup, matched nothing, left `field_ty = .unresolved`, and built a `ptrTo(.unresolved)` that tripped the LLVM emission guard. The read path resolved the lane fine — the two had diverged (issue-0083 two-resolver class). Extract a shared `Lowering.vectorLaneIndex` resolver and route BOTH paths through it. The read path (`lowerFieldAccessOnType`) delegates to it, dropping its silent `else 0` fallback. A new vector branch in `lowerAssignment` GEPs a typed pointer to the lane (`structGepTyped`) and stores via `storeOrCompound` (plain + compound). `emitStructGep` now addresses a vector base type with a `[0, lane]` GEP. A non-lane field now reports field-not-found on both paths instead of silent-lane-0 / panic. Regression: examples/1506-vectors-lane-store.sx (panicked pre-fix, now reads back written values) + a vectorLaneIndex unit test. Resolves issue 0086; spec documents element assignment.
This commit is contained in:
@@ -1053,3 +1053,23 @@ test "conversions: optionalOfFlattened wraps once, flattening a nested optional"
|
||||
try std.testing.expect(module.types.optionalOf(opt_s64) != opt_s64);
|
||||
}
|
||||
|
||||
|
||||
test "lower: vectorLaneIndex maps swizzle components, colour aliases, rejects non-lanes" {
|
||||
// Positional swizzle components → lanes 0..3.
|
||||
try std.testing.expectEqual(@as(?u32, 0), Lowering.vectorLaneIndex("x"));
|
||||
try std.testing.expectEqual(@as(?u32, 1), Lowering.vectorLaneIndex("y"));
|
||||
try std.testing.expectEqual(@as(?u32, 2), Lowering.vectorLaneIndex("z"));
|
||||
try std.testing.expectEqual(@as(?u32, 3), Lowering.vectorLaneIndex("w"));
|
||||
// Colour aliases share the same lane indices.
|
||||
try std.testing.expectEqual(@as(?u32, 0), Lowering.vectorLaneIndex("r"));
|
||||
try std.testing.expectEqual(@as(?u32, 1), Lowering.vectorLaneIndex("g"));
|
||||
try std.testing.expectEqual(@as(?u32, 2), Lowering.vectorLaneIndex("b"));
|
||||
try std.testing.expectEqual(@as(?u32, 3), Lowering.vectorLaneIndex("a"));
|
||||
// Any non-lane field is rejected (null) so the read and write paths share
|
||||
// one rule — a non-lane store no longer falls through to an .unresolved
|
||||
// pointee that panics at LLVM emission (issue 0086).
|
||||
try std.testing.expectEqual(@as(?u32, null), Lowering.vectorLaneIndex("q"));
|
||||
try std.testing.expectEqual(@as(?u32, null), Lowering.vectorLaneIndex("xy"));
|
||||
try std.testing.expectEqual(@as(?u32, null), Lowering.vectorLaneIndex("len"));
|
||||
try std.testing.expectEqual(@as(?u32, null), Lowering.vectorLaneIndex(""));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user