clang 24.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, bool IsCtor>
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 // FT is volatile-qualified, so propagate that onto the base lvalue's
567 // type.
568 QualType QT = QualType(RT).withVolatile();
569 Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset);
570 LValue DstBase =
571 this->CGF->MakeAddrLValue(DstAddr.withElementType(Ty), QT);
572 DstLV = this->CGF->EmitLValueForField(DstBase, FD);
573 Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], Offset);
574 LValue SrcBase =
575 this->CGF->MakeAddrLValue(SrcAddr.withElementType(Ty), QT);
576 SrcLV = this->CGF->EmitLValueForField(SrcBase, FD);
577 } else {
578 llvm::Type *Ty = this->CGF->ConvertTypeForMem(FT);
579 Address DstAddr = Addrs[DstIdx].withElementType(Ty);
580 Address SrcAddr = Addrs[SrcIdx].withElementType(Ty);
581 DstLV = this->CGF->MakeAddrLValue(DstAddr, FT);
582 SrcLV = this->CGF->MakeAddrLValue(SrcAddr, FT);
583 }
584 // Load the value from the source. For the aggregate case, load directly
585 // into DstLV's own storage via an AggValueSlot.
586 AggValueSlot Slot = AggValueSlot::forLValue(
590 RValue SrcVal =
591 this->CGF->EmitLoadOfAnyValue(SrcLV, Slot, SourceLocation());
593 case TEK_Aggregate:
594 break; // Already copied into DstLV via Slot above.
595 case TEK_Complex:
596 this->CGF->EmitStoreOfComplex(SrcVal.getComplexVal(), DstLV,
597 /*isInit=*/IsCtor);
598 break;
599 case TEK_Scalar:
600 this->CGF->EmitStoreThroughLValue(SrcVal, DstLV, /*isInit=*/IsCtor);
601 break;
602 }
603 }
604 void visitPtrAuth(QualType FT, const FieldDecl *FD, CharUnits CurStackOffset,
605 std::array<Address, 2> Addrs) {
606 PointerAuthQualifier PtrAuth = FT.getPointerAuth().withoutKeyNone();
607 Addrs[DstIdx] = this->getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
608 Addrs[SrcIdx] = this->getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);
609 this->CGF->EmitPointerAuthCopy(PtrAuth, FT, Addrs[DstIdx], Addrs[SrcIdx]);
610 }
611};
612
613// These classes that emit the special functions for a non-trivial struct.
614struct GenDestructor : StructVisitor<GenDestructor>,
615 GenFuncBase<GenDestructor>,
616 DestructedTypeVisitor<GenDestructor> {
617 using Super = DestructedTypeVisitor<GenDestructor>;
618 GenDestructor(ASTContext &Ctx) : StructVisitor<GenDestructor>(Ctx) {}
619
620 void visitWithKind(QualType::DestructionKind DK, QualType FT,
621 const FieldDecl *FD, CharUnits CurStructOffset,
622 std::array<Address, 1> Addrs) {
623 if (const auto *AT = getContext().getAsArrayType(FT)) {
624 visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset, Addrs);
625 return;
626 }
627
628 Super::visitWithKind(DK, FT, FD, CurStructOffset, Addrs);
629 }
630
631 void visitARCStrong(QualType QT, const FieldDecl *FD,
632 CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
634 *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
635 }
636
637 void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
638 std::array<Address, 1> Addrs) {
639 CGF->destroyARCWeak(
640 *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
641 }
642
643 void callSpecialFunction(QualType FT, CharUnits Offset,
644 std::array<Address, 1> Addrs) {
646 CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
647 }
648};
649
650struct GenDefaultInitialize
651 : StructVisitor<GenDefaultInitialize>,
652 GenFuncBase<GenDefaultInitialize>,
653 DefaultInitializedTypeVisitor<GenDefaultInitialize> {
654 using Super = DefaultInitializedTypeVisitor<GenDefaultInitialize>;
655 typedef GenFuncBase<GenDefaultInitialize> GenFuncBaseTy;
656
657 GenDefaultInitialize(ASTContext &Ctx)
658 : StructVisitor<GenDefaultInitialize>(Ctx) {}
659
660 void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
661 const FieldDecl *FD, CharUnits CurStructOffset,
662 std::array<Address, 1> Addrs) {
663 if (const auto *AT = getContext().getAsArrayType(FT)) {
664 visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset,
665 Addrs);
666 return;
667 }
668
669 Super::visitWithKind(PDIK, FT, FD, CurStructOffset, Addrs);
670 }
671
672 void visitARCStrong(QualType QT, const FieldDecl *FD,
673 CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
675 getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
676 }
677
678 void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
679 std::array<Address, 1> Addrs) {
681 getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
682 }
683
684 template <class FieldKind, size_t... Is>
685 void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
686 const FieldDecl *FD, CharUnits CurStructOffset,
687 std::array<Address, 1> Addrs) {
688 if (!FK)
689 return visitTrivial(QualType(AT, 0), FD, CurStructOffset, Addrs);
690
691 ASTContext &Ctx = getContext();
692 CharUnits Size = Ctx.getTypeSizeInChars(QualType(AT, 0));
693 QualType EltTy = Ctx.getBaseElementType(QualType(AT, 0));
694
695 if (Size < CharUnits::fromQuantity(16) ||
696 EltTy->getAsCanonical<RecordType>()) {
697 GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStructOffset, Addrs);
698 return;
699 }
700
701 llvm::Constant *SizeVal = CGF->Builder.getInt64(Size.getQuantity());
702 Address DstAddr = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
703 Address Loc = DstAddr.withElementType(CGF->Int8Ty);
704 CGF->Builder.CreateMemSet(Loc, CGF->Builder.getInt8(0), SizeVal,
705 IsVolatile);
706 }
707
708 void callSpecialFunction(QualType FT, CharUnits Offset,
709 std::array<Address, 1> Addrs) {
711 CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
712 }
713};
714
715struct GenCopyConstructor : GenBinaryFunc<GenCopyConstructor, false, true> {
716 GenCopyConstructor(ASTContext &Ctx)
717 : GenBinaryFunc<GenCopyConstructor, false, true>(Ctx) {}
718
719 void visitARCStrong(QualType QT, const FieldDecl *FD,
720 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
721 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
722 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
723 llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
724 Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
725 llvm::Value *Val = CGF->EmitARCRetain(QT, SrcVal);
726 CGF->EmitStoreOfScalar(Val, CGF->MakeAddrLValue(Addrs[DstIdx], QT), true);
727 }
728
729 void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
730 std::array<Address, 2> Addrs) {
731 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
732 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
733 CGF->EmitARCCopyWeak(Addrs[DstIdx], Addrs[SrcIdx]);
734 }
735
736 void callSpecialFunction(QualType FT, CharUnits Offset,
737 std::array<Address, 2> Addrs) {
738 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
739 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
740 CGF->callCStructCopyConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
741 CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
742 }
743};
744
745struct GenMoveConstructor : GenBinaryFunc<GenMoveConstructor, true, true> {
746 GenMoveConstructor(ASTContext &Ctx)
747 : GenBinaryFunc<GenMoveConstructor, true, true>(Ctx) {}
748
749 void visitARCStrong(QualType QT, const FieldDecl *FD,
750 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
751 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
752 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
753 LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
754 llvm::Value *SrcVal =
755 CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
756 CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress()), SrcLV);
757 CGF->EmitStoreOfScalar(SrcVal, CGF->MakeAddrLValue(Addrs[DstIdx], QT),
758 /* isInitialization */ true);
759 }
760
761 void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
762 std::array<Address, 2> Addrs) {
763 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
764 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
765 CGF->EmitARCMoveWeak(Addrs[DstIdx], Addrs[SrcIdx]);
766 }
767
768 void callSpecialFunction(QualType FT, CharUnits Offset,
769 std::array<Address, 2> Addrs) {
770 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
771 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
772 CGF->callCStructMoveConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
773 CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
774 }
775};
776
777struct GenCopyAssignment : GenBinaryFunc<GenCopyAssignment, false, false> {
778 GenCopyAssignment(ASTContext &Ctx)
779 : GenBinaryFunc<GenCopyAssignment, false, false>(Ctx) {}
780
781 void visitARCStrong(QualType QT, const FieldDecl *FD,
782 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
783 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
784 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
785 llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
786 Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
787 CGF->EmitARCStoreStrong(CGF->MakeAddrLValue(Addrs[DstIdx], QT), SrcVal,
788 false);
789 }
790
791 void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
792 std::array<Address, 2> Addrs) {
793 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
794 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
795 CGF->emitARCCopyAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
796 }
797
798 void callSpecialFunction(QualType FT, CharUnits Offset,
799 std::array<Address, 2> Addrs) {
800 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
801 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
803 CGF->MakeAddrLValue(Addrs[DstIdx], FT),
804 CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
805 }
806};
807
808struct GenMoveAssignment : GenBinaryFunc<GenMoveAssignment, true, false> {
809 GenMoveAssignment(ASTContext &Ctx)
810 : GenBinaryFunc<GenMoveAssignment, true, false>(Ctx) {}
811
812 void visitARCStrong(QualType QT, const FieldDecl *FD,
813 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
814 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
815 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
816 LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
817 llvm::Value *SrcVal =
818 CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
819 CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress()), SrcLV);
820 LValue DstLV = CGF->MakeAddrLValue(Addrs[DstIdx], QT);
821 llvm::Value *DstVal =
822 CGF->EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
823 CGF->EmitStoreOfScalar(SrcVal, DstLV);
825 }
826
827 void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
828 std::array<Address, 2> Addrs) {
829 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
830 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
831 CGF->emitARCMoveAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
832 }
833
834 void callSpecialFunction(QualType FT, CharUnits Offset,
835 std::array<Address, 2> Addrs) {
836 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
837 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
839 CGF->MakeAddrLValue(Addrs[DstIdx], FT),
840 CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
841 }
842};
843
844} // namespace
845
849}
850
851// Default-initialize a variable that is a non-trivial struct or an array of
852// such structure.
854 GenDefaultInitialize Gen(getContext());
855 Address DstPtr = Dst.getAddress().withElementType(CGM.Int8PtrTy);
856 Gen.setCGF(this);
857 QualType QT = Dst.getType();
858 QT = Dst.isVolatile() ? QT.withVolatile() : QT;
859 Gen.visit(QT, nullptr, CharUnits::Zero(), std::array<Address, 1>({{DstPtr}}));
860}
861
862template <class G, size_t N>
863static void callSpecialFunction(G &&Gen, StringRef FuncName, QualType QT,
864 bool IsVolatile, CodeGenFunction &CGF,
865 std::array<Address, N> Addrs) {
866 auto SetArtificialLoc = ApplyDebugLocation::CreateArtificial(CGF);
867 for (unsigned I = 0; I < N; ++I)
868 Addrs[I] = Addrs[I].withElementType(CGF.CGM.Int8PtrTy);
869 QT = IsVolatile ? QT.withVolatile() : QT;
870 Gen.callFunc(FuncName, QT, Addrs, CGF);
871}
872
873template <class G, size_t N>
874static llvm::Function *
875getSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile,
876 std::array<CharUnits, N> Alignments, CodeGenModule &CGM) {
877 QT = IsVolatile ? QT.withVolatile() : QT;
878 // The following call requires an array of addresses as arguments, but doesn't
879 // actually use them (it overwrites them with the addresses of the arguments
880 // of the created function).
881 return Gen.getFunction(FuncName, QT, Alignments, CGM);
882}
883
884// Functions to emit calls to the special functions of a non-trivial C struct.
886 bool IsVolatile = Dst.isVolatile();
887 Address DstPtr = Dst.getAddress();
888 QualType QT = Dst.getType();
889 GenDefaultInitializeFuncName GenName(DstPtr.getAlignment(), getContext());
890 std::string FuncName = GenName.getName(QT, IsVolatile);
891 callSpecialFunction(GenDefaultInitialize(getContext()), FuncName, QT,
892 IsVolatile, *this, std::array<Address, 1>({{DstPtr}}));
893}
894
896 QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx) {
897 GenBinaryFuncName<false> GenName("", Alignment, Alignment, Ctx);
898 return GenName.getName(QT, IsVolatile);
899}
900
902 CharUnits Alignment,
903 bool IsVolatile,
904 ASTContext &Ctx) {
905 GenDestructorFuncName GenName("", Alignment, Ctx);
906 return GenName.getName(QT, IsVolatile);
907}
908
910 bool IsVolatile = Dst.isVolatile();
911 Address DstPtr = Dst.getAddress();
912 QualType QT = Dst.getType();
913 GenDestructorFuncName GenName("__destructor_", DstPtr.getAlignment(),
914 getContext());
915 std::string FuncName = GenName.getName(QT, IsVolatile);
916 callSpecialFunction(GenDestructor(getContext()), FuncName, QT, IsVolatile,
917 *this, std::array<Address, 1>({{DstPtr}}));
918}
919
921 bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
922 Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress();
923 QualType QT = Dst.getType();
924 GenBinaryFuncName<false> GenName("__copy_constructor_", DstPtr.getAlignment(),
925 SrcPtr.getAlignment(), getContext());
926 std::string FuncName = GenName.getName(QT, IsVolatile);
927 callSpecialFunction(GenCopyConstructor(getContext()), FuncName, QT,
928 IsVolatile, *this,
929 std::array<Address, 2>({{DstPtr, SrcPtr}}));
930}
931
933
934) {
935 bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
936 Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress();
937 QualType QT = Dst.getType();
938 GenBinaryFuncName<false> GenName("__copy_assignment_", DstPtr.getAlignment(),
939 SrcPtr.getAlignment(), getContext());
940 std::string FuncName = GenName.getName(QT, IsVolatile);
941 callSpecialFunction(GenCopyAssignment(getContext()), FuncName, QT, IsVolatile,
942 *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
943}
944
946 bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
947 Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress();
948 QualType QT = Dst.getType();
949 GenBinaryFuncName<true> GenName("__move_constructor_", DstPtr.getAlignment(),
950 SrcPtr.getAlignment(), getContext());
951 std::string FuncName = GenName.getName(QT, IsVolatile);
952 callSpecialFunction(GenMoveConstructor(getContext()), FuncName, QT,
953 IsVolatile, *this,
954 std::array<Address, 2>({{DstPtr, SrcPtr}}));
955}
956
958
959) {
960 bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
961 Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress();
962 QualType QT = Dst.getType();
963 GenBinaryFuncName<true> GenName("__move_assignment_", DstPtr.getAlignment(),
964 SrcPtr.getAlignment(), getContext());
965 std::string FuncName = GenName.getName(QT, IsVolatile);
966 callSpecialFunction(GenMoveAssignment(getContext()), FuncName, QT, IsVolatile,
967 *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
968}
969
971 CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
972 ASTContext &Ctx = CGM.getContext();
973 GenDefaultInitializeFuncName GenName(DstAlignment, Ctx);
974 std::string FuncName = GenName.getName(QT, IsVolatile);
975 return getSpecialFunction(GenDefaultInitialize(Ctx), FuncName, QT, IsVolatile,
976 std::array<CharUnits, 1>({{DstAlignment}}), CGM);
977}
978
980 CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
981 bool IsVolatile, QualType QT) {
982 ASTContext &Ctx = CGM.getContext();
983 GenBinaryFuncName<false> GenName("__copy_constructor_", DstAlignment,
984 SrcAlignment, Ctx);
985 std::string FuncName = GenName.getName(QT, IsVolatile);
986 return getSpecialFunction(
987 GenCopyConstructor(Ctx), FuncName, QT, IsVolatile,
988 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
989}
990
992 CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
993 bool IsVolatile, QualType QT) {
994 ASTContext &Ctx = CGM.getContext();
995 GenBinaryFuncName<true> GenName("__move_constructor_", DstAlignment,
996 SrcAlignment, Ctx);
997 std::string FuncName = GenName.getName(QT, IsVolatile);
998 return getSpecialFunction(
999 GenMoveConstructor(Ctx), FuncName, QT, IsVolatile,
1000 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
1001}
1002
1004 CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
1005 bool IsVolatile, QualType QT) {
1006 ASTContext &Ctx = CGM.getContext();
1007 GenBinaryFuncName<false> GenName("__copy_assignment_", DstAlignment,
1008 SrcAlignment, Ctx);
1009 std::string FuncName = GenName.getName(QT, IsVolatile);
1010 return getSpecialFunction(
1011 GenCopyAssignment(Ctx), FuncName, QT, IsVolatile,
1012 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
1013}
1014
1016 CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
1017 bool IsVolatile, QualType QT) {
1018 ASTContext &Ctx = CGM.getContext();
1019 GenBinaryFuncName<true> GenName("__move_assignment_", DstAlignment,
1020 SrcAlignment, Ctx);
1021 std::string FuncName = GenName.getName(QT, IsVolatile);
1022 return getSpecialFunction(
1023 GenMoveAssignment(Ctx), FuncName, QT, IsVolatile,
1024 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
1025}
1026
1028 CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
1029 ASTContext &Ctx = CGM.getContext();
1030 GenDestructorFuncName GenName("__destructor_", DstAlignment, Ctx);
1031 std::string FuncName = GenName.getName(QT, IsVolatile);
1032 return getSpecialFunction(GenDestructor(Ctx), FuncName, QT, IsVolatile,
1033 std::array<CharUnits, 1>({{DstAlignment}}), CGM);
1034}
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:1197
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:46
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:245
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:852
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
static uint64_t getConstantArrayElementCount(const ConstantArrayType *CA)
Return number of (potentially nested) constant array elements.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
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:3832
This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
Definition CharUnits.h:155
static CharUnits fromQuantity(QuantityType Quantity)
Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:58
static CharUnits Zero()
Construct a CharUnits quantity of zero.
Definition CharUnits.h:52
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 AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)
Definition CGValue.h:649
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:148
llvm::CallInst * CreateMemSet(Address Dest, llvm::Value *Value, llvm::Value *Size, bool IsVolatile=false)
Definition CGBuilder.h:432
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
Definition CGBuilder.h:120
llvm::CallInst * CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile=false)
Definition CGBuilder.h:399
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:2711
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:2347
llvm::Value * EmitARCStoreStrong(LValue lvalue, llvm::Value *value, bool resultIgnored)
Store into a strong object.
Definition CGObjC.cpp:2564
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:2500
RValue EmitLoadOfAnyValue(LValue V, AggValueSlot Slot=AggValueSlot::ignored(), SourceLocation Loc={})
Like EmitLoadOfLValue but also handles complex and aggregate types.
Definition CGExpr.cpp:2531
LValue EmitLValueForField(LValue Base, const FieldDecl *Field, bool IsInBounds=true)
Definition CGExpr.cpp:5966
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
Definition CGExpr.cpp:2549
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:2733
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
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:2801
llvm::Type * ConvertTypeForMem(QualType T)
static std::string getNonTrivialCopyConstructorStr(QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx)
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
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:2720
void emitARCCopyAssignWeak(QualType Ty, Address DstAddr, Address SrcAddr)
Definition CGObjC.cpp:2726
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:2092
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
Definition CGCall.cpp:774
FunctionArgList - Type for representing both the decl and type of parameters to a function.
Definition CGCall.h:378
LValue - This represents an lvalue references.
Definition CGValue.h:183
bool isVolatile() const
Definition CGValue.h:340
Address getAddress() const
Definition CGValue.h:373
QualType getType() const
Definition CGValue.h:303
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
Definition CGValue.h:72
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
Definition CGValue.h:79
Represents a member of a struct/union/class.
Definition Decl.h:3311
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:3414
unsigned getBitWidthValue() const
Computes the bit width of this field, if this is a bit field.
Definition Decl.cpp:4843
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition Decl.h:3396
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3547
bool isZeroLengthBitField() const
Is this a zero-length bit-field?
Definition Decl.cpp:4852
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
Definition Decl.cpp:5699
bool authenticatesNullValues() const
Definition TypeBase.h:286
PointerAuthQualifier withoutKeyNone() const
Definition TypeBase.h:291
unsigned getExtraDiscriminator() const
Definition TypeBase.h:271
unsigned getKey() const
Definition TypeBase.h:259
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
Definition TypeBase.h:8662
PointerAuthQualifier getPointerAuth() const
Definition TypeBase.h:1469
QualType withVolatile() const
Definition TypeBase.h:1183
Encodes a location in the source.
The base class of the type hierarchy.
Definition TypeBase.h:1879
bool isBlockPointerType() const
Definition TypeBase.h:8835
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9498
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:3002
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
Definition CGValue.h:155
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:137
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
@ Address
A pointer to a ValueDecl.
Definition Primitives.h:28
Top level wrappers for InstallAPI frontend operations.
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:1787
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)