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