================ @@ -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; ---------------- CoTinker wrote:
SSE size is 16? Consider such structure: ``` struct { double a; struct {} b; } ``` Maybe `RegSize = neededInt ? neededInt * 8 : 8`, I think? https://github.com/llvm/llvm-project/pull/101639 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits