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 = QT->castAs<RecordType>()->getDecl()->getLocation();
468 CGM.Error(Loc, "special function " + FuncName +
469 " for non-trivial C struct has incorrect type");
470 return nullptr;
471 }
472 return F;
473 }
474
475 ASTContext &Ctx = CGM.getContext();
476 FunctionArgList Args;
477 const CGFunctionInfo &FI = getFunctionInfo<N>(CGM, Args);
478 llvm::FunctionType *FuncTy = CGM.getTypes().GetFunctionType(FI);
479 llvm::Function *F =
480 llvm::Function::Create(FuncTy, llvm::GlobalValue::LinkOnceODRLinkage,
481 FuncName, &CGM.getModule());
482 F->setVisibility(llvm::GlobalValue::HiddenVisibility);
483 CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F, /*IsThunk=*/false);
485 CodeGenFunction NewCGF(CGM);
486 setCGF(&NewCGF);
487 CGF->StartFunction(GlobalDecl(), Ctx.VoidTy, F, FI, Args);
489 std::array<Address, N> Addrs =
490 getParamAddrs<N>(std::make_index_sequence<N>{}, Alignments, Args, CGF);
491 asDerived().visitStructFields(QT, CharUnits::Zero(), Addrs);
492 CGF->FinishFunction();
493 return F;
494 }
495
496 template <size_t N>
497 void callFunc(StringRef FuncName, QualType QT, std::array<Address, N> Addrs,
498 CodeGenFunction &CallerCGF) {
499 std::array<CharUnits, N> Alignments;
500 llvm::Value *Ptrs[N];
501
502 for (unsigned I = 0; I < N; ++I) {
503 Alignments[I] = Addrs[I].getAlignment();
504 Ptrs[I] = Addrs[I].emitRawPointer(CallerCGF);
505 }
506
507 if (llvm::Function *F =
508 getFunction(FuncName, QT, Alignments, CallerCGF.CGM))
509 CallerCGF.EmitNounwindRuntimeCall(F, Ptrs);
510 }
511
512 Derived &asDerived() { return static_cast<Derived &>(*this); }
513
514 void setCGF(CodeGenFunction *F) { CGF = F; }
515
516 CodeGenFunction *CGF = nullptr;
517};
518
519template <class Derived, bool IsMove>
520struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>,
521 GenFuncBase<Derived> {
522 GenBinaryFunc(ASTContext &Ctx) : CopyStructVisitor<Derived, IsMove>(Ctx) {}
523
524 void flushTrivialFields(std::array<Address, 2> Addrs) {
525 CharUnits Size = this->End - this->Start;
526
527 if (Size.getQuantity() == 0)
528 return;
529
530 Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], this->Start);
531 Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], this->Start);
532
533 // Emit memcpy.
534 if (Size.getQuantity() >= 16 ||
535 !llvm::has_single_bit<uint32_t>(Size.getQuantity())) {
536 llvm::Value *SizeVal =
537 llvm::ConstantInt::get(this->CGF->SizeTy, Size.getQuantity());
538 DstAddr = DstAddr.withElementType(this->CGF->Int8Ty);
539 SrcAddr = SrcAddr.withElementType(this->CGF->Int8Ty);
540 this->CGF->Builder.CreateMemCpy(DstAddr, SrcAddr, SizeVal, false);
541 } else {
542 llvm::Type *Ty = llvm::Type::getIntNTy(
543 this->CGF->getLLVMContext(),
544 Size.getQuantity() * this->CGF->getContext().getCharWidth());
545 DstAddr = DstAddr.withElementType(Ty);
546 SrcAddr = SrcAddr.withElementType(Ty);
547 llvm::Value *SrcVal = this->CGF->Builder.CreateLoad(SrcAddr, false);
548 this->CGF->Builder.CreateStore(SrcVal, DstAddr, false);
549 }
550
551 this->Start = this->End = CharUnits::Zero();
552 }
553
554 template <class... Ts>
555 void visitVolatileTrivial(QualType FT, const FieldDecl *FD, CharUnits Offset,
556 std::array<Address, 2> Addrs) {
557 LValue DstLV, SrcLV;
558 if (FD) {
559 // No need to copy zero-length bit-fields.
560 if (FD->isZeroLengthBitField())
561 return;
562
563 CanQualType RT =
564 this->CGF->getContext().getCanonicalTagType(FD->getParent());
565 llvm::Type *Ty = this->CGF->ConvertType(RT);
566 Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset);
567 LValue DstBase =
568 this->CGF->MakeAddrLValue(DstAddr.withElementType(Ty), FT);
569 DstLV = this->CGF->EmitLValueForField(DstBase, FD);
570 Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], Offset);
571 LValue SrcBase =
572 this->CGF->MakeAddrLValue(SrcAddr.withElementType(Ty), FT);
573 SrcLV = this->CGF->EmitLValueForField(SrcBase, FD);
574 } else {
575 llvm::Type *Ty = this->CGF->ConvertTypeForMem(FT);
576 Address DstAddr = Addrs[DstIdx].withElementType(Ty);
577 Address SrcAddr = Addrs[SrcIdx].withElementType(Ty);
578 DstLV = this->CGF->MakeAddrLValue(DstAddr, FT);
579 SrcLV = this->CGF->MakeAddrLValue(SrcAddr, FT);
580 }
581 RValue SrcVal = this->CGF->EmitLoadOfLValue(SrcLV, SourceLocation());
582 this->CGF->EmitStoreThroughLValue(SrcVal, DstLV);
583 }
584 void visitPtrAuth(QualType FT, const FieldDecl *FD, CharUnits CurStackOffset,
585 std::array<Address, 2> Addrs) {
586 PointerAuthQualifier PtrAuth = FT.getPointerAuth().withoutKeyNone();
587 Addrs[DstIdx] = this->getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
588 Addrs[SrcIdx] = this->getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);
589 this->CGF->EmitPointerAuthCopy(PtrAuth, FT, Addrs[DstIdx], Addrs[SrcIdx]);
590 }
591};
592
593// These classes that emit the special functions for a non-trivial struct.
594struct GenDestructor : StructVisitor<GenDestructor>,
595 GenFuncBase<GenDestructor>,
596 DestructedTypeVisitor<GenDestructor> {
597 using Super = DestructedTypeVisitor<GenDestructor>;
598 GenDestructor(ASTContext &Ctx) : StructVisitor<GenDestructor>(Ctx) {}
599
600 void visitWithKind(QualType::DestructionKind DK, QualType FT,
601 const FieldDecl *FD, CharUnits CurStructOffset,
602 std::array<Address, 1> Addrs) {
603 if (const auto *AT = getContext().getAsArrayType(FT)) {
604 visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset, Addrs);
605 return;
606 }
607
608 Super::visitWithKind(DK, FT, FD, CurStructOffset, Addrs);
609 }
610
611 void visitARCStrong(QualType QT, const FieldDecl *FD,
612 CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
614 *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
615 }
616
617 void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
618 std::array<Address, 1> Addrs) {
619 CGF->destroyARCWeak(
620 *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
621 }
622
623 void callSpecialFunction(QualType FT, CharUnits Offset,
624 std::array<Address, 1> Addrs) {
626 CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
627 }
628};
629
630struct GenDefaultInitialize
631 : StructVisitor<GenDefaultInitialize>,
632 GenFuncBase<GenDefaultInitialize>,
633 DefaultInitializedTypeVisitor<GenDefaultInitialize> {
634 using Super = DefaultInitializedTypeVisitor<GenDefaultInitialize>;
635 typedef GenFuncBase<GenDefaultInitialize> GenFuncBaseTy;
636
637 GenDefaultInitialize(ASTContext &Ctx)
638 : StructVisitor<GenDefaultInitialize>(Ctx) {}
639
640 void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
641 const FieldDecl *FD, CharUnits CurStructOffset,
642 std::array<Address, 1> Addrs) {
643 if (const auto *AT = getContext().getAsArrayType(FT)) {
644 visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset,
645 Addrs);
646 return;
647 }
648
649 Super::visitWithKind(PDIK, FT, FD, CurStructOffset, Addrs);
650 }
651
652 void visitARCStrong(QualType QT, const FieldDecl *FD,
653 CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
655 getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
656 }
657
658 void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
659 std::array<Address, 1> Addrs) {
661 getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
662 }
663
664 template <class FieldKind, size_t... Is>
665 void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
666 const FieldDecl *FD, CharUnits CurStructOffset,
667 std::array<Address, 1> Addrs) {
668 if (!FK)
669 return visitTrivial(QualType(AT, 0), FD, CurStructOffset, Addrs);
670
671 ASTContext &Ctx = getContext();
672 CharUnits Size = Ctx.getTypeSizeInChars(QualType(AT, 0));
673 QualType EltTy = Ctx.getBaseElementType(QualType(AT, 0));
674
675 if (Size < CharUnits::fromQuantity(16) ||
676 EltTy->getAsCanonical<RecordType>()) {
677 GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStructOffset, Addrs);
678 return;
679 }
680
681 llvm::Constant *SizeVal = CGF->Builder.getInt64(Size.getQuantity());
682 Address DstAddr = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
683 Address Loc = DstAddr.withElementType(CGF->Int8Ty);
684 CGF->Builder.CreateMemSet(Loc, CGF->Builder.getInt8(0), SizeVal,
685 IsVolatile);
686 }
687
688 void callSpecialFunction(QualType FT, CharUnits Offset,
689 std::array<Address, 1> Addrs) {
691 CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
692 }
693};
694
695struct GenCopyConstructor : GenBinaryFunc<GenCopyConstructor, false> {
696 GenCopyConstructor(ASTContext &Ctx)
697 : GenBinaryFunc<GenCopyConstructor, false>(Ctx) {}
698
699 void visitARCStrong(QualType QT, const FieldDecl *FD,
700 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
701 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
702 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
703 llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
704 Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
705 llvm::Value *Val = CGF->EmitARCRetain(QT, SrcVal);
706 CGF->EmitStoreOfScalar(Val, CGF->MakeAddrLValue(Addrs[DstIdx], QT), true);
707 }
708
709 void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
710 std::array<Address, 2> Addrs) {
711 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
712 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
713 CGF->EmitARCCopyWeak(Addrs[DstIdx], Addrs[SrcIdx]);
714 }
715
716 void callSpecialFunction(QualType FT, CharUnits Offset,
717 std::array<Address, 2> Addrs) {
718 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
719 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
720 CGF->callCStructCopyConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
721 CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
722 }
723};
724
725struct GenMoveConstructor : GenBinaryFunc<GenMoveConstructor, true> {
726 GenMoveConstructor(ASTContext &Ctx)
727 : GenBinaryFunc<GenMoveConstructor, true>(Ctx) {}
728
729 void visitARCStrong(QualType QT, const FieldDecl *FD,
730 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
731 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
732 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
733 LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
734 llvm::Value *SrcVal =
735 CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
736 CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress()), SrcLV);
737 CGF->EmitStoreOfScalar(SrcVal, CGF->MakeAddrLValue(Addrs[DstIdx], QT),
738 /* isInitialization */ true);
739 }
740
741 void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
742 std::array<Address, 2> Addrs) {
743 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
744 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
745 CGF->EmitARCMoveWeak(Addrs[DstIdx], Addrs[SrcIdx]);
746 }
747
748 void callSpecialFunction(QualType FT, CharUnits Offset,
749 std::array<Address, 2> Addrs) {
750 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
751 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
752 CGF->callCStructMoveConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
753 CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
754 }
755};
756
757struct GenCopyAssignment : GenBinaryFunc<GenCopyAssignment, false> {
758 GenCopyAssignment(ASTContext &Ctx)
759 : GenBinaryFunc<GenCopyAssignment, false>(Ctx) {}
760
761 void visitARCStrong(QualType QT, const FieldDecl *FD,
762 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
763 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
764 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
765 llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
766 Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
767 CGF->EmitARCStoreStrong(CGF->MakeAddrLValue(Addrs[DstIdx], QT), SrcVal,
768 false);
769 }
770
771 void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
772 std::array<Address, 2> Addrs) {
773 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
774 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
775 CGF->emitARCCopyAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
776 }
777
778 void callSpecialFunction(QualType FT, CharUnits Offset,
779 std::array<Address, 2> Addrs) {
780 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
781 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
783 CGF->MakeAddrLValue(Addrs[DstIdx], FT),
784 CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
785 }
786};
787
788struct GenMoveAssignment : GenBinaryFunc<GenMoveAssignment, true> {
789 GenMoveAssignment(ASTContext &Ctx)
790 : GenBinaryFunc<GenMoveAssignment, true>(Ctx) {}
791
792 void visitARCStrong(QualType QT, const FieldDecl *FD,
793 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
794 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
795 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
796 LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
797 llvm::Value *SrcVal =
798 CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
799 CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress()), SrcLV);
800 LValue DstLV = CGF->MakeAddrLValue(Addrs[DstIdx], QT);
801 llvm::Value *DstVal =
802 CGF->EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
803 CGF->EmitStoreOfScalar(SrcVal, DstLV);
805 }
806
807 void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
808 std::array<Address, 2> Addrs) {
809 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
810 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
811 CGF->emitARCMoveAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
812 }
813
814 void callSpecialFunction(QualType FT, CharUnits Offset,
815 std::array<Address, 2> Addrs) {
816 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
817 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
819 CGF->MakeAddrLValue(Addrs[DstIdx], FT),
820 CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
821 }
822};
823
824} // namespace
825
829}
830
831// Default-initialize a variable that is a non-trivial struct or an array of
832// such structure.
834 GenDefaultInitialize Gen(getContext());
835 Address DstPtr = Dst.getAddress().withElementType(CGM.Int8PtrTy);
836 Gen.setCGF(this);
837 QualType QT = Dst.getType();
838 QT = Dst.isVolatile() ? QT.withVolatile() : QT;
839 Gen.visit(QT, nullptr, CharUnits::Zero(), std::array<Address, 1>({{DstPtr}}));
840}
841
842template <class G, size_t N>
843static void callSpecialFunction(G &&Gen, StringRef FuncName, QualType QT,
844 bool IsVolatile, CodeGenFunction &CGF,
845 std::array<Address, N> Addrs) {
846 auto SetArtificialLoc = ApplyDebugLocation::CreateArtificial(CGF);
847 for (unsigned I = 0; I < N; ++I)
848 Addrs[I] = Addrs[I].withElementType(CGF.CGM.Int8PtrTy);
849 QT = IsVolatile ? QT.withVolatile() : QT;
850 Gen.callFunc(FuncName, QT, Addrs, CGF);
851}
852
853template <class G, size_t N>
854static llvm::Function *
855getSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile,
856 std::array<CharUnits, N> Alignments, CodeGenModule &CGM) {
857 QT = IsVolatile ? QT.withVolatile() : QT;
858 // The following call requires an array of addresses as arguments, but doesn't
859 // actually use them (it overwrites them with the addresses of the arguments
860 // of the created function).
861 return Gen.getFunction(FuncName, QT, Alignments, CGM);
862}
863
864// Functions to emit calls to the special functions of a non-trivial C struct.
866 bool IsVolatile = Dst.isVolatile();
867 Address DstPtr = Dst.getAddress();
868 QualType QT = Dst.getType();
869 GenDefaultInitializeFuncName GenName(DstPtr.getAlignment(), getContext());
870 std::string FuncName = GenName.getName(QT, IsVolatile);
871 callSpecialFunction(GenDefaultInitialize(getContext()), FuncName, QT,
872 IsVolatile, *this, std::array<Address, 1>({{DstPtr}}));
873}
874
876 QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx) {
877 GenBinaryFuncName<false> GenName("", Alignment, Alignment, Ctx);
878 return GenName.getName(QT, IsVolatile);
879}
880
882 CharUnits Alignment,
883 bool IsVolatile,
884 ASTContext &Ctx) {
885 GenDestructorFuncName GenName("", Alignment, Ctx);
886 return GenName.getName(QT, IsVolatile);
887}
888
890 bool IsVolatile = Dst.isVolatile();
891 Address DstPtr = Dst.getAddress();
892 QualType QT = Dst.getType();
893 GenDestructorFuncName GenName("__destructor_", DstPtr.getAlignment(),
894 getContext());
895 std::string FuncName = GenName.getName(QT, IsVolatile);
896 callSpecialFunction(GenDestructor(getContext()), FuncName, QT, IsVolatile,
897 *this, std::array<Address, 1>({{DstPtr}}));
898}
899
901 bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
902 Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress();
903 QualType QT = Dst.getType();
904 GenBinaryFuncName<false> GenName("__copy_constructor_", DstPtr.getAlignment(),
905 SrcPtr.getAlignment(), getContext());
906 std::string FuncName = GenName.getName(QT, IsVolatile);
907 callSpecialFunction(GenCopyConstructor(getContext()), FuncName, QT,
908 IsVolatile, *this,
909 std::array<Address, 2>({{DstPtr, SrcPtr}}));
910}
911
913
914) {
915 bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
916 Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress();
917 QualType QT = Dst.getType();
918 GenBinaryFuncName<false> GenName("__copy_assignment_", DstPtr.getAlignment(),
919 SrcPtr.getAlignment(), getContext());
920 std::string FuncName = GenName.getName(QT, IsVolatile);
921 callSpecialFunction(GenCopyAssignment(getContext()), FuncName, QT, IsVolatile,
922 *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
923}
924
926 bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
927 Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress();
928 QualType QT = Dst.getType();
929 GenBinaryFuncName<true> GenName("__move_constructor_", DstPtr.getAlignment(),
930 SrcPtr.getAlignment(), getContext());
931 std::string FuncName = GenName.getName(QT, IsVolatile);
932 callSpecialFunction(GenMoveConstructor(getContext()), FuncName, QT,
933 IsVolatile, *this,
934 std::array<Address, 2>({{DstPtr, SrcPtr}}));
935}
936
938
939) {
940 bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
941 Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress();
942 QualType QT = Dst.getType();
943 GenBinaryFuncName<true> GenName("__move_assignment_", DstPtr.getAlignment(),
944 SrcPtr.getAlignment(), getContext());
945 std::string FuncName = GenName.getName(QT, IsVolatile);
946 callSpecialFunction(GenMoveAssignment(getContext()), FuncName, QT, IsVolatile,
947 *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
948}
949
951 CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
952 ASTContext &Ctx = CGM.getContext();
953 GenDefaultInitializeFuncName GenName(DstAlignment, Ctx);
954 std::string FuncName = GenName.getName(QT, IsVolatile);
955 return getSpecialFunction(GenDefaultInitialize(Ctx), FuncName, QT, IsVolatile,
956 std::array<CharUnits, 1>({{DstAlignment}}), CGM);
957}
958
960 CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
961 bool IsVolatile, QualType QT) {
962 ASTContext &Ctx = CGM.getContext();
963 GenBinaryFuncName<false> GenName("__copy_constructor_", DstAlignment,
964 SrcAlignment, Ctx);
965 std::string FuncName = GenName.getName(QT, IsVolatile);
966 return getSpecialFunction(
967 GenCopyConstructor(Ctx), FuncName, QT, IsVolatile,
968 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
969}
970
972 CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
973 bool IsVolatile, QualType QT) {
974 ASTContext &Ctx = CGM.getContext();
975 GenBinaryFuncName<true> GenName("__move_constructor_", DstAlignment,
976 SrcAlignment, Ctx);
977 std::string FuncName = GenName.getName(QT, IsVolatile);
978 return getSpecialFunction(
979 GenMoveConstructor(Ctx), FuncName, QT, IsVolatile,
980 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
981}
982
984 CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
985 bool IsVolatile, QualType QT) {
986 ASTContext &Ctx = CGM.getContext();
987 GenBinaryFuncName<false> GenName("__copy_assignment_", DstAlignment,
988 SrcAlignment, Ctx);
989 std::string FuncName = GenName.getName(QT, IsVolatile);
990 return getSpecialFunction(
991 GenCopyAssignment(Ctx), FuncName, QT, IsVolatile,
992 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
993}
994
996 CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
997 bool IsVolatile, QualType QT) {
998 ASTContext &Ctx = CGM.getContext();
999 GenBinaryFuncName<true> GenName("__move_assignment_", DstAlignment,
1000 SrcAlignment, Ctx);
1001 std::string FuncName = GenName.getName(QT, IsVolatile);
1002 return getSpecialFunction(
1003 GenMoveAssignment(Ctx), FuncName, QT, IsVolatile,
1004 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
1005}
1006
1008 CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
1009 ASTContext &Ctx = CGM.getContext();
1010 GenDestructorFuncName GenName("__destructor_", DstAlignment, Ctx);
1011 std::string FuncName = GenName.getName(QT, IsVolatile);
1012 return getSpecialFunction(GenDestructor(Ctx), FuncName, QT, IsVolatile,
1013 std::array<CharUnits, 1>({{DstAlignment}}), CGM);
1014}
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:4645
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:220
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:772
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:3734
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:5443
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
Definition CGExpr.cpp:2527
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:2724
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:3160
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:3263
unsigned getBitWidthValue() const
Computes the bit width of this field, if this is a bit field.
Definition Decl.cpp:4741
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition Decl.h:3245
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3396
bool isZeroLengthBitField() const
Is this a zero-length bit-field?
Definition Decl.cpp:4750
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:5522
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:8374
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:8547
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9170
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:1746
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)