opt: support 64-bit OpAccessChain index in FixStorageClass (#5446)
The SPIR-V specification allows any scalar integer type as an index. DXC
usually emits indexes as 32-bit integer types, however, in some cases it
is possible to make it emit 64-bit indexes instead (as in
https://github.com/microsoft/DirectXShaderCompiler/issues/5638).
diff --git a/source/opt/fix_storage_class.cpp b/source/opt/fix_storage_class.cpp
index 5597e82..564cd1b 100644
--- a/source/opt/fix_storage_class.cpp
+++ b/source/opt/fix_storage_class.cpp
@@ -318,7 +318,13 @@
const analysis::Constant* index_const =
context()->get_constant_mgr()->FindDeclaredConstant(
inst->GetSingleWordInOperand(i));
- uint32_t index = index_const->GetU32();
+ // It is highly unlikely that any type would have more fields than could
+ // be indexed by a 32-bit integer, and GetSingleWordInOperand only takes
+ // a 32-bit value, so we would not be able to handle it anyway. But the
+ // specification does allow any scalar integer type, treated as signed,
+ // so we simply downcast the index to 32-bits.
+ uint32_t index =
+ static_cast<uint32_t>(index_const->GetSignExtendedValue());
id = type_inst->GetSingleWordInOperand(index);
break;
}
diff --git a/test/opt/fix_storage_class_test.cpp b/test/opt/fix_storage_class_test.cpp
index 93ce873..684e006 100644
--- a/test/opt/fix_storage_class_test.cpp
+++ b/test/opt/fix_storage_class_test.cpp
@@ -874,6 +874,47 @@
SinglePassRunAndMatch<FixStorageClass>(text, false);
}
+TEST_F(FixStorageClassTest, SupportsU64Index) {
+ const std::string text = R"(
+; CHECK: OpAccessChain %_ptr_Uniform_float
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %1 "testMain" %gl_LocalInvocationID
+ OpExecutionMode %1 LocalSize 8 8 1
+ OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId
+ OpDecorate %8 DescriptorSet 0
+ OpDecorate %8 Binding 0
+ OpDecorate %_runtimearr_float ArrayStride 4
+ OpMemberDecorate %_struct_7 0 Offset 0
+ OpDecorate %_struct_7 BufferBlock
+ %ulong = OpTypeInt 64 0
+ %ulong_0 = OpConstant %ulong 0
+ %float = OpTypeFloat 32
+ %float_123 = OpConstant %float 123
+ %uint = OpTypeInt 32 0
+ %uint_10 = OpConstant %uint 10
+%_runtimearr_float = OpTypeRuntimeArray %float
+ %_struct_7 = OpTypeStruct %_runtimearr_float
+%_ptr_Uniform__struct_7 = OpTypePointer Uniform %_struct_7
+ %v3uint = OpTypeVector %uint 3
+%_ptr_Input_v3uint = OpTypePointer Input %v3uint
+ %void = OpTypeVoid
+ %30 = OpTypeFunction %void
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+ %8 = OpVariable %_ptr_Uniform__struct_7 Uniform
+%gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input
+ %1 = OpFunction %void None %30
+ %38 = OpLabel
+ %44 = OpLoad %v3uint %gl_LocalInvocationID
+ %59 = OpCompositeExtract %uint %44 0
+ %60 = OpAccessChain %_ptr_Uniform_float %8 %ulong_0 %59
+ OpStore %60 %float_123
+ OpReturn
+ OpFunctionEnd
+)";
+
+ SinglePassRunAndMatch<FixStorageClass>(text, false);
+}
} // namespace
} // namespace opt