17330f729Sjoerg //===--- CGNonTrivialStruct.cpp - Emit Special Functions for C Structs ----===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file defines functions to generate various special functions for C
107330f729Sjoerg // structs.
117330f729Sjoerg //
127330f729Sjoerg //===----------------------------------------------------------------------===//
137330f729Sjoerg
147330f729Sjoerg #include "CodeGenFunction.h"
157330f729Sjoerg #include "CodeGenModule.h"
167330f729Sjoerg #include "clang/AST/NonTrivialTypeVisitor.h"
177330f729Sjoerg #include "clang/CodeGen/CodeGenABITypes.h"
187330f729Sjoerg #include "llvm/Support/ScopedPrinter.h"
197330f729Sjoerg #include <array>
207330f729Sjoerg
217330f729Sjoerg using namespace clang;
227330f729Sjoerg using namespace CodeGen;
237330f729Sjoerg
247330f729Sjoerg // Return the size of a field in number of bits.
getFieldSize(const FieldDecl * FD,QualType FT,ASTContext & Ctx)257330f729Sjoerg static uint64_t getFieldSize(const FieldDecl *FD, QualType FT,
267330f729Sjoerg ASTContext &Ctx) {
277330f729Sjoerg if (FD && FD->isBitField())
287330f729Sjoerg return FD->getBitWidthValue(Ctx);
297330f729Sjoerg return Ctx.getTypeSize(FT);
307330f729Sjoerg }
317330f729Sjoerg
327330f729Sjoerg namespace {
337330f729Sjoerg enum { DstIdx = 0, SrcIdx = 1 };
347330f729Sjoerg const char *ValNameStr[2] = {"dst", "src"};
357330f729Sjoerg
367330f729Sjoerg template <class Derived> struct StructVisitor {
StructVisitor__anon28b95f1e0111::StructVisitor377330f729Sjoerg StructVisitor(ASTContext &Ctx) : Ctx(Ctx) {}
387330f729Sjoerg
397330f729Sjoerg template <class... Ts>
visitStructFields__anon28b95f1e0111::StructVisitor407330f729Sjoerg void visitStructFields(QualType QT, CharUnits CurStructOffset, Ts... Args) {
417330f729Sjoerg const RecordDecl *RD = QT->castAs<RecordType>()->getDecl();
427330f729Sjoerg
437330f729Sjoerg // Iterate over the fields of the struct.
447330f729Sjoerg for (const FieldDecl *FD : RD->fields()) {
457330f729Sjoerg QualType FT = FD->getType();
467330f729Sjoerg FT = QT.isVolatileQualified() ? FT.withVolatile() : FT;
477330f729Sjoerg asDerived().visit(FT, FD, CurStructOffset, Args...);
487330f729Sjoerg }
497330f729Sjoerg
507330f729Sjoerg asDerived().flushTrivialFields(Args...);
517330f729Sjoerg }
527330f729Sjoerg
visitTrivial__anon28b95f1e0111::StructVisitor537330f729Sjoerg template <class... Ts> void visitTrivial(Ts... Args) {}
547330f729Sjoerg
visitCXXDestructor__anon28b95f1e0111::StructVisitor557330f729Sjoerg template <class... Ts> void visitCXXDestructor(Ts... Args) {
567330f729Sjoerg llvm_unreachable("field of a C++ struct type is not expected");
577330f729Sjoerg }
587330f729Sjoerg
flushTrivialFields__anon28b95f1e0111::StructVisitor597330f729Sjoerg template <class... Ts> void flushTrivialFields(Ts... Args) {}
607330f729Sjoerg
getFieldOffsetInBits__anon28b95f1e0111::StructVisitor617330f729Sjoerg uint64_t getFieldOffsetInBits(const FieldDecl *FD) {
627330f729Sjoerg return FD ? Ctx.getASTRecordLayout(FD->getParent())
637330f729Sjoerg .getFieldOffset(FD->getFieldIndex())
647330f729Sjoerg : 0;
657330f729Sjoerg }
667330f729Sjoerg
getFieldOffset__anon28b95f1e0111::StructVisitor677330f729Sjoerg CharUnits getFieldOffset(const FieldDecl *FD) {
687330f729Sjoerg return Ctx.toCharUnitsFromBits(getFieldOffsetInBits(FD));
697330f729Sjoerg }
707330f729Sjoerg
asDerived__anon28b95f1e0111::StructVisitor717330f729Sjoerg Derived &asDerived() { return static_cast<Derived &>(*this); }
727330f729Sjoerg
getContext__anon28b95f1e0111::StructVisitor737330f729Sjoerg ASTContext &getContext() { return Ctx; }
747330f729Sjoerg ASTContext &Ctx;
757330f729Sjoerg };
767330f729Sjoerg
777330f729Sjoerg template <class Derived, bool IsMove>
787330f729Sjoerg struct CopyStructVisitor : StructVisitor<Derived>,
797330f729Sjoerg CopiedTypeVisitor<Derived, IsMove> {
807330f729Sjoerg using StructVisitor<Derived>::asDerived;
817330f729Sjoerg using Super = CopiedTypeVisitor<Derived, IsMove>;
827330f729Sjoerg
CopyStructVisitor__anon28b95f1e0111::CopyStructVisitor837330f729Sjoerg CopyStructVisitor(ASTContext &Ctx) : StructVisitor<Derived>(Ctx) {}
847330f729Sjoerg
857330f729Sjoerg template <class... Ts>
preVisit__anon28b95f1e0111::CopyStructVisitor867330f729Sjoerg void preVisit(QualType::PrimitiveCopyKind PCK, QualType FT,
877330f729Sjoerg const FieldDecl *FD, CharUnits CurStructOffset, Ts &&... Args) {
887330f729Sjoerg if (PCK)
897330f729Sjoerg asDerived().flushTrivialFields(std::forward<Ts>(Args)...);
907330f729Sjoerg }
917330f729Sjoerg
927330f729Sjoerg template <class... Ts>
visitWithKind__anon28b95f1e0111::CopyStructVisitor937330f729Sjoerg void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT,
947330f729Sjoerg const FieldDecl *FD, CharUnits CurStructOffset,
957330f729Sjoerg Ts &&... Args) {
967330f729Sjoerg if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
977330f729Sjoerg asDerived().visitArray(PCK, AT, FT.isVolatileQualified(), FD,
987330f729Sjoerg CurStructOffset, std::forward<Ts>(Args)...);
997330f729Sjoerg return;
1007330f729Sjoerg }
1017330f729Sjoerg
1027330f729Sjoerg Super::visitWithKind(PCK, FT, FD, CurStructOffset,
1037330f729Sjoerg std::forward<Ts>(Args)...);
1047330f729Sjoerg }
1057330f729Sjoerg
1067330f729Sjoerg template <class... Ts>
visitTrivial__anon28b95f1e0111::CopyStructVisitor1077330f729Sjoerg void visitTrivial(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset,
1087330f729Sjoerg Ts... Args) {
1097330f729Sjoerg assert(!FT.isVolatileQualified() && "volatile field not expected");
1107330f729Sjoerg ASTContext &Ctx = asDerived().getContext();
1117330f729Sjoerg uint64_t FieldSize = getFieldSize(FD, FT, Ctx);
1127330f729Sjoerg
1137330f729Sjoerg // Ignore zero-sized fields.
1147330f729Sjoerg if (FieldSize == 0)
1157330f729Sjoerg return;
1167330f729Sjoerg
1177330f729Sjoerg uint64_t FStartInBits = asDerived().getFieldOffsetInBits(FD);
1187330f729Sjoerg uint64_t FEndInBits = FStartInBits + FieldSize;
1197330f729Sjoerg uint64_t RoundedFEnd = llvm::alignTo(FEndInBits, Ctx.getCharWidth());
1207330f729Sjoerg
1217330f729Sjoerg // Set Start if this is the first field of a sequence of trivial fields.
1227330f729Sjoerg if (Start == End)
1237330f729Sjoerg Start = CurStructOffset + Ctx.toCharUnitsFromBits(FStartInBits);
1247330f729Sjoerg End = CurStructOffset + Ctx.toCharUnitsFromBits(RoundedFEnd);
1257330f729Sjoerg }
1267330f729Sjoerg
1277330f729Sjoerg CharUnits Start = CharUnits::Zero(), End = CharUnits::Zero();
1287330f729Sjoerg };
1297330f729Sjoerg
1307330f729Sjoerg // This function creates the mangled name of a special function of a non-trivial
1317330f729Sjoerg // C struct. Since there is no ODR in C, the function is mangled based on the
1327330f729Sjoerg // struct contents and not the name. The mangled name has the following
1337330f729Sjoerg // structure:
1347330f729Sjoerg //
1357330f729Sjoerg // <function-name> ::= <prefix> <alignment-info> "_" <struct-field-info>
1367330f729Sjoerg // <prefix> ::= "__destructor_" | "__default_constructor_" |
1377330f729Sjoerg // "__copy_constructor_" | "__move_constructor_" |
1387330f729Sjoerg // "__copy_assignment_" | "__move_assignment_"
1397330f729Sjoerg // <alignment-info> ::= <dst-alignment> ["_" <src-alignment>]
1407330f729Sjoerg // <struct-field-info> ::= <field-info>+
1417330f729Sjoerg // <field-info> ::= <struct-or-scalar-field-info> | <array-field-info>
1427330f729Sjoerg // <struct-or-scalar-field-info> ::= "_S" <struct-field-info> |
1437330f729Sjoerg // <strong-field-info> | <trivial-field-info>
1447330f729Sjoerg // <array-field-info> ::= "_AB" <array-offset> "s" <element-size> "n"
1457330f729Sjoerg // <num-elements> <innermost-element-info> "_AE"
1467330f729Sjoerg // <innermost-element-info> ::= <struct-or-scalar-field-info>
1477330f729Sjoerg // <strong-field-info> ::= "_s" ["b"] ["v"] <field-offset>
1487330f729Sjoerg // <trivial-field-info> ::= "_t" ["v"] <field-offset> "_" <field-size>
1497330f729Sjoerg
1507330f729Sjoerg template <class Derived> struct GenFuncNameBase {
getVolatileOffsetStr__anon28b95f1e0111::GenFuncNameBase1517330f729Sjoerg std::string getVolatileOffsetStr(bool IsVolatile, CharUnits Offset) {
1527330f729Sjoerg std::string S;
1537330f729Sjoerg if (IsVolatile)
1547330f729Sjoerg S = "v";
1557330f729Sjoerg S += llvm::to_string(Offset.getQuantity());
1567330f729Sjoerg return S;
1577330f729Sjoerg }
1587330f729Sjoerg
visitARCStrong__anon28b95f1e0111::GenFuncNameBase1597330f729Sjoerg void visitARCStrong(QualType FT, const FieldDecl *FD,
1607330f729Sjoerg CharUnits CurStructOffset) {
1617330f729Sjoerg appendStr("_s");
1627330f729Sjoerg if (FT->isBlockPointerType())
1637330f729Sjoerg appendStr("b");
1647330f729Sjoerg CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
1657330f729Sjoerg appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset));
1667330f729Sjoerg }
1677330f729Sjoerg
visitARCWeak__anon28b95f1e0111::GenFuncNameBase1687330f729Sjoerg void visitARCWeak(QualType FT, const FieldDecl *FD,
1697330f729Sjoerg CharUnits CurStructOffset) {
1707330f729Sjoerg appendStr("_w");
1717330f729Sjoerg CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
1727330f729Sjoerg appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset));
1737330f729Sjoerg }
1747330f729Sjoerg
visitStruct__anon28b95f1e0111::GenFuncNameBase1757330f729Sjoerg void visitStruct(QualType QT, const FieldDecl *FD,
1767330f729Sjoerg CharUnits CurStructOffset) {
1777330f729Sjoerg CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
1787330f729Sjoerg appendStr("_S");
1797330f729Sjoerg asDerived().visitStructFields(QT, FieldOffset);
1807330f729Sjoerg }
1817330f729Sjoerg
1827330f729Sjoerg template <class FieldKind>
visitArray__anon28b95f1e0111::GenFuncNameBase1837330f729Sjoerg void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
1847330f729Sjoerg const FieldDecl *FD, CharUnits CurStructOffset) {
1857330f729Sjoerg // String for non-volatile trivial fields is emitted when
1867330f729Sjoerg // flushTrivialFields is called.
1877330f729Sjoerg if (!FK)
1887330f729Sjoerg return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset);
1897330f729Sjoerg
1907330f729Sjoerg asDerived().flushTrivialFields();
1917330f729Sjoerg CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
1927330f729Sjoerg ASTContext &Ctx = asDerived().getContext();
1937330f729Sjoerg const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
1947330f729Sjoerg unsigned NumElts = Ctx.getConstantArrayElementCount(CAT);
1957330f729Sjoerg QualType EltTy = Ctx.getBaseElementType(CAT);
1967330f729Sjoerg CharUnits EltSize = Ctx.getTypeSizeInChars(EltTy);
1977330f729Sjoerg appendStr("_AB" + llvm::to_string(FieldOffset.getQuantity()) + "s" +
1987330f729Sjoerg llvm::to_string(EltSize.getQuantity()) + "n" +
1997330f729Sjoerg llvm::to_string(NumElts));
2007330f729Sjoerg EltTy = IsVolatile ? EltTy.withVolatile() : EltTy;
2017330f729Sjoerg asDerived().visitWithKind(FK, EltTy, nullptr, FieldOffset);
2027330f729Sjoerg appendStr("_AE");
2037330f729Sjoerg }
2047330f729Sjoerg
appendStr__anon28b95f1e0111::GenFuncNameBase2057330f729Sjoerg void appendStr(StringRef Str) { Name += Str; }
2067330f729Sjoerg
getName__anon28b95f1e0111::GenFuncNameBase2077330f729Sjoerg std::string getName(QualType QT, bool IsVolatile) {
2087330f729Sjoerg QT = IsVolatile ? QT.withVolatile() : QT;
2097330f729Sjoerg asDerived().visitStructFields(QT, CharUnits::Zero());
2107330f729Sjoerg return Name;
2117330f729Sjoerg }
2127330f729Sjoerg
asDerived__anon28b95f1e0111::GenFuncNameBase2137330f729Sjoerg Derived &asDerived() { return static_cast<Derived &>(*this); }
2147330f729Sjoerg
2157330f729Sjoerg std::string Name;
2167330f729Sjoerg };
2177330f729Sjoerg
2187330f729Sjoerg template <class Derived>
2197330f729Sjoerg struct GenUnaryFuncName : StructVisitor<Derived>, GenFuncNameBase<Derived> {
GenUnaryFuncName__anon28b95f1e0111::GenUnaryFuncName2207330f729Sjoerg GenUnaryFuncName(StringRef Prefix, CharUnits DstAlignment, ASTContext &Ctx)
2217330f729Sjoerg : StructVisitor<Derived>(Ctx) {
2227330f729Sjoerg this->appendStr(Prefix);
2237330f729Sjoerg this->appendStr(llvm::to_string(DstAlignment.getQuantity()));
2247330f729Sjoerg }
2257330f729Sjoerg };
2267330f729Sjoerg
2277330f729Sjoerg // Helper function to create a null constant.
getNullForVariable(Address Addr)2287330f729Sjoerg static llvm::Constant *getNullForVariable(Address Addr) {
2297330f729Sjoerg llvm::Type *Ty = Addr.getElementType();
2307330f729Sjoerg return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(Ty));
2317330f729Sjoerg }
2327330f729Sjoerg
2337330f729Sjoerg template <bool IsMove>
2347330f729Sjoerg struct GenBinaryFuncName : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>,
2357330f729Sjoerg GenFuncNameBase<GenBinaryFuncName<IsMove>> {
2367330f729Sjoerg
GenBinaryFuncName__anon28b95f1e0111::GenBinaryFuncName2377330f729Sjoerg GenBinaryFuncName(StringRef Prefix, CharUnits DstAlignment,
2387330f729Sjoerg CharUnits SrcAlignment, ASTContext &Ctx)
2397330f729Sjoerg : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>(Ctx) {
2407330f729Sjoerg this->appendStr(Prefix);
2417330f729Sjoerg this->appendStr(llvm::to_string(DstAlignment.getQuantity()));
2427330f729Sjoerg this->appendStr("_" + llvm::to_string(SrcAlignment.getQuantity()));
2437330f729Sjoerg }
2447330f729Sjoerg
flushTrivialFields__anon28b95f1e0111::GenBinaryFuncName2457330f729Sjoerg void flushTrivialFields() {
2467330f729Sjoerg if (this->Start == this->End)
2477330f729Sjoerg return;
2487330f729Sjoerg
2497330f729Sjoerg this->appendStr("_t" + llvm::to_string(this->Start.getQuantity()) + "w" +
2507330f729Sjoerg llvm::to_string((this->End - this->Start).getQuantity()));
2517330f729Sjoerg
2527330f729Sjoerg this->Start = this->End = CharUnits::Zero();
2537330f729Sjoerg }
2547330f729Sjoerg
visitVolatileTrivial__anon28b95f1e0111::GenBinaryFuncName2557330f729Sjoerg void visitVolatileTrivial(QualType FT, const FieldDecl *FD,
2567330f729Sjoerg CharUnits CurStructOffset) {
257*e038c9c4Sjoerg // Zero-length bit-fields don't need to be copied/assigned.
258*e038c9c4Sjoerg if (FD && FD->isZeroLengthBitField(this->Ctx))
259*e038c9c4Sjoerg return;
260*e038c9c4Sjoerg
2617330f729Sjoerg // Because volatile fields can be bit-fields and are individually copied,
2627330f729Sjoerg // their offset and width are in bits.
2637330f729Sjoerg uint64_t OffsetInBits =
2647330f729Sjoerg this->Ctx.toBits(CurStructOffset) + this->getFieldOffsetInBits(FD);
2657330f729Sjoerg this->appendStr("_tv" + llvm::to_string(OffsetInBits) + "w" +
2667330f729Sjoerg llvm::to_string(getFieldSize(FD, FT, this->Ctx)));
2677330f729Sjoerg }
2687330f729Sjoerg };
2697330f729Sjoerg
2707330f729Sjoerg struct GenDefaultInitializeFuncName
2717330f729Sjoerg : GenUnaryFuncName<GenDefaultInitializeFuncName>,
2727330f729Sjoerg DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName> {
2737330f729Sjoerg using Super = DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName>;
GenDefaultInitializeFuncName__anon28b95f1e0111::GenDefaultInitializeFuncName2747330f729Sjoerg GenDefaultInitializeFuncName(CharUnits DstAlignment, ASTContext &Ctx)
2757330f729Sjoerg : GenUnaryFuncName<GenDefaultInitializeFuncName>("__default_constructor_",
2767330f729Sjoerg DstAlignment, Ctx) {}
visitWithKind__anon28b95f1e0111::GenDefaultInitializeFuncName2777330f729Sjoerg void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
2787330f729Sjoerg const FieldDecl *FD, CharUnits CurStructOffset) {
2797330f729Sjoerg if (const auto *AT = getContext().getAsArrayType(FT)) {
2807330f729Sjoerg visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset);
2817330f729Sjoerg return;
2827330f729Sjoerg }
2837330f729Sjoerg
2847330f729Sjoerg Super::visitWithKind(PDIK, FT, FD, CurStructOffset);
2857330f729Sjoerg }
2867330f729Sjoerg };
2877330f729Sjoerg
2887330f729Sjoerg struct GenDestructorFuncName : GenUnaryFuncName<GenDestructorFuncName>,
2897330f729Sjoerg DestructedTypeVisitor<GenDestructorFuncName> {
2907330f729Sjoerg using Super = DestructedTypeVisitor<GenDestructorFuncName>;
GenDestructorFuncName__anon28b95f1e0111::GenDestructorFuncName2917330f729Sjoerg GenDestructorFuncName(const char *Prefix, CharUnits DstAlignment,
2927330f729Sjoerg ASTContext &Ctx)
2937330f729Sjoerg : GenUnaryFuncName<GenDestructorFuncName>(Prefix, DstAlignment, Ctx) {}
visitWithKind__anon28b95f1e0111::GenDestructorFuncName2947330f729Sjoerg void visitWithKind(QualType::DestructionKind DK, QualType FT,
2957330f729Sjoerg const FieldDecl *FD, CharUnits CurStructOffset) {
2967330f729Sjoerg if (const auto *AT = getContext().getAsArrayType(FT)) {
2977330f729Sjoerg visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset);
2987330f729Sjoerg return;
2997330f729Sjoerg }
3007330f729Sjoerg
3017330f729Sjoerg Super::visitWithKind(DK, FT, FD, CurStructOffset);
3027330f729Sjoerg }
3037330f729Sjoerg };
3047330f729Sjoerg
3057330f729Sjoerg // Helper function that creates CGFunctionInfo for an N-ary special function.
3067330f729Sjoerg template <size_t N>
getFunctionInfo(CodeGenModule & CGM,FunctionArgList & Args)3077330f729Sjoerg static const CGFunctionInfo &getFunctionInfo(CodeGenModule &CGM,
3087330f729Sjoerg FunctionArgList &Args) {
3097330f729Sjoerg ASTContext &Ctx = CGM.getContext();
3107330f729Sjoerg llvm::SmallVector<ImplicitParamDecl *, N> Params;
3117330f729Sjoerg QualType ParamTy = Ctx.getPointerType(Ctx.VoidPtrTy);
3127330f729Sjoerg
3137330f729Sjoerg for (unsigned I = 0; I < N; ++I)
3147330f729Sjoerg Params.push_back(ImplicitParamDecl::Create(
3157330f729Sjoerg Ctx, nullptr, SourceLocation(), &Ctx.Idents.get(ValNameStr[I]), ParamTy,
3167330f729Sjoerg ImplicitParamDecl::Other));
3177330f729Sjoerg
3187330f729Sjoerg for (auto &P : Params)
3197330f729Sjoerg Args.push_back(P);
3207330f729Sjoerg
3217330f729Sjoerg return CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args);
3227330f729Sjoerg }
3237330f729Sjoerg
324*e038c9c4Sjoerg template <size_t N, size_t... Ints>
getParamAddrs(std::index_sequence<Ints...> IntSeq,std::array<CharUnits,N> Alignments,FunctionArgList Args,CodeGenFunction * CGF)325*e038c9c4Sjoerg static std::array<Address, N> getParamAddrs(std::index_sequence<Ints...> IntSeq,
326*e038c9c4Sjoerg std::array<CharUnits, N> Alignments,
327*e038c9c4Sjoerg FunctionArgList Args,
328*e038c9c4Sjoerg CodeGenFunction *CGF) {
329*e038c9c4Sjoerg return std::array<Address, N>{{
330*e038c9c4Sjoerg Address(CGF->Builder.CreateLoad(CGF->GetAddrOfLocalVar(Args[Ints])),
331*e038c9c4Sjoerg Alignments[Ints])...}};
332*e038c9c4Sjoerg }
333*e038c9c4Sjoerg
3347330f729Sjoerg // Template classes that are used as bases for classes that emit special
3357330f729Sjoerg // functions.
3367330f729Sjoerg template <class Derived> struct GenFuncBase {
3377330f729Sjoerg template <size_t N>
visitStruct__anon28b95f1e0111::GenFuncBase3387330f729Sjoerg void visitStruct(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset,
3397330f729Sjoerg std::array<Address, N> Addrs) {
3407330f729Sjoerg this->asDerived().callSpecialFunction(
3417330f729Sjoerg FT, CurStructOffset + asDerived().getFieldOffset(FD), Addrs);
3427330f729Sjoerg }
3437330f729Sjoerg
3447330f729Sjoerg template <class FieldKind, size_t N>
visitArray__anon28b95f1e0111::GenFuncBase3457330f729Sjoerg void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
3467330f729Sjoerg const FieldDecl *FD, CharUnits CurStructOffset,
3477330f729Sjoerg std::array<Address, N> Addrs) {
3487330f729Sjoerg // Non-volatile trivial fields are copied when flushTrivialFields is called.
3497330f729Sjoerg if (!FK)
3507330f729Sjoerg return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset,
3517330f729Sjoerg Addrs);
3527330f729Sjoerg
3537330f729Sjoerg asDerived().flushTrivialFields(Addrs);
3547330f729Sjoerg CodeGenFunction &CGF = *this->CGF;
3557330f729Sjoerg ASTContext &Ctx = CGF.getContext();
3567330f729Sjoerg
3577330f729Sjoerg // Compute the end address.
3587330f729Sjoerg QualType BaseEltQT;
3597330f729Sjoerg std::array<Address, N> StartAddrs = Addrs;
3607330f729Sjoerg for (unsigned I = 0; I < N; ++I)
3617330f729Sjoerg StartAddrs[I] = getAddrWithOffset(Addrs[I], CurStructOffset, FD);
3627330f729Sjoerg Address DstAddr = StartAddrs[DstIdx];
3637330f729Sjoerg llvm::Value *NumElts = CGF.emitArrayLength(AT, BaseEltQT, DstAddr);
3647330f729Sjoerg unsigned BaseEltSize = Ctx.getTypeSizeInChars(BaseEltQT).getQuantity();
3657330f729Sjoerg llvm::Value *BaseEltSizeVal =
3667330f729Sjoerg llvm::ConstantInt::get(NumElts->getType(), BaseEltSize);
3677330f729Sjoerg llvm::Value *SizeInBytes =
3687330f729Sjoerg CGF.Builder.CreateNUWMul(BaseEltSizeVal, NumElts);
3697330f729Sjoerg Address BC = CGF.Builder.CreateBitCast(DstAddr, CGF.CGM.Int8PtrTy);
3707330f729Sjoerg llvm::Value *DstArrayEnd =
371*e038c9c4Sjoerg CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, BC.getPointer(), SizeInBytes);
3727330f729Sjoerg DstArrayEnd = CGF.Builder.CreateBitCast(DstArrayEnd, CGF.CGM.Int8PtrPtrTy,
3737330f729Sjoerg "dstarray.end");
3747330f729Sjoerg llvm::BasicBlock *PreheaderBB = CGF.Builder.GetInsertBlock();
3757330f729Sjoerg
3767330f729Sjoerg // Create the header block and insert the phi instructions.
3777330f729Sjoerg llvm::BasicBlock *HeaderBB = CGF.createBasicBlock("loop.header");
3787330f729Sjoerg CGF.EmitBlock(HeaderBB);
3797330f729Sjoerg llvm::PHINode *PHIs[N];
3807330f729Sjoerg
3817330f729Sjoerg for (unsigned I = 0; I < N; ++I) {
3827330f729Sjoerg PHIs[I] = CGF.Builder.CreatePHI(CGF.CGM.Int8PtrPtrTy, 2, "addr.cur");
3837330f729Sjoerg PHIs[I]->addIncoming(StartAddrs[I].getPointer(), PreheaderBB);
3847330f729Sjoerg }
3857330f729Sjoerg
3867330f729Sjoerg // Create the exit and loop body blocks.
3877330f729Sjoerg llvm::BasicBlock *ExitBB = CGF.createBasicBlock("loop.exit");
3887330f729Sjoerg llvm::BasicBlock *LoopBB = CGF.createBasicBlock("loop.body");
3897330f729Sjoerg
3907330f729Sjoerg // Emit the comparison and conditional branch instruction that jumps to
3917330f729Sjoerg // either the exit or the loop body.
3927330f729Sjoerg llvm::Value *Done =
3937330f729Sjoerg CGF.Builder.CreateICmpEQ(PHIs[DstIdx], DstArrayEnd, "done");
3947330f729Sjoerg CGF.Builder.CreateCondBr(Done, ExitBB, LoopBB);
3957330f729Sjoerg
3967330f729Sjoerg // Visit the element of the array in the loop body.
3977330f729Sjoerg CGF.EmitBlock(LoopBB);
3987330f729Sjoerg QualType EltQT = AT->getElementType();
3997330f729Sjoerg CharUnits EltSize = Ctx.getTypeSizeInChars(EltQT);
4007330f729Sjoerg std::array<Address, N> NewAddrs = Addrs;
4017330f729Sjoerg
4027330f729Sjoerg for (unsigned I = 0; I < N; ++I)
4037330f729Sjoerg NewAddrs[I] = Address(
4047330f729Sjoerg PHIs[I], StartAddrs[I].getAlignment().alignmentAtOffset(EltSize));
4057330f729Sjoerg
4067330f729Sjoerg EltQT = IsVolatile ? EltQT.withVolatile() : EltQT;
4077330f729Sjoerg this->asDerived().visitWithKind(FK, EltQT, nullptr, CharUnits::Zero(),
4087330f729Sjoerg NewAddrs);
4097330f729Sjoerg
4107330f729Sjoerg LoopBB = CGF.Builder.GetInsertBlock();
4117330f729Sjoerg
4127330f729Sjoerg for (unsigned I = 0; I < N; ++I) {
4137330f729Sjoerg // Instrs to update the destination and source addresses.
4147330f729Sjoerg // Update phi instructions.
4157330f729Sjoerg NewAddrs[I] = getAddrWithOffset(NewAddrs[I], EltSize);
4167330f729Sjoerg PHIs[I]->addIncoming(NewAddrs[I].getPointer(), LoopBB);
4177330f729Sjoerg }
4187330f729Sjoerg
4197330f729Sjoerg // Insert an unconditional branch to the header block.
4207330f729Sjoerg CGF.Builder.CreateBr(HeaderBB);
4217330f729Sjoerg CGF.EmitBlock(ExitBB);
4227330f729Sjoerg }
4237330f729Sjoerg
4247330f729Sjoerg /// Return an address with the specified offset from the passed address.
getAddrWithOffset__anon28b95f1e0111::GenFuncBase4257330f729Sjoerg Address getAddrWithOffset(Address Addr, CharUnits Offset) {
4267330f729Sjoerg assert(Addr.isValid() && "invalid address");
4277330f729Sjoerg if (Offset.getQuantity() == 0)
4287330f729Sjoerg return Addr;
4297330f729Sjoerg Addr = CGF->Builder.CreateBitCast(Addr, CGF->CGM.Int8PtrTy);
4307330f729Sjoerg Addr = CGF->Builder.CreateConstInBoundsGEP(Addr, Offset.getQuantity());
4317330f729Sjoerg return CGF->Builder.CreateBitCast(Addr, CGF->CGM.Int8PtrPtrTy);
4327330f729Sjoerg }
4337330f729Sjoerg
getAddrWithOffset__anon28b95f1e0111::GenFuncBase4347330f729Sjoerg Address getAddrWithOffset(Address Addr, CharUnits StructFieldOffset,
4357330f729Sjoerg const FieldDecl *FD) {
4367330f729Sjoerg return getAddrWithOffset(Addr, StructFieldOffset +
4377330f729Sjoerg asDerived().getFieldOffset(FD));
4387330f729Sjoerg }
4397330f729Sjoerg
4407330f729Sjoerg template <size_t N>
getFunction__anon28b95f1e0111::GenFuncBase441*e038c9c4Sjoerg llvm::Function *getFunction(StringRef FuncName, QualType QT,
442*e038c9c4Sjoerg std::array<CharUnits, N> Alignments,
443*e038c9c4Sjoerg CodeGenModule &CGM) {
4447330f729Sjoerg // If the special function already exists in the module, return it.
4457330f729Sjoerg if (llvm::Function *F = CGM.getModule().getFunction(FuncName)) {
4467330f729Sjoerg bool WrongType = false;
4477330f729Sjoerg if (!F->getReturnType()->isVoidTy())
4487330f729Sjoerg WrongType = true;
4497330f729Sjoerg else {
4507330f729Sjoerg for (const llvm::Argument &Arg : F->args())
4517330f729Sjoerg if (Arg.getType() != CGM.Int8PtrPtrTy)
4527330f729Sjoerg WrongType = true;
4537330f729Sjoerg }
4547330f729Sjoerg
4557330f729Sjoerg if (WrongType) {
456*e038c9c4Sjoerg std::string FuncName = std::string(F->getName());
4577330f729Sjoerg SourceLocation Loc = QT->castAs<RecordType>()->getDecl()->getLocation();
4587330f729Sjoerg CGM.Error(Loc, "special function " + FuncName +
4597330f729Sjoerg " for non-trivial C struct has incorrect type");
4607330f729Sjoerg return nullptr;
4617330f729Sjoerg }
4627330f729Sjoerg return F;
4637330f729Sjoerg }
4647330f729Sjoerg
4657330f729Sjoerg ASTContext &Ctx = CGM.getContext();
4667330f729Sjoerg FunctionArgList Args;
4677330f729Sjoerg const CGFunctionInfo &FI = getFunctionInfo<N>(CGM, Args);
4687330f729Sjoerg llvm::FunctionType *FuncTy = CGM.getTypes().GetFunctionType(FI);
4697330f729Sjoerg llvm::Function *F =
4707330f729Sjoerg llvm::Function::Create(FuncTy, llvm::GlobalValue::LinkOnceODRLinkage,
4717330f729Sjoerg FuncName, &CGM.getModule());
4727330f729Sjoerg F->setVisibility(llvm::GlobalValue::HiddenVisibility);
473*e038c9c4Sjoerg CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F, /*IsThunk=*/false);
4747330f729Sjoerg CGM.SetLLVMFunctionAttributesForDefinition(nullptr, F);
4757330f729Sjoerg IdentifierInfo *II = &Ctx.Idents.get(FuncName);
4767330f729Sjoerg FunctionDecl *FD = FunctionDecl::Create(
4777330f729Sjoerg Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(),
4787330f729Sjoerg II, Ctx.getFunctionType(Ctx.VoidTy, llvm::None, {}), nullptr,
4797330f729Sjoerg SC_PrivateExtern, false, false);
4807330f729Sjoerg CodeGenFunction NewCGF(CGM);
4817330f729Sjoerg setCGF(&NewCGF);
4827330f729Sjoerg CGF->StartFunction(FD, Ctx.VoidTy, F, FI, Args);
483*e038c9c4Sjoerg std::array<Address, N> Addrs =
484*e038c9c4Sjoerg getParamAddrs<N>(std::make_index_sequence<N>{}, Alignments, Args, CGF);
4857330f729Sjoerg asDerived().visitStructFields(QT, CharUnits::Zero(), Addrs);
4867330f729Sjoerg CGF->FinishFunction();
4877330f729Sjoerg return F;
4887330f729Sjoerg }
4897330f729Sjoerg
4907330f729Sjoerg template <size_t N>
callFunc__anon28b95f1e0111::GenFuncBase4917330f729Sjoerg void callFunc(StringRef FuncName, QualType QT, std::array<Address, N> Addrs,
4927330f729Sjoerg CodeGenFunction &CallerCGF) {
4937330f729Sjoerg std::array<CharUnits, N> Alignments;
4947330f729Sjoerg llvm::Value *Ptrs[N];
4957330f729Sjoerg
4967330f729Sjoerg for (unsigned I = 0; I < N; ++I) {
4977330f729Sjoerg Alignments[I] = Addrs[I].getAlignment();
4987330f729Sjoerg Ptrs[I] =
4997330f729Sjoerg CallerCGF.Builder.CreateBitCast(Addrs[I], CallerCGF.CGM.Int8PtrPtrTy)
5007330f729Sjoerg .getPointer();
5017330f729Sjoerg }
5027330f729Sjoerg
5037330f729Sjoerg if (llvm::Function *F =
504*e038c9c4Sjoerg getFunction(FuncName, QT, Alignments, CallerCGF.CGM))
5057330f729Sjoerg CallerCGF.EmitNounwindRuntimeCall(F, Ptrs);
5067330f729Sjoerg }
5077330f729Sjoerg
asDerived__anon28b95f1e0111::GenFuncBase5087330f729Sjoerg Derived &asDerived() { return static_cast<Derived &>(*this); }
5097330f729Sjoerg
setCGF__anon28b95f1e0111::GenFuncBase5107330f729Sjoerg void setCGF(CodeGenFunction *F) { CGF = F; }
5117330f729Sjoerg
5127330f729Sjoerg CodeGenFunction *CGF = nullptr;
5137330f729Sjoerg };
5147330f729Sjoerg
5157330f729Sjoerg template <class Derived, bool IsMove>
5167330f729Sjoerg struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>,
5177330f729Sjoerg GenFuncBase<Derived> {
GenBinaryFunc__anon28b95f1e0111::GenBinaryFunc5187330f729Sjoerg GenBinaryFunc(ASTContext &Ctx) : CopyStructVisitor<Derived, IsMove>(Ctx) {}
5197330f729Sjoerg
flushTrivialFields__anon28b95f1e0111::GenBinaryFunc5207330f729Sjoerg void flushTrivialFields(std::array<Address, 2> Addrs) {
5217330f729Sjoerg CharUnits Size = this->End - this->Start;
5227330f729Sjoerg
5237330f729Sjoerg if (Size.getQuantity() == 0)
5247330f729Sjoerg return;
5257330f729Sjoerg
5267330f729Sjoerg Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], this->Start);
5277330f729Sjoerg Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], this->Start);
5287330f729Sjoerg
5297330f729Sjoerg // Emit memcpy.
5307330f729Sjoerg if (Size.getQuantity() >= 16 || !llvm::isPowerOf2_32(Size.getQuantity())) {
5317330f729Sjoerg llvm::Value *SizeVal =
5327330f729Sjoerg llvm::ConstantInt::get(this->CGF->SizeTy, Size.getQuantity());
5337330f729Sjoerg DstAddr =
5347330f729Sjoerg this->CGF->Builder.CreateElementBitCast(DstAddr, this->CGF->Int8Ty);
5357330f729Sjoerg SrcAddr =
5367330f729Sjoerg this->CGF->Builder.CreateElementBitCast(SrcAddr, this->CGF->Int8Ty);
5377330f729Sjoerg this->CGF->Builder.CreateMemCpy(DstAddr, SrcAddr, SizeVal, false);
5387330f729Sjoerg } else {
5397330f729Sjoerg llvm::Type *Ty = llvm::Type::getIntNTy(
5407330f729Sjoerg this->CGF->getLLVMContext(),
5417330f729Sjoerg Size.getQuantity() * this->CGF->getContext().getCharWidth());
5427330f729Sjoerg DstAddr = this->CGF->Builder.CreateElementBitCast(DstAddr, Ty);
5437330f729Sjoerg SrcAddr = this->CGF->Builder.CreateElementBitCast(SrcAddr, Ty);
5447330f729Sjoerg llvm::Value *SrcVal = this->CGF->Builder.CreateLoad(SrcAddr, false);
5457330f729Sjoerg this->CGF->Builder.CreateStore(SrcVal, DstAddr, false);
5467330f729Sjoerg }
5477330f729Sjoerg
5487330f729Sjoerg this->Start = this->End = CharUnits::Zero();
5497330f729Sjoerg }
5507330f729Sjoerg
5517330f729Sjoerg template <class... Ts>
visitVolatileTrivial__anon28b95f1e0111::GenBinaryFunc5527330f729Sjoerg void visitVolatileTrivial(QualType FT, const FieldDecl *FD, CharUnits Offset,
5537330f729Sjoerg std::array<Address, 2> Addrs) {
5547330f729Sjoerg LValue DstLV, SrcLV;
5557330f729Sjoerg if (FD) {
556*e038c9c4Sjoerg // No need to copy zero-length bit-fields.
557*e038c9c4Sjoerg if (FD->isZeroLengthBitField(this->CGF->getContext()))
558*e038c9c4Sjoerg return;
559*e038c9c4Sjoerg
5607330f729Sjoerg QualType RT = QualType(FD->getParent()->getTypeForDecl(), 0);
5617330f729Sjoerg llvm::PointerType *PtrTy = this->CGF->ConvertType(RT)->getPointerTo();
5627330f729Sjoerg Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset);
5637330f729Sjoerg LValue DstBase = this->CGF->MakeAddrLValue(
5647330f729Sjoerg this->CGF->Builder.CreateBitCast(DstAddr, PtrTy), FT);
5657330f729Sjoerg DstLV = this->CGF->EmitLValueForField(DstBase, FD);
5667330f729Sjoerg Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], Offset);
5677330f729Sjoerg LValue SrcBase = this->CGF->MakeAddrLValue(
5687330f729Sjoerg this->CGF->Builder.CreateBitCast(SrcAddr, PtrTy), FT);
5697330f729Sjoerg SrcLV = this->CGF->EmitLValueForField(SrcBase, FD);
5707330f729Sjoerg } else {
571*e038c9c4Sjoerg llvm::PointerType *Ty = this->CGF->ConvertTypeForMem(FT)->getPointerTo();
5727330f729Sjoerg Address DstAddr = this->CGF->Builder.CreateBitCast(Addrs[DstIdx], Ty);
5737330f729Sjoerg Address SrcAddr = this->CGF->Builder.CreateBitCast(Addrs[SrcIdx], Ty);
5747330f729Sjoerg DstLV = this->CGF->MakeAddrLValue(DstAddr, FT);
5757330f729Sjoerg SrcLV = this->CGF->MakeAddrLValue(SrcAddr, FT);
5767330f729Sjoerg }
5777330f729Sjoerg RValue SrcVal = this->CGF->EmitLoadOfLValue(SrcLV, SourceLocation());
5787330f729Sjoerg this->CGF->EmitStoreThroughLValue(SrcVal, DstLV);
5797330f729Sjoerg }
5807330f729Sjoerg };
5817330f729Sjoerg
5827330f729Sjoerg // These classes that emit the special functions for a non-trivial struct.
5837330f729Sjoerg struct GenDestructor : StructVisitor<GenDestructor>,
5847330f729Sjoerg GenFuncBase<GenDestructor>,
5857330f729Sjoerg DestructedTypeVisitor<GenDestructor> {
5867330f729Sjoerg using Super = DestructedTypeVisitor<GenDestructor>;
GenDestructor__anon28b95f1e0111::GenDestructor5877330f729Sjoerg GenDestructor(ASTContext &Ctx) : StructVisitor<GenDestructor>(Ctx) {}
5887330f729Sjoerg
visitWithKind__anon28b95f1e0111::GenDestructor5897330f729Sjoerg void visitWithKind(QualType::DestructionKind DK, QualType FT,
5907330f729Sjoerg const FieldDecl *FD, CharUnits CurStructOffset,
5917330f729Sjoerg std::array<Address, 1> Addrs) {
5927330f729Sjoerg if (const auto *AT = getContext().getAsArrayType(FT)) {
5937330f729Sjoerg visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset, Addrs);
5947330f729Sjoerg return;
5957330f729Sjoerg }
5967330f729Sjoerg
5977330f729Sjoerg Super::visitWithKind(DK, FT, FD, CurStructOffset, Addrs);
5987330f729Sjoerg }
5997330f729Sjoerg
visitARCStrong__anon28b95f1e0111::GenDestructor6007330f729Sjoerg void visitARCStrong(QualType QT, const FieldDecl *FD,
6017330f729Sjoerg CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
6027330f729Sjoerg CGF->destroyARCStrongImprecise(
6037330f729Sjoerg *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
6047330f729Sjoerg }
6057330f729Sjoerg
visitARCWeak__anon28b95f1e0111::GenDestructor6067330f729Sjoerg void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
6077330f729Sjoerg std::array<Address, 1> Addrs) {
6087330f729Sjoerg CGF->destroyARCWeak(
6097330f729Sjoerg *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
6107330f729Sjoerg }
6117330f729Sjoerg
callSpecialFunction__anon28b95f1e0111::GenDestructor6127330f729Sjoerg void callSpecialFunction(QualType FT, CharUnits Offset,
6137330f729Sjoerg std::array<Address, 1> Addrs) {
6147330f729Sjoerg CGF->callCStructDestructor(
6157330f729Sjoerg CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
6167330f729Sjoerg }
6177330f729Sjoerg };
6187330f729Sjoerg
6197330f729Sjoerg struct GenDefaultInitialize
6207330f729Sjoerg : StructVisitor<GenDefaultInitialize>,
6217330f729Sjoerg GenFuncBase<GenDefaultInitialize>,
6227330f729Sjoerg DefaultInitializedTypeVisitor<GenDefaultInitialize> {
6237330f729Sjoerg using Super = DefaultInitializedTypeVisitor<GenDefaultInitialize>;
6247330f729Sjoerg typedef GenFuncBase<GenDefaultInitialize> GenFuncBaseTy;
6257330f729Sjoerg
GenDefaultInitialize__anon28b95f1e0111::GenDefaultInitialize6267330f729Sjoerg GenDefaultInitialize(ASTContext &Ctx)
6277330f729Sjoerg : StructVisitor<GenDefaultInitialize>(Ctx) {}
6287330f729Sjoerg
visitWithKind__anon28b95f1e0111::GenDefaultInitialize6297330f729Sjoerg void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
6307330f729Sjoerg const FieldDecl *FD, CharUnits CurStructOffset,
6317330f729Sjoerg std::array<Address, 1> Addrs) {
6327330f729Sjoerg if (const auto *AT = getContext().getAsArrayType(FT)) {
6337330f729Sjoerg visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset,
6347330f729Sjoerg Addrs);
6357330f729Sjoerg return;
6367330f729Sjoerg }
6377330f729Sjoerg
6387330f729Sjoerg Super::visitWithKind(PDIK, FT, FD, CurStructOffset, Addrs);
6397330f729Sjoerg }
6407330f729Sjoerg
visitARCStrong__anon28b95f1e0111::GenDefaultInitialize6417330f729Sjoerg void visitARCStrong(QualType QT, const FieldDecl *FD,
6427330f729Sjoerg CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
6437330f729Sjoerg CGF->EmitNullInitialization(
6447330f729Sjoerg getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
6457330f729Sjoerg }
6467330f729Sjoerg
visitARCWeak__anon28b95f1e0111::GenDefaultInitialize6477330f729Sjoerg void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
6487330f729Sjoerg std::array<Address, 1> Addrs) {
6497330f729Sjoerg CGF->EmitNullInitialization(
6507330f729Sjoerg getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
6517330f729Sjoerg }
6527330f729Sjoerg
6537330f729Sjoerg template <class FieldKind, size_t... Is>
visitArray__anon28b95f1e0111::GenDefaultInitialize6547330f729Sjoerg void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
6557330f729Sjoerg const FieldDecl *FD, CharUnits CurStructOffset,
6567330f729Sjoerg std::array<Address, 1> Addrs) {
6577330f729Sjoerg if (!FK)
6587330f729Sjoerg return visitTrivial(QualType(AT, 0), FD, CurStructOffset, Addrs);
6597330f729Sjoerg
6607330f729Sjoerg ASTContext &Ctx = getContext();
6617330f729Sjoerg CharUnits Size = Ctx.getTypeSizeInChars(QualType(AT, 0));
6627330f729Sjoerg QualType EltTy = Ctx.getBaseElementType(QualType(AT, 0));
6637330f729Sjoerg
6647330f729Sjoerg if (Size < CharUnits::fromQuantity(16) || EltTy->getAs<RecordType>()) {
6657330f729Sjoerg GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStructOffset, Addrs);
6667330f729Sjoerg return;
6677330f729Sjoerg }
6687330f729Sjoerg
6697330f729Sjoerg llvm::Constant *SizeVal = CGF->Builder.getInt64(Size.getQuantity());
6707330f729Sjoerg Address DstAddr = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
6717330f729Sjoerg Address Loc = CGF->Builder.CreateElementBitCast(DstAddr, CGF->Int8Ty);
6727330f729Sjoerg CGF->Builder.CreateMemSet(Loc, CGF->Builder.getInt8(0), SizeVal,
6737330f729Sjoerg IsVolatile);
6747330f729Sjoerg }
6757330f729Sjoerg
callSpecialFunction__anon28b95f1e0111::GenDefaultInitialize6767330f729Sjoerg void callSpecialFunction(QualType FT, CharUnits Offset,
6777330f729Sjoerg std::array<Address, 1> Addrs) {
6787330f729Sjoerg CGF->callCStructDefaultConstructor(
6797330f729Sjoerg CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
6807330f729Sjoerg }
6817330f729Sjoerg };
6827330f729Sjoerg
6837330f729Sjoerg struct GenCopyConstructor : GenBinaryFunc<GenCopyConstructor, false> {
GenCopyConstructor__anon28b95f1e0111::GenCopyConstructor6847330f729Sjoerg GenCopyConstructor(ASTContext &Ctx)
6857330f729Sjoerg : GenBinaryFunc<GenCopyConstructor, false>(Ctx) {}
6867330f729Sjoerg
visitARCStrong__anon28b95f1e0111::GenCopyConstructor6877330f729Sjoerg void visitARCStrong(QualType QT, const FieldDecl *FD,
6887330f729Sjoerg CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
6897330f729Sjoerg Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
6907330f729Sjoerg Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
6917330f729Sjoerg llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
6927330f729Sjoerg Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
6937330f729Sjoerg llvm::Value *Val = CGF->EmitARCRetain(QT, SrcVal);
6947330f729Sjoerg CGF->EmitStoreOfScalar(Val, CGF->MakeAddrLValue(Addrs[DstIdx], QT), true);
6957330f729Sjoerg }
6967330f729Sjoerg
visitARCWeak__anon28b95f1e0111::GenCopyConstructor6977330f729Sjoerg void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
6987330f729Sjoerg std::array<Address, 2> Addrs) {
6997330f729Sjoerg Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
7007330f729Sjoerg Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7017330f729Sjoerg CGF->EmitARCCopyWeak(Addrs[DstIdx], Addrs[SrcIdx]);
7027330f729Sjoerg }
7037330f729Sjoerg
callSpecialFunction__anon28b95f1e0111::GenCopyConstructor7047330f729Sjoerg void callSpecialFunction(QualType FT, CharUnits Offset,
7057330f729Sjoerg std::array<Address, 2> Addrs) {
7067330f729Sjoerg Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
7077330f729Sjoerg Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
7087330f729Sjoerg CGF->callCStructCopyConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
7097330f729Sjoerg CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
7107330f729Sjoerg }
7117330f729Sjoerg };
7127330f729Sjoerg
7137330f729Sjoerg struct GenMoveConstructor : GenBinaryFunc<GenMoveConstructor, true> {
GenMoveConstructor__anon28b95f1e0111::GenMoveConstructor7147330f729Sjoerg GenMoveConstructor(ASTContext &Ctx)
7157330f729Sjoerg : GenBinaryFunc<GenMoveConstructor, true>(Ctx) {}
7167330f729Sjoerg
visitARCStrong__anon28b95f1e0111::GenMoveConstructor7177330f729Sjoerg void visitARCStrong(QualType QT, const FieldDecl *FD,
7187330f729Sjoerg CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
7197330f729Sjoerg Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
7207330f729Sjoerg Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7217330f729Sjoerg LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
7227330f729Sjoerg llvm::Value *SrcVal =
7237330f729Sjoerg CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
724*e038c9c4Sjoerg CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress(*CGF)), SrcLV);
7257330f729Sjoerg CGF->EmitStoreOfScalar(SrcVal, CGF->MakeAddrLValue(Addrs[DstIdx], QT),
7267330f729Sjoerg /* isInitialization */ true);
7277330f729Sjoerg }
7287330f729Sjoerg
visitARCWeak__anon28b95f1e0111::GenMoveConstructor7297330f729Sjoerg void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
7307330f729Sjoerg std::array<Address, 2> Addrs) {
7317330f729Sjoerg Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
7327330f729Sjoerg Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7337330f729Sjoerg CGF->EmitARCMoveWeak(Addrs[DstIdx], Addrs[SrcIdx]);
7347330f729Sjoerg }
7357330f729Sjoerg
callSpecialFunction__anon28b95f1e0111::GenMoveConstructor7367330f729Sjoerg void callSpecialFunction(QualType FT, CharUnits Offset,
7377330f729Sjoerg std::array<Address, 2> Addrs) {
7387330f729Sjoerg Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
7397330f729Sjoerg Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
7407330f729Sjoerg CGF->callCStructMoveConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
7417330f729Sjoerg CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
7427330f729Sjoerg }
7437330f729Sjoerg };
7447330f729Sjoerg
7457330f729Sjoerg struct GenCopyAssignment : GenBinaryFunc<GenCopyAssignment, false> {
GenCopyAssignment__anon28b95f1e0111::GenCopyAssignment7467330f729Sjoerg GenCopyAssignment(ASTContext &Ctx)
7477330f729Sjoerg : GenBinaryFunc<GenCopyAssignment, false>(Ctx) {}
7487330f729Sjoerg
visitARCStrong__anon28b95f1e0111::GenCopyAssignment7497330f729Sjoerg void visitARCStrong(QualType QT, const FieldDecl *FD,
7507330f729Sjoerg CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
7517330f729Sjoerg Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
7527330f729Sjoerg Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7537330f729Sjoerg llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
7547330f729Sjoerg Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
7557330f729Sjoerg CGF->EmitARCStoreStrong(CGF->MakeAddrLValue(Addrs[DstIdx], QT), SrcVal,
7567330f729Sjoerg false);
7577330f729Sjoerg }
7587330f729Sjoerg
visitARCWeak__anon28b95f1e0111::GenCopyAssignment7597330f729Sjoerg void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
7607330f729Sjoerg std::array<Address, 2> Addrs) {
7617330f729Sjoerg Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
7627330f729Sjoerg Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7637330f729Sjoerg CGF->emitARCCopyAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
7647330f729Sjoerg }
7657330f729Sjoerg
callSpecialFunction__anon28b95f1e0111::GenCopyAssignment7667330f729Sjoerg void callSpecialFunction(QualType FT, CharUnits Offset,
7677330f729Sjoerg std::array<Address, 2> Addrs) {
7687330f729Sjoerg Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
7697330f729Sjoerg Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
7707330f729Sjoerg CGF->callCStructCopyAssignmentOperator(
7717330f729Sjoerg CGF->MakeAddrLValue(Addrs[DstIdx], FT),
7727330f729Sjoerg CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
7737330f729Sjoerg }
7747330f729Sjoerg };
7757330f729Sjoerg
7767330f729Sjoerg struct GenMoveAssignment : GenBinaryFunc<GenMoveAssignment, true> {
GenMoveAssignment__anon28b95f1e0111::GenMoveAssignment7777330f729Sjoerg GenMoveAssignment(ASTContext &Ctx)
7787330f729Sjoerg : GenBinaryFunc<GenMoveAssignment, true>(Ctx) {}
7797330f729Sjoerg
visitARCStrong__anon28b95f1e0111::GenMoveAssignment7807330f729Sjoerg void visitARCStrong(QualType QT, const FieldDecl *FD,
7817330f729Sjoerg CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
7827330f729Sjoerg Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
7837330f729Sjoerg Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7847330f729Sjoerg LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
7857330f729Sjoerg llvm::Value *SrcVal =
7867330f729Sjoerg CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
787*e038c9c4Sjoerg CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress(*CGF)), SrcLV);
7887330f729Sjoerg LValue DstLV = CGF->MakeAddrLValue(Addrs[DstIdx], QT);
7897330f729Sjoerg llvm::Value *DstVal =
7907330f729Sjoerg CGF->EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
7917330f729Sjoerg CGF->EmitStoreOfScalar(SrcVal, DstLV);
7927330f729Sjoerg CGF->EmitARCRelease(DstVal, ARCImpreciseLifetime);
7937330f729Sjoerg }
7947330f729Sjoerg
visitARCWeak__anon28b95f1e0111::GenMoveAssignment7957330f729Sjoerg void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
7967330f729Sjoerg std::array<Address, 2> Addrs) {
7977330f729Sjoerg Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
7987330f729Sjoerg Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7997330f729Sjoerg CGF->emitARCMoveAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
8007330f729Sjoerg }
8017330f729Sjoerg
callSpecialFunction__anon28b95f1e0111::GenMoveAssignment8027330f729Sjoerg void callSpecialFunction(QualType FT, CharUnits Offset,
8037330f729Sjoerg std::array<Address, 2> Addrs) {
8047330f729Sjoerg Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
8057330f729Sjoerg Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
8067330f729Sjoerg CGF->callCStructMoveAssignmentOperator(
8077330f729Sjoerg CGF->MakeAddrLValue(Addrs[DstIdx], FT),
8087330f729Sjoerg CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
8097330f729Sjoerg }
8107330f729Sjoerg };
8117330f729Sjoerg
8127330f729Sjoerg } // namespace
8137330f729Sjoerg
destroyNonTrivialCStruct(CodeGenFunction & CGF,Address Addr,QualType Type)8147330f729Sjoerg void CodeGenFunction::destroyNonTrivialCStruct(CodeGenFunction &CGF,
8157330f729Sjoerg Address Addr, QualType Type) {
8167330f729Sjoerg CGF.callCStructDestructor(CGF.MakeAddrLValue(Addr, Type));
8177330f729Sjoerg }
8187330f729Sjoerg
8197330f729Sjoerg // Default-initialize a variable that is a non-trivial struct or an array of
8207330f729Sjoerg // such structure.
defaultInitNonTrivialCStructVar(LValue Dst)8217330f729Sjoerg void CodeGenFunction::defaultInitNonTrivialCStructVar(LValue Dst) {
8227330f729Sjoerg GenDefaultInitialize Gen(getContext());
823*e038c9c4Sjoerg Address DstPtr =
824*e038c9c4Sjoerg Builder.CreateBitCast(Dst.getAddress(*this), CGM.Int8PtrPtrTy);
8257330f729Sjoerg Gen.setCGF(this);
8267330f729Sjoerg QualType QT = Dst.getType();
8277330f729Sjoerg QT = Dst.isVolatile() ? QT.withVolatile() : QT;
8287330f729Sjoerg Gen.visit(QT, nullptr, CharUnits::Zero(), std::array<Address, 1>({{DstPtr}}));
8297330f729Sjoerg }
8307330f729Sjoerg
8317330f729Sjoerg template <class G, size_t N>
callSpecialFunction(G && Gen,StringRef FuncName,QualType QT,bool IsVolatile,CodeGenFunction & CGF,std::array<Address,N> Addrs)8327330f729Sjoerg static void callSpecialFunction(G &&Gen, StringRef FuncName, QualType QT,
8337330f729Sjoerg bool IsVolatile, CodeGenFunction &CGF,
8347330f729Sjoerg std::array<Address, N> Addrs) {
835*e038c9c4Sjoerg auto SetArtificialLoc = ApplyDebugLocation::CreateArtificial(CGF);
8367330f729Sjoerg for (unsigned I = 0; I < N; ++I)
8377330f729Sjoerg Addrs[I] = CGF.Builder.CreateBitCast(Addrs[I], CGF.CGM.Int8PtrPtrTy);
8387330f729Sjoerg QT = IsVolatile ? QT.withVolatile() : QT;
8397330f729Sjoerg Gen.callFunc(FuncName, QT, Addrs, CGF);
8407330f729Sjoerg }
8417330f729Sjoerg
8427330f729Sjoerg template <class G, size_t N>
8437330f729Sjoerg static llvm::Function *
getSpecialFunction(G && Gen,StringRef FuncName,QualType QT,bool IsVolatile,std::array<CharUnits,N> Alignments,CodeGenModule & CGM)8447330f729Sjoerg getSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile,
8457330f729Sjoerg std::array<CharUnits, N> Alignments, CodeGenModule &CGM) {
8467330f729Sjoerg QT = IsVolatile ? QT.withVolatile() : QT;
8477330f729Sjoerg // The following call requires an array of addresses as arguments, but doesn't
8487330f729Sjoerg // actually use them (it overwrites them with the addresses of the arguments
8497330f729Sjoerg // of the created function).
850*e038c9c4Sjoerg return Gen.getFunction(FuncName, QT, Alignments, CGM);
8517330f729Sjoerg }
8527330f729Sjoerg
8537330f729Sjoerg // Functions to emit calls to the special functions of a non-trivial C struct.
callCStructDefaultConstructor(LValue Dst)8547330f729Sjoerg void CodeGenFunction::callCStructDefaultConstructor(LValue Dst) {
8557330f729Sjoerg bool IsVolatile = Dst.isVolatile();
856*e038c9c4Sjoerg Address DstPtr = Dst.getAddress(*this);
8577330f729Sjoerg QualType QT = Dst.getType();
8587330f729Sjoerg GenDefaultInitializeFuncName GenName(DstPtr.getAlignment(), getContext());
8597330f729Sjoerg std::string FuncName = GenName.getName(QT, IsVolatile);
8607330f729Sjoerg callSpecialFunction(GenDefaultInitialize(getContext()), FuncName, QT,
8617330f729Sjoerg IsVolatile, *this, std::array<Address, 1>({{DstPtr}}));
8627330f729Sjoerg }
8637330f729Sjoerg
getNonTrivialCopyConstructorStr(QualType QT,CharUnits Alignment,bool IsVolatile,ASTContext & Ctx)8647330f729Sjoerg std::string CodeGenFunction::getNonTrivialCopyConstructorStr(
8657330f729Sjoerg QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx) {
8667330f729Sjoerg GenBinaryFuncName<false> GenName("", Alignment, Alignment, Ctx);
8677330f729Sjoerg return GenName.getName(QT, IsVolatile);
8687330f729Sjoerg }
8697330f729Sjoerg
getNonTrivialDestructorStr(QualType QT,CharUnits Alignment,bool IsVolatile,ASTContext & Ctx)8707330f729Sjoerg std::string CodeGenFunction::getNonTrivialDestructorStr(QualType QT,
8717330f729Sjoerg CharUnits Alignment,
8727330f729Sjoerg bool IsVolatile,
8737330f729Sjoerg ASTContext &Ctx) {
8747330f729Sjoerg GenDestructorFuncName GenName("", Alignment, Ctx);
8757330f729Sjoerg return GenName.getName(QT, IsVolatile);
8767330f729Sjoerg }
8777330f729Sjoerg
callCStructDestructor(LValue Dst)8787330f729Sjoerg void CodeGenFunction::callCStructDestructor(LValue Dst) {
8797330f729Sjoerg bool IsVolatile = Dst.isVolatile();
880*e038c9c4Sjoerg Address DstPtr = Dst.getAddress(*this);
8817330f729Sjoerg QualType QT = Dst.getType();
8827330f729Sjoerg GenDestructorFuncName GenName("__destructor_", DstPtr.getAlignment(),
8837330f729Sjoerg getContext());
8847330f729Sjoerg std::string FuncName = GenName.getName(QT, IsVolatile);
8857330f729Sjoerg callSpecialFunction(GenDestructor(getContext()), FuncName, QT, IsVolatile,
8867330f729Sjoerg *this, std::array<Address, 1>({{DstPtr}}));
8877330f729Sjoerg }
8887330f729Sjoerg
callCStructCopyConstructor(LValue Dst,LValue Src)8897330f729Sjoerg void CodeGenFunction::callCStructCopyConstructor(LValue Dst, LValue Src) {
8907330f729Sjoerg bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
891*e038c9c4Sjoerg Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
8927330f729Sjoerg QualType QT = Dst.getType();
8937330f729Sjoerg GenBinaryFuncName<false> GenName("__copy_constructor_", DstPtr.getAlignment(),
8947330f729Sjoerg SrcPtr.getAlignment(), getContext());
8957330f729Sjoerg std::string FuncName = GenName.getName(QT, IsVolatile);
8967330f729Sjoerg callSpecialFunction(GenCopyConstructor(getContext()), FuncName, QT,
8977330f729Sjoerg IsVolatile, *this,
8987330f729Sjoerg std::array<Address, 2>({{DstPtr, SrcPtr}}));
8997330f729Sjoerg }
9007330f729Sjoerg
callCStructCopyAssignmentOperator(LValue Dst,LValue Src)9017330f729Sjoerg void CodeGenFunction::callCStructCopyAssignmentOperator(LValue Dst, LValue Src
9027330f729Sjoerg
9037330f729Sjoerg ) {
9047330f729Sjoerg bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
905*e038c9c4Sjoerg Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
9067330f729Sjoerg QualType QT = Dst.getType();
9077330f729Sjoerg GenBinaryFuncName<false> GenName("__copy_assignment_", DstPtr.getAlignment(),
9087330f729Sjoerg SrcPtr.getAlignment(), getContext());
9097330f729Sjoerg std::string FuncName = GenName.getName(QT, IsVolatile);
9107330f729Sjoerg callSpecialFunction(GenCopyAssignment(getContext()), FuncName, QT, IsVolatile,
9117330f729Sjoerg *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
9127330f729Sjoerg }
9137330f729Sjoerg
callCStructMoveConstructor(LValue Dst,LValue Src)9147330f729Sjoerg void CodeGenFunction::callCStructMoveConstructor(LValue Dst, LValue Src) {
9157330f729Sjoerg bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
916*e038c9c4Sjoerg Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
9177330f729Sjoerg QualType QT = Dst.getType();
9187330f729Sjoerg GenBinaryFuncName<true> GenName("__move_constructor_", DstPtr.getAlignment(),
9197330f729Sjoerg SrcPtr.getAlignment(), getContext());
9207330f729Sjoerg std::string FuncName = GenName.getName(QT, IsVolatile);
9217330f729Sjoerg callSpecialFunction(GenMoveConstructor(getContext()), FuncName, QT,
9227330f729Sjoerg IsVolatile, *this,
9237330f729Sjoerg std::array<Address, 2>({{DstPtr, SrcPtr}}));
9247330f729Sjoerg }
9257330f729Sjoerg
callCStructMoveAssignmentOperator(LValue Dst,LValue Src)9267330f729Sjoerg void CodeGenFunction::callCStructMoveAssignmentOperator(LValue Dst, LValue Src
9277330f729Sjoerg
9287330f729Sjoerg ) {
9297330f729Sjoerg bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
930*e038c9c4Sjoerg Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
9317330f729Sjoerg QualType QT = Dst.getType();
9327330f729Sjoerg GenBinaryFuncName<true> GenName("__move_assignment_", DstPtr.getAlignment(),
9337330f729Sjoerg SrcPtr.getAlignment(), getContext());
9347330f729Sjoerg std::string FuncName = GenName.getName(QT, IsVolatile);
9357330f729Sjoerg callSpecialFunction(GenMoveAssignment(getContext()), FuncName, QT, IsVolatile,
9367330f729Sjoerg *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
9377330f729Sjoerg }
9387330f729Sjoerg
getNonTrivialCStructDefaultConstructor(CodeGenModule & CGM,CharUnits DstAlignment,bool IsVolatile,QualType QT)9397330f729Sjoerg llvm::Function *clang::CodeGen::getNonTrivialCStructDefaultConstructor(
9407330f729Sjoerg CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
9417330f729Sjoerg ASTContext &Ctx = CGM.getContext();
9427330f729Sjoerg GenDefaultInitializeFuncName GenName(DstAlignment, Ctx);
9437330f729Sjoerg std::string FuncName = GenName.getName(QT, IsVolatile);
9447330f729Sjoerg return getSpecialFunction(GenDefaultInitialize(Ctx), FuncName, QT, IsVolatile,
9457330f729Sjoerg std::array<CharUnits, 1>({{DstAlignment}}), CGM);
9467330f729Sjoerg }
9477330f729Sjoerg
getNonTrivialCStructCopyConstructor(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)9487330f729Sjoerg llvm::Function *clang::CodeGen::getNonTrivialCStructCopyConstructor(
9497330f729Sjoerg CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
9507330f729Sjoerg bool IsVolatile, QualType QT) {
9517330f729Sjoerg ASTContext &Ctx = CGM.getContext();
9527330f729Sjoerg GenBinaryFuncName<false> GenName("__copy_constructor_", DstAlignment,
9537330f729Sjoerg SrcAlignment, Ctx);
9547330f729Sjoerg std::string FuncName = GenName.getName(QT, IsVolatile);
9557330f729Sjoerg return getSpecialFunction(
9567330f729Sjoerg GenCopyConstructor(Ctx), FuncName, QT, IsVolatile,
9577330f729Sjoerg std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
9587330f729Sjoerg }
9597330f729Sjoerg
getNonTrivialCStructMoveConstructor(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)9607330f729Sjoerg llvm::Function *clang::CodeGen::getNonTrivialCStructMoveConstructor(
9617330f729Sjoerg CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
9627330f729Sjoerg bool IsVolatile, QualType QT) {
9637330f729Sjoerg ASTContext &Ctx = CGM.getContext();
9647330f729Sjoerg GenBinaryFuncName<true> GenName("__move_constructor_", DstAlignment,
9657330f729Sjoerg SrcAlignment, Ctx);
9667330f729Sjoerg std::string FuncName = GenName.getName(QT, IsVolatile);
9677330f729Sjoerg return getSpecialFunction(
9687330f729Sjoerg GenMoveConstructor(Ctx), FuncName, QT, IsVolatile,
9697330f729Sjoerg std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
9707330f729Sjoerg }
9717330f729Sjoerg
getNonTrivialCStructCopyAssignmentOperator(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)9727330f729Sjoerg llvm::Function *clang::CodeGen::getNonTrivialCStructCopyAssignmentOperator(
9737330f729Sjoerg CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
9747330f729Sjoerg bool IsVolatile, QualType QT) {
9757330f729Sjoerg ASTContext &Ctx = CGM.getContext();
9767330f729Sjoerg GenBinaryFuncName<false> GenName("__copy_assignment_", DstAlignment,
9777330f729Sjoerg SrcAlignment, Ctx);
9787330f729Sjoerg std::string FuncName = GenName.getName(QT, IsVolatile);
9797330f729Sjoerg return getSpecialFunction(
9807330f729Sjoerg GenCopyAssignment(Ctx), FuncName, QT, IsVolatile,
9817330f729Sjoerg std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
9827330f729Sjoerg }
9837330f729Sjoerg
getNonTrivialCStructMoveAssignmentOperator(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)9847330f729Sjoerg llvm::Function *clang::CodeGen::getNonTrivialCStructMoveAssignmentOperator(
9857330f729Sjoerg CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
9867330f729Sjoerg bool IsVolatile, QualType QT) {
9877330f729Sjoerg ASTContext &Ctx = CGM.getContext();
9887330f729Sjoerg GenBinaryFuncName<true> GenName("__move_assignment_", DstAlignment,
9897330f729Sjoerg SrcAlignment, Ctx);
9907330f729Sjoerg std::string FuncName = GenName.getName(QT, IsVolatile);
9917330f729Sjoerg return getSpecialFunction(
9927330f729Sjoerg GenMoveAssignment(Ctx), FuncName, QT, IsVolatile,
9937330f729Sjoerg std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
9947330f729Sjoerg }
9957330f729Sjoerg
getNonTrivialCStructDestructor(CodeGenModule & CGM,CharUnits DstAlignment,bool IsVolatile,QualType QT)9967330f729Sjoerg llvm::Function *clang::CodeGen::getNonTrivialCStructDestructor(
9977330f729Sjoerg CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
9987330f729Sjoerg ASTContext &Ctx = CGM.getContext();
9997330f729Sjoerg GenDestructorFuncName GenName("__destructor_", DstAlignment, Ctx);
10007330f729Sjoerg std::string FuncName = GenName.getName(QT, IsVolatile);
10017330f729Sjoerg return getSpecialFunction(GenDestructor(Ctx), FuncName, QT, IsVolatile,
10027330f729Sjoerg std::array<CharUnits, 1>({{DstAlignment}}), CGM);
10037330f729Sjoerg }
1004