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