Skip to content

Commit 68d9f66

Browse files
AntonOrestenclaude
andcommitted
reinterpret: centralize validation in emit so invalid casts fail cleanly
The shape helpers and pack/unpack tfuncs ran inside the kernel-inferred path, where two failure modes produced confusing errors: - A tfunc returning `nothing` on an indivisible width left the result untypable, surfacing downstream as `internal error: invalid terminators`. - A `throw(ArgumentError(...))` in a shape helper became an unsupported `String` in kernel IR (`format_string`/`unsupported String` error), masking the intended message. Make both layers total: pack/unpack tfuncs always return a concrete type (via `fld`), and the shape helpers are pure arithmetic. Validation now lives solely in the pack/unpack/reshape emit, which throws a clear `IRError` (e.g. "unpack: 1 bytes do not evenly divide into Float32"). Valid reinterprets are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 436487d commit 68d9f66

1 file changed

Lines changed: 6 additions & 23 deletions

File tree

src/compiler/intrinsics/conversions.jl

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,7 @@ function tfunc(𝕃, ::typeof(Intrinsics.pack), @nospecialize(x))
8383
length(dims) == 1 || return nothing
8484
n = dims[1]::Int
8585
bs = lookup_bitwidth(S)
86-
(n * bs) % 8 == 0 || return nothing
87-
return Tile{UInt8, Tuple{(n * bs) ÷ 8}}
86+
return Tile{UInt8, Tuple{fld(n * bs, 8)}}
8887
end
8988
function emit_intrinsic!(ctx::CGCtx, ::typeof(Intrinsics.pack), args)
9089
cb = ctx.cb
@@ -132,8 +131,7 @@ function tfunc(𝕃, ::typeof(Intrinsics.unpack), @nospecialize(x), @nospecializ
132131
length(dims) == 1 || return nothing
133132
n = dims[1]::Int
134133
bt = lookup_bitwidth(T)
135-
(n * 8) % bt == 0 || return nothing
136-
return Tile{T, Tuple{(n * 8) ÷ bt}}
134+
return Tile{T, Tuple{fld(n * 8, bt)}}
137135
end
138136
function emit_intrinsic!(ctx::CGCtx, ::typeof(Intrinsics.unpack), args)
139137
cb = ctx.cb
@@ -194,13 +192,8 @@ end
194192
@inline function reinterpret_scaled_shape(::Type{T}, ::Type{S}, sz::NTuple{N, Int}) where {T, S, N}
195193
bs = bitwidth(S)
196194
bt = bitwidth(T)
197-
if N == 0
198-
bs == bt || throw(ArgumentError("reinterpret: a 0-D $S tile ($bs bits) cannot be reinterpreted as $T ($bt bits)"))
199-
return ()
200-
end
201-
(sz[1] * bs) % bt == 0 ||
202-
throw(ArgumentError("reinterpret: leading dimension $(sz[1]) of a $S tile ($(sz[1] * bs) bits) is not divisible by $bt-bit $T"))
203-
return (div(sz[1] * bs, bt), Base.tail(sz)...)
195+
N == 0 && return () # 0-D: only equal-width is valid; cross-width caught at emit
196+
return (fld(sz[1] * bs, bt), Base.tail(sz)...)
204197
end
205198

206199
# Result shape for `reinterpret(reshape, T, x)`: drop the leading dim on widening
@@ -209,18 +202,8 @@ end
209202
bs = bitwidth(S)
210203
bt = bitwidth(T)
211204
bs == bt && return sz
212-
if bt > bs
213-
bt % bs == 0 ||
214-
throw(ArgumentError("reinterpret(reshape, $T, x): $T ($bt bits) is not a whole multiple of $S ($bs bits)"))
215-
r = div(bt, bs)
216-
(N >= 1 && sz[1] == r) ||
217-
throw(ArgumentError("reinterpret(reshape, $T, x): leading dimension must be $r, got $(N == 0 ? () : sz[1])"))
218-
return Base.tail(sz)
219-
else
220-
bs % bt == 0 ||
221-
throw(ArgumentError("reinterpret(reshape, $T, x): $S ($bs bits) is not a whole multiple of $T ($bt bits)"))
222-
return (div(bs, bt), sz...)
223-
end
205+
N == 0 && return () # cross-width on a 0-D tile is invalid; caught at emit
206+
return bt > bs ? Base.tail(sz) : (div(bs, bt), sz...)
224207
end
225208

226209
"""

0 commit comments

Comments
 (0)