Repository: shader-slang/slang (2026-04-08T19:03:46Z)

Issue:
ICE when using RWByteAddressBuffer.Load<T>/Store<T> with interface type
## Issue Description

`RWByteAddressBuffer.Load<T>()` and `.Store<T>()` crash with ICE 99999 when `T` is an interface type. The front-end accepts the code without errors, but code generation fails during emit for SPIRV and HLSL targets. On CPU, the shader runs but produces empty output (no values written).

## Reproducer Code

```hlsl
[anyValueSize(8)]
interface IFoo
{
    float getValue();
}

struct ImplA : IFoo
{
    float v;
    float getValue() { return v; }
}

RWByteAddressBuffer byteBuffer;
RWStructuredBuffer<float> outputBuffer;

[numthreads(1, 1, 1)]
void computeMain()
{
    ImplA a;
    a.v = 7.0;
    IFoo fooA = a;
    byteBuffer.Store<IFoo>(0, fooA);

    IFoo loaded = byteBuffer.Load<IFoo>(0);
    outputBuffer[0] = loaded.getValue();
}
```

**Commands:**
```bash
slangc test.slang -target spirv -stage compute -entry computeMain -conformance "ImplA:IFoo=1"
slangc test.slang -target hlsl -stage compute -entry computeMain -conformance "ImplA:IFoo=1"
```

## Expected Behavior

The code should either compile and produce correct output (Load/Store serializes the existential tuple), or produce a clear diagnostic if interface types are not supported in ByteAddressBuffer Load/Store.

## Actual Behavior

**SPIRV target:**
```
error[E99999]: Slang compilation aborted due to an exception of N5Slang13InternalErrorE unimplemented: Unhandled local inst in spirv-emit:
let  %1 : %2 = lookupWitness(%3, %IFoox5FgetValue)
```

**HLSL target:**
```
internal error[E99999]: unimplemented feature in Slang compiler: unexpected IR opcode during code emit
```

**CPU target:** Compiles and runs without error but produces empty output buffer.

## Environment

- Slang Version: d6a3e4dcb (master)
- OS: macOS
- Targets: spirv, hlsl, cpu

Note: `StructuredBuffer<IFoo>` and `RWStructuredBuffer<IFoo>` work correctly with interface types. The issue is specific to the `ByteAddressBuffer` generic Load/Store path.


Discussion:

Patch:
diff --git a/source/slang/slang-ir-translate.cpp b/source/slang/slang-ir-translate.cpp
index 76a9649b00f..d08fa3f5dbb 100644
--- a/source/slang/slang-ir-translate.cpp
+++ b/source/slang/slang-ir-translate.cpp
@@ -391,10 +391,13 @@ IRInst* _resolveInstRec(TranslationContext* ctx, IRInst* inst)
     // At this point, we've resolved anything that can be translated & not in the global scope (i.e.
     // things like arithmetic operations)
     //
-    // If we still have something that's not in the global scope, then something went wrong.
-    // since all operations after this point require this.
+    // If the instruction is not at module scope, it cannot be resolved further.
+    // This can happen when a generic is specialized with an existential/interface type,
+    // producing function-local instructions that reach this resolution logic.
+    // Return the instruction as-is and let later passes handle the diagnostic.
     //
-    SLANG_ASSERT(as<IRModuleInst>(instWithCanonicalOperands->getParent()));
+    if (!as<IRModuleInst>(instWithCanonicalOperands->getParent()))
+        return instWithCanonicalOperands;
 
     // TODO: Group these.
     if (as<IRTranslateBase>(instWithCanonicalOperands) ||
diff --git a/source/slang/slang-ir-typeflow-specialize.cpp b/source/slang/slang-ir-typeflow-specialize.cpp
index e2d3cf84e6b..a32e8a1e4a0 100644
--- a/source/slang/slang-ir-typeflow-specialize.cpp
+++ b/source/slang/slang-ir-typeflow-specialize.cpp
@@ -223,6 +223,24 @@ bool isInvalidExistentialSpecialization(IRInst* specializedValue)
         {
             for (auto inst : block->getOrdinaryInsts())
             {
+                // Detect ByteAddressBufferLoad/Store specialized with an interface type.
+                // When byteAddressBufferLoad<IFoo> is specialized, the result type of
+                // the load instruction (or an operand type of the store) will be an
+                // interface type, which is not supported.
+                if (inst->getOp() == kIROp_ByteAddressBufferLoad)
+                {
+                    if (as<IRInterfaceType>(inst->getDataType()))
+                        return true;
+                }
+                if (inst->getOp() == kIROp_ByteAddressBufferStore)
+                {
+                    // Operands: (buffer, offset, alignment, value).
+                    // The stored value is at index 3.
+                    if (inst->getOperandCount() > 3 &&
+                        as<IRInterfaceType>(inst->getOperand(3)->getDataType()))
+                        return true;
+                }
+
                 auto call = as<IRCall>(inst);
                 if (!call)
                     continue;


Test patch:
diff --git a/tests/bugs/byte-address-buffer-interface-load-store.slang b/tests/bugs/byte-address-buffer-interface-load-store.slang
new file mode 100644
index 00000000000..fe5d6b5bf85
--- /dev/null
+++ b/tests/bugs/byte-address-buffer-interface-load-store.slang
@@ -0,0 +1,35 @@
+// Test that using ByteAddressBuffer.Load<T>/Store<T> with an interface type
+// emits a diagnostic instead of crashing the compiler.
+// GitHub issue: #10376
+
+//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK): -target spirv -stage compute -entry computeMain -conformance "ImplA:IFoo=1"
+//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK): -target hlsl -stage compute -entry computeMain -conformance "ImplA:IFoo=1"
+
+[anyValueSize(8)]
+interface IFoo
+{
+    float getValue();
+}
+
+struct ImplA : IFoo
+{
+    float v;
+    float getValue() { return v; }
+}
+
+RWByteAddressBuffer byteBuffer;
+RWStructuredBuffer<float> outputBuffer;
+
+[numthreads(1, 1, 1)]
+void computeMain()
+{
+    ImplA a;
+    a.v = 7.0;
+    IFoo fooA = a;
+    byteBuffer.Store<IFoo>(0, fooA);
+
+    IFoo loaded = byteBuffer.Load<IFoo>(0);
+    outputBuffer[0] = loaded.getValue();
+}
+
+// CHECK: error[E33180]