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.
getFieldSize(const FieldDecl * FD,QualType FT,ASTContext & Ctx)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 {
StructVisitor__anon1b29037b0111::StructVisitor370b57cec5SDimitry Andric   StructVisitor(ASTContext &Ctx) : Ctx(Ctx) {}
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric   template <class... Ts>
visitStructFields__anon1b29037b0111::StructVisitor400b57cec5SDimitry 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 
visitTrivial__anon1b29037b0111::StructVisitor530b57cec5SDimitry Andric   template <class... Ts> void visitTrivial(Ts... Args) {}
540b57cec5SDimitry Andric 
visitCXXDestructor__anon1b29037b0111::StructVisitor550b57cec5SDimitry 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 
flushTrivialFields__anon1b29037b0111::StructVisitor590b57cec5SDimitry Andric   template <class... Ts> void flushTrivialFields(Ts... Args) {}
600b57cec5SDimitry Andric 
getFieldOffsetInBits__anon1b29037b0111::StructVisitor610b57cec5SDimitry 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 
getFieldOffset__anon1b29037b0111::StructVisitor670b57cec5SDimitry Andric   CharUnits getFieldOffset(const FieldDecl *FD) {
680b57cec5SDimitry Andric     return Ctx.toCharUnitsFromBits(getFieldOffsetInBits(FD));
690b57cec5SDimitry Andric   }
700b57cec5SDimitry Andric 
asDerived__anon1b29037b0111::StructVisitor710b57cec5SDimitry Andric   Derived &asDerived() { return static_cast<Derived &>(*this); }
720b57cec5SDimitry Andric 
getContext__anon1b29037b0111::StructVisitor730b57cec5SDimitry 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 
CopyStructVisitor__anon1b29037b0111::CopyStructVisitor830b57cec5SDimitry Andric   CopyStructVisitor(ASTContext &Ctx) : StructVisitor<Derived>(Ctx) {}
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   template <class... Ts>
preVisit__anon1b29037b0111::CopyStructVisitor860b57cec5SDimitry 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>
visitWithKind__anon1b29037b0111::CopyStructVisitor930b57cec5SDimitry 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>
visitTrivial__anon1b29037b0111::CopyStructVisitor1070b57cec5SDimitry 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 {
getVolatileOffsetStr__anon1b29037b0111::GenFuncNameBase1510b57cec5SDimitry 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 
visitARCStrong__anon1b29037b0111::GenFuncNameBase1590b57cec5SDimitry 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 
visitARCWeak__anon1b29037b0111::GenFuncNameBase1680b57cec5SDimitry 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 
visitStruct__anon1b29037b0111::GenFuncNameBase1750b57cec5SDimitry 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>
visitArray__anon1b29037b0111::GenFuncNameBase1830b57cec5SDimitry 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 
appendStr__anon1b29037b0111::GenFuncNameBase2050b57cec5SDimitry Andric   void appendStr(StringRef Str) { Name += Str; }
2060b57cec5SDimitry Andric 
getName__anon1b29037b0111::GenFuncNameBase2070b57cec5SDimitry 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 
asDerived__anon1b29037b0111::GenFuncNameBase2130b57cec5SDimitry 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> {
GenUnaryFuncName__anon1b29037b0111::GenUnaryFuncName2200b57cec5SDimitry 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.
getNullForVariable(Address Addr)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 
GenBinaryFuncName__anon1b29037b0111::GenBinaryFuncName2370b57cec5SDimitry 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 
flushTrivialFields__anon1b29037b0111::GenBinaryFuncName2450b57cec5SDimitry 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 
visitVolatileTrivial__anon1b29037b0111::GenBinaryFuncName2550b57cec5SDimitry 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>;
GenDefaultInitializeFuncName__anon1b29037b0111::GenDefaultInitializeFuncName2740b57cec5SDimitry Andric   GenDefaultInitializeFuncName(CharUnits DstAlignment, ASTContext &Ctx)
2750b57cec5SDimitry Andric       : GenUnaryFuncName<GenDefaultInitializeFuncName>("__default_constructor_",
2760b57cec5SDimitry Andric                                                        DstAlignment, Ctx) {}
visitWithKind__anon1b29037b0111::GenDefaultInitializeFuncName2770b57cec5SDimitry 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>;
GenDestructorFuncName__anon1b29037b0111::GenDestructorFuncName2910b57cec5SDimitry Andric   GenDestructorFuncName(const char *Prefix, CharUnits DstAlignment,
2920b57cec5SDimitry Andric                         ASTContext &Ctx)
2930b57cec5SDimitry Andric       : GenUnaryFuncName<GenDestructorFuncName>(Prefix, DstAlignment, Ctx) {}
visitWithKind__anon1b29037b0111::GenDestructorFuncName2940b57cec5SDimitry 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>
getFunctionInfo(CodeGenModule & CGM,FunctionArgList & Args)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,
3165f757f3fSDimitry Andric         ImplicitParamKind::Other));
3170b57cec5SDimitry Andric 
31881ad6265SDimitry Andric   llvm::append_range(Args, Params);
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric   return CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args);
3210b57cec5SDimitry Andric }
3220b57cec5SDimitry Andric 
3235ffd83dbSDimitry Andric template <size_t N, size_t... Ints>
getParamAddrs(std::index_sequence<Ints...> IntSeq,std::array<CharUnits,N> Alignments,const FunctionArgList & Args,CodeGenFunction * CGF)3245ffd83dbSDimitry Andric static std::array<Address, N> getParamAddrs(std::index_sequence<Ints...> IntSeq,
3255ffd83dbSDimitry Andric                                             std::array<CharUnits, N> Alignments,
32606c3fb27SDimitry Andric                                             const FunctionArgList &Args,
3275ffd83dbSDimitry Andric                                             CodeGenFunction *CGF) {
32881ad6265SDimitry Andric   return std::array<Address, N>{
32981ad6265SDimitry Andric       {Address(CGF->Builder.CreateLoad(CGF->GetAddrOfLocalVar(Args[Ints])),
33006c3fb27SDimitry Andric                CGF->VoidPtrTy, Alignments[Ints], KnownNonNull)...}};
3315ffd83dbSDimitry Andric }
3325ffd83dbSDimitry Andric 
3330b57cec5SDimitry Andric // Template classes that are used as bases for classes that emit special
3340b57cec5SDimitry Andric // functions.
3350b57cec5SDimitry Andric template <class Derived> struct GenFuncBase {
3360b57cec5SDimitry Andric   template <size_t N>
visitStruct__anon1b29037b0111::GenFuncBase3370b57cec5SDimitry Andric   void visitStruct(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset,
3380b57cec5SDimitry Andric                    std::array<Address, N> Addrs) {
3390b57cec5SDimitry Andric     this->asDerived().callSpecialFunction(
3400b57cec5SDimitry Andric         FT, CurStructOffset + asDerived().getFieldOffset(FD), Addrs);
3410b57cec5SDimitry Andric   }
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric   template <class FieldKind, size_t N>
visitArray__anon1b29037b0111::GenFuncBase3440b57cec5SDimitry Andric   void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
3450b57cec5SDimitry Andric                   const FieldDecl *FD, CharUnits CurStructOffset,
3460b57cec5SDimitry Andric                   std::array<Address, N> Addrs) {
3470b57cec5SDimitry Andric     // Non-volatile trivial fields are copied when flushTrivialFields is called.
3480b57cec5SDimitry Andric     if (!FK)
3490b57cec5SDimitry Andric       return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset,
3500b57cec5SDimitry Andric                                       Addrs);
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric     asDerived().flushTrivialFields(Addrs);
3530b57cec5SDimitry Andric     CodeGenFunction &CGF = *this->CGF;
3540b57cec5SDimitry Andric     ASTContext &Ctx = CGF.getContext();
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric     // Compute the end address.
3570b57cec5SDimitry Andric     QualType BaseEltQT;
3580b57cec5SDimitry Andric     std::array<Address, N> StartAddrs = Addrs;
3590b57cec5SDimitry Andric     for (unsigned I = 0; I < N; ++I)
3600b57cec5SDimitry Andric       StartAddrs[I] = getAddrWithOffset(Addrs[I], CurStructOffset, FD);
3610b57cec5SDimitry Andric     Address DstAddr = StartAddrs[DstIdx];
3620b57cec5SDimitry Andric     llvm::Value *NumElts = CGF.emitArrayLength(AT, BaseEltQT, DstAddr);
3630b57cec5SDimitry Andric     unsigned BaseEltSize = Ctx.getTypeSizeInChars(BaseEltQT).getQuantity();
3640b57cec5SDimitry Andric     llvm::Value *BaseEltSizeVal =
3650b57cec5SDimitry Andric         llvm::ConstantInt::get(NumElts->getType(), BaseEltSize);
3660b57cec5SDimitry Andric     llvm::Value *SizeInBytes =
3670b57cec5SDimitry Andric         CGF.Builder.CreateNUWMul(BaseEltSizeVal, NumElts);
36806c3fb27SDimitry Andric     llvm::Value *DstArrayEnd = CGF.Builder.CreateInBoundsGEP(
36906c3fb27SDimitry Andric         CGF.Int8Ty, DstAddr.getPointer(), SizeInBytes);
3700b57cec5SDimitry Andric     llvm::BasicBlock *PreheaderBB = CGF.Builder.GetInsertBlock();
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric     // Create the header block and insert the phi instructions.
3730b57cec5SDimitry Andric     llvm::BasicBlock *HeaderBB = CGF.createBasicBlock("loop.header");
3740b57cec5SDimitry Andric     CGF.EmitBlock(HeaderBB);
3750b57cec5SDimitry Andric     llvm::PHINode *PHIs[N];
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric     for (unsigned I = 0; I < N; ++I) {
3780b57cec5SDimitry Andric       PHIs[I] = CGF.Builder.CreatePHI(CGF.CGM.Int8PtrPtrTy, 2, "addr.cur");
3790b57cec5SDimitry Andric       PHIs[I]->addIncoming(StartAddrs[I].getPointer(), PreheaderBB);
3800b57cec5SDimitry Andric     }
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric     // Create the exit and loop body blocks.
3830b57cec5SDimitry Andric     llvm::BasicBlock *ExitBB = CGF.createBasicBlock("loop.exit");
3840b57cec5SDimitry Andric     llvm::BasicBlock *LoopBB = CGF.createBasicBlock("loop.body");
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric     // Emit the comparison and conditional branch instruction that jumps to
3870b57cec5SDimitry Andric     // either the exit or the loop body.
3880b57cec5SDimitry Andric     llvm::Value *Done =
3890b57cec5SDimitry Andric         CGF.Builder.CreateICmpEQ(PHIs[DstIdx], DstArrayEnd, "done");
3900b57cec5SDimitry Andric     CGF.Builder.CreateCondBr(Done, ExitBB, LoopBB);
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric     // Visit the element of the array in the loop body.
3930b57cec5SDimitry Andric     CGF.EmitBlock(LoopBB);
3940b57cec5SDimitry Andric     QualType EltQT = AT->getElementType();
3950b57cec5SDimitry Andric     CharUnits EltSize = Ctx.getTypeSizeInChars(EltQT);
3960b57cec5SDimitry Andric     std::array<Address, N> NewAddrs = Addrs;
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric     for (unsigned I = 0; I < N; ++I)
39981ad6265SDimitry Andric       NewAddrs[I] =
40081ad6265SDimitry Andric             Address(PHIs[I], CGF.Int8PtrTy,
40181ad6265SDimitry Andric                     StartAddrs[I].getAlignment().alignmentAtOffset(EltSize));
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric     EltQT = IsVolatile ? EltQT.withVolatile() : EltQT;
4040b57cec5SDimitry Andric     this->asDerived().visitWithKind(FK, EltQT, nullptr, CharUnits::Zero(),
4050b57cec5SDimitry Andric                                     NewAddrs);
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric     LoopBB = CGF.Builder.GetInsertBlock();
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric     for (unsigned I = 0; I < N; ++I) {
4100b57cec5SDimitry Andric       // Instrs to update the destination and source addresses.
4110b57cec5SDimitry Andric       // Update phi instructions.
4120b57cec5SDimitry Andric       NewAddrs[I] = getAddrWithOffset(NewAddrs[I], EltSize);
4130b57cec5SDimitry Andric       PHIs[I]->addIncoming(NewAddrs[I].getPointer(), LoopBB);
4140b57cec5SDimitry Andric     }
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric     // Insert an unconditional branch to the header block.
4170b57cec5SDimitry Andric     CGF.Builder.CreateBr(HeaderBB);
4180b57cec5SDimitry Andric     CGF.EmitBlock(ExitBB);
4190b57cec5SDimitry Andric   }
4200b57cec5SDimitry Andric 
4210b57cec5SDimitry Andric   /// Return an address with the specified offset from the passed address.
getAddrWithOffset__anon1b29037b0111::GenFuncBase4220b57cec5SDimitry Andric   Address getAddrWithOffset(Address Addr, CharUnits Offset) {
4230b57cec5SDimitry Andric     assert(Addr.isValid() && "invalid address");
4240b57cec5SDimitry Andric     if (Offset.getQuantity() == 0)
4250b57cec5SDimitry Andric       return Addr;
42606c3fb27SDimitry Andric     Addr = Addr.withElementType(CGF->CGM.Int8Ty);
4270b57cec5SDimitry Andric     Addr = CGF->Builder.CreateConstInBoundsGEP(Addr, Offset.getQuantity());
42806c3fb27SDimitry Andric     return Addr.withElementType(CGF->CGM.Int8PtrTy);
4290b57cec5SDimitry Andric   }
4300b57cec5SDimitry Andric 
getAddrWithOffset__anon1b29037b0111::GenFuncBase4310b57cec5SDimitry Andric   Address getAddrWithOffset(Address Addr, CharUnits StructFieldOffset,
4320b57cec5SDimitry Andric                             const FieldDecl *FD) {
4330b57cec5SDimitry Andric     return getAddrWithOffset(Addr, StructFieldOffset +
4340b57cec5SDimitry Andric                                        asDerived().getFieldOffset(FD));
4350b57cec5SDimitry Andric   }
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric   template <size_t N>
getFunction__anon1b29037b0111::GenFuncBase4385ffd83dbSDimitry Andric   llvm::Function *getFunction(StringRef FuncName, QualType QT,
4395ffd83dbSDimitry Andric                               std::array<CharUnits, N> Alignments,
4405ffd83dbSDimitry Andric                               CodeGenModule &CGM) {
4410b57cec5SDimitry Andric     // If the special function already exists in the module, return it.
4420b57cec5SDimitry Andric     if (llvm::Function *F = CGM.getModule().getFunction(FuncName)) {
4430b57cec5SDimitry Andric       bool WrongType = false;
4440b57cec5SDimitry Andric       if (!F->getReturnType()->isVoidTy())
4450b57cec5SDimitry Andric         WrongType = true;
4460b57cec5SDimitry Andric       else {
4470b57cec5SDimitry Andric         for (const llvm::Argument &Arg : F->args())
4480b57cec5SDimitry Andric           if (Arg.getType() != CGM.Int8PtrPtrTy)
4490b57cec5SDimitry Andric             WrongType = true;
4500b57cec5SDimitry Andric       }
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric       if (WrongType) {
4535ffd83dbSDimitry Andric         std::string FuncName = std::string(F->getName());
4540b57cec5SDimitry Andric         SourceLocation Loc = QT->castAs<RecordType>()->getDecl()->getLocation();
4550b57cec5SDimitry Andric         CGM.Error(Loc, "special function " + FuncName +
4560b57cec5SDimitry Andric                            " for non-trivial C struct has incorrect type");
4570b57cec5SDimitry Andric         return nullptr;
4580b57cec5SDimitry Andric       }
4590b57cec5SDimitry Andric       return F;
4600b57cec5SDimitry Andric     }
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric     ASTContext &Ctx = CGM.getContext();
4630b57cec5SDimitry Andric     FunctionArgList Args;
4640b57cec5SDimitry Andric     const CGFunctionInfo &FI = getFunctionInfo<N>(CGM, Args);
4650b57cec5SDimitry Andric     llvm::FunctionType *FuncTy = CGM.getTypes().GetFunctionType(FI);
4660b57cec5SDimitry Andric     llvm::Function *F =
4670b57cec5SDimitry Andric         llvm::Function::Create(FuncTy, llvm::GlobalValue::LinkOnceODRLinkage,
4680b57cec5SDimitry Andric                                FuncName, &CGM.getModule());
4690b57cec5SDimitry Andric     F->setVisibility(llvm::GlobalValue::HiddenVisibility);
470fe6060f1SDimitry Andric     CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F, /*IsThunk=*/false);
4710b57cec5SDimitry Andric     CGM.SetLLVMFunctionAttributesForDefinition(nullptr, F);
4720b57cec5SDimitry Andric     CodeGenFunction NewCGF(CGM);
4730b57cec5SDimitry Andric     setCGF(&NewCGF);
474fe6060f1SDimitry Andric     CGF->StartFunction(GlobalDecl(), Ctx.VoidTy, F, FI, Args);
475fe6060f1SDimitry Andric     auto AL = ApplyDebugLocation::CreateArtificial(*CGF);
4765ffd83dbSDimitry Andric     std::array<Address, N> Addrs =
4775ffd83dbSDimitry Andric         getParamAddrs<N>(std::make_index_sequence<N>{}, Alignments, Args, CGF);
4780b57cec5SDimitry Andric     asDerived().visitStructFields(QT, CharUnits::Zero(), Addrs);
4790b57cec5SDimitry Andric     CGF->FinishFunction();
4800b57cec5SDimitry Andric     return F;
4810b57cec5SDimitry Andric   }
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric   template <size_t N>
callFunc__anon1b29037b0111::GenFuncBase4840b57cec5SDimitry Andric   void callFunc(StringRef FuncName, QualType QT, std::array<Address, N> Addrs,
4850b57cec5SDimitry Andric                 CodeGenFunction &CallerCGF) {
4860b57cec5SDimitry Andric     std::array<CharUnits, N> Alignments;
4870b57cec5SDimitry Andric     llvm::Value *Ptrs[N];
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric     for (unsigned I = 0; I < N; ++I) {
4900b57cec5SDimitry Andric       Alignments[I] = Addrs[I].getAlignment();
49106c3fb27SDimitry Andric       Ptrs[I] = Addrs[I].getPointer();
4920b57cec5SDimitry Andric     }
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric     if (llvm::Function *F =
4955ffd83dbSDimitry Andric             getFunction(FuncName, QT, Alignments, CallerCGF.CGM))
4960b57cec5SDimitry Andric       CallerCGF.EmitNounwindRuntimeCall(F, Ptrs);
4970b57cec5SDimitry Andric   }
4980b57cec5SDimitry Andric 
asDerived__anon1b29037b0111::GenFuncBase4990b57cec5SDimitry Andric   Derived &asDerived() { return static_cast<Derived &>(*this); }
5000b57cec5SDimitry Andric 
setCGF__anon1b29037b0111::GenFuncBase5010b57cec5SDimitry Andric   void setCGF(CodeGenFunction *F) { CGF = F; }
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric   CodeGenFunction *CGF = nullptr;
5040b57cec5SDimitry Andric };
5050b57cec5SDimitry Andric 
5060b57cec5SDimitry Andric template <class Derived, bool IsMove>
5070b57cec5SDimitry Andric struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>,
5080b57cec5SDimitry Andric                        GenFuncBase<Derived> {
GenBinaryFunc__anon1b29037b0111::GenBinaryFunc5090b57cec5SDimitry Andric   GenBinaryFunc(ASTContext &Ctx) : CopyStructVisitor<Derived, IsMove>(Ctx) {}
5100b57cec5SDimitry Andric 
flushTrivialFields__anon1b29037b0111::GenBinaryFunc5110b57cec5SDimitry Andric   void flushTrivialFields(std::array<Address, 2> Addrs) {
5120b57cec5SDimitry Andric     CharUnits Size = this->End - this->Start;
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric     if (Size.getQuantity() == 0)
5150b57cec5SDimitry Andric       return;
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric     Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], this->Start);
5180b57cec5SDimitry Andric     Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], this->Start);
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric     // Emit memcpy.
52106c3fb27SDimitry Andric     if (Size.getQuantity() >= 16 ||
52206c3fb27SDimitry Andric         !llvm::has_single_bit<uint32_t>(Size.getQuantity())) {
5230b57cec5SDimitry Andric       llvm::Value *SizeVal =
5240b57cec5SDimitry Andric           llvm::ConstantInt::get(this->CGF->SizeTy, Size.getQuantity());
52506c3fb27SDimitry Andric       DstAddr = DstAddr.withElementType(this->CGF->Int8Ty);
52606c3fb27SDimitry Andric       SrcAddr = SrcAddr.withElementType(this->CGF->Int8Ty);
5270b57cec5SDimitry Andric       this->CGF->Builder.CreateMemCpy(DstAddr, SrcAddr, SizeVal, false);
5280b57cec5SDimitry Andric     } else {
5290b57cec5SDimitry Andric       llvm::Type *Ty = llvm::Type::getIntNTy(
5300b57cec5SDimitry Andric           this->CGF->getLLVMContext(),
5310b57cec5SDimitry Andric           Size.getQuantity() * this->CGF->getContext().getCharWidth());
53206c3fb27SDimitry Andric       DstAddr = DstAddr.withElementType(Ty);
53306c3fb27SDimitry Andric       SrcAddr = SrcAddr.withElementType(Ty);
5340b57cec5SDimitry Andric       llvm::Value *SrcVal = this->CGF->Builder.CreateLoad(SrcAddr, false);
5350b57cec5SDimitry Andric       this->CGF->Builder.CreateStore(SrcVal, DstAddr, false);
5360b57cec5SDimitry Andric     }
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric     this->Start = this->End = CharUnits::Zero();
5390b57cec5SDimitry Andric   }
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric   template <class... Ts>
visitVolatileTrivial__anon1b29037b0111::GenBinaryFunc5420b57cec5SDimitry Andric   void visitVolatileTrivial(QualType FT, const FieldDecl *FD, CharUnits Offset,
5430b57cec5SDimitry Andric                             std::array<Address, 2> Addrs) {
5440b57cec5SDimitry Andric     LValue DstLV, SrcLV;
5450b57cec5SDimitry Andric     if (FD) {
5465ffd83dbSDimitry Andric       // No need to copy zero-length bit-fields.
5475ffd83dbSDimitry Andric       if (FD->isZeroLengthBitField(this->CGF->getContext()))
5485ffd83dbSDimitry Andric         return;
5495ffd83dbSDimitry Andric 
5500b57cec5SDimitry Andric       QualType RT = QualType(FD->getParent()->getTypeForDecl(), 0);
5510eae32dcSDimitry Andric       llvm::Type *Ty = this->CGF->ConvertType(RT);
5520b57cec5SDimitry Andric       Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset);
55306c3fb27SDimitry Andric       LValue DstBase =
55406c3fb27SDimitry Andric           this->CGF->MakeAddrLValue(DstAddr.withElementType(Ty), FT);
5550b57cec5SDimitry Andric       DstLV = this->CGF->EmitLValueForField(DstBase, FD);
5560b57cec5SDimitry Andric       Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], Offset);
55706c3fb27SDimitry Andric       LValue SrcBase =
55806c3fb27SDimitry Andric           this->CGF->MakeAddrLValue(SrcAddr.withElementType(Ty), FT);
5590b57cec5SDimitry Andric       SrcLV = this->CGF->EmitLValueForField(SrcBase, FD);
5600b57cec5SDimitry Andric     } else {
5610eae32dcSDimitry Andric       llvm::Type *Ty = this->CGF->ConvertTypeForMem(FT);
56206c3fb27SDimitry Andric       Address DstAddr = Addrs[DstIdx].withElementType(Ty);
56306c3fb27SDimitry Andric       Address SrcAddr = Addrs[SrcIdx].withElementType(Ty);
5640b57cec5SDimitry Andric       DstLV = this->CGF->MakeAddrLValue(DstAddr, FT);
5650b57cec5SDimitry Andric       SrcLV = this->CGF->MakeAddrLValue(SrcAddr, FT);
5660b57cec5SDimitry Andric     }
5670b57cec5SDimitry Andric     RValue SrcVal = this->CGF->EmitLoadOfLValue(SrcLV, SourceLocation());
5680b57cec5SDimitry Andric     this->CGF->EmitStoreThroughLValue(SrcVal, DstLV);
5690b57cec5SDimitry Andric   }
5700b57cec5SDimitry Andric };
5710b57cec5SDimitry Andric 
5720b57cec5SDimitry Andric // These classes that emit the special functions for a non-trivial struct.
5730b57cec5SDimitry Andric struct GenDestructor : StructVisitor<GenDestructor>,
5740b57cec5SDimitry Andric                        GenFuncBase<GenDestructor>,
5750b57cec5SDimitry Andric                        DestructedTypeVisitor<GenDestructor> {
5760b57cec5SDimitry Andric   using Super = DestructedTypeVisitor<GenDestructor>;
GenDestructor__anon1b29037b0111::GenDestructor5770b57cec5SDimitry Andric   GenDestructor(ASTContext &Ctx) : StructVisitor<GenDestructor>(Ctx) {}
5780b57cec5SDimitry Andric 
visitWithKind__anon1b29037b0111::GenDestructor5790b57cec5SDimitry Andric   void visitWithKind(QualType::DestructionKind DK, QualType FT,
5800b57cec5SDimitry Andric                      const FieldDecl *FD, CharUnits CurStructOffset,
5810b57cec5SDimitry Andric                      std::array<Address, 1> Addrs) {
5820b57cec5SDimitry Andric     if (const auto *AT = getContext().getAsArrayType(FT)) {
5830b57cec5SDimitry Andric       visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset, Addrs);
5840b57cec5SDimitry Andric       return;
5850b57cec5SDimitry Andric     }
5860b57cec5SDimitry Andric 
5870b57cec5SDimitry Andric     Super::visitWithKind(DK, FT, FD, CurStructOffset, Addrs);
5880b57cec5SDimitry Andric   }
5890b57cec5SDimitry Andric 
visitARCStrong__anon1b29037b0111::GenDestructor5900b57cec5SDimitry Andric   void visitARCStrong(QualType QT, const FieldDecl *FD,
5910b57cec5SDimitry Andric                       CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
5920b57cec5SDimitry Andric     CGF->destroyARCStrongImprecise(
5930b57cec5SDimitry Andric         *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
5940b57cec5SDimitry Andric   }
5950b57cec5SDimitry Andric 
visitARCWeak__anon1b29037b0111::GenDestructor5960b57cec5SDimitry Andric   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
5970b57cec5SDimitry Andric                     std::array<Address, 1> Addrs) {
5980b57cec5SDimitry Andric     CGF->destroyARCWeak(
5990b57cec5SDimitry Andric         *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
6000b57cec5SDimitry Andric   }
6010b57cec5SDimitry Andric 
callSpecialFunction__anon1b29037b0111::GenDestructor6020b57cec5SDimitry Andric   void callSpecialFunction(QualType FT, CharUnits Offset,
6030b57cec5SDimitry Andric                            std::array<Address, 1> Addrs) {
6040b57cec5SDimitry Andric     CGF->callCStructDestructor(
6050b57cec5SDimitry Andric         CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
6060b57cec5SDimitry Andric   }
6070b57cec5SDimitry Andric };
6080b57cec5SDimitry Andric 
6090b57cec5SDimitry Andric struct GenDefaultInitialize
6100b57cec5SDimitry Andric     : StructVisitor<GenDefaultInitialize>,
6110b57cec5SDimitry Andric       GenFuncBase<GenDefaultInitialize>,
6120b57cec5SDimitry Andric       DefaultInitializedTypeVisitor<GenDefaultInitialize> {
6130b57cec5SDimitry Andric   using Super = DefaultInitializedTypeVisitor<GenDefaultInitialize>;
6140b57cec5SDimitry Andric   typedef GenFuncBase<GenDefaultInitialize> GenFuncBaseTy;
6150b57cec5SDimitry Andric 
GenDefaultInitialize__anon1b29037b0111::GenDefaultInitialize6160b57cec5SDimitry Andric   GenDefaultInitialize(ASTContext &Ctx)
6170b57cec5SDimitry Andric       : StructVisitor<GenDefaultInitialize>(Ctx) {}
6180b57cec5SDimitry Andric 
visitWithKind__anon1b29037b0111::GenDefaultInitialize6190b57cec5SDimitry Andric   void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
6200b57cec5SDimitry Andric                      const FieldDecl *FD, CharUnits CurStructOffset,
6210b57cec5SDimitry Andric                      std::array<Address, 1> Addrs) {
6220b57cec5SDimitry Andric     if (const auto *AT = getContext().getAsArrayType(FT)) {
6230b57cec5SDimitry Andric       visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset,
6240b57cec5SDimitry Andric                  Addrs);
6250b57cec5SDimitry Andric       return;
6260b57cec5SDimitry Andric     }
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric     Super::visitWithKind(PDIK, FT, FD, CurStructOffset, Addrs);
6290b57cec5SDimitry Andric   }
6300b57cec5SDimitry Andric 
visitARCStrong__anon1b29037b0111::GenDefaultInitialize6310b57cec5SDimitry Andric   void visitARCStrong(QualType QT, const FieldDecl *FD,
6320b57cec5SDimitry Andric                       CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
6330b57cec5SDimitry Andric     CGF->EmitNullInitialization(
6340b57cec5SDimitry Andric         getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
6350b57cec5SDimitry Andric   }
6360b57cec5SDimitry Andric 
visitARCWeak__anon1b29037b0111::GenDefaultInitialize6370b57cec5SDimitry Andric   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
6380b57cec5SDimitry Andric                     std::array<Address, 1> Addrs) {
6390b57cec5SDimitry Andric     CGF->EmitNullInitialization(
6400b57cec5SDimitry Andric         getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
6410b57cec5SDimitry Andric   }
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric   template <class FieldKind, size_t... Is>
visitArray__anon1b29037b0111::GenDefaultInitialize6440b57cec5SDimitry Andric   void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
6450b57cec5SDimitry Andric                   const FieldDecl *FD, CharUnits CurStructOffset,
6460b57cec5SDimitry Andric                   std::array<Address, 1> Addrs) {
6470b57cec5SDimitry Andric     if (!FK)
6480b57cec5SDimitry Andric       return visitTrivial(QualType(AT, 0), FD, CurStructOffset, Addrs);
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric     ASTContext &Ctx = getContext();
6510b57cec5SDimitry Andric     CharUnits Size = Ctx.getTypeSizeInChars(QualType(AT, 0));
6520b57cec5SDimitry Andric     QualType EltTy = Ctx.getBaseElementType(QualType(AT, 0));
6530b57cec5SDimitry Andric 
6540b57cec5SDimitry Andric     if (Size < CharUnits::fromQuantity(16) || EltTy->getAs<RecordType>()) {
6550b57cec5SDimitry Andric       GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStructOffset, Addrs);
6560b57cec5SDimitry Andric       return;
6570b57cec5SDimitry Andric     }
6580b57cec5SDimitry Andric 
6590b57cec5SDimitry Andric     llvm::Constant *SizeVal = CGF->Builder.getInt64(Size.getQuantity());
6600b57cec5SDimitry Andric     Address DstAddr = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
66106c3fb27SDimitry Andric     Address Loc = DstAddr.withElementType(CGF->Int8Ty);
6620b57cec5SDimitry Andric     CGF->Builder.CreateMemSet(Loc, CGF->Builder.getInt8(0), SizeVal,
6630b57cec5SDimitry Andric                               IsVolatile);
6640b57cec5SDimitry Andric   }
6650b57cec5SDimitry Andric 
callSpecialFunction__anon1b29037b0111::GenDefaultInitialize6660b57cec5SDimitry Andric   void callSpecialFunction(QualType FT, CharUnits Offset,
6670b57cec5SDimitry Andric                            std::array<Address, 1> Addrs) {
6680b57cec5SDimitry Andric     CGF->callCStructDefaultConstructor(
6690b57cec5SDimitry Andric         CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
6700b57cec5SDimitry Andric   }
6710b57cec5SDimitry Andric };
6720b57cec5SDimitry Andric 
6730b57cec5SDimitry Andric struct GenCopyConstructor : GenBinaryFunc<GenCopyConstructor, false> {
GenCopyConstructor__anon1b29037b0111::GenCopyConstructor6740b57cec5SDimitry Andric   GenCopyConstructor(ASTContext &Ctx)
6750b57cec5SDimitry Andric       : GenBinaryFunc<GenCopyConstructor, false>(Ctx) {}
6760b57cec5SDimitry Andric 
visitARCStrong__anon1b29037b0111::GenCopyConstructor6770b57cec5SDimitry Andric   void visitARCStrong(QualType QT, const FieldDecl *FD,
6780b57cec5SDimitry Andric                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
6790b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
6800b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
6810b57cec5SDimitry Andric     llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
6820b57cec5SDimitry Andric         Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
6830b57cec5SDimitry Andric     llvm::Value *Val = CGF->EmitARCRetain(QT, SrcVal);
6840b57cec5SDimitry Andric     CGF->EmitStoreOfScalar(Val, CGF->MakeAddrLValue(Addrs[DstIdx], QT), true);
6850b57cec5SDimitry Andric   }
6860b57cec5SDimitry Andric 
visitARCWeak__anon1b29037b0111::GenCopyConstructor6870b57cec5SDimitry Andric   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
6880b57cec5SDimitry Andric                     std::array<Address, 2> Addrs) {
6890b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
6900b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
6910b57cec5SDimitry Andric     CGF->EmitARCCopyWeak(Addrs[DstIdx], Addrs[SrcIdx]);
6920b57cec5SDimitry Andric   }
6930b57cec5SDimitry Andric 
callSpecialFunction__anon1b29037b0111::GenCopyConstructor6940b57cec5SDimitry Andric   void callSpecialFunction(QualType FT, CharUnits Offset,
6950b57cec5SDimitry Andric                            std::array<Address, 2> Addrs) {
6960b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
6970b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
6980b57cec5SDimitry Andric     CGF->callCStructCopyConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
6990b57cec5SDimitry Andric                                     CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
7000b57cec5SDimitry Andric   }
7010b57cec5SDimitry Andric };
7020b57cec5SDimitry Andric 
7030b57cec5SDimitry Andric struct GenMoveConstructor : GenBinaryFunc<GenMoveConstructor, true> {
GenMoveConstructor__anon1b29037b0111::GenMoveConstructor7040b57cec5SDimitry Andric   GenMoveConstructor(ASTContext &Ctx)
7050b57cec5SDimitry Andric       : GenBinaryFunc<GenMoveConstructor, true>(Ctx) {}
7060b57cec5SDimitry Andric 
visitARCStrong__anon1b29037b0111::GenMoveConstructor7070b57cec5SDimitry Andric   void visitARCStrong(QualType QT, const FieldDecl *FD,
7080b57cec5SDimitry Andric                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
7090b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
7100b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7110b57cec5SDimitry Andric     LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
7120b57cec5SDimitry Andric     llvm::Value *SrcVal =
7130b57cec5SDimitry Andric         CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
714480093f4SDimitry Andric     CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress(*CGF)), SrcLV);
7150b57cec5SDimitry Andric     CGF->EmitStoreOfScalar(SrcVal, CGF->MakeAddrLValue(Addrs[DstIdx], QT),
7160b57cec5SDimitry Andric                            /* isInitialization */ true);
7170b57cec5SDimitry Andric   }
7180b57cec5SDimitry Andric 
visitARCWeak__anon1b29037b0111::GenMoveConstructor7190b57cec5SDimitry Andric   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
7200b57cec5SDimitry Andric                     std::array<Address, 2> Addrs) {
7210b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
7220b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7230b57cec5SDimitry Andric     CGF->EmitARCMoveWeak(Addrs[DstIdx], Addrs[SrcIdx]);
7240b57cec5SDimitry Andric   }
7250b57cec5SDimitry Andric 
callSpecialFunction__anon1b29037b0111::GenMoveConstructor7260b57cec5SDimitry Andric   void callSpecialFunction(QualType FT, CharUnits Offset,
7270b57cec5SDimitry Andric                            std::array<Address, 2> Addrs) {
7280b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
7290b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
7300b57cec5SDimitry Andric     CGF->callCStructMoveConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
7310b57cec5SDimitry Andric                                     CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
7320b57cec5SDimitry Andric   }
7330b57cec5SDimitry Andric };
7340b57cec5SDimitry Andric 
7350b57cec5SDimitry Andric struct GenCopyAssignment : GenBinaryFunc<GenCopyAssignment, false> {
GenCopyAssignment__anon1b29037b0111::GenCopyAssignment7360b57cec5SDimitry Andric   GenCopyAssignment(ASTContext &Ctx)
7370b57cec5SDimitry Andric       : GenBinaryFunc<GenCopyAssignment, false>(Ctx) {}
7380b57cec5SDimitry Andric 
visitARCStrong__anon1b29037b0111::GenCopyAssignment7390b57cec5SDimitry Andric   void visitARCStrong(QualType QT, const FieldDecl *FD,
7400b57cec5SDimitry Andric                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
7410b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
7420b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7430b57cec5SDimitry Andric     llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
7440b57cec5SDimitry Andric         Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
7450b57cec5SDimitry Andric     CGF->EmitARCStoreStrong(CGF->MakeAddrLValue(Addrs[DstIdx], QT), SrcVal,
7460b57cec5SDimitry Andric                             false);
7470b57cec5SDimitry Andric   }
7480b57cec5SDimitry Andric 
visitARCWeak__anon1b29037b0111::GenCopyAssignment7490b57cec5SDimitry Andric   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
7500b57cec5SDimitry Andric                     std::array<Address, 2> Addrs) {
7510b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
7520b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7530b57cec5SDimitry Andric     CGF->emitARCCopyAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
7540b57cec5SDimitry Andric   }
7550b57cec5SDimitry Andric 
callSpecialFunction__anon1b29037b0111::GenCopyAssignment7560b57cec5SDimitry Andric   void callSpecialFunction(QualType FT, CharUnits Offset,
7570b57cec5SDimitry Andric                            std::array<Address, 2> Addrs) {
7580b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
7590b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
7600b57cec5SDimitry Andric     CGF->callCStructCopyAssignmentOperator(
7610b57cec5SDimitry Andric         CGF->MakeAddrLValue(Addrs[DstIdx], FT),
7620b57cec5SDimitry Andric         CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
7630b57cec5SDimitry Andric   }
7640b57cec5SDimitry Andric };
7650b57cec5SDimitry Andric 
7660b57cec5SDimitry Andric struct GenMoveAssignment : GenBinaryFunc<GenMoveAssignment, true> {
GenMoveAssignment__anon1b29037b0111::GenMoveAssignment7670b57cec5SDimitry Andric   GenMoveAssignment(ASTContext &Ctx)
7680b57cec5SDimitry Andric       : GenBinaryFunc<GenMoveAssignment, true>(Ctx) {}
7690b57cec5SDimitry Andric 
visitARCStrong__anon1b29037b0111::GenMoveAssignment7700b57cec5SDimitry Andric   void visitARCStrong(QualType QT, const FieldDecl *FD,
7710b57cec5SDimitry Andric                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
7720b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
7730b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7740b57cec5SDimitry Andric     LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
7750b57cec5SDimitry Andric     llvm::Value *SrcVal =
7760b57cec5SDimitry Andric         CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
777480093f4SDimitry Andric     CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress(*CGF)), SrcLV);
7780b57cec5SDimitry Andric     LValue DstLV = CGF->MakeAddrLValue(Addrs[DstIdx], QT);
7790b57cec5SDimitry Andric     llvm::Value *DstVal =
7800b57cec5SDimitry Andric         CGF->EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
7810b57cec5SDimitry Andric     CGF->EmitStoreOfScalar(SrcVal, DstLV);
7820b57cec5SDimitry Andric     CGF->EmitARCRelease(DstVal, ARCImpreciseLifetime);
7830b57cec5SDimitry Andric   }
7840b57cec5SDimitry Andric 
visitARCWeak__anon1b29037b0111::GenMoveAssignment7850b57cec5SDimitry Andric   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
7860b57cec5SDimitry Andric                     std::array<Address, 2> Addrs) {
7870b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
7880b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7890b57cec5SDimitry Andric     CGF->emitARCMoveAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
7900b57cec5SDimitry Andric   }
7910b57cec5SDimitry Andric 
callSpecialFunction__anon1b29037b0111::GenMoveAssignment7920b57cec5SDimitry Andric   void callSpecialFunction(QualType FT, CharUnits Offset,
7930b57cec5SDimitry Andric                            std::array<Address, 2> Addrs) {
7940b57cec5SDimitry Andric     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
7950b57cec5SDimitry Andric     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
7960b57cec5SDimitry Andric     CGF->callCStructMoveAssignmentOperator(
7970b57cec5SDimitry Andric         CGF->MakeAddrLValue(Addrs[DstIdx], FT),
7980b57cec5SDimitry Andric         CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
7990b57cec5SDimitry Andric   }
8000b57cec5SDimitry Andric };
8010b57cec5SDimitry Andric 
8020b57cec5SDimitry Andric } // namespace
8030b57cec5SDimitry Andric 
destroyNonTrivialCStruct(CodeGenFunction & CGF,Address Addr,QualType Type)8040b57cec5SDimitry Andric void CodeGenFunction::destroyNonTrivialCStruct(CodeGenFunction &CGF,
8050b57cec5SDimitry Andric                                                Address Addr, QualType Type) {
8060b57cec5SDimitry Andric   CGF.callCStructDestructor(CGF.MakeAddrLValue(Addr, Type));
8070b57cec5SDimitry Andric }
8080b57cec5SDimitry Andric 
8090b57cec5SDimitry Andric // Default-initialize a variable that is a non-trivial struct or an array of
8100b57cec5SDimitry Andric // such structure.
defaultInitNonTrivialCStructVar(LValue Dst)8110b57cec5SDimitry Andric void CodeGenFunction::defaultInitNonTrivialCStructVar(LValue Dst) {
8120b57cec5SDimitry Andric   GenDefaultInitialize Gen(getContext());
81306c3fb27SDimitry Andric   Address DstPtr = Dst.getAddress(*this).withElementType(CGM.Int8PtrTy);
8140b57cec5SDimitry Andric   Gen.setCGF(this);
8150b57cec5SDimitry Andric   QualType QT = Dst.getType();
8160b57cec5SDimitry Andric   QT = Dst.isVolatile() ? QT.withVolatile() : QT;
8170b57cec5SDimitry Andric   Gen.visit(QT, nullptr, CharUnits::Zero(), std::array<Address, 1>({{DstPtr}}));
8180b57cec5SDimitry Andric }
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric template <class G, size_t N>
callSpecialFunction(G && Gen,StringRef FuncName,QualType QT,bool IsVolatile,CodeGenFunction & CGF,std::array<Address,N> Addrs)8210b57cec5SDimitry Andric static void callSpecialFunction(G &&Gen, StringRef FuncName, QualType QT,
8220b57cec5SDimitry Andric                                 bool IsVolatile, CodeGenFunction &CGF,
8230b57cec5SDimitry Andric                                 std::array<Address, N> Addrs) {
824480093f4SDimitry Andric   auto SetArtificialLoc = ApplyDebugLocation::CreateArtificial(CGF);
8250b57cec5SDimitry Andric   for (unsigned I = 0; I < N; ++I)
82606c3fb27SDimitry Andric     Addrs[I] = Addrs[I].withElementType(CGF.CGM.Int8PtrTy);
8270b57cec5SDimitry Andric   QT = IsVolatile ? QT.withVolatile() : QT;
8280b57cec5SDimitry Andric   Gen.callFunc(FuncName, QT, Addrs, CGF);
8290b57cec5SDimitry Andric }
8300b57cec5SDimitry Andric 
8310b57cec5SDimitry Andric template <class G, size_t N>
8320b57cec5SDimitry Andric static llvm::Function *
getSpecialFunction(G && Gen,StringRef FuncName,QualType QT,bool IsVolatile,std::array<CharUnits,N> Alignments,CodeGenModule & CGM)8330b57cec5SDimitry Andric getSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile,
8340b57cec5SDimitry Andric                    std::array<CharUnits, N> Alignments, CodeGenModule &CGM) {
8350b57cec5SDimitry Andric   QT = IsVolatile ? QT.withVolatile() : QT;
8360b57cec5SDimitry Andric   // The following call requires an array of addresses as arguments, but doesn't
8370b57cec5SDimitry Andric   // actually use them (it overwrites them with the addresses of the arguments
8380b57cec5SDimitry Andric   // of the created function).
8395ffd83dbSDimitry Andric   return Gen.getFunction(FuncName, QT, Alignments, CGM);
8400b57cec5SDimitry Andric }
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric // Functions to emit calls to the special functions of a non-trivial C struct.
callCStructDefaultConstructor(LValue Dst)8430b57cec5SDimitry Andric void CodeGenFunction::callCStructDefaultConstructor(LValue Dst) {
8440b57cec5SDimitry Andric   bool IsVolatile = Dst.isVolatile();
845480093f4SDimitry Andric   Address DstPtr = Dst.getAddress(*this);
8460b57cec5SDimitry Andric   QualType QT = Dst.getType();
8470b57cec5SDimitry Andric   GenDefaultInitializeFuncName GenName(DstPtr.getAlignment(), getContext());
8480b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
8490b57cec5SDimitry Andric   callSpecialFunction(GenDefaultInitialize(getContext()), FuncName, QT,
8500b57cec5SDimitry Andric                       IsVolatile, *this, std::array<Address, 1>({{DstPtr}}));
8510b57cec5SDimitry Andric }
8520b57cec5SDimitry Andric 
getNonTrivialCopyConstructorStr(QualType QT,CharUnits Alignment,bool IsVolatile,ASTContext & Ctx)8530b57cec5SDimitry Andric std::string CodeGenFunction::getNonTrivialCopyConstructorStr(
8540b57cec5SDimitry Andric     QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx) {
8550b57cec5SDimitry Andric   GenBinaryFuncName<false> GenName("", Alignment, Alignment, Ctx);
8560b57cec5SDimitry Andric   return GenName.getName(QT, IsVolatile);
8570b57cec5SDimitry Andric }
8580b57cec5SDimitry Andric 
getNonTrivialDestructorStr(QualType QT,CharUnits Alignment,bool IsVolatile,ASTContext & Ctx)8590b57cec5SDimitry Andric std::string CodeGenFunction::getNonTrivialDestructorStr(QualType QT,
8600b57cec5SDimitry Andric                                                         CharUnits Alignment,
8610b57cec5SDimitry Andric                                                         bool IsVolatile,
8620b57cec5SDimitry Andric                                                         ASTContext &Ctx) {
8630b57cec5SDimitry Andric   GenDestructorFuncName GenName("", Alignment, Ctx);
8640b57cec5SDimitry Andric   return GenName.getName(QT, IsVolatile);
8650b57cec5SDimitry Andric }
8660b57cec5SDimitry Andric 
callCStructDestructor(LValue Dst)8670b57cec5SDimitry Andric void CodeGenFunction::callCStructDestructor(LValue Dst) {
8680b57cec5SDimitry Andric   bool IsVolatile = Dst.isVolatile();
869480093f4SDimitry Andric   Address DstPtr = Dst.getAddress(*this);
8700b57cec5SDimitry Andric   QualType QT = Dst.getType();
8710b57cec5SDimitry Andric   GenDestructorFuncName GenName("__destructor_", DstPtr.getAlignment(),
8720b57cec5SDimitry Andric                                 getContext());
8730b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
8740b57cec5SDimitry Andric   callSpecialFunction(GenDestructor(getContext()), FuncName, QT, IsVolatile,
8750b57cec5SDimitry Andric                       *this, std::array<Address, 1>({{DstPtr}}));
8760b57cec5SDimitry Andric }
8770b57cec5SDimitry Andric 
callCStructCopyConstructor(LValue Dst,LValue Src)8780b57cec5SDimitry Andric void CodeGenFunction::callCStructCopyConstructor(LValue Dst, LValue Src) {
8790b57cec5SDimitry Andric   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
880480093f4SDimitry Andric   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
8810b57cec5SDimitry Andric   QualType QT = Dst.getType();
8820b57cec5SDimitry Andric   GenBinaryFuncName<false> GenName("__copy_constructor_", DstPtr.getAlignment(),
8830b57cec5SDimitry Andric                                    SrcPtr.getAlignment(), getContext());
8840b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
8850b57cec5SDimitry Andric   callSpecialFunction(GenCopyConstructor(getContext()), FuncName, QT,
8860b57cec5SDimitry Andric                       IsVolatile, *this,
8870b57cec5SDimitry Andric                       std::array<Address, 2>({{DstPtr, SrcPtr}}));
8880b57cec5SDimitry Andric }
8890b57cec5SDimitry Andric 
callCStructCopyAssignmentOperator(LValue Dst,LValue Src)8900b57cec5SDimitry Andric void CodeGenFunction::callCStructCopyAssignmentOperator(LValue Dst, LValue Src
8910b57cec5SDimitry Andric 
8920b57cec5SDimitry Andric ) {
8930b57cec5SDimitry Andric   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
894480093f4SDimitry Andric   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
8950b57cec5SDimitry Andric   QualType QT = Dst.getType();
8960b57cec5SDimitry Andric   GenBinaryFuncName<false> GenName("__copy_assignment_", DstPtr.getAlignment(),
8970b57cec5SDimitry Andric                                    SrcPtr.getAlignment(), getContext());
8980b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
8990b57cec5SDimitry Andric   callSpecialFunction(GenCopyAssignment(getContext()), FuncName, QT, IsVolatile,
9000b57cec5SDimitry Andric                       *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
9010b57cec5SDimitry Andric }
9020b57cec5SDimitry Andric 
callCStructMoveConstructor(LValue Dst,LValue Src)9030b57cec5SDimitry Andric void CodeGenFunction::callCStructMoveConstructor(LValue Dst, LValue Src) {
9040b57cec5SDimitry Andric   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
905480093f4SDimitry Andric   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
9060b57cec5SDimitry Andric   QualType QT = Dst.getType();
9070b57cec5SDimitry Andric   GenBinaryFuncName<true> GenName("__move_constructor_", DstPtr.getAlignment(),
9080b57cec5SDimitry Andric                                   SrcPtr.getAlignment(), getContext());
9090b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
9100b57cec5SDimitry Andric   callSpecialFunction(GenMoveConstructor(getContext()), FuncName, QT,
9110b57cec5SDimitry Andric                       IsVolatile, *this,
9120b57cec5SDimitry Andric                       std::array<Address, 2>({{DstPtr, SrcPtr}}));
9130b57cec5SDimitry Andric }
9140b57cec5SDimitry Andric 
callCStructMoveAssignmentOperator(LValue Dst,LValue Src)9150b57cec5SDimitry Andric void CodeGenFunction::callCStructMoveAssignmentOperator(LValue Dst, LValue Src
9160b57cec5SDimitry Andric 
9170b57cec5SDimitry Andric ) {
9180b57cec5SDimitry Andric   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
919480093f4SDimitry Andric   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
9200b57cec5SDimitry Andric   QualType QT = Dst.getType();
9210b57cec5SDimitry Andric   GenBinaryFuncName<true> GenName("__move_assignment_", DstPtr.getAlignment(),
9220b57cec5SDimitry Andric                                   SrcPtr.getAlignment(), getContext());
9230b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
9240b57cec5SDimitry Andric   callSpecialFunction(GenMoveAssignment(getContext()), FuncName, QT, IsVolatile,
9250b57cec5SDimitry Andric                       *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
9260b57cec5SDimitry Andric }
9270b57cec5SDimitry Andric 
getNonTrivialCStructDefaultConstructor(CodeGenModule & CGM,CharUnits DstAlignment,bool IsVolatile,QualType QT)9280b57cec5SDimitry Andric llvm::Function *clang::CodeGen::getNonTrivialCStructDefaultConstructor(
9290b57cec5SDimitry Andric     CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
9300b57cec5SDimitry Andric   ASTContext &Ctx = CGM.getContext();
9310b57cec5SDimitry Andric   GenDefaultInitializeFuncName GenName(DstAlignment, Ctx);
9320b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
9330b57cec5SDimitry Andric   return getSpecialFunction(GenDefaultInitialize(Ctx), FuncName, QT, IsVolatile,
9340b57cec5SDimitry Andric                             std::array<CharUnits, 1>({{DstAlignment}}), CGM);
9350b57cec5SDimitry Andric }
9360b57cec5SDimitry Andric 
getNonTrivialCStructCopyConstructor(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)9370b57cec5SDimitry Andric llvm::Function *clang::CodeGen::getNonTrivialCStructCopyConstructor(
9380b57cec5SDimitry Andric     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
9390b57cec5SDimitry Andric     bool IsVolatile, QualType QT) {
9400b57cec5SDimitry Andric   ASTContext &Ctx = CGM.getContext();
9410b57cec5SDimitry Andric   GenBinaryFuncName<false> GenName("__copy_constructor_", DstAlignment,
9420b57cec5SDimitry Andric                                    SrcAlignment, Ctx);
9430b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
9440b57cec5SDimitry Andric   return getSpecialFunction(
9450b57cec5SDimitry Andric       GenCopyConstructor(Ctx), FuncName, QT, IsVolatile,
9460b57cec5SDimitry Andric       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
9470b57cec5SDimitry Andric }
9480b57cec5SDimitry Andric 
getNonTrivialCStructMoveConstructor(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)9490b57cec5SDimitry Andric llvm::Function *clang::CodeGen::getNonTrivialCStructMoveConstructor(
9500b57cec5SDimitry Andric     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
9510b57cec5SDimitry Andric     bool IsVolatile, QualType QT) {
9520b57cec5SDimitry Andric   ASTContext &Ctx = CGM.getContext();
9530b57cec5SDimitry Andric   GenBinaryFuncName<true> GenName("__move_constructor_", DstAlignment,
9540b57cec5SDimitry Andric                                   SrcAlignment, Ctx);
9550b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
9560b57cec5SDimitry Andric   return getSpecialFunction(
9570b57cec5SDimitry Andric       GenMoveConstructor(Ctx), FuncName, QT, IsVolatile,
9580b57cec5SDimitry Andric       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
9590b57cec5SDimitry Andric }
9600b57cec5SDimitry Andric 
getNonTrivialCStructCopyAssignmentOperator(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)9610b57cec5SDimitry Andric llvm::Function *clang::CodeGen::getNonTrivialCStructCopyAssignmentOperator(
9620b57cec5SDimitry Andric     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
9630b57cec5SDimitry Andric     bool IsVolatile, QualType QT) {
9640b57cec5SDimitry Andric   ASTContext &Ctx = CGM.getContext();
9650b57cec5SDimitry Andric   GenBinaryFuncName<false> GenName("__copy_assignment_", DstAlignment,
9660b57cec5SDimitry Andric                                    SrcAlignment, Ctx);
9670b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
9680b57cec5SDimitry Andric   return getSpecialFunction(
9690b57cec5SDimitry Andric       GenCopyAssignment(Ctx), FuncName, QT, IsVolatile,
9700b57cec5SDimitry Andric       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
9710b57cec5SDimitry Andric }
9720b57cec5SDimitry Andric 
getNonTrivialCStructMoveAssignmentOperator(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)9730b57cec5SDimitry Andric llvm::Function *clang::CodeGen::getNonTrivialCStructMoveAssignmentOperator(
9740b57cec5SDimitry Andric     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
9750b57cec5SDimitry Andric     bool IsVolatile, QualType QT) {
9760b57cec5SDimitry Andric   ASTContext &Ctx = CGM.getContext();
9770b57cec5SDimitry Andric   GenBinaryFuncName<true> GenName("__move_assignment_", DstAlignment,
9780b57cec5SDimitry Andric                                   SrcAlignment, Ctx);
9790b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
9800b57cec5SDimitry Andric   return getSpecialFunction(
9810b57cec5SDimitry Andric       GenMoveAssignment(Ctx), FuncName, QT, IsVolatile,
9820b57cec5SDimitry Andric       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
9830b57cec5SDimitry Andric }
9840b57cec5SDimitry Andric 
getNonTrivialCStructDestructor(CodeGenModule & CGM,CharUnits DstAlignment,bool IsVolatile,QualType QT)9850b57cec5SDimitry Andric llvm::Function *clang::CodeGen::getNonTrivialCStructDestructor(
9860b57cec5SDimitry Andric     CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
9870b57cec5SDimitry Andric   ASTContext &Ctx = CGM.getContext();
9880b57cec5SDimitry Andric   GenDestructorFuncName GenName("__destructor_", DstAlignment, Ctx);
9890b57cec5SDimitry Andric   std::string FuncName = GenName.getName(QT, IsVolatile);
9900b57cec5SDimitry Andric   return getSpecialFunction(GenDestructor(Ctx), FuncName, QT, IsVolatile,
9910b57cec5SDimitry Andric                             std::array<CharUnits, 1>({{DstAlignment}}), CGM);
9920b57cec5SDimitry Andric }
993