[llvm] [HLSL][SPIRV] Codegen unbound array as OpTypeRuntimeArray (PR #185551)

via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 9 18:28:21 PDT 2026


=?utf-8?q?João?= Saffran <joaosaffranllvm at gmail.com>
Message-ID: <llvm.org/llvm/llvm-project/pull/185551 at github.com>
In-Reply-To:


https://github.com/joaosaffran created https://github.com/llvm/llvm-project/pull/185551

HLSL supports unbounded resources, such as `RWBuffer`, in order to make them compatible with SPIRV, they require to be generated as `OpTypeRuntimeArray`.
Fix: #183367

>From af0cc4133f5263d8813d62a903cc8275777dcda2 Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranllvm at gmail.com>
Date: Mon, 9 Mar 2026 17:18:40 -0700
Subject: [PATCH 1/2] modify codegen to account for unbound arrays

---
 llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index 9a85634c82626..e2a52a2a17665 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -910,7 +910,18 @@ SPIRVTypeInst SPIRVGlobalRegistry::getOpTypeArray(uint32_t NumElems,
   SPIRVTypeInst ArrayType = nullptr;
   const SPIRVSubtarget &ST =
       cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());
-  if (NumElems != 0) {
+
+  // Unbounded arrays (e.g. RWBuffer Buf[]) are represented in LLVM IR
+  // with UINT32_MAX as the element count. Lower these to OpTypeRuntimeArray
+  // instead of OpTypeArray.
+  if (NumElems == std::numeric_limits<uint32_t>::max()) {
+    ArrayType = createConstOrTypeAtFunctionEntry(
+        MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+          return MIRBuilder.buildInstr(SPIRV::OpTypeRuntimeArray)
+              .addDef(createTypeVReg(MIRBuilder))
+              .addUse(getSPIRVTypeID(ElemType));
+        });
+  } else if (NumElems != 0) {
     Register NumElementsVReg =
         buildConstantInt(NumElems, MIRBuilder, SpvTypeInt32, EmitIR);
     ArrayType = createConstOrTypeAtFunctionEntry(

>From 39d6b19500a130c59f13e83c56d29f6c0e546cbd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Saffran?= <joaosaffranllvm at gmail.com>
Date: Mon, 9 Mar 2026 18:21:30 -0700
Subject: [PATCH 2/2] add missing capability

---
 llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index e2a52a2a17665..363c7ba6911f4 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -915,6 +915,8 @@ SPIRVTypeInst SPIRVGlobalRegistry::getOpTypeArray(uint32_t NumElems,
   // with UINT32_MAX as the element count. Lower these to OpTypeRuntimeArray
   // instead of OpTypeArray.
   if (NumElems == std::numeric_limits<uint32_t>::max()) {
+    MIRBuilder.buildInstr(SPIRV::OpCapability)
+        .addImm(SPIRV::Capability::RuntimeDescriptorArrayEXT);
     ArrayType = createConstOrTypeAtFunctionEntry(
         MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
           return MIRBuilder.buildInstr(SPIRV::OpTypeRuntimeArray)



More information about the llvm-commits mailing list