[clang] [HLSL] Handle logical pointer for array assign (PR #193227)

Steven Perron via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 22 07:07:10 PDT 2026


Nathan =?utf-8?q?Gauër?= <brioche at google.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/193227 at github.com>


================
@@ -1545,51 +1515,86 @@ class HLSLBufferCopyEmitter {
     llvm::Type *ElementTy = ST->getElementType(1);
     if (PaddedTy->getElementType(0) != ElementTy)
       return false;
+    return true;
+  }
 
-    // All but the last of the logical array elements are in the padded array.
-    unsigned NumElts = PaddedEltsTy->getNumElements() + 1;
-
-    // Add an extra indirection to the load for the struct and walk the
-    // array prefix.
-    CurLoadIndices.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 0));
-    for (unsigned I = 0; I < NumElts - 1; ++I) {
-      // We need to copy the element itself, without the padding.
-      CurLoadIndices.push_back(llvm::ConstantInt::get(CGF.SizeTy, I));
-      emitCopyAtIndices(ElementTy, llvm::ConstantInt::get(CGF.SizeTy, I),
-                        llvm::ConstantInt::get(CGF.Int32Ty, 0));
-      CurLoadIndices.pop_back();
+  void emitBufferLayoutCopy(Value *Src, llvm::StructType *SrcTy, Value *Dst,
+                            llvm::ArrayType *DstTy) {
+    // Those assumptions are checked by isBufferLayoutArray.
+    auto *SrcPaddedArrayTy = cast<llvm::ArrayType>(SrcTy->getElementType(0));
+    auto *SrcPaddedEltTy =
+        cast<llvm::StructType>(SrcPaddedArrayTy->getElementType());
+    assert(SrcPaddedArrayTy->getNumElements() + 1 == DstTy->getNumElements());
+    assert(SrcPaddedEltTy->getElementType(0) == SrcTy->getElementType(1));
+
+    auto *SrcDataTy = SrcTy->getElementType(1);
+    auto Zero = llvm::ConstantInt::get(CGF.IntTy, 0);
+
+    for (unsigned I = 0; I < SrcPaddedArrayTy->getNumElements(); ++I) {
+      auto Index = llvm::ConstantInt::get(CGF.IntTy, I);
+      auto *SrcElt = emitAccessChain(SrcTy, Src, {Zero, Index, Zero});
+      auto *DstElt = emitAccessChain(DstTy, Dst, {Index});
+      emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType());
     }
-    CurLoadIndices.pop_back();
-
-    // Now copy the last element.
-    emitCopyAtIndices(ElementTy,
-                      llvm::ConstantInt::get(CGF.SizeTy, NumElts - 1),
-                      llvm::ConstantInt::get(CGF.Int32Ty, 1));
 
-    return true;
+    auto *SrcElt =
+        emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, 1)});
+    auto *DstElt = emitAccessChain(
+        DstTy, Dst,
+        {llvm::ConstantInt::get(CGF.IntTy, DstTy->getNumElements() - 1)});
+    emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType());
   }
 
-  bool processStruct(llvm::Type *FieldTy) {
-    auto *ST = dyn_cast<llvm::StructType>(FieldTy);
-    if (!ST)
-      return false;
+  void emitCopy(Value *Src, llvm::StructType *SrcTy, Value *Dst,
+                llvm::Type *DstTy) {
+    if (isBufferLayoutArray(SrcTy))
+      return emitBufferLayoutCopy(Src, SrcTy, Dst,
+                                  cast<llvm::ArrayType>(DstTy));
+
+    auto *DST = cast<llvm::StructType>(DstTy);
+    for (unsigned I = 0; I < SrcTy->getNumElements(); ++I) {
+      auto *SrcElt =
+          emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, I)});
+      auto *DstElt =
+          emitAccessChain(DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, I)});
----------------
s-perron wrote:

The old code skipped padding. Can you justify why you dropped that?

https://github.com/llvm/llvm-project/pull/193227


More information about the cfe-commits mailing list