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