1 //===--- CGNonTrivialStruct.cpp - Emit Special Functions for C Structs ----===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines functions to generate various special functions for C
10 // structs.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "CodeGenFunction.h"
15 #include "CodeGenModule.h"
16 #include "clang/AST/NonTrivialTypeVisitor.h"
17 #include "clang/CodeGen/CodeGenABITypes.h"
18 #include "llvm/Support/ScopedPrinter.h"
19 #include <array>
20 
21 using namespace clang;
22 using namespace CodeGen;
23 
24 // Return the size of a field in number of bits.
getFieldSize(const FieldDecl * FD,QualType FT,ASTContext & Ctx)25 static uint64_t getFieldSize(const FieldDecl *FD, QualType FT,
26                              ASTContext &Ctx) {
27   if (FD && FD->isBitField())
28     return FD->getBitWidthValue(Ctx);
29   return Ctx.getTypeSize(FT);
30 }
31 
32 namespace {
33 enum { DstIdx = 0, SrcIdx = 1 };
34 const char *ValNameStr[2] = {"dst", "src"};
35 
36 template <class Derived> struct StructVisitor {
StructVisitor__anon39bdd2a00111::StructVisitor37   StructVisitor(ASTContext &Ctx) : Ctx(Ctx) {}
38 
39   template <class... Ts>
visitStructFields__anon39bdd2a00111::StructVisitor40   void visitStructFields(QualType QT, CharUnits CurStructOffset, Ts... Args) {
41     const RecordDecl *RD = QT->castAs<RecordType>()->getDecl();
42 
43     // Iterate over the fields of the struct.
44     for (const FieldDecl *FD : RD->fields()) {
45       QualType FT = FD->getType();
46       FT = QT.isVolatileQualified() ? FT.withVolatile() : FT;
47       asDerived().visit(FT, FD, CurStructOffset, Args...);
48     }
49 
50     asDerived().flushTrivialFields(Args...);
51   }
52 
visitTrivial__anon39bdd2a00111::StructVisitor53   template <class... Ts> void visitTrivial(Ts... Args) {}
54 
visitCXXDestructor__anon39bdd2a00111::StructVisitor55   template <class... Ts> void visitCXXDestructor(Ts... Args) {
56     llvm_unreachable("field of a C++ struct type is not expected");
57   }
58 
flushTrivialFields__anon39bdd2a00111::StructVisitor59   template <class... Ts> void flushTrivialFields(Ts... Args) {}
60 
getFieldOffsetInBits__anon39bdd2a00111::StructVisitor61   uint64_t getFieldOffsetInBits(const FieldDecl *FD) {
62     return FD ? Ctx.getASTRecordLayout(FD->getParent())
63                     .getFieldOffset(FD->getFieldIndex())
64               : 0;
65   }
66 
getFieldOffset__anon39bdd2a00111::StructVisitor67   CharUnits getFieldOffset(const FieldDecl *FD) {
68     return Ctx.toCharUnitsFromBits(getFieldOffsetInBits(FD));
69   }
70 
asDerived__anon39bdd2a00111::StructVisitor71   Derived &asDerived() { return static_cast<Derived &>(*this); }
72 
getContext__anon39bdd2a00111::StructVisitor73   ASTContext &getContext() { return Ctx; }
74   ASTContext &Ctx;
75 };
76 
77 template <class Derived, bool IsMove>
78 struct CopyStructVisitor : StructVisitor<Derived>,
79                            CopiedTypeVisitor<Derived, IsMove> {
80   using StructVisitor<Derived>::asDerived;
81   using Super = CopiedTypeVisitor<Derived, IsMove>;
82 
CopyStructVisitor__anon39bdd2a00111::CopyStructVisitor83   CopyStructVisitor(ASTContext &Ctx) : StructVisitor<Derived>(Ctx) {}
84 
85   template <class... Ts>
preVisit__anon39bdd2a00111::CopyStructVisitor86   void preVisit(QualType::PrimitiveCopyKind PCK, QualType FT,
87                 const FieldDecl *FD, CharUnits CurStructOffset, Ts &&... Args) {
88     if (PCK)
89       asDerived().flushTrivialFields(std::forward<Ts>(Args)...);
90   }
91 
92   template <class... Ts>
visitWithKind__anon39bdd2a00111::CopyStructVisitor93   void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT,
94                      const FieldDecl *FD, CharUnits CurStructOffset,
95                      Ts &&... Args) {
96     if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
97       asDerived().visitArray(PCK, AT, FT.isVolatileQualified(), FD,
98                              CurStructOffset, std::forward<Ts>(Args)...);
99       return;
100     }
101 
102     Super::visitWithKind(PCK, FT, FD, CurStructOffset,
103                          std::forward<Ts>(Args)...);
104   }
105 
106   template <class... Ts>
visitTrivial__anon39bdd2a00111::CopyStructVisitor107   void visitTrivial(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset,
108                     Ts... Args) {
109     assert(!FT.isVolatileQualified() && "volatile field not expected");
110     ASTContext &Ctx = asDerived().getContext();
111     uint64_t FieldSize = getFieldSize(FD, FT, Ctx);
112 
113     // Ignore zero-sized fields.
114     if (FieldSize == 0)
115       return;
116 
117     uint64_t FStartInBits = asDerived().getFieldOffsetInBits(FD);
118     uint64_t FEndInBits = FStartInBits + FieldSize;
119     uint64_t RoundedFEnd = llvm::alignTo(FEndInBits, Ctx.getCharWidth());
120 
121     // Set Start if this is the first field of a sequence of trivial fields.
122     if (Start == End)
123       Start = CurStructOffset + Ctx.toCharUnitsFromBits(FStartInBits);
124     End = CurStructOffset + Ctx.toCharUnitsFromBits(RoundedFEnd);
125   }
126 
127   CharUnits Start = CharUnits::Zero(), End = CharUnits::Zero();
128 };
129 
130 // This function creates the mangled name of a special function of a non-trivial
131 // C struct. Since there is no ODR in C, the function is mangled based on the
132 // struct contents and not the name. The mangled name has the following
133 // structure:
134 //
135 // <function-name> ::= <prefix> <alignment-info> "_" <struct-field-info>
136 // <prefix> ::= "__destructor_" | "__default_constructor_" |
137 //              "__copy_constructor_" | "__move_constructor_" |
138 //              "__copy_assignment_" | "__move_assignment_"
139 // <alignment-info> ::= <dst-alignment> ["_" <src-alignment>]
140 // <struct-field-info> ::= <field-info>+
141 // <field-info> ::= <struct-or-scalar-field-info> | <array-field-info>
142 // <struct-or-scalar-field-info> ::= "_S" <struct-field-info> |
143 //                                   <strong-field-info> | <trivial-field-info>
144 // <array-field-info> ::= "_AB" <array-offset> "s" <element-size> "n"
145 //                        <num-elements> <innermost-element-info> "_AE"
146 // <innermost-element-info> ::= <struct-or-scalar-field-info>
147 // <strong-field-info> ::= "_s" ["b"] ["v"] <field-offset>
148 // <trivial-field-info> ::= "_t" ["v"] <field-offset> "_" <field-size>
149 
150 template <class Derived> struct GenFuncNameBase {
getVolatileOffsetStr__anon39bdd2a00111::GenFuncNameBase151   std::string getVolatileOffsetStr(bool IsVolatile, CharUnits Offset) {
152     std::string S;
153     if (IsVolatile)
154       S = "v";
155     S += llvm::to_string(Offset.getQuantity());
156     return S;
157   }
158 
visitARCStrong__anon39bdd2a00111::GenFuncNameBase159   void visitARCStrong(QualType FT, const FieldDecl *FD,
160                       CharUnits CurStructOffset) {
161     appendStr("_s");
162     if (FT->isBlockPointerType())
163       appendStr("b");
164     CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
165     appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset));
166   }
167 
visitARCWeak__anon39bdd2a00111::GenFuncNameBase168   void visitARCWeak(QualType FT, const FieldDecl *FD,
169                     CharUnits CurStructOffset) {
170     appendStr("_w");
171     CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
172     appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset));
173   }
174 
visitStruct__anon39bdd2a00111::GenFuncNameBase175   void visitStruct(QualType QT, const FieldDecl *FD,
176                    CharUnits CurStructOffset) {
177     CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
178     appendStr("_S");
179     asDerived().visitStructFields(QT, FieldOffset);
180   }
181 
182   template <class FieldKind>
visitArray__anon39bdd2a00111::GenFuncNameBase183   void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
184                   const FieldDecl *FD, CharUnits CurStructOffset) {
185     // String for non-volatile trivial fields is emitted when
186     // flushTrivialFields is called.
187     if (!FK)
188       return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset);
189 
190     asDerived().flushTrivialFields();
191     CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
192     ASTContext &Ctx = asDerived().getContext();
193     const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
194     unsigned NumElts = Ctx.getConstantArrayElementCount(CAT);
195     QualType EltTy = Ctx.getBaseElementType(CAT);
196     CharUnits EltSize = Ctx.getTypeSizeInChars(EltTy);
197     appendStr("_AB" + llvm::to_string(FieldOffset.getQuantity()) + "s" +
198               llvm::to_string(EltSize.getQuantity()) + "n" +
199               llvm::to_string(NumElts));
200     EltTy = IsVolatile ? EltTy.withVolatile() : EltTy;
201     asDerived().visitWithKind(FK, EltTy, nullptr, FieldOffset);
202     appendStr("_AE");
203   }
204 
appendStr__anon39bdd2a00111::GenFuncNameBase205   void appendStr(StringRef Str) { Name += Str; }
206 
getName__anon39bdd2a00111::GenFuncNameBase207   std::string getName(QualType QT, bool IsVolatile) {
208     QT = IsVolatile ? QT.withVolatile() : QT;
209     asDerived().visitStructFields(QT, CharUnits::Zero());
210     return Name;
211   }
212 
asDerived__anon39bdd2a00111::GenFuncNameBase213   Derived &asDerived() { return static_cast<Derived &>(*this); }
214 
215   std::string Name;
216 };
217 
218 template <class Derived>
219 struct GenUnaryFuncName : StructVisitor<Derived>, GenFuncNameBase<Derived> {
GenUnaryFuncName__anon39bdd2a00111::GenUnaryFuncName220   GenUnaryFuncName(StringRef Prefix, CharUnits DstAlignment, ASTContext &Ctx)
221       : StructVisitor<Derived>(Ctx) {
222     this->appendStr(Prefix);
223     this->appendStr(llvm::to_string(DstAlignment.getQuantity()));
224   }
225 };
226 
227 // Helper function to create a null constant.
getNullForVariable(Address Addr)228 static llvm::Constant *getNullForVariable(Address Addr) {
229   llvm::Type *Ty = Addr.getElementType();
230   return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(Ty));
231 }
232 
233 template <bool IsMove>
234 struct GenBinaryFuncName : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>,
235                            GenFuncNameBase<GenBinaryFuncName<IsMove>> {
236 
GenBinaryFuncName__anon39bdd2a00111::GenBinaryFuncName237   GenBinaryFuncName(StringRef Prefix, CharUnits DstAlignment,
238                     CharUnits SrcAlignment, ASTContext &Ctx)
239       : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>(Ctx) {
240     this->appendStr(Prefix);
241     this->appendStr(llvm::to_string(DstAlignment.getQuantity()));
242     this->appendStr("_" + llvm::to_string(SrcAlignment.getQuantity()));
243   }
244 
flushTrivialFields__anon39bdd2a00111::GenBinaryFuncName245   void flushTrivialFields() {
246     if (this->Start == this->End)
247       return;
248 
249     this->appendStr("_t" + llvm::to_string(this->Start.getQuantity()) + "w" +
250                     llvm::to_string((this->End - this->Start).getQuantity()));
251 
252     this->Start = this->End = CharUnits::Zero();
253   }
254 
visitVolatileTrivial__anon39bdd2a00111::GenBinaryFuncName255   void visitVolatileTrivial(QualType FT, const FieldDecl *FD,
256                             CharUnits CurStructOffset) {
257     // Zero-length bit-fields don't need to be copied/assigned.
258     if (FD && FD->isZeroLengthBitField(this->Ctx))
259       return;
260 
261     // Because volatile fields can be bit-fields and are individually copied,
262     // their offset and width are in bits.
263     uint64_t OffsetInBits =
264         this->Ctx.toBits(CurStructOffset) + this->getFieldOffsetInBits(FD);
265     this->appendStr("_tv" + llvm::to_string(OffsetInBits) + "w" +
266                     llvm::to_string(getFieldSize(FD, FT, this->Ctx)));
267   }
268 };
269 
270 struct GenDefaultInitializeFuncName
271     : GenUnaryFuncName<GenDefaultInitializeFuncName>,
272       DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName> {
273   using Super = DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName>;
GenDefaultInitializeFuncName__anon39bdd2a00111::GenDefaultInitializeFuncName274   GenDefaultInitializeFuncName(CharUnits DstAlignment, ASTContext &Ctx)
275       : GenUnaryFuncName<GenDefaultInitializeFuncName>("__default_constructor_",
276                                                        DstAlignment, Ctx) {}
visitWithKind__anon39bdd2a00111::GenDefaultInitializeFuncName277   void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
278                      const FieldDecl *FD, CharUnits CurStructOffset) {
279     if (const auto *AT = getContext().getAsArrayType(FT)) {
280       visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset);
281       return;
282     }
283 
284     Super::visitWithKind(PDIK, FT, FD, CurStructOffset);
285   }
286 };
287 
288 struct GenDestructorFuncName : GenUnaryFuncName<GenDestructorFuncName>,
289                                DestructedTypeVisitor<GenDestructorFuncName> {
290   using Super = DestructedTypeVisitor<GenDestructorFuncName>;
GenDestructorFuncName__anon39bdd2a00111::GenDestructorFuncName291   GenDestructorFuncName(const char *Prefix, CharUnits DstAlignment,
292                         ASTContext &Ctx)
293       : GenUnaryFuncName<GenDestructorFuncName>(Prefix, DstAlignment, Ctx) {}
visitWithKind__anon39bdd2a00111::GenDestructorFuncName294   void visitWithKind(QualType::DestructionKind DK, QualType FT,
295                      const FieldDecl *FD, CharUnits CurStructOffset) {
296     if (const auto *AT = getContext().getAsArrayType(FT)) {
297       visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset);
298       return;
299     }
300 
301     Super::visitWithKind(DK, FT, FD, CurStructOffset);
302   }
303 };
304 
305 // Helper function that creates CGFunctionInfo for an N-ary special function.
306 template <size_t N>
getFunctionInfo(CodeGenModule & CGM,FunctionArgList & Args)307 static const CGFunctionInfo &getFunctionInfo(CodeGenModule &CGM,
308                                              FunctionArgList &Args) {
309   ASTContext &Ctx = CGM.getContext();
310   llvm::SmallVector<ImplicitParamDecl *, N> Params;
311   QualType ParamTy = Ctx.getPointerType(Ctx.VoidPtrTy);
312 
313   for (unsigned I = 0; I < N; ++I)
314     Params.push_back(ImplicitParamDecl::Create(
315         Ctx, nullptr, SourceLocation(), &Ctx.Idents.get(ValNameStr[I]), ParamTy,
316         ImplicitParamDecl::Other));
317 
318   llvm::append_range(Args, Params);
319 
320   return CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args);
321 }
322 
323 template <size_t N, size_t... Ints>
getParamAddrs(std::index_sequence<Ints...> IntSeq,std::array<CharUnits,N> Alignments,FunctionArgList Args,CodeGenFunction * CGF)324 static std::array<Address, N> getParamAddrs(std::index_sequence<Ints...> IntSeq,
325                                             std::array<CharUnits, N> Alignments,
326                                             FunctionArgList Args,
327                                             CodeGenFunction *CGF) {
328   return std::array<Address, N>{
329       {Address(CGF->Builder.CreateLoad(CGF->GetAddrOfLocalVar(Args[Ints])),
330                CGF->VoidPtrTy, Alignments[Ints])...}};
331 }
332 
333 // Template classes that are used as bases for classes that emit special
334 // functions.
335 template <class Derived> struct GenFuncBase {
336   template <size_t N>
visitStruct__anon39bdd2a00111::GenFuncBase337   void visitStruct(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset,
338                    std::array<Address, N> Addrs) {
339     this->asDerived().callSpecialFunction(
340         FT, CurStructOffset + asDerived().getFieldOffset(FD), Addrs);
341   }
342 
343   template <class FieldKind, size_t N>
visitArray__anon39bdd2a00111::GenFuncBase344   void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
345                   const FieldDecl *FD, CharUnits CurStructOffset,
346                   std::array<Address, N> Addrs) {
347     // Non-volatile trivial fields are copied when flushTrivialFields is called.
348     if (!FK)
349       return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset,
350                                       Addrs);
351 
352     asDerived().flushTrivialFields(Addrs);
353     CodeGenFunction &CGF = *this->CGF;
354     ASTContext &Ctx = CGF.getContext();
355 
356     // Compute the end address.
357     QualType BaseEltQT;
358     std::array<Address, N> StartAddrs = Addrs;
359     for (unsigned I = 0; I < N; ++I)
360       StartAddrs[I] = getAddrWithOffset(Addrs[I], CurStructOffset, FD);
361     Address DstAddr = StartAddrs[DstIdx];
362     llvm::Value *NumElts = CGF.emitArrayLength(AT, BaseEltQT, DstAddr);
363     unsigned BaseEltSize = Ctx.getTypeSizeInChars(BaseEltQT).getQuantity();
364     llvm::Value *BaseEltSizeVal =
365         llvm::ConstantInt::get(NumElts->getType(), BaseEltSize);
366     llvm::Value *SizeInBytes =
367         CGF.Builder.CreateNUWMul(BaseEltSizeVal, NumElts);
368     Address BC = CGF.Builder.CreateElementBitCast(DstAddr, CGF.CGM.Int8Ty);
369     llvm::Value *DstArrayEnd =
370         CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, BC.getPointer(), SizeInBytes);
371     DstArrayEnd = CGF.Builder.CreateBitCast(
372         DstArrayEnd, CGF.CGM.Int8PtrPtrTy, "dstarray.end");
373     llvm::BasicBlock *PreheaderBB = CGF.Builder.GetInsertBlock();
374 
375     // Create the header block and insert the phi instructions.
376     llvm::BasicBlock *HeaderBB = CGF.createBasicBlock("loop.header");
377     CGF.EmitBlock(HeaderBB);
378     llvm::PHINode *PHIs[N];
379 
380     for (unsigned I = 0; I < N; ++I) {
381       PHIs[I] = CGF.Builder.CreatePHI(CGF.CGM.Int8PtrPtrTy, 2, "addr.cur");
382       PHIs[I]->addIncoming(StartAddrs[I].getPointer(), PreheaderBB);
383     }
384 
385     // Create the exit and loop body blocks.
386     llvm::BasicBlock *ExitBB = CGF.createBasicBlock("loop.exit");
387     llvm::BasicBlock *LoopBB = CGF.createBasicBlock("loop.body");
388 
389     // Emit the comparison and conditional branch instruction that jumps to
390     // either the exit or the loop body.
391     llvm::Value *Done =
392         CGF.Builder.CreateICmpEQ(PHIs[DstIdx], DstArrayEnd, "done");
393     CGF.Builder.CreateCondBr(Done, ExitBB, LoopBB);
394 
395     // Visit the element of the array in the loop body.
396     CGF.EmitBlock(LoopBB);
397     QualType EltQT = AT->getElementType();
398     CharUnits EltSize = Ctx.getTypeSizeInChars(EltQT);
399     std::array<Address, N> NewAddrs = Addrs;
400 
401     for (unsigned I = 0; I < N; ++I)
402       NewAddrs[I] =
403             Address(PHIs[I], CGF.Int8PtrTy,
404                     StartAddrs[I].getAlignment().alignmentAtOffset(EltSize));
405 
406     EltQT = IsVolatile ? EltQT.withVolatile() : EltQT;
407     this->asDerived().visitWithKind(FK, EltQT, nullptr, CharUnits::Zero(),
408                                     NewAddrs);
409 
410     LoopBB = CGF.Builder.GetInsertBlock();
411 
412     for (unsigned I = 0; I < N; ++I) {
413       // Instrs to update the destination and source addresses.
414       // Update phi instructions.
415       NewAddrs[I] = getAddrWithOffset(NewAddrs[I], EltSize);
416       PHIs[I]->addIncoming(NewAddrs[I].getPointer(), LoopBB);
417     }
418 
419     // Insert an unconditional branch to the header block.
420     CGF.Builder.CreateBr(HeaderBB);
421     CGF.EmitBlock(ExitBB);
422   }
423 
424   /// Return an address with the specified offset from the passed address.
getAddrWithOffset__anon39bdd2a00111::GenFuncBase425   Address getAddrWithOffset(Address Addr, CharUnits Offset) {
426     assert(Addr.isValid() && "invalid address");
427     if (Offset.getQuantity() == 0)
428       return Addr;
429     Addr = CGF->Builder.CreateElementBitCast(Addr, CGF->CGM.Int8Ty);
430     Addr = CGF->Builder.CreateConstInBoundsGEP(Addr, Offset.getQuantity());
431     return CGF->Builder.CreateElementBitCast(Addr, CGF->CGM.Int8PtrTy);
432   }
433 
getAddrWithOffset__anon39bdd2a00111::GenFuncBase434   Address getAddrWithOffset(Address Addr, CharUnits StructFieldOffset,
435                             const FieldDecl *FD) {
436     return getAddrWithOffset(Addr, StructFieldOffset +
437                                        asDerived().getFieldOffset(FD));
438   }
439 
440   template <size_t N>
getFunction__anon39bdd2a00111::GenFuncBase441   llvm::Function *getFunction(StringRef FuncName, QualType QT,
442                               std::array<CharUnits, N> Alignments,
443                               CodeGenModule &CGM) {
444     // If the special function already exists in the module, return it.
445     if (llvm::Function *F = CGM.getModule().getFunction(FuncName)) {
446       bool WrongType = false;
447       if (!F->getReturnType()->isVoidTy())
448         WrongType = true;
449       else {
450         for (const llvm::Argument &Arg : F->args())
451           if (Arg.getType() != CGM.Int8PtrPtrTy)
452             WrongType = true;
453       }
454 
455       if (WrongType) {
456         std::string FuncName = std::string(F->getName());
457         SourceLocation Loc = QT->castAs<RecordType>()->getDecl()->getLocation();
458         CGM.Error(Loc, "special function " + FuncName +
459                            " for non-trivial C struct has incorrect type");
460         return nullptr;
461       }
462       return F;
463     }
464 
465     ASTContext &Ctx = CGM.getContext();
466     FunctionArgList Args;
467     const CGFunctionInfo &FI = getFunctionInfo<N>(CGM, Args);
468     llvm::FunctionType *FuncTy = CGM.getTypes().GetFunctionType(FI);
469     llvm::Function *F =
470         llvm::Function::Create(FuncTy, llvm::GlobalValue::LinkOnceODRLinkage,
471                                FuncName, &CGM.getModule());
472     F->setVisibility(llvm::GlobalValue::HiddenVisibility);
473     CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F, /*IsThunk=*/false);
474     CGM.SetLLVMFunctionAttributesForDefinition(nullptr, F);
475     CodeGenFunction NewCGF(CGM);
476     setCGF(&NewCGF);
477     CGF->StartFunction(GlobalDecl(), Ctx.VoidTy, F, FI, Args);
478     auto AL = ApplyDebugLocation::CreateArtificial(*CGF);
479     std::array<Address, N> Addrs =
480         getParamAddrs<N>(std::make_index_sequence<N>{}, Alignments, Args, CGF);
481     asDerived().visitStructFields(QT, CharUnits::Zero(), Addrs);
482     CGF->FinishFunction();
483     return F;
484   }
485 
486   template <size_t N>
callFunc__anon39bdd2a00111::GenFuncBase487   void callFunc(StringRef FuncName, QualType QT, std::array<Address, N> Addrs,
488                 CodeGenFunction &CallerCGF) {
489     std::array<CharUnits, N> Alignments;
490     llvm::Value *Ptrs[N];
491 
492     for (unsigned I = 0; I < N; ++I) {
493       Alignments[I] = Addrs[I].getAlignment();
494       Ptrs[I] = CallerCGF.Builder.CreateElementBitCast(
495           Addrs[I], CallerCGF.CGM.Int8PtrTy).getPointer();
496     }
497 
498     if (llvm::Function *F =
499             getFunction(FuncName, QT, Alignments, CallerCGF.CGM))
500       CallerCGF.EmitNounwindRuntimeCall(F, Ptrs);
501   }
502 
asDerived__anon39bdd2a00111::GenFuncBase503   Derived &asDerived() { return static_cast<Derived &>(*this); }
504 
setCGF__anon39bdd2a00111::GenFuncBase505   void setCGF(CodeGenFunction *F) { CGF = F; }
506 
507   CodeGenFunction *CGF = nullptr;
508 };
509 
510 template <class Derived, bool IsMove>
511 struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>,
512                        GenFuncBase<Derived> {
GenBinaryFunc__anon39bdd2a00111::GenBinaryFunc513   GenBinaryFunc(ASTContext &Ctx) : CopyStructVisitor<Derived, IsMove>(Ctx) {}
514 
flushTrivialFields__anon39bdd2a00111::GenBinaryFunc515   void flushTrivialFields(std::array<Address, 2> Addrs) {
516     CharUnits Size = this->End - this->Start;
517 
518     if (Size.getQuantity() == 0)
519       return;
520 
521     Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], this->Start);
522     Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], this->Start);
523 
524     // Emit memcpy.
525     if (Size.getQuantity() >= 16 || !llvm::isPowerOf2_32(Size.getQuantity())) {
526       llvm::Value *SizeVal =
527           llvm::ConstantInt::get(this->CGF->SizeTy, Size.getQuantity());
528       DstAddr =
529           this->CGF->Builder.CreateElementBitCast(DstAddr, this->CGF->Int8Ty);
530       SrcAddr =
531           this->CGF->Builder.CreateElementBitCast(SrcAddr, this->CGF->Int8Ty);
532       this->CGF->Builder.CreateMemCpy(DstAddr, SrcAddr, SizeVal, false);
533     } else {
534       llvm::Type *Ty = llvm::Type::getIntNTy(
535           this->CGF->getLLVMContext(),
536           Size.getQuantity() * this->CGF->getContext().getCharWidth());
537       DstAddr = this->CGF->Builder.CreateElementBitCast(DstAddr, Ty);
538       SrcAddr = this->CGF->Builder.CreateElementBitCast(SrcAddr, Ty);
539       llvm::Value *SrcVal = this->CGF->Builder.CreateLoad(SrcAddr, false);
540       this->CGF->Builder.CreateStore(SrcVal, DstAddr, false);
541     }
542 
543     this->Start = this->End = CharUnits::Zero();
544   }
545 
546   template <class... Ts>
visitVolatileTrivial__anon39bdd2a00111::GenBinaryFunc547   void visitVolatileTrivial(QualType FT, const FieldDecl *FD, CharUnits Offset,
548                             std::array<Address, 2> Addrs) {
549     LValue DstLV, SrcLV;
550     if (FD) {
551       // No need to copy zero-length bit-fields.
552       if (FD->isZeroLengthBitField(this->CGF->getContext()))
553         return;
554 
555       QualType RT = QualType(FD->getParent()->getTypeForDecl(), 0);
556       llvm::Type *Ty = this->CGF->ConvertType(RT);
557       Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset);
558       LValue DstBase = this->CGF->MakeAddrLValue(
559           this->CGF->Builder.CreateElementBitCast(DstAddr, Ty), FT);
560       DstLV = this->CGF->EmitLValueForField(DstBase, FD);
561       Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], Offset);
562       LValue SrcBase = this->CGF->MakeAddrLValue(
563           this->CGF->Builder.CreateElementBitCast(SrcAddr, Ty), FT);
564       SrcLV = this->CGF->EmitLValueForField(SrcBase, FD);
565     } else {
566       llvm::Type *Ty = this->CGF->ConvertTypeForMem(FT);
567       Address DstAddr =
568           this->CGF->Builder.CreateElementBitCast(Addrs[DstIdx], Ty);
569       Address SrcAddr =
570           this->CGF->Builder.CreateElementBitCast(Addrs[SrcIdx], Ty);
571       DstLV = this->CGF->MakeAddrLValue(DstAddr, FT);
572       SrcLV = this->CGF->MakeAddrLValue(SrcAddr, FT);
573     }
574     RValue SrcVal = this->CGF->EmitLoadOfLValue(SrcLV, SourceLocation());
575     this->CGF->EmitStoreThroughLValue(SrcVal, DstLV);
576   }
577 };
578 
579 // These classes that emit the special functions for a non-trivial struct.
580 struct GenDestructor : StructVisitor<GenDestructor>,
581                        GenFuncBase<GenDestructor>,
582                        DestructedTypeVisitor<GenDestructor> {
583   using Super = DestructedTypeVisitor<GenDestructor>;
GenDestructor__anon39bdd2a00111::GenDestructor584   GenDestructor(ASTContext &Ctx) : StructVisitor<GenDestructor>(Ctx) {}
585 
visitWithKind__anon39bdd2a00111::GenDestructor586   void visitWithKind(QualType::DestructionKind DK, QualType FT,
587                      const FieldDecl *FD, CharUnits CurStructOffset,
588                      std::array<Address, 1> Addrs) {
589     if (const auto *AT = getContext().getAsArrayType(FT)) {
590       visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset, Addrs);
591       return;
592     }
593 
594     Super::visitWithKind(DK, FT, FD, CurStructOffset, Addrs);
595   }
596 
visitARCStrong__anon39bdd2a00111::GenDestructor597   void visitARCStrong(QualType QT, const FieldDecl *FD,
598                       CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
599     CGF->destroyARCStrongImprecise(
600         *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
601   }
602 
visitARCWeak__anon39bdd2a00111::GenDestructor603   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
604                     std::array<Address, 1> Addrs) {
605     CGF->destroyARCWeak(
606         *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
607   }
608 
callSpecialFunction__anon39bdd2a00111::GenDestructor609   void callSpecialFunction(QualType FT, CharUnits Offset,
610                            std::array<Address, 1> Addrs) {
611     CGF->callCStructDestructor(
612         CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
613   }
614 };
615 
616 struct GenDefaultInitialize
617     : StructVisitor<GenDefaultInitialize>,
618       GenFuncBase<GenDefaultInitialize>,
619       DefaultInitializedTypeVisitor<GenDefaultInitialize> {
620   using Super = DefaultInitializedTypeVisitor<GenDefaultInitialize>;
621   typedef GenFuncBase<GenDefaultInitialize> GenFuncBaseTy;
622 
GenDefaultInitialize__anon39bdd2a00111::GenDefaultInitialize623   GenDefaultInitialize(ASTContext &Ctx)
624       : StructVisitor<GenDefaultInitialize>(Ctx) {}
625 
visitWithKind__anon39bdd2a00111::GenDefaultInitialize626   void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
627                      const FieldDecl *FD, CharUnits CurStructOffset,
628                      std::array<Address, 1> Addrs) {
629     if (const auto *AT = getContext().getAsArrayType(FT)) {
630       visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset,
631                  Addrs);
632       return;
633     }
634 
635     Super::visitWithKind(PDIK, FT, FD, CurStructOffset, Addrs);
636   }
637 
visitARCStrong__anon39bdd2a00111::GenDefaultInitialize638   void visitARCStrong(QualType QT, const FieldDecl *FD,
639                       CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
640     CGF->EmitNullInitialization(
641         getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
642   }
643 
visitARCWeak__anon39bdd2a00111::GenDefaultInitialize644   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
645                     std::array<Address, 1> Addrs) {
646     CGF->EmitNullInitialization(
647         getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
648   }
649 
650   template <class FieldKind, size_t... Is>
visitArray__anon39bdd2a00111::GenDefaultInitialize651   void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
652                   const FieldDecl *FD, CharUnits CurStructOffset,
653                   std::array<Address, 1> Addrs) {
654     if (!FK)
655       return visitTrivial(QualType(AT, 0), FD, CurStructOffset, Addrs);
656 
657     ASTContext &Ctx = getContext();
658     CharUnits Size = Ctx.getTypeSizeInChars(QualType(AT, 0));
659     QualType EltTy = Ctx.getBaseElementType(QualType(AT, 0));
660 
661     if (Size < CharUnits::fromQuantity(16) || EltTy->getAs<RecordType>()) {
662       GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStructOffset, Addrs);
663       return;
664     }
665 
666     llvm::Constant *SizeVal = CGF->Builder.getInt64(Size.getQuantity());
667     Address DstAddr = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
668     Address Loc = CGF->Builder.CreateElementBitCast(DstAddr, CGF->Int8Ty);
669     CGF->Builder.CreateMemSet(Loc, CGF->Builder.getInt8(0), SizeVal,
670                               IsVolatile);
671   }
672 
callSpecialFunction__anon39bdd2a00111::GenDefaultInitialize673   void callSpecialFunction(QualType FT, CharUnits Offset,
674                            std::array<Address, 1> Addrs) {
675     CGF->callCStructDefaultConstructor(
676         CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
677   }
678 };
679 
680 struct GenCopyConstructor : GenBinaryFunc<GenCopyConstructor, false> {
GenCopyConstructor__anon39bdd2a00111::GenCopyConstructor681   GenCopyConstructor(ASTContext &Ctx)
682       : GenBinaryFunc<GenCopyConstructor, false>(Ctx) {}
683 
visitARCStrong__anon39bdd2a00111::GenCopyConstructor684   void visitARCStrong(QualType QT, const FieldDecl *FD,
685                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
686     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
687     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
688     llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
689         Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
690     llvm::Value *Val = CGF->EmitARCRetain(QT, SrcVal);
691     CGF->EmitStoreOfScalar(Val, CGF->MakeAddrLValue(Addrs[DstIdx], QT), true);
692   }
693 
visitARCWeak__anon39bdd2a00111::GenCopyConstructor694   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
695                     std::array<Address, 2> Addrs) {
696     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
697     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
698     CGF->EmitARCCopyWeak(Addrs[DstIdx], Addrs[SrcIdx]);
699   }
700 
callSpecialFunction__anon39bdd2a00111::GenCopyConstructor701   void callSpecialFunction(QualType FT, CharUnits Offset,
702                            std::array<Address, 2> Addrs) {
703     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
704     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
705     CGF->callCStructCopyConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
706                                     CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
707   }
708 };
709 
710 struct GenMoveConstructor : GenBinaryFunc<GenMoveConstructor, true> {
GenMoveConstructor__anon39bdd2a00111::GenMoveConstructor711   GenMoveConstructor(ASTContext &Ctx)
712       : GenBinaryFunc<GenMoveConstructor, true>(Ctx) {}
713 
visitARCStrong__anon39bdd2a00111::GenMoveConstructor714   void visitARCStrong(QualType QT, const FieldDecl *FD,
715                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
716     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
717     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
718     LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
719     llvm::Value *SrcVal =
720         CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
721     CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress(*CGF)), SrcLV);
722     CGF->EmitStoreOfScalar(SrcVal, CGF->MakeAddrLValue(Addrs[DstIdx], QT),
723                            /* isInitialization */ true);
724   }
725 
visitARCWeak__anon39bdd2a00111::GenMoveConstructor726   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
727                     std::array<Address, 2> Addrs) {
728     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
729     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
730     CGF->EmitARCMoveWeak(Addrs[DstIdx], Addrs[SrcIdx]);
731   }
732 
callSpecialFunction__anon39bdd2a00111::GenMoveConstructor733   void callSpecialFunction(QualType FT, CharUnits Offset,
734                            std::array<Address, 2> Addrs) {
735     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
736     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
737     CGF->callCStructMoveConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
738                                     CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
739   }
740 };
741 
742 struct GenCopyAssignment : GenBinaryFunc<GenCopyAssignment, false> {
GenCopyAssignment__anon39bdd2a00111::GenCopyAssignment743   GenCopyAssignment(ASTContext &Ctx)
744       : GenBinaryFunc<GenCopyAssignment, false>(Ctx) {}
745 
visitARCStrong__anon39bdd2a00111::GenCopyAssignment746   void visitARCStrong(QualType QT, const FieldDecl *FD,
747                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
748     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
749     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
750     llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
751         Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
752     CGF->EmitARCStoreStrong(CGF->MakeAddrLValue(Addrs[DstIdx], QT), SrcVal,
753                             false);
754   }
755 
visitARCWeak__anon39bdd2a00111::GenCopyAssignment756   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
757                     std::array<Address, 2> Addrs) {
758     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
759     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
760     CGF->emitARCCopyAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
761   }
762 
callSpecialFunction__anon39bdd2a00111::GenCopyAssignment763   void callSpecialFunction(QualType FT, CharUnits Offset,
764                            std::array<Address, 2> Addrs) {
765     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
766     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
767     CGF->callCStructCopyAssignmentOperator(
768         CGF->MakeAddrLValue(Addrs[DstIdx], FT),
769         CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
770   }
771 };
772 
773 struct GenMoveAssignment : GenBinaryFunc<GenMoveAssignment, true> {
GenMoveAssignment__anon39bdd2a00111::GenMoveAssignment774   GenMoveAssignment(ASTContext &Ctx)
775       : GenBinaryFunc<GenMoveAssignment, true>(Ctx) {}
776 
visitARCStrong__anon39bdd2a00111::GenMoveAssignment777   void visitARCStrong(QualType QT, const FieldDecl *FD,
778                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
779     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
780     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
781     LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
782     llvm::Value *SrcVal =
783         CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
784     CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress(*CGF)), SrcLV);
785     LValue DstLV = CGF->MakeAddrLValue(Addrs[DstIdx], QT);
786     llvm::Value *DstVal =
787         CGF->EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
788     CGF->EmitStoreOfScalar(SrcVal, DstLV);
789     CGF->EmitARCRelease(DstVal, ARCImpreciseLifetime);
790   }
791 
visitARCWeak__anon39bdd2a00111::GenMoveAssignment792   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
793                     std::array<Address, 2> Addrs) {
794     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
795     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
796     CGF->emitARCMoveAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
797   }
798 
callSpecialFunction__anon39bdd2a00111::GenMoveAssignment799   void callSpecialFunction(QualType FT, CharUnits Offset,
800                            std::array<Address, 2> Addrs) {
801     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
802     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
803     CGF->callCStructMoveAssignmentOperator(
804         CGF->MakeAddrLValue(Addrs[DstIdx], FT),
805         CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
806   }
807 };
808 
809 } // namespace
810 
destroyNonTrivialCStruct(CodeGenFunction & CGF,Address Addr,QualType Type)811 void CodeGenFunction::destroyNonTrivialCStruct(CodeGenFunction &CGF,
812                                                Address Addr, QualType Type) {
813   CGF.callCStructDestructor(CGF.MakeAddrLValue(Addr, Type));
814 }
815 
816 // Default-initialize a variable that is a non-trivial struct or an array of
817 // such structure.
defaultInitNonTrivialCStructVar(LValue Dst)818 void CodeGenFunction::defaultInitNonTrivialCStructVar(LValue Dst) {
819   GenDefaultInitialize Gen(getContext());
820   Address DstPtr =
821       Builder.CreateElementBitCast(Dst.getAddress(*this), CGM.Int8PtrTy);
822   Gen.setCGF(this);
823   QualType QT = Dst.getType();
824   QT = Dst.isVolatile() ? QT.withVolatile() : QT;
825   Gen.visit(QT, nullptr, CharUnits::Zero(), std::array<Address, 1>({{DstPtr}}));
826 }
827 
828 template <class G, size_t N>
callSpecialFunction(G && Gen,StringRef FuncName,QualType QT,bool IsVolatile,CodeGenFunction & CGF,std::array<Address,N> Addrs)829 static void callSpecialFunction(G &&Gen, StringRef FuncName, QualType QT,
830                                 bool IsVolatile, CodeGenFunction &CGF,
831                                 std::array<Address, N> Addrs) {
832   auto SetArtificialLoc = ApplyDebugLocation::CreateArtificial(CGF);
833   for (unsigned I = 0; I < N; ++I)
834     Addrs[I] = CGF.Builder.CreateElementBitCast(Addrs[I], CGF.CGM.Int8PtrTy);
835   QT = IsVolatile ? QT.withVolatile() : QT;
836   Gen.callFunc(FuncName, QT, Addrs, CGF);
837 }
838 
839 template <class G, size_t N>
840 static llvm::Function *
getSpecialFunction(G && Gen,StringRef FuncName,QualType QT,bool IsVolatile,std::array<CharUnits,N> Alignments,CodeGenModule & CGM)841 getSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile,
842                    std::array<CharUnits, N> Alignments, CodeGenModule &CGM) {
843   QT = IsVolatile ? QT.withVolatile() : QT;
844   // The following call requires an array of addresses as arguments, but doesn't
845   // actually use them (it overwrites them with the addresses of the arguments
846   // of the created function).
847   return Gen.getFunction(FuncName, QT, Alignments, CGM);
848 }
849 
850 // Functions to emit calls to the special functions of a non-trivial C struct.
callCStructDefaultConstructor(LValue Dst)851 void CodeGenFunction::callCStructDefaultConstructor(LValue Dst) {
852   bool IsVolatile = Dst.isVolatile();
853   Address DstPtr = Dst.getAddress(*this);
854   QualType QT = Dst.getType();
855   GenDefaultInitializeFuncName GenName(DstPtr.getAlignment(), getContext());
856   std::string FuncName = GenName.getName(QT, IsVolatile);
857   callSpecialFunction(GenDefaultInitialize(getContext()), FuncName, QT,
858                       IsVolatile, *this, std::array<Address, 1>({{DstPtr}}));
859 }
860 
getNonTrivialCopyConstructorStr(QualType QT,CharUnits Alignment,bool IsVolatile,ASTContext & Ctx)861 std::string CodeGenFunction::getNonTrivialCopyConstructorStr(
862     QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx) {
863   GenBinaryFuncName<false> GenName("", Alignment, Alignment, Ctx);
864   return GenName.getName(QT, IsVolatile);
865 }
866 
getNonTrivialDestructorStr(QualType QT,CharUnits Alignment,bool IsVolatile,ASTContext & Ctx)867 std::string CodeGenFunction::getNonTrivialDestructorStr(QualType QT,
868                                                         CharUnits Alignment,
869                                                         bool IsVolatile,
870                                                         ASTContext &Ctx) {
871   GenDestructorFuncName GenName("", Alignment, Ctx);
872   return GenName.getName(QT, IsVolatile);
873 }
874 
callCStructDestructor(LValue Dst)875 void CodeGenFunction::callCStructDestructor(LValue Dst) {
876   bool IsVolatile = Dst.isVolatile();
877   Address DstPtr = Dst.getAddress(*this);
878   QualType QT = Dst.getType();
879   GenDestructorFuncName GenName("__destructor_", DstPtr.getAlignment(),
880                                 getContext());
881   std::string FuncName = GenName.getName(QT, IsVolatile);
882   callSpecialFunction(GenDestructor(getContext()), FuncName, QT, IsVolatile,
883                       *this, std::array<Address, 1>({{DstPtr}}));
884 }
885 
callCStructCopyConstructor(LValue Dst,LValue Src)886 void CodeGenFunction::callCStructCopyConstructor(LValue Dst, LValue Src) {
887   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
888   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
889   QualType QT = Dst.getType();
890   GenBinaryFuncName<false> GenName("__copy_constructor_", DstPtr.getAlignment(),
891                                    SrcPtr.getAlignment(), getContext());
892   std::string FuncName = GenName.getName(QT, IsVolatile);
893   callSpecialFunction(GenCopyConstructor(getContext()), FuncName, QT,
894                       IsVolatile, *this,
895                       std::array<Address, 2>({{DstPtr, SrcPtr}}));
896 }
897 
callCStructCopyAssignmentOperator(LValue Dst,LValue Src)898 void CodeGenFunction::callCStructCopyAssignmentOperator(LValue Dst, LValue Src
899 
900 ) {
901   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
902   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
903   QualType QT = Dst.getType();
904   GenBinaryFuncName<false> GenName("__copy_assignment_", DstPtr.getAlignment(),
905                                    SrcPtr.getAlignment(), getContext());
906   std::string FuncName = GenName.getName(QT, IsVolatile);
907   callSpecialFunction(GenCopyAssignment(getContext()), FuncName, QT, IsVolatile,
908                       *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
909 }
910 
callCStructMoveConstructor(LValue Dst,LValue Src)911 void CodeGenFunction::callCStructMoveConstructor(LValue Dst, LValue Src) {
912   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
913   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
914   QualType QT = Dst.getType();
915   GenBinaryFuncName<true> GenName("__move_constructor_", DstPtr.getAlignment(),
916                                   SrcPtr.getAlignment(), getContext());
917   std::string FuncName = GenName.getName(QT, IsVolatile);
918   callSpecialFunction(GenMoveConstructor(getContext()), FuncName, QT,
919                       IsVolatile, *this,
920                       std::array<Address, 2>({{DstPtr, SrcPtr}}));
921 }
922 
callCStructMoveAssignmentOperator(LValue Dst,LValue Src)923 void CodeGenFunction::callCStructMoveAssignmentOperator(LValue Dst, LValue Src
924 
925 ) {
926   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
927   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
928   QualType QT = Dst.getType();
929   GenBinaryFuncName<true> GenName("__move_assignment_", DstPtr.getAlignment(),
930                                   SrcPtr.getAlignment(), getContext());
931   std::string FuncName = GenName.getName(QT, IsVolatile);
932   callSpecialFunction(GenMoveAssignment(getContext()), FuncName, QT, IsVolatile,
933                       *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
934 }
935 
getNonTrivialCStructDefaultConstructor(CodeGenModule & CGM,CharUnits DstAlignment,bool IsVolatile,QualType QT)936 llvm::Function *clang::CodeGen::getNonTrivialCStructDefaultConstructor(
937     CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
938   ASTContext &Ctx = CGM.getContext();
939   GenDefaultInitializeFuncName GenName(DstAlignment, Ctx);
940   std::string FuncName = GenName.getName(QT, IsVolatile);
941   return getSpecialFunction(GenDefaultInitialize(Ctx), FuncName, QT, IsVolatile,
942                             std::array<CharUnits, 1>({{DstAlignment}}), CGM);
943 }
944 
getNonTrivialCStructCopyConstructor(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)945 llvm::Function *clang::CodeGen::getNonTrivialCStructCopyConstructor(
946     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
947     bool IsVolatile, QualType QT) {
948   ASTContext &Ctx = CGM.getContext();
949   GenBinaryFuncName<false> GenName("__copy_constructor_", DstAlignment,
950                                    SrcAlignment, Ctx);
951   std::string FuncName = GenName.getName(QT, IsVolatile);
952   return getSpecialFunction(
953       GenCopyConstructor(Ctx), FuncName, QT, IsVolatile,
954       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
955 }
956 
getNonTrivialCStructMoveConstructor(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)957 llvm::Function *clang::CodeGen::getNonTrivialCStructMoveConstructor(
958     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
959     bool IsVolatile, QualType QT) {
960   ASTContext &Ctx = CGM.getContext();
961   GenBinaryFuncName<true> GenName("__move_constructor_", DstAlignment,
962                                   SrcAlignment, Ctx);
963   std::string FuncName = GenName.getName(QT, IsVolatile);
964   return getSpecialFunction(
965       GenMoveConstructor(Ctx), FuncName, QT, IsVolatile,
966       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
967 }
968 
getNonTrivialCStructCopyAssignmentOperator(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)969 llvm::Function *clang::CodeGen::getNonTrivialCStructCopyAssignmentOperator(
970     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
971     bool IsVolatile, QualType QT) {
972   ASTContext &Ctx = CGM.getContext();
973   GenBinaryFuncName<false> GenName("__copy_assignment_", DstAlignment,
974                                    SrcAlignment, Ctx);
975   std::string FuncName = GenName.getName(QT, IsVolatile);
976   return getSpecialFunction(
977       GenCopyAssignment(Ctx), FuncName, QT, IsVolatile,
978       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
979 }
980 
getNonTrivialCStructMoveAssignmentOperator(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)981 llvm::Function *clang::CodeGen::getNonTrivialCStructMoveAssignmentOperator(
982     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
983     bool IsVolatile, QualType QT) {
984   ASTContext &Ctx = CGM.getContext();
985   GenBinaryFuncName<true> GenName("__move_assignment_", DstAlignment,
986                                   SrcAlignment, Ctx);
987   std::string FuncName = GenName.getName(QT, IsVolatile);
988   return getSpecialFunction(
989       GenMoveAssignment(Ctx), FuncName, QT, IsVolatile,
990       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
991 }
992 
getNonTrivialCStructDestructor(CodeGenModule & CGM,CharUnits DstAlignment,bool IsVolatile,QualType QT)993 llvm::Function *clang::CodeGen::getNonTrivialCStructDestructor(
994     CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
995   ASTContext &Ctx = CGM.getContext();
996   GenDestructorFuncName GenName("__destructor_", DstAlignment, Ctx);
997   std::string FuncName = GenName.getName(QT, IsVolatile);
998   return getSpecialFunction(GenDestructor(Ctx), FuncName, QT, IsVolatile,
999                             std::array<CharUnits, 1>({{DstAlignment}}), CGM);
1000 }
1001