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 llvm::BasicBlock
*PreheaderBB
= CGF
.Builder
.GetInsertBlock();
372 // Create the header block and insert the phi instructions.
373 llvm::BasicBlock
*HeaderBB
= CGF
.createBasicBlock("loop.header");
374 CGF
.EmitBlock(HeaderBB
);
375 llvm::PHINode
*PHIs
[N
];
377 for (unsigned I
= 0; I
< N
; ++I
) {
378 PHIs
[I
] = CGF
.Builder
.CreatePHI(CGF
.CGM
.Int8PtrPtrTy
, 2, "addr.cur");
379 PHIs
[I
]->addIncoming(StartAddrs
[I
].getPointer(), PreheaderBB
);
382 // Create the exit and loop body blocks.
383 llvm::BasicBlock
*ExitBB
= CGF
.createBasicBlock("loop.exit");
384 llvm::BasicBlock
*LoopBB
= CGF
.createBasicBlock("loop.body");
386 // Emit the comparison and conditional branch instruction that jumps to
387 // either the exit or the loop body.
389 CGF
.Builder
.CreateICmpEQ(PHIs
[DstIdx
], DstArrayEnd
, "done");
390 CGF
.Builder
.CreateCondBr(Done
, ExitBB
, LoopBB
);
392 // Visit the element of the array in the loop body.
393 CGF
.EmitBlock(LoopBB
);
394 QualType EltQT
= AT
->getElementType();
395 CharUnits EltSize
= Ctx
.getTypeSizeInChars(EltQT
);
396 std::array
<Address
, N
> NewAddrs
= Addrs
;
398 for (unsigned I
= 0; I
< N
; ++I
)
400 Address(PHIs
[I
], CGF
.Int8PtrTy
,
401 StartAddrs
[I
].getAlignment().alignmentAtOffset(EltSize
));
403 EltQT
= IsVolatile
? EltQT
.withVolatile() : EltQT
;
404 this->asDerived().visitWithKind(FK
, EltQT
, nullptr, CharUnits::Zero(),
407 LoopBB
= CGF
.Builder
.GetInsertBlock();
409 for (unsigned I
= 0; I
< N
; ++I
) {
410 // Instrs to update the destination and source addresses.
411 // Update phi instructions.
412 NewAddrs
[I
] = getAddrWithOffset(NewAddrs
[I
], EltSize
);
413 PHIs
[I
]->addIncoming(NewAddrs
[I
].getPointer(), LoopBB
);
416 // Insert an unconditional branch to the header block.
417 CGF
.Builder
.CreateBr(HeaderBB
);
418 CGF
.EmitBlock(ExitBB
);
421 /// Return an address with the specified offset from the passed address.
422 Address
getAddrWithOffset(Address Addr
, CharUnits Offset
) {
423 assert(Addr
.isValid() && "invalid address");
424 if (Offset
.getQuantity() == 0)
426 Addr
= Addr
.withElementType(CGF
->CGM
.Int8Ty
);
427 Addr
= CGF
->Builder
.CreateConstInBoundsGEP(Addr
, Offset
.getQuantity());
428 return Addr
.withElementType(CGF
->CGM
.Int8PtrTy
);
431 Address
getAddrWithOffset(Address Addr
, CharUnits StructFieldOffset
,
432 const FieldDecl
*FD
) {
433 return getAddrWithOffset(Addr
, StructFieldOffset
+
434 asDerived().getFieldOffset(FD
));
438 llvm::Function
*getFunction(StringRef FuncName
, QualType QT
,
439 std::array
<CharUnits
, N
> Alignments
,
440 CodeGenModule
&CGM
) {
441 // If the special function already exists in the module, return it.
442 if (llvm::Function
*F
= CGM
.getModule().getFunction(FuncName
)) {
443 bool WrongType
= false;
444 if (!F
->getReturnType()->isVoidTy())
447 for (const llvm::Argument
&Arg
: F
->args())
448 if (Arg
.getType() != CGM
.Int8PtrPtrTy
)
453 std::string FuncName
= std::string(F
->getName());
454 SourceLocation Loc
= QT
->castAs
<RecordType
>()->getDecl()->getLocation();
455 CGM
.Error(Loc
, "special function " + FuncName
+
456 " for non-trivial C struct has incorrect type");
462 ASTContext
&Ctx
= CGM
.getContext();
463 FunctionArgList Args
;
464 const CGFunctionInfo
&FI
= getFunctionInfo
<N
>(CGM
, Args
);
465 llvm::FunctionType
*FuncTy
= CGM
.getTypes().GetFunctionType(FI
);
467 llvm::Function::Create(FuncTy
, llvm::GlobalValue::LinkOnceODRLinkage
,
468 FuncName
, &CGM
.getModule());
469 F
->setVisibility(llvm::GlobalValue::HiddenVisibility
);
470 CGM
.SetLLVMFunctionAttributes(GlobalDecl(), FI
, F
, /*IsThunk=*/false);
471 CGM
.SetLLVMFunctionAttributesForDefinition(nullptr, F
);
472 CodeGenFunction
NewCGF(CGM
);
474 CGF
->StartFunction(GlobalDecl(), Ctx
.VoidTy
, F
, FI
, Args
);
475 auto AL
= ApplyDebugLocation::CreateArtificial(*CGF
);
476 std::array
<Address
, N
> Addrs
=
477 getParamAddrs
<N
>(std::make_index_sequence
<N
>{}, Alignments
, Args
, CGF
);
478 asDerived().visitStructFields(QT
, CharUnits::Zero(), Addrs
);
479 CGF
->FinishFunction();
484 void callFunc(StringRef FuncName
, QualType QT
, std::array
<Address
, N
> Addrs
,
485 CodeGenFunction
&CallerCGF
) {
486 std::array
<CharUnits
, N
> Alignments
;
487 llvm::Value
*Ptrs
[N
];
489 for (unsigned I
= 0; I
< N
; ++I
) {
490 Alignments
[I
] = Addrs
[I
].getAlignment();
491 Ptrs
[I
] = Addrs
[I
].getPointer();
494 if (llvm::Function
*F
=
495 getFunction(FuncName
, QT
, Alignments
, CallerCGF
.CGM
))
496 CallerCGF
.EmitNounwindRuntimeCall(F
, Ptrs
);
499 Derived
&asDerived() { return static_cast<Derived
&>(*this); }
501 void setCGF(CodeGenFunction
*F
) { CGF
= F
; }
503 CodeGenFunction
*CGF
= nullptr;
506 template <class Derived
, bool IsMove
>
507 struct GenBinaryFunc
: CopyStructVisitor
<Derived
, IsMove
>,
508 GenFuncBase
<Derived
> {
509 GenBinaryFunc(ASTContext
&Ctx
) : CopyStructVisitor
<Derived
, IsMove
>(Ctx
) {}
511 void flushTrivialFields(std::array
<Address
, 2> Addrs
) {
512 CharUnits Size
= this->End
- this->Start
;
514 if (Size
.getQuantity() == 0)
517 Address DstAddr
= this->getAddrWithOffset(Addrs
[DstIdx
], this->Start
);
518 Address SrcAddr
= this->getAddrWithOffset(Addrs
[SrcIdx
], this->Start
);
521 if (Size
.getQuantity() >= 16 ||
522 !llvm::has_single_bit
<uint32_t>(Size
.getQuantity())) {
523 llvm::Value
*SizeVal
=
524 llvm::ConstantInt::get(this->CGF
->SizeTy
, Size
.getQuantity());
525 DstAddr
= DstAddr
.withElementType(this->CGF
->Int8Ty
);
526 SrcAddr
= SrcAddr
.withElementType(this->CGF
->Int8Ty
);
527 this->CGF
->Builder
.CreateMemCpy(DstAddr
, SrcAddr
, SizeVal
, false);
529 llvm::Type
*Ty
= llvm::Type::getIntNTy(
530 this->CGF
->getLLVMContext(),
531 Size
.getQuantity() * this->CGF
->getContext().getCharWidth());
532 DstAddr
= DstAddr
.withElementType(Ty
);
533 SrcAddr
= SrcAddr
.withElementType(Ty
);
534 llvm::Value
*SrcVal
= this->CGF
->Builder
.CreateLoad(SrcAddr
, false);
535 this->CGF
->Builder
.CreateStore(SrcVal
, DstAddr
, false);
538 this->Start
= this->End
= CharUnits::Zero();
541 template <class... Ts
>
542 void visitVolatileTrivial(QualType FT
, const FieldDecl
*FD
, CharUnits Offset
,
543 std::array
<Address
, 2> Addrs
) {
546 // No need to copy zero-length bit-fields.
547 if (FD
->isZeroLengthBitField(this->CGF
->getContext()))
550 QualType RT
= QualType(FD
->getParent()->getTypeForDecl(), 0);
551 llvm::Type
*Ty
= this->CGF
->ConvertType(RT
);
552 Address DstAddr
= this->getAddrWithOffset(Addrs
[DstIdx
], Offset
);
554 this->CGF
->MakeAddrLValue(DstAddr
.withElementType(Ty
), FT
);
555 DstLV
= this->CGF
->EmitLValueForField(DstBase
, FD
);
556 Address SrcAddr
= this->getAddrWithOffset(Addrs
[SrcIdx
], Offset
);
558 this->CGF
->MakeAddrLValue(SrcAddr
.withElementType(Ty
), FT
);
559 SrcLV
= this->CGF
->EmitLValueForField(SrcBase
, FD
);
561 llvm::Type
*Ty
= this->CGF
->ConvertTypeForMem(FT
);
562 Address DstAddr
= Addrs
[DstIdx
].withElementType(Ty
);
563 Address SrcAddr
= Addrs
[SrcIdx
].withElementType(Ty
);
564 DstLV
= this->CGF
->MakeAddrLValue(DstAddr
, FT
);
565 SrcLV
= this->CGF
->MakeAddrLValue(SrcAddr
, FT
);
567 RValue SrcVal
= this->CGF
->EmitLoadOfLValue(SrcLV
, SourceLocation());
568 this->CGF
->EmitStoreThroughLValue(SrcVal
, DstLV
);
572 // These classes that emit the special functions for a non-trivial struct.
573 struct GenDestructor
: StructVisitor
<GenDestructor
>,
574 GenFuncBase
<GenDestructor
>,
575 DestructedTypeVisitor
<GenDestructor
> {
576 using Super
= DestructedTypeVisitor
<GenDestructor
>;
577 GenDestructor(ASTContext
&Ctx
) : StructVisitor
<GenDestructor
>(Ctx
) {}
579 void visitWithKind(QualType::DestructionKind DK
, QualType FT
,
580 const FieldDecl
*FD
, CharUnits CurStructOffset
,
581 std::array
<Address
, 1> Addrs
) {
582 if (const auto *AT
= getContext().getAsArrayType(FT
)) {
583 visitArray(DK
, AT
, FT
.isVolatileQualified(), FD
, CurStructOffset
, Addrs
);
587 Super::visitWithKind(DK
, FT
, FD
, CurStructOffset
, Addrs
);
590 void visitARCStrong(QualType QT
, const FieldDecl
*FD
,
591 CharUnits CurStructOffset
, std::array
<Address
, 1> Addrs
) {
592 CGF
->destroyARCStrongImprecise(
593 *CGF
, getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
), QT
);
596 void visitARCWeak(QualType QT
, const FieldDecl
*FD
, CharUnits CurStructOffset
,
597 std::array
<Address
, 1> Addrs
) {
599 *CGF
, getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
), QT
);
602 void callSpecialFunction(QualType FT
, CharUnits Offset
,
603 std::array
<Address
, 1> Addrs
) {
604 CGF
->callCStructDestructor(
605 CGF
->MakeAddrLValue(getAddrWithOffset(Addrs
[DstIdx
], Offset
), FT
));
609 struct GenDefaultInitialize
610 : StructVisitor
<GenDefaultInitialize
>,
611 GenFuncBase
<GenDefaultInitialize
>,
612 DefaultInitializedTypeVisitor
<GenDefaultInitialize
> {
613 using Super
= DefaultInitializedTypeVisitor
<GenDefaultInitialize
>;
614 typedef GenFuncBase
<GenDefaultInitialize
> GenFuncBaseTy
;
616 GenDefaultInitialize(ASTContext
&Ctx
)
617 : StructVisitor
<GenDefaultInitialize
>(Ctx
) {}
619 void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK
, QualType FT
,
620 const FieldDecl
*FD
, CharUnits CurStructOffset
,
621 std::array
<Address
, 1> Addrs
) {
622 if (const auto *AT
= getContext().getAsArrayType(FT
)) {
623 visitArray(PDIK
, AT
, FT
.isVolatileQualified(), FD
, CurStructOffset
,
628 Super::visitWithKind(PDIK
, FT
, FD
, CurStructOffset
, Addrs
);
631 void visitARCStrong(QualType QT
, const FieldDecl
*FD
,
632 CharUnits CurStructOffset
, std::array
<Address
, 1> Addrs
) {
633 CGF
->EmitNullInitialization(
634 getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
), QT
);
637 void visitARCWeak(QualType QT
, const FieldDecl
*FD
, CharUnits CurStructOffset
,
638 std::array
<Address
, 1> Addrs
) {
639 CGF
->EmitNullInitialization(
640 getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
), QT
);
643 template <class FieldKind
, size_t... Is
>
644 void visitArray(FieldKind FK
, const ArrayType
*AT
, bool IsVolatile
,
645 const FieldDecl
*FD
, CharUnits CurStructOffset
,
646 std::array
<Address
, 1> Addrs
) {
648 return visitTrivial(QualType(AT
, 0), FD
, CurStructOffset
, Addrs
);
650 ASTContext
&Ctx
= getContext();
651 CharUnits Size
= Ctx
.getTypeSizeInChars(QualType(AT
, 0));
652 QualType EltTy
= Ctx
.getBaseElementType(QualType(AT
, 0));
654 if (Size
< CharUnits::fromQuantity(16) || EltTy
->getAs
<RecordType
>()) {
655 GenFuncBaseTy::visitArray(FK
, AT
, IsVolatile
, FD
, CurStructOffset
, Addrs
);
659 llvm::Constant
*SizeVal
= CGF
->Builder
.getInt64(Size
.getQuantity());
660 Address DstAddr
= getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
661 Address Loc
= DstAddr
.withElementType(CGF
->Int8Ty
);
662 CGF
->Builder
.CreateMemSet(Loc
, CGF
->Builder
.getInt8(0), SizeVal
,
666 void callSpecialFunction(QualType FT
, CharUnits Offset
,
667 std::array
<Address
, 1> Addrs
) {
668 CGF
->callCStructDefaultConstructor(
669 CGF
->MakeAddrLValue(getAddrWithOffset(Addrs
[DstIdx
], Offset
), FT
));
673 struct GenCopyConstructor
: GenBinaryFunc
<GenCopyConstructor
, false> {
674 GenCopyConstructor(ASTContext
&Ctx
)
675 : GenBinaryFunc
<GenCopyConstructor
, false>(Ctx
) {}
677 void visitARCStrong(QualType QT
, const FieldDecl
*FD
,
678 CharUnits CurStructOffset
, std::array
<Address
, 2> Addrs
) {
679 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
680 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
681 llvm::Value
*SrcVal
= CGF
->EmitLoadOfScalar(
682 Addrs
[SrcIdx
], QT
.isVolatileQualified(), QT
, SourceLocation());
683 llvm::Value
*Val
= CGF
->EmitARCRetain(QT
, SrcVal
);
684 CGF
->EmitStoreOfScalar(Val
, CGF
->MakeAddrLValue(Addrs
[DstIdx
], QT
), true);
687 void visitARCWeak(QualType QT
, const FieldDecl
*FD
, CharUnits CurStructOffset
,
688 std::array
<Address
, 2> Addrs
) {
689 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
690 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
691 CGF
->EmitARCCopyWeak(Addrs
[DstIdx
], Addrs
[SrcIdx
]);
694 void callSpecialFunction(QualType FT
, CharUnits Offset
,
695 std::array
<Address
, 2> Addrs
) {
696 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], Offset
);
697 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], Offset
);
698 CGF
->callCStructCopyConstructor(CGF
->MakeAddrLValue(Addrs
[DstIdx
], FT
),
699 CGF
->MakeAddrLValue(Addrs
[SrcIdx
], FT
));
703 struct GenMoveConstructor
: GenBinaryFunc
<GenMoveConstructor
, true> {
704 GenMoveConstructor(ASTContext
&Ctx
)
705 : GenBinaryFunc
<GenMoveConstructor
, true>(Ctx
) {}
707 void visitARCStrong(QualType QT
, const FieldDecl
*FD
,
708 CharUnits CurStructOffset
, std::array
<Address
, 2> Addrs
) {
709 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
710 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
711 LValue SrcLV
= CGF
->MakeAddrLValue(Addrs
[SrcIdx
], QT
);
712 llvm::Value
*SrcVal
=
713 CGF
->EmitLoadOfLValue(SrcLV
, SourceLocation()).getScalarVal();
714 CGF
->EmitStoreOfScalar(getNullForVariable(SrcLV
.getAddress(*CGF
)), SrcLV
);
715 CGF
->EmitStoreOfScalar(SrcVal
, CGF
->MakeAddrLValue(Addrs
[DstIdx
], QT
),
716 /* isInitialization */ true);
719 void visitARCWeak(QualType QT
, const FieldDecl
*FD
, CharUnits CurStructOffset
,
720 std::array
<Address
, 2> Addrs
) {
721 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
722 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
723 CGF
->EmitARCMoveWeak(Addrs
[DstIdx
], Addrs
[SrcIdx
]);
726 void callSpecialFunction(QualType FT
, CharUnits Offset
,
727 std::array
<Address
, 2> Addrs
) {
728 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], Offset
);
729 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], Offset
);
730 CGF
->callCStructMoveConstructor(CGF
->MakeAddrLValue(Addrs
[DstIdx
], FT
),
731 CGF
->MakeAddrLValue(Addrs
[SrcIdx
], FT
));
735 struct GenCopyAssignment
: GenBinaryFunc
<GenCopyAssignment
, false> {
736 GenCopyAssignment(ASTContext
&Ctx
)
737 : GenBinaryFunc
<GenCopyAssignment
, false>(Ctx
) {}
739 void visitARCStrong(QualType QT
, const FieldDecl
*FD
,
740 CharUnits CurStructOffset
, std::array
<Address
, 2> Addrs
) {
741 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
742 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
743 llvm::Value
*SrcVal
= CGF
->EmitLoadOfScalar(
744 Addrs
[SrcIdx
], QT
.isVolatileQualified(), QT
, SourceLocation());
745 CGF
->EmitARCStoreStrong(CGF
->MakeAddrLValue(Addrs
[DstIdx
], QT
), SrcVal
,
749 void visitARCWeak(QualType QT
, const FieldDecl
*FD
, CharUnits CurStructOffset
,
750 std::array
<Address
, 2> Addrs
) {
751 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
752 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
753 CGF
->emitARCCopyAssignWeak(QT
, Addrs
[DstIdx
], Addrs
[SrcIdx
]);
756 void callSpecialFunction(QualType FT
, CharUnits Offset
,
757 std::array
<Address
, 2> Addrs
) {
758 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], Offset
);
759 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], Offset
);
760 CGF
->callCStructCopyAssignmentOperator(
761 CGF
->MakeAddrLValue(Addrs
[DstIdx
], FT
),
762 CGF
->MakeAddrLValue(Addrs
[SrcIdx
], FT
));
766 struct GenMoveAssignment
: GenBinaryFunc
<GenMoveAssignment
, true> {
767 GenMoveAssignment(ASTContext
&Ctx
)
768 : GenBinaryFunc
<GenMoveAssignment
, true>(Ctx
) {}
770 void visitARCStrong(QualType QT
, const FieldDecl
*FD
,
771 CharUnits CurStructOffset
, std::array
<Address
, 2> Addrs
) {
772 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
773 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
774 LValue SrcLV
= CGF
->MakeAddrLValue(Addrs
[SrcIdx
], QT
);
775 llvm::Value
*SrcVal
=
776 CGF
->EmitLoadOfLValue(SrcLV
, SourceLocation()).getScalarVal();
777 CGF
->EmitStoreOfScalar(getNullForVariable(SrcLV
.getAddress(*CGF
)), SrcLV
);
778 LValue DstLV
= CGF
->MakeAddrLValue(Addrs
[DstIdx
], QT
);
779 llvm::Value
*DstVal
=
780 CGF
->EmitLoadOfLValue(DstLV
, SourceLocation()).getScalarVal();
781 CGF
->EmitStoreOfScalar(SrcVal
, DstLV
);
782 CGF
->EmitARCRelease(DstVal
, ARCImpreciseLifetime
);
785 void visitARCWeak(QualType QT
, const FieldDecl
*FD
, CharUnits CurStructOffset
,
786 std::array
<Address
, 2> Addrs
) {
787 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
788 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
789 CGF
->emitARCMoveAssignWeak(QT
, Addrs
[DstIdx
], Addrs
[SrcIdx
]);
792 void callSpecialFunction(QualType FT
, CharUnits Offset
,
793 std::array
<Address
, 2> Addrs
) {
794 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], Offset
);
795 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], Offset
);
796 CGF
->callCStructMoveAssignmentOperator(
797 CGF
->MakeAddrLValue(Addrs
[DstIdx
], FT
),
798 CGF
->MakeAddrLValue(Addrs
[SrcIdx
], FT
));
804 void CodeGenFunction::destroyNonTrivialCStruct(CodeGenFunction
&CGF
,
805 Address Addr
, QualType Type
) {
806 CGF
.callCStructDestructor(CGF
.MakeAddrLValue(Addr
, Type
));
809 // Default-initialize a variable that is a non-trivial struct or an array of
811 void CodeGenFunction::defaultInitNonTrivialCStructVar(LValue Dst
) {
812 GenDefaultInitialize
Gen(getContext());
813 Address DstPtr
= Dst
.getAddress(*this).withElementType(CGM
.Int8PtrTy
);
815 QualType QT
= Dst
.getType();
816 QT
= Dst
.isVolatile() ? QT
.withVolatile() : QT
;
817 Gen
.visit(QT
, nullptr, CharUnits::Zero(), std::array
<Address
, 1>({{DstPtr
}}));
820 template <class G
, size_t N
>
821 static void callSpecialFunction(G
&&Gen
, StringRef FuncName
, QualType QT
,
822 bool IsVolatile
, CodeGenFunction
&CGF
,
823 std::array
<Address
, N
> Addrs
) {
824 auto SetArtificialLoc
= ApplyDebugLocation::CreateArtificial(CGF
);
825 for (unsigned I
= 0; I
< N
; ++I
)
826 Addrs
[I
] = Addrs
[I
].withElementType(CGF
.CGM
.Int8PtrTy
);
827 QT
= IsVolatile
? QT
.withVolatile() : QT
;
828 Gen
.callFunc(FuncName
, QT
, Addrs
, CGF
);
831 template <class G
, size_t N
>
832 static llvm::Function
*
833 getSpecialFunction(G
&&Gen
, StringRef FuncName
, QualType QT
, bool IsVolatile
,
834 std::array
<CharUnits
, N
> Alignments
, CodeGenModule
&CGM
) {
835 QT
= IsVolatile
? QT
.withVolatile() : QT
;
836 // The following call requires an array of addresses as arguments, but doesn't
837 // actually use them (it overwrites them with the addresses of the arguments
838 // of the created function).
839 return Gen
.getFunction(FuncName
, QT
, Alignments
, CGM
);
842 // Functions to emit calls to the special functions of a non-trivial C struct.
843 void CodeGenFunction::callCStructDefaultConstructor(LValue Dst
) {
844 bool IsVolatile
= Dst
.isVolatile();
845 Address DstPtr
= Dst
.getAddress(*this);
846 QualType QT
= Dst
.getType();
847 GenDefaultInitializeFuncName
GenName(DstPtr
.getAlignment(), getContext());
848 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
849 callSpecialFunction(GenDefaultInitialize(getContext()), FuncName
, QT
,
850 IsVolatile
, *this, std::array
<Address
, 1>({{DstPtr
}}));
853 std::string
CodeGenFunction::getNonTrivialCopyConstructorStr(
854 QualType QT
, CharUnits Alignment
, bool IsVolatile
, ASTContext
&Ctx
) {
855 GenBinaryFuncName
<false> GenName("", Alignment
, Alignment
, Ctx
);
856 return GenName
.getName(QT
, IsVolatile
);
859 std::string
CodeGenFunction::getNonTrivialDestructorStr(QualType QT
,
863 GenDestructorFuncName
GenName("", Alignment
, Ctx
);
864 return GenName
.getName(QT
, IsVolatile
);
867 void CodeGenFunction::callCStructDestructor(LValue Dst
) {
868 bool IsVolatile
= Dst
.isVolatile();
869 Address DstPtr
= Dst
.getAddress(*this);
870 QualType QT
= Dst
.getType();
871 GenDestructorFuncName
GenName("__destructor_", DstPtr
.getAlignment(),
873 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
874 callSpecialFunction(GenDestructor(getContext()), FuncName
, QT
, IsVolatile
,
875 *this, std::array
<Address
, 1>({{DstPtr
}}));
878 void CodeGenFunction::callCStructCopyConstructor(LValue Dst
, LValue Src
) {
879 bool IsVolatile
= Dst
.isVolatile() || Src
.isVolatile();
880 Address DstPtr
= Dst
.getAddress(*this), SrcPtr
= Src
.getAddress(*this);
881 QualType QT
= Dst
.getType();
882 GenBinaryFuncName
<false> GenName("__copy_constructor_", DstPtr
.getAlignment(),
883 SrcPtr
.getAlignment(), getContext());
884 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
885 callSpecialFunction(GenCopyConstructor(getContext()), FuncName
, QT
,
887 std::array
<Address
, 2>({{DstPtr
, SrcPtr
}}));
890 void CodeGenFunction::callCStructCopyAssignmentOperator(LValue Dst
, LValue Src
893 bool IsVolatile
= Dst
.isVolatile() || Src
.isVolatile();
894 Address DstPtr
= Dst
.getAddress(*this), SrcPtr
= Src
.getAddress(*this);
895 QualType QT
= Dst
.getType();
896 GenBinaryFuncName
<false> GenName("__copy_assignment_", DstPtr
.getAlignment(),
897 SrcPtr
.getAlignment(), getContext());
898 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
899 callSpecialFunction(GenCopyAssignment(getContext()), FuncName
, QT
, IsVolatile
,
900 *this, std::array
<Address
, 2>({{DstPtr
, SrcPtr
}}));
903 void CodeGenFunction::callCStructMoveConstructor(LValue Dst
, LValue Src
) {
904 bool IsVolatile
= Dst
.isVolatile() || Src
.isVolatile();
905 Address DstPtr
= Dst
.getAddress(*this), SrcPtr
= Src
.getAddress(*this);
906 QualType QT
= Dst
.getType();
907 GenBinaryFuncName
<true> GenName("__move_constructor_", DstPtr
.getAlignment(),
908 SrcPtr
.getAlignment(), getContext());
909 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
910 callSpecialFunction(GenMoveConstructor(getContext()), FuncName
, QT
,
912 std::array
<Address
, 2>({{DstPtr
, SrcPtr
}}));
915 void CodeGenFunction::callCStructMoveAssignmentOperator(LValue Dst
, LValue Src
918 bool IsVolatile
= Dst
.isVolatile() || Src
.isVolatile();
919 Address DstPtr
= Dst
.getAddress(*this), SrcPtr
= Src
.getAddress(*this);
920 QualType QT
= Dst
.getType();
921 GenBinaryFuncName
<true> GenName("__move_assignment_", DstPtr
.getAlignment(),
922 SrcPtr
.getAlignment(), getContext());
923 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
924 callSpecialFunction(GenMoveAssignment(getContext()), FuncName
, QT
, IsVolatile
,
925 *this, std::array
<Address
, 2>({{DstPtr
, SrcPtr
}}));
928 llvm::Function
*clang::CodeGen::getNonTrivialCStructDefaultConstructor(
929 CodeGenModule
&CGM
, CharUnits DstAlignment
, bool IsVolatile
, QualType QT
) {
930 ASTContext
&Ctx
= CGM
.getContext();
931 GenDefaultInitializeFuncName
GenName(DstAlignment
, Ctx
);
932 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
933 return getSpecialFunction(GenDefaultInitialize(Ctx
), FuncName
, QT
, IsVolatile
,
934 std::array
<CharUnits
, 1>({{DstAlignment
}}), CGM
);
937 llvm::Function
*clang::CodeGen::getNonTrivialCStructCopyConstructor(
938 CodeGenModule
&CGM
, CharUnits DstAlignment
, CharUnits SrcAlignment
,
939 bool IsVolatile
, QualType QT
) {
940 ASTContext
&Ctx
= CGM
.getContext();
941 GenBinaryFuncName
<false> GenName("__copy_constructor_", DstAlignment
,
943 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
944 return getSpecialFunction(
945 GenCopyConstructor(Ctx
), FuncName
, QT
, IsVolatile
,
946 std::array
<CharUnits
, 2>({{DstAlignment
, SrcAlignment
}}), CGM
);
949 llvm::Function
*clang::CodeGen::getNonTrivialCStructMoveConstructor(
950 CodeGenModule
&CGM
, CharUnits DstAlignment
, CharUnits SrcAlignment
,
951 bool IsVolatile
, QualType QT
) {
952 ASTContext
&Ctx
= CGM
.getContext();
953 GenBinaryFuncName
<true> GenName("__move_constructor_", DstAlignment
,
955 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
956 return getSpecialFunction(
957 GenMoveConstructor(Ctx
), FuncName
, QT
, IsVolatile
,
958 std::array
<CharUnits
, 2>({{DstAlignment
, SrcAlignment
}}), CGM
);
961 llvm::Function
*clang::CodeGen::getNonTrivialCStructCopyAssignmentOperator(
962 CodeGenModule
&CGM
, CharUnits DstAlignment
, CharUnits SrcAlignment
,
963 bool IsVolatile
, QualType QT
) {
964 ASTContext
&Ctx
= CGM
.getContext();
965 GenBinaryFuncName
<false> GenName("__copy_assignment_", DstAlignment
,
967 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
968 return getSpecialFunction(
969 GenCopyAssignment(Ctx
), FuncName
, QT
, IsVolatile
,
970 std::array
<CharUnits
, 2>({{DstAlignment
, SrcAlignment
}}), CGM
);
973 llvm::Function
*clang::CodeGen::getNonTrivialCStructMoveAssignmentOperator(
974 CodeGenModule
&CGM
, CharUnits DstAlignment
, CharUnits SrcAlignment
,
975 bool IsVolatile
, QualType QT
) {
976 ASTContext
&Ctx
= CGM
.getContext();
977 GenBinaryFuncName
<true> GenName("__move_assignment_", DstAlignment
,
979 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
980 return getSpecialFunction(
981 GenMoveAssignment(Ctx
), FuncName
, QT
, IsVolatile
,
982 std::array
<CharUnits
, 2>({{DstAlignment
, SrcAlignment
}}), CGM
);
985 llvm::Function
*clang::CodeGen::getNonTrivialCStructDestructor(
986 CodeGenModule
&CGM
, CharUnits DstAlignment
, bool IsVolatile
, QualType QT
) {
987 ASTContext
&Ctx
= CGM
.getContext();
988 GenDestructorFuncName
GenName("__destructor_", DstAlignment
, Ctx
);
989 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
990 return getSpecialFunction(GenDestructor(Ctx
), FuncName
, QT
, IsVolatile
,
991 std::array
<CharUnits
, 1>({{DstAlignment
}}), CGM
);