[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #101639)

Eli Friedman via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 12 11:00:58 PDT 2024


================
@@ -3124,26 +3124,76 @@ RValue X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
     CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1));
 
     RegAddr = Tmp.withElementType(LTy);
-  } else if (neededInt) {
-    RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset),
-                      LTy, CharUnits::fromQuantity(8));
-
+  } else if (neededInt || neededSSE == 1) {
     // Copy to a temporary if necessary to ensure the appropriate alignment.
     auto TInfo = getContext().getTypeInfoInChars(Ty);
     uint64_t TySize = TInfo.Width.getQuantity();
     CharUnits TyAlign = TInfo.Align;
+    llvm::Type *CoTy = nullptr;
+    uint64_t RegSize = TySize;
+    if (AI.isDirect())
+      CoTy = AI.getCoerceToType();
+    // Obtain the actual register storage size.
+    if (CoTy) {
+      if (CoTy->isStructTy()) {
+        RegSize = 0;
+        auto ST = cast<llvm::StructType>(CoTy);
+        for (unsigned i = 0; i < ST->getNumElements(); ++i) {
+          auto elementType = ST->getElementType(i);
+          RegSize += CGF.CGM.getDataLayout().getTypeAllocSize(elementType);
+        }
+      } else {
+        RegSize = CGF.CGM.getDataLayout().getTypeAllocSize(CoTy);
+      }
+    }
 
-    // Copy into a temporary if the type is more aligned than the
-    // register save area.
-    if (TyAlign.getQuantity() > 8) {
+    llvm::Value *GpOrFpOffset = neededInt ? gp_offset : fp_offset;
+    uint64_t Alignment = neededInt ? 8 : 16;
+    // There are two cases require special handling:
+    // 1)
+    //    ```
+    //    struct {
+    //      struct {} a[8];
+    //      int b;
+    //    };
+    //    ```
+    //    The lower 8 bytes of the structure are not stored,
+    //    so an 8-byte offset is needed when accessing the structure.
+    // 2)
+    //   ```
+    //   struct {
+    //     long long a;
+    //     int b;
----------------
efriedma-quic wrote:

The relevant "size" here is the size of the slots in the register save area.  Which is 16 bytes for fp registers.

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


More information about the cfe-commits mailing list