xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/CGNonTrivialStruct.cpp (revision 0eae32dcef82f6f06de6419a0d623d7def0cc8f6)
10b57cec5SDimitry Andric //===--- CGNonTrivialStruct.cpp - Emit Special Functions for C Structs ----===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines functions to generate various special functions for C
100b57cec5SDimitry Andric // structs.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "CodeGenFunction.h"
150b57cec5SDimitry Andric #include "CodeGenModule.h"
160b57cec5SDimitry Andric #include "clang/AST/NonTrivialTypeVisitor.h"
170b57cec5SDimitry Andric #include "clang/CodeGen/CodeGenABITypes.h"
180b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
190b57cec5SDimitry Andric #include <array>
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric using namespace clang;
220b57cec5SDimitry Andric using namespace CodeGen;
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric // Return the size of a field in number of bits.
250b57cec5SDimitry Andric static uint64_t getFieldSize(const FieldDecl *FD, QualType FT,
260b57cec5SDimitry Andric                              ASTContext &Ctx) {
270b57cec5SDimitry Andric   if (FD && FD->isBitField())
280b57cec5SDimitry Andric     return FD->getBitWidthValue(Ctx);
290b57cec5SDimitry Andric   return Ctx.getTypeSize(FT);
300b57cec5SDimitry Andric }
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric namespace {
330b57cec5SDimitry Andric enum { DstIdx = 0, SrcIdx = 1 };
340b57cec5SDimitry Andric const char *ValNameStr[2] = {"dst", "src"};
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric template <class Derived> struct StructVisitor {
370b57cec5SDimitry Andric   StructVisitor(ASTContext &Ctx) : Ctx(Ctx) {}
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric   template <class... Ts>
400b57cec5SDimitry Andric   void visitStructFields(QualType QT, CharUnits CurStructOffset, Ts... Args) {
410b57cec5SDimitry Andric     const RecordDecl *RD = QT->castAs<RecordType>()->getDecl();
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric     // Iterate over the fields of the struct.
440b57cec5SDimitry Andric     for (const FieldDecl *FD : RD->fields()) {
450b57cec5SDimitry Andric       QualType FT = FD->getType();
460b57cec5SDimitry Andric       FT = QT.isVolatileQualified() ? FT.withVolatile() : FT;
470b57cec5SDimitry Andric       asDerived().visit(FT, FD, CurStructOffset, Args...);
480b57cec5SDimitry Andric     }
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric     asDerived().flushTrivialFields(Args...);
510b57cec5SDimitry Andric   }
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   template <class... Ts> void visitTrivial(Ts... Args) {}
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   template <class... Ts> void visitCXXDestructor(Ts... Args) {
560b57cec5SDimitry Andric     llvm_unreachable("field of a C++ struct type is not expected");
570b57cec5SDimitry Andric   }
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   template <class... Ts> void flushTrivialFields(Ts... Args) {}
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric   uint64_t getFieldOffsetInBits(const FieldDecl *FD) {
620b57cec5SDimitry Andric     return FD ? Ctx.getASTRecordLayout(FD->getParent())
630b57cec5SDimitry Andric                     .getFieldOffset(FD->getFieldIndex())
640b57cec5SDimitry Andric               : 0;
650b57cec5SDimitry Andric   }
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric   CharUnits getFieldOffset(const FieldDecl *FD) {
680b57cec5SDimitry Andric     return Ctx.toCharUnitsFromBits(getFieldOffsetInBits(FD));
690b57cec5SDimitry Andric   }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   Derived &asDerived() { return static_cast<Derived &>(*this); }
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   ASTContext &getContext() { return Ctx; }
740b57cec5SDimitry Andric   ASTContext &Ctx;
750b57cec5SDimitry Andric };
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric template <class Derived, bool IsMove>
780b57cec5SDimitry Andric struct CopyStructVisitor : StructVisitor<Derived>,
790b57cec5SDimitry Andric                            CopiedTypeVisitor<Derived, IsMove> {
800b57cec5SDimitry Andric   using StructVisitor<Derived>::asDerived;
810b57cec5SDimitry Andric   using Super = CopiedTypeVisitor<Derived, IsMove>;
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   CopyStructVisitor(ASTContext &Ctx) : StructVisitor<Derived>(Ctx) {}
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   template <class... Ts>
860b57cec5SDimitry Andric   void preVisit(QualType::PrimitiveCopyKind PCK, QualType FT,
870b57cec5SDimitry Andric                 const FieldDecl *FD, CharUnits CurStructOffset, Ts &&... Args) {
880b57cec5SDimitry Andric     if (PCK)
890b57cec5SDimitry Andric       asDerived().flushTrivialFields(std::forward<Ts>(Args)...);
900b57cec5SDimitry Andric   }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   template <class... Ts>
930b57cec5SDimitry Andric   void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT,
940b57cec5SDimitry Andric                      const FieldDecl *FD, CharUnits CurStructOffset,
950b57cec5SDimitry Andric                      Ts &&... Args) {
960b57cec5SDimitry Andric     if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
970b57cec5SDimitry Andric       asDerived().visitArray(PCK, AT, FT.isVolatileQualified(), FD,
980b57cec5SDimitry Andric                              CurStructOffset, std::forward<Ts>(Args)...);
990b57cec5SDimitry Andric       return;
1000b57cec5SDimitry Andric     }
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric     Super::visitWithKind(PCK, FT, FD, CurStructOffset,
1030b57cec5SDimitry Andric                          std::forward<Ts>(Args)...);
1040b57cec5SDimitry Andric   }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric   template <class... Ts>
1070b57cec5SDimitry Andric   void visitTrivial(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset,
1080b57cec5SDimitry Andric                     Ts... Args) {
1090b57cec5SDimitry Andric     assert(!FT.isVolatileQualified() && "volatile field not expected");
1100b57cec5SDimitry Andric     ASTContext &Ctx = asDerived().getContext();
1110b57cec5SDimitry Andric     uint64_t FieldSize = getFieldSize(FD, FT, Ctx);
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric     // Ignore zero-sized fields.
1140b57cec5SDimitry Andric     if (FieldSize == 0)
1150b57cec5SDimitry Andric       return;
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric     uint64_t FStartInBits = asDerived().getFieldOffsetInBits(FD);
1180b57cec5SDimitry Andric     uint64_t FEndInBits = FStartInBits + FieldSize;
1190b57cec5SDimitry Andric     uint64_t RoundedFEnd = llvm::alignTo(FEndInBits, Ctx.getCharWidth());
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric     // Set Start if this is the first field of a sequence of trivial fields.
1220b57cec5SDimitry Andric     if (Start == End)
1230b57cec5SDimitry Andric       Start = CurStructOffset + Ctx.toCharUnitsFromBits(FStartInBits);
1240b57cec5SDimitry Andric     End = CurStructOffset + Ctx.toCharUnitsFromBits(RoundedFEnd);
1250b57cec5SDimitry Andric   }
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   CharUnits Start = CharUnits::Zero(), End = CharUnits::Zero();
1280b57cec5SDimitry Andric };
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric // This function creates the mangled name of a special function of a non-trivial
1310b57cec5SDimitry Andric // C struct. Since there is no ODR in C, the function is mangled based on the
1320b57cec5SDimitry Andric // struct contents and not the name. The mangled name has the following
1330b57cec5SDimitry Andric // structure:
1340b57cec5SDimitry Andric //
1350b57cec5SDimitry Andric // <function-name> ::= <prefix> <alignment-info> "_" <struct-field-info>
1360b57cec5SDimitry Andric // <prefix> ::= "__destructor_" | "__default_constructor_" |
1370b57cec5SDimitry Andric //              "__copy_constructor_" | "__move_constructor_" |
1380b57cec5SDimitry Andric //              "__copy_assignment_" | "__move_assignment_"
1390b57cec5SDimitry Andric // <alignment-info> ::= <dst-alignment> ["_" <src-alignment>]
1400b57cec5SDimitry Andric // <struct-field-info> ::= <field-info>+
1410b57cec5SDimitry Andric // <field-info> ::= <struct-or-scalar-field-info> | <array-field-info>
1420b57cec5SDimitry Andric // <struct-or-scalar-field-info> ::= "_S" <struct-field-info> |
1430b57cec5SDimitry Andric //                                   <strong-field-info> | <trivial-field-info>
1440b57cec5SDimitry Andric // <array-field-info> ::= "_AB" <array-offset> "s" <element-size> "n"
1450b57cec5SDimitry Andric //                        <num-elements> <innermost-element-info> "_AE"
1460b57cec5SDimitry Andric // <innermost-element-info> ::= <struct-or-scalar-field-info>
1470b57cec5SDimitry Andric // <strong-field-info> ::= "_s" ["b"] ["v"] <field-offset>
1480b57cec5SDimitry Andric // <trivial-field-info> ::= "_t" ["v"] <field-offset> "_" <field-size>
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric template <class Derived> struct GenFuncNameBase {
1510b57cec5SDimitry Andric   std::string getVolatileOffsetStr(bool IsVolatile, CharUnits Offset) {
1520b57cec5SDimitry Andric     std::string S;
1530b57cec5SDimitry Andric     if (IsVolatile)
1540b57cec5SDimitry Andric       S = "v";
1550b57cec5SDimitry Andric     S += llvm::to_string(Offset.getQuantity());
1560b57cec5SDimitry Andric     return S;
1570b57cec5SDimitry Andric   }
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric   void visitARCStrong(QualType FT, const FieldDecl *FD,
1600b57cec5SDimitry Andric                       CharUnits CurStructOffset) {
1610b57cec5SDimitry Andric     appendStr("_s");
1620b57cec5SDimitry Andric     if (FT->isBlockPointerType())
1630b57cec5SDimitry Andric       appendStr("b");
1640b57cec5SDimitry Andric     CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
1650b57cec5SDimitry Andric     appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset));
1660b57cec5SDimitry Andric   }
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   void visitARCWeak(QualType FT, const FieldDecl *FD,
1690b57cec5SDimitry Andric                     CharUnits CurStructOffset) {
1700b57cec5SDimitry Andric     appendStr("_w");
1710b57cec5SDimitry Andric     CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
1720b57cec5SDimitry Andric     appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset));
1730b57cec5SDimitry Andric   }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   void visitStruct(QualType QT, const FieldDecl *FD,
1760b57cec5SDimitry Andric                    CharUnits CurStructOffset) {
1770b57cec5SDimitry Andric     CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
1780b57cec5SDimitry Andric     appendStr("_S");
1790b57cec5SDimitry Andric     asDerived().visitStructFields(QT, FieldOffset);
1800b57cec5SDimitry Andric   }
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   template <class FieldKind>
1830b57cec5SDimitry Andric   void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
1840b57cec5SDimitry Andric                   const FieldDecl *FD, CharUnits CurStructOffset) {
1850b57cec5SDimitry Andric     // String for non-volatile trivial fields is emitted when
1860b57cec5SDimitry Andric     // flushTrivialFields is called.
1870b57cec5SDimitry Andric     if (!FK)
1880b57cec5SDimitry Andric       return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset);
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric     asDerived().flushTrivialFields();
1910b57cec5SDimitry Andric     CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
1920b57cec5SDimitry Andric     ASTContext &Ctx = asDerived().getContext();
1930b57cec5SDimitry Andric     const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
1940b57cec5SDimitry Andric     unsigned NumElts = Ctx.getConstantArrayElementCount(CAT);
1950b57cec5SDimitry Andric     QualType EltTy = Ctx.getBaseElementType(CAT);
1960b57cec5SDimitry Andric     CharUnits EltSize = Ctx.getTypeSizeInChars(EltTy);
1970b57cec5SDimitry Andric     appendStr("_AB" + llvm::to_string(FieldOffset.getQuantity()) + "s" +
1980b57cec5SDimitry Andric               llvm::to_string(EltSize.getQuantity()) + "n" +
1990b57cec5SDimitry Andric               llvm::to_string(NumElts));
2000b57cec5SDimitry Andric     EltTy = IsVolatile ? EltTy.withVolatile() : EltTy;
2010b57cec5SDimitry Andric     asDerived().visitWithKind(FK, EltTy, nullptr, FieldOffset);
2020b57cec5SDimitry Andric     appendStr("_AE");
2030b57cec5SDimitry Andric   }
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric   void appendStr(StringRef Str) { Name += Str; }
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   std::string getName(QualType QT, bool IsVolatile) {
2080b57cec5SDimitry Andric     QT = IsVolatile ? QT.withVolatile() : QT;
2090b57cec5SDimitry Andric     asDerived().visitStructFields(QT, CharUnits::Zero());
2100b57cec5SDimitry Andric     return Name;
2110b57cec5SDimitry Andric   }
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   Derived &asDerived() { return static_cast<Derived &>(*this); }
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   std::string Name;
2160b57cec5SDimitry Andric };
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric template <class Derived>
2190b57cec5SDimitry Andric struct GenUnaryFuncName : StructVisitor<Derived>, GenFuncNameBase<Derived> {
2200b57cec5SDimitry Andric   GenUnaryFuncName(StringRef Prefix, CharUnits DstAlignment, ASTContext &Ctx)
2210b57cec5SDimitry Andric       : StructVisitor<Derived>(Ctx) {
2220b57cec5SDimitry Andric     this->appendStr(Prefix);
2230b57cec5SDimitry Andric     this->appendStr(llvm::to_string(DstAlignment.getQuantity()));
2240b57cec5SDimitry Andric   }
2250b57cec5SDimitry Andric };
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric // Helper function to create a null constant.
2280b57cec5SDimitry Andric static llvm::Constant *getNullForVariable(Address Addr) {
2290b57cec5SDimitry Andric   llvm::Type *Ty = Addr.getElementType();
2300b57cec5SDimitry Andric   return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(Ty));
2310b57cec5SDimitry Andric }
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric template <bool IsMove>
2340b57cec5SDimitry Andric struct GenBinaryFuncName : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>,
2350b57cec5SDimitry Andric                            GenFuncNameBase<GenBinaryFuncName<IsMove>> {
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric   GenBinaryFuncName(StringRef Prefix, CharUnits DstAlignment,
2380b57cec5SDimitry Andric                     CharUnits SrcAlignment, ASTContext &Ctx)
2390b57cec5SDimitry Andric       : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>(Ctx) {
2400b57cec5SDimitry Andric     this->appendStr(Prefix);
2410b57cec5SDimitry Andric     this->appendStr(llvm::to_string(DstAlignment.getQuantity()));
2420b57cec5SDimitry Andric     this->appendStr("_" + llvm::to_string(SrcAlignment.getQuantity()));
2430b57cec5SDimitry Andric   }
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric   void flushTrivialFields() {
2460b57cec5SDimitry Andric     if (this->Start == this->End)
2470b57cec5SDimitry Andric       return;
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric     this->appendStr("_t" + llvm::to_string(this->Start.getQuantity()) + "w" +
2500b57cec5SDimitry Andric                     llvm::to_string((this->End - this->Start).getQuantity()));
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric     this->Start = this->End = CharUnits::Zero();
2530b57cec5SDimitry Andric   }
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   void visitVolatileTrivial(QualType FT, const FieldDecl *FD,
2560b57cec5SDimitry Andric                             CharUnits CurStructOffset) {
2575ffd83dbSDimitry Andric     // Zero-length bit-fields don't need to be copied/assigned.
2585ffd83dbSDimitry Andric     if (FD && FD->isZeroLengthBitField(this->Ctx))
2595ffd83dbSDimitry Andric       return;
2605ffd83dbSDimitry Andric 
2610b57cec5SDimitry Andric     // Because volatile fields can be bit-fields and are individually copied,
2620b57cec5SDimitry Andric     // their offset and width are in bits.
2630b57cec5SDimitry Andric     uint64_t OffsetInBits =
2640b57cec5SDimitry Andric         this->Ctx.toBits(CurStructOffset) + this->getFieldOffsetInBits(FD);
2650b57cec5SDimitry Andric     this->appendStr("_tv" + llvm::to_string(OffsetInBits) + "w" +
2660b57cec5SDimitry Andric                     llvm::to_string(getFieldSize(FD, FT, this->Ctx)));
2670b57cec5SDimitry Andric   }
2680b57cec5SDimitry Andric };
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric struct GenDefaultInitializeFuncName
2710b57cec5SDimitry Andric     : GenUnaryFuncName<GenDefaultInitializeFuncName>,
2720b57cec5SDimitry Andric       DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName> {
2730b57cec5SDimitry Andric   using Super = DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName>;
2740b57cec5SDimitry Andric   GenDefaultInitializeFuncName(CharUnits DstAlignment, ASTContext &Ctx)
2750b57cec5SDimitry Andric       : GenUnaryFuncName<GenDefaultInitializeFuncName>("__default_constructor_",
2760b57cec5SDimitry Andric                                                        DstAlignment, Ctx) {}
2770b57cec5SDimitry Andric   void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
2780b57cec5SDimitry Andric                      const FieldDecl *FD, CharUnits CurStructOffset) {
2790b57cec5SDimitry Andric     if (const auto *AT = getContext().getAsArrayType(FT)) {
2800b57cec5SDimitry Andric       visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset);
2810b57cec5SDimitry Andric       return;
2820b57cec5SDimitry Andric     }
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric     Super::visitWithKind(PDIK, FT, FD, CurStructOffset);
2850b57cec5SDimitry Andric   }
2860b57cec5SDimitry Andric };
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric struct GenDestructorFuncName : GenUnaryFuncName<GenDestructorFuncName>,
2890b57cec5SDimitry Andric                                DestructedTypeVisitor<GenDestructorFuncName> {
2900b57cec5SDimitry Andric   using Super = DestructedTypeVisitor<GenDestructorFuncName>;
2910b57cec5SDimitry Andric   GenDestructorFuncName(const char *Prefix, CharUnits DstAlignment,
2920b57cec5SDimitry Andric                         ASTContext &Ctx)
2930b57cec5SDimitry Andric       : GenUnaryFuncName<GenDestructorFuncName>(Prefix, DstAlignment, Ctx) {}
2940b57cec5SDimitry Andric   void visitWithKind(QualType::DestructionKind DK, QualType FT,
2950b57cec5SDimitry Andric                      const FieldDecl *FD, CharUnits CurStructOffset) {
2960b57cec5SDimitry Andric     if (const auto *AT = getContext().getAsArrayType(FT)) {
2970b57cec5SDimitry Andric       visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset);
2980b57cec5SDimitry Andric       return;
2990b57cec5SDimitry Andric     }
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric     Super::visitWithKind(DK, FT, FD, CurStructOffset);
3020b57cec5SDimitry Andric   }
3030b57cec5SDimitry Andric };
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric // Helper function that creates CGFunctionInfo for an N-ary special function.
3060b57cec5SDimitry Andric template <size_t N>
3070b57cec5SDimitry Andric static const CGFunctionInfo &getFunctionInfo(CodeGenModule &CGM,
3080b57cec5SDimitry Andric                                              FunctionArgList &Args) {
3090b57cec5SDimitry Andric   ASTContext &Ctx = CGM.getContext();
3100b57cec5SDimitry Andric   llvm::SmallVector<ImplicitParamDecl *, N> Params;
3110b57cec5SDimitry Andric   QualType ParamTy = Ctx.getPointerType(Ctx.VoidPtrTy);
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric   for (unsigned I = 0; I < N; ++I)
3140b57cec5SDimitry Andric     Params.push_back(ImplicitParamDecl::Create(
3150b57cec5SDimitry Andric         Ctx, nullptr, SourceLocation(), &Ctx.Idents.get(ValNameStr[I]), ParamTy,
3160b57cec5SDimitry Andric         ImplicitParamDecl::Other));
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric   for (auto &P : Params)
3190b57cec5SDimitry Andric     Args.push_back(P);
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric   return CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args);
3220b57cec5SDimitry Andric }
3230b57cec5SDimitry Andric 
3245ffd83dbSDimitry Andric template <size_t N, size_t... Ints>
3255ffd83dbSDimitry Andric static std::array<Address, N> getParamAddrs(std::index_sequence<Ints...> IntSeq,
3265ffd83dbSDimitry Andric                                             std::array<CharUnits, N> Alignments,
3275ffd83dbSDimitry Andric                                             FunctionArgList Args,
3285ffd83dbSDimitry Andric                                             CodeGenFunction *CGF) {
3295ffd83dbSDimitry Andric   return std::array<Address, N>{{
3305ffd83dbSDimitry Andric       Address(CGF->Builder.CreateLoad(CGF->GetAddrOfLocalVar(Args[Ints])),
3315ffd83dbSDimitry Andric               Alignments[Ints])...}};
3325ffd83dbSDimitry Andric }
3335ffd83dbSDimitry Andric 
3340b57cec5SDimitry Andric // Template classes that are used as bases for classes that emit special
3350b57cec5SDimitry Andric // functions.
3360b57cec5SDimitry Andric template <class Derived> struct GenFuncBase {
3370b57cec5SDimitry Andric   template <size_t N>
3380b57cec5SDimitry Andric   void visitStruct(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset,
3390b57cec5SDimitry Andric                    std::array<Address, N> Addrs) {
3400b57cec5SDimitry Andric     this->asDerived().callSpecialFunction(
3410b57cec5SDimitry Andric         FT, CurStructOffset + asDerived().getFieldOffset(FD), Addrs);
3420b57cec5SDimitry Andric   }
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric   template <class FieldKind, size_t N>
3450b57cec5SDimitry Andric   void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
3460b57cec5SDimitry Andric                   const FieldDecl *FD, CharUnits CurStructOffset,
3470b57cec5SDimitry Andric                   std::array<Address, N> Addrs) {
3480b57cec5SDimitry Andric     // Non-volatile trivial fields are copied when flushTrivialFields is called.
3490b57cec5SDimitry Andric     if (!FK)
3500b57cec5SDimitry Andric       return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset,
3510b57cec5SDimitry Andric                                       Addrs);
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric     asDerived().flushTrivialFields(Addrs);
3540b57cec5SDimitry Andric     CodeGenFunction &CGF = *this->CGF;
3550b57cec5SDimitry Andric     ASTContext &Ctx = CGF.getContext();
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric     // Compute the end address.
3580b57cec5SDimitry Andric     QualType BaseEltQT;
3590b57cec5SDimitry Andric     std::array<Address, N> StartAddrs = Addrs;
3600b57cec5SDimitry Andric     for (unsigned I = 0; I < N; ++I)
3610b57cec5SDimitry Andric       StartAddrs[I] = getAddrWithOffset(Addrs[I], CurStructOffset, FD);
3620b57cec5SDimitry Andric     Address DstAddr = StartAddrs[DstIdx];
3630b57cec5SDimitry Andric     llvm::Value *NumElts = CGF.emitArrayLength(AT, BaseEltQT, DstAddr);
3640b57cec5SDimitry Andric     unsigned BaseEltSize = Ctx.getTypeSizeInChars(BaseEltQT).getQuantity();
3650b57cec5SDimitry Andric     llvm::Value *BaseEltSizeVal =
3660b57cec5SDimitry Andric         llvm::ConstantInt::get(NumElts->getType(), BaseEltSize);
3670b57cec5SDimitry Andric     llvm::Value *SizeInBytes =
3680b57cec5SDimitry Andric         CGF.Builder.CreateNUWMul(BaseEltSizeVal, NumElts);
369*0eae32dcSDimitry Andric     Address BC = CGF.Builder.CreateElementBitCast(DstAddr, CGF.CGM.Int8Ty);
3700b57cec5SDimitry Andric     llvm::Value *DstArrayEnd =
371fe6060f1SDimitry Andric         CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, BC.getPointer(), SizeInBytes);
372*0eae32dcSDimitry Andric     DstArrayEnd = CGF.Builder.CreateBitCast(
373*0eae32dcSDimitry Andric         DstArrayEnd, CGF.CGM.Int8PtrPtrTy, "dstarray.end");
3740b57cec5SDimitry Andric     llvm::BasicBlock *PreheaderBB = CGF.Builder.GetInsertBlock();
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric     // Create the header block and insert the phi instructions.
3770b57cec5SDimitry Andric     llvm::BasicBlock *HeaderBB = CGF.createBasicBlock("loop.header");
3780b57cec5SDimitry Andric     CGF.EmitBlock(HeaderBB);
3790b57cec5SDimitry Andric     llvm::PHINode *PHIs[N];
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric     for (unsigned I = 0; I < N; ++I) {
3820b57cec5SDimitry Andric       PHIs[I] = CGF.Builder.CreatePHI(CGF.CGM.Int8PtrPtrTy, 2, "addr.cur");
3830b57cec5SDimitry Andric       PHIs[I]->addIncoming(StartAddrs[I].getPointer(), PreheaderBB);
3840b57cec5SDimitry Andric     }
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric     // Create the exit and loop body blocks.
3870b57cec5SDimitry Andric     llvm::BasicBlock *ExitBB = CGF.createBasicBlock("loop.exit");
3880b57cec5SDimitry Andric     llvm::BasicBlock *LoopBB = CGF.createBasicBlock("loop.body");
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric     // Emit the comparison and conditional branch instruction that jumps to
3910b57cec5SDimitry Andric     // either the exit or the loop body.
3920b57cec5SDimitry Andric     llvm::Value *Done =
3930b57cec5SDimitry Andric         CGF.Builder.CreateICmpEQ(PHIs[DstIdx], DstArrayEnd, "done");
3940b57cec5SDimitry Andric     CGF.Builder.CreateCondBr(Done, ExitBB, LoopBB);
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric     // Visit the element of the array in the loop body.
3970b57cec5SDimitry Andric     CGF.EmitBlock(LoopBB);
3980b57cec5SDimitry Andric     QualType EltQT = AT->getElementType();
3990b57cec5SDimitry Andric     CharUnits EltSize = Ctx.getTypeSizeInChars(EltQT);
4000b57cec5SDimitry Andric     std::array<Address, N> NewAddrs = Addrs;
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric     for (unsigned I = 0; I < N; ++I)
4030b57cec5SDimitry Andric       NewAddrs[I] = Address(
4040b57cec5SDimitry Andric           PHIs[I], StartAddrs[I].getAlignment().alignmentAtOffset(EltSize));
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric     EltQT = IsVolatile ? EltQT.withVolatile() : EltQT;
4070b57cec5SDimitry Andric     this->asDerived().visitWithKind(FK, EltQT, nullptr, CharUnits::Zero(),
4080b57cec5SDimitry Andric                                     NewAddrs);
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric     LoopBB = CGF.Builder.GetInsertBlock();
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric     for (unsigned I = 0; I < N; ++I) {
4130b57cec5SDimitry Andric       // Instrs to update the destination and source addresses.
4140b57cec5SDimitry Andric       // Update phi instructions.
4150b57cec5SDimitry Andric       NewAddrs[I] = getAddrWithOffset(NewAddrs[I], EltSize);
4160b57cec5SDimitry Andric       PHIs[I]->addIncoming(NewAddrs[I].getPointer(), LoopBB);
4170b57cec5SDimitry Andric     }
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric     // Insert an unconditional branch to the header block.
4200b57cec5SDimitry Andric     CGF.Builder.CreateBr(HeaderBB);
4210b57cec5SDimitry Andric     CGF.EmitBlock(ExitBB);
4220b57cec5SDimitry Andric   }
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric   /// Return an address with the specified offset from the passed address.
4250b57cec5SDimitry Andric   Address getAddrWithOffset(Address Addr, CharUnits Offset) {
4260b57cec5SDimitry Andric     assert(Addr.isValid() && "invalid address");
4270b57cec5SDimitry Andric     if (Offset.getQuantity() == 0)
4280b57cec5SDimitry Andric       return Addr;
429*0eae32dcSDimitry Andric     Addr = CGF->Builder.CreateElementBitCast(Addr, CGF->CGM.Int8Ty);
4300b57cec5SDimitry Andric     Addr = CGF->Builder.CreateConstInBoundsGEP(Addr, Offset.getQuantity());
431*0eae32dcSDimitry Andric     return CGF->Builder.CreateElementBitCast(Addr, CGF->CGM.Int8PtrTy);
4320b57cec5SDimitry Andric   }
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric   Address getAddrWithOffset(Address Addr, CharUnits StructFieldOffset,
4350b57cec5SDimitry Andric                             const FieldDecl *FD) {
4360b57cec5SDimitry Andric     return getAddrWithOffset(Addr, StructFieldOffset +
4370b57cec5SDimitry Andric                                        asDerived().getFieldOffset(FD));
4380b57cec5SDimitry Andric   }
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric   template <size_t N>
4415ffd83dbSDimitry Andric   llvm::Function *getFunction(StringRef FuncName, QualType QT,
4425ffd83dbSDimitry Andric                               std::array<CharUnits, N> Alignments,
4435ffd83dbSDimitry Andric                               CodeGenModule &CGM) {
4440b57cec5SDimitry Andric     // If the special function already exists in the module, return it.
4450b57cec5SDimitry Andric     if (llvm::Function *F = CGM.getModule().getFunction(FuncName)) {
4460b57cec5SDimitry Andric       bool WrongType = false;
4470b57cec5SDimitry Andric       if (!F->getReturnType()->isVoidTy())
4480b57cec5SDimitry Andric         WrongType = true;
4490b57cec5SDimitry Andric       else {
4500b57cec5SDimitry Andric         for (const llvm::Argument &Arg : F->args())
4510b57cec5SDimitry Andric           if (Arg.getType() != CGM.Int8PtrPtrTy)
4520b57cec5SDimitry Andric             WrongType = true;
4530b57cec5SDimitry Andric       }
4540b57cec5SDimitry Andric 
4550b57cec5SDimitry Andric       if (WrongType) {
4565ffd83dbSDimitry Andric         std::string FuncName = std::string(F->getName());
4570b57cec5SDimitry Andric         SourceLocation Loc = QT->castAs<RecordType>()->getDecl()->getLocation();
4580b57cec5SDimitry Andric         CGM.Error(Loc, "special function " + FuncName +
4590b57cec5SDimitry Andric                            " for non-trivial C struct has incorrect type");
4600b57cec5SDimitry Andric         return nullptr;
4610b57cec5SDimitry Andric       }
4620b57cec5SDimitry Andric       return F;
4630b57cec5SDimitry Andric     }
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric     ASTContext &Ctx = CGM.getContext();
4660b57cec5SDimitry Andric     FunctionArgList Args;
4670b57cec5SDimitry Andric     const CGFunctionInfo &FI = getFunctionInfo<N>(CGM, Args);
4680b57cec5SDimitry Andric     llvm::FunctionType *FuncTy = CGM.getTypes().GetFunctionType(FI);
4690b57cec5SDimitry Andric     llvm::Function *F =
4700b57cec5SDimitry Andric         llvm::Function::Create(FuncTy, llvm::GlobalValue::LinkOnceODRLinkage,
4710b57cec5SDimitry Andric                                FuncName, &CGM.getModule());
4720b57cec5SDimitry Andric     F->setVisibility(llvm::GlobalValue::HiddenVisibility);
473fe6060f1SDimitry Andric     CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F, /*IsThunk=*/false);
4740b57cec5SDimitry Andric     CGM.SetLLVMFunctionAttributesForDefinition(nullptr, F);
4750b57cec5SDimitry Andric     CodeGenFunction NewCGF(CGM);
4760b57cec5SDimitry Andric     setCGF(&NewCGF);
477fe6060f1SDimitry Andric     CGF->StartFunction(GlobalDecl(), Ctx.VoidTy, F, FI, Args);
478fe6060f1SDimitry Andric     auto AL = ApplyDebugLocation::CreateArtificial(*CGF);
4795ffd83dbSDimitry Andric     std::array<Address, N> Addrs =
4805ffd83dbSDimitry Andric         getParamAddrs<N>(std::make_index_sequence<N>{}, Alignments, Args, CGF);
4810b57cec5SDimitry Andric     asDerived().visitStructFields(QT, CharUnits::Zero(), Addrs);
4820b57cec5SDimitry Andric     CGF->FinishFunction();
4830b57cec5SDimitry Andric     return F;
4840b57cec5SDimitry Andric   }
4850b57cec5SDimitry Andric 
4860b57cec5SDimitry Andric   template <size_t N>
4870b57cec5SDimitry Andric   void callFunc(StringRef FuncName, QualType QT, std::array<Address, N> Addrs,
4880b57cec5SDimitry Andric                 CodeGenFunction &CallerCGF) {
4890b57cec5SDimitry Andric     std::array<CharUnits, N> Alignments;
4900b57cec5SDimitry Andric     llvm::Value *Ptrs[N];
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric     for (unsigned I = 0; I < N; ++I) {
4930b57cec5SDimitry Andric       Alignments[I] = Addrs[I].getAlignment();
494*0eae32dcSDimitry Andric       Ptrs[I] = CallerCGF.Builder.CreateElementBitCast(
495*0eae32dcSDimitry Andric           Addrs[I], CallerCGF.CGM.Int8PtrTy).getPointer();
4960b57cec5SDimitry Andric     }
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric     if (llvm::Function *F =
4995ffd83dbSDimitry Andric             getFunction(FuncName, QT, Alignments, CallerCGF.CGM))
5000b57cec5SDimitry Andric       CallerCGF.EmitNounwindRuntimeCall(F, Ptrs);
5010b57cec5SDimitry Andric   }
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric   Derived &asDerived() { return static_cast<Derived &>(*this); }
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric   void setCGF(CodeGenFunction *F) { CGF = F; }
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric   CodeGenFunction *CGF = nullptr;
5080b57cec5SDimitry Andric };
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric template <class Derived, bool IsMove>
5110b57cec5SDimitry Andric struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>,
5120b57cec5SDimitry Andric                        GenFuncBase<Derived> {
5130b57cec5SDimitry Andric   GenBinaryFunc(ASTContext &Ctx) : CopyStructVisitor<Derived, IsMove>(Ctx) {}
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric   void flushTrivialFields(std::array<Address, 2> Addrs) {
5160b57cec5SDimitry Andric     CharUnits Size = this->End - this->Start;
5170b57cec5SDimitry Andric 
5180b57cec5SDimitry Andric     if (Size.getQuantity() == 0)
5190b57cec5SDimitry Andric       return;
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric     Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], this->Start);
5220b57cec5SDimitry Andric     Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], this->Start);
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric     // Emit memcpy.
5250b57cec5SDimitry Andric     if (Size.getQuantity() >= 16 || !llvm::isPowerOf2_32(Size.getQuantity())) {
5260b57cec5SDimitry Andric       llvm::Value *SizeVal =
5270b57cec5SDimitry Andric           llvm::ConstantInt::get(this->CGF->SizeTy, Size.getQuantity());
5280b57cec5SDimitry Andric       DstAddr =
5290b57cec5SDimitry Andric           this->CGF->Builder.CreateElementBitCast(DstAddr, this->CGF->Int8Ty);
5300b57cec5SDimitry Andric       SrcAddr =
5310b57cec5SDimitry Andric           this->CGF->Builder.CreateElementBitCast(SrcAddr, this->CGF->Int8Ty);
5320b57cec5SDimitry Andric       this->CGF->Builder.CreateMemCpy(DstAddr, SrcAddr, SizeVal, false);
5330b57cec5SDimitry Andric     } else {
5340b57cec5SDimitry Andric       llvm::Type *Ty = llvm::Type::getIntNTy(
5350b57cec5SDimitry Andric           this->CGF->getLLVMContext(),
5360b57cec5SDimitry Andric           Size.getQuantity() * this->CGF->getContext().getCharWidth());
5370b57cec5SDimitry Andric       DstAddr = this->CGF->Builder.CreateElementBitCast(DstAddr, Ty);
5380b57cec5SDimitry Andric       SrcAddr = this->CGF->Builder.CreateElementBitCast(SrcAddr, Ty);
5390b57cec5SDimitry Andric       llvm::Value *SrcVal = this->CGF->Builder.CreateLoad(SrcAddr, false);
5400b57cec5SDimitry Andric       this->CGF->Builder.CreateStore(SrcVal, DstAddr, false);
5410b57cec5SDimitry Andric     }
5420b57cec5SDimitry Andric 
5430b57cec5SDimitry Andric     this->Start = this->End = CharUnits::Zero();
5440b57cec5SDimitry Andric   }
5450b57cec5SDimitry Andric 
5460b57cec5SDimitry Andric   template <class... Ts>
5470b57cec5SDimitry Andric   void visitVolatileTrivial(QualType FT, const FieldDecl *FD, CharUnits Offset,
5480b57cec5SDimitry Andric                             std::array<Address, 2> Addrs) {
5490b57cec5SDimitry Andric     LValue DstLV, SrcLV;
5500b57cec5SDimitry Andric     if (FD) {
5515ffd83dbSDimitry Andric       // No need to copy zero-length bit-fields.
5525ffd83dbSDimitry Andric       if (FD->isZeroLengthBitField(this->CGF->getContext()))
5535ffd83dbSDimitry Andric         return;
5545ffd83dbSDimitry Andric 
5550b57cec5SDimitry Andric       QualType RT = QualType(FD->getParent()->getTypeForDecl(), 0);
556*0eae32dcSDimitry Andric       llvm::Type *Ty = this->CGF->ConvertType(RT);
5570b57cec5SDimitry Andric       Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset);
5580b57cec5SDimitry Andric       LValue DstBase = this->CGF->MakeAddrLValue(
559*0eae32dcSDimitry Andric           this->CGF->Builder.CreateElementBitCast(DstAddr, Ty), FT);
5600b57cec5SDimitry Andric       DstLV = this->CGF->EmitLValueForField(DstBase, FD);
5610b57cec5SDimitry Andric       Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], Offset);
5620b57cec5SDimitry Andric       LValue SrcBase = this->CGF->MakeAddrLValue(
563*0eae32dcSDimitry Andric           this->CGF->Builder.CreateElementBitCast(SrcAddr, Ty), FT);
5640b57cec5SDimitry Andric       SrcLV = this->CGF->EmitLValueForField(SrcBase, FD);
5650b57cec5SDimitry Andric     } else {
566*0eae32dcSDimitry Andric       llvm::Type *Ty = this->CGF->ConvertTypeForMem(FT);
567*0eae32dcSDimitry Andric       Address DstAddr =
568*0eae32dcSDimitry Andric           this->CGF->Builder.CreateElementBitCast(Addrs[DstIdx], Ty);
569*0eae32dcSDimitry Andric       Address SrcAddr =
570*0eae32dcSDimitry Andric           this->CGF->Builder.CreateElementBitCast(Addrs[SrcIdx], Ty);
5710b57cec5SDimitry Andric       DstLV = this->CGF->MakeAddrLValue(DstAddr, FT);
5720b57cec5SDimitry Andric       SrcLV = this->CGF->MakeAddrLValue(SrcAddr, FT);
5730b57cec5SDimitry Andric     }
5740b57cec5SDimitry Andric     RValue SrcVal = this->CGF->EmitLoadOfLValue(SrcLV, SourceLocation());
5750b57cec5SDimitry Andric     this->CGF->EmitStoreThroughLValue(SrcVal, DstLV);
5760b57cec5SDimitry Andric   }
5770b57cec5SDimitry Andric };
5780b57cec5SDimitry Andric 
5790b57cec5SDimitry Andric // These classes that emit the special functions for a non-trivial struct.
5800b57cec5SDimitry Andric struct GenDestructor : StructVisitor<GenDestructor>,
5810b57cec5SDimitry Andric                        GenFuncBase<GenDestructor>,
5820b57cec5SDimitry Andric                        DestructedTypeVisitor<GenDestructor> {
5830b57cec5SDimitry Andric   using Super = DestructedTypeVisitor<GenDestructor>;
5840b57cec5SDimitry Andric   GenDestructor(ASTContext &Ctx) : StructVisitor<GenDestructor>(Ctx) {}
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric   void visitWithKind(QualType::DestructionKind DK, QualType FT,
5870b57cec5SDimitry Andric                      const FieldDecl *FD, CharUnits CurStructOffset,
5880b57cec5SDimitry Andric                      std::array<Address, 1> Addrs) {
5890b57cec5SDimitry Andric     if (const auto *AT = getContext().getAsArrayType(FT)) {
5900b57cec5SDimitry Andric       visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset, Addrs);
5910b57cec5SDimitry Andric       return;
5920b57cec5SDimitry Andric     }
5930b57cec5SDimitry Andric 
5940b57cec5SDimitry Andric     Super::visitWithKind(DK, FT, FD, CurStructOffset, Addrs);
5950b57cec5SDimitry Andric   }
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric   void visitARCStrong(QualType QT, const FieldDecl *FD,
5980b57cec5SDimitry Andric                       CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
5990b57cec5SDimitry Andric     CGF->destroyARCStrongImprecise(
6000b57cec5SDimitry Andric         *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
6010b57cec5SDimitry Andric   }
6020b57cec5SDimitry Andric 
6030b57cec5SDimitry Andric   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
6040b57cec5SDimitry Andric                     std::array<Address, 1> Addrs) {
6050b57cec5SDimitry Andric     CGF->destroyARCWeak(
6060b57cec5SDimitry Andric         *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
6070b57cec5SDimitry Andric   }
6080b57cec5SDimitry Andric 
6090b57cec5SDimitry Andric   void callSpecialFunction(QualType FT, CharUnits Offset,
6100b57cec5SDimitry Andric                            std::array<Address, 1> Addrs) {
6110b57cec5SDimitry Andric     CGF->callCStructDestructor(
6120b57cec5SDimitry Andric         CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
6130b57cec5SDimitry Andric   }
6140b57cec5SDimitry Andric };
6150b57cec5SDimitry Andric 
6160b57cec5SDimitry Andric struct GenDefaultInitialize
6170b57cec5SDimitry Andric     : StructVisitor<GenDefaultInitialize>,
6180b57cec5SDimitry Andric       GenFuncBase<GenDefaultInitialize>,
6190b57cec5SDimitry Andric       DefaultInitializedTypeVisitor<GenDefaultInitialize> {
6200b57cec5SDimitry Andric   using Super = DefaultInitializedTypeVisitor<GenDefaultInitialize>;
6210b57cec5SDimitry Andric   typedef GenFuncBase<GenDefaultInitialize> GenFuncBaseTy;
6220b57cec5SDimitry Andric 
6230b57cec5SDimitry Andric   GenDefaultInitialize(ASTContext &Ctx)
6240b57cec5SDimitry Andric       : StructVisitor<GenDefaultInitialize>(Ctx) {}
6250b57cec5SDimitry Andric 
6260b57cec5SDimitry Andric   void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
6270b57cec5SDimitry Andric                      const FieldDecl *FD, CharUnits CurStructOffset,
6280b57cec5SDimitry Andric                      std::array<Address, 1> Addrs) {
6290b57cec5SDimitry Andric     if (const auto *AT = getContext().getAsArrayType(FT)) {
6300b57cec5SDimitry Andric       visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset,
6310b57cec5SDimitry Andric                  Addrs);
6320b57cec5SDimitry Andric       return;
6330b57cec5SDimitry Andric     }
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric     Super::visitWithKind(PDIK, FT, FD, CurStructOffset, Addrs);
6360b57cec5SDimitry Andric   }
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric   void visitARCStrong(QualType QT, const FieldDecl *FD,
6390b57cec5SDimitry Andric                       CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
6400b57cec5SDimitry Andric     CGF->EmitNullInitialization(
6410b57cec5SDimitry Andric         getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
6420b57cec5SDimitry Andric   }
6430b57cec5SDimitry Andric 
6440b57cec5SDimitry Andric   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
6450b57cec5SDimitry Andric                     std::array<Address, 1> Addrs) {
6460b57cec5SDimitry Andric     CGF->EmitNullInitialization(
6470b57cec5SDimitry Andric         getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
6480b57cec5SDimitry Andric   }
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric   template <class FieldKind, size_t... Is>
6510b57cec5SDimitry Andric   void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
6520b57cec5SDimitry Andric                   const FieldDecl *FD, CharUnits CurStructOffset,
6530b57cec5SDimitry Andric                   std::array<Address, 1> Addrs) {
6540b57cec5SDimitry Andric     if (!FK)
6550b57cec5SDimitry Andric       return visitTrivial(QualType(AT, 0), FD, CurStructOffset, Addrs);
6560b57cec5SDimitry Andric 
6570b57cec5SDimitry Andric     ASTContext &Ctx = getContext();
6580b57cec5SDimitry Andric     CharUnits Size = Ctx.getTypeSizeInChars(QualType(AT, 0));
6590b57cec5SDimitry Andric     QualType EltTy = Ctx.getBaseElementType(QualType(AT, 0));
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric     if (Size < CharUnits::fromQuantity(16) || EltTy->getAs<RecordType>()) {
6620b57cec5SDimitry Andric       GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStructOffset, Addrs);
6630b57cec5SDimitry Andric       return;
6640b57cec5SDimitry Andric     }
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric     llvm::Constant *SizeVal = CGF->Builder.getInt64(Size.getQuantity());
6670b57cec5SDimitry Andric     Address DstAddr = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
6680b57cec5SDimitry Andric     Address Loc = CGF->Builder.CreateElementBitCast(DstAddr, CGF->Int8Ty);
6690b57cec5SDimitry Andric     CGF->Builder.CreateMemSet(Loc, CGF->Builder.getInt8(0), SizeVal,
6700b57cec5SDimitry Andric                               IsVolatile);
6710b57cec5SDimitry Andric   }
6720b57cec5SDimitry Andric 
6730b57cec5SDimitry Andric   void callSpecialFunction(QualType FT, CharUnits Offset,
6740b57cec5SDimitry Andric                            std::array<Address, 1> Addrs) {
6750b57cec5SDimitry Andric     CGF->callCStructDefaultConstructor(
6760b57cec5SDimitry Andric         CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
6770b57cec5SDimitry Andric   }
6780b57cec5SDimitry Andric };
6790b57cec5SDimitry Andric 
6800b57cec5SDimitry Andric struct GenCopyConstructor : GenBinaryFunc<GenCopyConstructor, false> {
6810b57cec5SDimitry Andric   GenCopyConstructor(ASTContext &Ctx)
6820b57cec5SDimitry Andric       : GenBinaryFunc<GenCopyConstructor, false>(Ctx) {}
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric   void visitARCStrong(QualType QT, const FieldDecl *FD,
6850b57cec5SDimitry Andric                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
6860b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
6870b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
6880b57cec5SDimitry Andric     llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
6890b57cec5SDimitry Andric         Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
6900b57cec5SDimitry Andric     llvm::Value *Val = CGF->EmitARCRetain(QT, SrcVal);
6910b57cec5SDimitry Andric     CGF->EmitStoreOfScalar(Val, CGF->MakeAddrLValue(Addrs[DstIdx], QT), true);
6920b57cec5SDimitry Andric   }
6930b57cec5SDimitry Andric 
6940b57cec5SDimitry Andric   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
6950b57cec5SDimitry Andric                     std::array<Address, 2> Addrs) {
6960b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
6970b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
6980b57cec5SDimitry Andric     CGF->EmitARCCopyWeak(Addrs[DstIdx], Addrs[SrcIdx]);
6990b57cec5SDimitry Andric   }
7000b57cec5SDimitry Andric 
7010b57cec5SDimitry Andric   void callSpecialFunction(QualType FT, CharUnits Offset,
7020b57cec5SDimitry Andric                            std::array<Address, 2> Addrs) {
7030b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
7040b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
7050b57cec5SDimitry Andric     CGF->callCStructCopyConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
7060b57cec5SDimitry Andric                                     CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
7070b57cec5SDimitry Andric   }
7080b57cec5SDimitry Andric };
7090b57cec5SDimitry Andric 
7100b57cec5SDimitry Andric struct GenMoveConstructor : GenBinaryFunc<GenMoveConstructor, true> {
7110b57cec5SDimitry Andric   GenMoveConstructor(ASTContext &Ctx)
7120b57cec5SDimitry Andric       : GenBinaryFunc<GenMoveConstructor, true>(Ctx) {}
7130b57cec5SDimitry Andric 
7140b57cec5SDimitry Andric   void visitARCStrong(QualType QT, const FieldDecl *FD,
7150b57cec5SDimitry Andric                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
7160b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
7170b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7180b57cec5SDimitry Andric     LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
7190b57cec5SDimitry Andric     llvm::Value *SrcVal =
7200b57cec5SDimitry Andric         CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
721480093f4SDimitry Andric     CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress(*CGF)), SrcLV);
7220b57cec5SDimitry Andric     CGF->EmitStoreOfScalar(SrcVal, CGF->MakeAddrLValue(Addrs[DstIdx], QT),
7230b57cec5SDimitry Andric                            /* isInitialization */ true);
7240b57cec5SDimitry Andric   }
7250b57cec5SDimitry Andric 
7260b57cec5SDimitry Andric   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
7270b57cec5SDimitry Andric                     std::array<Address, 2> Addrs) {
7280b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
7290b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7300b57cec5SDimitry Andric     CGF->EmitARCMoveWeak(Addrs[DstIdx], Addrs[SrcIdx]);
7310b57cec5SDimitry Andric   }
7320b57cec5SDimitry Andric 
7330b57cec5SDimitry Andric   void callSpecialFunction(QualType FT, CharUnits Offset,
7340b57cec5SDimitry Andric                            std::array<Address, 2> Addrs) {
7350b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
7360b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
7370b57cec5SDimitry Andric     CGF->callCStructMoveConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
7380b57cec5SDimitry Andric                                     CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
7390b57cec5SDimitry Andric   }
7400b57cec5SDimitry Andric };
7410b57cec5SDimitry Andric 
7420b57cec5SDimitry Andric struct GenCopyAssignment : GenBinaryFunc<GenCopyAssignment, false> {
7430b57cec5SDimitry Andric   GenCopyAssignment(ASTContext &Ctx)
7440b57cec5SDimitry Andric       : GenBinaryFunc<GenCopyAssignment, false>(Ctx) {}
7450b57cec5SDimitry Andric 
7460b57cec5SDimitry Andric   void visitARCStrong(QualType QT, const FieldDecl *FD,
7470b57cec5SDimitry Andric                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
7480b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
7490b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7500b57cec5SDimitry Andric     llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
7510b57cec5SDimitry Andric         Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
7520b57cec5SDimitry Andric     CGF->EmitARCStoreStrong(CGF->MakeAddrLValue(Addrs[DstIdx], QT), SrcVal,
7530b57cec5SDimitry Andric                             false);
7540b57cec5SDimitry Andric   }
7550b57cec5SDimitry Andric 
7560b57cec5SDimitry Andric   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
7570b57cec5SDimitry Andric                     std::array<Address, 2> Addrs) {
7580b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
7590b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7600b57cec5SDimitry Andric     CGF->emitARCCopyAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
7610b57cec5SDimitry Andric   }
7620b57cec5SDimitry Andric 
7630b57cec5SDimitry Andric   void callSpecialFunction(QualType FT, CharUnits Offset,
7640b57cec5SDimitry Andric                            std::array<Address, 2> Addrs) {
7650b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
7660b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
7670b57cec5SDimitry Andric     CGF->callCStructCopyAssignmentOperator(
7680b57cec5SDimitry Andric         CGF->MakeAddrLValue(Addrs[DstIdx], FT),
7690b57cec5SDimitry Andric         CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
7700b57cec5SDimitry Andric   }
7710b57cec5SDimitry Andric };
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric struct GenMoveAssignment : GenBinaryFunc<GenMoveAssignment, true> {
7740b57cec5SDimitry Andric   GenMoveAssignment(ASTContext &Ctx)
7750b57cec5SDimitry Andric       : GenBinaryFunc<GenMoveAssignment, true>(Ctx) {}
7760b57cec5SDimitry Andric 
7770b57cec5SDimitry Andric   void visitARCStrong(QualType QT, const FieldDecl *FD,
7780b57cec5SDimitry Andric                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
7790b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
7800b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7810b57cec5SDimitry Andric     LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
7820b57cec5SDimitry Andric     llvm::Value *SrcVal =
7830b57cec5SDimitry Andric         CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
784480093f4SDimitry Andric     CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress(*CGF)), SrcLV);
7850b57cec5SDimitry Andric     LValue DstLV = CGF->MakeAddrLValue(Addrs[DstIdx], QT);
7860b57cec5SDimitry Andric     llvm::Value *DstVal =
7870b57cec5SDimitry Andric         CGF->EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
7880b57cec5SDimitry Andric     CGF->EmitStoreOfScalar(SrcVal, DstLV);
7890b57cec5SDimitry Andric     CGF->EmitARCRelease(DstVal, ARCImpreciseLifetime);
7900b57cec5SDimitry Andric   }
7910b57cec5SDimitry Andric 
7920b57cec5SDimitry Andric   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
7930b57cec5SDimitry Andric                     std::array<Address, 2> Addrs) {
7940b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
7950b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7960b57cec5SDimitry Andric     CGF->emitARCMoveAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
7970b57cec5SDimitry Andric   }
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric   void callSpecialFunction(QualType FT, CharUnits Offset,
8000b57cec5SDimitry Andric                            std::array<Address, 2> Addrs) {
8010b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
8020b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
8030b57cec5SDimitry Andric     CGF->callCStructMoveAssignmentOperator(
8040b57cec5SDimitry Andric         CGF->MakeAddrLValue(Addrs[DstIdx], FT),
8050b57cec5SDimitry Andric         CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
8060b57cec5SDimitry Andric   }
8070b57cec5SDimitry Andric };
8080b57cec5SDimitry Andric 
8090b57cec5SDimitry Andric } // namespace
8100b57cec5SDimitry Andric 
8110b57cec5SDimitry Andric void CodeGenFunction::destroyNonTrivialCStruct(CodeGenFunction &CGF,
8120b57cec5SDimitry Andric                                                Address Addr, QualType Type) {
8130b57cec5SDimitry Andric   CGF.callCStructDestructor(CGF.MakeAddrLValue(Addr, Type));
8140b57cec5SDimitry Andric }
8150b57cec5SDimitry Andric 
8160b57cec5SDimitry Andric // Default-initialize a variable that is a non-trivial struct or an array of
8170b57cec5SDimitry Andric // such structure.
8180b57cec5SDimitry Andric void CodeGenFunction::defaultInitNonTrivialCStructVar(LValue Dst) {
8190b57cec5SDimitry Andric   GenDefaultInitialize Gen(getContext());
820480093f4SDimitry Andric   Address DstPtr =
821*0eae32dcSDimitry Andric       Builder.CreateElementBitCast(Dst.getAddress(*this), CGM.Int8PtrTy);
8220b57cec5SDimitry Andric   Gen.setCGF(this);
8230b57cec5SDimitry Andric   QualType QT = Dst.getType();
8240b57cec5SDimitry Andric   QT = Dst.isVolatile() ? QT.withVolatile() : QT;
8250b57cec5SDimitry Andric   Gen.visit(QT, nullptr, CharUnits::Zero(), std::array<Address, 1>({{DstPtr}}));
8260b57cec5SDimitry Andric }
8270b57cec5SDimitry Andric 
8280b57cec5SDimitry Andric template <class G, size_t N>
8290b57cec5SDimitry Andric static void callSpecialFunction(G &&Gen, StringRef FuncName, QualType QT,
8300b57cec5SDimitry Andric                                 bool IsVolatile, CodeGenFunction &CGF,
8310b57cec5SDimitry Andric                                 std::array<Address, N> Addrs) {
832480093f4SDimitry Andric   auto SetArtificialLoc = ApplyDebugLocation::CreateArtificial(CGF);
8330b57cec5SDimitry Andric   for (unsigned I = 0; I < N; ++I)
834*0eae32dcSDimitry Andric     Addrs[I] = CGF.Builder.CreateElementBitCast(Addrs[I], CGF.CGM.Int8PtrTy);
8350b57cec5SDimitry Andric   QT = IsVolatile ? QT.withVolatile() : QT;
8360b57cec5SDimitry Andric   Gen.callFunc(FuncName, QT, Addrs, CGF);
8370b57cec5SDimitry Andric }
8380b57cec5SDimitry Andric 
8390b57cec5SDimitry Andric template <class G, size_t N>
8400b57cec5SDimitry Andric static llvm::Function *
8410b57cec5SDimitry Andric getSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile,
8420b57cec5SDimitry Andric                    std::array<CharUnits, N> Alignments, CodeGenModule &CGM) {
8430b57cec5SDimitry Andric   QT = IsVolatile ? QT.withVolatile() : QT;
8440b57cec5SDimitry Andric   // The following call requires an array of addresses as arguments, but doesn't
8450b57cec5SDimitry Andric   // actually use them (it overwrites them with the addresses of the arguments
8460b57cec5SDimitry Andric   // of the created function).
8475ffd83dbSDimitry Andric   return Gen.getFunction(FuncName, QT, Alignments, CGM);
8480b57cec5SDimitry Andric }
8490b57cec5SDimitry Andric 
8500b57cec5SDimitry Andric // Functions to emit calls to the special functions of a non-trivial C struct.
8510b57cec5SDimitry Andric void CodeGenFunction::callCStructDefaultConstructor(LValue Dst) {
8520b57cec5SDimitry Andric   bool IsVolatile = Dst.isVolatile();
853480093f4SDimitry Andric   Address DstPtr = Dst.getAddress(*this);
8540b57cec5SDimitry Andric   QualType QT = Dst.getType();
8550b57cec5SDimitry Andric   GenDefaultInitializeFuncName GenName(DstPtr.getAlignment(), getContext());
8560b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
8570b57cec5SDimitry Andric   callSpecialFunction(GenDefaultInitialize(getContext()), FuncName, QT,
8580b57cec5SDimitry Andric                       IsVolatile, *this, std::array<Address, 1>({{DstPtr}}));
8590b57cec5SDimitry Andric }
8600b57cec5SDimitry Andric 
8610b57cec5SDimitry Andric std::string CodeGenFunction::getNonTrivialCopyConstructorStr(
8620b57cec5SDimitry Andric     QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx) {
8630b57cec5SDimitry Andric   GenBinaryFuncName<false> GenName("", Alignment, Alignment, Ctx);
8640b57cec5SDimitry Andric   return GenName.getName(QT, IsVolatile);
8650b57cec5SDimitry Andric }
8660b57cec5SDimitry Andric 
8670b57cec5SDimitry Andric std::string CodeGenFunction::getNonTrivialDestructorStr(QualType QT,
8680b57cec5SDimitry Andric                                                         CharUnits Alignment,
8690b57cec5SDimitry Andric                                                         bool IsVolatile,
8700b57cec5SDimitry Andric                                                         ASTContext &Ctx) {
8710b57cec5SDimitry Andric   GenDestructorFuncName GenName("", Alignment, Ctx);
8720b57cec5SDimitry Andric   return GenName.getName(QT, IsVolatile);
8730b57cec5SDimitry Andric }
8740b57cec5SDimitry Andric 
8750b57cec5SDimitry Andric void CodeGenFunction::callCStructDestructor(LValue Dst) {
8760b57cec5SDimitry Andric   bool IsVolatile = Dst.isVolatile();
877480093f4SDimitry Andric   Address DstPtr = Dst.getAddress(*this);
8780b57cec5SDimitry Andric   QualType QT = Dst.getType();
8790b57cec5SDimitry Andric   GenDestructorFuncName GenName("__destructor_", DstPtr.getAlignment(),
8800b57cec5SDimitry Andric                                 getContext());
8810b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
8820b57cec5SDimitry Andric   callSpecialFunction(GenDestructor(getContext()), FuncName, QT, IsVolatile,
8830b57cec5SDimitry Andric                       *this, std::array<Address, 1>({{DstPtr}}));
8840b57cec5SDimitry Andric }
8850b57cec5SDimitry Andric 
8860b57cec5SDimitry Andric void CodeGenFunction::callCStructCopyConstructor(LValue Dst, LValue Src) {
8870b57cec5SDimitry Andric   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
888480093f4SDimitry Andric   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
8890b57cec5SDimitry Andric   QualType QT = Dst.getType();
8900b57cec5SDimitry Andric   GenBinaryFuncName<false> GenName("__copy_constructor_", DstPtr.getAlignment(),
8910b57cec5SDimitry Andric                                    SrcPtr.getAlignment(), getContext());
8920b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
8930b57cec5SDimitry Andric   callSpecialFunction(GenCopyConstructor(getContext()), FuncName, QT,
8940b57cec5SDimitry Andric                       IsVolatile, *this,
8950b57cec5SDimitry Andric                       std::array<Address, 2>({{DstPtr, SrcPtr}}));
8960b57cec5SDimitry Andric }
8970b57cec5SDimitry Andric 
8980b57cec5SDimitry Andric void CodeGenFunction::callCStructCopyAssignmentOperator(LValue Dst, LValue Src
8990b57cec5SDimitry Andric 
9000b57cec5SDimitry Andric ) {
9010b57cec5SDimitry Andric   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
902480093f4SDimitry Andric   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
9030b57cec5SDimitry Andric   QualType QT = Dst.getType();
9040b57cec5SDimitry Andric   GenBinaryFuncName<false> GenName("__copy_assignment_", DstPtr.getAlignment(),
9050b57cec5SDimitry Andric                                    SrcPtr.getAlignment(), getContext());
9060b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
9070b57cec5SDimitry Andric   callSpecialFunction(GenCopyAssignment(getContext()), FuncName, QT, IsVolatile,
9080b57cec5SDimitry Andric                       *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
9090b57cec5SDimitry Andric }
9100b57cec5SDimitry Andric 
9110b57cec5SDimitry Andric void CodeGenFunction::callCStructMoveConstructor(LValue Dst, LValue Src) {
9120b57cec5SDimitry Andric   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
913480093f4SDimitry Andric   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
9140b57cec5SDimitry Andric   QualType QT = Dst.getType();
9150b57cec5SDimitry Andric   GenBinaryFuncName<true> GenName("__move_constructor_", DstPtr.getAlignment(),
9160b57cec5SDimitry Andric                                   SrcPtr.getAlignment(), getContext());
9170b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
9180b57cec5SDimitry Andric   callSpecialFunction(GenMoveConstructor(getContext()), FuncName, QT,
9190b57cec5SDimitry Andric                       IsVolatile, *this,
9200b57cec5SDimitry Andric                       std::array<Address, 2>({{DstPtr, SrcPtr}}));
9210b57cec5SDimitry Andric }
9220b57cec5SDimitry Andric 
9230b57cec5SDimitry Andric void CodeGenFunction::callCStructMoveAssignmentOperator(LValue Dst, LValue Src
9240b57cec5SDimitry Andric 
9250b57cec5SDimitry Andric ) {
9260b57cec5SDimitry Andric   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
927480093f4SDimitry Andric   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
9280b57cec5SDimitry Andric   QualType QT = Dst.getType();
9290b57cec5SDimitry Andric   GenBinaryFuncName<true> GenName("__move_assignment_", DstPtr.getAlignment(),
9300b57cec5SDimitry Andric                                   SrcPtr.getAlignment(), getContext());
9310b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
9320b57cec5SDimitry Andric   callSpecialFunction(GenMoveAssignment(getContext()), FuncName, QT, IsVolatile,
9330b57cec5SDimitry Andric                       *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
9340b57cec5SDimitry Andric }
9350b57cec5SDimitry Andric 
9360b57cec5SDimitry Andric llvm::Function *clang::CodeGen::getNonTrivialCStructDefaultConstructor(
9370b57cec5SDimitry Andric     CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
9380b57cec5SDimitry Andric   ASTContext &Ctx = CGM.getContext();
9390b57cec5SDimitry Andric   GenDefaultInitializeFuncName GenName(DstAlignment, Ctx);
9400b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
9410b57cec5SDimitry Andric   return getSpecialFunction(GenDefaultInitialize(Ctx), FuncName, QT, IsVolatile,
9420b57cec5SDimitry Andric                             std::array<CharUnits, 1>({{DstAlignment}}), CGM);
9430b57cec5SDimitry Andric }
9440b57cec5SDimitry Andric 
9450b57cec5SDimitry Andric llvm::Function *clang::CodeGen::getNonTrivialCStructCopyConstructor(
9460b57cec5SDimitry Andric     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
9470b57cec5SDimitry Andric     bool IsVolatile, QualType QT) {
9480b57cec5SDimitry Andric   ASTContext &Ctx = CGM.getContext();
9490b57cec5SDimitry Andric   GenBinaryFuncName<false> GenName("__copy_constructor_", DstAlignment,
9500b57cec5SDimitry Andric                                    SrcAlignment, Ctx);
9510b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
9520b57cec5SDimitry Andric   return getSpecialFunction(
9530b57cec5SDimitry Andric       GenCopyConstructor(Ctx), FuncName, QT, IsVolatile,
9540b57cec5SDimitry Andric       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
9550b57cec5SDimitry Andric }
9560b57cec5SDimitry Andric 
9570b57cec5SDimitry Andric llvm::Function *clang::CodeGen::getNonTrivialCStructMoveConstructor(
9580b57cec5SDimitry Andric     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
9590b57cec5SDimitry Andric     bool IsVolatile, QualType QT) {
9600b57cec5SDimitry Andric   ASTContext &Ctx = CGM.getContext();
9610b57cec5SDimitry Andric   GenBinaryFuncName<true> GenName("__move_constructor_", DstAlignment,
9620b57cec5SDimitry Andric                                   SrcAlignment, Ctx);
9630b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
9640b57cec5SDimitry Andric   return getSpecialFunction(
9650b57cec5SDimitry Andric       GenMoveConstructor(Ctx), FuncName, QT, IsVolatile,
9660b57cec5SDimitry Andric       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
9670b57cec5SDimitry Andric }
9680b57cec5SDimitry Andric 
9690b57cec5SDimitry Andric llvm::Function *clang::CodeGen::getNonTrivialCStructCopyAssignmentOperator(
9700b57cec5SDimitry Andric     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
9710b57cec5SDimitry Andric     bool IsVolatile, QualType QT) {
9720b57cec5SDimitry Andric   ASTContext &Ctx = CGM.getContext();
9730b57cec5SDimitry Andric   GenBinaryFuncName<false> GenName("__copy_assignment_", DstAlignment,
9740b57cec5SDimitry Andric                                    SrcAlignment, Ctx);
9750b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
9760b57cec5SDimitry Andric   return getSpecialFunction(
9770b57cec5SDimitry Andric       GenCopyAssignment(Ctx), FuncName, QT, IsVolatile,
9780b57cec5SDimitry Andric       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
9790b57cec5SDimitry Andric }
9800b57cec5SDimitry Andric 
9810b57cec5SDimitry Andric llvm::Function *clang::CodeGen::getNonTrivialCStructMoveAssignmentOperator(
9820b57cec5SDimitry Andric     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
9830b57cec5SDimitry Andric     bool IsVolatile, QualType QT) {
9840b57cec5SDimitry Andric   ASTContext &Ctx = CGM.getContext();
9850b57cec5SDimitry Andric   GenBinaryFuncName<true> GenName("__move_assignment_", DstAlignment,
9860b57cec5SDimitry Andric                                   SrcAlignment, Ctx);
9870b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
9880b57cec5SDimitry Andric   return getSpecialFunction(
9890b57cec5SDimitry Andric       GenMoveAssignment(Ctx), FuncName, QT, IsVolatile,
9900b57cec5SDimitry Andric       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
9910b57cec5SDimitry Andric }
9920b57cec5SDimitry Andric 
9930b57cec5SDimitry Andric llvm::Function *clang::CodeGen::getNonTrivialCStructDestructor(
9940b57cec5SDimitry Andric     CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
9950b57cec5SDimitry Andric   ASTContext &Ctx = CGM.getContext();
9960b57cec5SDimitry Andric   GenDestructorFuncName GenName("__destructor_", DstAlignment, Ctx);
9970b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
9980b57cec5SDimitry Andric   return getSpecialFunction(GenDestructor(Ctx), FuncName, QT, IsVolatile,
9990b57cec5SDimitry Andric                             std::array<CharUnits, 1>({{DstAlignment}}), CGM);
10000b57cec5SDimitry Andric }
1001