xref: /freebsd-src/contrib/llvm-project/clang/lib/CodeGen/ABIInfoImpl.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1*06c3fb27SDimitry Andric //===- ABIInfoImpl.cpp ----------------------------------------------------===//
2*06c3fb27SDimitry Andric //
3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*06c3fb27SDimitry Andric //
7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
8*06c3fb27SDimitry Andric 
9*06c3fb27SDimitry Andric #include "ABIInfoImpl.h"
10*06c3fb27SDimitry Andric 
11*06c3fb27SDimitry Andric using namespace clang;
12*06c3fb27SDimitry Andric using namespace clang::CodeGen;
13*06c3fb27SDimitry Andric 
14*06c3fb27SDimitry Andric // Pin the vtable to this file.
15*06c3fb27SDimitry Andric DefaultABIInfo::~DefaultABIInfo() = default;
16*06c3fb27SDimitry Andric 
17*06c3fb27SDimitry Andric ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const {
18*06c3fb27SDimitry Andric   Ty = useFirstFieldIfTransparentUnion(Ty);
19*06c3fb27SDimitry Andric 
20*06c3fb27SDimitry Andric   if (isAggregateTypeForABI(Ty)) {
21*06c3fb27SDimitry Andric     // Records with non-trivial destructors/copy-constructors should not be
22*06c3fb27SDimitry Andric     // passed by value.
23*06c3fb27SDimitry Andric     if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
24*06c3fb27SDimitry Andric       return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
25*06c3fb27SDimitry Andric 
26*06c3fb27SDimitry Andric     return getNaturalAlignIndirect(Ty);
27*06c3fb27SDimitry Andric   }
28*06c3fb27SDimitry Andric 
29*06c3fb27SDimitry Andric   // Treat an enum type as its underlying type.
30*06c3fb27SDimitry Andric   if (const EnumType *EnumTy = Ty->getAs<EnumType>())
31*06c3fb27SDimitry Andric     Ty = EnumTy->getDecl()->getIntegerType();
32*06c3fb27SDimitry Andric 
33*06c3fb27SDimitry Andric   ASTContext &Context = getContext();
34*06c3fb27SDimitry Andric   if (const auto *EIT = Ty->getAs<BitIntType>())
35*06c3fb27SDimitry Andric     if (EIT->getNumBits() >
36*06c3fb27SDimitry Andric         Context.getTypeSize(Context.getTargetInfo().hasInt128Type()
37*06c3fb27SDimitry Andric                                 ? Context.Int128Ty
38*06c3fb27SDimitry Andric                                 : Context.LongLongTy))
39*06c3fb27SDimitry Andric       return getNaturalAlignIndirect(Ty);
40*06c3fb27SDimitry Andric 
41*06c3fb27SDimitry Andric   return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty)
42*06c3fb27SDimitry Andric                                             : ABIArgInfo::getDirect());
43*06c3fb27SDimitry Andric }
44*06c3fb27SDimitry Andric 
45*06c3fb27SDimitry Andric ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const {
46*06c3fb27SDimitry Andric   if (RetTy->isVoidType())
47*06c3fb27SDimitry Andric     return ABIArgInfo::getIgnore();
48*06c3fb27SDimitry Andric 
49*06c3fb27SDimitry Andric   if (isAggregateTypeForABI(RetTy))
50*06c3fb27SDimitry Andric     return getNaturalAlignIndirect(RetTy);
51*06c3fb27SDimitry Andric 
52*06c3fb27SDimitry Andric   // Treat an enum type as its underlying type.
53*06c3fb27SDimitry Andric   if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
54*06c3fb27SDimitry Andric     RetTy = EnumTy->getDecl()->getIntegerType();
55*06c3fb27SDimitry Andric 
56*06c3fb27SDimitry Andric   if (const auto *EIT = RetTy->getAs<BitIntType>())
57*06c3fb27SDimitry Andric     if (EIT->getNumBits() >
58*06c3fb27SDimitry Andric         getContext().getTypeSize(getContext().getTargetInfo().hasInt128Type()
59*06c3fb27SDimitry Andric                                      ? getContext().Int128Ty
60*06c3fb27SDimitry Andric                                      : getContext().LongLongTy))
61*06c3fb27SDimitry Andric       return getNaturalAlignIndirect(RetTy);
62*06c3fb27SDimitry Andric 
63*06c3fb27SDimitry Andric   return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy)
64*06c3fb27SDimitry Andric                                                : ABIArgInfo::getDirect());
65*06c3fb27SDimitry Andric }
66*06c3fb27SDimitry Andric 
67*06c3fb27SDimitry Andric void DefaultABIInfo::computeInfo(CGFunctionInfo &FI) const {
68*06c3fb27SDimitry Andric   if (!getCXXABI().classifyReturnType(FI))
69*06c3fb27SDimitry Andric     FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
70*06c3fb27SDimitry Andric   for (auto &I : FI.arguments())
71*06c3fb27SDimitry Andric     I.info = classifyArgumentType(I.type);
72*06c3fb27SDimitry Andric }
73*06c3fb27SDimitry Andric 
74*06c3fb27SDimitry Andric Address DefaultABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
75*06c3fb27SDimitry Andric                                   QualType Ty) const {
76*06c3fb27SDimitry Andric   return EmitVAArgInstr(CGF, VAListAddr, Ty, classifyArgumentType(Ty));
77*06c3fb27SDimitry Andric }
78*06c3fb27SDimitry Andric 
79*06c3fb27SDimitry Andric ABIArgInfo CodeGen::coerceToIntArray(QualType Ty, ASTContext &Context,
80*06c3fb27SDimitry Andric                                      llvm::LLVMContext &LLVMContext) {
81*06c3fb27SDimitry Andric   // Alignment and Size are measured in bits.
82*06c3fb27SDimitry Andric   const uint64_t Size = Context.getTypeSize(Ty);
83*06c3fb27SDimitry Andric   const uint64_t Alignment = Context.getTypeAlign(Ty);
84*06c3fb27SDimitry Andric   llvm::Type *IntType = llvm::Type::getIntNTy(LLVMContext, Alignment);
85*06c3fb27SDimitry Andric   const uint64_t NumElements = (Size + Alignment - 1) / Alignment;
86*06c3fb27SDimitry Andric   return ABIArgInfo::getDirect(llvm::ArrayType::get(IntType, NumElements));
87*06c3fb27SDimitry Andric }
88*06c3fb27SDimitry Andric 
89*06c3fb27SDimitry Andric void CodeGen::AssignToArrayRange(CodeGen::CGBuilderTy &Builder,
90*06c3fb27SDimitry Andric                                  llvm::Value *Array, llvm::Value *Value,
91*06c3fb27SDimitry Andric                                  unsigned FirstIndex, unsigned LastIndex) {
92*06c3fb27SDimitry Andric   // Alternatively, we could emit this as a loop in the source.
93*06c3fb27SDimitry Andric   for (unsigned I = FirstIndex; I <= LastIndex; ++I) {
94*06c3fb27SDimitry Andric     llvm::Value *Cell =
95*06c3fb27SDimitry Andric         Builder.CreateConstInBoundsGEP1_32(Builder.getInt8Ty(), Array, I);
96*06c3fb27SDimitry Andric     Builder.CreateAlignedStore(Value, Cell, CharUnits::One());
97*06c3fb27SDimitry Andric   }
98*06c3fb27SDimitry Andric }
99*06c3fb27SDimitry Andric 
100*06c3fb27SDimitry Andric bool CodeGen::isAggregateTypeForABI(QualType T) {
101*06c3fb27SDimitry Andric   return !CodeGenFunction::hasScalarEvaluationKind(T) ||
102*06c3fb27SDimitry Andric          T->isMemberFunctionPointerType();
103*06c3fb27SDimitry Andric }
104*06c3fb27SDimitry Andric 
105*06c3fb27SDimitry Andric llvm::Type *CodeGen::getVAListElementType(CodeGenFunction &CGF) {
106*06c3fb27SDimitry Andric   return CGF.ConvertTypeForMem(
107*06c3fb27SDimitry Andric       CGF.getContext().getBuiltinVaListType()->getPointeeType());
108*06c3fb27SDimitry Andric }
109*06c3fb27SDimitry Andric 
110*06c3fb27SDimitry Andric CGCXXABI::RecordArgABI CodeGen::getRecordArgABI(const RecordType *RT,
111*06c3fb27SDimitry Andric                                                 CGCXXABI &CXXABI) {
112*06c3fb27SDimitry Andric   const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
113*06c3fb27SDimitry Andric   if (!RD) {
114*06c3fb27SDimitry Andric     if (!RT->getDecl()->canPassInRegisters())
115*06c3fb27SDimitry Andric       return CGCXXABI::RAA_Indirect;
116*06c3fb27SDimitry Andric     return CGCXXABI::RAA_Default;
117*06c3fb27SDimitry Andric   }
118*06c3fb27SDimitry Andric   return CXXABI.getRecordArgABI(RD);
119*06c3fb27SDimitry Andric }
120*06c3fb27SDimitry Andric 
121*06c3fb27SDimitry Andric CGCXXABI::RecordArgABI CodeGen::getRecordArgABI(QualType T, CGCXXABI &CXXABI) {
122*06c3fb27SDimitry Andric   const RecordType *RT = T->getAs<RecordType>();
123*06c3fb27SDimitry Andric   if (!RT)
124*06c3fb27SDimitry Andric     return CGCXXABI::RAA_Default;
125*06c3fb27SDimitry Andric   return getRecordArgABI(RT, CXXABI);
126*06c3fb27SDimitry Andric }
127*06c3fb27SDimitry Andric 
128*06c3fb27SDimitry Andric bool CodeGen::classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI,
129*06c3fb27SDimitry Andric                                  const ABIInfo &Info) {
130*06c3fb27SDimitry Andric   QualType Ty = FI.getReturnType();
131*06c3fb27SDimitry Andric 
132*06c3fb27SDimitry Andric   if (const auto *RT = Ty->getAs<RecordType>())
133*06c3fb27SDimitry Andric     if (!isa<CXXRecordDecl>(RT->getDecl()) &&
134*06c3fb27SDimitry Andric         !RT->getDecl()->canPassInRegisters()) {
135*06c3fb27SDimitry Andric       FI.getReturnInfo() = Info.getNaturalAlignIndirect(Ty);
136*06c3fb27SDimitry Andric       return true;
137*06c3fb27SDimitry Andric     }
138*06c3fb27SDimitry Andric 
139*06c3fb27SDimitry Andric   return CXXABI.classifyReturnType(FI);
140*06c3fb27SDimitry Andric }
141*06c3fb27SDimitry Andric 
142*06c3fb27SDimitry Andric QualType CodeGen::useFirstFieldIfTransparentUnion(QualType Ty) {
143*06c3fb27SDimitry Andric   if (const RecordType *UT = Ty->getAsUnionType()) {
144*06c3fb27SDimitry Andric     const RecordDecl *UD = UT->getDecl();
145*06c3fb27SDimitry Andric     if (UD->hasAttr<TransparentUnionAttr>()) {
146*06c3fb27SDimitry Andric       assert(!UD->field_empty() && "sema created an empty transparent union");
147*06c3fb27SDimitry Andric       return UD->field_begin()->getType();
148*06c3fb27SDimitry Andric     }
149*06c3fb27SDimitry Andric   }
150*06c3fb27SDimitry Andric   return Ty;
151*06c3fb27SDimitry Andric }
152*06c3fb27SDimitry Andric 
153*06c3fb27SDimitry Andric llvm::Value *CodeGen::emitRoundPointerUpToAlignment(CodeGenFunction &CGF,
154*06c3fb27SDimitry Andric                                                     llvm::Value *Ptr,
155*06c3fb27SDimitry Andric                                                     CharUnits Align) {
156*06c3fb27SDimitry Andric   // OverflowArgArea = (OverflowArgArea + Align - 1) & -Align;
157*06c3fb27SDimitry Andric   llvm::Value *RoundUp = CGF.Builder.CreateConstInBoundsGEP1_32(
158*06c3fb27SDimitry Andric       CGF.Builder.getInt8Ty(), Ptr, Align.getQuantity() - 1);
159*06c3fb27SDimitry Andric   return CGF.Builder.CreateIntrinsic(
160*06c3fb27SDimitry Andric       llvm::Intrinsic::ptrmask, {CGF.AllocaInt8PtrTy, CGF.IntPtrTy},
161*06c3fb27SDimitry Andric       {RoundUp, llvm::ConstantInt::get(CGF.IntPtrTy, -Align.getQuantity())},
162*06c3fb27SDimitry Andric       nullptr, Ptr->getName() + ".aligned");
163*06c3fb27SDimitry Andric }
164*06c3fb27SDimitry Andric 
165*06c3fb27SDimitry Andric Address
166*06c3fb27SDimitry Andric CodeGen::emitVoidPtrDirectVAArg(CodeGenFunction &CGF, Address VAListAddr,
167*06c3fb27SDimitry Andric                                 llvm::Type *DirectTy, CharUnits DirectSize,
168*06c3fb27SDimitry Andric                                 CharUnits DirectAlign, CharUnits SlotSize,
169*06c3fb27SDimitry Andric                                 bool AllowHigherAlign, bool ForceRightAdjust) {
170*06c3fb27SDimitry Andric   // Cast the element type to i8* if necessary.  Some platforms define
171*06c3fb27SDimitry Andric   // va_list as a struct containing an i8* instead of just an i8*.
172*06c3fb27SDimitry Andric   if (VAListAddr.getElementType() != CGF.Int8PtrTy)
173*06c3fb27SDimitry Andric     VAListAddr = VAListAddr.withElementType(CGF.Int8PtrTy);
174*06c3fb27SDimitry Andric 
175*06c3fb27SDimitry Andric   llvm::Value *Ptr = CGF.Builder.CreateLoad(VAListAddr, "argp.cur");
176*06c3fb27SDimitry Andric 
177*06c3fb27SDimitry Andric   // If the CC aligns values higher than the slot size, do so if needed.
178*06c3fb27SDimitry Andric   Address Addr = Address::invalid();
179*06c3fb27SDimitry Andric   if (AllowHigherAlign && DirectAlign > SlotSize) {
180*06c3fb27SDimitry Andric     Addr = Address(emitRoundPointerUpToAlignment(CGF, Ptr, DirectAlign),
181*06c3fb27SDimitry Andric                    CGF.Int8Ty, DirectAlign);
182*06c3fb27SDimitry Andric   } else {
183*06c3fb27SDimitry Andric     Addr = Address(Ptr, CGF.Int8Ty, SlotSize);
184*06c3fb27SDimitry Andric   }
185*06c3fb27SDimitry Andric 
186*06c3fb27SDimitry Andric   // Advance the pointer past the argument, then store that back.
187*06c3fb27SDimitry Andric   CharUnits FullDirectSize = DirectSize.alignTo(SlotSize);
188*06c3fb27SDimitry Andric   Address NextPtr =
189*06c3fb27SDimitry Andric       CGF.Builder.CreateConstInBoundsByteGEP(Addr, FullDirectSize, "argp.next");
190*06c3fb27SDimitry Andric   CGF.Builder.CreateStore(NextPtr.getPointer(), VAListAddr);
191*06c3fb27SDimitry Andric 
192*06c3fb27SDimitry Andric   // If the argument is smaller than a slot, and this is a big-endian
193*06c3fb27SDimitry Andric   // target, the argument will be right-adjusted in its slot.
194*06c3fb27SDimitry Andric   if (DirectSize < SlotSize && CGF.CGM.getDataLayout().isBigEndian() &&
195*06c3fb27SDimitry Andric       (!DirectTy->isStructTy() || ForceRightAdjust)) {
196*06c3fb27SDimitry Andric     Addr = CGF.Builder.CreateConstInBoundsByteGEP(Addr, SlotSize - DirectSize);
197*06c3fb27SDimitry Andric   }
198*06c3fb27SDimitry Andric 
199*06c3fb27SDimitry Andric   return Addr.withElementType(DirectTy);
200*06c3fb27SDimitry Andric }
201*06c3fb27SDimitry Andric 
202*06c3fb27SDimitry Andric Address CodeGen::emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr,
203*06c3fb27SDimitry Andric                                   QualType ValueTy, bool IsIndirect,
204*06c3fb27SDimitry Andric                                   TypeInfoChars ValueInfo,
205*06c3fb27SDimitry Andric                                   CharUnits SlotSizeAndAlign,
206*06c3fb27SDimitry Andric                                   bool AllowHigherAlign,
207*06c3fb27SDimitry Andric                                   bool ForceRightAdjust) {
208*06c3fb27SDimitry Andric   // The size and alignment of the value that was passed directly.
209*06c3fb27SDimitry Andric   CharUnits DirectSize, DirectAlign;
210*06c3fb27SDimitry Andric   if (IsIndirect) {
211*06c3fb27SDimitry Andric     DirectSize = CGF.getPointerSize();
212*06c3fb27SDimitry Andric     DirectAlign = CGF.getPointerAlign();
213*06c3fb27SDimitry Andric   } else {
214*06c3fb27SDimitry Andric     DirectSize = ValueInfo.Width;
215*06c3fb27SDimitry Andric     DirectAlign = ValueInfo.Align;
216*06c3fb27SDimitry Andric   }
217*06c3fb27SDimitry Andric 
218*06c3fb27SDimitry Andric   // Cast the address we've calculated to the right type.
219*06c3fb27SDimitry Andric   llvm::Type *DirectTy = CGF.ConvertTypeForMem(ValueTy), *ElementTy = DirectTy;
220*06c3fb27SDimitry Andric   if (IsIndirect) {
221*06c3fb27SDimitry Andric     unsigned AllocaAS = CGF.CGM.getDataLayout().getAllocaAddrSpace();
222*06c3fb27SDimitry Andric     DirectTy = llvm::PointerType::get(CGF.getLLVMContext(), AllocaAS);
223*06c3fb27SDimitry Andric   }
224*06c3fb27SDimitry Andric 
225*06c3fb27SDimitry Andric   Address Addr = emitVoidPtrDirectVAArg(CGF, VAListAddr, DirectTy, DirectSize,
226*06c3fb27SDimitry Andric                                         DirectAlign, SlotSizeAndAlign,
227*06c3fb27SDimitry Andric                                         AllowHigherAlign, ForceRightAdjust);
228*06c3fb27SDimitry Andric 
229*06c3fb27SDimitry Andric   if (IsIndirect) {
230*06c3fb27SDimitry Andric     Addr = Address(CGF.Builder.CreateLoad(Addr), ElementTy, ValueInfo.Align);
231*06c3fb27SDimitry Andric   }
232*06c3fb27SDimitry Andric 
233*06c3fb27SDimitry Andric   return Addr;
234*06c3fb27SDimitry Andric }
235*06c3fb27SDimitry Andric 
236*06c3fb27SDimitry Andric Address CodeGen::emitMergePHI(CodeGenFunction &CGF, Address Addr1,
237*06c3fb27SDimitry Andric                               llvm::BasicBlock *Block1, Address Addr2,
238*06c3fb27SDimitry Andric                               llvm::BasicBlock *Block2,
239*06c3fb27SDimitry Andric                               const llvm::Twine &Name) {
240*06c3fb27SDimitry Andric   assert(Addr1.getType() == Addr2.getType());
241*06c3fb27SDimitry Andric   llvm::PHINode *PHI = CGF.Builder.CreatePHI(Addr1.getType(), 2, Name);
242*06c3fb27SDimitry Andric   PHI->addIncoming(Addr1.getPointer(), Block1);
243*06c3fb27SDimitry Andric   PHI->addIncoming(Addr2.getPointer(), Block2);
244*06c3fb27SDimitry Andric   CharUnits Align = std::min(Addr1.getAlignment(), Addr2.getAlignment());
245*06c3fb27SDimitry Andric   return Address(PHI, Addr1.getElementType(), Align);
246*06c3fb27SDimitry Andric }
247*06c3fb27SDimitry Andric 
248*06c3fb27SDimitry Andric bool CodeGen::isEmptyField(ASTContext &Context, const FieldDecl *FD,
249*06c3fb27SDimitry Andric                            bool AllowArrays) {
250*06c3fb27SDimitry Andric   if (FD->isUnnamedBitfield())
251*06c3fb27SDimitry Andric     return true;
252*06c3fb27SDimitry Andric 
253*06c3fb27SDimitry Andric   QualType FT = FD->getType();
254*06c3fb27SDimitry Andric 
255*06c3fb27SDimitry Andric   // Constant arrays of empty records count as empty, strip them off.
256*06c3fb27SDimitry Andric   // Constant arrays of zero length always count as empty.
257*06c3fb27SDimitry Andric   bool WasArray = false;
258*06c3fb27SDimitry Andric   if (AllowArrays)
259*06c3fb27SDimitry Andric     while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) {
260*06c3fb27SDimitry Andric       if (AT->getSize() == 0)
261*06c3fb27SDimitry Andric         return true;
262*06c3fb27SDimitry Andric       FT = AT->getElementType();
263*06c3fb27SDimitry Andric       // The [[no_unique_address]] special case below does not apply to
264*06c3fb27SDimitry Andric       // arrays of C++ empty records, so we need to remember this fact.
265*06c3fb27SDimitry Andric       WasArray = true;
266*06c3fb27SDimitry Andric     }
267*06c3fb27SDimitry Andric 
268*06c3fb27SDimitry Andric   const RecordType *RT = FT->getAs<RecordType>();
269*06c3fb27SDimitry Andric   if (!RT)
270*06c3fb27SDimitry Andric     return false;
271*06c3fb27SDimitry Andric 
272*06c3fb27SDimitry Andric   // C++ record fields are never empty, at least in the Itanium ABI.
273*06c3fb27SDimitry Andric   //
274*06c3fb27SDimitry Andric   // FIXME: We should use a predicate for whether this behavior is true in the
275*06c3fb27SDimitry Andric   // current ABI.
276*06c3fb27SDimitry Andric   //
277*06c3fb27SDimitry Andric   // The exception to the above rule are fields marked with the
278*06c3fb27SDimitry Andric   // [[no_unique_address]] attribute (since C++20).  Those do count as empty
279*06c3fb27SDimitry Andric   // according to the Itanium ABI.  The exception applies only to records,
280*06c3fb27SDimitry Andric   // not arrays of records, so we must also check whether we stripped off an
281*06c3fb27SDimitry Andric   // array type above.
282*06c3fb27SDimitry Andric   if (isa<CXXRecordDecl>(RT->getDecl()) &&
283*06c3fb27SDimitry Andric       (WasArray || !FD->hasAttr<NoUniqueAddressAttr>()))
284*06c3fb27SDimitry Andric     return false;
285*06c3fb27SDimitry Andric 
286*06c3fb27SDimitry Andric   return isEmptyRecord(Context, FT, AllowArrays);
287*06c3fb27SDimitry Andric }
288*06c3fb27SDimitry Andric 
289*06c3fb27SDimitry Andric bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays) {
290*06c3fb27SDimitry Andric   const RecordType *RT = T->getAs<RecordType>();
291*06c3fb27SDimitry Andric   if (!RT)
292*06c3fb27SDimitry Andric     return false;
293*06c3fb27SDimitry Andric   const RecordDecl *RD = RT->getDecl();
294*06c3fb27SDimitry Andric   if (RD->hasFlexibleArrayMember())
295*06c3fb27SDimitry Andric     return false;
296*06c3fb27SDimitry Andric 
297*06c3fb27SDimitry Andric   // If this is a C++ record, check the bases first.
298*06c3fb27SDimitry Andric   if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
299*06c3fb27SDimitry Andric     for (const auto &I : CXXRD->bases())
300*06c3fb27SDimitry Andric       if (!isEmptyRecord(Context, I.getType(), true))
301*06c3fb27SDimitry Andric         return false;
302*06c3fb27SDimitry Andric 
303*06c3fb27SDimitry Andric   for (const auto *I : RD->fields())
304*06c3fb27SDimitry Andric     if (!isEmptyField(Context, I, AllowArrays))
305*06c3fb27SDimitry Andric       return false;
306*06c3fb27SDimitry Andric   return true;
307*06c3fb27SDimitry Andric }
308*06c3fb27SDimitry Andric 
309*06c3fb27SDimitry Andric const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) {
310*06c3fb27SDimitry Andric   const RecordType *RT = T->getAs<RecordType>();
311*06c3fb27SDimitry Andric   if (!RT)
312*06c3fb27SDimitry Andric     return nullptr;
313*06c3fb27SDimitry Andric 
314*06c3fb27SDimitry Andric   const RecordDecl *RD = RT->getDecl();
315*06c3fb27SDimitry Andric   if (RD->hasFlexibleArrayMember())
316*06c3fb27SDimitry Andric     return nullptr;
317*06c3fb27SDimitry Andric 
318*06c3fb27SDimitry Andric   const Type *Found = nullptr;
319*06c3fb27SDimitry Andric 
320*06c3fb27SDimitry Andric   // If this is a C++ record, check the bases first.
321*06c3fb27SDimitry Andric   if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
322*06c3fb27SDimitry Andric     for (const auto &I : CXXRD->bases()) {
323*06c3fb27SDimitry Andric       // Ignore empty records.
324*06c3fb27SDimitry Andric       if (isEmptyRecord(Context, I.getType(), true))
325*06c3fb27SDimitry Andric         continue;
326*06c3fb27SDimitry Andric 
327*06c3fb27SDimitry Andric       // If we already found an element then this isn't a single-element struct.
328*06c3fb27SDimitry Andric       if (Found)
329*06c3fb27SDimitry Andric         return nullptr;
330*06c3fb27SDimitry Andric 
331*06c3fb27SDimitry Andric       // If this is non-empty and not a single element struct, the composite
332*06c3fb27SDimitry Andric       // cannot be a single element struct.
333*06c3fb27SDimitry Andric       Found = isSingleElementStruct(I.getType(), Context);
334*06c3fb27SDimitry Andric       if (!Found)
335*06c3fb27SDimitry Andric         return nullptr;
336*06c3fb27SDimitry Andric     }
337*06c3fb27SDimitry Andric   }
338*06c3fb27SDimitry Andric 
339*06c3fb27SDimitry Andric   // Check for single element.
340*06c3fb27SDimitry Andric   for (const auto *FD : RD->fields()) {
341*06c3fb27SDimitry Andric     QualType FT = FD->getType();
342*06c3fb27SDimitry Andric 
343*06c3fb27SDimitry Andric     // Ignore empty fields.
344*06c3fb27SDimitry Andric     if (isEmptyField(Context, FD, true))
345*06c3fb27SDimitry Andric       continue;
346*06c3fb27SDimitry Andric 
347*06c3fb27SDimitry Andric     // If we already found an element then this isn't a single-element
348*06c3fb27SDimitry Andric     // struct.
349*06c3fb27SDimitry Andric     if (Found)
350*06c3fb27SDimitry Andric       return nullptr;
351*06c3fb27SDimitry Andric 
352*06c3fb27SDimitry Andric     // Treat single element arrays as the element.
353*06c3fb27SDimitry Andric     while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) {
354*06c3fb27SDimitry Andric       if (AT->getSize().getZExtValue() != 1)
355*06c3fb27SDimitry Andric         break;
356*06c3fb27SDimitry Andric       FT = AT->getElementType();
357*06c3fb27SDimitry Andric     }
358*06c3fb27SDimitry Andric 
359*06c3fb27SDimitry Andric     if (!isAggregateTypeForABI(FT)) {
360*06c3fb27SDimitry Andric       Found = FT.getTypePtr();
361*06c3fb27SDimitry Andric     } else {
362*06c3fb27SDimitry Andric       Found = isSingleElementStruct(FT, Context);
363*06c3fb27SDimitry Andric       if (!Found)
364*06c3fb27SDimitry Andric         return nullptr;
365*06c3fb27SDimitry Andric     }
366*06c3fb27SDimitry Andric   }
367*06c3fb27SDimitry Andric 
368*06c3fb27SDimitry Andric   // We don't consider a struct a single-element struct if it has
369*06c3fb27SDimitry Andric   // padding beyond the element type.
370*06c3fb27SDimitry Andric   if (Found && Context.getTypeSize(Found) != Context.getTypeSize(T))
371*06c3fb27SDimitry Andric     return nullptr;
372*06c3fb27SDimitry Andric 
373*06c3fb27SDimitry Andric   return Found;
374*06c3fb27SDimitry Andric }
375*06c3fb27SDimitry Andric 
376*06c3fb27SDimitry Andric Address CodeGen::EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr,
377*06c3fb27SDimitry Andric                                 QualType Ty, const ABIArgInfo &AI) {
378*06c3fb27SDimitry Andric   // This default implementation defers to the llvm backend's va_arg
379*06c3fb27SDimitry Andric   // instruction. It can handle only passing arguments directly
380*06c3fb27SDimitry Andric   // (typically only handled in the backend for primitive types), or
381*06c3fb27SDimitry Andric   // aggregates passed indirectly by pointer (NOTE: if the "byval"
382*06c3fb27SDimitry Andric   // flag has ABI impact in the callee, this implementation cannot
383*06c3fb27SDimitry Andric   // work.)
384*06c3fb27SDimitry Andric 
385*06c3fb27SDimitry Andric   // Only a few cases are covered here at the moment -- those needed
386*06c3fb27SDimitry Andric   // by the default abi.
387*06c3fb27SDimitry Andric   llvm::Value *Val;
388*06c3fb27SDimitry Andric 
389*06c3fb27SDimitry Andric   if (AI.isIndirect()) {
390*06c3fb27SDimitry Andric     assert(!AI.getPaddingType() &&
391*06c3fb27SDimitry Andric            "Unexpected PaddingType seen in arginfo in generic VAArg emitter!");
392*06c3fb27SDimitry Andric     assert(
393*06c3fb27SDimitry Andric         !AI.getIndirectRealign() &&
394*06c3fb27SDimitry Andric         "Unexpected IndirectRealign seen in arginfo in generic VAArg emitter!");
395*06c3fb27SDimitry Andric 
396*06c3fb27SDimitry Andric     auto TyInfo = CGF.getContext().getTypeInfoInChars(Ty);
397*06c3fb27SDimitry Andric     CharUnits TyAlignForABI = TyInfo.Align;
398*06c3fb27SDimitry Andric 
399*06c3fb27SDimitry Andric     llvm::Type *ElementTy = CGF.ConvertTypeForMem(Ty);
400*06c3fb27SDimitry Andric     llvm::Type *BaseTy = llvm::PointerType::getUnqual(ElementTy);
401*06c3fb27SDimitry Andric     llvm::Value *Addr =
402*06c3fb27SDimitry Andric         CGF.Builder.CreateVAArg(VAListAddr.getPointer(), BaseTy);
403*06c3fb27SDimitry Andric     return Address(Addr, ElementTy, TyAlignForABI);
404*06c3fb27SDimitry Andric   } else {
405*06c3fb27SDimitry Andric     assert((AI.isDirect() || AI.isExtend()) &&
406*06c3fb27SDimitry Andric            "Unexpected ArgInfo Kind in generic VAArg emitter!");
407*06c3fb27SDimitry Andric 
408*06c3fb27SDimitry Andric     assert(!AI.getInReg() &&
409*06c3fb27SDimitry Andric            "Unexpected InReg seen in arginfo in generic VAArg emitter!");
410*06c3fb27SDimitry Andric     assert(!AI.getPaddingType() &&
411*06c3fb27SDimitry Andric            "Unexpected PaddingType seen in arginfo in generic VAArg emitter!");
412*06c3fb27SDimitry Andric     assert(!AI.getDirectOffset() &&
413*06c3fb27SDimitry Andric            "Unexpected DirectOffset seen in arginfo in generic VAArg emitter!");
414*06c3fb27SDimitry Andric     assert(!AI.getCoerceToType() &&
415*06c3fb27SDimitry Andric            "Unexpected CoerceToType seen in arginfo in generic VAArg emitter!");
416*06c3fb27SDimitry Andric 
417*06c3fb27SDimitry Andric     Address Temp = CGF.CreateMemTemp(Ty, "varet");
418*06c3fb27SDimitry Andric     Val = CGF.Builder.CreateVAArg(VAListAddr.getPointer(),
419*06c3fb27SDimitry Andric                                   CGF.ConvertTypeForMem(Ty));
420*06c3fb27SDimitry Andric     CGF.Builder.CreateStore(Val, Temp);
421*06c3fb27SDimitry Andric     return Temp;
422*06c3fb27SDimitry Andric   }
423*06c3fb27SDimitry Andric }
424*06c3fb27SDimitry Andric 
425*06c3fb27SDimitry Andric bool CodeGen::isSIMDVectorType(ASTContext &Context, QualType Ty) {
426*06c3fb27SDimitry Andric   return Ty->getAs<VectorType>() && Context.getTypeSize(Ty) == 128;
427*06c3fb27SDimitry Andric }
428*06c3fb27SDimitry Andric 
429*06c3fb27SDimitry Andric bool CodeGen::isRecordWithSIMDVectorType(ASTContext &Context, QualType Ty) {
430*06c3fb27SDimitry Andric   const RecordType *RT = Ty->getAs<RecordType>();
431*06c3fb27SDimitry Andric   if (!RT)
432*06c3fb27SDimitry Andric     return false;
433*06c3fb27SDimitry Andric   const RecordDecl *RD = RT->getDecl();
434*06c3fb27SDimitry Andric 
435*06c3fb27SDimitry Andric   // If this is a C++ record, check the bases first.
436*06c3fb27SDimitry Andric   if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
437*06c3fb27SDimitry Andric     for (const auto &I : CXXRD->bases())
438*06c3fb27SDimitry Andric       if (!isRecordWithSIMDVectorType(Context, I.getType()))
439*06c3fb27SDimitry Andric         return false;
440*06c3fb27SDimitry Andric 
441*06c3fb27SDimitry Andric   for (const auto *i : RD->fields()) {
442*06c3fb27SDimitry Andric     QualType FT = i->getType();
443*06c3fb27SDimitry Andric 
444*06c3fb27SDimitry Andric     if (isSIMDVectorType(Context, FT))
445*06c3fb27SDimitry Andric       return true;
446*06c3fb27SDimitry Andric 
447*06c3fb27SDimitry Andric     if (isRecordWithSIMDVectorType(Context, FT))
448*06c3fb27SDimitry Andric       return true;
449*06c3fb27SDimitry Andric   }
450*06c3fb27SDimitry Andric 
451*06c3fb27SDimitry Andric   return false;
452*06c3fb27SDimitry Andric }
453