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 Address BC
= CGF
.Builder
.CreateElementBitCast(DstAddr
, CGF
.CGM
.Int8Ty
);
369 llvm::Value
*DstArrayEnd
=
370 CGF
.Builder
.CreateInBoundsGEP(CGF
.Int8Ty
, BC
.getPointer(), SizeInBytes
);
371 DstArrayEnd
= CGF
.Builder
.CreateBitCast(
372 DstArrayEnd
, CGF
.CGM
.Int8PtrPtrTy
, "dstarray.end");
373 llvm::BasicBlock
*PreheaderBB
= CGF
.Builder
.GetInsertBlock();
375 // Create the header block and insert the phi instructions.
376 llvm::BasicBlock
*HeaderBB
= CGF
.createBasicBlock("loop.header");
377 CGF
.EmitBlock(HeaderBB
);
378 llvm::PHINode
*PHIs
[N
];
380 for (unsigned I
= 0; I
< N
; ++I
) {
381 PHIs
[I
] = CGF
.Builder
.CreatePHI(CGF
.CGM
.Int8PtrPtrTy
, 2, "addr.cur");
382 PHIs
[I
]->addIncoming(StartAddrs
[I
].getPointer(), PreheaderBB
);
385 // Create the exit and loop body blocks.
386 llvm::BasicBlock
*ExitBB
= CGF
.createBasicBlock("loop.exit");
387 llvm::BasicBlock
*LoopBB
= CGF
.createBasicBlock("loop.body");
389 // Emit the comparison and conditional branch instruction that jumps to
390 // either the exit or the loop body.
392 CGF
.Builder
.CreateICmpEQ(PHIs
[DstIdx
], DstArrayEnd
, "done");
393 CGF
.Builder
.CreateCondBr(Done
, ExitBB
, LoopBB
);
395 // Visit the element of the array in the loop body.
396 CGF
.EmitBlock(LoopBB
);
397 QualType EltQT
= AT
->getElementType();
398 CharUnits EltSize
= Ctx
.getTypeSizeInChars(EltQT
);
399 std::array
<Address
, N
> NewAddrs
= Addrs
;
401 for (unsigned I
= 0; I
< N
; ++I
)
403 Address(PHIs
[I
], CGF
.Int8PtrTy
,
404 StartAddrs
[I
].getAlignment().alignmentAtOffset(EltSize
));
406 EltQT
= IsVolatile
? EltQT
.withVolatile() : EltQT
;
407 this->asDerived().visitWithKind(FK
, EltQT
, nullptr, CharUnits::Zero(),
410 LoopBB
= CGF
.Builder
.GetInsertBlock();
412 for (unsigned I
= 0; I
< N
; ++I
) {
413 // Instrs to update the destination and source addresses.
414 // Update phi instructions.
415 NewAddrs
[I
] = getAddrWithOffset(NewAddrs
[I
], EltSize
);
416 PHIs
[I
]->addIncoming(NewAddrs
[I
].getPointer(), LoopBB
);
419 // Insert an unconditional branch to the header block.
420 CGF
.Builder
.CreateBr(HeaderBB
);
421 CGF
.EmitBlock(ExitBB
);
424 /// Return an address with the specified offset from the passed address.
425 Address
getAddrWithOffset(Address Addr
, CharUnits Offset
) {
426 assert(Addr
.isValid() && "invalid address");
427 if (Offset
.getQuantity() == 0)
429 Addr
= CGF
->Builder
.CreateElementBitCast(Addr
, CGF
->CGM
.Int8Ty
);
430 Addr
= CGF
->Builder
.CreateConstInBoundsGEP(Addr
, Offset
.getQuantity());
431 return CGF
->Builder
.CreateElementBitCast(Addr
, CGF
->CGM
.Int8PtrTy
);
434 Address
getAddrWithOffset(Address Addr
, CharUnits StructFieldOffset
,
435 const FieldDecl
*FD
) {
436 return getAddrWithOffset(Addr
, StructFieldOffset
+
437 asDerived().getFieldOffset(FD
));
441 llvm::Function
*getFunction(StringRef FuncName
, QualType QT
,
442 std::array
<CharUnits
, N
> Alignments
,
443 CodeGenModule
&CGM
) {
444 // If the special function already exists in the module, return it.
445 if (llvm::Function
*F
= CGM
.getModule().getFunction(FuncName
)) {
446 bool WrongType
= false;
447 if (!F
->getReturnType()->isVoidTy())
450 for (const llvm::Argument
&Arg
: F
->args())
451 if (Arg
.getType() != CGM
.Int8PtrPtrTy
)
456 std::string FuncName
= std::string(F
->getName());
457 SourceLocation Loc
= QT
->castAs
<RecordType
>()->getDecl()->getLocation();
458 CGM
.Error(Loc
, "special function " + FuncName
+
459 " for non-trivial C struct has incorrect type");
465 ASTContext
&Ctx
= CGM
.getContext();
466 FunctionArgList Args
;
467 const CGFunctionInfo
&FI
= getFunctionInfo
<N
>(CGM
, Args
);
468 llvm::FunctionType
*FuncTy
= CGM
.getTypes().GetFunctionType(FI
);
470 llvm::Function::Create(FuncTy
, llvm::GlobalValue::LinkOnceODRLinkage
,
471 FuncName
, &CGM
.getModule());
472 F
->setVisibility(llvm::GlobalValue::HiddenVisibility
);
473 CGM
.SetLLVMFunctionAttributes(GlobalDecl(), FI
, F
, /*IsThunk=*/false);
474 CGM
.SetLLVMFunctionAttributesForDefinition(nullptr, F
);
475 CodeGenFunction
NewCGF(CGM
);
477 CGF
->StartFunction(GlobalDecl(), Ctx
.VoidTy
, F
, FI
, Args
);
478 auto AL
= ApplyDebugLocation::CreateArtificial(*CGF
);
479 std::array
<Address
, N
> Addrs
=
480 getParamAddrs
<N
>(std::make_index_sequence
<N
>{}, Alignments
, Args
, CGF
);
481 asDerived().visitStructFields(QT
, CharUnits::Zero(), Addrs
);
482 CGF
->FinishFunction();
487 void callFunc(StringRef FuncName
, QualType QT
, std::array
<Address
, N
> Addrs
,
488 CodeGenFunction
&CallerCGF
) {
489 std::array
<CharUnits
, N
> Alignments
;
490 llvm::Value
*Ptrs
[N
];
492 for (unsigned I
= 0; I
< N
; ++I
) {
493 Alignments
[I
] = Addrs
[I
].getAlignment();
494 Ptrs
[I
] = CallerCGF
.Builder
.CreateElementBitCast(
495 Addrs
[I
], CallerCGF
.CGM
.Int8PtrTy
).getPointer();
498 if (llvm::Function
*F
=
499 getFunction(FuncName
, QT
, Alignments
, CallerCGF
.CGM
))
500 CallerCGF
.EmitNounwindRuntimeCall(F
, Ptrs
);
503 Derived
&asDerived() { return static_cast<Derived
&>(*this); }
505 void setCGF(CodeGenFunction
*F
) { CGF
= F
; }
507 CodeGenFunction
*CGF
= nullptr;
510 template <class Derived
, bool IsMove
>
511 struct GenBinaryFunc
: CopyStructVisitor
<Derived
, IsMove
>,
512 GenFuncBase
<Derived
> {
513 GenBinaryFunc(ASTContext
&Ctx
) : CopyStructVisitor
<Derived
, IsMove
>(Ctx
) {}
515 void flushTrivialFields(std::array
<Address
, 2> Addrs
) {
516 CharUnits Size
= this->End
- this->Start
;
518 if (Size
.getQuantity() == 0)
521 Address DstAddr
= this->getAddrWithOffset(Addrs
[DstIdx
], this->Start
);
522 Address SrcAddr
= this->getAddrWithOffset(Addrs
[SrcIdx
], this->Start
);
525 if (Size
.getQuantity() >= 16 ||
526 !llvm::has_single_bit
<uint32_t>(Size
.getQuantity())) {
527 llvm::Value
*SizeVal
=
528 llvm::ConstantInt::get(this->CGF
->SizeTy
, Size
.getQuantity());
530 this->CGF
->Builder
.CreateElementBitCast(DstAddr
, this->CGF
->Int8Ty
);
532 this->CGF
->Builder
.CreateElementBitCast(SrcAddr
, this->CGF
->Int8Ty
);
533 this->CGF
->Builder
.CreateMemCpy(DstAddr
, SrcAddr
, SizeVal
, false);
535 llvm::Type
*Ty
= llvm::Type::getIntNTy(
536 this->CGF
->getLLVMContext(),
537 Size
.getQuantity() * this->CGF
->getContext().getCharWidth());
538 DstAddr
= this->CGF
->Builder
.CreateElementBitCast(DstAddr
, Ty
);
539 SrcAddr
= this->CGF
->Builder
.CreateElementBitCast(SrcAddr
, Ty
);
540 llvm::Value
*SrcVal
= this->CGF
->Builder
.CreateLoad(SrcAddr
, false);
541 this->CGF
->Builder
.CreateStore(SrcVal
, DstAddr
, false);
544 this->Start
= this->End
= CharUnits::Zero();
547 template <class... Ts
>
548 void visitVolatileTrivial(QualType FT
, const FieldDecl
*FD
, CharUnits Offset
,
549 std::array
<Address
, 2> Addrs
) {
552 // No need to copy zero-length bit-fields.
553 if (FD
->isZeroLengthBitField(this->CGF
->getContext()))
556 QualType RT
= QualType(FD
->getParent()->getTypeForDecl(), 0);
557 llvm::Type
*Ty
= this->CGF
->ConvertType(RT
);
558 Address DstAddr
= this->getAddrWithOffset(Addrs
[DstIdx
], Offset
);
559 LValue DstBase
= this->CGF
->MakeAddrLValue(
560 this->CGF
->Builder
.CreateElementBitCast(DstAddr
, Ty
), FT
);
561 DstLV
= this->CGF
->EmitLValueForField(DstBase
, FD
);
562 Address SrcAddr
= this->getAddrWithOffset(Addrs
[SrcIdx
], Offset
);
563 LValue SrcBase
= this->CGF
->MakeAddrLValue(
564 this->CGF
->Builder
.CreateElementBitCast(SrcAddr
, Ty
), FT
);
565 SrcLV
= this->CGF
->EmitLValueForField(SrcBase
, FD
);
567 llvm::Type
*Ty
= this->CGF
->ConvertTypeForMem(FT
);
569 this->CGF
->Builder
.CreateElementBitCast(Addrs
[DstIdx
], Ty
);
571 this->CGF
->Builder
.CreateElementBitCast(Addrs
[SrcIdx
], Ty
);
572 DstLV
= this->CGF
->MakeAddrLValue(DstAddr
, FT
);
573 SrcLV
= this->CGF
->MakeAddrLValue(SrcAddr
, FT
);
575 RValue SrcVal
= this->CGF
->EmitLoadOfLValue(SrcLV
, SourceLocation());
576 this->CGF
->EmitStoreThroughLValue(SrcVal
, DstLV
);
580 // These classes that emit the special functions for a non-trivial struct.
581 struct GenDestructor
: StructVisitor
<GenDestructor
>,
582 GenFuncBase
<GenDestructor
>,
583 DestructedTypeVisitor
<GenDestructor
> {
584 using Super
= DestructedTypeVisitor
<GenDestructor
>;
585 GenDestructor(ASTContext
&Ctx
) : StructVisitor
<GenDestructor
>(Ctx
) {}
587 void visitWithKind(QualType::DestructionKind DK
, QualType FT
,
588 const FieldDecl
*FD
, CharUnits CurStructOffset
,
589 std::array
<Address
, 1> Addrs
) {
590 if (const auto *AT
= getContext().getAsArrayType(FT
)) {
591 visitArray(DK
, AT
, FT
.isVolatileQualified(), FD
, CurStructOffset
, Addrs
);
595 Super::visitWithKind(DK
, FT
, FD
, CurStructOffset
, Addrs
);
598 void visitARCStrong(QualType QT
, const FieldDecl
*FD
,
599 CharUnits CurStructOffset
, std::array
<Address
, 1> Addrs
) {
600 CGF
->destroyARCStrongImprecise(
601 *CGF
, getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
), QT
);
604 void visitARCWeak(QualType QT
, const FieldDecl
*FD
, CharUnits CurStructOffset
,
605 std::array
<Address
, 1> Addrs
) {
607 *CGF
, getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
), QT
);
610 void callSpecialFunction(QualType FT
, CharUnits Offset
,
611 std::array
<Address
, 1> Addrs
) {
612 CGF
->callCStructDestructor(
613 CGF
->MakeAddrLValue(getAddrWithOffset(Addrs
[DstIdx
], Offset
), FT
));
617 struct GenDefaultInitialize
618 : StructVisitor
<GenDefaultInitialize
>,
619 GenFuncBase
<GenDefaultInitialize
>,
620 DefaultInitializedTypeVisitor
<GenDefaultInitialize
> {
621 using Super
= DefaultInitializedTypeVisitor
<GenDefaultInitialize
>;
622 typedef GenFuncBase
<GenDefaultInitialize
> GenFuncBaseTy
;
624 GenDefaultInitialize(ASTContext
&Ctx
)
625 : StructVisitor
<GenDefaultInitialize
>(Ctx
) {}
627 void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK
, QualType FT
,
628 const FieldDecl
*FD
, CharUnits CurStructOffset
,
629 std::array
<Address
, 1> Addrs
) {
630 if (const auto *AT
= getContext().getAsArrayType(FT
)) {
631 visitArray(PDIK
, AT
, FT
.isVolatileQualified(), FD
, CurStructOffset
,
636 Super::visitWithKind(PDIK
, FT
, FD
, CurStructOffset
, Addrs
);
639 void visitARCStrong(QualType QT
, const FieldDecl
*FD
,
640 CharUnits CurStructOffset
, std::array
<Address
, 1> Addrs
) {
641 CGF
->EmitNullInitialization(
642 getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
), QT
);
645 void visitARCWeak(QualType QT
, const FieldDecl
*FD
, CharUnits CurStructOffset
,
646 std::array
<Address
, 1> Addrs
) {
647 CGF
->EmitNullInitialization(
648 getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
), QT
);
651 template <class FieldKind
, size_t... Is
>
652 void visitArray(FieldKind FK
, const ArrayType
*AT
, bool IsVolatile
,
653 const FieldDecl
*FD
, CharUnits CurStructOffset
,
654 std::array
<Address
, 1> Addrs
) {
656 return visitTrivial(QualType(AT
, 0), FD
, CurStructOffset
, Addrs
);
658 ASTContext
&Ctx
= getContext();
659 CharUnits Size
= Ctx
.getTypeSizeInChars(QualType(AT
, 0));
660 QualType EltTy
= Ctx
.getBaseElementType(QualType(AT
, 0));
662 if (Size
< CharUnits::fromQuantity(16) || EltTy
->getAs
<RecordType
>()) {
663 GenFuncBaseTy::visitArray(FK
, AT
, IsVolatile
, FD
, CurStructOffset
, Addrs
);
667 llvm::Constant
*SizeVal
= CGF
->Builder
.getInt64(Size
.getQuantity());
668 Address DstAddr
= getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
669 Address Loc
= CGF
->Builder
.CreateElementBitCast(DstAddr
, CGF
->Int8Ty
);
670 CGF
->Builder
.CreateMemSet(Loc
, CGF
->Builder
.getInt8(0), SizeVal
,
674 void callSpecialFunction(QualType FT
, CharUnits Offset
,
675 std::array
<Address
, 1> Addrs
) {
676 CGF
->callCStructDefaultConstructor(
677 CGF
->MakeAddrLValue(getAddrWithOffset(Addrs
[DstIdx
], Offset
), FT
));
681 struct GenCopyConstructor
: GenBinaryFunc
<GenCopyConstructor
, false> {
682 GenCopyConstructor(ASTContext
&Ctx
)
683 : GenBinaryFunc
<GenCopyConstructor
, false>(Ctx
) {}
685 void visitARCStrong(QualType QT
, const FieldDecl
*FD
,
686 CharUnits CurStructOffset
, std::array
<Address
, 2> Addrs
) {
687 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
688 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
689 llvm::Value
*SrcVal
= CGF
->EmitLoadOfScalar(
690 Addrs
[SrcIdx
], QT
.isVolatileQualified(), QT
, SourceLocation());
691 llvm::Value
*Val
= CGF
->EmitARCRetain(QT
, SrcVal
);
692 CGF
->EmitStoreOfScalar(Val
, CGF
->MakeAddrLValue(Addrs
[DstIdx
], QT
), true);
695 void visitARCWeak(QualType QT
, const FieldDecl
*FD
, CharUnits CurStructOffset
,
696 std::array
<Address
, 2> Addrs
) {
697 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
698 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
699 CGF
->EmitARCCopyWeak(Addrs
[DstIdx
], Addrs
[SrcIdx
]);
702 void callSpecialFunction(QualType FT
, CharUnits Offset
,
703 std::array
<Address
, 2> Addrs
) {
704 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], Offset
);
705 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], Offset
);
706 CGF
->callCStructCopyConstructor(CGF
->MakeAddrLValue(Addrs
[DstIdx
], FT
),
707 CGF
->MakeAddrLValue(Addrs
[SrcIdx
], FT
));
711 struct GenMoveConstructor
: GenBinaryFunc
<GenMoveConstructor
, true> {
712 GenMoveConstructor(ASTContext
&Ctx
)
713 : GenBinaryFunc
<GenMoveConstructor
, true>(Ctx
) {}
715 void visitARCStrong(QualType QT
, const FieldDecl
*FD
,
716 CharUnits CurStructOffset
, std::array
<Address
, 2> Addrs
) {
717 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
718 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
719 LValue SrcLV
= CGF
->MakeAddrLValue(Addrs
[SrcIdx
], QT
);
720 llvm::Value
*SrcVal
=
721 CGF
->EmitLoadOfLValue(SrcLV
, SourceLocation()).getScalarVal();
722 CGF
->EmitStoreOfScalar(getNullForVariable(SrcLV
.getAddress(*CGF
)), SrcLV
);
723 CGF
->EmitStoreOfScalar(SrcVal
, CGF
->MakeAddrLValue(Addrs
[DstIdx
], QT
),
724 /* isInitialization */ true);
727 void visitARCWeak(QualType QT
, const FieldDecl
*FD
, CharUnits CurStructOffset
,
728 std::array
<Address
, 2> Addrs
) {
729 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
730 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
731 CGF
->EmitARCMoveWeak(Addrs
[DstIdx
], Addrs
[SrcIdx
]);
734 void callSpecialFunction(QualType FT
, CharUnits Offset
,
735 std::array
<Address
, 2> Addrs
) {
736 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], Offset
);
737 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], Offset
);
738 CGF
->callCStructMoveConstructor(CGF
->MakeAddrLValue(Addrs
[DstIdx
], FT
),
739 CGF
->MakeAddrLValue(Addrs
[SrcIdx
], FT
));
743 struct GenCopyAssignment
: GenBinaryFunc
<GenCopyAssignment
, false> {
744 GenCopyAssignment(ASTContext
&Ctx
)
745 : GenBinaryFunc
<GenCopyAssignment
, false>(Ctx
) {}
747 void visitARCStrong(QualType QT
, const FieldDecl
*FD
,
748 CharUnits CurStructOffset
, std::array
<Address
, 2> Addrs
) {
749 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
750 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
751 llvm::Value
*SrcVal
= CGF
->EmitLoadOfScalar(
752 Addrs
[SrcIdx
], QT
.isVolatileQualified(), QT
, SourceLocation());
753 CGF
->EmitARCStoreStrong(CGF
->MakeAddrLValue(Addrs
[DstIdx
], QT
), SrcVal
,
757 void visitARCWeak(QualType QT
, const FieldDecl
*FD
, CharUnits CurStructOffset
,
758 std::array
<Address
, 2> Addrs
) {
759 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
760 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
761 CGF
->emitARCCopyAssignWeak(QT
, Addrs
[DstIdx
], Addrs
[SrcIdx
]);
764 void callSpecialFunction(QualType FT
, CharUnits Offset
,
765 std::array
<Address
, 2> Addrs
) {
766 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], Offset
);
767 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], Offset
);
768 CGF
->callCStructCopyAssignmentOperator(
769 CGF
->MakeAddrLValue(Addrs
[DstIdx
], FT
),
770 CGF
->MakeAddrLValue(Addrs
[SrcIdx
], FT
));
774 struct GenMoveAssignment
: GenBinaryFunc
<GenMoveAssignment
, true> {
775 GenMoveAssignment(ASTContext
&Ctx
)
776 : GenBinaryFunc
<GenMoveAssignment
, true>(Ctx
) {}
778 void visitARCStrong(QualType QT
, const FieldDecl
*FD
,
779 CharUnits CurStructOffset
, std::array
<Address
, 2> Addrs
) {
780 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
781 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
782 LValue SrcLV
= CGF
->MakeAddrLValue(Addrs
[SrcIdx
], QT
);
783 llvm::Value
*SrcVal
=
784 CGF
->EmitLoadOfLValue(SrcLV
, SourceLocation()).getScalarVal();
785 CGF
->EmitStoreOfScalar(getNullForVariable(SrcLV
.getAddress(*CGF
)), SrcLV
);
786 LValue DstLV
= CGF
->MakeAddrLValue(Addrs
[DstIdx
], QT
);
787 llvm::Value
*DstVal
=
788 CGF
->EmitLoadOfLValue(DstLV
, SourceLocation()).getScalarVal();
789 CGF
->EmitStoreOfScalar(SrcVal
, DstLV
);
790 CGF
->EmitARCRelease(DstVal
, ARCImpreciseLifetime
);
793 void visitARCWeak(QualType QT
, const FieldDecl
*FD
, CharUnits CurStructOffset
,
794 std::array
<Address
, 2> Addrs
) {
795 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], CurStructOffset
, FD
);
796 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], CurStructOffset
, FD
);
797 CGF
->emitARCMoveAssignWeak(QT
, Addrs
[DstIdx
], Addrs
[SrcIdx
]);
800 void callSpecialFunction(QualType FT
, CharUnits Offset
,
801 std::array
<Address
, 2> Addrs
) {
802 Addrs
[DstIdx
] = getAddrWithOffset(Addrs
[DstIdx
], Offset
);
803 Addrs
[SrcIdx
] = getAddrWithOffset(Addrs
[SrcIdx
], Offset
);
804 CGF
->callCStructMoveAssignmentOperator(
805 CGF
->MakeAddrLValue(Addrs
[DstIdx
], FT
),
806 CGF
->MakeAddrLValue(Addrs
[SrcIdx
], FT
));
812 void CodeGenFunction::destroyNonTrivialCStruct(CodeGenFunction
&CGF
,
813 Address Addr
, QualType Type
) {
814 CGF
.callCStructDestructor(CGF
.MakeAddrLValue(Addr
, Type
));
817 // Default-initialize a variable that is a non-trivial struct or an array of
819 void CodeGenFunction::defaultInitNonTrivialCStructVar(LValue Dst
) {
820 GenDefaultInitialize
Gen(getContext());
822 Builder
.CreateElementBitCast(Dst
.getAddress(*this), CGM
.Int8PtrTy
);
824 QualType QT
= Dst
.getType();
825 QT
= Dst
.isVolatile() ? QT
.withVolatile() : QT
;
826 Gen
.visit(QT
, nullptr, CharUnits::Zero(), std::array
<Address
, 1>({{DstPtr
}}));
829 template <class G
, size_t N
>
830 static void callSpecialFunction(G
&&Gen
, StringRef FuncName
, QualType QT
,
831 bool IsVolatile
, CodeGenFunction
&CGF
,
832 std::array
<Address
, N
> Addrs
) {
833 auto SetArtificialLoc
= ApplyDebugLocation::CreateArtificial(CGF
);
834 for (unsigned I
= 0; I
< N
; ++I
)
835 Addrs
[I
] = CGF
.Builder
.CreateElementBitCast(Addrs
[I
], CGF
.CGM
.Int8PtrTy
);
836 QT
= IsVolatile
? QT
.withVolatile() : QT
;
837 Gen
.callFunc(FuncName
, QT
, Addrs
, CGF
);
840 template <class G
, size_t N
>
841 static llvm::Function
*
842 getSpecialFunction(G
&&Gen
, StringRef FuncName
, QualType QT
, bool IsVolatile
,
843 std::array
<CharUnits
, N
> Alignments
, CodeGenModule
&CGM
) {
844 QT
= IsVolatile
? QT
.withVolatile() : QT
;
845 // The following call requires an array of addresses as arguments, but doesn't
846 // actually use them (it overwrites them with the addresses of the arguments
847 // of the created function).
848 return Gen
.getFunction(FuncName
, QT
, Alignments
, CGM
);
851 // Functions to emit calls to the special functions of a non-trivial C struct.
852 void CodeGenFunction::callCStructDefaultConstructor(LValue Dst
) {
853 bool IsVolatile
= Dst
.isVolatile();
854 Address DstPtr
= Dst
.getAddress(*this);
855 QualType QT
= Dst
.getType();
856 GenDefaultInitializeFuncName
GenName(DstPtr
.getAlignment(), getContext());
857 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
858 callSpecialFunction(GenDefaultInitialize(getContext()), FuncName
, QT
,
859 IsVolatile
, *this, std::array
<Address
, 1>({{DstPtr
}}));
862 std::string
CodeGenFunction::getNonTrivialCopyConstructorStr(
863 QualType QT
, CharUnits Alignment
, bool IsVolatile
, ASTContext
&Ctx
) {
864 GenBinaryFuncName
<false> GenName("", Alignment
, Alignment
, Ctx
);
865 return GenName
.getName(QT
, IsVolatile
);
868 std::string
CodeGenFunction::getNonTrivialDestructorStr(QualType QT
,
872 GenDestructorFuncName
GenName("", Alignment
, Ctx
);
873 return GenName
.getName(QT
, IsVolatile
);
876 void CodeGenFunction::callCStructDestructor(LValue Dst
) {
877 bool IsVolatile
= Dst
.isVolatile();
878 Address DstPtr
= Dst
.getAddress(*this);
879 QualType QT
= Dst
.getType();
880 GenDestructorFuncName
GenName("__destructor_", DstPtr
.getAlignment(),
882 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
883 callSpecialFunction(GenDestructor(getContext()), FuncName
, QT
, IsVolatile
,
884 *this, std::array
<Address
, 1>({{DstPtr
}}));
887 void CodeGenFunction::callCStructCopyConstructor(LValue Dst
, LValue Src
) {
888 bool IsVolatile
= Dst
.isVolatile() || Src
.isVolatile();
889 Address DstPtr
= Dst
.getAddress(*this), SrcPtr
= Src
.getAddress(*this);
890 QualType QT
= Dst
.getType();
891 GenBinaryFuncName
<false> GenName("__copy_constructor_", DstPtr
.getAlignment(),
892 SrcPtr
.getAlignment(), getContext());
893 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
894 callSpecialFunction(GenCopyConstructor(getContext()), FuncName
, QT
,
896 std::array
<Address
, 2>({{DstPtr
, SrcPtr
}}));
899 void CodeGenFunction::callCStructCopyAssignmentOperator(LValue Dst
, LValue Src
902 bool IsVolatile
= Dst
.isVolatile() || Src
.isVolatile();
903 Address DstPtr
= Dst
.getAddress(*this), SrcPtr
= Src
.getAddress(*this);
904 QualType QT
= Dst
.getType();
905 GenBinaryFuncName
<false> GenName("__copy_assignment_", DstPtr
.getAlignment(),
906 SrcPtr
.getAlignment(), getContext());
907 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
908 callSpecialFunction(GenCopyAssignment(getContext()), FuncName
, QT
, IsVolatile
,
909 *this, std::array
<Address
, 2>({{DstPtr
, SrcPtr
}}));
912 void CodeGenFunction::callCStructMoveConstructor(LValue Dst
, LValue Src
) {
913 bool IsVolatile
= Dst
.isVolatile() || Src
.isVolatile();
914 Address DstPtr
= Dst
.getAddress(*this), SrcPtr
= Src
.getAddress(*this);
915 QualType QT
= Dst
.getType();
916 GenBinaryFuncName
<true> GenName("__move_constructor_", DstPtr
.getAlignment(),
917 SrcPtr
.getAlignment(), getContext());
918 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
919 callSpecialFunction(GenMoveConstructor(getContext()), FuncName
, QT
,
921 std::array
<Address
, 2>({{DstPtr
, SrcPtr
}}));
924 void CodeGenFunction::callCStructMoveAssignmentOperator(LValue Dst
, LValue Src
927 bool IsVolatile
= Dst
.isVolatile() || Src
.isVolatile();
928 Address DstPtr
= Dst
.getAddress(*this), SrcPtr
= Src
.getAddress(*this);
929 QualType QT
= Dst
.getType();
930 GenBinaryFuncName
<true> GenName("__move_assignment_", DstPtr
.getAlignment(),
931 SrcPtr
.getAlignment(), getContext());
932 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
933 callSpecialFunction(GenMoveAssignment(getContext()), FuncName
, QT
, IsVolatile
,
934 *this, std::array
<Address
, 2>({{DstPtr
, SrcPtr
}}));
937 llvm::Function
*clang::CodeGen::getNonTrivialCStructDefaultConstructor(
938 CodeGenModule
&CGM
, CharUnits DstAlignment
, bool IsVolatile
, QualType QT
) {
939 ASTContext
&Ctx
= CGM
.getContext();
940 GenDefaultInitializeFuncName
GenName(DstAlignment
, Ctx
);
941 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
942 return getSpecialFunction(GenDefaultInitialize(Ctx
), FuncName
, QT
, IsVolatile
,
943 std::array
<CharUnits
, 1>({{DstAlignment
}}), CGM
);
946 llvm::Function
*clang::CodeGen::getNonTrivialCStructCopyConstructor(
947 CodeGenModule
&CGM
, CharUnits DstAlignment
, CharUnits SrcAlignment
,
948 bool IsVolatile
, QualType QT
) {
949 ASTContext
&Ctx
= CGM
.getContext();
950 GenBinaryFuncName
<false> GenName("__copy_constructor_", DstAlignment
,
952 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
953 return getSpecialFunction(
954 GenCopyConstructor(Ctx
), FuncName
, QT
, IsVolatile
,
955 std::array
<CharUnits
, 2>({{DstAlignment
, SrcAlignment
}}), CGM
);
958 llvm::Function
*clang::CodeGen::getNonTrivialCStructMoveConstructor(
959 CodeGenModule
&CGM
, CharUnits DstAlignment
, CharUnits SrcAlignment
,
960 bool IsVolatile
, QualType QT
) {
961 ASTContext
&Ctx
= CGM
.getContext();
962 GenBinaryFuncName
<true> GenName("__move_constructor_", DstAlignment
,
964 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
965 return getSpecialFunction(
966 GenMoveConstructor(Ctx
), FuncName
, QT
, IsVolatile
,
967 std::array
<CharUnits
, 2>({{DstAlignment
, SrcAlignment
}}), CGM
);
970 llvm::Function
*clang::CodeGen::getNonTrivialCStructCopyAssignmentOperator(
971 CodeGenModule
&CGM
, CharUnits DstAlignment
, CharUnits SrcAlignment
,
972 bool IsVolatile
, QualType QT
) {
973 ASTContext
&Ctx
= CGM
.getContext();
974 GenBinaryFuncName
<false> GenName("__copy_assignment_", DstAlignment
,
976 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
977 return getSpecialFunction(
978 GenCopyAssignment(Ctx
), FuncName
, QT
, IsVolatile
,
979 std::array
<CharUnits
, 2>({{DstAlignment
, SrcAlignment
}}), CGM
);
982 llvm::Function
*clang::CodeGen::getNonTrivialCStructMoveAssignmentOperator(
983 CodeGenModule
&CGM
, CharUnits DstAlignment
, CharUnits SrcAlignment
,
984 bool IsVolatile
, QualType QT
) {
985 ASTContext
&Ctx
= CGM
.getContext();
986 GenBinaryFuncName
<true> GenName("__move_assignment_", DstAlignment
,
988 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
989 return getSpecialFunction(
990 GenMoveAssignment(Ctx
), FuncName
, QT
, IsVolatile
,
991 std::array
<CharUnits
, 2>({{DstAlignment
, SrcAlignment
}}), CGM
);
994 llvm::Function
*clang::CodeGen::getNonTrivialCStructDestructor(
995 CodeGenModule
&CGM
, CharUnits DstAlignment
, bool IsVolatile
, QualType QT
) {
996 ASTContext
&Ctx
= CGM
.getContext();
997 GenDestructorFuncName
GenName("__destructor_", DstAlignment
, Ctx
);
998 std::string FuncName
= GenName
.getName(QT
, IsVolatile
);
999 return getSpecialFunction(GenDestructor(Ctx
), FuncName
, QT
, IsVolatile
,
1000 std::array
<CharUnits
, 1>({{DstAlignment
}}), CGM
);