Repro: (compile with dxc -T cs_6_0):
RWByteAddressBuffer gBuf0 : register(u0);
RWByteAddressBuffer gBuf1 : register(u1);
[numthreads(1,1,1)]
void main(uint3 tid : SV_DispatchThreadID) {
RWByteAddressBuffer a = gBuf0;
RWByteAddressBuffer b = gBuf1;
(true ? a : b) = gBuf1; // expected: rebinds a to gBuf1
a.Store(tid.x * 4, 42); // expected: writes 42 to gBuf1
}
Expected: Either (a) sema error "expression is not assignable" (matching DXC's own behavior for uint/float4/float4x4/scalar struct lvalue ternary), or (b) the assignment is honored and a.Store writes to gBuf1.
Actual:
- Debug build: assert getValueKind() == VK_LValue fires in tools/clang/lib/AST/ExprClassification.cpp:56 (ClassifyImpl); compiler exits with status -5.
- Release build: compile succeeds, but the ternary-lvalue assignment is silently dropped. Emitted DXIL stores 42 to gBuf0_UAV_rawbuf (register u0), not gBuf1_UAV_rawbuf (register u1).
Type-class scope: Bug only reproduces when the ternary's lvalue type is a resource/object type (RWByteAddressBuffer, RWStructuredBuffer, Texture2D, SamplerState, ...). Scalars/vectors/matrices/POD structs already produce the expected sema error.
This is the resulting IR for assert-disabled builds:
%dx.types.Handle = type { i8* }
%struct.RWByteAddressBuffer = type { i32 }
define void @main() {
%gBuf1_UAV_rawbuf = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 1, i32 1, i1 false), !dbg !41
%gBuf0_UAV_rawbuf = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 0, i1 false), !dbg !41
%1 = call i32 @dx.op.threadId.i32(i32 93, i32 0), !dbg !42
call void @llvm.dbg.value(metadata i32 %1, i64 0, metadata !43, metadata !44), !dbg !45
%2 = shl i32 %1, 2, !dbg !46
call void @dx.op.rawBufferStore.i32(i32 140, %dx.types.Handle %gBuf0_UAV_rawbuf, i32 %2, i32 undef, i32 1, i32 undef, i32 undef, i32 undef, i8 i32 4), !dbg !47
call void @dx.op.rawBufferStore.i32(i32 140, %dx.types.Handle %gBuf1_UAV_rawbuf, i32 %2, i32 undef, i32 2, i32 undef, i32 undef, i32 undef, i8 i32 4), !dbg !48
ret void, !dbg !49
}
declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #0
declare i32 @dx.op.threadId.i32(i32, i32) #0
declare void @dx.op.rawBufferStore.i32(i32, %dx.types.Handle, i32, i32, i32, i32, i32, i32, i8, i32) #1
declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1) #2
attributes #0 = { nounwind readnone }
attributes #1 = { nounwind }
attributes #2 = { nounwind readonly }
An obscure LLVM internal failure occurs:
# .---command stderr------------
# | Internal compiler error: LLVM Assert
# `-----------------------------
# error: command failed with exit status: 0xe0000001
--
********************
When targeting warp d3d12 as well.
Assisted by: Github Copilot
Repro: (compile with dxc -T cs_6_0):
Expected: Either (a) sema error "expression is not assignable" (matching DXC's own behavior for uint/float4/float4x4/scalar struct lvalue ternary), or (b) the assignment is honored and a.Store writes to gBuf1.
Actual:
Type-class scope: Bug only reproduces when the ternary's lvalue type is a resource/object type (RWByteAddressBuffer, RWStructuredBuffer, Texture2D, SamplerState, ...). Scalars/vectors/matrices/POD structs already produce the expected sema error.
This is the resulting IR for assert-disabled builds:
An obscure LLVM internal failure occurs:
When targeting warp d3d12 as well.
Assisted by: Github Copilot