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