Home | History | Annotate | Line # | Download | only in CodeGen
      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.
     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 {
     37   StructVisitor(ASTContext &Ctx) : Ctx(Ctx) {}
     38 
     39   template <class... Ts>
     40   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 
     53   template <class... Ts> void visitTrivial(Ts... Args) {}
     54 
     55   template <class... Ts> void visitCXXDestructor(Ts... Args) {
     56     llvm_unreachable("field of a C++ struct type is not expected");
     57   }
     58 
     59   template <class... Ts> void flushTrivialFields(Ts... Args) {}
     60 
     61   uint64_t getFieldOffsetInBits(const FieldDecl *FD) {
     62     return FD ? Ctx.getASTRecordLayout(FD->getParent())
     63                     .getFieldOffset(FD->getFieldIndex())
     64               : 0;
     65   }
     66 
     67   CharUnits getFieldOffset(const FieldDecl *FD) {
     68     return Ctx.toCharUnitsFromBits(getFieldOffsetInBits(FD));
     69   }
     70 
     71   Derived &asDerived() { return static_cast<Derived &>(*this); }
     72 
     73   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 
     83   CopyStructVisitor(ASTContext &Ctx) : StructVisitor<Derived>(Ctx) {}
     84 
     85   template <class... Ts>
     86   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>
     93   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>
    107   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 {
    151   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 
    159   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 
    168   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 
    175   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>
    183   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 
    205   void appendStr(StringRef Str) { Name += Str; }
    206 
    207   std::string getName(QualType QT, bool IsVolatile) {
    208     QT = IsVolatile ? QT.withVolatile() : QT;
    209     asDerived().visitStructFields(QT, CharUnits::Zero());
    210     return Name;
    211   }
    212 
    213   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> {
    220   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.
    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 
    237   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 
    245   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 
    255   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>;
    274   GenDefaultInitializeFuncName(CharUnits DstAlignment, ASTContext &Ctx)
    275       : GenUnaryFuncName<GenDefaultInitializeFuncName>("__default_constructor_",
    276                                                        DstAlignment, Ctx) {}
    277   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>;
    291   GenDestructorFuncName(const char *Prefix, CharUnits DstAlignment,
    292                         ASTContext &Ctx)
    293       : GenUnaryFuncName<GenDestructorFuncName>(Prefix, DstAlignment, Ctx) {}
    294   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>
    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   for (auto &P : Params)
    319     Args.push_back(P);
    320 
    321   return CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args);
    322 }
    323 
    324 template <size_t N, size_t... Ints>
    325 static std::array<Address, N> getParamAddrs(std::index_sequence<Ints...> IntSeq,
    326                                             std::array<CharUnits, N> Alignments,
    327                                             FunctionArgList Args,
    328                                             CodeGenFunction *CGF) {
    329   return std::array<Address, N>{{
    330       Address(CGF->Builder.CreateLoad(CGF->GetAddrOfLocalVar(Args[Ints])),
    331               Alignments[Ints])...}};
    332 }
    333 
    334 // Template classes that are used as bases for classes that emit special
    335 // functions.
    336 template <class Derived> struct GenFuncBase {
    337   template <size_t N>
    338   void visitStruct(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset,
    339                    std::array<Address, N> Addrs) {
    340     this->asDerived().callSpecialFunction(
    341         FT, CurStructOffset + asDerived().getFieldOffset(FD), Addrs);
    342   }
    343 
    344   template <class FieldKind, size_t N>
    345   void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
    346                   const FieldDecl *FD, CharUnits CurStructOffset,
    347                   std::array<Address, N> Addrs) {
    348     // Non-volatile trivial fields are copied when flushTrivialFields is called.
    349     if (!FK)
    350       return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset,
    351                                       Addrs);
    352 
    353     asDerived().flushTrivialFields(Addrs);
    354     CodeGenFunction &CGF = *this->CGF;
    355     ASTContext &Ctx = CGF.getContext();
    356 
    357     // Compute the end address.
    358     QualType BaseEltQT;
    359     std::array<Address, N> StartAddrs = Addrs;
    360     for (unsigned I = 0; I < N; ++I)
    361       StartAddrs[I] = getAddrWithOffset(Addrs[I], CurStructOffset, FD);
    362     Address DstAddr = StartAddrs[DstIdx];
    363     llvm::Value *NumElts = CGF.emitArrayLength(AT, BaseEltQT, DstAddr);
    364     unsigned BaseEltSize = Ctx.getTypeSizeInChars(BaseEltQT).getQuantity();
    365     llvm::Value *BaseEltSizeVal =
    366         llvm::ConstantInt::get(NumElts->getType(), BaseEltSize);
    367     llvm::Value *SizeInBytes =
    368         CGF.Builder.CreateNUWMul(BaseEltSizeVal, NumElts);
    369     Address BC = CGF.Builder.CreateBitCast(DstAddr, CGF.CGM.Int8PtrTy);
    370     llvm::Value *DstArrayEnd =
    371         CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, BC.getPointer(), SizeInBytes);
    372     DstArrayEnd = CGF.Builder.CreateBitCast(DstArrayEnd, CGF.CGM.Int8PtrPtrTy,
    373                                             "dstarray.end");
    374     llvm::BasicBlock *PreheaderBB = CGF.Builder.GetInsertBlock();
    375 
    376     // Create the header block and insert the phi instructions.
    377     llvm::BasicBlock *HeaderBB = CGF.createBasicBlock("loop.header");
    378     CGF.EmitBlock(HeaderBB);
    379     llvm::PHINode *PHIs[N];
    380 
    381     for (unsigned I = 0; I < N; ++I) {
    382       PHIs[I] = CGF.Builder.CreatePHI(CGF.CGM.Int8PtrPtrTy, 2, "addr.cur");
    383       PHIs[I]->addIncoming(StartAddrs[I].getPointer(), PreheaderBB);
    384     }
    385 
    386     // Create the exit and loop body blocks.
    387     llvm::BasicBlock *ExitBB = CGF.createBasicBlock("loop.exit");
    388     llvm::BasicBlock *LoopBB = CGF.createBasicBlock("loop.body");
    389 
    390     // Emit the comparison and conditional branch instruction that jumps to
    391     // either the exit or the loop body.
    392     llvm::Value *Done =
    393         CGF.Builder.CreateICmpEQ(PHIs[DstIdx], DstArrayEnd, "done");
    394     CGF.Builder.CreateCondBr(Done, ExitBB, LoopBB);
    395 
    396     // Visit the element of the array in the loop body.
    397     CGF.EmitBlock(LoopBB);
    398     QualType EltQT = AT->getElementType();
    399     CharUnits EltSize = Ctx.getTypeSizeInChars(EltQT);
    400     std::array<Address, N> NewAddrs = Addrs;
    401 
    402     for (unsigned I = 0; I < N; ++I)
    403       NewAddrs[I] = Address(
    404           PHIs[I], 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.
    425   Address getAddrWithOffset(Address Addr, CharUnits Offset) {
    426     assert(Addr.isValid() && "invalid address");
    427     if (Offset.getQuantity() == 0)
    428       return Addr;
    429     Addr = CGF->Builder.CreateBitCast(Addr, CGF->CGM.Int8PtrTy);
    430     Addr = CGF->Builder.CreateConstInBoundsGEP(Addr, Offset.getQuantity());
    431     return CGF->Builder.CreateBitCast(Addr, CGF->CGM.Int8PtrPtrTy);
    432   }
    433 
    434   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>
    441   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     IdentifierInfo *II = &Ctx.Idents.get(FuncName);
    476     FunctionDecl *FD = FunctionDecl::Create(
    477         Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(),
    478         II, Ctx.getFunctionType(Ctx.VoidTy, llvm::None, {}), nullptr,
    479         SC_PrivateExtern, false, false);
    480     CodeGenFunction NewCGF(CGM);
    481     setCGF(&NewCGF);
    482     CGF->StartFunction(FD, Ctx.VoidTy, F, FI, Args);
    483     std::array<Address, N> Addrs =
    484         getParamAddrs<N>(std::make_index_sequence<N>{}, Alignments, Args, CGF);
    485     asDerived().visitStructFields(QT, CharUnits::Zero(), Addrs);
    486     CGF->FinishFunction();
    487     return F;
    488   }
    489 
    490   template <size_t N>
    491   void callFunc(StringRef FuncName, QualType QT, std::array<Address, N> Addrs,
    492                 CodeGenFunction &CallerCGF) {
    493     std::array<CharUnits, N> Alignments;
    494     llvm::Value *Ptrs[N];
    495 
    496     for (unsigned I = 0; I < N; ++I) {
    497       Alignments[I] = Addrs[I].getAlignment();
    498       Ptrs[I] =
    499           CallerCGF.Builder.CreateBitCast(Addrs[I], CallerCGF.CGM.Int8PtrPtrTy)
    500               .getPointer();
    501     }
    502 
    503     if (llvm::Function *F =
    504             getFunction(FuncName, QT, Alignments, CallerCGF.CGM))
    505       CallerCGF.EmitNounwindRuntimeCall(F, Ptrs);
    506   }
    507 
    508   Derived &asDerived() { return static_cast<Derived &>(*this); }
    509 
    510   void setCGF(CodeGenFunction *F) { CGF = F; }
    511 
    512   CodeGenFunction *CGF = nullptr;
    513 };
    514 
    515 template <class Derived, bool IsMove>
    516 struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>,
    517                        GenFuncBase<Derived> {
    518   GenBinaryFunc(ASTContext &Ctx) : CopyStructVisitor<Derived, IsMove>(Ctx) {}
    519 
    520   void flushTrivialFields(std::array<Address, 2> Addrs) {
    521     CharUnits Size = this->End - this->Start;
    522 
    523     if (Size.getQuantity() == 0)
    524       return;
    525 
    526     Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], this->Start);
    527     Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], this->Start);
    528 
    529     // Emit memcpy.
    530     if (Size.getQuantity() >= 16 || !llvm::isPowerOf2_32(Size.getQuantity())) {
    531       llvm::Value *SizeVal =
    532           llvm::ConstantInt::get(this->CGF->SizeTy, Size.getQuantity());
    533       DstAddr =
    534           this->CGF->Builder.CreateElementBitCast(DstAddr, this->CGF->Int8Ty);
    535       SrcAddr =
    536           this->CGF->Builder.CreateElementBitCast(SrcAddr, this->CGF->Int8Ty);
    537       this->CGF->Builder.CreateMemCpy(DstAddr, SrcAddr, SizeVal, false);
    538     } else {
    539       llvm::Type *Ty = llvm::Type::getIntNTy(
    540           this->CGF->getLLVMContext(),
    541           Size.getQuantity() * this->CGF->getContext().getCharWidth());
    542       DstAddr = this->CGF->Builder.CreateElementBitCast(DstAddr, Ty);
    543       SrcAddr = this->CGF->Builder.CreateElementBitCast(SrcAddr, Ty);
    544       llvm::Value *SrcVal = this->CGF->Builder.CreateLoad(SrcAddr, false);
    545       this->CGF->Builder.CreateStore(SrcVal, DstAddr, false);
    546     }
    547 
    548     this->Start = this->End = CharUnits::Zero();
    549   }
    550 
    551   template <class... Ts>
    552   void visitVolatileTrivial(QualType FT, const FieldDecl *FD, CharUnits Offset,
    553                             std::array<Address, 2> Addrs) {
    554     LValue DstLV, SrcLV;
    555     if (FD) {
    556       // No need to copy zero-length bit-fields.
    557       if (FD->isZeroLengthBitField(this->CGF->getContext()))
    558         return;
    559 
    560       QualType RT = QualType(FD->getParent()->getTypeForDecl(), 0);
    561       llvm::PointerType *PtrTy = this->CGF->ConvertType(RT)->getPointerTo();
    562       Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset);
    563       LValue DstBase = this->CGF->MakeAddrLValue(
    564           this->CGF->Builder.CreateBitCast(DstAddr, PtrTy), FT);
    565       DstLV = this->CGF->EmitLValueForField(DstBase, FD);
    566       Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], Offset);
    567       LValue SrcBase = this->CGF->MakeAddrLValue(
    568           this->CGF->Builder.CreateBitCast(SrcAddr, PtrTy), FT);
    569       SrcLV = this->CGF->EmitLValueForField(SrcBase, FD);
    570     } else {
    571       llvm::PointerType *Ty = this->CGF->ConvertTypeForMem(FT)->getPointerTo();
    572       Address DstAddr = this->CGF->Builder.CreateBitCast(Addrs[DstIdx], Ty);
    573       Address SrcAddr = this->CGF->Builder.CreateBitCast(Addrs[SrcIdx], Ty);
    574       DstLV = this->CGF->MakeAddrLValue(DstAddr, FT);
    575       SrcLV = this->CGF->MakeAddrLValue(SrcAddr, FT);
    576     }
    577     RValue SrcVal = this->CGF->EmitLoadOfLValue(SrcLV, SourceLocation());
    578     this->CGF->EmitStoreThroughLValue(SrcVal, DstLV);
    579   }
    580 };
    581 
    582 // These classes that emit the special functions for a non-trivial struct.
    583 struct GenDestructor : StructVisitor<GenDestructor>,
    584                        GenFuncBase<GenDestructor>,
    585                        DestructedTypeVisitor<GenDestructor> {
    586   using Super = DestructedTypeVisitor<GenDestructor>;
    587   GenDestructor(ASTContext &Ctx) : StructVisitor<GenDestructor>(Ctx) {}
    588 
    589   void visitWithKind(QualType::DestructionKind DK, QualType FT,
    590                      const FieldDecl *FD, CharUnits CurStructOffset,
    591                      std::array<Address, 1> Addrs) {
    592     if (const auto *AT = getContext().getAsArrayType(FT)) {
    593       visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset, Addrs);
    594       return;
    595     }
    596 
    597     Super::visitWithKind(DK, FT, FD, CurStructOffset, Addrs);
    598   }
    599 
    600   void visitARCStrong(QualType QT, const FieldDecl *FD,
    601                       CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
    602     CGF->destroyARCStrongImprecise(
    603         *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
    604   }
    605 
    606   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
    607                     std::array<Address, 1> Addrs) {
    608     CGF->destroyARCWeak(
    609         *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
    610   }
    611 
    612   void callSpecialFunction(QualType FT, CharUnits Offset,
    613                            std::array<Address, 1> Addrs) {
    614     CGF->callCStructDestructor(
    615         CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
    616   }
    617 };
    618 
    619 struct GenDefaultInitialize
    620     : StructVisitor<GenDefaultInitialize>,
    621       GenFuncBase<GenDefaultInitialize>,
    622       DefaultInitializedTypeVisitor<GenDefaultInitialize> {
    623   using Super = DefaultInitializedTypeVisitor<GenDefaultInitialize>;
    624   typedef GenFuncBase<GenDefaultInitialize> GenFuncBaseTy;
    625 
    626   GenDefaultInitialize(ASTContext &Ctx)
    627       : StructVisitor<GenDefaultInitialize>(Ctx) {}
    628 
    629   void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
    630                      const FieldDecl *FD, CharUnits CurStructOffset,
    631                      std::array<Address, 1> Addrs) {
    632     if (const auto *AT = getContext().getAsArrayType(FT)) {
    633       visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset,
    634                  Addrs);
    635       return;
    636     }
    637 
    638     Super::visitWithKind(PDIK, FT, FD, CurStructOffset, Addrs);
    639   }
    640 
    641   void visitARCStrong(QualType QT, const FieldDecl *FD,
    642                       CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
    643     CGF->EmitNullInitialization(
    644         getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
    645   }
    646 
    647   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
    648                     std::array<Address, 1> Addrs) {
    649     CGF->EmitNullInitialization(
    650         getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
    651   }
    652 
    653   template <class FieldKind, size_t... Is>
    654   void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
    655                   const FieldDecl *FD, CharUnits CurStructOffset,
    656                   std::array<Address, 1> Addrs) {
    657     if (!FK)
    658       return visitTrivial(QualType(AT, 0), FD, CurStructOffset, Addrs);
    659 
    660     ASTContext &Ctx = getContext();
    661     CharUnits Size = Ctx.getTypeSizeInChars(QualType(AT, 0));
    662     QualType EltTy = Ctx.getBaseElementType(QualType(AT, 0));
    663 
    664     if (Size < CharUnits::fromQuantity(16) || EltTy->getAs<RecordType>()) {
    665       GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStructOffset, Addrs);
    666       return;
    667     }
    668 
    669     llvm::Constant *SizeVal = CGF->Builder.getInt64(Size.getQuantity());
    670     Address DstAddr = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
    671     Address Loc = CGF->Builder.CreateElementBitCast(DstAddr, CGF->Int8Ty);
    672     CGF->Builder.CreateMemSet(Loc, CGF->Builder.getInt8(0), SizeVal,
    673                               IsVolatile);
    674   }
    675 
    676   void callSpecialFunction(QualType FT, CharUnits Offset,
    677                            std::array<Address, 1> Addrs) {
    678     CGF->callCStructDefaultConstructor(
    679         CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
    680   }
    681 };
    682 
    683 struct GenCopyConstructor : GenBinaryFunc<GenCopyConstructor, false> {
    684   GenCopyConstructor(ASTContext &Ctx)
    685       : GenBinaryFunc<GenCopyConstructor, false>(Ctx) {}
    686 
    687   void visitARCStrong(QualType QT, const FieldDecl *FD,
    688                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
    689     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
    690     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
    691     llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
    692         Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
    693     llvm::Value *Val = CGF->EmitARCRetain(QT, SrcVal);
    694     CGF->EmitStoreOfScalar(Val, CGF->MakeAddrLValue(Addrs[DstIdx], QT), true);
    695   }
    696 
    697   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
    698                     std::array<Address, 2> Addrs) {
    699     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
    700     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
    701     CGF->EmitARCCopyWeak(Addrs[DstIdx], Addrs[SrcIdx]);
    702   }
    703 
    704   void callSpecialFunction(QualType FT, CharUnits Offset,
    705                            std::array<Address, 2> Addrs) {
    706     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
    707     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
    708     CGF->callCStructCopyConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
    709                                     CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
    710   }
    711 };
    712 
    713 struct GenMoveConstructor : GenBinaryFunc<GenMoveConstructor, true> {
    714   GenMoveConstructor(ASTContext &Ctx)
    715       : GenBinaryFunc<GenMoveConstructor, true>(Ctx) {}
    716 
    717   void visitARCStrong(QualType QT, const FieldDecl *FD,
    718                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
    719     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
    720     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
    721     LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
    722     llvm::Value *SrcVal =
    723         CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
    724     CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress(*CGF)), SrcLV);
    725     CGF->EmitStoreOfScalar(SrcVal, CGF->MakeAddrLValue(Addrs[DstIdx], QT),
    726                            /* isInitialization */ true);
    727   }
    728 
    729   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
    730                     std::array<Address, 2> Addrs) {
    731     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
    732     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
    733     CGF->EmitARCMoveWeak(Addrs[DstIdx], Addrs[SrcIdx]);
    734   }
    735 
    736   void callSpecialFunction(QualType FT, CharUnits Offset,
    737                            std::array<Address, 2> Addrs) {
    738     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
    739     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
    740     CGF->callCStructMoveConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
    741                                     CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
    742   }
    743 };
    744 
    745 struct GenCopyAssignment : GenBinaryFunc<GenCopyAssignment, false> {
    746   GenCopyAssignment(ASTContext &Ctx)
    747       : GenBinaryFunc<GenCopyAssignment, false>(Ctx) {}
    748 
    749   void visitARCStrong(QualType QT, const FieldDecl *FD,
    750                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
    751     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
    752     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
    753     llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
    754         Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
    755     CGF->EmitARCStoreStrong(CGF->MakeAddrLValue(Addrs[DstIdx], QT), SrcVal,
    756                             false);
    757   }
    758 
    759   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
    760                     std::array<Address, 2> Addrs) {
    761     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
    762     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
    763     CGF->emitARCCopyAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
    764   }
    765 
    766   void callSpecialFunction(QualType FT, CharUnits Offset,
    767                            std::array<Address, 2> Addrs) {
    768     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
    769     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
    770     CGF->callCStructCopyAssignmentOperator(
    771         CGF->MakeAddrLValue(Addrs[DstIdx], FT),
    772         CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
    773   }
    774 };
    775 
    776 struct GenMoveAssignment : GenBinaryFunc<GenMoveAssignment, true> {
    777   GenMoveAssignment(ASTContext &Ctx)
    778       : GenBinaryFunc<GenMoveAssignment, true>(Ctx) {}
    779 
    780   void visitARCStrong(QualType QT, const FieldDecl *FD,
    781                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
    782     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
    783     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
    784     LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
    785     llvm::Value *SrcVal =
    786         CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
    787     CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress(*CGF)), SrcLV);
    788     LValue DstLV = CGF->MakeAddrLValue(Addrs[DstIdx], QT);
    789     llvm::Value *DstVal =
    790         CGF->EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
    791     CGF->EmitStoreOfScalar(SrcVal, DstLV);
    792     CGF->EmitARCRelease(DstVal, ARCImpreciseLifetime);
    793   }
    794 
    795   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
    796                     std::array<Address, 2> Addrs) {
    797     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
    798     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
    799     CGF->emitARCMoveAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
    800   }
    801 
    802   void callSpecialFunction(QualType FT, CharUnits Offset,
    803                            std::array<Address, 2> Addrs) {
    804     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
    805     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
    806     CGF->callCStructMoveAssignmentOperator(
    807         CGF->MakeAddrLValue(Addrs[DstIdx], FT),
    808         CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
    809   }
    810 };
    811 
    812 } // namespace
    813 
    814 void CodeGenFunction::destroyNonTrivialCStruct(CodeGenFunction &CGF,
    815                                                Address Addr, QualType Type) {
    816   CGF.callCStructDestructor(CGF.MakeAddrLValue(Addr, Type));
    817 }
    818 
    819 // Default-initialize a variable that is a non-trivial struct or an array of
    820 // such structure.
    821 void CodeGenFunction::defaultInitNonTrivialCStructVar(LValue Dst) {
    822   GenDefaultInitialize Gen(getContext());
    823   Address DstPtr =
    824       Builder.CreateBitCast(Dst.getAddress(*this), CGM.Int8PtrPtrTy);
    825   Gen.setCGF(this);
    826   QualType QT = Dst.getType();
    827   QT = Dst.isVolatile() ? QT.withVolatile() : QT;
    828   Gen.visit(QT, nullptr, CharUnits::Zero(), std::array<Address, 1>({{DstPtr}}));
    829 }
    830 
    831 template <class G, size_t N>
    832 static void callSpecialFunction(G &&Gen, StringRef FuncName, QualType QT,
    833                                 bool IsVolatile, CodeGenFunction &CGF,
    834                                 std::array<Address, N> Addrs) {
    835   auto SetArtificialLoc = ApplyDebugLocation::CreateArtificial(CGF);
    836   for (unsigned I = 0; I < N; ++I)
    837     Addrs[I] = CGF.Builder.CreateBitCast(Addrs[I], CGF.CGM.Int8PtrPtrTy);
    838   QT = IsVolatile ? QT.withVolatile() : QT;
    839   Gen.callFunc(FuncName, QT, Addrs, CGF);
    840 }
    841 
    842 template <class G, size_t N>
    843 static llvm::Function *
    844 getSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile,
    845                    std::array<CharUnits, N> Alignments, CodeGenModule &CGM) {
    846   QT = IsVolatile ? QT.withVolatile() : QT;
    847   // The following call requires an array of addresses as arguments, but doesn't
    848   // actually use them (it overwrites them with the addresses of the arguments
    849   // of the created function).
    850   return Gen.getFunction(FuncName, QT, Alignments, CGM);
    851 }
    852 
    853 // Functions to emit calls to the special functions of a non-trivial C struct.
    854 void CodeGenFunction::callCStructDefaultConstructor(LValue Dst) {
    855   bool IsVolatile = Dst.isVolatile();
    856   Address DstPtr = Dst.getAddress(*this);
    857   QualType QT = Dst.getType();
    858   GenDefaultInitializeFuncName GenName(DstPtr.getAlignment(), getContext());
    859   std::string FuncName = GenName.getName(QT, IsVolatile);
    860   callSpecialFunction(GenDefaultInitialize(getContext()), FuncName, QT,
    861                       IsVolatile, *this, std::array<Address, 1>({{DstPtr}}));
    862 }
    863 
    864 std::string CodeGenFunction::getNonTrivialCopyConstructorStr(
    865     QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx) {
    866   GenBinaryFuncName<false> GenName("", Alignment, Alignment, Ctx);
    867   return GenName.getName(QT, IsVolatile);
    868 }
    869 
    870 std::string CodeGenFunction::getNonTrivialDestructorStr(QualType QT,
    871                                                         CharUnits Alignment,
    872                                                         bool IsVolatile,
    873                                                         ASTContext &Ctx) {
    874   GenDestructorFuncName GenName("", Alignment, Ctx);
    875   return GenName.getName(QT, IsVolatile);
    876 }
    877 
    878 void CodeGenFunction::callCStructDestructor(LValue Dst) {
    879   bool IsVolatile = Dst.isVolatile();
    880   Address DstPtr = Dst.getAddress(*this);
    881   QualType QT = Dst.getType();
    882   GenDestructorFuncName GenName("__destructor_", DstPtr.getAlignment(),
    883                                 getContext());
    884   std::string FuncName = GenName.getName(QT, IsVolatile);
    885   callSpecialFunction(GenDestructor(getContext()), FuncName, QT, IsVolatile,
    886                       *this, std::array<Address, 1>({{DstPtr}}));
    887 }
    888 
    889 void CodeGenFunction::callCStructCopyConstructor(LValue Dst, LValue Src) {
    890   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
    891   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
    892   QualType QT = Dst.getType();
    893   GenBinaryFuncName<false> GenName("__copy_constructor_", DstPtr.getAlignment(),
    894                                    SrcPtr.getAlignment(), getContext());
    895   std::string FuncName = GenName.getName(QT, IsVolatile);
    896   callSpecialFunction(GenCopyConstructor(getContext()), FuncName, QT,
    897                       IsVolatile, *this,
    898                       std::array<Address, 2>({{DstPtr, SrcPtr}}));
    899 }
    900 
    901 void CodeGenFunction::callCStructCopyAssignmentOperator(LValue Dst, LValue Src
    902 
    903 ) {
    904   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
    905   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
    906   QualType QT = Dst.getType();
    907   GenBinaryFuncName<false> GenName("__copy_assignment_", DstPtr.getAlignment(),
    908                                    SrcPtr.getAlignment(), getContext());
    909   std::string FuncName = GenName.getName(QT, IsVolatile);
    910   callSpecialFunction(GenCopyAssignment(getContext()), FuncName, QT, IsVolatile,
    911                       *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
    912 }
    913 
    914 void CodeGenFunction::callCStructMoveConstructor(LValue Dst, LValue Src) {
    915   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
    916   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
    917   QualType QT = Dst.getType();
    918   GenBinaryFuncName<true> GenName("__move_constructor_", DstPtr.getAlignment(),
    919                                   SrcPtr.getAlignment(), getContext());
    920   std::string FuncName = GenName.getName(QT, IsVolatile);
    921   callSpecialFunction(GenMoveConstructor(getContext()), FuncName, QT,
    922                       IsVolatile, *this,
    923                       std::array<Address, 2>({{DstPtr, SrcPtr}}));
    924 }
    925 
    926 void CodeGenFunction::callCStructMoveAssignmentOperator(LValue Dst, LValue Src
    927 
    928 ) {
    929   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
    930   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
    931   QualType QT = Dst.getType();
    932   GenBinaryFuncName<true> GenName("__move_assignment_", DstPtr.getAlignment(),
    933                                   SrcPtr.getAlignment(), getContext());
    934   std::string FuncName = GenName.getName(QT, IsVolatile);
    935   callSpecialFunction(GenMoveAssignment(getContext()), FuncName, QT, IsVolatile,
    936                       *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
    937 }
    938 
    939 llvm::Function *clang::CodeGen::getNonTrivialCStructDefaultConstructor(
    940     CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
    941   ASTContext &Ctx = CGM.getContext();
    942   GenDefaultInitializeFuncName GenName(DstAlignment, Ctx);
    943   std::string FuncName = GenName.getName(QT, IsVolatile);
    944   return getSpecialFunction(GenDefaultInitialize(Ctx), FuncName, QT, IsVolatile,
    945                             std::array<CharUnits, 1>({{DstAlignment}}), CGM);
    946 }
    947 
    948 llvm::Function *clang::CodeGen::getNonTrivialCStructCopyConstructor(
    949     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
    950     bool IsVolatile, QualType QT) {
    951   ASTContext &Ctx = CGM.getContext();
    952   GenBinaryFuncName<false> GenName("__copy_constructor_", DstAlignment,
    953                                    SrcAlignment, Ctx);
    954   std::string FuncName = GenName.getName(QT, IsVolatile);
    955   return getSpecialFunction(
    956       GenCopyConstructor(Ctx), FuncName, QT, IsVolatile,
    957       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
    958 }
    959 
    960 llvm::Function *clang::CodeGen::getNonTrivialCStructMoveConstructor(
    961     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
    962     bool IsVolatile, QualType QT) {
    963   ASTContext &Ctx = CGM.getContext();
    964   GenBinaryFuncName<true> GenName("__move_constructor_", DstAlignment,
    965                                   SrcAlignment, Ctx);
    966   std::string FuncName = GenName.getName(QT, IsVolatile);
    967   return getSpecialFunction(
    968       GenMoveConstructor(Ctx), FuncName, QT, IsVolatile,
    969       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
    970 }
    971 
    972 llvm::Function *clang::CodeGen::getNonTrivialCStructCopyAssignmentOperator(
    973     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
    974     bool IsVolatile, QualType QT) {
    975   ASTContext &Ctx = CGM.getContext();
    976   GenBinaryFuncName<false> GenName("__copy_assignment_", DstAlignment,
    977                                    SrcAlignment, Ctx);
    978   std::string FuncName = GenName.getName(QT, IsVolatile);
    979   return getSpecialFunction(
    980       GenCopyAssignment(Ctx), FuncName, QT, IsVolatile,
    981       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
    982 }
    983 
    984 llvm::Function *clang::CodeGen::getNonTrivialCStructMoveAssignmentOperator(
    985     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
    986     bool IsVolatile, QualType QT) {
    987   ASTContext &Ctx = CGM.getContext();
    988   GenBinaryFuncName<true> GenName("__move_assignment_", DstAlignment,
    989                                   SrcAlignment, Ctx);
    990   std::string FuncName = GenName.getName(QT, IsVolatile);
    991   return getSpecialFunction(
    992       GenMoveAssignment(Ctx), FuncName, QT, IsVolatile,
    993       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
    994 }
    995 
    996 llvm::Function *clang::CodeGen::getNonTrivialCStructDestructor(
    997     CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
    998   ASTContext &Ctx = CGM.getContext();
    999   GenDestructorFuncName GenName("__destructor_", DstAlignment, Ctx);
   1000   std::string FuncName = GenName.getName(QT, IsVolatile);
   1001   return getSpecialFunction(GenDestructor(Ctx), FuncName, QT, IsVolatile,
   1002                             std::array<CharUnits, 1>({{DstAlignment}}), CGM);
   1003 }
   1004