106f32e7eSjoerg //===--- CGNonTrivialStruct.cpp - Emit Special Functions for C Structs ----===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg // This file defines functions to generate various special functions for C
1006f32e7eSjoerg // structs.
1106f32e7eSjoerg //
1206f32e7eSjoerg //===----------------------------------------------------------------------===//
1306f32e7eSjoerg 
1406f32e7eSjoerg #include "CodeGenFunction.h"
1506f32e7eSjoerg #include "CodeGenModule.h"
1606f32e7eSjoerg #include "clang/AST/NonTrivialTypeVisitor.h"
1706f32e7eSjoerg #include "clang/CodeGen/CodeGenABITypes.h"
1806f32e7eSjoerg #include "llvm/Support/ScopedPrinter.h"
1906f32e7eSjoerg #include <array>
2006f32e7eSjoerg 
2106f32e7eSjoerg using namespace clang;
2206f32e7eSjoerg using namespace CodeGen;
2306f32e7eSjoerg 
2406f32e7eSjoerg // Return the size of a field in number of bits.
getFieldSize(const FieldDecl * FD,QualType FT,ASTContext & Ctx)2506f32e7eSjoerg static uint64_t getFieldSize(const FieldDecl *FD, QualType FT,
2606f32e7eSjoerg                              ASTContext &Ctx) {
2706f32e7eSjoerg   if (FD && FD->isBitField())
2806f32e7eSjoerg     return FD->getBitWidthValue(Ctx);
2906f32e7eSjoerg   return Ctx.getTypeSize(FT);
3006f32e7eSjoerg }
3106f32e7eSjoerg 
3206f32e7eSjoerg namespace {
3306f32e7eSjoerg enum { DstIdx = 0, SrcIdx = 1 };
3406f32e7eSjoerg const char *ValNameStr[2] = {"dst", "src"};
3506f32e7eSjoerg 
3606f32e7eSjoerg template <class Derived> struct StructVisitor {
StructVisitor__anon4ebc9cf40111::StructVisitor3706f32e7eSjoerg   StructVisitor(ASTContext &Ctx) : Ctx(Ctx) {}
3806f32e7eSjoerg 
3906f32e7eSjoerg   template <class... Ts>
visitStructFields__anon4ebc9cf40111::StructVisitor4006f32e7eSjoerg   void visitStructFields(QualType QT, CharUnits CurStructOffset, Ts... Args) {
4106f32e7eSjoerg     const RecordDecl *RD = QT->castAs<RecordType>()->getDecl();
4206f32e7eSjoerg 
4306f32e7eSjoerg     // Iterate over the fields of the struct.
4406f32e7eSjoerg     for (const FieldDecl *FD : RD->fields()) {
4506f32e7eSjoerg       QualType FT = FD->getType();
4606f32e7eSjoerg       FT = QT.isVolatileQualified() ? FT.withVolatile() : FT;
4706f32e7eSjoerg       asDerived().visit(FT, FD, CurStructOffset, Args...);
4806f32e7eSjoerg     }
4906f32e7eSjoerg 
5006f32e7eSjoerg     asDerived().flushTrivialFields(Args...);
5106f32e7eSjoerg   }
5206f32e7eSjoerg 
visitTrivial__anon4ebc9cf40111::StructVisitor5306f32e7eSjoerg   template <class... Ts> void visitTrivial(Ts... Args) {}
5406f32e7eSjoerg 
visitCXXDestructor__anon4ebc9cf40111::StructVisitor5506f32e7eSjoerg   template <class... Ts> void visitCXXDestructor(Ts... Args) {
5606f32e7eSjoerg     llvm_unreachable("field of a C++ struct type is not expected");
5706f32e7eSjoerg   }
5806f32e7eSjoerg 
flushTrivialFields__anon4ebc9cf40111::StructVisitor5906f32e7eSjoerg   template <class... Ts> void flushTrivialFields(Ts... Args) {}
6006f32e7eSjoerg 
getFieldOffsetInBits__anon4ebc9cf40111::StructVisitor6106f32e7eSjoerg   uint64_t getFieldOffsetInBits(const FieldDecl *FD) {
6206f32e7eSjoerg     return FD ? Ctx.getASTRecordLayout(FD->getParent())
6306f32e7eSjoerg                     .getFieldOffset(FD->getFieldIndex())
6406f32e7eSjoerg               : 0;
6506f32e7eSjoerg   }
6606f32e7eSjoerg 
getFieldOffset__anon4ebc9cf40111::StructVisitor6706f32e7eSjoerg   CharUnits getFieldOffset(const FieldDecl *FD) {
6806f32e7eSjoerg     return Ctx.toCharUnitsFromBits(getFieldOffsetInBits(FD));
6906f32e7eSjoerg   }
7006f32e7eSjoerg 
asDerived__anon4ebc9cf40111::StructVisitor7106f32e7eSjoerg   Derived &asDerived() { return static_cast<Derived &>(*this); }
7206f32e7eSjoerg 
getContext__anon4ebc9cf40111::StructVisitor7306f32e7eSjoerg   ASTContext &getContext() { return Ctx; }
7406f32e7eSjoerg   ASTContext &Ctx;
7506f32e7eSjoerg };
7606f32e7eSjoerg 
7706f32e7eSjoerg template <class Derived, bool IsMove>
7806f32e7eSjoerg struct CopyStructVisitor : StructVisitor<Derived>,
7906f32e7eSjoerg                            CopiedTypeVisitor<Derived, IsMove> {
8006f32e7eSjoerg   using StructVisitor<Derived>::asDerived;
8106f32e7eSjoerg   using Super = CopiedTypeVisitor<Derived, IsMove>;
8206f32e7eSjoerg 
CopyStructVisitor__anon4ebc9cf40111::CopyStructVisitor8306f32e7eSjoerg   CopyStructVisitor(ASTContext &Ctx) : StructVisitor<Derived>(Ctx) {}
8406f32e7eSjoerg 
8506f32e7eSjoerg   template <class... Ts>
preVisit__anon4ebc9cf40111::CopyStructVisitor8606f32e7eSjoerg   void preVisit(QualType::PrimitiveCopyKind PCK, QualType FT,
8706f32e7eSjoerg                 const FieldDecl *FD, CharUnits CurStructOffset, Ts &&... Args) {
8806f32e7eSjoerg     if (PCK)
8906f32e7eSjoerg       asDerived().flushTrivialFields(std::forward<Ts>(Args)...);
9006f32e7eSjoerg   }
9106f32e7eSjoerg 
9206f32e7eSjoerg   template <class... Ts>
visitWithKind__anon4ebc9cf40111::CopyStructVisitor9306f32e7eSjoerg   void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT,
9406f32e7eSjoerg                      const FieldDecl *FD, CharUnits CurStructOffset,
9506f32e7eSjoerg                      Ts &&... Args) {
9606f32e7eSjoerg     if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
9706f32e7eSjoerg       asDerived().visitArray(PCK, AT, FT.isVolatileQualified(), FD,
9806f32e7eSjoerg                              CurStructOffset, std::forward<Ts>(Args)...);
9906f32e7eSjoerg       return;
10006f32e7eSjoerg     }
10106f32e7eSjoerg 
10206f32e7eSjoerg     Super::visitWithKind(PCK, FT, FD, CurStructOffset,
10306f32e7eSjoerg                          std::forward<Ts>(Args)...);
10406f32e7eSjoerg   }
10506f32e7eSjoerg 
10606f32e7eSjoerg   template <class... Ts>
visitTrivial__anon4ebc9cf40111::CopyStructVisitor10706f32e7eSjoerg   void visitTrivial(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset,
10806f32e7eSjoerg                     Ts... Args) {
10906f32e7eSjoerg     assert(!FT.isVolatileQualified() && "volatile field not expected");
11006f32e7eSjoerg     ASTContext &Ctx = asDerived().getContext();
11106f32e7eSjoerg     uint64_t FieldSize = getFieldSize(FD, FT, Ctx);
11206f32e7eSjoerg 
11306f32e7eSjoerg     // Ignore zero-sized fields.
11406f32e7eSjoerg     if (FieldSize == 0)
11506f32e7eSjoerg       return;
11606f32e7eSjoerg 
11706f32e7eSjoerg     uint64_t FStartInBits = asDerived().getFieldOffsetInBits(FD);
11806f32e7eSjoerg     uint64_t FEndInBits = FStartInBits + FieldSize;
11906f32e7eSjoerg     uint64_t RoundedFEnd = llvm::alignTo(FEndInBits, Ctx.getCharWidth());
12006f32e7eSjoerg 
12106f32e7eSjoerg     // Set Start if this is the first field of a sequence of trivial fields.
12206f32e7eSjoerg     if (Start == End)
12306f32e7eSjoerg       Start = CurStructOffset + Ctx.toCharUnitsFromBits(FStartInBits);
12406f32e7eSjoerg     End = CurStructOffset + Ctx.toCharUnitsFromBits(RoundedFEnd);
12506f32e7eSjoerg   }
12606f32e7eSjoerg 
12706f32e7eSjoerg   CharUnits Start = CharUnits::Zero(), End = CharUnits::Zero();
12806f32e7eSjoerg };
12906f32e7eSjoerg 
13006f32e7eSjoerg // This function creates the mangled name of a special function of a non-trivial
13106f32e7eSjoerg // C struct. Since there is no ODR in C, the function is mangled based on the
13206f32e7eSjoerg // struct contents and not the name. The mangled name has the following
13306f32e7eSjoerg // structure:
13406f32e7eSjoerg //
13506f32e7eSjoerg // <function-name> ::= <prefix> <alignment-info> "_" <struct-field-info>
13606f32e7eSjoerg // <prefix> ::= "__destructor_" | "__default_constructor_" |
13706f32e7eSjoerg //              "__copy_constructor_" | "__move_constructor_" |
13806f32e7eSjoerg //              "__copy_assignment_" | "__move_assignment_"
13906f32e7eSjoerg // <alignment-info> ::= <dst-alignment> ["_" <src-alignment>]
14006f32e7eSjoerg // <struct-field-info> ::= <field-info>+
14106f32e7eSjoerg // <field-info> ::= <struct-or-scalar-field-info> | <array-field-info>
14206f32e7eSjoerg // <struct-or-scalar-field-info> ::= "_S" <struct-field-info> |
14306f32e7eSjoerg //                                   <strong-field-info> | <trivial-field-info>
14406f32e7eSjoerg // <array-field-info> ::= "_AB" <array-offset> "s" <element-size> "n"
14506f32e7eSjoerg //                        <num-elements> <innermost-element-info> "_AE"
14606f32e7eSjoerg // <innermost-element-info> ::= <struct-or-scalar-field-info>
14706f32e7eSjoerg // <strong-field-info> ::= "_s" ["b"] ["v"] <field-offset>
14806f32e7eSjoerg // <trivial-field-info> ::= "_t" ["v"] <field-offset> "_" <field-size>
14906f32e7eSjoerg 
15006f32e7eSjoerg template <class Derived> struct GenFuncNameBase {
getVolatileOffsetStr__anon4ebc9cf40111::GenFuncNameBase15106f32e7eSjoerg   std::string getVolatileOffsetStr(bool IsVolatile, CharUnits Offset) {
15206f32e7eSjoerg     std::string S;
15306f32e7eSjoerg     if (IsVolatile)
15406f32e7eSjoerg       S = "v";
15506f32e7eSjoerg     S += llvm::to_string(Offset.getQuantity());
15606f32e7eSjoerg     return S;
15706f32e7eSjoerg   }
15806f32e7eSjoerg 
visitARCStrong__anon4ebc9cf40111::GenFuncNameBase15906f32e7eSjoerg   void visitARCStrong(QualType FT, const FieldDecl *FD,
16006f32e7eSjoerg                       CharUnits CurStructOffset) {
16106f32e7eSjoerg     appendStr("_s");
16206f32e7eSjoerg     if (FT->isBlockPointerType())
16306f32e7eSjoerg       appendStr("b");
16406f32e7eSjoerg     CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
16506f32e7eSjoerg     appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset));
16606f32e7eSjoerg   }
16706f32e7eSjoerg 
visitARCWeak__anon4ebc9cf40111::GenFuncNameBase16806f32e7eSjoerg   void visitARCWeak(QualType FT, const FieldDecl *FD,
16906f32e7eSjoerg                     CharUnits CurStructOffset) {
17006f32e7eSjoerg     appendStr("_w");
17106f32e7eSjoerg     CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
17206f32e7eSjoerg     appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset));
17306f32e7eSjoerg   }
17406f32e7eSjoerg 
visitStruct__anon4ebc9cf40111::GenFuncNameBase17506f32e7eSjoerg   void visitStruct(QualType QT, const FieldDecl *FD,
17606f32e7eSjoerg                    CharUnits CurStructOffset) {
17706f32e7eSjoerg     CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
17806f32e7eSjoerg     appendStr("_S");
17906f32e7eSjoerg     asDerived().visitStructFields(QT, FieldOffset);
18006f32e7eSjoerg   }
18106f32e7eSjoerg 
18206f32e7eSjoerg   template <class FieldKind>
visitArray__anon4ebc9cf40111::GenFuncNameBase18306f32e7eSjoerg   void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
18406f32e7eSjoerg                   const FieldDecl *FD, CharUnits CurStructOffset) {
18506f32e7eSjoerg     // String for non-volatile trivial fields is emitted when
18606f32e7eSjoerg     // flushTrivialFields is called.
18706f32e7eSjoerg     if (!FK)
18806f32e7eSjoerg       return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset);
18906f32e7eSjoerg 
19006f32e7eSjoerg     asDerived().flushTrivialFields();
19106f32e7eSjoerg     CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
19206f32e7eSjoerg     ASTContext &Ctx = asDerived().getContext();
19306f32e7eSjoerg     const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
19406f32e7eSjoerg     unsigned NumElts = Ctx.getConstantArrayElementCount(CAT);
19506f32e7eSjoerg     QualType EltTy = Ctx.getBaseElementType(CAT);
19606f32e7eSjoerg     CharUnits EltSize = Ctx.getTypeSizeInChars(EltTy);
19706f32e7eSjoerg     appendStr("_AB" + llvm::to_string(FieldOffset.getQuantity()) + "s" +
19806f32e7eSjoerg               llvm::to_string(EltSize.getQuantity()) + "n" +
19906f32e7eSjoerg               llvm::to_string(NumElts));
20006f32e7eSjoerg     EltTy = IsVolatile ? EltTy.withVolatile() : EltTy;
20106f32e7eSjoerg     asDerived().visitWithKind(FK, EltTy, nullptr, FieldOffset);
20206f32e7eSjoerg     appendStr("_AE");
20306f32e7eSjoerg   }
20406f32e7eSjoerg 
appendStr__anon4ebc9cf40111::GenFuncNameBase20506f32e7eSjoerg   void appendStr(StringRef Str) { Name += Str; }
20606f32e7eSjoerg 
getName__anon4ebc9cf40111::GenFuncNameBase20706f32e7eSjoerg   std::string getName(QualType QT, bool IsVolatile) {
20806f32e7eSjoerg     QT = IsVolatile ? QT.withVolatile() : QT;
20906f32e7eSjoerg     asDerived().visitStructFields(QT, CharUnits::Zero());
21006f32e7eSjoerg     return Name;
21106f32e7eSjoerg   }
21206f32e7eSjoerg 
asDerived__anon4ebc9cf40111::GenFuncNameBase21306f32e7eSjoerg   Derived &asDerived() { return static_cast<Derived &>(*this); }
21406f32e7eSjoerg 
21506f32e7eSjoerg   std::string Name;
21606f32e7eSjoerg };
21706f32e7eSjoerg 
21806f32e7eSjoerg template <class Derived>
21906f32e7eSjoerg struct GenUnaryFuncName : StructVisitor<Derived>, GenFuncNameBase<Derived> {
GenUnaryFuncName__anon4ebc9cf40111::GenUnaryFuncName22006f32e7eSjoerg   GenUnaryFuncName(StringRef Prefix, CharUnits DstAlignment, ASTContext &Ctx)
22106f32e7eSjoerg       : StructVisitor<Derived>(Ctx) {
22206f32e7eSjoerg     this->appendStr(Prefix);
22306f32e7eSjoerg     this->appendStr(llvm::to_string(DstAlignment.getQuantity()));
22406f32e7eSjoerg   }
22506f32e7eSjoerg };
22606f32e7eSjoerg 
22706f32e7eSjoerg // Helper function to create a null constant.
getNullForVariable(Address Addr)22806f32e7eSjoerg static llvm::Constant *getNullForVariable(Address Addr) {
22906f32e7eSjoerg   llvm::Type *Ty = Addr.getElementType();
23006f32e7eSjoerg   return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(Ty));
23106f32e7eSjoerg }
23206f32e7eSjoerg 
23306f32e7eSjoerg template <bool IsMove>
23406f32e7eSjoerg struct GenBinaryFuncName : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>,
23506f32e7eSjoerg                            GenFuncNameBase<GenBinaryFuncName<IsMove>> {
23606f32e7eSjoerg 
GenBinaryFuncName__anon4ebc9cf40111::GenBinaryFuncName23706f32e7eSjoerg   GenBinaryFuncName(StringRef Prefix, CharUnits DstAlignment,
23806f32e7eSjoerg                     CharUnits SrcAlignment, ASTContext &Ctx)
23906f32e7eSjoerg       : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>(Ctx) {
24006f32e7eSjoerg     this->appendStr(Prefix);
24106f32e7eSjoerg     this->appendStr(llvm::to_string(DstAlignment.getQuantity()));
24206f32e7eSjoerg     this->appendStr("_" + llvm::to_string(SrcAlignment.getQuantity()));
24306f32e7eSjoerg   }
24406f32e7eSjoerg 
flushTrivialFields__anon4ebc9cf40111::GenBinaryFuncName24506f32e7eSjoerg   void flushTrivialFields() {
24606f32e7eSjoerg     if (this->Start == this->End)
24706f32e7eSjoerg       return;
24806f32e7eSjoerg 
24906f32e7eSjoerg     this->appendStr("_t" + llvm::to_string(this->Start.getQuantity()) + "w" +
25006f32e7eSjoerg                     llvm::to_string((this->End - this->Start).getQuantity()));
25106f32e7eSjoerg 
25206f32e7eSjoerg     this->Start = this->End = CharUnits::Zero();
25306f32e7eSjoerg   }
25406f32e7eSjoerg 
visitVolatileTrivial__anon4ebc9cf40111::GenBinaryFuncName25506f32e7eSjoerg   void visitVolatileTrivial(QualType FT, const FieldDecl *FD,
25606f32e7eSjoerg                             CharUnits CurStructOffset) {
257*13fbcb42Sjoerg     // Zero-length bit-fields don't need to be copied/assigned.
258*13fbcb42Sjoerg     if (FD && FD->isZeroLengthBitField(this->Ctx))
259*13fbcb42Sjoerg       return;
260*13fbcb42Sjoerg 
26106f32e7eSjoerg     // Because volatile fields can be bit-fields and are individually copied,
26206f32e7eSjoerg     // their offset and width are in bits.
26306f32e7eSjoerg     uint64_t OffsetInBits =
26406f32e7eSjoerg         this->Ctx.toBits(CurStructOffset) + this->getFieldOffsetInBits(FD);
26506f32e7eSjoerg     this->appendStr("_tv" + llvm::to_string(OffsetInBits) + "w" +
26606f32e7eSjoerg                     llvm::to_string(getFieldSize(FD, FT, this->Ctx)));
26706f32e7eSjoerg   }
26806f32e7eSjoerg };
26906f32e7eSjoerg 
27006f32e7eSjoerg struct GenDefaultInitializeFuncName
27106f32e7eSjoerg     : GenUnaryFuncName<GenDefaultInitializeFuncName>,
27206f32e7eSjoerg       DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName> {
27306f32e7eSjoerg   using Super = DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName>;
GenDefaultInitializeFuncName__anon4ebc9cf40111::GenDefaultInitializeFuncName27406f32e7eSjoerg   GenDefaultInitializeFuncName(CharUnits DstAlignment, ASTContext &Ctx)
27506f32e7eSjoerg       : GenUnaryFuncName<GenDefaultInitializeFuncName>("__default_constructor_",
27606f32e7eSjoerg                                                        DstAlignment, Ctx) {}
visitWithKind__anon4ebc9cf40111::GenDefaultInitializeFuncName27706f32e7eSjoerg   void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
27806f32e7eSjoerg                      const FieldDecl *FD, CharUnits CurStructOffset) {
27906f32e7eSjoerg     if (const auto *AT = getContext().getAsArrayType(FT)) {
28006f32e7eSjoerg       visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset);
28106f32e7eSjoerg       return;
28206f32e7eSjoerg     }
28306f32e7eSjoerg 
28406f32e7eSjoerg     Super::visitWithKind(PDIK, FT, FD, CurStructOffset);
28506f32e7eSjoerg   }
28606f32e7eSjoerg };
28706f32e7eSjoerg 
28806f32e7eSjoerg struct GenDestructorFuncName : GenUnaryFuncName<GenDestructorFuncName>,
28906f32e7eSjoerg                                DestructedTypeVisitor<GenDestructorFuncName> {
29006f32e7eSjoerg   using Super = DestructedTypeVisitor<GenDestructorFuncName>;
GenDestructorFuncName__anon4ebc9cf40111::GenDestructorFuncName29106f32e7eSjoerg   GenDestructorFuncName(const char *Prefix, CharUnits DstAlignment,
29206f32e7eSjoerg                         ASTContext &Ctx)
29306f32e7eSjoerg       : GenUnaryFuncName<GenDestructorFuncName>(Prefix, DstAlignment, Ctx) {}
visitWithKind__anon4ebc9cf40111::GenDestructorFuncName29406f32e7eSjoerg   void visitWithKind(QualType::DestructionKind DK, QualType FT,
29506f32e7eSjoerg                      const FieldDecl *FD, CharUnits CurStructOffset) {
29606f32e7eSjoerg     if (const auto *AT = getContext().getAsArrayType(FT)) {
29706f32e7eSjoerg       visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset);
29806f32e7eSjoerg       return;
29906f32e7eSjoerg     }
30006f32e7eSjoerg 
30106f32e7eSjoerg     Super::visitWithKind(DK, FT, FD, CurStructOffset);
30206f32e7eSjoerg   }
30306f32e7eSjoerg };
30406f32e7eSjoerg 
30506f32e7eSjoerg // Helper function that creates CGFunctionInfo for an N-ary special function.
30606f32e7eSjoerg template <size_t N>
getFunctionInfo(CodeGenModule & CGM,FunctionArgList & Args)30706f32e7eSjoerg static const CGFunctionInfo &getFunctionInfo(CodeGenModule &CGM,
30806f32e7eSjoerg                                              FunctionArgList &Args) {
30906f32e7eSjoerg   ASTContext &Ctx = CGM.getContext();
31006f32e7eSjoerg   llvm::SmallVector<ImplicitParamDecl *, N> Params;
31106f32e7eSjoerg   QualType ParamTy = Ctx.getPointerType(Ctx.VoidPtrTy);
31206f32e7eSjoerg 
31306f32e7eSjoerg   for (unsigned I = 0; I < N; ++I)
31406f32e7eSjoerg     Params.push_back(ImplicitParamDecl::Create(
31506f32e7eSjoerg         Ctx, nullptr, SourceLocation(), &Ctx.Idents.get(ValNameStr[I]), ParamTy,
31606f32e7eSjoerg         ImplicitParamDecl::Other));
31706f32e7eSjoerg 
31806f32e7eSjoerg   for (auto &P : Params)
31906f32e7eSjoerg     Args.push_back(P);
32006f32e7eSjoerg 
32106f32e7eSjoerg   return CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args);
32206f32e7eSjoerg }
32306f32e7eSjoerg 
324*13fbcb42Sjoerg template <size_t N, size_t... Ints>
getParamAddrs(std::index_sequence<Ints...> IntSeq,std::array<CharUnits,N> Alignments,FunctionArgList Args,CodeGenFunction * CGF)325*13fbcb42Sjoerg static std::array<Address, N> getParamAddrs(std::index_sequence<Ints...> IntSeq,
326*13fbcb42Sjoerg                                             std::array<CharUnits, N> Alignments,
327*13fbcb42Sjoerg                                             FunctionArgList Args,
328*13fbcb42Sjoerg                                             CodeGenFunction *CGF) {
329*13fbcb42Sjoerg   return std::array<Address, N>{{
330*13fbcb42Sjoerg       Address(CGF->Builder.CreateLoad(CGF->GetAddrOfLocalVar(Args[Ints])),
331*13fbcb42Sjoerg               Alignments[Ints])...}};
332*13fbcb42Sjoerg }
333*13fbcb42Sjoerg 
33406f32e7eSjoerg // Template classes that are used as bases for classes that emit special
33506f32e7eSjoerg // functions.
33606f32e7eSjoerg template <class Derived> struct GenFuncBase {
33706f32e7eSjoerg   template <size_t N>
visitStruct__anon4ebc9cf40111::GenFuncBase33806f32e7eSjoerg   void visitStruct(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset,
33906f32e7eSjoerg                    std::array<Address, N> Addrs) {
34006f32e7eSjoerg     this->asDerived().callSpecialFunction(
34106f32e7eSjoerg         FT, CurStructOffset + asDerived().getFieldOffset(FD), Addrs);
34206f32e7eSjoerg   }
34306f32e7eSjoerg 
34406f32e7eSjoerg   template <class FieldKind, size_t N>
visitArray__anon4ebc9cf40111::GenFuncBase34506f32e7eSjoerg   void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
34606f32e7eSjoerg                   const FieldDecl *FD, CharUnits CurStructOffset,
34706f32e7eSjoerg                   std::array<Address, N> Addrs) {
34806f32e7eSjoerg     // Non-volatile trivial fields are copied when flushTrivialFields is called.
34906f32e7eSjoerg     if (!FK)
35006f32e7eSjoerg       return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset,
35106f32e7eSjoerg                                       Addrs);
35206f32e7eSjoerg 
35306f32e7eSjoerg     asDerived().flushTrivialFields(Addrs);
35406f32e7eSjoerg     CodeGenFunction &CGF = *this->CGF;
35506f32e7eSjoerg     ASTContext &Ctx = CGF.getContext();
35606f32e7eSjoerg 
35706f32e7eSjoerg     // Compute the end address.
35806f32e7eSjoerg     QualType BaseEltQT;
35906f32e7eSjoerg     std::array<Address, N> StartAddrs = Addrs;
36006f32e7eSjoerg     for (unsigned I = 0; I < N; ++I)
36106f32e7eSjoerg       StartAddrs[I] = getAddrWithOffset(Addrs[I], CurStructOffset, FD);
36206f32e7eSjoerg     Address DstAddr = StartAddrs[DstIdx];
36306f32e7eSjoerg     llvm::Value *NumElts = CGF.emitArrayLength(AT, BaseEltQT, DstAddr);
36406f32e7eSjoerg     unsigned BaseEltSize = Ctx.getTypeSizeInChars(BaseEltQT).getQuantity();
36506f32e7eSjoerg     llvm::Value *BaseEltSizeVal =
36606f32e7eSjoerg         llvm::ConstantInt::get(NumElts->getType(), BaseEltSize);
36706f32e7eSjoerg     llvm::Value *SizeInBytes =
36806f32e7eSjoerg         CGF.Builder.CreateNUWMul(BaseEltSizeVal, NumElts);
36906f32e7eSjoerg     Address BC = CGF.Builder.CreateBitCast(DstAddr, CGF.CGM.Int8PtrTy);
37006f32e7eSjoerg     llvm::Value *DstArrayEnd =
371*13fbcb42Sjoerg         CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, BC.getPointer(), SizeInBytes);
37206f32e7eSjoerg     DstArrayEnd = CGF.Builder.CreateBitCast(DstArrayEnd, CGF.CGM.Int8PtrPtrTy,
37306f32e7eSjoerg                                             "dstarray.end");
37406f32e7eSjoerg     llvm::BasicBlock *PreheaderBB = CGF.Builder.GetInsertBlock();
37506f32e7eSjoerg 
37606f32e7eSjoerg     // Create the header block and insert the phi instructions.
37706f32e7eSjoerg     llvm::BasicBlock *HeaderBB = CGF.createBasicBlock("loop.header");
37806f32e7eSjoerg     CGF.EmitBlock(HeaderBB);
37906f32e7eSjoerg     llvm::PHINode *PHIs[N];
38006f32e7eSjoerg 
38106f32e7eSjoerg     for (unsigned I = 0; I < N; ++I) {
38206f32e7eSjoerg       PHIs[I] = CGF.Builder.CreatePHI(CGF.CGM.Int8PtrPtrTy, 2, "addr.cur");
38306f32e7eSjoerg       PHIs[I]->addIncoming(StartAddrs[I].getPointer(), PreheaderBB);
38406f32e7eSjoerg     }
38506f32e7eSjoerg 
38606f32e7eSjoerg     // Create the exit and loop body blocks.
38706f32e7eSjoerg     llvm::BasicBlock *ExitBB = CGF.createBasicBlock("loop.exit");
38806f32e7eSjoerg     llvm::BasicBlock *LoopBB = CGF.createBasicBlock("loop.body");
38906f32e7eSjoerg 
39006f32e7eSjoerg     // Emit the comparison and conditional branch instruction that jumps to
39106f32e7eSjoerg     // either the exit or the loop body.
39206f32e7eSjoerg     llvm::Value *Done =
39306f32e7eSjoerg         CGF.Builder.CreateICmpEQ(PHIs[DstIdx], DstArrayEnd, "done");
39406f32e7eSjoerg     CGF.Builder.CreateCondBr(Done, ExitBB, LoopBB);
39506f32e7eSjoerg 
39606f32e7eSjoerg     // Visit the element of the array in the loop body.
39706f32e7eSjoerg     CGF.EmitBlock(LoopBB);
39806f32e7eSjoerg     QualType EltQT = AT->getElementType();
39906f32e7eSjoerg     CharUnits EltSize = Ctx.getTypeSizeInChars(EltQT);
40006f32e7eSjoerg     std::array<Address, N> NewAddrs = Addrs;
40106f32e7eSjoerg 
40206f32e7eSjoerg     for (unsigned I = 0; I < N; ++I)
40306f32e7eSjoerg       NewAddrs[I] = Address(
40406f32e7eSjoerg           PHIs[I], StartAddrs[I].getAlignment().alignmentAtOffset(EltSize));
40506f32e7eSjoerg 
40606f32e7eSjoerg     EltQT = IsVolatile ? EltQT.withVolatile() : EltQT;
40706f32e7eSjoerg     this->asDerived().visitWithKind(FK, EltQT, nullptr, CharUnits::Zero(),
40806f32e7eSjoerg                                     NewAddrs);
40906f32e7eSjoerg 
41006f32e7eSjoerg     LoopBB = CGF.Builder.GetInsertBlock();
41106f32e7eSjoerg 
41206f32e7eSjoerg     for (unsigned I = 0; I < N; ++I) {
41306f32e7eSjoerg       // Instrs to update the destination and source addresses.
41406f32e7eSjoerg       // Update phi instructions.
41506f32e7eSjoerg       NewAddrs[I] = getAddrWithOffset(NewAddrs[I], EltSize);
41606f32e7eSjoerg       PHIs[I]->addIncoming(NewAddrs[I].getPointer(), LoopBB);
41706f32e7eSjoerg     }
41806f32e7eSjoerg 
41906f32e7eSjoerg     // Insert an unconditional branch to the header block.
42006f32e7eSjoerg     CGF.Builder.CreateBr(HeaderBB);
42106f32e7eSjoerg     CGF.EmitBlock(ExitBB);
42206f32e7eSjoerg   }
42306f32e7eSjoerg 
42406f32e7eSjoerg   /// Return an address with the specified offset from the passed address.
getAddrWithOffset__anon4ebc9cf40111::GenFuncBase42506f32e7eSjoerg   Address getAddrWithOffset(Address Addr, CharUnits Offset) {
42606f32e7eSjoerg     assert(Addr.isValid() && "invalid address");
42706f32e7eSjoerg     if (Offset.getQuantity() == 0)
42806f32e7eSjoerg       return Addr;
42906f32e7eSjoerg     Addr = CGF->Builder.CreateBitCast(Addr, CGF->CGM.Int8PtrTy);
43006f32e7eSjoerg     Addr = CGF->Builder.CreateConstInBoundsGEP(Addr, Offset.getQuantity());
43106f32e7eSjoerg     return CGF->Builder.CreateBitCast(Addr, CGF->CGM.Int8PtrPtrTy);
43206f32e7eSjoerg   }
43306f32e7eSjoerg 
getAddrWithOffset__anon4ebc9cf40111::GenFuncBase43406f32e7eSjoerg   Address getAddrWithOffset(Address Addr, CharUnits StructFieldOffset,
43506f32e7eSjoerg                             const FieldDecl *FD) {
43606f32e7eSjoerg     return getAddrWithOffset(Addr, StructFieldOffset +
43706f32e7eSjoerg                                        asDerived().getFieldOffset(FD));
43806f32e7eSjoerg   }
43906f32e7eSjoerg 
44006f32e7eSjoerg   template <size_t N>
getFunction__anon4ebc9cf40111::GenFuncBase441*13fbcb42Sjoerg   llvm::Function *getFunction(StringRef FuncName, QualType QT,
442*13fbcb42Sjoerg                               std::array<CharUnits, N> Alignments,
443*13fbcb42Sjoerg                               CodeGenModule &CGM) {
44406f32e7eSjoerg     // If the special function already exists in the module, return it.
44506f32e7eSjoerg     if (llvm::Function *F = CGM.getModule().getFunction(FuncName)) {
44606f32e7eSjoerg       bool WrongType = false;
44706f32e7eSjoerg       if (!F->getReturnType()->isVoidTy())
44806f32e7eSjoerg         WrongType = true;
44906f32e7eSjoerg       else {
45006f32e7eSjoerg         for (const llvm::Argument &Arg : F->args())
45106f32e7eSjoerg           if (Arg.getType() != CGM.Int8PtrPtrTy)
45206f32e7eSjoerg             WrongType = true;
45306f32e7eSjoerg       }
45406f32e7eSjoerg 
45506f32e7eSjoerg       if (WrongType) {
456*13fbcb42Sjoerg         std::string FuncName = std::string(F->getName());
45706f32e7eSjoerg         SourceLocation Loc = QT->castAs<RecordType>()->getDecl()->getLocation();
45806f32e7eSjoerg         CGM.Error(Loc, "special function " + FuncName +
45906f32e7eSjoerg                            " for non-trivial C struct has incorrect type");
46006f32e7eSjoerg         return nullptr;
46106f32e7eSjoerg       }
46206f32e7eSjoerg       return F;
46306f32e7eSjoerg     }
46406f32e7eSjoerg 
46506f32e7eSjoerg     ASTContext &Ctx = CGM.getContext();
46606f32e7eSjoerg     FunctionArgList Args;
46706f32e7eSjoerg     const CGFunctionInfo &FI = getFunctionInfo<N>(CGM, Args);
46806f32e7eSjoerg     llvm::FunctionType *FuncTy = CGM.getTypes().GetFunctionType(FI);
46906f32e7eSjoerg     llvm::Function *F =
47006f32e7eSjoerg         llvm::Function::Create(FuncTy, llvm::GlobalValue::LinkOnceODRLinkage,
47106f32e7eSjoerg                                FuncName, &CGM.getModule());
47206f32e7eSjoerg     F->setVisibility(llvm::GlobalValue::HiddenVisibility);
473*13fbcb42Sjoerg     CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F, /*IsThunk=*/false);
47406f32e7eSjoerg     CGM.SetLLVMFunctionAttributesForDefinition(nullptr, F);
47506f32e7eSjoerg     IdentifierInfo *II = &Ctx.Idents.get(FuncName);
47606f32e7eSjoerg     FunctionDecl *FD = FunctionDecl::Create(
47706f32e7eSjoerg         Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(),
47806f32e7eSjoerg         II, Ctx.getFunctionType(Ctx.VoidTy, llvm::None, {}), nullptr,
47906f32e7eSjoerg         SC_PrivateExtern, false, false);
48006f32e7eSjoerg     CodeGenFunction NewCGF(CGM);
48106f32e7eSjoerg     setCGF(&NewCGF);
48206f32e7eSjoerg     CGF->StartFunction(FD, Ctx.VoidTy, F, FI, Args);
483*13fbcb42Sjoerg     std::array<Address, N> Addrs =
484*13fbcb42Sjoerg         getParamAddrs<N>(std::make_index_sequence<N>{}, Alignments, Args, CGF);
48506f32e7eSjoerg     asDerived().visitStructFields(QT, CharUnits::Zero(), Addrs);
48606f32e7eSjoerg     CGF->FinishFunction();
48706f32e7eSjoerg     return F;
48806f32e7eSjoerg   }
48906f32e7eSjoerg 
49006f32e7eSjoerg   template <size_t N>
callFunc__anon4ebc9cf40111::GenFuncBase49106f32e7eSjoerg   void callFunc(StringRef FuncName, QualType QT, std::array<Address, N> Addrs,
49206f32e7eSjoerg                 CodeGenFunction &CallerCGF) {
49306f32e7eSjoerg     std::array<CharUnits, N> Alignments;
49406f32e7eSjoerg     llvm::Value *Ptrs[N];
49506f32e7eSjoerg 
49606f32e7eSjoerg     for (unsigned I = 0; I < N; ++I) {
49706f32e7eSjoerg       Alignments[I] = Addrs[I].getAlignment();
49806f32e7eSjoerg       Ptrs[I] =
49906f32e7eSjoerg           CallerCGF.Builder.CreateBitCast(Addrs[I], CallerCGF.CGM.Int8PtrPtrTy)
50006f32e7eSjoerg               .getPointer();
50106f32e7eSjoerg     }
50206f32e7eSjoerg 
50306f32e7eSjoerg     if (llvm::Function *F =
504*13fbcb42Sjoerg             getFunction(FuncName, QT, Alignments, CallerCGF.CGM))
50506f32e7eSjoerg       CallerCGF.EmitNounwindRuntimeCall(F, Ptrs);
50606f32e7eSjoerg   }
50706f32e7eSjoerg 
asDerived__anon4ebc9cf40111::GenFuncBase50806f32e7eSjoerg   Derived &asDerived() { return static_cast<Derived &>(*this); }
50906f32e7eSjoerg 
setCGF__anon4ebc9cf40111::GenFuncBase51006f32e7eSjoerg   void setCGF(CodeGenFunction *F) { CGF = F; }
51106f32e7eSjoerg 
51206f32e7eSjoerg   CodeGenFunction *CGF = nullptr;
51306f32e7eSjoerg };
51406f32e7eSjoerg 
51506f32e7eSjoerg template <class Derived, bool IsMove>
51606f32e7eSjoerg struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>,
51706f32e7eSjoerg                        GenFuncBase<Derived> {
GenBinaryFunc__anon4ebc9cf40111::GenBinaryFunc51806f32e7eSjoerg   GenBinaryFunc(ASTContext &Ctx) : CopyStructVisitor<Derived, IsMove>(Ctx) {}
51906f32e7eSjoerg 
flushTrivialFields__anon4ebc9cf40111::GenBinaryFunc52006f32e7eSjoerg   void flushTrivialFields(std::array<Address, 2> Addrs) {
52106f32e7eSjoerg     CharUnits Size = this->End - this->Start;
52206f32e7eSjoerg 
52306f32e7eSjoerg     if (Size.getQuantity() == 0)
52406f32e7eSjoerg       return;
52506f32e7eSjoerg 
52606f32e7eSjoerg     Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], this->Start);
52706f32e7eSjoerg     Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], this->Start);
52806f32e7eSjoerg 
52906f32e7eSjoerg     // Emit memcpy.
53006f32e7eSjoerg     if (Size.getQuantity() >= 16 || !llvm::isPowerOf2_32(Size.getQuantity())) {
53106f32e7eSjoerg       llvm::Value *SizeVal =
53206f32e7eSjoerg           llvm::ConstantInt::get(this->CGF->SizeTy, Size.getQuantity());
53306f32e7eSjoerg       DstAddr =
53406f32e7eSjoerg           this->CGF->Builder.CreateElementBitCast(DstAddr, this->CGF->Int8Ty);
53506f32e7eSjoerg       SrcAddr =
53606f32e7eSjoerg           this->CGF->Builder.CreateElementBitCast(SrcAddr, this->CGF->Int8Ty);
53706f32e7eSjoerg       this->CGF->Builder.CreateMemCpy(DstAddr, SrcAddr, SizeVal, false);
53806f32e7eSjoerg     } else {
53906f32e7eSjoerg       llvm::Type *Ty = llvm::Type::getIntNTy(
54006f32e7eSjoerg           this->CGF->getLLVMContext(),
54106f32e7eSjoerg           Size.getQuantity() * this->CGF->getContext().getCharWidth());
54206f32e7eSjoerg       DstAddr = this->CGF->Builder.CreateElementBitCast(DstAddr, Ty);
54306f32e7eSjoerg       SrcAddr = this->CGF->Builder.CreateElementBitCast(SrcAddr, Ty);
54406f32e7eSjoerg       llvm::Value *SrcVal = this->CGF->Builder.CreateLoad(SrcAddr, false);
54506f32e7eSjoerg       this->CGF->Builder.CreateStore(SrcVal, DstAddr, false);
54606f32e7eSjoerg     }
54706f32e7eSjoerg 
54806f32e7eSjoerg     this->Start = this->End = CharUnits::Zero();
54906f32e7eSjoerg   }
55006f32e7eSjoerg 
55106f32e7eSjoerg   template <class... Ts>
visitVolatileTrivial__anon4ebc9cf40111::GenBinaryFunc55206f32e7eSjoerg   void visitVolatileTrivial(QualType FT, const FieldDecl *FD, CharUnits Offset,
55306f32e7eSjoerg                             std::array<Address, 2> Addrs) {
55406f32e7eSjoerg     LValue DstLV, SrcLV;
55506f32e7eSjoerg     if (FD) {
556*13fbcb42Sjoerg       // No need to copy zero-length bit-fields.
557*13fbcb42Sjoerg       if (FD->isZeroLengthBitField(this->CGF->getContext()))
558*13fbcb42Sjoerg         return;
559*13fbcb42Sjoerg 
56006f32e7eSjoerg       QualType RT = QualType(FD->getParent()->getTypeForDecl(), 0);
56106f32e7eSjoerg       llvm::PointerType *PtrTy = this->CGF->ConvertType(RT)->getPointerTo();
56206f32e7eSjoerg       Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset);
56306f32e7eSjoerg       LValue DstBase = this->CGF->MakeAddrLValue(
56406f32e7eSjoerg           this->CGF->Builder.CreateBitCast(DstAddr, PtrTy), FT);
56506f32e7eSjoerg       DstLV = this->CGF->EmitLValueForField(DstBase, FD);
56606f32e7eSjoerg       Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], Offset);
56706f32e7eSjoerg       LValue SrcBase = this->CGF->MakeAddrLValue(
56806f32e7eSjoerg           this->CGF->Builder.CreateBitCast(SrcAddr, PtrTy), FT);
56906f32e7eSjoerg       SrcLV = this->CGF->EmitLValueForField(SrcBase, FD);
57006f32e7eSjoerg     } else {
571*13fbcb42Sjoerg       llvm::PointerType *Ty = this->CGF->ConvertTypeForMem(FT)->getPointerTo();
57206f32e7eSjoerg       Address DstAddr = this->CGF->Builder.CreateBitCast(Addrs[DstIdx], Ty);
57306f32e7eSjoerg       Address SrcAddr = this->CGF->Builder.CreateBitCast(Addrs[SrcIdx], Ty);
57406f32e7eSjoerg       DstLV = this->CGF->MakeAddrLValue(DstAddr, FT);
57506f32e7eSjoerg       SrcLV = this->CGF->MakeAddrLValue(SrcAddr, FT);
57606f32e7eSjoerg     }
57706f32e7eSjoerg     RValue SrcVal = this->CGF->EmitLoadOfLValue(SrcLV, SourceLocation());
57806f32e7eSjoerg     this->CGF->EmitStoreThroughLValue(SrcVal, DstLV);
57906f32e7eSjoerg   }
58006f32e7eSjoerg };
58106f32e7eSjoerg 
58206f32e7eSjoerg // These classes that emit the special functions for a non-trivial struct.
58306f32e7eSjoerg struct GenDestructor : StructVisitor<GenDestructor>,
58406f32e7eSjoerg                        GenFuncBase<GenDestructor>,
58506f32e7eSjoerg                        DestructedTypeVisitor<GenDestructor> {
58606f32e7eSjoerg   using Super = DestructedTypeVisitor<GenDestructor>;
GenDestructor__anon4ebc9cf40111::GenDestructor58706f32e7eSjoerg   GenDestructor(ASTContext &Ctx) : StructVisitor<GenDestructor>(Ctx) {}
58806f32e7eSjoerg 
visitWithKind__anon4ebc9cf40111::GenDestructor58906f32e7eSjoerg   void visitWithKind(QualType::DestructionKind DK, QualType FT,
59006f32e7eSjoerg                      const FieldDecl *FD, CharUnits CurStructOffset,
59106f32e7eSjoerg                      std::array<Address, 1> Addrs) {
59206f32e7eSjoerg     if (const auto *AT = getContext().getAsArrayType(FT)) {
59306f32e7eSjoerg       visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset, Addrs);
59406f32e7eSjoerg       return;
59506f32e7eSjoerg     }
59606f32e7eSjoerg 
59706f32e7eSjoerg     Super::visitWithKind(DK, FT, FD, CurStructOffset, Addrs);
59806f32e7eSjoerg   }
59906f32e7eSjoerg 
visitARCStrong__anon4ebc9cf40111::GenDestructor60006f32e7eSjoerg   void visitARCStrong(QualType QT, const FieldDecl *FD,
60106f32e7eSjoerg                       CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
60206f32e7eSjoerg     CGF->destroyARCStrongImprecise(
60306f32e7eSjoerg         *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
60406f32e7eSjoerg   }
60506f32e7eSjoerg 
visitARCWeak__anon4ebc9cf40111::GenDestructor60606f32e7eSjoerg   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
60706f32e7eSjoerg                     std::array<Address, 1> Addrs) {
60806f32e7eSjoerg     CGF->destroyARCWeak(
60906f32e7eSjoerg         *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
61006f32e7eSjoerg   }
61106f32e7eSjoerg 
callSpecialFunction__anon4ebc9cf40111::GenDestructor61206f32e7eSjoerg   void callSpecialFunction(QualType FT, CharUnits Offset,
61306f32e7eSjoerg                            std::array<Address, 1> Addrs) {
61406f32e7eSjoerg     CGF->callCStructDestructor(
61506f32e7eSjoerg         CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
61606f32e7eSjoerg   }
61706f32e7eSjoerg };
61806f32e7eSjoerg 
61906f32e7eSjoerg struct GenDefaultInitialize
62006f32e7eSjoerg     : StructVisitor<GenDefaultInitialize>,
62106f32e7eSjoerg       GenFuncBase<GenDefaultInitialize>,
62206f32e7eSjoerg       DefaultInitializedTypeVisitor<GenDefaultInitialize> {
62306f32e7eSjoerg   using Super = DefaultInitializedTypeVisitor<GenDefaultInitialize>;
62406f32e7eSjoerg   typedef GenFuncBase<GenDefaultInitialize> GenFuncBaseTy;
62506f32e7eSjoerg 
GenDefaultInitialize__anon4ebc9cf40111::GenDefaultInitialize62606f32e7eSjoerg   GenDefaultInitialize(ASTContext &Ctx)
62706f32e7eSjoerg       : StructVisitor<GenDefaultInitialize>(Ctx) {}
62806f32e7eSjoerg 
visitWithKind__anon4ebc9cf40111::GenDefaultInitialize62906f32e7eSjoerg   void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
63006f32e7eSjoerg                      const FieldDecl *FD, CharUnits CurStructOffset,
63106f32e7eSjoerg                      std::array<Address, 1> Addrs) {
63206f32e7eSjoerg     if (const auto *AT = getContext().getAsArrayType(FT)) {
63306f32e7eSjoerg       visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset,
63406f32e7eSjoerg                  Addrs);
63506f32e7eSjoerg       return;
63606f32e7eSjoerg     }
63706f32e7eSjoerg 
63806f32e7eSjoerg     Super::visitWithKind(PDIK, FT, FD, CurStructOffset, Addrs);
63906f32e7eSjoerg   }
64006f32e7eSjoerg 
visitARCStrong__anon4ebc9cf40111::GenDefaultInitialize64106f32e7eSjoerg   void visitARCStrong(QualType QT, const FieldDecl *FD,
64206f32e7eSjoerg                       CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
64306f32e7eSjoerg     CGF->EmitNullInitialization(
64406f32e7eSjoerg         getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
64506f32e7eSjoerg   }
64606f32e7eSjoerg 
visitARCWeak__anon4ebc9cf40111::GenDefaultInitialize64706f32e7eSjoerg   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
64806f32e7eSjoerg                     std::array<Address, 1> Addrs) {
64906f32e7eSjoerg     CGF->EmitNullInitialization(
65006f32e7eSjoerg         getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
65106f32e7eSjoerg   }
65206f32e7eSjoerg 
65306f32e7eSjoerg   template <class FieldKind, size_t... Is>
visitArray__anon4ebc9cf40111::GenDefaultInitialize65406f32e7eSjoerg   void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
65506f32e7eSjoerg                   const FieldDecl *FD, CharUnits CurStructOffset,
65606f32e7eSjoerg                   std::array<Address, 1> Addrs) {
65706f32e7eSjoerg     if (!FK)
65806f32e7eSjoerg       return visitTrivial(QualType(AT, 0), FD, CurStructOffset, Addrs);
65906f32e7eSjoerg 
66006f32e7eSjoerg     ASTContext &Ctx = getContext();
66106f32e7eSjoerg     CharUnits Size = Ctx.getTypeSizeInChars(QualType(AT, 0));
66206f32e7eSjoerg     QualType EltTy = Ctx.getBaseElementType(QualType(AT, 0));
66306f32e7eSjoerg 
66406f32e7eSjoerg     if (Size < CharUnits::fromQuantity(16) || EltTy->getAs<RecordType>()) {
66506f32e7eSjoerg       GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStructOffset, Addrs);
66606f32e7eSjoerg       return;
66706f32e7eSjoerg     }
66806f32e7eSjoerg 
66906f32e7eSjoerg     llvm::Constant *SizeVal = CGF->Builder.getInt64(Size.getQuantity());
67006f32e7eSjoerg     Address DstAddr = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
67106f32e7eSjoerg     Address Loc = CGF->Builder.CreateElementBitCast(DstAddr, CGF->Int8Ty);
67206f32e7eSjoerg     CGF->Builder.CreateMemSet(Loc, CGF->Builder.getInt8(0), SizeVal,
67306f32e7eSjoerg                               IsVolatile);
67406f32e7eSjoerg   }
67506f32e7eSjoerg 
callSpecialFunction__anon4ebc9cf40111::GenDefaultInitialize67606f32e7eSjoerg   void callSpecialFunction(QualType FT, CharUnits Offset,
67706f32e7eSjoerg                            std::array<Address, 1> Addrs) {
67806f32e7eSjoerg     CGF->callCStructDefaultConstructor(
67906f32e7eSjoerg         CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
68006f32e7eSjoerg   }
68106f32e7eSjoerg };
68206f32e7eSjoerg 
68306f32e7eSjoerg struct GenCopyConstructor : GenBinaryFunc<GenCopyConstructor, false> {
GenCopyConstructor__anon4ebc9cf40111::GenCopyConstructor68406f32e7eSjoerg   GenCopyConstructor(ASTContext &Ctx)
68506f32e7eSjoerg       : GenBinaryFunc<GenCopyConstructor, false>(Ctx) {}
68606f32e7eSjoerg 
visitARCStrong__anon4ebc9cf40111::GenCopyConstructor68706f32e7eSjoerg   void visitARCStrong(QualType QT, const FieldDecl *FD,
68806f32e7eSjoerg                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
68906f32e7eSjoerg     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
69006f32e7eSjoerg     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
69106f32e7eSjoerg     llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
69206f32e7eSjoerg         Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
69306f32e7eSjoerg     llvm::Value *Val = CGF->EmitARCRetain(QT, SrcVal);
69406f32e7eSjoerg     CGF->EmitStoreOfScalar(Val, CGF->MakeAddrLValue(Addrs[DstIdx], QT), true);
69506f32e7eSjoerg   }
69606f32e7eSjoerg 
visitARCWeak__anon4ebc9cf40111::GenCopyConstructor69706f32e7eSjoerg   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
69806f32e7eSjoerg                     std::array<Address, 2> Addrs) {
69906f32e7eSjoerg     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
70006f32e7eSjoerg     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
70106f32e7eSjoerg     CGF->EmitARCCopyWeak(Addrs[DstIdx], Addrs[SrcIdx]);
70206f32e7eSjoerg   }
70306f32e7eSjoerg 
callSpecialFunction__anon4ebc9cf40111::GenCopyConstructor70406f32e7eSjoerg   void callSpecialFunction(QualType FT, CharUnits Offset,
70506f32e7eSjoerg                            std::array<Address, 2> Addrs) {
70606f32e7eSjoerg     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
70706f32e7eSjoerg     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
70806f32e7eSjoerg     CGF->callCStructCopyConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
70906f32e7eSjoerg                                     CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
71006f32e7eSjoerg   }
71106f32e7eSjoerg };
71206f32e7eSjoerg 
71306f32e7eSjoerg struct GenMoveConstructor : GenBinaryFunc<GenMoveConstructor, true> {
GenMoveConstructor__anon4ebc9cf40111::GenMoveConstructor71406f32e7eSjoerg   GenMoveConstructor(ASTContext &Ctx)
71506f32e7eSjoerg       : GenBinaryFunc<GenMoveConstructor, true>(Ctx) {}
71606f32e7eSjoerg 
visitARCStrong__anon4ebc9cf40111::GenMoveConstructor71706f32e7eSjoerg   void visitARCStrong(QualType QT, const FieldDecl *FD,
71806f32e7eSjoerg                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
71906f32e7eSjoerg     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
72006f32e7eSjoerg     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
72106f32e7eSjoerg     LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
72206f32e7eSjoerg     llvm::Value *SrcVal =
72306f32e7eSjoerg         CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
724*13fbcb42Sjoerg     CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress(*CGF)), SrcLV);
72506f32e7eSjoerg     CGF->EmitStoreOfScalar(SrcVal, CGF->MakeAddrLValue(Addrs[DstIdx], QT),
72606f32e7eSjoerg                            /* isInitialization */ true);
72706f32e7eSjoerg   }
72806f32e7eSjoerg 
visitARCWeak__anon4ebc9cf40111::GenMoveConstructor72906f32e7eSjoerg   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
73006f32e7eSjoerg                     std::array<Address, 2> Addrs) {
73106f32e7eSjoerg     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
73206f32e7eSjoerg     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
73306f32e7eSjoerg     CGF->EmitARCMoveWeak(Addrs[DstIdx], Addrs[SrcIdx]);
73406f32e7eSjoerg   }
73506f32e7eSjoerg 
callSpecialFunction__anon4ebc9cf40111::GenMoveConstructor73606f32e7eSjoerg   void callSpecialFunction(QualType FT, CharUnits Offset,
73706f32e7eSjoerg                            std::array<Address, 2> Addrs) {
73806f32e7eSjoerg     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
73906f32e7eSjoerg     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
74006f32e7eSjoerg     CGF->callCStructMoveConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
74106f32e7eSjoerg                                     CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
74206f32e7eSjoerg   }
74306f32e7eSjoerg };
74406f32e7eSjoerg 
74506f32e7eSjoerg struct GenCopyAssignment : GenBinaryFunc<GenCopyAssignment, false> {
GenCopyAssignment__anon4ebc9cf40111::GenCopyAssignment74606f32e7eSjoerg   GenCopyAssignment(ASTContext &Ctx)
74706f32e7eSjoerg       : GenBinaryFunc<GenCopyAssignment, false>(Ctx) {}
74806f32e7eSjoerg 
visitARCStrong__anon4ebc9cf40111::GenCopyAssignment74906f32e7eSjoerg   void visitARCStrong(QualType QT, const FieldDecl *FD,
75006f32e7eSjoerg                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
75106f32e7eSjoerg     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
75206f32e7eSjoerg     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
75306f32e7eSjoerg     llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
75406f32e7eSjoerg         Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
75506f32e7eSjoerg     CGF->EmitARCStoreStrong(CGF->MakeAddrLValue(Addrs[DstIdx], QT), SrcVal,
75606f32e7eSjoerg                             false);
75706f32e7eSjoerg   }
75806f32e7eSjoerg 
visitARCWeak__anon4ebc9cf40111::GenCopyAssignment75906f32e7eSjoerg   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
76006f32e7eSjoerg                     std::array<Address, 2> Addrs) {
76106f32e7eSjoerg     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
76206f32e7eSjoerg     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
76306f32e7eSjoerg     CGF->emitARCCopyAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
76406f32e7eSjoerg   }
76506f32e7eSjoerg 
callSpecialFunction__anon4ebc9cf40111::GenCopyAssignment76606f32e7eSjoerg   void callSpecialFunction(QualType FT, CharUnits Offset,
76706f32e7eSjoerg                            std::array<Address, 2> Addrs) {
76806f32e7eSjoerg     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
76906f32e7eSjoerg     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
77006f32e7eSjoerg     CGF->callCStructCopyAssignmentOperator(
77106f32e7eSjoerg         CGF->MakeAddrLValue(Addrs[DstIdx], FT),
77206f32e7eSjoerg         CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
77306f32e7eSjoerg   }
77406f32e7eSjoerg };
77506f32e7eSjoerg 
77606f32e7eSjoerg struct GenMoveAssignment : GenBinaryFunc<GenMoveAssignment, true> {
GenMoveAssignment__anon4ebc9cf40111::GenMoveAssignment77706f32e7eSjoerg   GenMoveAssignment(ASTContext &Ctx)
77806f32e7eSjoerg       : GenBinaryFunc<GenMoveAssignment, true>(Ctx) {}
77906f32e7eSjoerg 
visitARCStrong__anon4ebc9cf40111::GenMoveAssignment78006f32e7eSjoerg   void visitARCStrong(QualType QT, const FieldDecl *FD,
78106f32e7eSjoerg                       CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
78206f32e7eSjoerg     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
78306f32e7eSjoerg     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
78406f32e7eSjoerg     LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
78506f32e7eSjoerg     llvm::Value *SrcVal =
78606f32e7eSjoerg         CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
787*13fbcb42Sjoerg     CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress(*CGF)), SrcLV);
78806f32e7eSjoerg     LValue DstLV = CGF->MakeAddrLValue(Addrs[DstIdx], QT);
78906f32e7eSjoerg     llvm::Value *DstVal =
79006f32e7eSjoerg         CGF->EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
79106f32e7eSjoerg     CGF->EmitStoreOfScalar(SrcVal, DstLV);
79206f32e7eSjoerg     CGF->EmitARCRelease(DstVal, ARCImpreciseLifetime);
79306f32e7eSjoerg   }
79406f32e7eSjoerg 
visitARCWeak__anon4ebc9cf40111::GenMoveAssignment79506f32e7eSjoerg   void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
79606f32e7eSjoerg                     std::array<Address, 2> Addrs) {
79706f32e7eSjoerg     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
79806f32e7eSjoerg     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
79906f32e7eSjoerg     CGF->emitARCMoveAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
80006f32e7eSjoerg   }
80106f32e7eSjoerg 
callSpecialFunction__anon4ebc9cf40111::GenMoveAssignment80206f32e7eSjoerg   void callSpecialFunction(QualType FT, CharUnits Offset,
80306f32e7eSjoerg                            std::array<Address, 2> Addrs) {
80406f32e7eSjoerg     Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
80506f32e7eSjoerg     Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
80606f32e7eSjoerg     CGF->callCStructMoveAssignmentOperator(
80706f32e7eSjoerg         CGF->MakeAddrLValue(Addrs[DstIdx], FT),
80806f32e7eSjoerg         CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
80906f32e7eSjoerg   }
81006f32e7eSjoerg };
81106f32e7eSjoerg 
81206f32e7eSjoerg } // namespace
81306f32e7eSjoerg 
destroyNonTrivialCStruct(CodeGenFunction & CGF,Address Addr,QualType Type)81406f32e7eSjoerg void CodeGenFunction::destroyNonTrivialCStruct(CodeGenFunction &CGF,
81506f32e7eSjoerg                                                Address Addr, QualType Type) {
81606f32e7eSjoerg   CGF.callCStructDestructor(CGF.MakeAddrLValue(Addr, Type));
81706f32e7eSjoerg }
81806f32e7eSjoerg 
81906f32e7eSjoerg // Default-initialize a variable that is a non-trivial struct or an array of
82006f32e7eSjoerg // such structure.
defaultInitNonTrivialCStructVar(LValue Dst)82106f32e7eSjoerg void CodeGenFunction::defaultInitNonTrivialCStructVar(LValue Dst) {
82206f32e7eSjoerg   GenDefaultInitialize Gen(getContext());
823*13fbcb42Sjoerg   Address DstPtr =
824*13fbcb42Sjoerg       Builder.CreateBitCast(Dst.getAddress(*this), CGM.Int8PtrPtrTy);
82506f32e7eSjoerg   Gen.setCGF(this);
82606f32e7eSjoerg   QualType QT = Dst.getType();
82706f32e7eSjoerg   QT = Dst.isVolatile() ? QT.withVolatile() : QT;
82806f32e7eSjoerg   Gen.visit(QT, nullptr, CharUnits::Zero(), std::array<Address, 1>({{DstPtr}}));
82906f32e7eSjoerg }
83006f32e7eSjoerg 
83106f32e7eSjoerg template <class G, size_t N>
callSpecialFunction(G && Gen,StringRef FuncName,QualType QT,bool IsVolatile,CodeGenFunction & CGF,std::array<Address,N> Addrs)83206f32e7eSjoerg static void callSpecialFunction(G &&Gen, StringRef FuncName, QualType QT,
83306f32e7eSjoerg                                 bool IsVolatile, CodeGenFunction &CGF,
83406f32e7eSjoerg                                 std::array<Address, N> Addrs) {
835*13fbcb42Sjoerg   auto SetArtificialLoc = ApplyDebugLocation::CreateArtificial(CGF);
83606f32e7eSjoerg   for (unsigned I = 0; I < N; ++I)
83706f32e7eSjoerg     Addrs[I] = CGF.Builder.CreateBitCast(Addrs[I], CGF.CGM.Int8PtrPtrTy);
83806f32e7eSjoerg   QT = IsVolatile ? QT.withVolatile() : QT;
83906f32e7eSjoerg   Gen.callFunc(FuncName, QT, Addrs, CGF);
84006f32e7eSjoerg }
84106f32e7eSjoerg 
84206f32e7eSjoerg template <class G, size_t N>
84306f32e7eSjoerg static llvm::Function *
getSpecialFunction(G && Gen,StringRef FuncName,QualType QT,bool IsVolatile,std::array<CharUnits,N> Alignments,CodeGenModule & CGM)84406f32e7eSjoerg getSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile,
84506f32e7eSjoerg                    std::array<CharUnits, N> Alignments, CodeGenModule &CGM) {
84606f32e7eSjoerg   QT = IsVolatile ? QT.withVolatile() : QT;
84706f32e7eSjoerg   // The following call requires an array of addresses as arguments, but doesn't
84806f32e7eSjoerg   // actually use them (it overwrites them with the addresses of the arguments
84906f32e7eSjoerg   // of the created function).
850*13fbcb42Sjoerg   return Gen.getFunction(FuncName, QT, Alignments, CGM);
85106f32e7eSjoerg }
85206f32e7eSjoerg 
85306f32e7eSjoerg // Functions to emit calls to the special functions of a non-trivial C struct.
callCStructDefaultConstructor(LValue Dst)85406f32e7eSjoerg void CodeGenFunction::callCStructDefaultConstructor(LValue Dst) {
85506f32e7eSjoerg   bool IsVolatile = Dst.isVolatile();
856*13fbcb42Sjoerg   Address DstPtr = Dst.getAddress(*this);
85706f32e7eSjoerg   QualType QT = Dst.getType();
85806f32e7eSjoerg   GenDefaultInitializeFuncName GenName(DstPtr.getAlignment(), getContext());
85906f32e7eSjoerg   std::string FuncName = GenName.getName(QT, IsVolatile);
86006f32e7eSjoerg   callSpecialFunction(GenDefaultInitialize(getContext()), FuncName, QT,
86106f32e7eSjoerg                       IsVolatile, *this, std::array<Address, 1>({{DstPtr}}));
86206f32e7eSjoerg }
86306f32e7eSjoerg 
getNonTrivialCopyConstructorStr(QualType QT,CharUnits Alignment,bool IsVolatile,ASTContext & Ctx)86406f32e7eSjoerg std::string CodeGenFunction::getNonTrivialCopyConstructorStr(
86506f32e7eSjoerg     QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx) {
86606f32e7eSjoerg   GenBinaryFuncName<false> GenName("", Alignment, Alignment, Ctx);
86706f32e7eSjoerg   return GenName.getName(QT, IsVolatile);
86806f32e7eSjoerg }
86906f32e7eSjoerg 
getNonTrivialDestructorStr(QualType QT,CharUnits Alignment,bool IsVolatile,ASTContext & Ctx)87006f32e7eSjoerg std::string CodeGenFunction::getNonTrivialDestructorStr(QualType QT,
87106f32e7eSjoerg                                                         CharUnits Alignment,
87206f32e7eSjoerg                                                         bool IsVolatile,
87306f32e7eSjoerg                                                         ASTContext &Ctx) {
87406f32e7eSjoerg   GenDestructorFuncName GenName("", Alignment, Ctx);
87506f32e7eSjoerg   return GenName.getName(QT, IsVolatile);
87606f32e7eSjoerg }
87706f32e7eSjoerg 
callCStructDestructor(LValue Dst)87806f32e7eSjoerg void CodeGenFunction::callCStructDestructor(LValue Dst) {
87906f32e7eSjoerg   bool IsVolatile = Dst.isVolatile();
880*13fbcb42Sjoerg   Address DstPtr = Dst.getAddress(*this);
88106f32e7eSjoerg   QualType QT = Dst.getType();
88206f32e7eSjoerg   GenDestructorFuncName GenName("__destructor_", DstPtr.getAlignment(),
88306f32e7eSjoerg                                 getContext());
88406f32e7eSjoerg   std::string FuncName = GenName.getName(QT, IsVolatile);
88506f32e7eSjoerg   callSpecialFunction(GenDestructor(getContext()), FuncName, QT, IsVolatile,
88606f32e7eSjoerg                       *this, std::array<Address, 1>({{DstPtr}}));
88706f32e7eSjoerg }
88806f32e7eSjoerg 
callCStructCopyConstructor(LValue Dst,LValue Src)88906f32e7eSjoerg void CodeGenFunction::callCStructCopyConstructor(LValue Dst, LValue Src) {
89006f32e7eSjoerg   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
891*13fbcb42Sjoerg   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
89206f32e7eSjoerg   QualType QT = Dst.getType();
89306f32e7eSjoerg   GenBinaryFuncName<false> GenName("__copy_constructor_", DstPtr.getAlignment(),
89406f32e7eSjoerg                                    SrcPtr.getAlignment(), getContext());
89506f32e7eSjoerg   std::string FuncName = GenName.getName(QT, IsVolatile);
89606f32e7eSjoerg   callSpecialFunction(GenCopyConstructor(getContext()), FuncName, QT,
89706f32e7eSjoerg                       IsVolatile, *this,
89806f32e7eSjoerg                       std::array<Address, 2>({{DstPtr, SrcPtr}}));
89906f32e7eSjoerg }
90006f32e7eSjoerg 
callCStructCopyAssignmentOperator(LValue Dst,LValue Src)90106f32e7eSjoerg void CodeGenFunction::callCStructCopyAssignmentOperator(LValue Dst, LValue Src
90206f32e7eSjoerg 
90306f32e7eSjoerg ) {
90406f32e7eSjoerg   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
905*13fbcb42Sjoerg   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
90606f32e7eSjoerg   QualType QT = Dst.getType();
90706f32e7eSjoerg   GenBinaryFuncName<false> GenName("__copy_assignment_", DstPtr.getAlignment(),
90806f32e7eSjoerg                                    SrcPtr.getAlignment(), getContext());
90906f32e7eSjoerg   std::string FuncName = GenName.getName(QT, IsVolatile);
91006f32e7eSjoerg   callSpecialFunction(GenCopyAssignment(getContext()), FuncName, QT, IsVolatile,
91106f32e7eSjoerg                       *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
91206f32e7eSjoerg }
91306f32e7eSjoerg 
callCStructMoveConstructor(LValue Dst,LValue Src)91406f32e7eSjoerg void CodeGenFunction::callCStructMoveConstructor(LValue Dst, LValue Src) {
91506f32e7eSjoerg   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
916*13fbcb42Sjoerg   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
91706f32e7eSjoerg   QualType QT = Dst.getType();
91806f32e7eSjoerg   GenBinaryFuncName<true> GenName("__move_constructor_", DstPtr.getAlignment(),
91906f32e7eSjoerg                                   SrcPtr.getAlignment(), getContext());
92006f32e7eSjoerg   std::string FuncName = GenName.getName(QT, IsVolatile);
92106f32e7eSjoerg   callSpecialFunction(GenMoveConstructor(getContext()), FuncName, QT,
92206f32e7eSjoerg                       IsVolatile, *this,
92306f32e7eSjoerg                       std::array<Address, 2>({{DstPtr, SrcPtr}}));
92406f32e7eSjoerg }
92506f32e7eSjoerg 
callCStructMoveAssignmentOperator(LValue Dst,LValue Src)92606f32e7eSjoerg void CodeGenFunction::callCStructMoveAssignmentOperator(LValue Dst, LValue Src
92706f32e7eSjoerg 
92806f32e7eSjoerg ) {
92906f32e7eSjoerg   bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
930*13fbcb42Sjoerg   Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
93106f32e7eSjoerg   QualType QT = Dst.getType();
93206f32e7eSjoerg   GenBinaryFuncName<true> GenName("__move_assignment_", DstPtr.getAlignment(),
93306f32e7eSjoerg                                   SrcPtr.getAlignment(), getContext());
93406f32e7eSjoerg   std::string FuncName = GenName.getName(QT, IsVolatile);
93506f32e7eSjoerg   callSpecialFunction(GenMoveAssignment(getContext()), FuncName, QT, IsVolatile,
93606f32e7eSjoerg                       *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
93706f32e7eSjoerg }
93806f32e7eSjoerg 
getNonTrivialCStructDefaultConstructor(CodeGenModule & CGM,CharUnits DstAlignment,bool IsVolatile,QualType QT)93906f32e7eSjoerg llvm::Function *clang::CodeGen::getNonTrivialCStructDefaultConstructor(
94006f32e7eSjoerg     CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
94106f32e7eSjoerg   ASTContext &Ctx = CGM.getContext();
94206f32e7eSjoerg   GenDefaultInitializeFuncName GenName(DstAlignment, Ctx);
94306f32e7eSjoerg   std::string FuncName = GenName.getName(QT, IsVolatile);
94406f32e7eSjoerg   return getSpecialFunction(GenDefaultInitialize(Ctx), FuncName, QT, IsVolatile,
94506f32e7eSjoerg                             std::array<CharUnits, 1>({{DstAlignment}}), CGM);
94606f32e7eSjoerg }
94706f32e7eSjoerg 
getNonTrivialCStructCopyConstructor(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)94806f32e7eSjoerg llvm::Function *clang::CodeGen::getNonTrivialCStructCopyConstructor(
94906f32e7eSjoerg     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
95006f32e7eSjoerg     bool IsVolatile, QualType QT) {
95106f32e7eSjoerg   ASTContext &Ctx = CGM.getContext();
95206f32e7eSjoerg   GenBinaryFuncName<false> GenName("__copy_constructor_", DstAlignment,
95306f32e7eSjoerg                                    SrcAlignment, Ctx);
95406f32e7eSjoerg   std::string FuncName = GenName.getName(QT, IsVolatile);
95506f32e7eSjoerg   return getSpecialFunction(
95606f32e7eSjoerg       GenCopyConstructor(Ctx), FuncName, QT, IsVolatile,
95706f32e7eSjoerg       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
95806f32e7eSjoerg }
95906f32e7eSjoerg 
getNonTrivialCStructMoveConstructor(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)96006f32e7eSjoerg llvm::Function *clang::CodeGen::getNonTrivialCStructMoveConstructor(
96106f32e7eSjoerg     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
96206f32e7eSjoerg     bool IsVolatile, QualType QT) {
96306f32e7eSjoerg   ASTContext &Ctx = CGM.getContext();
96406f32e7eSjoerg   GenBinaryFuncName<true> GenName("__move_constructor_", DstAlignment,
96506f32e7eSjoerg                                   SrcAlignment, Ctx);
96606f32e7eSjoerg   std::string FuncName = GenName.getName(QT, IsVolatile);
96706f32e7eSjoerg   return getSpecialFunction(
96806f32e7eSjoerg       GenMoveConstructor(Ctx), FuncName, QT, IsVolatile,
96906f32e7eSjoerg       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
97006f32e7eSjoerg }
97106f32e7eSjoerg 
getNonTrivialCStructCopyAssignmentOperator(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)97206f32e7eSjoerg llvm::Function *clang::CodeGen::getNonTrivialCStructCopyAssignmentOperator(
97306f32e7eSjoerg     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
97406f32e7eSjoerg     bool IsVolatile, QualType QT) {
97506f32e7eSjoerg   ASTContext &Ctx = CGM.getContext();
97606f32e7eSjoerg   GenBinaryFuncName<false> GenName("__copy_assignment_", DstAlignment,
97706f32e7eSjoerg                                    SrcAlignment, Ctx);
97806f32e7eSjoerg   std::string FuncName = GenName.getName(QT, IsVolatile);
97906f32e7eSjoerg   return getSpecialFunction(
98006f32e7eSjoerg       GenCopyAssignment(Ctx), FuncName, QT, IsVolatile,
98106f32e7eSjoerg       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
98206f32e7eSjoerg }
98306f32e7eSjoerg 
getNonTrivialCStructMoveAssignmentOperator(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)98406f32e7eSjoerg llvm::Function *clang::CodeGen::getNonTrivialCStructMoveAssignmentOperator(
98506f32e7eSjoerg     CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
98606f32e7eSjoerg     bool IsVolatile, QualType QT) {
98706f32e7eSjoerg   ASTContext &Ctx = CGM.getContext();
98806f32e7eSjoerg   GenBinaryFuncName<true> GenName("__move_assignment_", DstAlignment,
98906f32e7eSjoerg                                   SrcAlignment, Ctx);
99006f32e7eSjoerg   std::string FuncName = GenName.getName(QT, IsVolatile);
99106f32e7eSjoerg   return getSpecialFunction(
99206f32e7eSjoerg       GenMoveAssignment(Ctx), FuncName, QT, IsVolatile,
99306f32e7eSjoerg       std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
99406f32e7eSjoerg }
99506f32e7eSjoerg 
getNonTrivialCStructDestructor(CodeGenModule & CGM,CharUnits DstAlignment,bool IsVolatile,QualType QT)99606f32e7eSjoerg llvm::Function *clang::CodeGen::getNonTrivialCStructDestructor(
99706f32e7eSjoerg     CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
99806f32e7eSjoerg   ASTContext &Ctx = CGM.getContext();
99906f32e7eSjoerg   GenDestructorFuncName GenName("__destructor_", DstAlignment, Ctx);
100006f32e7eSjoerg   std::string FuncName = GenName.getName(QT, IsVolatile);
100106f32e7eSjoerg   return getSpecialFunction(GenDestructor(Ctx), FuncName, QT, IsVolatile,
100206f32e7eSjoerg                             std::array<CharUnits, 1>({{DstAlignment}}), CGM);
100306f32e7eSjoerg }
1004