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