Skip to content

Metal: dynamic dispatch uint2 handle type cannot be cast to pointer #11313

Description

@jhelferty-nv

Summary

The dynamic dispatch infrastructure lowers WitnessTableIDType and RTTIHandleType to uint2 (vector of 2×uint32) in slang-ir-lower-dynamic-dispatch-insts.cpp:1607-1634. This works on SPIRV/CUDA/CPU where uint2 can be bitcast to a 64-bit pointer, but fails on Metal because MSL does not allow vector-to-pointer casts.

Error

When enabling Metal on tests that use interface/existential pointers (e.g. tests/language-feature/dynamic-dispatch/buffer-address-ref.slang):

metal error: cannot cast from type 'uint2' (vector of 2 'unsigned int' values) to pointer type 'device Tuple_0 *'

Root cause

lowerHandleTypes() in slang-ir-lower-dynamic-dispatch-insts.cpp unconditionally replaces WitnessTableID and RTTIHandle types with uint2. The uint2 was chosen to avoid Int64 capability requirements (PR #9386). However, Metal fully supports Int64 (ulong) and requires scalar types for pointer casts.

Proposed fix

Option A (emitter-level): In slang-emit-metal.cpp, when emitting a cast from uint2 to a pointer type, emit a two-step cast: as_type<ulong>(uint2Value) then (device T*)ulongValue.

Option B (IR-level): On Metal targets, lower handles to ulong instead of uint2 in lowerHandleTypes(). Metal has Int64 support, so the "avoid Int64" concern doesn't apply.

Context

Found while investigating whether tests/language-feature/dynamic-dispatch/buffer-address-ref.slang could be enabled for Metal as part of PR #10947 (Metal pointer-to-pointer lowering).

Related: #9828 (dynamic dispatch quality umbrella)

Metadata

Metadata

Assignees

Type

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions