1 //===--- CGNonTrivialStruct.cpp - Emit Special Functions for C Structs ----===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines functions to generate various special functions for C
12 //===----------------------------------------------------------------------===//
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"
21 using namespace clang
;
22 using namespace CodeGen
;
24 // Return the size of a field in number of bits.
25 static uint64_t getFieldSize(const FieldDecl
*FD
, QualType FT
,
27 if (FD
&& FD
->isBitField())
28 return FD
->getBitWidthValue(Ctx
);
29 return Ctx
.getTypeSize(FT
);
33 enum { DstIdx
= 0, SrcIdx
= 1 };
34 const char *ValNameStr
[2] = {"dst", "src"};
36 template <class Derived
> struct StructVisitor
{
37 StructVisitor(ASTContext
&Ctx
) : Ctx(Ctx
) {}
39 template <class... Ts
>
40 void visitStructFields(QualType QT
, CharUnits CurStructOffset
, Ts
... Args
) {
41 const RecordDecl
*RD
= QT
->castAs
<RecordType
>()->getDecl();
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
...);
50 asDerived().flushTrivialFields(Args
...);
53 template <class... Ts
> void visitTrivial(Ts
... Args
) {}
55 template <class... Ts
> void visitCXXDestructor(Ts
... Args
) {
56 llvm_unreachable("field of a C++ struct type is not expected");
59 template <class... Ts
> void flushTrivialFields(Ts
... Args
) {}
61 uint64_t getFieldOffsetInBits(const FieldDecl
*FD
) {
62 return FD
? Ctx
.getASTRecordLayout(FD
->getParent())
63 .getFieldOffset(FD
->getFieldIndex())
67 CharUnits
getFieldOffset(const FieldDecl
*FD
) {
68 return Ctx
.toCharUnitsFromBits(getFieldOffsetInBits(FD
));
71 Derived
&asDerived() { return static_cast<Derived
&>(*this); }
73 ASTContext
&getContext() { return Ctx
; }
77 template <class Derived
, bool IsMove
>
78 struct CopyStructVisitor
: StructVisitor
<Derived
>,
79 CopiedTypeVisitor
<Derived
, IsMove
> {
80 using StructVisitor
<Derived
>::asDerived
;
81 using Super
= CopiedTypeVisitor
<Derived
, IsMove
>;
83 CopyStructVisitor(ASTContext
&Ctx
) : StructVisitor
<Derived
>(Ctx
) {}
85 template <class... Ts
>
86 void preVisit(QualType::PrimitiveCopyKind PCK
, QualType FT
,
87 const FieldDecl
*FD
, CharUnits CurStructOffset
, Ts
&&... Args
) {
89 asDerived().flushTrivialFields(std::forward
<Ts
>(Args
)...);
92 template <class... Ts
>
93 void visitWithKind(QualType::PrimitiveCopyKind PCK
, QualType FT
,
94 const FieldDecl
*FD
, CharUnits CurStructOffset
,
96 if (const auto *AT
= asDerived().getContext().getAsArrayType(FT
)) {
97 asDerived().visitArray(PCK
, AT
, FT
.isVolatileQualified(), FD
,
98 CurStructOffset
, std::forward
<Ts
>(Args
)...);
102 Super::visitWithKind(PCK
, FT
, FD
, CurStructOffset
,
103 std::forward
<Ts
>(Args
)...);
106 template <class... Ts
>
107 void visitTrivial(QualType FT
, const FieldDecl
*FD
, CharUnits CurStructOffset
,
109 assert(!FT
.isVolatileQualified() && "volatile field not expected");
110 ASTContext
&Ctx
= asDerived().getContext();
111 uint64_t FieldSize
= getFieldSize(FD
, FT
, Ctx
);
113 // Ignore zero-sized fields.
117 uint64_t FStartInBits
= asDerived().getFieldOffsetInBits(FD
);
118 uint64_t FEndInBits
= FStartInBits
+ FieldSize
;
119 uint64_t RoundedFEnd
= llvm::alignTo(FEndInBits
, Ctx
.getCharWidth());
121 // Set Start if this is the first field of a sequence of trivial fields.
123 Start
= CurStructOffset
+ Ctx
.toCharUnitsFromBits(FStartInBits
);
124 End
= CurStructOffset
+ Ctx
.toCharUnitsFromBits(RoundedFEnd
);
127 CharUnits Start
= CharUnits::Zero(), End
= CharUnits::Zero();
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
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>
150 template <class Derived
> struct GenFuncNameBase
{
151 std::string
getVolatileOffsetStr(bool IsVolatile
, CharUnits Offset
) {
155 S
+= llvm::to_string(Offset
.getQuantity());
159 void visitARCStrong(QualType FT
, const FieldDecl
*FD
,
160 CharUnits CurStructOffset
) {
162 if (FT
->isBlockPointerType())
164 CharUnits FieldOffset
= CurStructOffset
+ asDerived().getFieldOffset(FD
);
165 appendStr(getVolatileOffsetStr(FT
.isVolatileQualified(), FieldOffset
));
168 void visitARCWeak(QualType FT
, const FieldDecl
*FD
,
169 CharUnits CurStructOffset
) {
171 CharUnits FieldOffset
= CurStructOffset
+ asDerived().getFieldOffset(FD
);
172 appendStr(getVolatileOffsetStr(FT
.isVolatileQualified(), FieldOffset
));
175 void visitStruct(QualType QT
, const FieldDecl
*FD
,
176 CharUnits CurStructOffset
) {
177 CharUnits FieldOffset
= CurStructOffset
+ asDerived().getFieldOffset(FD
);
179 asDerived().visitStructFields(QT
, FieldOffset
);
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.
188 return asDerived().visitTrivial(QualType(AT
, 0), FD
, CurStructOffset
);
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
);
205 void appendStr(StringRef Str
) { Name
+= Str
; }
207 std::string
getName(QualType QT
, bool IsVolatile
) {
208 QT
= IsVolatile
? QT
.withVolatile() : QT
;
209 asDerived().visitStructFields(QT
, CharUnits::Zero());
213 Derived
&asDerived() { return static_cast<Derived
&>(*this); }
218 template <class Derived
>
219 struct 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()));
227 // Helper function to create a null constant.
228 static llvm::Constant
*getNullForVariable(Address Addr
) {
229 llvm::Type
*Ty
= Addr
.getElementType();
230 return llvm::ConstantPointerNull::get(cast
<llvm::PointerType
>(Ty
));
233 template <bool IsMove
>
234 struct GenBinaryFuncName
: CopyStructVisitor
<GenBinaryFuncName
<IsMove
>, IsMove
>,
235 GenFuncNameBase
<GenBinaryFuncName
<IsMove
>> {
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()));
245 void flushTrivialFields() {
246 if (this->Start
== this->End
)
249 this->appendStr("_t" + llvm::to_string(this->Start
.getQuantity()) + "w" +
250 llvm::to_string((this->End
- this->Start
).getQuantity()));
252 this->Start
= this->End
= CharUnits::Zero();
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
))
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
)));
270 struct 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
);
284 Super::visitWithKind(PDIK
, FT
, FD
, CurStructOffset
);
288 struct GenDestructorFuncName
: GenUnaryFuncName
<GenDestructorFuncName
>,
289 DestructedTypeVisitor
<GenDestructorFuncName
> {
290 using Super
= DestructedTypeVisitor
<GenDestructorFuncName
>;
291 GenDestructorFuncName(const char *Prefix
, CharUnits DstAlignment
,
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
);
301 Super::visitWithKind(DK
, FT
, FD
, CurStructOffset
);
305 // Helper function that creates CGFunctionInfo for an N-ary special function.
307 static 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
);
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
));
318 llvm::append_range(Args
, Params
);
320 return CGM
.getTypes().arrangeBuiltinFunctionDeclaration(Ctx
.VoidTy
, Args
);
323 template <size_t N
, size_t... Ints
>
324 static std::array
<Address
, N
> getParamAddrs(std::index_sequence
<Ints
...> IntSeq
,
325 std::array
<CharUnits
, N
> Alignments
,
326 const 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
], KnownNonNull
)...}};
333 // Template classes that are used as bases for classes that emit special
335 template <class Derived
> struct GenFuncBase
{
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
);
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.
349 return asDerived().visitTrivial(QualType(AT
, 0), FD
, CurStructOffset
,
352 asDerived().flushTrivialFields(Addrs
);
353 CodeGenFunction
&CGF
= *this->CGF
;
354 ASTContext
&Ctx
= CGF
.getContext();
356 // Compute the end address.
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 llvm::Value
*DstArrayEnd
= CGF
.Builder
.CreateInBoundsGEP(
369 CGF
.Int8Ty
, DstAddr
.getPointer(), SizeInBytes
);
370 DstArrayEnd
= CGF
.Builder
.CreateBitCast(
371 DstArrayEnd
, CGF
.CGM
.Int8PtrPtrTy
, "dstarray.end");
372 llvm::BasicBlock
*PreheaderBB
= CGF
.Builder
.GetInsertBlock();
374 // Create the header block and insert the phi instructions.
375 llvm::BasicBlock
*HeaderBB
= CGF
.createBasicBlock("loop.header");
376 CGF
.EmitBlock(HeaderBB
);
377 llvm::PHINode
*PHIs
[N
];
379 for (unsigned I
= 0; I
< N
; ++I
) {
380 PHIs
[I
] = CGF
.Builder
.CreatePHI(CGF
.CGM
.Int8PtrPtrTy
, 2, "addr.cur");
381 PHIs
[I
]->addIncoming(StartAddrs
[I
].getPointer(), PreheaderBB
);
384 // Create the exit and loop body blocks.
385 llvm::BasicBlock
*ExitBB
= CGF
.createBasicBlock("loop.exit");
386 llvm::BasicBlock
*LoopBB
= CGF
.createBasicBlock("loop.body");
388 // Emit the comparison and conditional branch instruction that jumps to
389 // either the exit or the loop body.
391 CGF
.Builder
.CreateICmpEQ(PHIs
[DstIdx
], DstArrayEnd
, "done");
392 CGF
.Builder
.CreateCondBr(Done
, ExitBB
, LoopBB
);
394 // Visit the element of the array in the loop body.
395 CGF
.EmitBlock(LoopBB
);
396 QualType EltQT
= AT
->getElementType();
397 CharUnits EltSize
= Ctx
.getTypeSizeInChars(EltQT
);
398 std::array
<Address
, N
> NewAddrs
= Addrs
;
400 for (unsigned I
= 0; I
< N
; ++I
)
402 Address(PHIs
[I
], CGF
.Int8PtrTy
,
403 StartAddrs
[I
].getAlignment().alignmentAtOffset(EltSize
));
405 EltQT
= IsVolatile
? EltQT
.withVolatile() : EltQT
;
406 this->asDerived().visitWithKind(FK
, EltQT
, nullptr, CharUnits::Zero(),
409 LoopBB
= CGF
.Builder
.GetInsertBlock();
411 for (unsigned I
= 0; I
< N
; ++I
) {
412 // Instrs to update the destination and source addresses.
413 // Update phi instructions.
414 NewAddrs
[I
] = getAddrWithOffset(NewAddrs
[I
], EltSize
);
415 PHIs
[I
]->addIncoming(NewAddrs
[I
].getPointer(), LoopBB
);
418 // Insert an unconditional branch to the header block.
419 CGF
.Builder
.CreateBr(HeaderBB
);
420 CGF
.EmitBlock(ExitBB
);
423 /// Return an address with the specified offset from the passed address.
424 Address
getAddrWithOffset(Address Addr
, CharUnits Offset
) {
425 assert(Addr
.isValid() && "invalid address");
426 if (Offset
.getQuantity() == 0)
428 Addr
= Addr
.withElementType(CGF
->CGM
.Int8Ty
);
429 Addr
= CGF
->Builder
.CreateConstInBoundsGEP(Addr
, Offset
.getQuantity());
430 return Addr
.withElementType(CGF
->CGM
.Int8PtrTy
);
433 Address
getAddrWithOffset(Address Addr
, CharUnits StructFieldOffset
,
434 const FieldDecl
*FD
) {
435 return getAddrWithOffset(Addr
, StructFieldOffset
+
436 asDerived().getFieldOffset(FD
));
440 llvm::Function
*getFunction(StringRef FuncName
, QualType QT
,
441 std::array
<CharUnits
, N
> Alignments
,
442 CodeGenModule
&CGM
) {
443 // If the special function already exists in the module, return it.
444 if (llvm::Function
*F
= CGM
.getModule().getFunction(FuncName
)) {
445 bool WrongType
= false;
446 if (!F
->getReturnType()->isVoidTy())
449 for (const llvm::Argument
&Arg
: F
->args())
450 if (Arg
.getType() != CGM
.Int8PtrPtrTy
)
455 std::string FuncName
= std::string(F
->getName());
456 SourceLocation Loc
= QT
->castAs
<RecordType
>()->getDecl()->getLocation();
457 CGM
.Error(Loc
, "special function " + FuncName
+
458 " for non-trivial C struct has incorrect type");
464 ASTContext
&Ctx
= CGM
.getContext();
465 FunctionArgList Args
;
466 const CGFunctionInfo
&FI
= getFunctionInfo
<N
>(CGM
, Args
);
467 llvm::FunctionType
*FuncTy
= CGM
.getTypes().GetFunctionType(FI
);
469 llvm::Function::Create(FuncTy
, llvm::GlobalValue::LinkOnceODRLinkage
,
470 FuncName
, &CGM
.getModule());
471 F
->setVisibility(llvm::GlobalValue::HiddenVisibility
);
472 CGM
.SetLLVMFunctionAttributes(GlobalDecl(), FI
, F
, /*IsThunk=*/false);
473 CGM
.SetLLVMFunctionAttributesForDefinition(nullptr, F
);
474 CodeGenFunction
NewCGF(CGM
);
476 CGF
->StartFunction(GlobalDecl(), Ctx
.VoidTy
, F
, FI
, Args
);
477 auto AL
= ApplyDebugLocation::CreateArtificial(*CGF
);
478 std::array
<Address
, N
> Addrs
=
479 getParamAddrs
<N
>(std::make_index_sequence
<N
>{}, Alignments
, Args
, CGF
);
480 asDerived().visitStructFields(QT
, CharUnits::Zero(), Addrs
);
481 CGF
->FinishFunction();
486 void callFunc(StringRef FuncName
, QualType QT
, std::array
<Address
, N
> Addrs
,
487 CodeGenFunction
&CallerCGF
) {
488 std::array
<CharUnits
, N
> Alignments
;
489 llvm::Value
*Ptrs
[N
];
491 for (unsigned I
= 0; I
< N
; ++I
) {
492 Alignments
[I
] = Addrs
[I
].getAlignment();
493 Ptrs
[I
] = Addrs
[I
].getPointer();
496 if (llvm::Function
*F
=
497 getFunction(FuncName
, QT
, Alignments
, CallerCGF
.CGM
))
498 CallerCGF
.EmitNounwindRuntimeCall(F
, Ptrs
);
501 Derived
&asDerived() { return static_cast<Derived
&>(*this); }
503 void setCGF(CodeGenFunction
*F
) { CGF
= F
; }
505 CodeGenFunction
*CGF
= nullptr;
508 template <class Derived
, bool IsMove
>
509 struct GenBinaryFunc
: CopyStructVisitor
<Derived
, IsMove
>,
510 GenFuncBase
<Derived
> {
511 GenBinaryFunc(ASTContext
&Ctx
) : CopyStructVisitor
<Derived
, IsMove
>(Ctx
) {}
513 void flushTrivialFields(std::array
<Address
, 2> Addrs
) {
514 CharUnits Size
= this->End
- this->Start
;
516 if (Size
.getQuantity() == 0)
519 Address DstAddr
= this->getAddrWithOffset(Addrs
[DstIdx
], this->Start
);
520 Address SrcAddr
= this->getAddrWithOffset(Addrs
[SrcIdx
], this->Start
);
523 if (Size
.getQuantity() >= 16 ||
524 !llvm::has_single_bit
<uint32_t>(Size
.getQuantity())) {
525 llvm::Value
*SizeVal
=
526 llvm::ConstantInt::get(this->CGF
->SizeTy
, Size
.getQuantity());
527 DstAddr
= DstAddr
.withElementType(this->CGF
->Int8Ty
);
528 SrcAddr
= SrcAddr
.withElementType(this->CGF
->Int8Ty
);
529 this->CGF
->Builder
.CreateMemCpy(DstAddr
, SrcAddr
, SizeVal
, false);
531 llvm::Type
*Ty
= llvm::Type::getIntNTy(
532 this->CGF
->getLLVMContext(),
533 Size
.getQuantity() * this->CGF
->getContext().getCharWidth());
534 DstAddr
= DstAddr
.withElementType(Ty
);
535 SrcAddr
= SrcAddr
.withElementType(Ty
);
536 llvm::Value
*SrcVal
= this->CGF
->Builder
.CreateLoad(SrcAddr
, false);
537 this->CGF
->Builder
.CreateStore(SrcVal
, DstAddr
, false);
540 this->Start
= this->End
= CharUnits::Zero();
543 template <class... Ts
>
544 void visitVolatileTrivial(QualType FT
, const FieldDecl
*FD
, CharUnits Offset
,
545 std::array
<Address
, 2> Addrs
) {
548 // No need to copy zero-length bit-fields.
549 if (FD
->isZeroLengthBitField(this->CGF
->getContext()))
552 QualType RT
= QualType(FD
->getParent()->getTypeForDecl(), 0);
553 llvm::Type
*Ty
= this->CGF
->ConvertType(RT
);
554 Address DstAddr
= this->getAddrWithOffset(Addrs
[DstIdx
], Offset
);
556 this->CGF
->MakeAddrLValue(DstAddr
.withElementType(Ty
), FT
);
557 DstLV
= this->CGF
->EmitLValueForField(DstBase
, FD
);
558 Address SrcAddr
= this->getAddrWithOffset(Addrs
[SrcIdx
], Offset
);
560 this->CGF
->MakeAddrLValue(SrcAddr
.withElementType(Ty
), FT
);
561 SrcLV
= this->CGF
->EmitLValueForField(SrcBase
, FD
);
563 llvm::Type
*Ty
= this->CGF
->ConvertTypeForMem(FT
);
564 Address DstAddr
= Addrs
[DstIdx
].withElementType(Ty
);
565 Address SrcAddr
= Addrs
[SrcIdx
].withElementType(Ty
);
566 DstLV
= this->CGF
->MakeAddrLValue(DstAddr
, FT
);
567 SrcLV
= this->CGF
->MakeAddrLValue(SrcAddr
, FT
);
569 RValue SrcVal
= this->CGF
->EmitLoadOfLValue(SrcLV
, SourceLocation());
570 this->CGF
->EmitStoreThroughLValue(SrcVal
, DstLV
);
574 // These classes that emit the special functions for a non-trivial struct.
575 struct GenDestructor
: StructVisitor
<GenDestructor
>,
576 GenFuncBase
<GenDestructor
>,
577 DestructedTypeVisitor
<GenDestructor
> {
578 using Super
= DestructedTypeVisitor
<GenDestructor
>;
579 GenDestructor(ASTContext
&Ctx
) : StructVisitor
<GenDestructor
>(Ctx
) {}
581 void visitWithKind(QualType::DestructionKind DK
, QualType FT
,
582 const FieldDecl
*FD
, CharUnits CurStructOffset
,
583 std::array
<Address
, 1> Addrs
) {
584 if (const auto *AT
= getContext().getAsArrayType(FT
)) {
585 visitArray(DK
, AT
, FT
.isVolatileQualified(), FD
, CurStructOffset
, Addrs
);
589 Super::visitWithKind(DK
, FT
, FD
, CurStructOffset
, Addrs
);
592 void visitARCStrong(QualType QT
, const FieldDecl
*FD
,
593 CharUnits CurStructOffset
, std::array
<Address
, 1> Addrs
) {
594 CGF
->destroyARCStrongImprecise(
595 *CGF
, getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
), QT
);
598 void visitARCWeak(QualType QT
, const FieldDecl
*FD
, CharUnits CurStructOffset
,
599 std::array
<Address
, 1> Addrs
) {
601 *CGF
, getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
), QT
);
604 void callSpecialFunction(QualType FT
, CharUnits Offset
,
605 std::array
<Address
, 1> Addrs
) {
606 CGF
->callCStructDestructor(
607 CGF
->MakeAddrLValue(getAddrWithOffset(Addrs
[DstIdx
], Offset
), FT
));
611 struct GenDefaultInitialize
612 : StructVisitor
<GenDefaultInitialize
>,
613 GenFuncBase
<GenDefaultInitialize
>,
614 DefaultInitializedTypeVisitor
<GenDefaultInitialize
> {
615 using Super
= DefaultInitializedTypeVisitor
<GenDefaultInitialize
>;
616 typedef GenFuncBase
<GenDefaultInitialize
> GenFuncBaseTy
;
618 GenDefaultInitialize(ASTContext
&Ctx
)
619 : StructVisitor
<GenDefaultInitialize
>(Ctx
) {}
621 void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK
, QualType FT
,
622 const FieldDecl
*FD
, CharUnits CurStructOffset
,
623 std::array
<Address
, 1> Addrs
) {
624 if (const auto *AT
= getContext().getAsArrayType(FT
)) {
625 visitArray(PDIK
, AT
, FT
.isVolatileQualified(), FD
, CurStructOffset
,
630 Super::visitWithKind(PDIK
, FT
, FD
, CurStructOffset
, Addrs
);
633 void visitARCStrong(QualType QT
, const FieldDecl
*FD
,
634 CharUnits CurStructOffset
, std::array
<Address
, 1> Addrs
) {
635 CGF
->EmitNullInitialization(
636 getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
), QT
);
639 void visitARCWeak(QualType QT
, const FieldDecl
*FD
, CharUnits CurStructOffset
,
640 std::array
<Address
, 1> Addrs
) {
641 CGF
->EmitNullInitialization(
642 getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
), QT
);
645 template <class FieldKind
, size_t... Is
>
646 void visitArray(FieldKind FK
, const ArrayType
*AT
, bool IsVolatile
,
647 const FieldDecl
*FD
, CharUnits CurStructOffset
,
648 std::array
<Address
, 1> Addrs
) {
650 return visitTrivial(QualType(AT
, 0), FD
, CurStructOffset
, Addrs
);
652 ASTContext
&Ctx
= getContext();
653 CharUnits Size
= Ctx
.getTypeSizeInChars(QualType(AT
, 0));
654 QualType EltTy
= Ctx
.getBaseElementType(QualType(AT
, 0));
656 if (Size
< CharUnits::fromQuantity(16) || EltTy
->getAs
<RecordType
>()) {
657 GenFuncBaseTy::visitArray(FK
, AT
, IsVolatile
, FD
, CurStructOffset
, Addrs
);
661 llvm::Constant
*SizeVal
= CGF
->Builder
.getInt64(Size
.getQuantity());
662 Address DstAddr
= getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
663 Address Loc
= DstAddr
.withElementType(CGF
->Int8Ty
);
664 CGF
->Builder
.CreateMemSet(Loc
, CGF
->Builder
.getInt8(0), SizeVal
,
668 void callSpecialFunction(QualType FT
, CharUnits Offset
,
669 std::array
<Address
, 1> Addrs
) {
670 CGF
->callCStructDefaultConstructor(
671 CGF
->MakeAddrLValue(getAddrWithOffset(Addrs
[DstIdx
], Offset
), FT
));
675 struct GenCopyConstructor
: GenBinaryFunc
<GenCopyConstructor
, false> {
676 GenCopyConstructor(ASTContext
&Ctx
)
677 : GenBinaryFunc
<GenCopyConstructor
, false>(Ctx
) {}
679 void visitARCStrong(QualType QT
, const FieldDecl
*FD
,
680 CharUnits CurStructOffset
, std::array
<Address
, 2> Addrs
) {
681 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
682 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
683 llvm::Value
*SrcVal
= CGF
->EmitLoadOfScalar(
684 Addrs
[SrcIdx
], QT
.isVolatileQualified(), QT
, SourceLocation());
685 llvm::Value
*Val
= CGF
->EmitARCRetain(QT
, SrcVal
);
686 CGF
->EmitStoreOfScalar(Val
, CGF
->MakeAddrLValue(Addrs
[DstIdx
], QT
), true);
689 void visitARCWeak(QualType QT
, const FieldDecl
*FD
, CharUnits CurStructOffset
,
690 std::array
<Address
, 2> Addrs
) {
691 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
692 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
693 CGF
->EmitARCCopyWeak(Addrs
[DstIdx
], Addrs
[SrcIdx
]);
696 void callSpecialFunction(QualType FT
, CharUnits Offset
,
697 std::array
<Address
, 2> Addrs
) {
698 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], Offset
);
699 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], Offset
);
700 CGF
->callCStructCopyConstructor(CGF
->MakeAddrLValue(Addrs
[DstIdx
], FT
),
701 CGF
->MakeAddrLValue(Addrs
[SrcIdx
], FT
));
705 struct GenMoveConstructor
: GenBinaryFunc
<GenMoveConstructor
, true> {
706 GenMoveConstructor(ASTContext
&Ctx
)
707 : GenBinaryFunc
<GenMoveConstructor
, true>(Ctx
) {}
709 void visitARCStrong(QualType QT
, const FieldDecl
*FD
,
710 CharUnits CurStructOffset
, std::array
<Address
, 2> Addrs
) {
711 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
712 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
713 LValue SrcLV
= CGF
->MakeAddrLValue(Addrs
[SrcIdx
], QT
);
714 llvm::Value
*SrcVal
=
715 CGF
->EmitLoadOfLValue(SrcLV
, SourceLocation()).getScalarVal();
716 CGF
->EmitStoreOfScalar(getNullForVariable(SrcLV
.getAddress(*CGF
)), SrcLV
);
717 CGF
->EmitStoreOfScalar(SrcVal
, CGF
->MakeAddrLValue(Addrs
[DstIdx
], QT
),
718 /* isInitialization */ true);
721 void visitARCWeak(QualType QT
, const FieldDecl
*FD
, CharUnits CurStructOffset
,
722 std::array
<Address
, 2> Addrs
) {
723 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
724 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
725 CGF
->EmitARCMoveWeak(Addrs
[DstIdx
], Addrs
[SrcIdx
]);
728 void callSpecialFunction(QualType FT
, CharUnits Offset
,
729 std::array
<Address
, 2> Addrs
) {
730 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], Offset
);
731 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], Offset
);
732 CGF
->callCStructMoveConstructor(CGF
->MakeAddrLValue(Addrs
[DstIdx
], FT
),
733 CGF
->MakeAddrLValue(Addrs
[SrcIdx
], FT
));
737 struct GenCopyAssignment
: GenBinaryFunc
<GenCopyAssignment
, false> {
738 GenCopyAssignment(ASTContext
&Ctx
)
739 : GenBinaryFunc
<GenCopyAssignment
, false>(Ctx
) {}
741 void visitARCStrong(QualType QT
, const FieldDecl
*FD
,
742 CharUnits CurStructOffset
, std::array
<Address
, 2> Addrs
) {
743 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
744 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
745 llvm::Value
*SrcVal
= CGF
->EmitLoadOfScalar(
746 Addrs
[SrcIdx
], QT
.isVolatileQualified(), QT
, SourceLocation());
747 CGF
->EmitARCStoreStrong(CGF
->MakeAddrLValue(Addrs
[DstIdx
], QT
), SrcVal
,
751 void visitARCWeak(QualType QT
, const FieldDecl
*FD
, CharUnits CurStructOffset
,
752 std::array
<Address
, 2> Addrs
) {
753 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
754 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
755 CGF
->emitARCCopyAssignWeak(QT
, Addrs
[DstIdx
], Addrs
[SrcIdx
]);
758 void callSpecialFunction(QualType FT
, CharUnits Offset
,
759 std::array
<Address
, 2> Addrs
) {
760 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], Offset
);
761 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], Offset
);
762 CGF
->callCStructCopyAssignmentOperator(
763 CGF
->MakeAddrLValue(Addrs
[DstIdx
], FT
),
764 CGF
->MakeAddrLValue(Addrs
[SrcIdx
], FT
));
768 struct GenMoveAssignment
: GenBinaryFunc
<GenMoveAssignment
, true> {
769 GenMoveAssignment(ASTContext
&Ctx
)
770 : GenBinaryFunc
<GenMoveAssignment
, true>(Ctx
) {}
772 void visitARCStrong(QualType QT
, const FieldDecl
*FD
,
773 CharUnits CurStructOffset
, std::array
<Address
, 2> Addrs
) {
774 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
775 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
776 LValue SrcLV
= CGF
->MakeAddrLValue(Addrs
[SrcIdx
], QT
);
777 llvm::Value
*SrcVal
=
778 CGF
->EmitLoadOfLValue(SrcLV
, SourceLocation()).getScalarVal();
779 CGF
->EmitStoreOfScalar(getNullForVariable(SrcLV
.getAddress(*CGF
)), SrcLV
);
780 LValue DstLV
= CGF
->MakeAddrLValue(Addrs
[DstIdx
], QT
);
781 llvm::Value
*DstVal
=
782 CGF
->EmitLoadOfLValue(DstLV
, SourceLocation()).getScalarVal();
783 CGF
->EmitStoreOfScalar(SrcVal
, DstLV
);
784 CGF
->EmitARCRelease(DstVal
, ARCImpreciseLifetime
);
787 void visitARCWeak(QualType QT
, const FieldDecl
*FD
, CharUnits CurStructOffset
,
788 std::array
<Address
, 2> Addrs
) {
789 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
790 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
791 CGF
->emitARCMoveAssignWeak(QT
, Addrs
[DstIdx
], Addrs
[SrcIdx
]);
794 void callSpecialFunction(QualType FT
, CharUnits Offset
,
795 std::array
<Address
, 2> Addrs
) {
796 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], Offset
);
797 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], Offset
);
798 CGF
->callCStructMoveAssignmentOperator(
799 CGF
->MakeAddrLValue(Addrs
[DstIdx
], FT
),
800 CGF
->MakeAddrLValue(Addrs
[SrcIdx
], FT
));
806 void CodeGenFunction::destroyNonTrivialCStruct(CodeGenFunction
&CGF
,
807 Address Addr
, QualType Type
) {
808 CGF
.callCStructDestructor(CGF
.MakeAddrLValue(Addr
, Type
));
811 // Default-initialize a variable that is a non-trivial struct or an array of
813 void CodeGenFunction::defaultInitNonTrivialCStructVar(LValue Dst
) {
814 GenDefaultInitialize
Gen(getContext());
815 Address DstPtr
= Dst
.getAddress(*this).withElementType(CGM
.Int8PtrTy
);
817 QualType QT
= Dst
.getType();
818 QT
= Dst
.isVolatile() ? QT
.withVolatile() : QT
;
819 Gen
.visit(QT
, nullptr, CharUnits::Zero(), std::array
<Address
, 1>({{DstPtr
}}));
822 template <class G
, size_t N
>
823 static void callSpecialFunction(G
&&Gen
, StringRef FuncName
, QualType QT
,
824 bool IsVolatile
, CodeGenFunction
&CGF
,
825 std::array
<Address
, N
> Addrs
) {
826 auto SetArtificialLoc
= ApplyDebugLocation::CreateArtificial(CGF
);
827 for (unsigned I
= 0; I
< N
; ++I
)
828 Addrs
[I
] = Addrs
[I
].withElementType(CGF
.CGM
.Int8PtrTy
);
829 QT
= IsVolatile
? QT
.withVolatile() : QT
;
830 Gen
.callFunc(FuncName
, QT
, Addrs
, CGF
);
833 template <class G
, size_t N
>
834 static llvm::Function
*
835 getSpecialFunction(G
&&Gen
, StringRef FuncName
, QualType QT
, bool IsVolatile
,
836 std::array
<CharUnits
, N
> Alignments
, CodeGenModule
&CGM
) {
837 QT
= IsVolatile
? QT
.withVolatile() : QT
;
838 // The following call requires an array of addresses as arguments, but doesn't
839 // actually use them (it overwrites them with the addresses of the arguments
840 // of the created function).
841 return Gen
.getFunction(FuncName
, QT
, Alignments
, CGM
);
844 // Functions to emit calls to the special functions of a non-trivial C struct.
845 void CodeGenFunction::callCStructDefaultConstructor(LValue Dst
) {
846 bool IsVolatile
= Dst
.isVolatile();
847 Address DstPtr
= Dst
.getAddress(*this);
848 QualType QT
= Dst
.getType();
849 GenDefaultInitializeFuncName
GenName(DstPtr
.getAlignment(), getContext());
850 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
851 callSpecialFunction(GenDefaultInitialize(getContext()), FuncName
, QT
,
852 IsVolatile
, *this, std::array
<Address
, 1>({{DstPtr
}}));
855 std::string
CodeGenFunction::getNonTrivialCopyConstructorStr(
856 QualType QT
, CharUnits Alignment
, bool IsVolatile
, ASTContext
&Ctx
) {
857 GenBinaryFuncName
<false> GenName("", Alignment
, Alignment
, Ctx
);
858 return GenName
.getName(QT
, IsVolatile
);
861 std::string
CodeGenFunction::getNonTrivialDestructorStr(QualType QT
,
865 GenDestructorFuncName
GenName("", Alignment
, Ctx
);
866 return GenName
.getName(QT
, IsVolatile
);
869 void CodeGenFunction::callCStructDestructor(LValue Dst
) {
870 bool IsVolatile
= Dst
.isVolatile();
871 Address DstPtr
= Dst
.getAddress(*this);
872 QualType QT
= Dst
.getType();
873 GenDestructorFuncName
GenName("__destructor_", DstPtr
.getAlignment(),
875 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
876 callSpecialFunction(GenDestructor(getContext()), FuncName
, QT
, IsVolatile
,
877 *this, std::array
<Address
, 1>({{DstPtr
}}));
880 void CodeGenFunction::callCStructCopyConstructor(LValue Dst
, LValue Src
) {
881 bool IsVolatile
= Dst
.isVolatile() || Src
.isVolatile();
882 Address DstPtr
= Dst
.getAddress(*this), SrcPtr
= Src
.getAddress(*this);
883 QualType QT
= Dst
.getType();
884 GenBinaryFuncName
<false> GenName("__copy_constructor_", DstPtr
.getAlignment(),
885 SrcPtr
.getAlignment(), getContext());
886 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
887 callSpecialFunction(GenCopyConstructor(getContext()), FuncName
, QT
,
889 std::array
<Address
, 2>({{DstPtr
, SrcPtr
}}));
892 void CodeGenFunction::callCStructCopyAssignmentOperator(LValue Dst
, LValue Src
895 bool IsVolatile
= Dst
.isVolatile() || Src
.isVolatile();
896 Address DstPtr
= Dst
.getAddress(*this), SrcPtr
= Src
.getAddress(*this);
897 QualType QT
= Dst
.getType();
898 GenBinaryFuncName
<false> GenName("__copy_assignment_", DstPtr
.getAlignment(),
899 SrcPtr
.getAlignment(), getContext());
900 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
901 callSpecialFunction(GenCopyAssignment(getContext()), FuncName
, QT
, IsVolatile
,
902 *this, std::array
<Address
, 2>({{DstPtr
, SrcPtr
}}));
905 void CodeGenFunction::callCStructMoveConstructor(LValue Dst
, LValue Src
) {
906 bool IsVolatile
= Dst
.isVolatile() || Src
.isVolatile();
907 Address DstPtr
= Dst
.getAddress(*this), SrcPtr
= Src
.getAddress(*this);
908 QualType QT
= Dst
.getType();
909 GenBinaryFuncName
<true> GenName("__move_constructor_", DstPtr
.getAlignment(),
910 SrcPtr
.getAlignment(), getContext());
911 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
912 callSpecialFunction(GenMoveConstructor(getContext()), FuncName
, QT
,
914 std::array
<Address
, 2>({{DstPtr
, SrcPtr
}}));
917 void CodeGenFunction::callCStructMoveAssignmentOperator(LValue Dst
, LValue Src
920 bool IsVolatile
= Dst
.isVolatile() || Src
.isVolatile();
921 Address DstPtr
= Dst
.getAddress(*this), SrcPtr
= Src
.getAddress(*this);
922 QualType QT
= Dst
.getType();
923 GenBinaryFuncName
<true> GenName("__move_assignment_", DstPtr
.getAlignment(),
924 SrcPtr
.getAlignment(), getContext());
925 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
926 callSpecialFunction(GenMoveAssignment(getContext()), FuncName
, QT
, IsVolatile
,
927 *this, std::array
<Address
, 2>({{DstPtr
, SrcPtr
}}));
930 llvm::Function
*clang::CodeGen::getNonTrivialCStructDefaultConstructor(
931 CodeGenModule
&CGM
, CharUnits DstAlignment
, bool IsVolatile
, QualType QT
) {
932 ASTContext
&Ctx
= CGM
.getContext();
933 GenDefaultInitializeFuncName
GenName(DstAlignment
, Ctx
);
934 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
935 return getSpecialFunction(GenDefaultInitialize(Ctx
), FuncName
, QT
, IsVolatile
,
936 std::array
<CharUnits
, 1>({{DstAlignment
}}), CGM
);
939 llvm::Function
*clang::CodeGen::getNonTrivialCStructCopyConstructor(
940 CodeGenModule
&CGM
, CharUnits DstAlignment
, CharUnits SrcAlignment
,
941 bool IsVolatile
, QualType QT
) {
942 ASTContext
&Ctx
= CGM
.getContext();
943 GenBinaryFuncName
<false> GenName("__copy_constructor_", DstAlignment
,
945 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
946 return getSpecialFunction(
947 GenCopyConstructor(Ctx
), FuncName
, QT
, IsVolatile
,
948 std::array
<CharUnits
, 2>({{DstAlignment
, SrcAlignment
}}), CGM
);
951 llvm::Function
*clang::CodeGen::getNonTrivialCStructMoveConstructor(
952 CodeGenModule
&CGM
, CharUnits DstAlignment
, CharUnits SrcAlignment
,
953 bool IsVolatile
, QualType QT
) {
954 ASTContext
&Ctx
= CGM
.getContext();
955 GenBinaryFuncName
<true> GenName("__move_constructor_", DstAlignment
,
957 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
958 return getSpecialFunction(
959 GenMoveConstructor(Ctx
), FuncName
, QT
, IsVolatile
,
960 std::array
<CharUnits
, 2>({{DstAlignment
, SrcAlignment
}}), CGM
);
963 llvm::Function
*clang::CodeGen::getNonTrivialCStructCopyAssignmentOperator(
964 CodeGenModule
&CGM
, CharUnits DstAlignment
, CharUnits SrcAlignment
,
965 bool IsVolatile
, QualType QT
) {
966 ASTContext
&Ctx
= CGM
.getContext();
967 GenBinaryFuncName
<false> GenName("__copy_assignment_", DstAlignment
,
969 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
970 return getSpecialFunction(
971 GenCopyAssignment(Ctx
), FuncName
, QT
, IsVolatile
,
972 std::array
<CharUnits
, 2>({{DstAlignment
, SrcAlignment
}}), CGM
);
975 llvm::Function
*clang::CodeGen::getNonTrivialCStructMoveAssignmentOperator(
976 CodeGenModule
&CGM
, CharUnits DstAlignment
, CharUnits SrcAlignment
,
977 bool IsVolatile
, QualType QT
) {
978 ASTContext
&Ctx
= CGM
.getContext();
979 GenBinaryFuncName
<true> GenName("__move_assignment_", DstAlignment
,
981 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
982 return getSpecialFunction(
983 GenMoveAssignment(Ctx
), FuncName
, QT
, IsVolatile
,
984 std::array
<CharUnits
, 2>({{DstAlignment
, SrcAlignment
}}), CGM
);
987 llvm::Function
*clang::CodeGen::getNonTrivialCStructDestructor(
988 CodeGenModule
&CGM
, CharUnits DstAlignment
, bool IsVolatile
, QualType QT
) {
989 ASTContext
&Ctx
= CGM
.getContext();
990 GenDestructorFuncName
GenName("__destructor_", DstAlignment
, Ctx
);
991 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
992 return getSpecialFunction(GenDestructor(Ctx
), FuncName
, QT
, IsVolatile
,
993 std::array
<CharUnits
, 1>({{DstAlignment
}}), CGM
);