1992cb984SSergei Barannikov //===- ABIInfoImpl.cpp ----------------------------------------------------===// 2992cb984SSergei Barannikov // 3992cb984SSergei Barannikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4992cb984SSergei Barannikov // See https://llvm.org/LICENSE.txt for license information. 5992cb984SSergei Barannikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6992cb984SSergei Barannikov // 7992cb984SSergei Barannikov //===----------------------------------------------------------------------===// 8992cb984SSergei Barannikov 9992cb984SSergei Barannikov #include "ABIInfoImpl.h" 10992cb984SSergei Barannikov 11992cb984SSergei Barannikov using namespace clang; 12992cb984SSergei Barannikov using namespace clang::CodeGen; 13992cb984SSergei Barannikov 14992cb984SSergei Barannikov // Pin the vtable to this file. 15992cb984SSergei Barannikov DefaultABIInfo::~DefaultABIInfo() = default; 16992cb984SSergei Barannikov 17992cb984SSergei Barannikov ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const { 18992cb984SSergei Barannikov Ty = useFirstFieldIfTransparentUnion(Ty); 19992cb984SSergei Barannikov 20992cb984SSergei Barannikov if (isAggregateTypeForABI(Ty)) { 21992cb984SSergei Barannikov // Records with non-trivial destructors/copy-constructors should not be 22992cb984SSergei Barannikov // passed by value. 23992cb984SSergei Barannikov if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) 24992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); 25992cb984SSergei Barannikov 26992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty); 27992cb984SSergei Barannikov } 28992cb984SSergei Barannikov 29992cb984SSergei Barannikov // Treat an enum type as its underlying type. 30992cb984SSergei Barannikov if (const EnumType *EnumTy = Ty->getAs<EnumType>()) 31992cb984SSergei Barannikov Ty = EnumTy->getDecl()->getIntegerType(); 32992cb984SSergei Barannikov 33992cb984SSergei Barannikov ASTContext &Context = getContext(); 34992cb984SSergei Barannikov if (const auto *EIT = Ty->getAs<BitIntType>()) 35992cb984SSergei Barannikov if (EIT->getNumBits() > 36992cb984SSergei Barannikov Context.getTypeSize(Context.getTargetInfo().hasInt128Type() 37992cb984SSergei Barannikov ? Context.Int128Ty 38992cb984SSergei Barannikov : Context.LongLongTy)) 39992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty); 40992cb984SSergei Barannikov 41f95026dbSLei Huang return (isPromotableIntegerTypeForABI(Ty) 42f95026dbSLei Huang ? ABIArgInfo::getExtend(Ty, CGT.ConvertType(Ty)) 43992cb984SSergei Barannikov : ABIArgInfo::getDirect()); 44992cb984SSergei Barannikov } 45992cb984SSergei Barannikov 46992cb984SSergei Barannikov ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const { 47992cb984SSergei Barannikov if (RetTy->isVoidType()) 48992cb984SSergei Barannikov return ABIArgInfo::getIgnore(); 49992cb984SSergei Barannikov 50992cb984SSergei Barannikov if (isAggregateTypeForABI(RetTy)) 51992cb984SSergei Barannikov return getNaturalAlignIndirect(RetTy); 52992cb984SSergei Barannikov 53992cb984SSergei Barannikov // Treat an enum type as its underlying type. 54992cb984SSergei Barannikov if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) 55992cb984SSergei Barannikov RetTy = EnumTy->getDecl()->getIntegerType(); 56992cb984SSergei Barannikov 57992cb984SSergei Barannikov if (const auto *EIT = RetTy->getAs<BitIntType>()) 58992cb984SSergei Barannikov if (EIT->getNumBits() > 59992cb984SSergei Barannikov getContext().getTypeSize(getContext().getTargetInfo().hasInt128Type() 60992cb984SSergei Barannikov ? getContext().Int128Ty 61992cb984SSergei Barannikov : getContext().LongLongTy)) 62992cb984SSergei Barannikov return getNaturalAlignIndirect(RetTy); 63992cb984SSergei Barannikov 64992cb984SSergei Barannikov return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) 65992cb984SSergei Barannikov : ABIArgInfo::getDirect()); 66992cb984SSergei Barannikov } 67992cb984SSergei Barannikov 68992cb984SSergei Barannikov void DefaultABIInfo::computeInfo(CGFunctionInfo &FI) const { 69992cb984SSergei Barannikov if (!getCXXABI().classifyReturnType(FI)) 70992cb984SSergei Barannikov FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); 71992cb984SSergei Barannikov for (auto &I : FI.arguments()) 72992cb984SSergei Barannikov I.info = classifyArgumentType(I.type); 73992cb984SSergei Barannikov } 74992cb984SSergei Barannikov 756d973b45SMariya Podchishchaeva RValue DefaultABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 766d973b45SMariya Podchishchaeva QualType Ty, AggValueSlot Slot) const { 776d973b45SMariya Podchishchaeva return CGF.EmitLoadOfAnyValue( 786d973b45SMariya Podchishchaeva CGF.MakeAddrLValue( 796d973b45SMariya Podchishchaeva EmitVAArgInstr(CGF, VAListAddr, Ty, classifyArgumentType(Ty)), Ty), 806d973b45SMariya Podchishchaeva Slot); 81992cb984SSergei Barannikov } 82992cb984SSergei Barannikov 83992cb984SSergei Barannikov void CodeGen::AssignToArrayRange(CodeGen::CGBuilderTy &Builder, 84992cb984SSergei Barannikov llvm::Value *Array, llvm::Value *Value, 85992cb984SSergei Barannikov unsigned FirstIndex, unsigned LastIndex) { 86992cb984SSergei Barannikov // Alternatively, we could emit this as a loop in the source. 87992cb984SSergei Barannikov for (unsigned I = FirstIndex; I <= LastIndex; ++I) { 88992cb984SSergei Barannikov llvm::Value *Cell = 89992cb984SSergei Barannikov Builder.CreateConstInBoundsGEP1_32(Builder.getInt8Ty(), Array, I); 90992cb984SSergei Barannikov Builder.CreateAlignedStore(Value, Cell, CharUnits::One()); 91992cb984SSergei Barannikov } 92992cb984SSergei Barannikov } 93992cb984SSergei Barannikov 94992cb984SSergei Barannikov bool CodeGen::isAggregateTypeForABI(QualType T) { 95992cb984SSergei Barannikov return !CodeGenFunction::hasScalarEvaluationKind(T) || 96992cb984SSergei Barannikov T->isMemberFunctionPointerType(); 97992cb984SSergei Barannikov } 98992cb984SSergei Barannikov 99992cb984SSergei Barannikov llvm::Type *CodeGen::getVAListElementType(CodeGenFunction &CGF) { 100992cb984SSergei Barannikov return CGF.ConvertTypeForMem( 101992cb984SSergei Barannikov CGF.getContext().getBuiltinVaListType()->getPointeeType()); 102992cb984SSergei Barannikov } 103992cb984SSergei Barannikov 104992cb984SSergei Barannikov CGCXXABI::RecordArgABI CodeGen::getRecordArgABI(const RecordType *RT, 105992cb984SSergei Barannikov CGCXXABI &CXXABI) { 106992cb984SSergei Barannikov const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); 107992cb984SSergei Barannikov if (!RD) { 108992cb984SSergei Barannikov if (!RT->getDecl()->canPassInRegisters()) 109992cb984SSergei Barannikov return CGCXXABI::RAA_Indirect; 110992cb984SSergei Barannikov return CGCXXABI::RAA_Default; 111992cb984SSergei Barannikov } 112992cb984SSergei Barannikov return CXXABI.getRecordArgABI(RD); 113992cb984SSergei Barannikov } 114992cb984SSergei Barannikov 115992cb984SSergei Barannikov CGCXXABI::RecordArgABI CodeGen::getRecordArgABI(QualType T, CGCXXABI &CXXABI) { 116992cb984SSergei Barannikov const RecordType *RT = T->getAs<RecordType>(); 117992cb984SSergei Barannikov if (!RT) 118992cb984SSergei Barannikov return CGCXXABI::RAA_Default; 119992cb984SSergei Barannikov return getRecordArgABI(RT, CXXABI); 120992cb984SSergei Barannikov } 121992cb984SSergei Barannikov 122992cb984SSergei Barannikov bool CodeGen::classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, 123992cb984SSergei Barannikov const ABIInfo &Info) { 124992cb984SSergei Barannikov QualType Ty = FI.getReturnType(); 125992cb984SSergei Barannikov 126992cb984SSergei Barannikov if (const auto *RT = Ty->getAs<RecordType>()) 127992cb984SSergei Barannikov if (!isa<CXXRecordDecl>(RT->getDecl()) && 128992cb984SSergei Barannikov !RT->getDecl()->canPassInRegisters()) { 129992cb984SSergei Barannikov FI.getReturnInfo() = Info.getNaturalAlignIndirect(Ty); 130992cb984SSergei Barannikov return true; 131992cb984SSergei Barannikov } 132992cb984SSergei Barannikov 133992cb984SSergei Barannikov return CXXABI.classifyReturnType(FI); 134992cb984SSergei Barannikov } 135992cb984SSergei Barannikov 136992cb984SSergei Barannikov QualType CodeGen::useFirstFieldIfTransparentUnion(QualType Ty) { 137992cb984SSergei Barannikov if (const RecordType *UT = Ty->getAsUnionType()) { 138992cb984SSergei Barannikov const RecordDecl *UD = UT->getDecl(); 139992cb984SSergei Barannikov if (UD->hasAttr<TransparentUnionAttr>()) { 140992cb984SSergei Barannikov assert(!UD->field_empty() && "sema created an empty transparent union"); 141992cb984SSergei Barannikov return UD->field_begin()->getType(); 142992cb984SSergei Barannikov } 143992cb984SSergei Barannikov } 144992cb984SSergei Barannikov return Ty; 145992cb984SSergei Barannikov } 146992cb984SSergei Barannikov 147992cb984SSergei Barannikov llvm::Value *CodeGen::emitRoundPointerUpToAlignment(CodeGenFunction &CGF, 148992cb984SSergei Barannikov llvm::Value *Ptr, 149992cb984SSergei Barannikov CharUnits Align) { 150992cb984SSergei Barannikov // OverflowArgArea = (OverflowArgArea + Align - 1) & -Align; 151992cb984SSergei Barannikov llvm::Value *RoundUp = CGF.Builder.CreateConstInBoundsGEP1_32( 152992cb984SSergei Barannikov CGF.Builder.getInt8Ty(), Ptr, Align.getQuantity() - 1); 153992cb984SSergei Barannikov return CGF.Builder.CreateIntrinsic( 15478eb2c2cSJon Chesterfield llvm::Intrinsic::ptrmask, {Ptr->getType(), CGF.IntPtrTy}, 155992cb984SSergei Barannikov {RoundUp, llvm::ConstantInt::get(CGF.IntPtrTy, -Align.getQuantity())}, 156992cb984SSergei Barannikov nullptr, Ptr->getName() + ".aligned"); 157992cb984SSergei Barannikov } 158992cb984SSergei Barannikov 159992cb984SSergei Barannikov Address 160992cb984SSergei Barannikov CodeGen::emitVoidPtrDirectVAArg(CodeGenFunction &CGF, Address VAListAddr, 161992cb984SSergei Barannikov llvm::Type *DirectTy, CharUnits DirectSize, 162992cb984SSergei Barannikov CharUnits DirectAlign, CharUnits SlotSize, 163992cb984SSergei Barannikov bool AllowHigherAlign, bool ForceRightAdjust) { 164992cb984SSergei Barannikov // Cast the element type to i8* if necessary. Some platforms define 165992cb984SSergei Barannikov // va_list as a struct containing an i8* instead of just an i8*. 166992cb984SSergei Barannikov if (VAListAddr.getElementType() != CGF.Int8PtrTy) 1675f32baf1SYoungsuk Kim VAListAddr = VAListAddr.withElementType(CGF.Int8PtrTy); 168992cb984SSergei Barannikov 169992cb984SSergei Barannikov llvm::Value *Ptr = CGF.Builder.CreateLoad(VAListAddr, "argp.cur"); 170992cb984SSergei Barannikov 171992cb984SSergei Barannikov // If the CC aligns values higher than the slot size, do so if needed. 172992cb984SSergei Barannikov Address Addr = Address::invalid(); 173992cb984SSergei Barannikov if (AllowHigherAlign && DirectAlign > SlotSize) { 174992cb984SSergei Barannikov Addr = Address(emitRoundPointerUpToAlignment(CGF, Ptr, DirectAlign), 175992cb984SSergei Barannikov CGF.Int8Ty, DirectAlign); 176992cb984SSergei Barannikov } else { 177992cb984SSergei Barannikov Addr = Address(Ptr, CGF.Int8Ty, SlotSize); 178992cb984SSergei Barannikov } 179992cb984SSergei Barannikov 180992cb984SSergei Barannikov // Advance the pointer past the argument, then store that back. 181992cb984SSergei Barannikov CharUnits FullDirectSize = DirectSize.alignTo(SlotSize); 182992cb984SSergei Barannikov Address NextPtr = 183992cb984SSergei Barannikov CGF.Builder.CreateConstInBoundsByteGEP(Addr, FullDirectSize, "argp.next"); 18484780af4SAkira Hatanaka CGF.Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr); 185992cb984SSergei Barannikov 186992cb984SSergei Barannikov // If the argument is smaller than a slot, and this is a big-endian 187992cb984SSergei Barannikov // target, the argument will be right-adjusted in its slot. 188992cb984SSergei Barannikov if (DirectSize < SlotSize && CGF.CGM.getDataLayout().isBigEndian() && 189992cb984SSergei Barannikov (!DirectTy->isStructTy() || ForceRightAdjust)) { 190992cb984SSergei Barannikov Addr = CGF.Builder.CreateConstInBoundsByteGEP(Addr, SlotSize - DirectSize); 191992cb984SSergei Barannikov } 192992cb984SSergei Barannikov 1935f32baf1SYoungsuk Kim return Addr.withElementType(DirectTy); 194992cb984SSergei Barannikov } 195992cb984SSergei Barannikov 1966d973b45SMariya Podchishchaeva RValue CodeGen::emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr, 197992cb984SSergei Barannikov QualType ValueTy, bool IsIndirect, 198992cb984SSergei Barannikov TypeInfoChars ValueInfo, 199992cb984SSergei Barannikov CharUnits SlotSizeAndAlign, 2006d973b45SMariya Podchishchaeva bool AllowHigherAlign, AggValueSlot Slot, 201992cb984SSergei Barannikov bool ForceRightAdjust) { 202992cb984SSergei Barannikov // The size and alignment of the value that was passed directly. 203992cb984SSergei Barannikov CharUnits DirectSize, DirectAlign; 204992cb984SSergei Barannikov if (IsIndirect) { 205992cb984SSergei Barannikov DirectSize = CGF.getPointerSize(); 206992cb984SSergei Barannikov DirectAlign = CGF.getPointerAlign(); 207992cb984SSergei Barannikov } else { 208992cb984SSergei Barannikov DirectSize = ValueInfo.Width; 209992cb984SSergei Barannikov DirectAlign = ValueInfo.Align; 210992cb984SSergei Barannikov } 211992cb984SSergei Barannikov 212992cb984SSergei Barannikov // Cast the address we've calculated to the right type. 213992cb984SSergei Barannikov llvm::Type *DirectTy = CGF.ConvertTypeForMem(ValueTy), *ElementTy = DirectTy; 214992cb984SSergei Barannikov if (IsIndirect) { 215992cb984SSergei Barannikov unsigned AllocaAS = CGF.CGM.getDataLayout().getAllocaAddrSpace(); 216992cb984SSergei Barannikov DirectTy = llvm::PointerType::get(CGF.getLLVMContext(), AllocaAS); 217992cb984SSergei Barannikov } 218992cb984SSergei Barannikov 219992cb984SSergei Barannikov Address Addr = emitVoidPtrDirectVAArg(CGF, VAListAddr, DirectTy, DirectSize, 220992cb984SSergei Barannikov DirectAlign, SlotSizeAndAlign, 221992cb984SSergei Barannikov AllowHigherAlign, ForceRightAdjust); 222992cb984SSergei Barannikov 223992cb984SSergei Barannikov if (IsIndirect) { 224992cb984SSergei Barannikov Addr = Address(CGF.Builder.CreateLoad(Addr), ElementTy, ValueInfo.Align); 225992cb984SSergei Barannikov } 226992cb984SSergei Barannikov 2276d973b45SMariya Podchishchaeva return CGF.EmitLoadOfAnyValue(CGF.MakeAddrLValue(Addr, ValueTy), Slot); 228992cb984SSergei Barannikov } 229992cb984SSergei Barannikov 230992cb984SSergei Barannikov Address CodeGen::emitMergePHI(CodeGenFunction &CGF, Address Addr1, 231992cb984SSergei Barannikov llvm::BasicBlock *Block1, Address Addr2, 232992cb984SSergei Barannikov llvm::BasicBlock *Block2, 233992cb984SSergei Barannikov const llvm::Twine &Name) { 234992cb984SSergei Barannikov assert(Addr1.getType() == Addr2.getType()); 235992cb984SSergei Barannikov llvm::PHINode *PHI = CGF.Builder.CreatePHI(Addr1.getType(), 2, Name); 23684780af4SAkira Hatanaka PHI->addIncoming(Addr1.emitRawPointer(CGF), Block1); 23784780af4SAkira Hatanaka PHI->addIncoming(Addr2.emitRawPointer(CGF), Block2); 238992cb984SSergei Barannikov CharUnits Align = std::min(Addr1.getAlignment(), Addr2.getAlignment()); 239992cb984SSergei Barannikov return Address(PHI, Addr1.getElementType(), Align); 240992cb984SSergei Barannikov } 241992cb984SSergei Barannikov 242992cb984SSergei Barannikov bool CodeGen::isEmptyField(ASTContext &Context, const FieldDecl *FD, 243e3c57fddSAlex Bradbury bool AllowArrays, bool AsIfNoUniqueAddr) { 2443d56ea05STimm Baeder if (FD->isUnnamedBitField()) 245992cb984SSergei Barannikov return true; 246992cb984SSergei Barannikov 247992cb984SSergei Barannikov QualType FT = FD->getType(); 248992cb984SSergei Barannikov 249992cb984SSergei Barannikov // Constant arrays of empty records count as empty, strip them off. 250992cb984SSergei Barannikov // Constant arrays of zero length always count as empty. 251992cb984SSergei Barannikov bool WasArray = false; 252992cb984SSergei Barannikov if (AllowArrays) 253992cb984SSergei Barannikov while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) { 25428ddbd4aSChris B if (AT->isZeroSize()) 255992cb984SSergei Barannikov return true; 256992cb984SSergei Barannikov FT = AT->getElementType(); 257992cb984SSergei Barannikov // The [[no_unique_address]] special case below does not apply to 258992cb984SSergei Barannikov // arrays of C++ empty records, so we need to remember this fact. 259992cb984SSergei Barannikov WasArray = true; 260992cb984SSergei Barannikov } 261992cb984SSergei Barannikov 262992cb984SSergei Barannikov const RecordType *RT = FT->getAs<RecordType>(); 263992cb984SSergei Barannikov if (!RT) 264992cb984SSergei Barannikov return false; 265992cb984SSergei Barannikov 266992cb984SSergei Barannikov // C++ record fields are never empty, at least in the Itanium ABI. 267992cb984SSergei Barannikov // 268992cb984SSergei Barannikov // FIXME: We should use a predicate for whether this behavior is true in the 269992cb984SSergei Barannikov // current ABI. 270992cb984SSergei Barannikov // 271992cb984SSergei Barannikov // The exception to the above rule are fields marked with the 272992cb984SSergei Barannikov // [[no_unique_address]] attribute (since C++20). Those do count as empty 273992cb984SSergei Barannikov // according to the Itanium ABI. The exception applies only to records, 274992cb984SSergei Barannikov // not arrays of records, so we must also check whether we stripped off an 275992cb984SSergei Barannikov // array type above. 276992cb984SSergei Barannikov if (isa<CXXRecordDecl>(RT->getDecl()) && 277e3c57fddSAlex Bradbury (WasArray || (!AsIfNoUniqueAddr && !FD->hasAttr<NoUniqueAddressAttr>()))) 278992cb984SSergei Barannikov return false; 279992cb984SSergei Barannikov 280e3c57fddSAlex Bradbury return isEmptyRecord(Context, FT, AllowArrays, AsIfNoUniqueAddr); 281992cb984SSergei Barannikov } 282992cb984SSergei Barannikov 283e3c57fddSAlex Bradbury bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays, 284e3c57fddSAlex Bradbury bool AsIfNoUniqueAddr) { 285992cb984SSergei Barannikov const RecordType *RT = T->getAs<RecordType>(); 286992cb984SSergei Barannikov if (!RT) 287992cb984SSergei Barannikov return false; 288992cb984SSergei Barannikov const RecordDecl *RD = RT->getDecl(); 289992cb984SSergei Barannikov if (RD->hasFlexibleArrayMember()) 290992cb984SSergei Barannikov return false; 291992cb984SSergei Barannikov 292992cb984SSergei Barannikov // If this is a C++ record, check the bases first. 293992cb984SSergei Barannikov if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) 294992cb984SSergei Barannikov for (const auto &I : CXXRD->bases()) 295e3c57fddSAlex Bradbury if (!isEmptyRecord(Context, I.getType(), true, AsIfNoUniqueAddr)) 296992cb984SSergei Barannikov return false; 297992cb984SSergei Barannikov 298992cb984SSergei Barannikov for (const auto *I : RD->fields()) 299e3c57fddSAlex Bradbury if (!isEmptyField(Context, I, AllowArrays, AsIfNoUniqueAddr)) 300992cb984SSergei Barannikov return false; 301992cb984SSergei Barannikov return true; 302992cb984SSergei Barannikov } 303992cb984SSergei Barannikov 3044497ec29SMichael Buch bool CodeGen::isEmptyFieldForLayout(const ASTContext &Context, 3054497ec29SMichael Buch const FieldDecl *FD) { 306*cfe26358STimm Baeder if (FD->isZeroLengthBitField()) 3074497ec29SMichael Buch return true; 3084497ec29SMichael Buch 3094497ec29SMichael Buch if (FD->isUnnamedBitField()) 3104497ec29SMichael Buch return false; 3114497ec29SMichael Buch 3124497ec29SMichael Buch return isEmptyRecordForLayout(Context, FD->getType()); 3134497ec29SMichael Buch } 3144497ec29SMichael Buch 3154497ec29SMichael Buch bool CodeGen::isEmptyRecordForLayout(const ASTContext &Context, QualType T) { 3164497ec29SMichael Buch const RecordType *RT = T->getAs<RecordType>(); 3174497ec29SMichael Buch if (!RT) 3184497ec29SMichael Buch return false; 3194497ec29SMichael Buch 3204497ec29SMichael Buch const RecordDecl *RD = RT->getDecl(); 3214497ec29SMichael Buch 3224497ec29SMichael Buch // If this is a C++ record, check the bases first. 3234497ec29SMichael Buch if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) { 3244497ec29SMichael Buch if (CXXRD->isDynamicClass()) 3254497ec29SMichael Buch return false; 3264497ec29SMichael Buch 3274497ec29SMichael Buch for (const auto &I : CXXRD->bases()) 3284497ec29SMichael Buch if (!isEmptyRecordForLayout(Context, I.getType())) 3294497ec29SMichael Buch return false; 3304497ec29SMichael Buch } 3314497ec29SMichael Buch 3324497ec29SMichael Buch for (const auto *I : RD->fields()) 3334497ec29SMichael Buch if (!isEmptyFieldForLayout(Context, I)) 3344497ec29SMichael Buch return false; 3354497ec29SMichael Buch 3364497ec29SMichael Buch return true; 3374497ec29SMichael Buch } 3384497ec29SMichael Buch 339992cb984SSergei Barannikov const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) { 340992cb984SSergei Barannikov const RecordType *RT = T->getAs<RecordType>(); 341992cb984SSergei Barannikov if (!RT) 342992cb984SSergei Barannikov return nullptr; 343992cb984SSergei Barannikov 344992cb984SSergei Barannikov const RecordDecl *RD = RT->getDecl(); 345992cb984SSergei Barannikov if (RD->hasFlexibleArrayMember()) 346992cb984SSergei Barannikov return nullptr; 347992cb984SSergei Barannikov 348992cb984SSergei Barannikov const Type *Found = nullptr; 349992cb984SSergei Barannikov 350992cb984SSergei Barannikov // If this is a C++ record, check the bases first. 351992cb984SSergei Barannikov if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) { 352992cb984SSergei Barannikov for (const auto &I : CXXRD->bases()) { 353992cb984SSergei Barannikov // Ignore empty records. 354992cb984SSergei Barannikov if (isEmptyRecord(Context, I.getType(), true)) 355992cb984SSergei Barannikov continue; 356992cb984SSergei Barannikov 357992cb984SSergei Barannikov // If we already found an element then this isn't a single-element struct. 358992cb984SSergei Barannikov if (Found) 359992cb984SSergei Barannikov return nullptr; 360992cb984SSergei Barannikov 361992cb984SSergei Barannikov // If this is non-empty and not a single element struct, the composite 362992cb984SSergei Barannikov // cannot be a single element struct. 363992cb984SSergei Barannikov Found = isSingleElementStruct(I.getType(), Context); 364992cb984SSergei Barannikov if (!Found) 365992cb984SSergei Barannikov return nullptr; 366992cb984SSergei Barannikov } 367992cb984SSergei Barannikov } 368992cb984SSergei Barannikov 369992cb984SSergei Barannikov // Check for single element. 370992cb984SSergei Barannikov for (const auto *FD : RD->fields()) { 371992cb984SSergei Barannikov QualType FT = FD->getType(); 372992cb984SSergei Barannikov 373992cb984SSergei Barannikov // Ignore empty fields. 374992cb984SSergei Barannikov if (isEmptyField(Context, FD, true)) 375992cb984SSergei Barannikov continue; 376992cb984SSergei Barannikov 377992cb984SSergei Barannikov // If we already found an element then this isn't a single-element 378992cb984SSergei Barannikov // struct. 379992cb984SSergei Barannikov if (Found) 380992cb984SSergei Barannikov return nullptr; 381992cb984SSergei Barannikov 382992cb984SSergei Barannikov // Treat single element arrays as the element. 383992cb984SSergei Barannikov while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) { 38428ddbd4aSChris B if (AT->getZExtSize() != 1) 385992cb984SSergei Barannikov break; 386992cb984SSergei Barannikov FT = AT->getElementType(); 387992cb984SSergei Barannikov } 388992cb984SSergei Barannikov 389992cb984SSergei Barannikov if (!isAggregateTypeForABI(FT)) { 390992cb984SSergei Barannikov Found = FT.getTypePtr(); 391992cb984SSergei Barannikov } else { 392992cb984SSergei Barannikov Found = isSingleElementStruct(FT, Context); 393992cb984SSergei Barannikov if (!Found) 394992cb984SSergei Barannikov return nullptr; 395992cb984SSergei Barannikov } 396992cb984SSergei Barannikov } 397992cb984SSergei Barannikov 398992cb984SSergei Barannikov // We don't consider a struct a single-element struct if it has 399992cb984SSergei Barannikov // padding beyond the element type. 400992cb984SSergei Barannikov if (Found && Context.getTypeSize(Found) != Context.getTypeSize(T)) 401992cb984SSergei Barannikov return nullptr; 402992cb984SSergei Barannikov 403992cb984SSergei Barannikov return Found; 404992cb984SSergei Barannikov } 405992cb984SSergei Barannikov 406992cb984SSergei Barannikov Address CodeGen::EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr, 407992cb984SSergei Barannikov QualType Ty, const ABIArgInfo &AI) { 408992cb984SSergei Barannikov // This default implementation defers to the llvm backend's va_arg 409992cb984SSergei Barannikov // instruction. It can handle only passing arguments directly 410992cb984SSergei Barannikov // (typically only handled in the backend for primitive types), or 411992cb984SSergei Barannikov // aggregates passed indirectly by pointer (NOTE: if the "byval" 412992cb984SSergei Barannikov // flag has ABI impact in the callee, this implementation cannot 413992cb984SSergei Barannikov // work.) 414992cb984SSergei Barannikov 415992cb984SSergei Barannikov // Only a few cases are covered here at the moment -- those needed 416992cb984SSergei Barannikov // by the default abi. 417992cb984SSergei Barannikov llvm::Value *Val; 418992cb984SSergei Barannikov 419992cb984SSergei Barannikov if (AI.isIndirect()) { 420992cb984SSergei Barannikov assert(!AI.getPaddingType() && 421992cb984SSergei Barannikov "Unexpected PaddingType seen in arginfo in generic VAArg emitter!"); 422992cb984SSergei Barannikov assert( 423992cb984SSergei Barannikov !AI.getIndirectRealign() && 424992cb984SSergei Barannikov "Unexpected IndirectRealign seen in arginfo in generic VAArg emitter!"); 425992cb984SSergei Barannikov 426992cb984SSergei Barannikov auto TyInfo = CGF.getContext().getTypeInfoInChars(Ty); 427992cb984SSergei Barannikov CharUnits TyAlignForABI = TyInfo.Align; 428992cb984SSergei Barannikov 429992cb984SSergei Barannikov llvm::Type *ElementTy = CGF.ConvertTypeForMem(Ty); 430992cb984SSergei Barannikov llvm::Type *BaseTy = llvm::PointerType::getUnqual(ElementTy); 431992cb984SSergei Barannikov llvm::Value *Addr = 43284780af4SAkira Hatanaka CGF.Builder.CreateVAArg(VAListAddr.emitRawPointer(CGF), BaseTy); 433992cb984SSergei Barannikov return Address(Addr, ElementTy, TyAlignForABI); 434992cb984SSergei Barannikov } else { 435992cb984SSergei Barannikov assert((AI.isDirect() || AI.isExtend()) && 436992cb984SSergei Barannikov "Unexpected ArgInfo Kind in generic VAArg emitter!"); 437992cb984SSergei Barannikov 438992cb984SSergei Barannikov assert(!AI.getInReg() && 439992cb984SSergei Barannikov "Unexpected InReg seen in arginfo in generic VAArg emitter!"); 440992cb984SSergei Barannikov assert(!AI.getPaddingType() && 441992cb984SSergei Barannikov "Unexpected PaddingType seen in arginfo in generic VAArg emitter!"); 442992cb984SSergei Barannikov assert(!AI.getDirectOffset() && 443992cb984SSergei Barannikov "Unexpected DirectOffset seen in arginfo in generic VAArg emitter!"); 444992cb984SSergei Barannikov assert(!AI.getCoerceToType() && 445992cb984SSergei Barannikov "Unexpected CoerceToType seen in arginfo in generic VAArg emitter!"); 446992cb984SSergei Barannikov 447992cb984SSergei Barannikov Address Temp = CGF.CreateMemTemp(Ty, "varet"); 44884780af4SAkira Hatanaka Val = CGF.Builder.CreateVAArg(VAListAddr.emitRawPointer(CGF), 449992cb984SSergei Barannikov CGF.ConvertTypeForMem(Ty)); 450992cb984SSergei Barannikov CGF.Builder.CreateStore(Val, Temp); 451992cb984SSergei Barannikov return Temp; 452992cb984SSergei Barannikov } 453992cb984SSergei Barannikov } 454992cb984SSergei Barannikov 455992cb984SSergei Barannikov bool CodeGen::isSIMDVectorType(ASTContext &Context, QualType Ty) { 456992cb984SSergei Barannikov return Ty->getAs<VectorType>() && Context.getTypeSize(Ty) == 128; 457992cb984SSergei Barannikov } 458992cb984SSergei Barannikov 459992cb984SSergei Barannikov bool CodeGen::isRecordWithSIMDVectorType(ASTContext &Context, QualType Ty) { 460992cb984SSergei Barannikov const RecordType *RT = Ty->getAs<RecordType>(); 461992cb984SSergei Barannikov if (!RT) 462992cb984SSergei Barannikov return false; 463992cb984SSergei Barannikov const RecordDecl *RD = RT->getDecl(); 464992cb984SSergei Barannikov 465992cb984SSergei Barannikov // If this is a C++ record, check the bases first. 466992cb984SSergei Barannikov if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) 467992cb984SSergei Barannikov for (const auto &I : CXXRD->bases()) 468992cb984SSergei Barannikov if (!isRecordWithSIMDVectorType(Context, I.getType())) 469992cb984SSergei Barannikov return false; 470992cb984SSergei Barannikov 471992cb984SSergei Barannikov for (const auto *i : RD->fields()) { 472992cb984SSergei Barannikov QualType FT = i->getType(); 473992cb984SSergei Barannikov 474992cb984SSergei Barannikov if (isSIMDVectorType(Context, FT)) 475992cb984SSergei Barannikov return true; 476992cb984SSergei Barannikov 477992cb984SSergei Barannikov if (isRecordWithSIMDVectorType(Context, FT)) 478992cb984SSergei Barannikov return true; 479992cb984SSergei Barannikov } 480992cb984SSergei Barannikov 481992cb984SSergei Barannikov return false; 482992cb984SSergei Barannikov } 483