================
@@ -1101,3 +1111,236 @@ std::optional<LValue> 
CGHLSLRuntime::emitResourceArraySubscriptExpr(
   }
   return CGF.MakeAddrLValue(TmpVar, ResultTy, AlignmentSource::Decl);
 }
+
+std::optional<LValue> CGHLSLRuntime::emitBufferArraySubscriptExpr(
+    const ArraySubscriptExpr *E, CodeGenFunction &CGF,
+    llvm::function_ref<llvm::Value *(bool Promote)> EmitIdxAfterBase) {
+  // Find the element type to index by first padding the element type per HLSL
+  // buffer rules, and then padding out to a 16-byte register boundary if
+  // necessary.
+  llvm::Type *LayoutTy =
+      HLSLBufferLayoutBuilder(CGF.CGM).layOutType(E->getType());
+  uint64_t LayoutSizeInBits =
+      CGM.getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
+  CharUnits ElementSize = CharUnits::fromQuantity(LayoutSizeInBits / 8);
+  CharUnits RowAlignedSize = ElementSize.alignTo(CharUnits::fromQuantity(16));
+  if (RowAlignedSize > ElementSize) {
+    llvm::Type *Padding = CGM.getTargetCodeGenInfo().getHLSLPadding(
+        CGM, RowAlignedSize - ElementSize);
+    assert(Padding && "No padding type for target?");
+    LayoutTy = llvm::StructType::get(CGF.getLLVMContext(), {LayoutTy, Padding},
+                                     /*isPacked=*/true);
+  }
+
+  // If the layout type doesn't introduce any padding, we don't need to do
+  // anything special.
+  llvm::Type *OrigTy = CGF.CGM.getTypes().ConvertTypeForMem(E->getType());
+  if (LayoutTy == OrigTy)
+    return std::nullopt;
+
+  LValueBaseInfo EltBaseInfo;
+  TBAAAccessInfo EltTBAAInfo;
+  Address Addr =
+      CGF.EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
+  llvm::Value *Idx = EmitIdxAfterBase(/*Promote*/ true);
+
+  // Index into the object as-if we have an array of the padded element type,
+  // and then dereference the element itself to avoid reading padding that may
+  // be past the end of the in-memory object.
+  SmallVector<llvm::Value *, 2> Indices;
+  Indices.push_back(Idx);
+  Indices.push_back(llvm::ConstantInt::get(Idx->getType(), 0));
+
+  llvm::Value *GEP = CGF.Builder.CreateGEP(LayoutTy, Addr.emitRawPointer(CGF),
+                                           Indices, "cbufferidx");
+  Addr = Address(GEP, Addr.getElementType(), RowAlignedSize, KnownNonNull);
----------------
s-perron wrote:

I was trying the example below, and I'm getting an error when compiling for 
spir-v. It complains that the GEP is not valid. This is coming from the 
verifier. It does not fail for DXIL. Do you know anything about this?

```
Invalid indices for GEP pointer type!
  %cbufferidx = getelementptr <{ <3 x float>, target("spirv.Padding", 4) }>, 
ptr addrspace(12) @myArray, i64 %idxprom, i64 0
fatal error: error in backend: Broken module found, compilation aborted!
```

```
cbuffer MyCBuffer : register(b0)
{
    // An array of 3 elements. This should be represented in IR
    // as a struct containing an array of 2 elements and a final
    // separate element to handle cbuffer padding rules.
    float3 myArray[3];
};

RWStructuredBuffer<float3> output : register(u0);

[numthreads(8, 1, 1)]
void main(uint3 dispatchThreadID : SV_DispatchThreadID)
{
    // Access the array with a variable index to ensure
    // the compiler generates GEPs for indexing.
    uint index = dispatchThreadID.x % 3;
    output[dispatchThreadID.x] = myArray[index];
}
```

https://github.com/llvm/llvm-project/pull/167404
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to