1*0b57cec5SDimitry Andric //===--- CGNonTrivialStruct.cpp - Emit Special Functions for C Structs ----===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file defines functions to generate various special functions for C 10*0b57cec5SDimitry Andric // structs. 11*0b57cec5SDimitry Andric // 12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric #include "CodeGenFunction.h" 15*0b57cec5SDimitry Andric #include "CodeGenModule.h" 16*0b57cec5SDimitry Andric #include "clang/AST/NonTrivialTypeVisitor.h" 17*0b57cec5SDimitry Andric #include "clang/CodeGen/CodeGenABITypes.h" 18*0b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h" 19*0b57cec5SDimitry Andric #include <array> 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andric using namespace clang; 22*0b57cec5SDimitry Andric using namespace CodeGen; 23*0b57cec5SDimitry Andric 24*0b57cec5SDimitry Andric // Return the size of a field in number of bits. 25*0b57cec5SDimitry Andric static uint64_t getFieldSize(const FieldDecl *FD, QualType FT, 26*0b57cec5SDimitry Andric ASTContext &Ctx) { 27*0b57cec5SDimitry Andric if (FD && FD->isBitField()) 28*0b57cec5SDimitry Andric return FD->getBitWidthValue(Ctx); 29*0b57cec5SDimitry Andric return Ctx.getTypeSize(FT); 30*0b57cec5SDimitry Andric } 31*0b57cec5SDimitry Andric 32*0b57cec5SDimitry Andric namespace { 33*0b57cec5SDimitry Andric enum { DstIdx = 0, SrcIdx = 1 }; 34*0b57cec5SDimitry Andric const char *ValNameStr[2] = {"dst", "src"}; 35*0b57cec5SDimitry Andric 36*0b57cec5SDimitry Andric template <class Derived> struct StructVisitor { 37*0b57cec5SDimitry Andric StructVisitor(ASTContext &Ctx) : Ctx(Ctx) {} 38*0b57cec5SDimitry Andric 39*0b57cec5SDimitry Andric template <class... Ts> 40*0b57cec5SDimitry Andric void visitStructFields(QualType QT, CharUnits CurStructOffset, Ts... Args) { 41*0b57cec5SDimitry Andric const RecordDecl *RD = QT->castAs<RecordType>()->getDecl(); 42*0b57cec5SDimitry Andric 43*0b57cec5SDimitry Andric // Iterate over the fields of the struct. 44*0b57cec5SDimitry Andric for (const FieldDecl *FD : RD->fields()) { 45*0b57cec5SDimitry Andric QualType FT = FD->getType(); 46*0b57cec5SDimitry Andric FT = QT.isVolatileQualified() ? FT.withVolatile() : FT; 47*0b57cec5SDimitry Andric asDerived().visit(FT, FD, CurStructOffset, Args...); 48*0b57cec5SDimitry Andric } 49*0b57cec5SDimitry Andric 50*0b57cec5SDimitry Andric asDerived().flushTrivialFields(Args...); 51*0b57cec5SDimitry Andric } 52*0b57cec5SDimitry Andric 53*0b57cec5SDimitry Andric template <class... Ts> void visitTrivial(Ts... Args) {} 54*0b57cec5SDimitry Andric 55*0b57cec5SDimitry Andric template <class... Ts> void visitCXXDestructor(Ts... Args) { 56*0b57cec5SDimitry Andric llvm_unreachable("field of a C++ struct type is not expected"); 57*0b57cec5SDimitry Andric } 58*0b57cec5SDimitry Andric 59*0b57cec5SDimitry Andric template <class... Ts> void flushTrivialFields(Ts... Args) {} 60*0b57cec5SDimitry Andric 61*0b57cec5SDimitry Andric uint64_t getFieldOffsetInBits(const FieldDecl *FD) { 62*0b57cec5SDimitry Andric return FD ? Ctx.getASTRecordLayout(FD->getParent()) 63*0b57cec5SDimitry Andric .getFieldOffset(FD->getFieldIndex()) 64*0b57cec5SDimitry Andric : 0; 65*0b57cec5SDimitry Andric } 66*0b57cec5SDimitry Andric 67*0b57cec5SDimitry Andric CharUnits getFieldOffset(const FieldDecl *FD) { 68*0b57cec5SDimitry Andric return Ctx.toCharUnitsFromBits(getFieldOffsetInBits(FD)); 69*0b57cec5SDimitry Andric } 70*0b57cec5SDimitry Andric 71*0b57cec5SDimitry Andric Derived &asDerived() { return static_cast<Derived &>(*this); } 72*0b57cec5SDimitry Andric 73*0b57cec5SDimitry Andric ASTContext &getContext() { return Ctx; } 74*0b57cec5SDimitry Andric ASTContext &Ctx; 75*0b57cec5SDimitry Andric }; 76*0b57cec5SDimitry Andric 77*0b57cec5SDimitry Andric template <class Derived, bool IsMove> 78*0b57cec5SDimitry Andric struct CopyStructVisitor : StructVisitor<Derived>, 79*0b57cec5SDimitry Andric CopiedTypeVisitor<Derived, IsMove> { 80*0b57cec5SDimitry Andric using StructVisitor<Derived>::asDerived; 81*0b57cec5SDimitry Andric using Super = CopiedTypeVisitor<Derived, IsMove>; 82*0b57cec5SDimitry Andric 83*0b57cec5SDimitry Andric CopyStructVisitor(ASTContext &Ctx) : StructVisitor<Derived>(Ctx) {} 84*0b57cec5SDimitry Andric 85*0b57cec5SDimitry Andric template <class... Ts> 86*0b57cec5SDimitry Andric void preVisit(QualType::PrimitiveCopyKind PCK, QualType FT, 87*0b57cec5SDimitry Andric const FieldDecl *FD, CharUnits CurStructOffset, Ts &&... Args) { 88*0b57cec5SDimitry Andric if (PCK) 89*0b57cec5SDimitry Andric asDerived().flushTrivialFields(std::forward<Ts>(Args)...); 90*0b57cec5SDimitry Andric } 91*0b57cec5SDimitry Andric 92*0b57cec5SDimitry Andric template <class... Ts> 93*0b57cec5SDimitry Andric void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT, 94*0b57cec5SDimitry Andric const FieldDecl *FD, CharUnits CurStructOffset, 95*0b57cec5SDimitry Andric Ts &&... Args) { 96*0b57cec5SDimitry Andric if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) { 97*0b57cec5SDimitry Andric asDerived().visitArray(PCK, AT, FT.isVolatileQualified(), FD, 98*0b57cec5SDimitry Andric CurStructOffset, std::forward<Ts>(Args)...); 99*0b57cec5SDimitry Andric return; 100*0b57cec5SDimitry Andric } 101*0b57cec5SDimitry Andric 102*0b57cec5SDimitry Andric Super::visitWithKind(PCK, FT, FD, CurStructOffset, 103*0b57cec5SDimitry Andric std::forward<Ts>(Args)...); 104*0b57cec5SDimitry Andric } 105*0b57cec5SDimitry Andric 106*0b57cec5SDimitry Andric template <class... Ts> 107*0b57cec5SDimitry Andric void visitTrivial(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset, 108*0b57cec5SDimitry Andric Ts... Args) { 109*0b57cec5SDimitry Andric assert(!FT.isVolatileQualified() && "volatile field not expected"); 110*0b57cec5SDimitry Andric ASTContext &Ctx = asDerived().getContext(); 111*0b57cec5SDimitry Andric uint64_t FieldSize = getFieldSize(FD, FT, Ctx); 112*0b57cec5SDimitry Andric 113*0b57cec5SDimitry Andric // Ignore zero-sized fields. 114*0b57cec5SDimitry Andric if (FieldSize == 0) 115*0b57cec5SDimitry Andric return; 116*0b57cec5SDimitry Andric 117*0b57cec5SDimitry Andric uint64_t FStartInBits = asDerived().getFieldOffsetInBits(FD); 118*0b57cec5SDimitry Andric uint64_t FEndInBits = FStartInBits + FieldSize; 119*0b57cec5SDimitry Andric uint64_t RoundedFEnd = llvm::alignTo(FEndInBits, Ctx.getCharWidth()); 120*0b57cec5SDimitry Andric 121*0b57cec5SDimitry Andric // Set Start if this is the first field of a sequence of trivial fields. 122*0b57cec5SDimitry Andric if (Start == End) 123*0b57cec5SDimitry Andric Start = CurStructOffset + Ctx.toCharUnitsFromBits(FStartInBits); 124*0b57cec5SDimitry Andric End = CurStructOffset + Ctx.toCharUnitsFromBits(RoundedFEnd); 125*0b57cec5SDimitry Andric } 126*0b57cec5SDimitry Andric 127*0b57cec5SDimitry Andric CharUnits Start = CharUnits::Zero(), End = CharUnits::Zero(); 128*0b57cec5SDimitry Andric }; 129*0b57cec5SDimitry Andric 130*0b57cec5SDimitry Andric // This function creates the mangled name of a special function of a non-trivial 131*0b57cec5SDimitry Andric // C struct. Since there is no ODR in C, the function is mangled based on the 132*0b57cec5SDimitry Andric // struct contents and not the name. The mangled name has the following 133*0b57cec5SDimitry Andric // structure: 134*0b57cec5SDimitry Andric // 135*0b57cec5SDimitry Andric // <function-name> ::= <prefix> <alignment-info> "_" <struct-field-info> 136*0b57cec5SDimitry Andric // <prefix> ::= "__destructor_" | "__default_constructor_" | 137*0b57cec5SDimitry Andric // "__copy_constructor_" | "__move_constructor_" | 138*0b57cec5SDimitry Andric // "__copy_assignment_" | "__move_assignment_" 139*0b57cec5SDimitry Andric // <alignment-info> ::= <dst-alignment> ["_" <src-alignment>] 140*0b57cec5SDimitry Andric // <struct-field-info> ::= <field-info>+ 141*0b57cec5SDimitry Andric // <field-info> ::= <struct-or-scalar-field-info> | <array-field-info> 142*0b57cec5SDimitry Andric // <struct-or-scalar-field-info> ::= "_S" <struct-field-info> | 143*0b57cec5SDimitry Andric // <strong-field-info> | <trivial-field-info> 144*0b57cec5SDimitry Andric // <array-field-info> ::= "_AB" <array-offset> "s" <element-size> "n" 145*0b57cec5SDimitry Andric // <num-elements> <innermost-element-info> "_AE" 146*0b57cec5SDimitry Andric // <innermost-element-info> ::= <struct-or-scalar-field-info> 147*0b57cec5SDimitry Andric // <strong-field-info> ::= "_s" ["b"] ["v"] <field-offset> 148*0b57cec5SDimitry Andric // <trivial-field-info> ::= "_t" ["v"] <field-offset> "_" <field-size> 149*0b57cec5SDimitry Andric 150*0b57cec5SDimitry Andric template <class Derived> struct GenFuncNameBase { 151*0b57cec5SDimitry Andric std::string getVolatileOffsetStr(bool IsVolatile, CharUnits Offset) { 152*0b57cec5SDimitry Andric std::string S; 153*0b57cec5SDimitry Andric if (IsVolatile) 154*0b57cec5SDimitry Andric S = "v"; 155*0b57cec5SDimitry Andric S += llvm::to_string(Offset.getQuantity()); 156*0b57cec5SDimitry Andric return S; 157*0b57cec5SDimitry Andric } 158*0b57cec5SDimitry Andric 159*0b57cec5SDimitry Andric void visitARCStrong(QualType FT, const FieldDecl *FD, 160*0b57cec5SDimitry Andric CharUnits CurStructOffset) { 161*0b57cec5SDimitry Andric appendStr("_s"); 162*0b57cec5SDimitry Andric if (FT->isBlockPointerType()) 163*0b57cec5SDimitry Andric appendStr("b"); 164*0b57cec5SDimitry Andric CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD); 165*0b57cec5SDimitry Andric appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset)); 166*0b57cec5SDimitry Andric } 167*0b57cec5SDimitry Andric 168*0b57cec5SDimitry Andric void visitARCWeak(QualType FT, const FieldDecl *FD, 169*0b57cec5SDimitry Andric CharUnits CurStructOffset) { 170*0b57cec5SDimitry Andric appendStr("_w"); 171*0b57cec5SDimitry Andric CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD); 172*0b57cec5SDimitry Andric appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset)); 173*0b57cec5SDimitry Andric } 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric void visitStruct(QualType QT, const FieldDecl *FD, 176*0b57cec5SDimitry Andric CharUnits CurStructOffset) { 177*0b57cec5SDimitry Andric CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD); 178*0b57cec5SDimitry Andric appendStr("_S"); 179*0b57cec5SDimitry Andric asDerived().visitStructFields(QT, FieldOffset); 180*0b57cec5SDimitry Andric } 181*0b57cec5SDimitry Andric 182*0b57cec5SDimitry Andric template <class FieldKind> 183*0b57cec5SDimitry Andric void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile, 184*0b57cec5SDimitry Andric const FieldDecl *FD, CharUnits CurStructOffset) { 185*0b57cec5SDimitry Andric // String for non-volatile trivial fields is emitted when 186*0b57cec5SDimitry Andric // flushTrivialFields is called. 187*0b57cec5SDimitry Andric if (!FK) 188*0b57cec5SDimitry Andric return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset); 189*0b57cec5SDimitry Andric 190*0b57cec5SDimitry Andric asDerived().flushTrivialFields(); 191*0b57cec5SDimitry Andric CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD); 192*0b57cec5SDimitry Andric ASTContext &Ctx = asDerived().getContext(); 193*0b57cec5SDimitry Andric const ConstantArrayType *CAT = cast<ConstantArrayType>(AT); 194*0b57cec5SDimitry Andric unsigned NumElts = Ctx.getConstantArrayElementCount(CAT); 195*0b57cec5SDimitry Andric QualType EltTy = Ctx.getBaseElementType(CAT); 196*0b57cec5SDimitry Andric CharUnits EltSize = Ctx.getTypeSizeInChars(EltTy); 197*0b57cec5SDimitry Andric appendStr("_AB" + llvm::to_string(FieldOffset.getQuantity()) + "s" + 198*0b57cec5SDimitry Andric llvm::to_string(EltSize.getQuantity()) + "n" + 199*0b57cec5SDimitry Andric llvm::to_string(NumElts)); 200*0b57cec5SDimitry Andric EltTy = IsVolatile ? EltTy.withVolatile() : EltTy; 201*0b57cec5SDimitry Andric asDerived().visitWithKind(FK, EltTy, nullptr, FieldOffset); 202*0b57cec5SDimitry Andric appendStr("_AE"); 203*0b57cec5SDimitry Andric } 204*0b57cec5SDimitry Andric 205*0b57cec5SDimitry Andric void appendStr(StringRef Str) { Name += Str; } 206*0b57cec5SDimitry Andric 207*0b57cec5SDimitry Andric std::string getName(QualType QT, bool IsVolatile) { 208*0b57cec5SDimitry Andric QT = IsVolatile ? QT.withVolatile() : QT; 209*0b57cec5SDimitry Andric asDerived().visitStructFields(QT, CharUnits::Zero()); 210*0b57cec5SDimitry Andric return Name; 211*0b57cec5SDimitry Andric } 212*0b57cec5SDimitry Andric 213*0b57cec5SDimitry Andric Derived &asDerived() { return static_cast<Derived &>(*this); } 214*0b57cec5SDimitry Andric 215*0b57cec5SDimitry Andric std::string Name; 216*0b57cec5SDimitry Andric }; 217*0b57cec5SDimitry Andric 218*0b57cec5SDimitry Andric template <class Derived> 219*0b57cec5SDimitry Andric struct GenUnaryFuncName : StructVisitor<Derived>, GenFuncNameBase<Derived> { 220*0b57cec5SDimitry Andric GenUnaryFuncName(StringRef Prefix, CharUnits DstAlignment, ASTContext &Ctx) 221*0b57cec5SDimitry Andric : StructVisitor<Derived>(Ctx) { 222*0b57cec5SDimitry Andric this->appendStr(Prefix); 223*0b57cec5SDimitry Andric this->appendStr(llvm::to_string(DstAlignment.getQuantity())); 224*0b57cec5SDimitry Andric } 225*0b57cec5SDimitry Andric }; 226*0b57cec5SDimitry Andric 227*0b57cec5SDimitry Andric // Helper function to create a null constant. 228*0b57cec5SDimitry Andric static llvm::Constant *getNullForVariable(Address Addr) { 229*0b57cec5SDimitry Andric llvm::Type *Ty = Addr.getElementType(); 230*0b57cec5SDimitry Andric return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(Ty)); 231*0b57cec5SDimitry Andric } 232*0b57cec5SDimitry Andric 233*0b57cec5SDimitry Andric template <bool IsMove> 234*0b57cec5SDimitry Andric struct GenBinaryFuncName : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>, 235*0b57cec5SDimitry Andric GenFuncNameBase<GenBinaryFuncName<IsMove>> { 236*0b57cec5SDimitry Andric 237*0b57cec5SDimitry Andric GenBinaryFuncName(StringRef Prefix, CharUnits DstAlignment, 238*0b57cec5SDimitry Andric CharUnits SrcAlignment, ASTContext &Ctx) 239*0b57cec5SDimitry Andric : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>(Ctx) { 240*0b57cec5SDimitry Andric this->appendStr(Prefix); 241*0b57cec5SDimitry Andric this->appendStr(llvm::to_string(DstAlignment.getQuantity())); 242*0b57cec5SDimitry Andric this->appendStr("_" + llvm::to_string(SrcAlignment.getQuantity())); 243*0b57cec5SDimitry Andric } 244*0b57cec5SDimitry Andric 245*0b57cec5SDimitry Andric void flushTrivialFields() { 246*0b57cec5SDimitry Andric if (this->Start == this->End) 247*0b57cec5SDimitry Andric return; 248*0b57cec5SDimitry Andric 249*0b57cec5SDimitry Andric this->appendStr("_t" + llvm::to_string(this->Start.getQuantity()) + "w" + 250*0b57cec5SDimitry Andric llvm::to_string((this->End - this->Start).getQuantity())); 251*0b57cec5SDimitry Andric 252*0b57cec5SDimitry Andric this->Start = this->End = CharUnits::Zero(); 253*0b57cec5SDimitry Andric } 254*0b57cec5SDimitry Andric 255*0b57cec5SDimitry Andric void visitVolatileTrivial(QualType FT, const FieldDecl *FD, 256*0b57cec5SDimitry Andric CharUnits CurStructOffset) { 257*0b57cec5SDimitry Andric // Because volatile fields can be bit-fields and are individually copied, 258*0b57cec5SDimitry Andric // their offset and width are in bits. 259*0b57cec5SDimitry Andric uint64_t OffsetInBits = 260*0b57cec5SDimitry Andric this->Ctx.toBits(CurStructOffset) + this->getFieldOffsetInBits(FD); 261*0b57cec5SDimitry Andric this->appendStr("_tv" + llvm::to_string(OffsetInBits) + "w" + 262*0b57cec5SDimitry Andric llvm::to_string(getFieldSize(FD, FT, this->Ctx))); 263*0b57cec5SDimitry Andric } 264*0b57cec5SDimitry Andric }; 265*0b57cec5SDimitry Andric 266*0b57cec5SDimitry Andric struct GenDefaultInitializeFuncName 267*0b57cec5SDimitry Andric : GenUnaryFuncName<GenDefaultInitializeFuncName>, 268*0b57cec5SDimitry Andric DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName> { 269*0b57cec5SDimitry Andric using Super = DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName>; 270*0b57cec5SDimitry Andric GenDefaultInitializeFuncName(CharUnits DstAlignment, ASTContext &Ctx) 271*0b57cec5SDimitry Andric : GenUnaryFuncName<GenDefaultInitializeFuncName>("__default_constructor_", 272*0b57cec5SDimitry Andric DstAlignment, Ctx) {} 273*0b57cec5SDimitry Andric void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT, 274*0b57cec5SDimitry Andric const FieldDecl *FD, CharUnits CurStructOffset) { 275*0b57cec5SDimitry Andric if (const auto *AT = getContext().getAsArrayType(FT)) { 276*0b57cec5SDimitry Andric visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset); 277*0b57cec5SDimitry Andric return; 278*0b57cec5SDimitry Andric } 279*0b57cec5SDimitry Andric 280*0b57cec5SDimitry Andric Super::visitWithKind(PDIK, FT, FD, CurStructOffset); 281*0b57cec5SDimitry Andric } 282*0b57cec5SDimitry Andric }; 283*0b57cec5SDimitry Andric 284*0b57cec5SDimitry Andric struct GenDestructorFuncName : GenUnaryFuncName<GenDestructorFuncName>, 285*0b57cec5SDimitry Andric DestructedTypeVisitor<GenDestructorFuncName> { 286*0b57cec5SDimitry Andric using Super = DestructedTypeVisitor<GenDestructorFuncName>; 287*0b57cec5SDimitry Andric GenDestructorFuncName(const char *Prefix, CharUnits DstAlignment, 288*0b57cec5SDimitry Andric ASTContext &Ctx) 289*0b57cec5SDimitry Andric : GenUnaryFuncName<GenDestructorFuncName>(Prefix, DstAlignment, Ctx) {} 290*0b57cec5SDimitry Andric void visitWithKind(QualType::DestructionKind DK, QualType FT, 291*0b57cec5SDimitry Andric const FieldDecl *FD, CharUnits CurStructOffset) { 292*0b57cec5SDimitry Andric if (const auto *AT = getContext().getAsArrayType(FT)) { 293*0b57cec5SDimitry Andric visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset); 294*0b57cec5SDimitry Andric return; 295*0b57cec5SDimitry Andric } 296*0b57cec5SDimitry Andric 297*0b57cec5SDimitry Andric Super::visitWithKind(DK, FT, FD, CurStructOffset); 298*0b57cec5SDimitry Andric } 299*0b57cec5SDimitry Andric }; 300*0b57cec5SDimitry Andric 301*0b57cec5SDimitry Andric // Helper function that creates CGFunctionInfo for an N-ary special function. 302*0b57cec5SDimitry Andric template <size_t N> 303*0b57cec5SDimitry Andric static const CGFunctionInfo &getFunctionInfo(CodeGenModule &CGM, 304*0b57cec5SDimitry Andric FunctionArgList &Args) { 305*0b57cec5SDimitry Andric ASTContext &Ctx = CGM.getContext(); 306*0b57cec5SDimitry Andric llvm::SmallVector<ImplicitParamDecl *, N> Params; 307*0b57cec5SDimitry Andric QualType ParamTy = Ctx.getPointerType(Ctx.VoidPtrTy); 308*0b57cec5SDimitry Andric 309*0b57cec5SDimitry Andric for (unsigned I = 0; I < N; ++I) 310*0b57cec5SDimitry Andric Params.push_back(ImplicitParamDecl::Create( 311*0b57cec5SDimitry Andric Ctx, nullptr, SourceLocation(), &Ctx.Idents.get(ValNameStr[I]), ParamTy, 312*0b57cec5SDimitry Andric ImplicitParamDecl::Other)); 313*0b57cec5SDimitry Andric 314*0b57cec5SDimitry Andric for (auto &P : Params) 315*0b57cec5SDimitry Andric Args.push_back(P); 316*0b57cec5SDimitry Andric 317*0b57cec5SDimitry Andric return CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args); 318*0b57cec5SDimitry Andric } 319*0b57cec5SDimitry Andric 320*0b57cec5SDimitry Andric // Template classes that are used as bases for classes that emit special 321*0b57cec5SDimitry Andric // functions. 322*0b57cec5SDimitry Andric template <class Derived> struct GenFuncBase { 323*0b57cec5SDimitry Andric template <size_t N> 324*0b57cec5SDimitry Andric void visitStruct(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset, 325*0b57cec5SDimitry Andric std::array<Address, N> Addrs) { 326*0b57cec5SDimitry Andric this->asDerived().callSpecialFunction( 327*0b57cec5SDimitry Andric FT, CurStructOffset + asDerived().getFieldOffset(FD), Addrs); 328*0b57cec5SDimitry Andric } 329*0b57cec5SDimitry Andric 330*0b57cec5SDimitry Andric template <class FieldKind, size_t N> 331*0b57cec5SDimitry Andric void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile, 332*0b57cec5SDimitry Andric const FieldDecl *FD, CharUnits CurStructOffset, 333*0b57cec5SDimitry Andric std::array<Address, N> Addrs) { 334*0b57cec5SDimitry Andric // Non-volatile trivial fields are copied when flushTrivialFields is called. 335*0b57cec5SDimitry Andric if (!FK) 336*0b57cec5SDimitry Andric return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset, 337*0b57cec5SDimitry Andric Addrs); 338*0b57cec5SDimitry Andric 339*0b57cec5SDimitry Andric asDerived().flushTrivialFields(Addrs); 340*0b57cec5SDimitry Andric CodeGenFunction &CGF = *this->CGF; 341*0b57cec5SDimitry Andric ASTContext &Ctx = CGF.getContext(); 342*0b57cec5SDimitry Andric 343*0b57cec5SDimitry Andric // Compute the end address. 344*0b57cec5SDimitry Andric QualType BaseEltQT; 345*0b57cec5SDimitry Andric std::array<Address, N> StartAddrs = Addrs; 346*0b57cec5SDimitry Andric for (unsigned I = 0; I < N; ++I) 347*0b57cec5SDimitry Andric StartAddrs[I] = getAddrWithOffset(Addrs[I], CurStructOffset, FD); 348*0b57cec5SDimitry Andric Address DstAddr = StartAddrs[DstIdx]; 349*0b57cec5SDimitry Andric llvm::Value *NumElts = CGF.emitArrayLength(AT, BaseEltQT, DstAddr); 350*0b57cec5SDimitry Andric unsigned BaseEltSize = Ctx.getTypeSizeInChars(BaseEltQT).getQuantity(); 351*0b57cec5SDimitry Andric llvm::Value *BaseEltSizeVal = 352*0b57cec5SDimitry Andric llvm::ConstantInt::get(NumElts->getType(), BaseEltSize); 353*0b57cec5SDimitry Andric llvm::Value *SizeInBytes = 354*0b57cec5SDimitry Andric CGF.Builder.CreateNUWMul(BaseEltSizeVal, NumElts); 355*0b57cec5SDimitry Andric Address BC = CGF.Builder.CreateBitCast(DstAddr, CGF.CGM.Int8PtrTy); 356*0b57cec5SDimitry Andric llvm::Value *DstArrayEnd = 357*0b57cec5SDimitry Andric CGF.Builder.CreateInBoundsGEP(BC.getPointer(), SizeInBytes); 358*0b57cec5SDimitry Andric DstArrayEnd = CGF.Builder.CreateBitCast(DstArrayEnd, CGF.CGM.Int8PtrPtrTy, 359*0b57cec5SDimitry Andric "dstarray.end"); 360*0b57cec5SDimitry Andric llvm::BasicBlock *PreheaderBB = CGF.Builder.GetInsertBlock(); 361*0b57cec5SDimitry Andric 362*0b57cec5SDimitry Andric // Create the header block and insert the phi instructions. 363*0b57cec5SDimitry Andric llvm::BasicBlock *HeaderBB = CGF.createBasicBlock("loop.header"); 364*0b57cec5SDimitry Andric CGF.EmitBlock(HeaderBB); 365*0b57cec5SDimitry Andric llvm::PHINode *PHIs[N]; 366*0b57cec5SDimitry Andric 367*0b57cec5SDimitry Andric for (unsigned I = 0; I < N; ++I) { 368*0b57cec5SDimitry Andric PHIs[I] = CGF.Builder.CreatePHI(CGF.CGM.Int8PtrPtrTy, 2, "addr.cur"); 369*0b57cec5SDimitry Andric PHIs[I]->addIncoming(StartAddrs[I].getPointer(), PreheaderBB); 370*0b57cec5SDimitry Andric } 371*0b57cec5SDimitry Andric 372*0b57cec5SDimitry Andric // Create the exit and loop body blocks. 373*0b57cec5SDimitry Andric llvm::BasicBlock *ExitBB = CGF.createBasicBlock("loop.exit"); 374*0b57cec5SDimitry Andric llvm::BasicBlock *LoopBB = CGF.createBasicBlock("loop.body"); 375*0b57cec5SDimitry Andric 376*0b57cec5SDimitry Andric // Emit the comparison and conditional branch instruction that jumps to 377*0b57cec5SDimitry Andric // either the exit or the loop body. 378*0b57cec5SDimitry Andric llvm::Value *Done = 379*0b57cec5SDimitry Andric CGF.Builder.CreateICmpEQ(PHIs[DstIdx], DstArrayEnd, "done"); 380*0b57cec5SDimitry Andric CGF.Builder.CreateCondBr(Done, ExitBB, LoopBB); 381*0b57cec5SDimitry Andric 382*0b57cec5SDimitry Andric // Visit the element of the array in the loop body. 383*0b57cec5SDimitry Andric CGF.EmitBlock(LoopBB); 384*0b57cec5SDimitry Andric QualType EltQT = AT->getElementType(); 385*0b57cec5SDimitry Andric CharUnits EltSize = Ctx.getTypeSizeInChars(EltQT); 386*0b57cec5SDimitry Andric std::array<Address, N> NewAddrs = Addrs; 387*0b57cec5SDimitry Andric 388*0b57cec5SDimitry Andric for (unsigned I = 0; I < N; ++I) 389*0b57cec5SDimitry Andric NewAddrs[I] = Address( 390*0b57cec5SDimitry Andric PHIs[I], StartAddrs[I].getAlignment().alignmentAtOffset(EltSize)); 391*0b57cec5SDimitry Andric 392*0b57cec5SDimitry Andric EltQT = IsVolatile ? EltQT.withVolatile() : EltQT; 393*0b57cec5SDimitry Andric this->asDerived().visitWithKind(FK, EltQT, nullptr, CharUnits::Zero(), 394*0b57cec5SDimitry Andric NewAddrs); 395*0b57cec5SDimitry Andric 396*0b57cec5SDimitry Andric LoopBB = CGF.Builder.GetInsertBlock(); 397*0b57cec5SDimitry Andric 398*0b57cec5SDimitry Andric for (unsigned I = 0; I < N; ++I) { 399*0b57cec5SDimitry Andric // Instrs to update the destination and source addresses. 400*0b57cec5SDimitry Andric // Update phi instructions. 401*0b57cec5SDimitry Andric NewAddrs[I] = getAddrWithOffset(NewAddrs[I], EltSize); 402*0b57cec5SDimitry Andric PHIs[I]->addIncoming(NewAddrs[I].getPointer(), LoopBB); 403*0b57cec5SDimitry Andric } 404*0b57cec5SDimitry Andric 405*0b57cec5SDimitry Andric // Insert an unconditional branch to the header block. 406*0b57cec5SDimitry Andric CGF.Builder.CreateBr(HeaderBB); 407*0b57cec5SDimitry Andric CGF.EmitBlock(ExitBB); 408*0b57cec5SDimitry Andric } 409*0b57cec5SDimitry Andric 410*0b57cec5SDimitry Andric /// Return an address with the specified offset from the passed address. 411*0b57cec5SDimitry Andric Address getAddrWithOffset(Address Addr, CharUnits Offset) { 412*0b57cec5SDimitry Andric assert(Addr.isValid() && "invalid address"); 413*0b57cec5SDimitry Andric if (Offset.getQuantity() == 0) 414*0b57cec5SDimitry Andric return Addr; 415*0b57cec5SDimitry Andric Addr = CGF->Builder.CreateBitCast(Addr, CGF->CGM.Int8PtrTy); 416*0b57cec5SDimitry Andric Addr = CGF->Builder.CreateConstInBoundsGEP(Addr, Offset.getQuantity()); 417*0b57cec5SDimitry Andric return CGF->Builder.CreateBitCast(Addr, CGF->CGM.Int8PtrPtrTy); 418*0b57cec5SDimitry Andric } 419*0b57cec5SDimitry Andric 420*0b57cec5SDimitry Andric Address getAddrWithOffset(Address Addr, CharUnits StructFieldOffset, 421*0b57cec5SDimitry Andric const FieldDecl *FD) { 422*0b57cec5SDimitry Andric return getAddrWithOffset(Addr, StructFieldOffset + 423*0b57cec5SDimitry Andric asDerived().getFieldOffset(FD)); 424*0b57cec5SDimitry Andric } 425*0b57cec5SDimitry Andric 426*0b57cec5SDimitry Andric template <size_t N> 427*0b57cec5SDimitry Andric llvm::Function * 428*0b57cec5SDimitry Andric getFunction(StringRef FuncName, QualType QT, std::array<Address, N> Addrs, 429*0b57cec5SDimitry Andric std::array<CharUnits, N> Alignments, CodeGenModule &CGM) { 430*0b57cec5SDimitry Andric // If the special function already exists in the module, return it. 431*0b57cec5SDimitry Andric if (llvm::Function *F = CGM.getModule().getFunction(FuncName)) { 432*0b57cec5SDimitry Andric bool WrongType = false; 433*0b57cec5SDimitry Andric if (!F->getReturnType()->isVoidTy()) 434*0b57cec5SDimitry Andric WrongType = true; 435*0b57cec5SDimitry Andric else { 436*0b57cec5SDimitry Andric for (const llvm::Argument &Arg : F->args()) 437*0b57cec5SDimitry Andric if (Arg.getType() != CGM.Int8PtrPtrTy) 438*0b57cec5SDimitry Andric WrongType = true; 439*0b57cec5SDimitry Andric } 440*0b57cec5SDimitry Andric 441*0b57cec5SDimitry Andric if (WrongType) { 442*0b57cec5SDimitry Andric std::string FuncName = F->getName(); 443*0b57cec5SDimitry Andric SourceLocation Loc = QT->castAs<RecordType>()->getDecl()->getLocation(); 444*0b57cec5SDimitry Andric CGM.Error(Loc, "special function " + FuncName + 445*0b57cec5SDimitry Andric " for non-trivial C struct has incorrect type"); 446*0b57cec5SDimitry Andric return nullptr; 447*0b57cec5SDimitry Andric } 448*0b57cec5SDimitry Andric return F; 449*0b57cec5SDimitry Andric } 450*0b57cec5SDimitry Andric 451*0b57cec5SDimitry Andric ASTContext &Ctx = CGM.getContext(); 452*0b57cec5SDimitry Andric FunctionArgList Args; 453*0b57cec5SDimitry Andric const CGFunctionInfo &FI = getFunctionInfo<N>(CGM, Args); 454*0b57cec5SDimitry Andric llvm::FunctionType *FuncTy = CGM.getTypes().GetFunctionType(FI); 455*0b57cec5SDimitry Andric llvm::Function *F = 456*0b57cec5SDimitry Andric llvm::Function::Create(FuncTy, llvm::GlobalValue::LinkOnceODRLinkage, 457*0b57cec5SDimitry Andric FuncName, &CGM.getModule()); 458*0b57cec5SDimitry Andric F->setVisibility(llvm::GlobalValue::HiddenVisibility); 459*0b57cec5SDimitry Andric CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F); 460*0b57cec5SDimitry Andric CGM.SetLLVMFunctionAttributesForDefinition(nullptr, F); 461*0b57cec5SDimitry Andric IdentifierInfo *II = &Ctx.Idents.get(FuncName); 462*0b57cec5SDimitry Andric FunctionDecl *FD = FunctionDecl::Create( 463*0b57cec5SDimitry Andric Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), 464*0b57cec5SDimitry Andric II, Ctx.getFunctionType(Ctx.VoidTy, llvm::None, {}), nullptr, 465*0b57cec5SDimitry Andric SC_PrivateExtern, false, false); 466*0b57cec5SDimitry Andric CodeGenFunction NewCGF(CGM); 467*0b57cec5SDimitry Andric setCGF(&NewCGF); 468*0b57cec5SDimitry Andric CGF->StartFunction(FD, Ctx.VoidTy, F, FI, Args); 469*0b57cec5SDimitry Andric 470*0b57cec5SDimitry Andric for (unsigned I = 0; I < N; ++I) { 471*0b57cec5SDimitry Andric llvm::Value *V = CGF->Builder.CreateLoad(CGF->GetAddrOfLocalVar(Args[I])); 472*0b57cec5SDimitry Andric Addrs[I] = Address(V, Alignments[I]); 473*0b57cec5SDimitry Andric } 474*0b57cec5SDimitry Andric 475*0b57cec5SDimitry Andric asDerived().visitStructFields(QT, CharUnits::Zero(), Addrs); 476*0b57cec5SDimitry Andric CGF->FinishFunction(); 477*0b57cec5SDimitry Andric return F; 478*0b57cec5SDimitry Andric } 479*0b57cec5SDimitry Andric 480*0b57cec5SDimitry Andric template <size_t N> 481*0b57cec5SDimitry Andric void callFunc(StringRef FuncName, QualType QT, std::array<Address, N> Addrs, 482*0b57cec5SDimitry Andric CodeGenFunction &CallerCGF) { 483*0b57cec5SDimitry Andric std::array<CharUnits, N> Alignments; 484*0b57cec5SDimitry Andric llvm::Value *Ptrs[N]; 485*0b57cec5SDimitry Andric 486*0b57cec5SDimitry Andric for (unsigned I = 0; I < N; ++I) { 487*0b57cec5SDimitry Andric Alignments[I] = Addrs[I].getAlignment(); 488*0b57cec5SDimitry Andric Ptrs[I] = 489*0b57cec5SDimitry Andric CallerCGF.Builder.CreateBitCast(Addrs[I], CallerCGF.CGM.Int8PtrPtrTy) 490*0b57cec5SDimitry Andric .getPointer(); 491*0b57cec5SDimitry Andric } 492*0b57cec5SDimitry Andric 493*0b57cec5SDimitry Andric if (llvm::Function *F = 494*0b57cec5SDimitry Andric getFunction(FuncName, QT, Addrs, Alignments, CallerCGF.CGM)) 495*0b57cec5SDimitry Andric CallerCGF.EmitNounwindRuntimeCall(F, Ptrs); 496*0b57cec5SDimitry Andric } 497*0b57cec5SDimitry Andric 498*0b57cec5SDimitry Andric Derived &asDerived() { return static_cast<Derived &>(*this); } 499*0b57cec5SDimitry Andric 500*0b57cec5SDimitry Andric void setCGF(CodeGenFunction *F) { CGF = F; } 501*0b57cec5SDimitry Andric 502*0b57cec5SDimitry Andric CodeGenFunction *CGF = nullptr; 503*0b57cec5SDimitry Andric }; 504*0b57cec5SDimitry Andric 505*0b57cec5SDimitry Andric template <class Derived, bool IsMove> 506*0b57cec5SDimitry Andric struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>, 507*0b57cec5SDimitry Andric GenFuncBase<Derived> { 508*0b57cec5SDimitry Andric GenBinaryFunc(ASTContext &Ctx) : CopyStructVisitor<Derived, IsMove>(Ctx) {} 509*0b57cec5SDimitry Andric 510*0b57cec5SDimitry Andric void flushTrivialFields(std::array<Address, 2> Addrs) { 511*0b57cec5SDimitry Andric CharUnits Size = this->End - this->Start; 512*0b57cec5SDimitry Andric 513*0b57cec5SDimitry Andric if (Size.getQuantity() == 0) 514*0b57cec5SDimitry Andric return; 515*0b57cec5SDimitry Andric 516*0b57cec5SDimitry Andric Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], this->Start); 517*0b57cec5SDimitry Andric Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], this->Start); 518*0b57cec5SDimitry Andric 519*0b57cec5SDimitry Andric // Emit memcpy. 520*0b57cec5SDimitry Andric if (Size.getQuantity() >= 16 || !llvm::isPowerOf2_32(Size.getQuantity())) { 521*0b57cec5SDimitry Andric llvm::Value *SizeVal = 522*0b57cec5SDimitry Andric llvm::ConstantInt::get(this->CGF->SizeTy, Size.getQuantity()); 523*0b57cec5SDimitry Andric DstAddr = 524*0b57cec5SDimitry Andric this->CGF->Builder.CreateElementBitCast(DstAddr, this->CGF->Int8Ty); 525*0b57cec5SDimitry Andric SrcAddr = 526*0b57cec5SDimitry Andric this->CGF->Builder.CreateElementBitCast(SrcAddr, this->CGF->Int8Ty); 527*0b57cec5SDimitry Andric this->CGF->Builder.CreateMemCpy(DstAddr, SrcAddr, SizeVal, false); 528*0b57cec5SDimitry Andric } else { 529*0b57cec5SDimitry Andric llvm::Type *Ty = llvm::Type::getIntNTy( 530*0b57cec5SDimitry Andric this->CGF->getLLVMContext(), 531*0b57cec5SDimitry Andric Size.getQuantity() * this->CGF->getContext().getCharWidth()); 532*0b57cec5SDimitry Andric DstAddr = this->CGF->Builder.CreateElementBitCast(DstAddr, Ty); 533*0b57cec5SDimitry Andric SrcAddr = this->CGF->Builder.CreateElementBitCast(SrcAddr, Ty); 534*0b57cec5SDimitry Andric llvm::Value *SrcVal = this->CGF->Builder.CreateLoad(SrcAddr, false); 535*0b57cec5SDimitry Andric this->CGF->Builder.CreateStore(SrcVal, DstAddr, false); 536*0b57cec5SDimitry Andric } 537*0b57cec5SDimitry Andric 538*0b57cec5SDimitry Andric this->Start = this->End = CharUnits::Zero(); 539*0b57cec5SDimitry Andric } 540*0b57cec5SDimitry Andric 541*0b57cec5SDimitry Andric template <class... Ts> 542*0b57cec5SDimitry Andric void visitVolatileTrivial(QualType FT, const FieldDecl *FD, CharUnits Offset, 543*0b57cec5SDimitry Andric std::array<Address, 2> Addrs) { 544*0b57cec5SDimitry Andric LValue DstLV, SrcLV; 545*0b57cec5SDimitry Andric if (FD) { 546*0b57cec5SDimitry Andric QualType RT = QualType(FD->getParent()->getTypeForDecl(), 0); 547*0b57cec5SDimitry Andric llvm::PointerType *PtrTy = this->CGF->ConvertType(RT)->getPointerTo(); 548*0b57cec5SDimitry Andric Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset); 549*0b57cec5SDimitry Andric LValue DstBase = this->CGF->MakeAddrLValue( 550*0b57cec5SDimitry Andric this->CGF->Builder.CreateBitCast(DstAddr, PtrTy), FT); 551*0b57cec5SDimitry Andric DstLV = this->CGF->EmitLValueForField(DstBase, FD); 552*0b57cec5SDimitry Andric Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], Offset); 553*0b57cec5SDimitry Andric LValue SrcBase = this->CGF->MakeAddrLValue( 554*0b57cec5SDimitry Andric this->CGF->Builder.CreateBitCast(SrcAddr, PtrTy), FT); 555*0b57cec5SDimitry Andric SrcLV = this->CGF->EmitLValueForField(SrcBase, FD); 556*0b57cec5SDimitry Andric } else { 557*0b57cec5SDimitry Andric llvm::PointerType *Ty = this->CGF->ConvertType(FT)->getPointerTo(); 558*0b57cec5SDimitry Andric Address DstAddr = this->CGF->Builder.CreateBitCast(Addrs[DstIdx], Ty); 559*0b57cec5SDimitry Andric Address SrcAddr = this->CGF->Builder.CreateBitCast(Addrs[SrcIdx], Ty); 560*0b57cec5SDimitry Andric DstLV = this->CGF->MakeAddrLValue(DstAddr, FT); 561*0b57cec5SDimitry Andric SrcLV = this->CGF->MakeAddrLValue(SrcAddr, FT); 562*0b57cec5SDimitry Andric } 563*0b57cec5SDimitry Andric RValue SrcVal = this->CGF->EmitLoadOfLValue(SrcLV, SourceLocation()); 564*0b57cec5SDimitry Andric this->CGF->EmitStoreThroughLValue(SrcVal, DstLV); 565*0b57cec5SDimitry Andric } 566*0b57cec5SDimitry Andric }; 567*0b57cec5SDimitry Andric 568*0b57cec5SDimitry Andric // These classes that emit the special functions for a non-trivial struct. 569*0b57cec5SDimitry Andric struct GenDestructor : StructVisitor<GenDestructor>, 570*0b57cec5SDimitry Andric GenFuncBase<GenDestructor>, 571*0b57cec5SDimitry Andric DestructedTypeVisitor<GenDestructor> { 572*0b57cec5SDimitry Andric using Super = DestructedTypeVisitor<GenDestructor>; 573*0b57cec5SDimitry Andric GenDestructor(ASTContext &Ctx) : StructVisitor<GenDestructor>(Ctx) {} 574*0b57cec5SDimitry Andric 575*0b57cec5SDimitry Andric void visitWithKind(QualType::DestructionKind DK, QualType FT, 576*0b57cec5SDimitry Andric const FieldDecl *FD, CharUnits CurStructOffset, 577*0b57cec5SDimitry Andric std::array<Address, 1> Addrs) { 578*0b57cec5SDimitry Andric if (const auto *AT = getContext().getAsArrayType(FT)) { 579*0b57cec5SDimitry Andric visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset, Addrs); 580*0b57cec5SDimitry Andric return; 581*0b57cec5SDimitry Andric } 582*0b57cec5SDimitry Andric 583*0b57cec5SDimitry Andric Super::visitWithKind(DK, FT, FD, CurStructOffset, Addrs); 584*0b57cec5SDimitry Andric } 585*0b57cec5SDimitry Andric 586*0b57cec5SDimitry Andric void visitARCStrong(QualType QT, const FieldDecl *FD, 587*0b57cec5SDimitry Andric CharUnits CurStructOffset, std::array<Address, 1> Addrs) { 588*0b57cec5SDimitry Andric CGF->destroyARCStrongImprecise( 589*0b57cec5SDimitry Andric *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT); 590*0b57cec5SDimitry Andric } 591*0b57cec5SDimitry Andric 592*0b57cec5SDimitry Andric void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset, 593*0b57cec5SDimitry Andric std::array<Address, 1> Addrs) { 594*0b57cec5SDimitry Andric CGF->destroyARCWeak( 595*0b57cec5SDimitry Andric *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT); 596*0b57cec5SDimitry Andric } 597*0b57cec5SDimitry Andric 598*0b57cec5SDimitry Andric void callSpecialFunction(QualType FT, CharUnits Offset, 599*0b57cec5SDimitry Andric std::array<Address, 1> Addrs) { 600*0b57cec5SDimitry Andric CGF->callCStructDestructor( 601*0b57cec5SDimitry Andric CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT)); 602*0b57cec5SDimitry Andric } 603*0b57cec5SDimitry Andric }; 604*0b57cec5SDimitry Andric 605*0b57cec5SDimitry Andric struct GenDefaultInitialize 606*0b57cec5SDimitry Andric : StructVisitor<GenDefaultInitialize>, 607*0b57cec5SDimitry Andric GenFuncBase<GenDefaultInitialize>, 608*0b57cec5SDimitry Andric DefaultInitializedTypeVisitor<GenDefaultInitialize> { 609*0b57cec5SDimitry Andric using Super = DefaultInitializedTypeVisitor<GenDefaultInitialize>; 610*0b57cec5SDimitry Andric typedef GenFuncBase<GenDefaultInitialize> GenFuncBaseTy; 611*0b57cec5SDimitry Andric 612*0b57cec5SDimitry Andric GenDefaultInitialize(ASTContext &Ctx) 613*0b57cec5SDimitry Andric : StructVisitor<GenDefaultInitialize>(Ctx) {} 614*0b57cec5SDimitry Andric 615*0b57cec5SDimitry Andric void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT, 616*0b57cec5SDimitry Andric const FieldDecl *FD, CharUnits CurStructOffset, 617*0b57cec5SDimitry Andric std::array<Address, 1> Addrs) { 618*0b57cec5SDimitry Andric if (const auto *AT = getContext().getAsArrayType(FT)) { 619*0b57cec5SDimitry Andric visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset, 620*0b57cec5SDimitry Andric Addrs); 621*0b57cec5SDimitry Andric return; 622*0b57cec5SDimitry Andric } 623*0b57cec5SDimitry Andric 624*0b57cec5SDimitry Andric Super::visitWithKind(PDIK, FT, FD, CurStructOffset, Addrs); 625*0b57cec5SDimitry Andric } 626*0b57cec5SDimitry Andric 627*0b57cec5SDimitry Andric void visitARCStrong(QualType QT, const FieldDecl *FD, 628*0b57cec5SDimitry Andric CharUnits CurStructOffset, std::array<Address, 1> Addrs) { 629*0b57cec5SDimitry Andric CGF->EmitNullInitialization( 630*0b57cec5SDimitry Andric getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT); 631*0b57cec5SDimitry Andric } 632*0b57cec5SDimitry Andric 633*0b57cec5SDimitry Andric void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset, 634*0b57cec5SDimitry Andric std::array<Address, 1> Addrs) { 635*0b57cec5SDimitry Andric CGF->EmitNullInitialization( 636*0b57cec5SDimitry Andric getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT); 637*0b57cec5SDimitry Andric } 638*0b57cec5SDimitry Andric 639*0b57cec5SDimitry Andric template <class FieldKind, size_t... Is> 640*0b57cec5SDimitry Andric void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile, 641*0b57cec5SDimitry Andric const FieldDecl *FD, CharUnits CurStructOffset, 642*0b57cec5SDimitry Andric std::array<Address, 1> Addrs) { 643*0b57cec5SDimitry Andric if (!FK) 644*0b57cec5SDimitry Andric return visitTrivial(QualType(AT, 0), FD, CurStructOffset, Addrs); 645*0b57cec5SDimitry Andric 646*0b57cec5SDimitry Andric ASTContext &Ctx = getContext(); 647*0b57cec5SDimitry Andric CharUnits Size = Ctx.getTypeSizeInChars(QualType(AT, 0)); 648*0b57cec5SDimitry Andric QualType EltTy = Ctx.getBaseElementType(QualType(AT, 0)); 649*0b57cec5SDimitry Andric 650*0b57cec5SDimitry Andric if (Size < CharUnits::fromQuantity(16) || EltTy->getAs<RecordType>()) { 651*0b57cec5SDimitry Andric GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStructOffset, Addrs); 652*0b57cec5SDimitry Andric return; 653*0b57cec5SDimitry Andric } 654*0b57cec5SDimitry Andric 655*0b57cec5SDimitry Andric llvm::Constant *SizeVal = CGF->Builder.getInt64(Size.getQuantity()); 656*0b57cec5SDimitry Andric Address DstAddr = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD); 657*0b57cec5SDimitry Andric Address Loc = CGF->Builder.CreateElementBitCast(DstAddr, CGF->Int8Ty); 658*0b57cec5SDimitry Andric CGF->Builder.CreateMemSet(Loc, CGF->Builder.getInt8(0), SizeVal, 659*0b57cec5SDimitry Andric IsVolatile); 660*0b57cec5SDimitry Andric } 661*0b57cec5SDimitry Andric 662*0b57cec5SDimitry Andric void callSpecialFunction(QualType FT, CharUnits Offset, 663*0b57cec5SDimitry Andric std::array<Address, 1> Addrs) { 664*0b57cec5SDimitry Andric CGF->callCStructDefaultConstructor( 665*0b57cec5SDimitry Andric CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT)); 666*0b57cec5SDimitry Andric } 667*0b57cec5SDimitry Andric }; 668*0b57cec5SDimitry Andric 669*0b57cec5SDimitry Andric struct GenCopyConstructor : GenBinaryFunc<GenCopyConstructor, false> { 670*0b57cec5SDimitry Andric GenCopyConstructor(ASTContext &Ctx) 671*0b57cec5SDimitry Andric : GenBinaryFunc<GenCopyConstructor, false>(Ctx) {} 672*0b57cec5SDimitry Andric 673*0b57cec5SDimitry Andric void visitARCStrong(QualType QT, const FieldDecl *FD, 674*0b57cec5SDimitry Andric CharUnits CurStructOffset, std::array<Address, 2> Addrs) { 675*0b57cec5SDimitry Andric Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD); 676*0b57cec5SDimitry Andric Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD); 677*0b57cec5SDimitry Andric llvm::Value *SrcVal = CGF->EmitLoadOfScalar( 678*0b57cec5SDimitry Andric Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation()); 679*0b57cec5SDimitry Andric llvm::Value *Val = CGF->EmitARCRetain(QT, SrcVal); 680*0b57cec5SDimitry Andric CGF->EmitStoreOfScalar(Val, CGF->MakeAddrLValue(Addrs[DstIdx], QT), true); 681*0b57cec5SDimitry Andric } 682*0b57cec5SDimitry Andric 683*0b57cec5SDimitry Andric void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset, 684*0b57cec5SDimitry Andric std::array<Address, 2> Addrs) { 685*0b57cec5SDimitry Andric Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD); 686*0b57cec5SDimitry Andric Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD); 687*0b57cec5SDimitry Andric CGF->EmitARCCopyWeak(Addrs[DstIdx], Addrs[SrcIdx]); 688*0b57cec5SDimitry Andric } 689*0b57cec5SDimitry Andric 690*0b57cec5SDimitry Andric void callSpecialFunction(QualType FT, CharUnits Offset, 691*0b57cec5SDimitry Andric std::array<Address, 2> Addrs) { 692*0b57cec5SDimitry Andric Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset); 693*0b57cec5SDimitry Andric Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset); 694*0b57cec5SDimitry Andric CGF->callCStructCopyConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT), 695*0b57cec5SDimitry Andric CGF->MakeAddrLValue(Addrs[SrcIdx], FT)); 696*0b57cec5SDimitry Andric } 697*0b57cec5SDimitry Andric }; 698*0b57cec5SDimitry Andric 699*0b57cec5SDimitry Andric struct GenMoveConstructor : GenBinaryFunc<GenMoveConstructor, true> { 700*0b57cec5SDimitry Andric GenMoveConstructor(ASTContext &Ctx) 701*0b57cec5SDimitry Andric : GenBinaryFunc<GenMoveConstructor, true>(Ctx) {} 702*0b57cec5SDimitry Andric 703*0b57cec5SDimitry Andric void visitARCStrong(QualType QT, const FieldDecl *FD, 704*0b57cec5SDimitry Andric CharUnits CurStructOffset, std::array<Address, 2> Addrs) { 705*0b57cec5SDimitry Andric Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD); 706*0b57cec5SDimitry Andric Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD); 707*0b57cec5SDimitry Andric LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT); 708*0b57cec5SDimitry Andric llvm::Value *SrcVal = 709*0b57cec5SDimitry Andric CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal(); 710*0b57cec5SDimitry Andric CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress()), SrcLV); 711*0b57cec5SDimitry Andric CGF->EmitStoreOfScalar(SrcVal, CGF->MakeAddrLValue(Addrs[DstIdx], QT), 712*0b57cec5SDimitry Andric /* isInitialization */ true); 713*0b57cec5SDimitry Andric } 714*0b57cec5SDimitry Andric 715*0b57cec5SDimitry Andric void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset, 716*0b57cec5SDimitry Andric std::array<Address, 2> Addrs) { 717*0b57cec5SDimitry Andric Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD); 718*0b57cec5SDimitry Andric Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD); 719*0b57cec5SDimitry Andric CGF->EmitARCMoveWeak(Addrs[DstIdx], Addrs[SrcIdx]); 720*0b57cec5SDimitry Andric } 721*0b57cec5SDimitry Andric 722*0b57cec5SDimitry Andric void callSpecialFunction(QualType FT, CharUnits Offset, 723*0b57cec5SDimitry Andric std::array<Address, 2> Addrs) { 724*0b57cec5SDimitry Andric Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset); 725*0b57cec5SDimitry Andric Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset); 726*0b57cec5SDimitry Andric CGF->callCStructMoveConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT), 727*0b57cec5SDimitry Andric CGF->MakeAddrLValue(Addrs[SrcIdx], FT)); 728*0b57cec5SDimitry Andric } 729*0b57cec5SDimitry Andric }; 730*0b57cec5SDimitry Andric 731*0b57cec5SDimitry Andric struct GenCopyAssignment : GenBinaryFunc<GenCopyAssignment, false> { 732*0b57cec5SDimitry Andric GenCopyAssignment(ASTContext &Ctx) 733*0b57cec5SDimitry Andric : GenBinaryFunc<GenCopyAssignment, false>(Ctx) {} 734*0b57cec5SDimitry Andric 735*0b57cec5SDimitry Andric void visitARCStrong(QualType QT, const FieldDecl *FD, 736*0b57cec5SDimitry Andric CharUnits CurStructOffset, std::array<Address, 2> Addrs) { 737*0b57cec5SDimitry Andric Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD); 738*0b57cec5SDimitry Andric Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD); 739*0b57cec5SDimitry Andric llvm::Value *SrcVal = CGF->EmitLoadOfScalar( 740*0b57cec5SDimitry Andric Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation()); 741*0b57cec5SDimitry Andric CGF->EmitARCStoreStrong(CGF->MakeAddrLValue(Addrs[DstIdx], QT), SrcVal, 742*0b57cec5SDimitry Andric false); 743*0b57cec5SDimitry Andric } 744*0b57cec5SDimitry Andric 745*0b57cec5SDimitry Andric void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset, 746*0b57cec5SDimitry Andric std::array<Address, 2> Addrs) { 747*0b57cec5SDimitry Andric Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD); 748*0b57cec5SDimitry Andric Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD); 749*0b57cec5SDimitry Andric CGF->emitARCCopyAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]); 750*0b57cec5SDimitry Andric } 751*0b57cec5SDimitry Andric 752*0b57cec5SDimitry Andric void callSpecialFunction(QualType FT, CharUnits Offset, 753*0b57cec5SDimitry Andric std::array<Address, 2> Addrs) { 754*0b57cec5SDimitry Andric Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset); 755*0b57cec5SDimitry Andric Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset); 756*0b57cec5SDimitry Andric CGF->callCStructCopyAssignmentOperator( 757*0b57cec5SDimitry Andric CGF->MakeAddrLValue(Addrs[DstIdx], FT), 758*0b57cec5SDimitry Andric CGF->MakeAddrLValue(Addrs[SrcIdx], FT)); 759*0b57cec5SDimitry Andric } 760*0b57cec5SDimitry Andric }; 761*0b57cec5SDimitry Andric 762*0b57cec5SDimitry Andric struct GenMoveAssignment : GenBinaryFunc<GenMoveAssignment, true> { 763*0b57cec5SDimitry Andric GenMoveAssignment(ASTContext &Ctx) 764*0b57cec5SDimitry Andric : GenBinaryFunc<GenMoveAssignment, true>(Ctx) {} 765*0b57cec5SDimitry Andric 766*0b57cec5SDimitry Andric void visitARCStrong(QualType QT, const FieldDecl *FD, 767*0b57cec5SDimitry Andric CharUnits CurStructOffset, std::array<Address, 2> Addrs) { 768*0b57cec5SDimitry Andric Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD); 769*0b57cec5SDimitry Andric Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD); 770*0b57cec5SDimitry Andric LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT); 771*0b57cec5SDimitry Andric llvm::Value *SrcVal = 772*0b57cec5SDimitry Andric CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal(); 773*0b57cec5SDimitry Andric CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress()), SrcLV); 774*0b57cec5SDimitry Andric LValue DstLV = CGF->MakeAddrLValue(Addrs[DstIdx], QT); 775*0b57cec5SDimitry Andric llvm::Value *DstVal = 776*0b57cec5SDimitry Andric CGF->EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal(); 777*0b57cec5SDimitry Andric CGF->EmitStoreOfScalar(SrcVal, DstLV); 778*0b57cec5SDimitry Andric CGF->EmitARCRelease(DstVal, ARCImpreciseLifetime); 779*0b57cec5SDimitry Andric } 780*0b57cec5SDimitry Andric 781*0b57cec5SDimitry Andric void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset, 782*0b57cec5SDimitry Andric std::array<Address, 2> Addrs) { 783*0b57cec5SDimitry Andric Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD); 784*0b57cec5SDimitry Andric Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD); 785*0b57cec5SDimitry Andric CGF->emitARCMoveAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]); 786*0b57cec5SDimitry Andric } 787*0b57cec5SDimitry Andric 788*0b57cec5SDimitry Andric void callSpecialFunction(QualType FT, CharUnits Offset, 789*0b57cec5SDimitry Andric std::array<Address, 2> Addrs) { 790*0b57cec5SDimitry Andric Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset); 791*0b57cec5SDimitry Andric Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset); 792*0b57cec5SDimitry Andric CGF->callCStructMoveAssignmentOperator( 793*0b57cec5SDimitry Andric CGF->MakeAddrLValue(Addrs[DstIdx], FT), 794*0b57cec5SDimitry Andric CGF->MakeAddrLValue(Addrs[SrcIdx], FT)); 795*0b57cec5SDimitry Andric } 796*0b57cec5SDimitry Andric }; 797*0b57cec5SDimitry Andric 798*0b57cec5SDimitry Andric } // namespace 799*0b57cec5SDimitry Andric 800*0b57cec5SDimitry Andric void CodeGenFunction::destroyNonTrivialCStruct(CodeGenFunction &CGF, 801*0b57cec5SDimitry Andric Address Addr, QualType Type) { 802*0b57cec5SDimitry Andric CGF.callCStructDestructor(CGF.MakeAddrLValue(Addr, Type)); 803*0b57cec5SDimitry Andric } 804*0b57cec5SDimitry Andric 805*0b57cec5SDimitry Andric // Default-initialize a variable that is a non-trivial struct or an array of 806*0b57cec5SDimitry Andric // such structure. 807*0b57cec5SDimitry Andric void CodeGenFunction::defaultInitNonTrivialCStructVar(LValue Dst) { 808*0b57cec5SDimitry Andric GenDefaultInitialize Gen(getContext()); 809*0b57cec5SDimitry Andric Address DstPtr = Builder.CreateBitCast(Dst.getAddress(), CGM.Int8PtrPtrTy); 810*0b57cec5SDimitry Andric Gen.setCGF(this); 811*0b57cec5SDimitry Andric QualType QT = Dst.getType(); 812*0b57cec5SDimitry Andric QT = Dst.isVolatile() ? QT.withVolatile() : QT; 813*0b57cec5SDimitry Andric Gen.visit(QT, nullptr, CharUnits::Zero(), std::array<Address, 1>({{DstPtr}})); 814*0b57cec5SDimitry Andric } 815*0b57cec5SDimitry Andric 816*0b57cec5SDimitry Andric template <class G, size_t N> 817*0b57cec5SDimitry Andric static void callSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, 818*0b57cec5SDimitry Andric bool IsVolatile, CodeGenFunction &CGF, 819*0b57cec5SDimitry Andric std::array<Address, N> Addrs) { 820*0b57cec5SDimitry Andric for (unsigned I = 0; I < N; ++I) 821*0b57cec5SDimitry Andric Addrs[I] = CGF.Builder.CreateBitCast(Addrs[I], CGF.CGM.Int8PtrPtrTy); 822*0b57cec5SDimitry Andric QT = IsVolatile ? QT.withVolatile() : QT; 823*0b57cec5SDimitry Andric Gen.callFunc(FuncName, QT, Addrs, CGF); 824*0b57cec5SDimitry Andric } 825*0b57cec5SDimitry Andric 826*0b57cec5SDimitry Andric template <size_t N> std::array<Address, N> createNullAddressArray(); 827*0b57cec5SDimitry Andric 828*0b57cec5SDimitry Andric template <> std::array<Address, 1> createNullAddressArray() { 829*0b57cec5SDimitry Andric return std::array<Address, 1>({{Address(nullptr, CharUnits::Zero())}}); 830*0b57cec5SDimitry Andric } 831*0b57cec5SDimitry Andric 832*0b57cec5SDimitry Andric template <> std::array<Address, 2> createNullAddressArray() { 833*0b57cec5SDimitry Andric return std::array<Address, 2>({{Address(nullptr, CharUnits::Zero()), 834*0b57cec5SDimitry Andric Address(nullptr, CharUnits::Zero())}}); 835*0b57cec5SDimitry Andric } 836*0b57cec5SDimitry Andric 837*0b57cec5SDimitry Andric template <class G, size_t N> 838*0b57cec5SDimitry Andric static llvm::Function * 839*0b57cec5SDimitry Andric getSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile, 840*0b57cec5SDimitry Andric std::array<CharUnits, N> Alignments, CodeGenModule &CGM) { 841*0b57cec5SDimitry Andric QT = IsVolatile ? QT.withVolatile() : QT; 842*0b57cec5SDimitry Andric // The following call requires an array of addresses as arguments, but doesn't 843*0b57cec5SDimitry Andric // actually use them (it overwrites them with the addresses of the arguments 844*0b57cec5SDimitry Andric // of the created function). 845*0b57cec5SDimitry Andric return Gen.getFunction(FuncName, QT, createNullAddressArray<N>(), Alignments, 846*0b57cec5SDimitry Andric CGM); 847*0b57cec5SDimitry Andric } 848*0b57cec5SDimitry Andric 849*0b57cec5SDimitry Andric // Functions to emit calls to the special functions of a non-trivial C struct. 850*0b57cec5SDimitry Andric void CodeGenFunction::callCStructDefaultConstructor(LValue Dst) { 851*0b57cec5SDimitry Andric bool IsVolatile = Dst.isVolatile(); 852*0b57cec5SDimitry Andric Address DstPtr = Dst.getAddress(); 853*0b57cec5SDimitry Andric QualType QT = Dst.getType(); 854*0b57cec5SDimitry Andric GenDefaultInitializeFuncName GenName(DstPtr.getAlignment(), getContext()); 855*0b57cec5SDimitry Andric std::string FuncName = GenName.getName(QT, IsVolatile); 856*0b57cec5SDimitry Andric callSpecialFunction(GenDefaultInitialize(getContext()), FuncName, QT, 857*0b57cec5SDimitry Andric IsVolatile, *this, std::array<Address, 1>({{DstPtr}})); 858*0b57cec5SDimitry Andric } 859*0b57cec5SDimitry Andric 860*0b57cec5SDimitry Andric std::string CodeGenFunction::getNonTrivialCopyConstructorStr( 861*0b57cec5SDimitry Andric QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx) { 862*0b57cec5SDimitry Andric GenBinaryFuncName<false> GenName("", Alignment, Alignment, Ctx); 863*0b57cec5SDimitry Andric return GenName.getName(QT, IsVolatile); 864*0b57cec5SDimitry Andric } 865*0b57cec5SDimitry Andric 866*0b57cec5SDimitry Andric std::string CodeGenFunction::getNonTrivialDestructorStr(QualType QT, 867*0b57cec5SDimitry Andric CharUnits Alignment, 868*0b57cec5SDimitry Andric bool IsVolatile, 869*0b57cec5SDimitry Andric ASTContext &Ctx) { 870*0b57cec5SDimitry Andric GenDestructorFuncName GenName("", Alignment, Ctx); 871*0b57cec5SDimitry Andric return GenName.getName(QT, IsVolatile); 872*0b57cec5SDimitry Andric } 873*0b57cec5SDimitry Andric 874*0b57cec5SDimitry Andric void CodeGenFunction::callCStructDestructor(LValue Dst) { 875*0b57cec5SDimitry Andric bool IsVolatile = Dst.isVolatile(); 876*0b57cec5SDimitry Andric Address DstPtr = Dst.getAddress(); 877*0b57cec5SDimitry Andric QualType QT = Dst.getType(); 878*0b57cec5SDimitry Andric GenDestructorFuncName GenName("__destructor_", DstPtr.getAlignment(), 879*0b57cec5SDimitry Andric getContext()); 880*0b57cec5SDimitry Andric std::string FuncName = GenName.getName(QT, IsVolatile); 881*0b57cec5SDimitry Andric callSpecialFunction(GenDestructor(getContext()), FuncName, QT, IsVolatile, 882*0b57cec5SDimitry Andric *this, std::array<Address, 1>({{DstPtr}})); 883*0b57cec5SDimitry Andric } 884*0b57cec5SDimitry Andric 885*0b57cec5SDimitry Andric void CodeGenFunction::callCStructCopyConstructor(LValue Dst, LValue Src) { 886*0b57cec5SDimitry Andric bool IsVolatile = Dst.isVolatile() || Src.isVolatile(); 887*0b57cec5SDimitry Andric Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress(); 888*0b57cec5SDimitry Andric QualType QT = Dst.getType(); 889*0b57cec5SDimitry Andric GenBinaryFuncName<false> GenName("__copy_constructor_", DstPtr.getAlignment(), 890*0b57cec5SDimitry Andric SrcPtr.getAlignment(), getContext()); 891*0b57cec5SDimitry Andric std::string FuncName = GenName.getName(QT, IsVolatile); 892*0b57cec5SDimitry Andric callSpecialFunction(GenCopyConstructor(getContext()), FuncName, QT, 893*0b57cec5SDimitry Andric IsVolatile, *this, 894*0b57cec5SDimitry Andric std::array<Address, 2>({{DstPtr, SrcPtr}})); 895*0b57cec5SDimitry Andric } 896*0b57cec5SDimitry Andric 897*0b57cec5SDimitry Andric void CodeGenFunction::callCStructCopyAssignmentOperator(LValue Dst, LValue Src 898*0b57cec5SDimitry Andric 899*0b57cec5SDimitry Andric ) { 900*0b57cec5SDimitry Andric bool IsVolatile = Dst.isVolatile() || Src.isVolatile(); 901*0b57cec5SDimitry Andric Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress(); 902*0b57cec5SDimitry Andric QualType QT = Dst.getType(); 903*0b57cec5SDimitry Andric GenBinaryFuncName<false> GenName("__copy_assignment_", DstPtr.getAlignment(), 904*0b57cec5SDimitry Andric SrcPtr.getAlignment(), getContext()); 905*0b57cec5SDimitry Andric std::string FuncName = GenName.getName(QT, IsVolatile); 906*0b57cec5SDimitry Andric callSpecialFunction(GenCopyAssignment(getContext()), FuncName, QT, IsVolatile, 907*0b57cec5SDimitry Andric *this, std::array<Address, 2>({{DstPtr, SrcPtr}})); 908*0b57cec5SDimitry Andric } 909*0b57cec5SDimitry Andric 910*0b57cec5SDimitry Andric void CodeGenFunction::callCStructMoveConstructor(LValue Dst, LValue Src) { 911*0b57cec5SDimitry Andric bool IsVolatile = Dst.isVolatile() || Src.isVolatile(); 912*0b57cec5SDimitry Andric Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress(); 913*0b57cec5SDimitry Andric QualType QT = Dst.getType(); 914*0b57cec5SDimitry Andric GenBinaryFuncName<true> GenName("__move_constructor_", DstPtr.getAlignment(), 915*0b57cec5SDimitry Andric SrcPtr.getAlignment(), getContext()); 916*0b57cec5SDimitry Andric std::string FuncName = GenName.getName(QT, IsVolatile); 917*0b57cec5SDimitry Andric callSpecialFunction(GenMoveConstructor(getContext()), FuncName, QT, 918*0b57cec5SDimitry Andric IsVolatile, *this, 919*0b57cec5SDimitry Andric std::array<Address, 2>({{DstPtr, SrcPtr}})); 920*0b57cec5SDimitry Andric } 921*0b57cec5SDimitry Andric 922*0b57cec5SDimitry Andric void CodeGenFunction::callCStructMoveAssignmentOperator(LValue Dst, LValue Src 923*0b57cec5SDimitry Andric 924*0b57cec5SDimitry Andric ) { 925*0b57cec5SDimitry Andric bool IsVolatile = Dst.isVolatile() || Src.isVolatile(); 926*0b57cec5SDimitry Andric Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress(); 927*0b57cec5SDimitry Andric QualType QT = Dst.getType(); 928*0b57cec5SDimitry Andric GenBinaryFuncName<true> GenName("__move_assignment_", DstPtr.getAlignment(), 929*0b57cec5SDimitry Andric SrcPtr.getAlignment(), getContext()); 930*0b57cec5SDimitry Andric std::string FuncName = GenName.getName(QT, IsVolatile); 931*0b57cec5SDimitry Andric callSpecialFunction(GenMoveAssignment(getContext()), FuncName, QT, IsVolatile, 932*0b57cec5SDimitry Andric *this, std::array<Address, 2>({{DstPtr, SrcPtr}})); 933*0b57cec5SDimitry Andric } 934*0b57cec5SDimitry Andric 935*0b57cec5SDimitry Andric llvm::Function *clang::CodeGen::getNonTrivialCStructDefaultConstructor( 936*0b57cec5SDimitry Andric CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) { 937*0b57cec5SDimitry Andric ASTContext &Ctx = CGM.getContext(); 938*0b57cec5SDimitry Andric GenDefaultInitializeFuncName GenName(DstAlignment, Ctx); 939*0b57cec5SDimitry Andric std::string FuncName = GenName.getName(QT, IsVolatile); 940*0b57cec5SDimitry Andric return getSpecialFunction(GenDefaultInitialize(Ctx), FuncName, QT, IsVolatile, 941*0b57cec5SDimitry Andric std::array<CharUnits, 1>({{DstAlignment}}), CGM); 942*0b57cec5SDimitry Andric } 943*0b57cec5SDimitry Andric 944*0b57cec5SDimitry Andric llvm::Function *clang::CodeGen::getNonTrivialCStructCopyConstructor( 945*0b57cec5SDimitry Andric CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment, 946*0b57cec5SDimitry Andric bool IsVolatile, QualType QT) { 947*0b57cec5SDimitry Andric ASTContext &Ctx = CGM.getContext(); 948*0b57cec5SDimitry Andric GenBinaryFuncName<false> GenName("__copy_constructor_", DstAlignment, 949*0b57cec5SDimitry Andric SrcAlignment, Ctx); 950*0b57cec5SDimitry Andric std::string FuncName = GenName.getName(QT, IsVolatile); 951*0b57cec5SDimitry Andric return getSpecialFunction( 952*0b57cec5SDimitry Andric GenCopyConstructor(Ctx), FuncName, QT, IsVolatile, 953*0b57cec5SDimitry Andric std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM); 954*0b57cec5SDimitry Andric } 955*0b57cec5SDimitry Andric 956*0b57cec5SDimitry Andric llvm::Function *clang::CodeGen::getNonTrivialCStructMoveConstructor( 957*0b57cec5SDimitry Andric CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment, 958*0b57cec5SDimitry Andric bool IsVolatile, QualType QT) { 959*0b57cec5SDimitry Andric ASTContext &Ctx = CGM.getContext(); 960*0b57cec5SDimitry Andric GenBinaryFuncName<true> GenName("__move_constructor_", DstAlignment, 961*0b57cec5SDimitry Andric SrcAlignment, Ctx); 962*0b57cec5SDimitry Andric std::string FuncName = GenName.getName(QT, IsVolatile); 963*0b57cec5SDimitry Andric return getSpecialFunction( 964*0b57cec5SDimitry Andric GenMoveConstructor(Ctx), FuncName, QT, IsVolatile, 965*0b57cec5SDimitry Andric std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM); 966*0b57cec5SDimitry Andric } 967*0b57cec5SDimitry Andric 968*0b57cec5SDimitry Andric llvm::Function *clang::CodeGen::getNonTrivialCStructCopyAssignmentOperator( 969*0b57cec5SDimitry Andric CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment, 970*0b57cec5SDimitry Andric bool IsVolatile, QualType QT) { 971*0b57cec5SDimitry Andric ASTContext &Ctx = CGM.getContext(); 972*0b57cec5SDimitry Andric GenBinaryFuncName<false> GenName("__copy_assignment_", DstAlignment, 973*0b57cec5SDimitry Andric SrcAlignment, Ctx); 974*0b57cec5SDimitry Andric std::string FuncName = GenName.getName(QT, IsVolatile); 975*0b57cec5SDimitry Andric return getSpecialFunction( 976*0b57cec5SDimitry Andric GenCopyAssignment(Ctx), FuncName, QT, IsVolatile, 977*0b57cec5SDimitry Andric std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM); 978*0b57cec5SDimitry Andric } 979*0b57cec5SDimitry Andric 980*0b57cec5SDimitry Andric llvm::Function *clang::CodeGen::getNonTrivialCStructMoveAssignmentOperator( 981*0b57cec5SDimitry Andric CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment, 982*0b57cec5SDimitry Andric bool IsVolatile, QualType QT) { 983*0b57cec5SDimitry Andric ASTContext &Ctx = CGM.getContext(); 984*0b57cec5SDimitry Andric GenBinaryFuncName<true> GenName("__move_assignment_", DstAlignment, 985*0b57cec5SDimitry Andric SrcAlignment, Ctx); 986*0b57cec5SDimitry Andric std::string FuncName = GenName.getName(QT, IsVolatile); 987*0b57cec5SDimitry Andric return getSpecialFunction( 988*0b57cec5SDimitry Andric GenMoveAssignment(Ctx), FuncName, QT, IsVolatile, 989*0b57cec5SDimitry Andric std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM); 990*0b57cec5SDimitry Andric } 991*0b57cec5SDimitry Andric 992*0b57cec5SDimitry Andric llvm::Function *clang::CodeGen::getNonTrivialCStructDestructor( 993*0b57cec5SDimitry Andric CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) { 994*0b57cec5SDimitry Andric ASTContext &Ctx = CGM.getContext(); 995*0b57cec5SDimitry Andric GenDestructorFuncName GenName("__destructor_", DstAlignment, Ctx); 996*0b57cec5SDimitry Andric std::string FuncName = GenName.getName(QT, IsVolatile); 997*0b57cec5SDimitry Andric return getSpecialFunction(GenDestructor(Ctx), FuncName, QT, IsVolatile, 998*0b57cec5SDimitry Andric std::array<CharUnits, 1>({{DstAlignment}}), CGM); 999*0b57cec5SDimitry Andric } 1000