clang 22.0.0git
CGNonTrivialStruct.cpp
Go to the documentation of this file.
1//===--- CGNonTrivialStruct.cpp - Emit Special Functions for C Structs ----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines functions to generate various special functions for C
10// structs.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CGDebugInfo.h"
15#include "CodeGenFunction.h"
16#include "CodeGenModule.h"
19#include "llvm/Support/ScopedPrinter.h"
20#include <array>
21
22using namespace clang;
23using namespace CodeGen;
24
25// Return the size of a field in number of bits.
26static uint64_t getFieldSize(const FieldDecl *FD, QualType FT,
27 ASTContext &Ctx) {
28 if (FD && FD->isBitField())
29 return FD->getBitWidthValue();
30 return Ctx.getTypeSize(FT);
31}
32
33namespace {
34enum { DstIdx = 0, SrcIdx = 1 };
35const char *ValNameStr[2] = {"dst", "src"};
36
37template <class Derived> struct StructVisitor {
38 StructVisitor(ASTContext &Ctx) : Ctx(Ctx) {}
39
40 template <class... Ts>
41 void visitStructFields(QualType QT, CharUnits CurStructOffset, Ts... Args) {
42 const auto *RD = QT->castAsRecordDecl();
43
44 // Iterate over the fields of the struct.
45 for (const FieldDecl *FD : RD->fields()) {
46 QualType FT = FD->getType();
47 FT = QT.isVolatileQualified() ? FT.withVolatile() : FT;
48 asDerived().visit(FT, FD, CurStructOffset, Args...);
49 }
50
51 asDerived().flushTrivialFields(Args...);
52 }
53
54 template <class... Ts> void visitTrivial(Ts... Args) {}
55
56 template <class... Ts> void visitCXXDestructor(Ts... Args) {
57 llvm_unreachable("field of a C++ struct type is not expected");
58 }
59
60 template <class... Ts> void flushTrivialFields(Ts... Args) {}
61
62 uint64_t getFieldOffsetInBits(const FieldDecl *FD) {
63 return FD ? Ctx.getASTRecordLayout(FD->getParent())
64 .getFieldOffset(FD->getFieldIndex())
65 : 0;
66 }
67
68 CharUnits getFieldOffset(const FieldDecl *FD) {
69 return Ctx.toCharUnitsFromBits(getFieldOffsetInBits(FD));
70 }
71
72 Derived &asDerived() { return static_cast<Derived &>(*this); }
73
74 ASTContext &getContext() { return Ctx; }
75 ASTContext &Ctx;
76};
77
78template <class Derived, bool IsMove>
79struct CopyStructVisitor : StructVisitor<Derived>,
80 CopiedTypeVisitor<Derived, IsMove> {
81 using StructVisitor<Derived>::asDerived;
82 using Super = CopiedTypeVisitor<Derived, IsMove>;
83
84 CopyStructVisitor(ASTContext &Ctx) : StructVisitor<Derived>(Ctx) {}
85
86 template <class... Ts>
87 void preVisit(QualType::PrimitiveCopyKind PCK, QualType FT,
88 const FieldDecl *FD, CharUnits CurStructOffset, Ts &&... Args) {
89 if (PCK)
90 asDerived().flushTrivialFields(std::forward<Ts>(Args)...);
91 }
92
93 template <class... Ts>
94 void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT,
95 const FieldDecl *FD, CharUnits CurStructOffset,
96 Ts &&... Args) {
97 if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
98 asDerived().visitArray(PCK, AT, FT.isVolatileQualified(), FD,
99 CurStructOffset, std::forward<Ts>(Args)...);
100 return;
101 }
102
103 Super::visitWithKind(PCK, FT, FD, CurStructOffset,
104 std::forward<Ts>(Args)...);
105 }
106
107 template <class... Ts>
108 void visitTrivial(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset,
109 Ts... Args) {
110 assert(!FT.isVolatileQualified() && "volatile field not expected");
111 ASTContext &Ctx = asDerived().getContext();
112 uint64_t FieldSize = getFieldSize(FD, FT, Ctx);
113
114 // Ignore zero-sized fields.
115 if (FieldSize == 0)
116 return;
117
118 uint64_t FStartInBits = asDerived().getFieldOffsetInBits(FD);
119 uint64_t FEndInBits = FStartInBits + FieldSize;
120 uint64_t RoundedFEnd = llvm::alignTo(FEndInBits, Ctx.getCharWidth());
121
122 // Set Start if this is the first field of a sequence of trivial fields.
123 if (Start == End)
124 Start = CurStructOffset + Ctx.toCharUnitsFromBits(FStartInBits);
125 End = CurStructOffset + Ctx.toCharUnitsFromBits(RoundedFEnd);
126 }
127
128 CharUnits Start = CharUnits::Zero(), End = CharUnits::Zero();
129};
130
131// This function creates the mangled name of a special function of a non-trivial
132// C struct. Since there is no ODR in C, the function is mangled based on the
133// struct contents and not the name. The mangled name has the following
134// structure:
135//
136// <function-name> ::= <prefix> <alignment-info> "_" <struct-field-info>
137// <prefix> ::= "__destructor_" | "__default_constructor_" |
138// "__copy_constructor_" | "__move_constructor_" |
139// "__copy_assignment_" | "__move_assignment_"
140// <alignment-info> ::= <dst-alignment> ["_" <src-alignment>]
141// <struct-field-info> ::= <field-info>+
142// <field-info> ::= <struct-or-scalar-field-info> | <array-field-info>
143// <struct-or-scalar-field-info> ::= "_S" <struct-field-info> |
144// <strong-field-info> | <trivial-field-info>
145// <array-field-info> ::= "_AB" <array-offset> "s" <element-size> "n"
146// <num-elements> <innermost-element-info> "_AE"
147// <innermost-element-info> ::= <struct-or-scalar-field-info>
148// <strong-field-info> ::= "_s" ["b"] ["v"] <field-offset>
149// <trivial-field-info> ::= "_t" ["v"] <field-offset> "_" <field-size>
150
151template <class Derived> struct GenFuncNameBase {
152 std::string getVolatileOffsetStr(bool IsVolatile, CharUnits Offset) {
153 std::string S;
154 if (IsVolatile)
155 S = "v";
156 S += llvm::to_string(Offset.getQuantity());
157 return S;
158 }
159
160 void visitARCStrong(QualType FT, const FieldDecl *FD,
161 CharUnits CurStructOffset) {
162 appendStr("_s");
163 if (FT->isBlockPointerType())
164 appendStr("b");
165 CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
166 appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset));
167 }
168
169 void visitARCWeak(QualType FT, const FieldDecl *FD,
170 CharUnits CurStructOffset) {
171 appendStr("_w");
172 CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
173 appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset));
174 }
175
176 void visitStruct(QualType QT, const FieldDecl *FD,
177 CharUnits CurStructOffset) {
178 CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
179 appendStr("_S");
180 asDerived().visitStructFields(QT, FieldOffset);
181 }
182
183 template <class FieldKind>
184 void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
185 const FieldDecl *FD, CharUnits CurStructOffset) {
186 // String for non-volatile trivial fields is emitted when
187 // flushTrivialFields is called.
188 if (!FK)
189 return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset);
190
191 asDerived().flushTrivialFields();
192 CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
193 ASTContext &Ctx = asDerived().getContext();
194 const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
195 unsigned NumElts = Ctx.getConstantArrayElementCount(CAT);
196 QualType EltTy = Ctx.getBaseElementType(CAT);
197 CharUnits EltSize = Ctx.getTypeSizeInChars(EltTy);
198 appendStr("_AB" + llvm::to_string(FieldOffset.getQuantity()) + "s" +
199 llvm::to_string(EltSize.getQuantity()) + "n" +
200 llvm::to_string(NumElts));
201 EltTy = IsVolatile ? EltTy.withVolatile() : EltTy;
202 asDerived().visitWithKind(FK, EltTy, nullptr, FieldOffset);
203 appendStr("_AE");
204 }
205
206 void appendStr(StringRef Str) { Name += Str; }
207
208 std::string getName(QualType QT, bool IsVolatile) {
209 QT = IsVolatile ? QT.withVolatile() : QT;
210 asDerived().visitStructFields(QT, CharUnits::Zero());
211 return Name;
212 }
213
214 Derived &asDerived() { return static_cast<Derived &>(*this); }
215
216 std::string Name;
217};
218
219template <class Derived>
220struct GenUnaryFuncName : StructVisitor<Derived>, GenFuncNameBase<Derived> {
221 GenUnaryFuncName(StringRef Prefix, CharUnits DstAlignment, ASTContext &Ctx)
222 : StructVisitor<Derived>(Ctx) {
223 this->appendStr(Prefix);
224 this->appendStr(llvm::to_string(DstAlignment.getQuantity()));
225 }
226};
227
228// Helper function to create a null constant.
229static llvm::Constant *getNullForVariable(Address Addr) {
230 llvm::Type *Ty = Addr.getElementType();
231 return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(Ty));
232}
233
234template <bool IsMove>
235struct GenBinaryFuncName : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>,
236 GenFuncNameBase<GenBinaryFuncName<IsMove>> {
237
238 GenBinaryFuncName(StringRef Prefix, CharUnits DstAlignment,
239 CharUnits SrcAlignment, ASTContext &Ctx)
240 : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>(Ctx) {
241 this->appendStr(Prefix);
242 this->appendStr(llvm::to_string(DstAlignment.getQuantity()));
243 this->appendStr("_" + llvm::to_string(SrcAlignment.getQuantity()));
244 }
245
246 void flushTrivialFields() {
247 if (this->Start == this->End)
248 return;
249
250 this->appendStr("_t" + llvm::to_string(this->Start.getQuantity()) + "w" +
251 llvm::to_string((this->End - this->Start).getQuantity()));
252
253 this->Start = this->End = CharUnits::Zero();
254 }
255
256 void visitVolatileTrivial(QualType FT, const FieldDecl *FD,
257 CharUnits CurStructOffset) {
258 // Zero-length bit-fields don't need to be copied/assigned.
259 if (FD && FD->isZeroLengthBitField())
260 return;
261
262 // Because volatile fields can be bit-fields and are individually copied,
263 // their offset and width are in bits.
264 uint64_t OffsetInBits =
265 this->Ctx.toBits(CurStructOffset) + this->getFieldOffsetInBits(FD);
266 this->appendStr("_tv" + llvm::to_string(OffsetInBits) + "w" +
267 llvm::to_string(getFieldSize(FD, FT, this->Ctx)));
268 }
269
270 void visitPtrAuth(QualType FT, const FieldDecl *FD,
271 CharUnits CurStructOffset) {
272 this->appendStr("_pa");
273 PointerAuthQualifier PtrAuth = FT.getPointerAuth().withoutKeyNone();
274 this->appendStr(llvm::to_string(PtrAuth.getKey()) + "_");
275 this->appendStr(llvm::to_string(PtrAuth.getExtraDiscriminator()) + "_");
276 if (PtrAuth.authenticatesNullValues())
277 this->appendStr("anv_");
278 CharUnits FieldOffset = CurStructOffset + this->getFieldOffset(FD);
279 this->appendStr(llvm::to_string(FieldOffset.getQuantity()));
280 }
281};
282
283struct GenDefaultInitializeFuncName
284 : GenUnaryFuncName<GenDefaultInitializeFuncName>,
285 DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName> {
286 using Super = DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName>;
287 GenDefaultInitializeFuncName(CharUnits DstAlignment, ASTContext &Ctx)
288 : GenUnaryFuncName<GenDefaultInitializeFuncName>("__default_constructor_",
289 DstAlignment, Ctx) {}
290 void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
291 const FieldDecl *FD, CharUnits CurStructOffset) {
292 if (const auto *AT = getContext().getAsArrayType(FT)) {
293 visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset);
294 return;
295 }
296
297 Super::visitWithKind(PDIK, FT, FD, CurStructOffset);
298 }
299};
300
301struct GenDestructorFuncName : GenUnaryFuncName<GenDestructorFuncName>,
302 DestructedTypeVisitor<GenDestructorFuncName> {
303 using Super = DestructedTypeVisitor<GenDestructorFuncName>;
304 GenDestructorFuncName(const char *Prefix, CharUnits DstAlignment,
305 ASTContext &Ctx)
306 : GenUnaryFuncName<GenDestructorFuncName>(Prefix, DstAlignment, Ctx) {}
307 void visitWithKind(QualType::DestructionKind DK, QualType FT,
308 const FieldDecl *FD, CharUnits CurStructOffset) {
309 if (const auto *AT = getContext().getAsArrayType(FT)) {
310 visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset);
311 return;
312 }
313
314 Super::visitWithKind(DK, FT, FD, CurStructOffset);
315 }
316};
317
318// Helper function that creates CGFunctionInfo for an N-ary special function.
319template <size_t N>
320static const CGFunctionInfo &getFunctionInfo(CodeGenModule &CGM,
321 FunctionArgList &Args) {
322 ASTContext &Ctx = CGM.getContext();
324 QualType ParamTy = Ctx.getPointerType(Ctx.VoidPtrTy);
325
326 for (unsigned I = 0; I < N; ++I)
327 Params.push_back(ImplicitParamDecl::Create(
328 Ctx, nullptr, SourceLocation(), &Ctx.Idents.get(ValNameStr[I]), ParamTy,
330
331 llvm::append_range(Args, Params);
332
333 return CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args);
334}
335
336template <size_t N, size_t... Ints>
337static std::array<Address, N> getParamAddrs(std::index_sequence<Ints...> IntSeq,
338 std::array<CharUnits, N> Alignments,
339 const FunctionArgList &Args,
340 CodeGenFunction *CGF) {
341 return std::array<Address, N>{
342 {Address(CGF->Builder.CreateLoad(CGF->GetAddrOfLocalVar(Args[Ints])),
343 CGF->VoidPtrTy, Alignments[Ints], KnownNonNull)...}};
344}
345
346// Template classes that are used as bases for classes that emit special
347// functions.
348template <class Derived> struct GenFuncBase {
349 template <size_t N>
350 void visitStruct(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset,
351 std::array<Address, N> Addrs) {
352 this->asDerived().callSpecialFunction(
353 FT, CurStructOffset + asDerived().getFieldOffset(FD), Addrs);
354 }
355
356 template <class FieldKind, size_t N>
357 void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
358 const FieldDecl *FD, CharUnits CurStructOffset,
359 std::array<Address, N> Addrs) {
360 // Non-volatile trivial fields are copied when flushTrivialFields is called.
361 if (!FK)
362 return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset,
363 Addrs);
364
365 asDerived().flushTrivialFields(Addrs);
366 CodeGenFunction &CGF = *this->CGF;
367 ASTContext &Ctx = CGF.getContext();
368
369 // Compute the end address.
370 QualType BaseEltQT;
371 std::array<Address, N> StartAddrs = Addrs;
372 for (unsigned I = 0; I < N; ++I)
373 StartAddrs[I] = getAddrWithOffset(Addrs[I], CurStructOffset, FD);
374 Address DstAddr = StartAddrs[DstIdx];
375 llvm::Value *NumElts = CGF.emitArrayLength(AT, BaseEltQT, DstAddr);
376 unsigned BaseEltSize = Ctx.getTypeSizeInChars(BaseEltQT).getQuantity();
377 llvm::Value *BaseEltSizeVal =
378 llvm::ConstantInt::get(NumElts->getType(), BaseEltSize);
379 llvm::Value *SizeInBytes =
380 CGF.Builder.CreateNUWMul(BaseEltSizeVal, NumElts);
381 llvm::Value *DstArrayEnd = CGF.Builder.CreateInBoundsGEP(
382 CGF.Int8Ty, DstAddr.emitRawPointer(CGF), SizeInBytes);
383 llvm::BasicBlock *PreheaderBB = CGF.Builder.GetInsertBlock();
384
385 // Create the header block and insert the phi instructions.
386 llvm::BasicBlock *HeaderBB = CGF.createBasicBlock("loop.header");
387 CGF.EmitBlock(HeaderBB);
388 llvm::PHINode *PHIs[N];
389
390 for (unsigned I = 0; I < N; ++I) {
391 PHIs[I] = CGF.Builder.CreatePHI(CGF.CGM.Int8PtrPtrTy, 2, "addr.cur");
392 PHIs[I]->addIncoming(StartAddrs[I].emitRawPointer(CGF), PreheaderBB);
393 }
394
395 // Create the exit and loop body blocks.
396 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("loop.exit");
397 llvm::BasicBlock *LoopBB = CGF.createBasicBlock("loop.body");
398
399 // Emit the comparison and conditional branch instruction that jumps to
400 // either the exit or the loop body.
401 llvm::Value *Done =
402 CGF.Builder.CreateICmpEQ(PHIs[DstIdx], DstArrayEnd, "done");
403 CGF.Builder.CreateCondBr(Done, ExitBB, LoopBB);
404
405 // Visit the element of the array in the loop body.
406 CGF.EmitBlock(LoopBB);
407 QualType EltQT = AT->getElementType();
408 CharUnits EltSize = Ctx.getTypeSizeInChars(EltQT);
409 std::array<Address, N> NewAddrs = Addrs;
410
411 for (unsigned I = 0; I < N; ++I)
412 NewAddrs[I] =
413 Address(PHIs[I], CGF.Int8PtrTy,
414 StartAddrs[I].getAlignment().alignmentAtOffset(EltSize));
415
416 EltQT = IsVolatile ? EltQT.withVolatile() : EltQT;
417 this->asDerived().visitWithKind(FK, EltQT, nullptr, CharUnits::Zero(),
418 NewAddrs);
419
420 LoopBB = CGF.Builder.GetInsertBlock();
421
422 for (unsigned I = 0; I < N; ++I) {
423 // Instrs to update the destination and source addresses.
424 // Update phi instructions.
425 NewAddrs[I] = getAddrWithOffset(NewAddrs[I], EltSize);
426 PHIs[I]->addIncoming(NewAddrs[I].emitRawPointer(CGF), LoopBB);
427 }
428
429 // Insert an unconditional branch to the header block.
430 CGF.Builder.CreateBr(HeaderBB);
431 CGF.EmitBlock(ExitBB);
432 }
433
434 /// Return an address with the specified offset from the passed address.
435 Address getAddrWithOffset(Address Addr, CharUnits Offset) {
436 assert(Addr.isValid() && "invalid address");
437 if (Offset.getQuantity() == 0)
438 return Addr;
439 Addr = Addr.withElementType(CGF->CGM.Int8Ty);
440 Addr = CGF->Builder.CreateConstInBoundsGEP(Addr, Offset.getQuantity());
441 return Addr.withElementType(CGF->CGM.Int8PtrTy);
442 }
443
444 Address getAddrWithOffset(Address Addr, CharUnits StructFieldOffset,
445 const FieldDecl *FD) {
446 return getAddrWithOffset(Addr, StructFieldOffset +
447 asDerived().getFieldOffset(FD));
448 }
449
450 template <size_t N>
451 llvm::Function *getFunction(StringRef FuncName, QualType QT,
452 std::array<CharUnits, N> Alignments,
453 CodeGenModule &CGM) {
454 // If the special function already exists in the module, return it.
455 if (llvm::Function *F = CGM.getModule().getFunction(FuncName)) {
456 bool WrongType = false;
457 if (!F->getReturnType()->isVoidTy())
458 WrongType = true;
459 else {
460 for (const llvm::Argument &Arg : F->args())
461 if (Arg.getType() != CGM.Int8PtrPtrTy)
462 WrongType = true;
463 }
464
465 if (WrongType) {
466 std::string FuncName = std::string(F->getName());
467 SourceLocation Loc =
468 QT->castAs<RecordType>()->getOriginalDecl()->getLocation();
469 CGM.Error(Loc, "special function " + FuncName +
470 " for non-trivial C struct has incorrect type");
471 return nullptr;
472 }
473 return F;
474 }
475
476 ASTContext &Ctx = CGM.getContext();
477 FunctionArgList Args;
478 const CGFunctionInfo &FI = getFunctionInfo<N>(CGM, Args);
479 llvm::FunctionType *FuncTy = CGM.getTypes().GetFunctionType(FI);
480 llvm::Function *F =
481 llvm::Function::Create(FuncTy, llvm::GlobalValue::LinkOnceODRLinkage,
482 FuncName, &CGM.getModule());
483 F->setVisibility(llvm::GlobalValue::HiddenVisibility);
484 CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F, /*IsThunk=*/false);
486 CodeGenFunction NewCGF(CGM);
487 setCGF(&NewCGF);
488 CGF->StartFunction(GlobalDecl(), Ctx.VoidTy, F, FI, Args);
490 std::array<Address, N> Addrs =
491 getParamAddrs<N>(std::make_index_sequence<N>{}, Alignments, Args, CGF);
492 asDerived().visitStructFields(QT, CharUnits::Zero(), Addrs);
493 CGF->FinishFunction();
494 return F;
495 }
496
497 template <size_t N>
498 void callFunc(StringRef FuncName, QualType QT, std::array<Address, N> Addrs,
499 CodeGenFunction &CallerCGF) {
500 std::array<CharUnits, N> Alignments;
501 llvm::Value *Ptrs[N];
502
503 for (unsigned I = 0; I < N; ++I) {
504 Alignments[I] = Addrs[I].getAlignment();
505 Ptrs[I] = Addrs[I].emitRawPointer(CallerCGF);
506 }
507
508 if (llvm::Function *F =
509 getFunction(FuncName, QT, Alignments, CallerCGF.CGM))
510 CallerCGF.EmitNounwindRuntimeCall(F, Ptrs);
511 }
512
513 Derived &asDerived() { return static_cast<Derived &>(*this); }
514
515 void setCGF(CodeGenFunction *F) { CGF = F; }
516
517 CodeGenFunction *CGF = nullptr;
518};
519
520template <class Derived, bool IsMove>
521struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>,
522 GenFuncBase<Derived> {
523 GenBinaryFunc(ASTContext &Ctx) : CopyStructVisitor<Derived, IsMove>(Ctx) {}
524
525 void flushTrivialFields(std::array<Address, 2> Addrs) {
526 CharUnits Size = this->End - this->Start;
527
528 if (Size.getQuantity() == 0)
529 return;
530
531 Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], this->Start);
532 Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], this->Start);
533
534 // Emit memcpy.
535 if (Size.getQuantity() >= 16 ||
536 !llvm::has_single_bit<uint32_t>(Size.getQuantity())) {
537 llvm::Value *SizeVal =
538 llvm::ConstantInt::get(this->CGF->SizeTy, Size.getQuantity());
539 DstAddr = DstAddr.withElementType(this->CGF->Int8Ty);
540 SrcAddr = SrcAddr.withElementType(this->CGF->Int8Ty);
541 this->CGF->Builder.CreateMemCpy(DstAddr, SrcAddr, SizeVal, false);
542 } else {
543 llvm::Type *Ty = llvm::Type::getIntNTy(
544 this->CGF->getLLVMContext(),
545 Size.getQuantity() * this->CGF->getContext().getCharWidth());
546 DstAddr = DstAddr.withElementType(Ty);
547 SrcAddr = SrcAddr.withElementType(Ty);
548 llvm::Value *SrcVal = this->CGF->Builder.CreateLoad(SrcAddr, false);
549 this->CGF->Builder.CreateStore(SrcVal, DstAddr, false);
550 }
551
552 this->Start = this->End = CharUnits::Zero();
553 }
554
555 template <class... Ts>
556 void visitVolatileTrivial(QualType FT, const FieldDecl *FD, CharUnits Offset,
557 std::array<Address, 2> Addrs) {
558 LValue DstLV, SrcLV;
559 if (FD) {
560 // No need to copy zero-length bit-fields.
561 if (FD->isZeroLengthBitField())
562 return;
563
564 CanQualType RT =
565 this->CGF->getContext().getCanonicalTagType(FD->getParent());
566 llvm::Type *Ty = this->CGF->ConvertType(RT);
567 Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset);
568 LValue DstBase =
569 this->CGF->MakeAddrLValue(DstAddr.withElementType(Ty), FT);
570 DstLV = this->CGF->EmitLValueForField(DstBase, FD);
571 Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], Offset);
572 LValue SrcBase =
573 this->CGF->MakeAddrLValue(SrcAddr.withElementType(Ty), FT);
574 SrcLV = this->CGF->EmitLValueForField(SrcBase, FD);
575 } else {
576 llvm::Type *Ty = this->CGF->ConvertTypeForMem(FT);
577 Address DstAddr = Addrs[DstIdx].withElementType(Ty);
578 Address SrcAddr = Addrs[SrcIdx].withElementType(Ty);
579 DstLV = this->CGF->MakeAddrLValue(DstAddr, FT);
580 SrcLV = this->CGF->MakeAddrLValue(SrcAddr, FT);
581 }
582 RValue SrcVal = this->CGF->EmitLoadOfLValue(SrcLV, SourceLocation());
583 this->CGF->EmitStoreThroughLValue(SrcVal, DstLV);
584 }
585 void visitPtrAuth(QualType FT, const FieldDecl *FD, CharUnits CurStackOffset,
586 std::array<Address, 2> Addrs) {
587 PointerAuthQualifier PtrAuth = FT.getPointerAuth().withoutKeyNone();
588 Addrs[DstIdx] = this->getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
589 Addrs[SrcIdx] = this->getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);
590 this->CGF->EmitPointerAuthCopy(PtrAuth, FT, Addrs[DstIdx], Addrs[SrcIdx]);
591 }
592};
593
594// These classes that emit the special functions for a non-trivial struct.
595struct GenDestructor : StructVisitor<GenDestructor>,
596 GenFuncBase<GenDestructor>,
597 DestructedTypeVisitor<GenDestructor> {
598 using Super = DestructedTypeVisitor<GenDestructor>;
599 GenDestructor(ASTContext &Ctx) : StructVisitor<GenDestructor>(Ctx) {}
600
601 void visitWithKind(QualType::DestructionKind DK, QualType FT,
602 const FieldDecl *FD, CharUnits CurStructOffset,
603 std::array<Address, 1> Addrs) {
604 if (const auto *AT = getContext().getAsArrayType(FT)) {
605 visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset, Addrs);
606 return;
607 }
608
609 Super::visitWithKind(DK, FT, FD, CurStructOffset, Addrs);
610 }
611
612 void visitARCStrong(QualType QT, const FieldDecl *FD,
613 CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
615 *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
616 }
617
618 void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
619 std::array<Address, 1> Addrs) {
620 CGF->destroyARCWeak(
621 *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
622 }
623
624 void callSpecialFunction(QualType FT, CharUnits Offset,
625 std::array<Address, 1> Addrs) {
627 CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
628 }
629};
630
631struct GenDefaultInitialize
632 : StructVisitor<GenDefaultInitialize>,
633 GenFuncBase<GenDefaultInitialize>,
634 DefaultInitializedTypeVisitor<GenDefaultInitialize> {
635 using Super = DefaultInitializedTypeVisitor<GenDefaultInitialize>;
636 typedef GenFuncBase<GenDefaultInitialize> GenFuncBaseTy;
637
638 GenDefaultInitialize(ASTContext &Ctx)
639 : StructVisitor<GenDefaultInitialize>(Ctx) {}
640
641 void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
642 const FieldDecl *FD, CharUnits CurStructOffset,
643 std::array<Address, 1> Addrs) {
644 if (const auto *AT = getContext().getAsArrayType(FT)) {
645 visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset,
646 Addrs);
647 return;
648 }
649
650 Super::visitWithKind(PDIK, FT, FD, CurStructOffset, Addrs);
651 }
652
653 void visitARCStrong(QualType QT, const FieldDecl *FD,
654 CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
656 getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
657 }
658
659 void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
660 std::array<Address, 1> Addrs) {
662 getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
663 }
664
665 template <class FieldKind, size_t... Is>
666 void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
667 const FieldDecl *FD, CharUnits CurStructOffset,
668 std::array<Address, 1> Addrs) {
669 if (!FK)
670 return visitTrivial(QualType(AT, 0), FD, CurStructOffset, Addrs);
671
672 ASTContext &Ctx = getContext();
673 CharUnits Size = Ctx.getTypeSizeInChars(QualType(AT, 0));
674 QualType EltTy = Ctx.getBaseElementType(QualType(AT, 0));
675
676 if (Size < CharUnits::fromQuantity(16) ||
677 EltTy->getAsCanonical<RecordType>()) {
678 GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStructOffset, Addrs);
679 return;
680 }
681
682 llvm::Constant *SizeVal = CGF->Builder.getInt64(Size.getQuantity());
683 Address DstAddr = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
684 Address Loc = DstAddr.withElementType(CGF->Int8Ty);
685 CGF->Builder.CreateMemSet(Loc, CGF->Builder.getInt8(0), SizeVal,
686 IsVolatile);
687 }
688
689 void callSpecialFunction(QualType FT, CharUnits Offset,
690 std::array<Address, 1> Addrs) {
692 CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
693 }
694};
695
696struct GenCopyConstructor : GenBinaryFunc<GenCopyConstructor, false> {
697 GenCopyConstructor(ASTContext &Ctx)
698 : GenBinaryFunc<GenCopyConstructor, false>(Ctx) {}
699
700 void visitARCStrong(QualType QT, const FieldDecl *FD,
701 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
702 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
703 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
704 llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
705 Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
706 llvm::Value *Val = CGF->EmitARCRetain(QT, SrcVal);
707 CGF->EmitStoreOfScalar(Val, CGF->MakeAddrLValue(Addrs[DstIdx], QT), true);
708 }
709
710 void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
711 std::array<Address, 2> Addrs) {
712 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
713 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
714 CGF->EmitARCCopyWeak(Addrs[DstIdx], Addrs[SrcIdx]);
715 }
716
717 void callSpecialFunction(QualType FT, CharUnits Offset,
718 std::array<Address, 2> Addrs) {
719 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
720 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
721 CGF->callCStructCopyConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
722 CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
723 }
724};
725
726struct GenMoveConstructor : GenBinaryFunc<GenMoveConstructor, true> {
727 GenMoveConstructor(ASTContext &Ctx)
728 : GenBinaryFunc<GenMoveConstructor, true>(Ctx) {}
729
730 void visitARCStrong(QualType QT, const FieldDecl *FD,
731 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
732 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
733 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
734 LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
735 llvm::Value *SrcVal =
736 CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
737 CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress()), SrcLV);
738 CGF->EmitStoreOfScalar(SrcVal, CGF->MakeAddrLValue(Addrs[DstIdx], QT),
739 /* isInitialization */ true);
740 }
741
742 void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
743 std::array<Address, 2> Addrs) {
744 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
745 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
746 CGF->EmitARCMoveWeak(Addrs[DstIdx], Addrs[SrcIdx]);
747 }
748
749 void callSpecialFunction(QualType FT, CharUnits Offset,
750 std::array<Address, 2> Addrs) {
751 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
752 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
753 CGF->callCStructMoveConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
754 CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
755 }
756};
757
758struct GenCopyAssignment : GenBinaryFunc<GenCopyAssignment, false> {
759 GenCopyAssignment(ASTContext &Ctx)
760 : GenBinaryFunc<GenCopyAssignment, false>(Ctx) {}
761
762 void visitARCStrong(QualType QT, const FieldDecl *FD,
763 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
764 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
765 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
766 llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
767 Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
768 CGF->EmitARCStoreStrong(CGF->MakeAddrLValue(Addrs[DstIdx], QT), SrcVal,
769 false);
770 }
771
772 void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
773 std::array<Address, 2> Addrs) {
774 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
775 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
776 CGF->emitARCCopyAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
777 }
778
779 void callSpecialFunction(QualType FT, CharUnits Offset,
780 std::array<Address, 2> Addrs) {
781 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
782 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
784 CGF->MakeAddrLValue(Addrs[DstIdx], FT),
785 CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
786 }
787};
788
789struct GenMoveAssignment : GenBinaryFunc<GenMoveAssignment, true> {
790 GenMoveAssignment(ASTContext &Ctx)
791 : GenBinaryFunc<GenMoveAssignment, true>(Ctx) {}
792
793 void visitARCStrong(QualType QT, const FieldDecl *FD,
794 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
795 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
796 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
797 LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
798 llvm::Value *SrcVal =
799 CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
800 CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress()), SrcLV);
801 LValue DstLV = CGF->MakeAddrLValue(Addrs[DstIdx], QT);
802 llvm::Value *DstVal =
803 CGF->EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
804 CGF->EmitStoreOfScalar(SrcVal, DstLV);
806 }
807
808 void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
809 std::array<Address, 2> Addrs) {
810 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
811 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
812 CGF->emitARCMoveAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
813 }
814
815 void callSpecialFunction(QualType FT, CharUnits Offset,
816 std::array<Address, 2> Addrs) {
817 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
818 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
820 CGF->MakeAddrLValue(Addrs[DstIdx], FT),
821 CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
822 }
823};
824
825} // namespace
826
830}
831
832// Default-initialize a variable that is a non-trivial struct or an array of
833// such structure.
835 GenDefaultInitialize Gen(getContext());
836 Address DstPtr = Dst.getAddress().withElementType(CGM.Int8PtrTy);
837 Gen.setCGF(this);
838 QualType QT = Dst.getType();
839 QT = Dst.isVolatile() ? QT.withVolatile() : QT;
840 Gen.visit(QT, nullptr, CharUnits::Zero(), std::array<Address, 1>({{DstPtr}}));
841}
842
843template <class G, size_t N>
844static void callSpecialFunction(G &&Gen, StringRef FuncName, QualType QT,
845 bool IsVolatile, CodeGenFunction &CGF,
846 std::array<Address, N> Addrs) {
847 auto SetArtificialLoc = ApplyDebugLocation::CreateArtificial(CGF);
848 for (unsigned I = 0; I < N; ++I)
849 Addrs[I] = Addrs[I].withElementType(CGF.CGM.Int8PtrTy);
850 QT = IsVolatile ? QT.withVolatile() : QT;
851 Gen.callFunc(FuncName, QT, Addrs, CGF);
852}
853
854template <class G, size_t N>
855static llvm::Function *
856getSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile,
857 std::array<CharUnits, N> Alignments, CodeGenModule &CGM) {
858 QT = IsVolatile ? QT.withVolatile() : QT;
859 // The following call requires an array of addresses as arguments, but doesn't
860 // actually use them (it overwrites them with the addresses of the arguments
861 // of the created function).
862 return Gen.getFunction(FuncName, QT, Alignments, CGM);
863}
864
865// Functions to emit calls to the special functions of a non-trivial C struct.
867 bool IsVolatile = Dst.isVolatile();
868 Address DstPtr = Dst.getAddress();
869 QualType QT = Dst.getType();
870 GenDefaultInitializeFuncName GenName(DstPtr.getAlignment(), getContext());
871 std::string FuncName = GenName.getName(QT, IsVolatile);
872 callSpecialFunction(GenDefaultInitialize(getContext()), FuncName, QT,
873 IsVolatile, *this, std::array<Address, 1>({{DstPtr}}));
874}
875
877 QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx) {
878 GenBinaryFuncName<false> GenName("", Alignment, Alignment, Ctx);
879 return GenName.getName(QT, IsVolatile);
880}
881
883 CharUnits Alignment,
884 bool IsVolatile,
885 ASTContext &Ctx) {
886 GenDestructorFuncName GenName("", Alignment, Ctx);
887 return GenName.getName(QT, IsVolatile);
888}
889
891 bool IsVolatile = Dst.isVolatile();
892 Address DstPtr = Dst.getAddress();
893 QualType QT = Dst.getType();
894 GenDestructorFuncName GenName("__destructor_", DstPtr.getAlignment(),
895 getContext());
896 std::string FuncName = GenName.getName(QT, IsVolatile);
897 callSpecialFunction(GenDestructor(getContext()), FuncName, QT, IsVolatile,
898 *this, std::array<Address, 1>({{DstPtr}}));
899}
900
902 bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
903 Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress();
904 QualType QT = Dst.getType();
905 GenBinaryFuncName<false> GenName("__copy_constructor_", DstPtr.getAlignment(),
906 SrcPtr.getAlignment(), getContext());
907 std::string FuncName = GenName.getName(QT, IsVolatile);
908 callSpecialFunction(GenCopyConstructor(getContext()), FuncName, QT,
909 IsVolatile, *this,
910 std::array<Address, 2>({{DstPtr, SrcPtr}}));
911}
912
914
915) {
916 bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
917 Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress();
918 QualType QT = Dst.getType();
919 GenBinaryFuncName<false> GenName("__copy_assignment_", DstPtr.getAlignment(),
920 SrcPtr.getAlignment(), getContext());
921 std::string FuncName = GenName.getName(QT, IsVolatile);
922 callSpecialFunction(GenCopyAssignment(getContext()), FuncName, QT, IsVolatile,
923 *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
924}
925
927 bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
928 Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress();
929 QualType QT = Dst.getType();
930 GenBinaryFuncName<true> GenName("__move_constructor_", DstPtr.getAlignment(),
931 SrcPtr.getAlignment(), getContext());
932 std::string FuncName = GenName.getName(QT, IsVolatile);
933 callSpecialFunction(GenMoveConstructor(getContext()), FuncName, QT,
934 IsVolatile, *this,
935 std::array<Address, 2>({{DstPtr, SrcPtr}}));
936}
937
939
940) {
941 bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
942 Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress();
943 QualType QT = Dst.getType();
944 GenBinaryFuncName<true> GenName("__move_assignment_", DstPtr.getAlignment(),
945 SrcPtr.getAlignment(), getContext());
946 std::string FuncName = GenName.getName(QT, IsVolatile);
947 callSpecialFunction(GenMoveAssignment(getContext()), FuncName, QT, IsVolatile,
948 *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
949}
950
952 CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
953 ASTContext &Ctx = CGM.getContext();
954 GenDefaultInitializeFuncName GenName(DstAlignment, Ctx);
955 std::string FuncName = GenName.getName(QT, IsVolatile);
956 return getSpecialFunction(GenDefaultInitialize(Ctx), FuncName, QT, IsVolatile,
957 std::array<CharUnits, 1>({{DstAlignment}}), CGM);
958}
959
961 CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
962 bool IsVolatile, QualType QT) {
963 ASTContext &Ctx = CGM.getContext();
964 GenBinaryFuncName<false> GenName("__copy_constructor_", DstAlignment,
965 SrcAlignment, Ctx);
966 std::string FuncName = GenName.getName(QT, IsVolatile);
967 return getSpecialFunction(
968 GenCopyConstructor(Ctx), FuncName, QT, IsVolatile,
969 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
970}
971
973 CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
974 bool IsVolatile, QualType QT) {
975 ASTContext &Ctx = CGM.getContext();
976 GenBinaryFuncName<true> GenName("__move_constructor_", DstAlignment,
977 SrcAlignment, Ctx);
978 std::string FuncName = GenName.getName(QT, IsVolatile);
979 return getSpecialFunction(
980 GenMoveConstructor(Ctx), FuncName, QT, IsVolatile,
981 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
982}
983
985 CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
986 bool IsVolatile, QualType QT) {
987 ASTContext &Ctx = CGM.getContext();
988 GenBinaryFuncName<false> GenName("__copy_assignment_", DstAlignment,
989 SrcAlignment, Ctx);
990 std::string FuncName = GenName.getName(QT, IsVolatile);
991 return getSpecialFunction(
992 GenCopyAssignment(Ctx), FuncName, QT, IsVolatile,
993 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
994}
995
997 CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
998 bool IsVolatile, QualType QT) {
999 ASTContext &Ctx = CGM.getContext();
1000 GenBinaryFuncName<true> GenName("__move_assignment_", DstAlignment,
1001 SrcAlignment, Ctx);
1002 std::string FuncName = GenName.getName(QT, IsVolatile);
1003 return getSpecialFunction(
1004 GenMoveAssignment(Ctx), FuncName, QT, IsVolatile,
1005 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
1006}
1007
1009 CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
1010 ASTContext &Ctx = CGM.getContext();
1011 GenDestructorFuncName GenName("__destructor_", DstAlignment, Ctx);
1012 std::string FuncName = GenName.getName(QT, IsVolatile);
1013 return getSpecialFunction(GenDestructor(Ctx), FuncName, QT, IsVolatile,
1014 std::array<CharUnits, 1>({{DstAlignment}}), CGM);
1015}
static bool getFieldOffsetInBits(CodeGenFunction &CGF, const RecordDecl *RD, const FieldDecl *Field, int64_t &Offset)
The offset of a field from the beginning of the record.
Definition CGExpr.cpp:4454
static uint64_t getFieldSize(const FieldDecl *FD, QualType FT, ASTContext &Ctx)
static void callSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile, CodeGenFunction &CGF, std::array< Address, N > Addrs)
static llvm::Function * getSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile, std::array< CharUnits, N > Alignments, CodeGenModule &CGM)
static llvm::Constant * getNullForVariable(Address addr)
Given the address of a variable of pointer type, find the correct null to store into it.
Definition CGObjC.cpp:45
static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:188
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType VoidPtrTy
IdentifierTable & Idents
Definition ASTContext.h:737
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType VoidTy
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
CanQualType getCanonicalTagType(const TagDecl *TD) const
uint64_t getCharWidth() const
Return the size of the character type, in bits.
QualType getElementType() const
Definition TypeBase.h:3732
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Definition CharUnits.h:53
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
Definition Address.h:128
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
Definition Address.h:253
CharUnits getAlignment() const
Definition Address.h:194
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
Definition Address.h:276
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)
Apply TemporaryLocation if it is valid.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Definition CGBuilder.h:140
llvm::CallInst * CreateMemSet(Address Dest, llvm::Value *Value, llvm::Value *Size, bool IsVolatile=false)
Definition CGBuilder.h:402
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
Definition CGBuilder.h:112
llvm::CallInst * CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile=false)
Definition CGBuilder.h:369
CGFunctionInfo - Class to encapsulate the information about a function definition.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitARCMoveWeak(Address dst, Address src)
void @objc_moveWeak(i8** dest, i8** src) Disregards the current value in dest.
Definition CGObjC.cpp:2692
void callCStructMoveConstructor(LValue Dst, LValue Src)
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
llvm::Type * ConvertType(QualType T)
llvm::Value * EmitARCRetain(QualType type, llvm::Value *value)
Produce the code to do a retain.
Definition CGObjC.cpp:2328
llvm::Value * EmitARCStoreStrong(LValue lvalue, llvm::Value *value, bool resultIgnored)
Store into a strong object.
Definition CGObjC.cpp:2545
static std::string getNonTrivialDestructorStr(QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx)
void EmitARCRelease(llvm::Value *value, ARCPreciseLifetime_t precise)
Release the given object.
Definition CGObjC.cpp:2481
LValue EmitLValueForField(LValue Base, const FieldDecl *Field, bool IsInBounds=true)
Definition CGExpr.cpp:5252
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
Definition CGExpr.cpp:2336
void callCStructCopyAssignmentOperator(LValue Dst, LValue Src)
void callCStructCopyConstructor(LValue Dst, LValue Src)
void EmitPointerAuthCopy(PointerAuthQualifier Qualifier, QualType Type, Address DestField, Address SrcField)
void callCStructMoveAssignmentOperator(LValue Dst, LValue Src)
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
void emitARCMoveAssignWeak(QualType Ty, Address DstAddr, Address SrcAddr)
Definition CGObjC.cpp:2714
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
Definition CGExpr.cpp:2533
llvm::Type * ConvertTypeForMem(QualType T)
static std::string getNonTrivialCopyConstructorStr(QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx)
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
llvm::LLVMContext & getLLVMContext()
void EmitARCCopyWeak(Address dst, Address src)
void @objc_copyWeak(i8** dest, i8** src) Disregards the current value in dest.
Definition CGObjC.cpp:2701
void emitARCCopyAssignWeak(QualType Ty, Address DstAddr, Address SrcAddr)
Definition CGObjC.cpp:2707
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
This class organizes the cross-function state that is used while generating LLVM code.
llvm::Module & getModule() const
void Error(SourceLocation loc, StringRef error)
Emit a general error that something can't be done.
ASTContext & getContext() const
void SetLLVMFunctionAttributes(GlobalDecl GD, const CGFunctionInfo &Info, llvm::Function *F, bool IsThunk)
Set the LLVM function attributes (sext, zext, etc).
void SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F)
Set the LLVM function attributes which only apply to a function definition.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
Definition CGCall.cpp:1701
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
Definition CGCall.cpp:739
FunctionArgList - Type for representing both the decl and type of parameters to a function.
Definition CGCall.h:375
LValue - This represents an lvalue references.
Definition CGValue.h:182
bool isVolatile() const
Definition CGValue.h:328
Address getAddress() const
Definition CGValue.h:361
QualType getType() const
Definition CGValue.h:291
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
Definition CGValue.h:71
Represents a member of a struct/union/class.
Definition Decl.h:3157
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:3260
unsigned getBitWidthValue() const
Computes the bit width of this field, if this is a bit field.
Definition Decl.cpp:4693
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition Decl.h:3242
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3393
bool isZeroLengthBitField() const
Is this a zero-length bit-field?
Definition Decl.cpp:4702
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
Definition Decl.cpp:5470
bool authenticatesNullValues() const
Definition TypeBase.h:285
PointerAuthQualifier withoutKeyNone() const
Definition TypeBase.h:290
unsigned getExtraDiscriminator() const
Definition TypeBase.h:270
unsigned getKey() const
Definition TypeBase.h:258
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
Definition TypeBase.h:8369
PointerAuthQualifier getPointerAuth() const
Definition TypeBase.h:1453
QualType withVolatile() const
Definition TypeBase.h:1167
Encodes a location in the source.
The base class of the type hierarchy.
Definition TypeBase.h:1833
bool isBlockPointerType() const
Definition TypeBase.h:8542
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9168
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:2921
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
Definition CGValue.h:154
llvm::Function * getNonTrivialCStructCopyConstructor(CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment, bool IsVolatile, QualType QT)
Returns the copy constructor for a C struct with non-trivially copyable fields, generating it if nece...
llvm::Function * getNonTrivialCStructMoveConstructor(CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment, bool IsVolatile, QualType QT)
Returns the move constructor for a C struct with non-trivially copyable fields, generating it if nece...
llvm::Function * getNonTrivialCStructCopyAssignmentOperator(CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment, bool IsVolatile, QualType QT)
Returns the copy assignment operator for a C struct with non-trivially copyable fields,...
llvm::Function * getNonTrivialCStructMoveAssignmentOperator(CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment, bool IsVolatile, QualType QT)
Return the move assignment operator for a C struct with non-trivially copyable fields,...
@ ARCImpreciseLifetime
Definition CGValue.h:136
llvm::Function * getNonTrivialCStructDestructor(CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT)
Returns the destructor for a C struct with non-trivially copyable fields, generating it if necessary.
llvm::Function * getNonTrivialCStructDefaultConstructor(CodeGenModule &GCM, CharUnits DstAlignment, bool IsVolatile, QualType QT)
Returns the default constructor for a C struct with non-trivially copyable fields,...
StringRef getName(const HeaderType T)
Definition HeaderFile.h:38
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
U cast(CodeGen::Address addr)
Definition Address.h:327
@ Other
Other implicit parameter.
Definition Decl.h:1745
unsigned long uint64_t
#define false
Definition stdbool.h:26
#define true
Definition stdbool.h:25
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
RetTy visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT, Ts &&... Args)
void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT, Ts &&... Args)
void visitWithKind(QualType::DestructionKind DK, QualType FT, Ts &&... Args)