clang: lib/CodeGen/ItaniumCXXABI.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
33#include "llvm/IR/DataLayout.h"
34#include "llvm/IR/GlobalValue.h"
35#include "llvm/IR/Instructions.h"
36#include "llvm/IR/Intrinsics.h"
37#include "llvm/IR/Value.h"
38#include "llvm/Support/ScopedPrinter.h"
39
40#include
41
42using namespace clang;
44
45namespace {
47
48 llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables;
49
50
51 llvm::SmallVector<std::pair<const VarDecl *, llvm::Function *>, 8>
52 ThreadWrappers;
53
54protected:
55 bool UseARMMethodPtrABI;
56 bool UseARMGuardVarABI;
57 bool Use32BitVTableOffsetABI;
58
59 ItaniumMangleContext &getMangleContext() {
61 }
62
63public:
64 ItaniumCXXABI(CodeGen::CodeGenModule &CGM,
65 bool UseARMMethodPtrABI = false,
66 bool UseARMGuardVarABI = false) :
67 CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),
68 UseARMGuardVarABI(UseARMGuardVarABI),
69 Use32BitVTableOffsetABI(false) { }
70
72
73 RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override {
74
76 return RAA_Indirect;
77 return RAA_Default;
78 }
79
80 bool isThisCompleteObject(GlobalDecl GD) const override {
81
82
87 return true;
88
90 return false;
91
93 llvm_unreachable("emitting dtor comdat as function?");
95 llvm_unreachable("emitting unified dtor as function?");
97 llvm_unreachable("unexpected dtor kind for this ABI");
98 }
99 llvm_unreachable("bad dtor kind");
100 }
104 return true;
105
107 return false;
108
111 llvm_unreachable("closure ctors in Itanium ABI?");
112
114 llvm_unreachable("emitting ctor comdat as function?");
115
117 llvm_unreachable("emitting unified ctor as function?");
118 }
119 llvm_unreachable("bad dtor kind");
120 }
121
122
123 return false;
124 }
125
126 bool isZeroInitializable(const MemberPointerType *MPT) override;
127
128 llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT) override;
129
130 CGCallee
131 EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
132 const Expr *E,
133 Address This,
134 llvm::Value *&ThisPtrForCall,
135 llvm::Value *MemFnPtr,
136 const MemberPointerType *MPT) override;
137
138 llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,
139 Address Base, llvm::Value *MemPtr,
140 const MemberPointerType *MPT,
141 bool IsInBounds) override;
142
143 llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF,
145 llvm::Value *Src) override;
146 llvm::Constant *EmitMemberPointerConversion(const CastExpr *E,
147 llvm::Constant *Src) override;
148
149 llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT) override;
150
151 llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD) override;
152 llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
153 CharUnits offset) override;
154 llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT) override;
155 llvm::Constant *BuildMemberPointer(const CXXMethodDecl *MD,
156 CharUnits ThisAdjustment);
157
158 llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF,
159 llvm::Value *L, llvm::Value *R,
160 const MemberPointerType *MPT,
161 bool Inequality) override;
162
163 llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
164 llvm::Value *Addr,
165 const MemberPointerType *MPT) override;
166
167 void emitVirtualObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE,
168 Address Ptr, QualType ElementType,
169 const CXXDestructorDecl *Dtor) override;
170
171 void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) override;
172 void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) override;
173
174 void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override;
175
176 llvm::CallInst *
177 emitTerminateForUnexpectedException(CodeGenFunction &CGF,
178 llvm::Value *Exn) override;
179
180 void EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD);
181 llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override;
182 CatchTypeInfo
183 getAddrOfCXXCatchHandlerType(QualType Ty,
184 QualType CatchHandlerType) override {
185 return CatchTypeInfo{getAddrOfRTTIDescriptor(Ty), 0};
186 }
187
188 bool shouldTypeidBeNullChecked(QualType SrcRecordTy) override;
189 void EmitBadTypeidCall(CodeGenFunction &CGF) override;
190 llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
191 Address ThisPtr,
192 llvm::Type *StdTypeInfoPtrTy) override;
193
194 bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
195 QualType SrcRecordTy) override;
196
197
198
199
200
201 bool hasUniqueVTablePointer(QualType RecordTy) {
203
204
205
206 if (!CGM.getCodeGenOpts().AssumeUniqueVTables ||
207 getContext().getLangOpts().AppleKext)
208 return false;
209
210
211
212 if (!CGM.shouldEmitRTTI())
213 return false;
214
215
216
217 if (!llvm::GlobalValue::isWeakForLinker(CGM.getVTableLinkage(RD)))
218 return true;
219
220
221
222
223
224
225 if (CGM.GetLLVMVisibility(RD->getVisibility()) !=
226 llvm::GlobalValue::DefaultVisibility)
227 return false;
228
229 return true;
230 }
231
232 bool shouldEmitExactDynamicCast(QualType DestRecordTy) override {
233 return hasUniqueVTablePointer(DestRecordTy);
234 }
235
236 std::optional
237 getExactDynamicCastInfo(QualType SrcRecordTy, QualType DestTy,
238 QualType DestRecordTy) override;
239
240 llvm::Value *emitDynamicCastCall(CodeGenFunction &CGF, Address Value,
241 QualType SrcRecordTy, QualType DestTy,
242 QualType DestRecordTy,
243 llvm::BasicBlock *CastEnd) override;
244
246 QualType SrcRecordTy, QualType DestTy,
247 QualType DestRecordTy,
248 const ExactDynamicCastInfo &CastInfo,
249 llvm::BasicBlock *CastSuccess,
250 llvm::BasicBlock *CastFail) override;
251
253 QualType SrcRecordTy) override;
254
255 bool EmitBadCastCall(CodeGenFunction &CGF) override;
256
257 llvm::Value *
258 GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This,
259 const CXXRecordDecl *ClassDecl,
260 const CXXRecordDecl *BaseClassDecl) override;
261
262 void EmitCXXConstructors(const CXXConstructorDecl *D) override;
263
264 AddedStructorArgCounts
265 buildStructorSignature(GlobalDecl GD,
266 SmallVectorImpl &ArgTys) override;
267
268 bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,
270
271
272
273 return false;
274 }
275
276 void EmitCXXDestructors(const CXXDestructorDecl *D) override;
277
278 void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy,
279 FunctionArgList &Params) override;
280
281 void EmitInstanceFunctionProlog(CodeGenFunction &CGF) override;
282
283 AddedStructorArgs getImplicitConstructorArgs(CodeGenFunction &CGF,
284 const CXXConstructorDecl *D,
286 bool ForVirtualBase,
288
290 const CXXDestructorDecl *DD,
292 bool ForVirtualBase,
294
295 void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD,
298 QualType ThisTy) override;
299
300 void emitVTableDefinitions(CodeGenVTables &CGVT,
301 const CXXRecordDecl *RD) override;
302
303 bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF,
304 CodeGenFunction::VPtr Vptr) override;
305
306 bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass) override {
307 return true;
308 }
309
310 llvm::Constant *
311 getVTableAddressPoint(BaseSubobject Base,
312 const CXXRecordDecl *VTableClass) override;
313
314 llvm::Value *getVTableAddressPointInStructor(
315 CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
316 BaseSubobject Base, const CXXRecordDecl *NearestVBase) override;
317
318 llvm::Value *getVTableAddressPointInStructorWithVTT(
319 CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
320 BaseSubobject Base, const CXXRecordDecl *NearestVBase);
321
322 llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,
323 CharUnits VPtrOffset) override;
324
325 CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
326 Address This, llvm::Type *Ty,
327 SourceLocation Loc) override;
328
329 llvm::Value *
330 EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor,
332 DeleteOrMemberCallExpr E,
333 llvm::CallBase **CallOrInvoke) override;
334
335 void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override;
336
337 bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override;
338 bool canSpeculativelyEmitVTableAsBaseClass(const CXXRecordDecl *RD) const;
339
340 void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD,
341 bool ReturnAdjustment) override {
342
343
344 if (ForVTable && !Thunk->hasLocalLinkage())
345 Thunk->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
346 CGM.setGVProperties(Thunk, GD);
347 }
348
349 bool exportThunk() override { return true; }
350
351 llvm::Value *performThisAdjustment(CodeGenFunction &CGF, Address This,
352 const CXXRecordDecl *UnadjustedThisClass,
353 const ThunkInfo &TI) override;
354
355 llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, Address Ret,
356 const CXXRecordDecl *UnadjustedRetClass,
357 const ReturnAdjustment &RA) override;
358
359 size_t getSrcArgforCopyCtor(const CXXConstructorDecl *,
360 FunctionArgList &Args) const override {
361 assert(!Args.empty() && "expected the arglist to not be empty!");
362 return Args.size() - 1;
363 }
364
365 StringRef GetPureVirtualCallName() override { return "__cxa_pure_virtual"; }
366 StringRef GetDeletedVirtualCallName() override
367 { return "__cxa_deleted_virtual"; }
368
369 CharUnits getArrayCookieSizeImpl(QualType elementType) override;
370 Address InitializeArrayCookie(CodeGenFunction &CGF,
371 Address NewPtr,
372 llvm::Value *NumElements,
373 const CXXNewExpr *expr,
374 QualType ElementType) override;
375 llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
376 Address allocPtr,
377 CharUnits cookieSize) override;
378
379 void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
380 llvm::GlobalVariable *DeclPtr,
381 bool PerformInit) override;
382 void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
383 llvm::FunctionCallee dtor,
384 llvm::Constant *addr) override;
385
386 llvm::Function *getOrCreateThreadLocalWrapper(const VarDecl *VD,
387 llvm::Value *Val);
388 void EmitThreadLocalInitFuncs(
389 CodeGenModule &CGM,
390 ArrayRef<const VarDecl *> CXXThreadLocals,
391 ArrayRef<llvm::Function *> CXXThreadLocalInits,
392 ArrayRef<const VarDecl *> CXXThreadLocalInitVars) override;
393
394 bool usesThreadWrapperFunction(const VarDecl *VD) const override {
395 return !isEmittedWithConstantInitializer(VD) ||
396 mayNeedDestruction(VD);
397 }
398 LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
399 QualType LValType) override;
400
401 bool NeedsVTTParameter(GlobalDecl GD) override;
402
403 llvm::Constant *
404 getOrCreateVirtualFunctionPointerThunk(const CXXMethodDecl *MD);
405
406
407
408protected:
409
410
411 virtual bool shouldRTTIBeUnique() const { return true; }
412
413public:
414
415 enum RTTIUniquenessKind {
416
417
418 RUK_Unique,
419
420
421
422 RUK_NonUniqueHidden,
423
424
425
426
427 RUK_NonUniqueVisible
428 };
429
430
431
432 RTTIUniquenessKind
433 classifyRTTIUniqueness(QualType CanTy,
434 llvm::GlobalValue::LinkageTypes Linkage) const;
435 friend class ItaniumRTTIBuilder;
436
437 void emitCXXStructor(GlobalDecl GD) override;
438
439 std::pair<llvm::Value *, const CXXRecordDecl *>
440 LoadVTablePtr(CodeGenFunction &CGF, Address This,
441 const CXXRecordDecl *RD) override;
442
443 private:
444 llvm::Constant *
445 getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD);
446
447 bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const {
448 const auto &VtableLayout =
449 CGM.getItaniumVTableContext().getVTableLayout(RD);
450
451 for (const auto &VtableComponent : VtableLayout.vtable_components()) {
452
453 if (!VtableComponent.isUsedFunctionPointerKind())
454 continue;
455
456 const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
457 const FunctionDecl *FD = Method->getDefinition();
458 const bool IsInlined =
459 Method->getCanonicalDecl()->isInlined() || (FD && FD->isInlined());
460 if (!IsInlined)
461 continue;
462
463 StringRef Name = CGM.getMangledName(
464 VtableComponent.getGlobalDecl(false));
465 auto *Entry = CGM.GetGlobalValue(Name);
466
467
468
469
470
471 if (!Entry || Entry->isDeclaration())
472 return true;
473 }
474 return false;
475 }
476
477 bool isVTableHidden(const CXXRecordDecl *RD) const {
478 const auto &VtableLayout =
479 CGM.getItaniumVTableContext().getVTableLayout(RD);
480
481 for (const auto &VtableComponent : VtableLayout.vtable_components()) {
482 if (VtableComponent.isRTTIKind()) {
483 const CXXRecordDecl *RTTIDecl = VtableComponent.getRTTIDecl();
484 if (RTTIDecl->getVisibility() == Visibility::HiddenVisibility)
485 return true;
486 } else if (VtableComponent.isUsedFunctionPointerKind()) {
487 const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
488 if (Method->getVisibility() == Visibility::HiddenVisibility &&
489 ->isDefined())
490 return true;
491 }
492 }
493 return false;
494 }
495};
496
497class ARMCXXABI : public ItaniumCXXABI {
498public:
499 ARMCXXABI(CodeGen::CodeGenModule &CGM) :
500 ItaniumCXXABI(CGM, true,
501 true) {}
502
503 bool constructorsAndDestructorsReturnThis() const override { return true; }
504
505 void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV,
506 QualType ResTy) override;
507
508 CharUnits getArrayCookieSizeImpl(QualType elementType) override;
509 Address InitializeArrayCookie(CodeGenFunction &CGF,
510 Address NewPtr,
511 llvm::Value *NumElements,
512 const CXXNewExpr *expr,
513 QualType ElementType) override;
514 llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, Address allocPtr,
515 CharUnits cookieSize) override;
516};
517
518class AppleARM64CXXABI : public ARMCXXABI {
519public:
520 AppleARM64CXXABI(CodeGen::CodeGenModule &CGM) : ARMCXXABI(CGM) {
521 Use32BitVTableOffsetABI = true;
522 }
523
524
525 bool shouldRTTIBeUnique() const override { return false; }
526};
527
528class FuchsiaCXXABI final : public ItaniumCXXABI {
529public:
530 explicit FuchsiaCXXABI(CodeGen::CodeGenModule &CGM)
531 : ItaniumCXXABI(CGM) {}
532
533private:
534 bool constructorsAndDestructorsReturnThis() const override { return true; }
535};
536
537class WebAssemblyCXXABI final : public ItaniumCXXABI {
538public:
539 explicit WebAssemblyCXXABI(CodeGen::CodeGenModule &CGM)
540 : ItaniumCXXABI(CGM, true,
541 true) {}
542 void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override;
543 llvm::CallInst *
544 emitTerminateForUnexpectedException(CodeGenFunction &CGF,
545 llvm::Value *Exn) override;
546
547private:
548 bool constructorsAndDestructorsReturnThis() const override { return true; }
549 bool canCallMismatchedFunctionType() const override { return false; }
550};
551
552class XLCXXABI final : public ItaniumCXXABI {
553public:
554 explicit XLCXXABI(CodeGen::CodeGenModule &CGM)
555 : ItaniumCXXABI(CGM) {}
556
557 void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
558 llvm::FunctionCallee dtor,
559 llvm::Constant *addr) override;
560
561 bool useSinitAndSterm() const override { return true; }
562
563private:
564 void emitCXXStermFinalizer(const VarDecl &D, llvm::Function *dtorStub,
565 llvm::Constant *addr);
566};
567}
568
571
572
573 case TargetCXXABI::GenericARM:
574 case TargetCXXABI::iOS:
575 case TargetCXXABI::WatchOS:
576 return new ARMCXXABI(CGM);
577
578 case TargetCXXABI::AppleARM64:
579 return new AppleARM64CXXABI(CGM);
580
581 case TargetCXXABI::Fuchsia:
582 return new FuchsiaCXXABI(CGM);
583
584
585
586
587 case TargetCXXABI::GenericAArch64:
588 return new ItaniumCXXABI(CGM, true,
589 true);
590
591 case TargetCXXABI::GenericMIPS:
592 return new ItaniumCXXABI(CGM, true);
593
594 case TargetCXXABI::WebAssembly:
595 return new WebAssemblyCXXABI(CGM);
596
597 case TargetCXXABI::XL:
598 return new XLCXXABI(CGM);
599
600 case TargetCXXABI::GenericItanium:
601 return new ItaniumCXXABI(CGM);
602
603 case TargetCXXABI::Microsoft:
604 llvm_unreachable("Microsoft ABI is not Itanium-based");
605 }
606 llvm_unreachable("bad ABI kind");
607}
608
609llvm::Type *
610ItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
612 return CGM.PtrDiffTy;
613 return llvm::StructType::get(CGM.PtrDiffTy, CGM.PtrDiffTy);
614}
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
638 llvm::Value *&ThisPtrForCall,
641
645
646 llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1);
647
648 llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("memptr.virtual");
649 llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("memptr.nonvirtual");
650 llvm::BasicBlock *FnEnd = CGF.createBasicBlock("memptr.end");
651
652
653 llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1, "memptr.adj");
654
655
656 llvm::Value *Adj = RawAdj;
657 if (UseARMMethodPtrABI)
658 Adj = Builder.CreateAShr(Adj, ptrdiff_1, "memptr.adj.shifted");
659
660
661
663 This = Builder.CreateInBoundsGEP(Builder.getInt8Ty(), This, Adj);
664 ThisPtrForCall = This;
665
666
667 llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0, "memptr.ptr");
668
669
670
671 llvm::Value *IsVirtual;
672 if (UseARMMethodPtrABI)
673 IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1);
674 else
675 IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1);
676 IsVirtual = Builder.CreateIsNotNull(IsVirtual, "memptr.isvirtual");
677 Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
678
679
680
681
683
684
691
692
693
694
695 llvm::Value *VTableOffset = FnAsInt;
696 if (!UseARMMethodPtrABI)
697 VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1);
698 if (Use32BitVTableOffsetABI) {
699 VTableOffset = Builder.CreateTrunc(VTableOffset, CGF.Int32Ty);
700 VTableOffset = Builder.CreateZExt(VTableOffset, CGM.PtrDiffTy);
701 }
702
703
704
705 llvm::Constant *CheckSourceLocation;
706 llvm::Constant *CheckTypeDesc;
707 bool ShouldEmitCFICheck = CGF.SanOpts.has(SanitizerKind::CFIMFCall) &&
708 CGM.HasHiddenLTOVisibility(RD);
709
710 if (ShouldEmitCFICheck) {
711 if (const auto *BinOp = dyn_cast(E)) {
712 if (BinOp->isPtrMemOp() &&
713 BinOp->getRHS()
714 ->getType()
715 ->hasPointeeToCFIUncheckedCalleeFunctionType())
716 ShouldEmitCFICheck = false;
717 }
718 }
719
720 bool ShouldEmitVFEInfo = CGM.getCodeGenOpts().VirtualFunctionElimination &&
721 CGM.HasHiddenLTOVisibility(RD);
722
723
724
725 bool ShouldEmitWPDInfo =
726 (CGM.getCodeGenOpts().WholeProgramVTables &&
727
728 !CGM.AlwaysHasLTOVisibilityPublic(RD)) ||
729 CGM.getCodeGenOpts().DevirtualizeSpeculatively;
730 llvm::Value *VirtualFn = nullptr;
731
732 {
733 auto CheckOrdinal = SanitizerKind::SO_CFIMFCall;
734 auto CheckHandler = SanitizerHandler::CFICheckFail;
735 SanitizerDebugLocation SanScope(&CGF, {CheckOrdinal}, CheckHandler);
736
737 llvm::Value *TypeId = nullptr;
738 llvm::Value *CheckResult = nullptr;
739
740 if (ShouldEmitCFICheck || ShouldEmitVFEInfo || ShouldEmitWPDInfo) {
741
742
743 llvm::Metadata *MD =
744 CGM.CreateMetadataIdentifierForVirtualMemPtrType(QualType(MPT, 0));
745 TypeId = llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);
746 }
747
748 if (ShouldEmitVFEInfo) {
749 llvm::Value *VFPAddr =
750 Builder.CreateGEP(CGF.Int8Ty, VTable, VTableOffset);
751
752
753
754
755
756
757 llvm::Value *CheckedLoad = Builder.CreateCall(
758 CGM.getIntrinsic(llvm::Intrinsic::type_checked_load),
759 {VFPAddr, llvm::ConstantInt::get(CGM.Int32Ty, 0), TypeId});
760 CheckResult = Builder.CreateExtractValue(CheckedLoad, 1);
761 VirtualFn = Builder.CreateExtractValue(CheckedLoad, 0);
762 } else {
763
764
765 if (ShouldEmitCFICheck || ShouldEmitWPDInfo) {
766 llvm::Value *VFPAddr =
767 Builder.CreateGEP(CGF.Int8Ty, VTable, VTableOffset);
768 llvm::Intrinsic::ID IID = CGM.HasHiddenLTOVisibility(RD)
769 ? llvm::Intrinsic::type_test
770 : llvm::Intrinsic::public_type_test;
771
772 CheckResult =
773 Builder.CreateCall(CGM.getIntrinsic(IID), {VFPAddr, TypeId});
774 }
775
776 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
777 VirtualFn = CGF.Builder.CreateCall(
778 CGM.getIntrinsic(llvm::Intrinsic::load_relative,
779 {VTableOffset->getType()}),
780 {VTable, VTableOffset});
781 } else {
782 llvm::Value *VFPAddr =
786 "memptr.virtualfn");
787 }
788 }
789 assert(VirtualFn && "Virtual fuction pointer not created!");
790 assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || !ShouldEmitWPDInfo ||
791 CheckResult) &&
792 "Check result required but not created!");
793
794 if (ShouldEmitCFICheck) {
795
798 llvm::Constant *StaticData[] = {
800 CheckSourceLocation,
801 CheckTypeDesc,
802 };
803
804 if (CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIMFCall)) {
806 } else {
807 llvm::Value *AllVtables = llvm::MetadataAsValue::get(
808 CGM.getLLVMContext(),
809 llvm::MDString::get(CGM.getLLVMContext(), "all-vtables"));
810 llvm::Value *ValidVtable = Builder.CreateCall(
811 CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});
812 CGF.EmitCheck(std::make_pair(CheckResult, CheckOrdinal), CheckHandler,
813 StaticData, {VTable, ValidVtable});
814 }
815
816 FnVirtual = Builder.GetInsertBlock();
817 }
818 }
819
821
822
823
825 llvm::Value *NonVirtualFn =
826 Builder.CreateIntToPtr(FnAsInt, CGF.DefaultPtrTy, "memptr.nonvirtualfn");
827
828
829 if (ShouldEmitCFICheck) {
832 auto CheckOrdinal = SanitizerKind::SO_CFIMFCall;
833 auto CheckHandler = SanitizerHandler::CFICheckFail;
834 SanitizerDebugLocation SanScope(&CGF, {CheckOrdinal}, CheckHandler);
835
836 llvm::Constant *StaticData[] = {
838 CheckSourceLocation,
839 CheckTypeDesc,
840 };
841
842 llvm::Value *Bit = Builder.getFalse();
843 for (const CXXRecordDecl *Base : CGM.getMostBaseClasses(RD)) {
844 llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(
845 getContext().getMemberPointerType(MPT->getPointeeType(),
846 std::nullopt,
847 Base->getCanonicalDecl()));
848 llvm::Value *TypeId =
849 llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);
850
851 llvm::Value *TypeTest =
852 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test),
853 {NonVirtualFn, TypeId});
854 Bit = Builder.CreateOr(Bit, TypeTest);
855 }
856
857 CGF.EmitCheck(std::make_pair(Bit, CheckOrdinal), CheckHandler, StaticData,
858 {NonVirtualFn, llvm::UndefValue::get(CGF.IntPtrTy)});
859
860 FnNonVirtual = Builder.GetInsertBlock();
861 }
862 }
863
864
866 llvm::PHINode *CalleePtr = Builder.CreatePHI(CGF.DefaultPtrTy, 2);
867 CalleePtr->addIncoming(VirtualFn, FnVirtual);
868 CalleePtr->addIncoming(NonVirtualFn, FnNonVirtual);
869
870 CGPointerAuthInfo PointerAuth;
871
872 if (const auto &Schema =
873 CGM.getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers) {
874 llvm::PHINode *DiscriminatorPHI = Builder.CreatePHI(CGF.IntPtrTy, 2);
875 DiscriminatorPHI->addIncoming(llvm::ConstantInt::get(CGF.IntPtrTy, 0),
876 FnVirtual);
877 const auto &AuthInfo =
878 CGM.getMemberFunctionPointerAuthInfo(QualType(MPT, 0));
879 assert(Schema.getKey() == AuthInfo.getKey() &&
880 "Keys for virtual and non-virtual member functions must match");
881 auto *NonVirtualDiscriminator = AuthInfo.getDiscriminator();
882 DiscriminatorPHI->addIncoming(NonVirtualDiscriminator, FnNonVirtual);
883 PointerAuth = CGPointerAuthInfo(
884 Schema.getKey(), Schema.getAuthenticationMode(), Schema.isIsaPointer(),
885 Schema.authenticatesNullValues(), DiscriminatorPHI);
886 }
887
888 CGCallee Callee(FPT, CalleePtr, PointerAuth);
890}
891
892
893
894llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(
895 CodeGenFunction &CGF, const Expr *E, Address Base, llvm::Value *MemPtr,
896 const MemberPointerType *MPT, bool IsInBounds) {
897 assert(MemPtr->getType() == CGM.PtrDiffTy);
898
899 CGBuilderTy &Builder = CGF.Builder;
900
901
902 llvm::Value *BaseAddr = Base.emitRawPointer(CGF);
903 return Builder.CreateGEP(CGF.Int8Ty, BaseAddr, MemPtr, "memptr.offset",
904 IsInBounds ? llvm::GEPNoWrapFlags::inBounds()
905 : llvm::GEPNoWrapFlags::none());
906}
907
908
912 const auto *CPA = dyn_castllvm::ConstantPtrAuth(Ptr);
913
914 if (!CPA)
915 return nullptr;
916
917 assert(CPA->getKey()->getZExtValue() == CurAuthInfo.getKey() &&
918 CPA->getAddrDiscriminator()->isZeroValue() &&
920 "unexpected key or discriminators");
921
923 CPA->getPointer(), NewAuthInfo.getKey(), nullptr,
925}
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950llvm::Value *
951ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
953 llvm::Value *src) {
954
957
958 assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
959 E->getCastKind() == CK_BaseToDerivedMemberPointer ||
960 E->getCastKind() == CK_ReinterpretMemberPointer);
961
962 CGBuilderTy &Builder = CGF.Builder;
963 QualType DstType = E->getType();
964
966 if (const auto &NewAuthInfo =
967 CGM.getMemberFunctionPointerAuthInfo(DstType)) {
970 const auto &CurAuthInfo = CGM.getMemberFunctionPointerAuthInfo(SrcType);
971 llvm::Value *MemFnPtr = Builder.CreateExtractValue(src, 0, "memptr.ptr");
972 llvm::Type *OrigTy = MemFnPtr->getType();
973
974 llvm::BasicBlock *StartBB = Builder.GetInsertBlock();
977
978
979 assert(UseARMMethodPtrABI && "ARM ABI expected");
980 llvm::Value *Adj = Builder.CreateExtractValue(src, 1, "memptr.adj");
981 llvm::Constant *Ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1);
982 llvm::Value *AndVal = Builder.CreateAnd(Adj, Ptrdiff_1);
983 llvm::Value *IsVirtualOffset =
984 Builder.CreateIsNotNull(AndVal, "is.virtual.offset");
985 Builder.CreateCondBr(IsVirtualOffset, MergeBB, ResignBB);
986
988 llvm::Type *PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
989 MemFnPtr = Builder.CreateIntToPtr(MemFnPtr, PtrTy);
990 MemFnPtr =
993 MemFnPtr = Builder.CreatePtrToInt(MemFnPtr, OrigTy);
994 llvm::Value *ResignedVal = Builder.CreateInsertValue(src, MemFnPtr, 0);
995 ResignBB = Builder.GetInsertBlock();
996
998 llvm::PHINode *NewSrc = Builder.CreatePHI(src->getType(), 2);
999 NewSrc->addIncoming(src, StartBB);
1000 NewSrc->addIncoming(ResignedVal, ResignBB);
1001 src = NewSrc;
1002 }
1003 }
1004
1005
1006 if (E->getCastKind() == CK_ReinterpretMemberPointer) return src;
1007
1008 llvm::Constant *adj = getMemberPointerAdjustment(E);
1009 if (!adj) return src;
1010
1011 bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);
1012
1013 const MemberPointerType *destTy =
1015
1016
1017
1019 llvm::Value *dst;
1020 if (isDerivedToBase)
1021 dst = Builder.CreateNSWSub(src, adj, "adj");
1022 else
1023 dst = Builder.CreateNSWAdd(src, adj, "adj");
1024
1025
1026 llvm::Value *null = llvm::Constant::getAllOnesValue(src->getType());
1027 llvm::Value *isNull = Builder.CreateICmpEQ(src, null, "memptr.isnull");
1028 return Builder.CreateSelect(isNull, src, dst);
1029 }
1030
1031
1032 if (UseARMMethodPtrABI) {
1034 offset <<= 1;
1035 adj = llvm::ConstantInt::get(adj->getType(), offset);
1036 }
1037
1038 llvm::Value *srcAdj = Builder.CreateExtractValue(src, 1, "src.adj");
1039 llvm::Value *dstAdj;
1040 if (isDerivedToBase)
1041 dstAdj = Builder.CreateNSWSub(srcAdj, adj, "adj");
1042 else
1043 dstAdj = Builder.CreateNSWAdd(srcAdj, adj, "adj");
1044
1045 return Builder.CreateInsertValue(src, dstAdj, 1);
1046}
1047
1048static llvm::Constant *
1053 "member function pointers expected");
1054 if (DestType == SrcType)
1055 return Src;
1056
1059
1060 if (!NewAuthInfo && !CurAuthInfo)
1061 return Src;
1062
1063 llvm::Constant *MemFnPtr = Src->getAggregateElement(0u);
1064 if (MemFnPtr->getNumOperands() == 0) {
1065
1067 return Src;
1068 }
1069
1071 castllvm::User(MemFnPtr)->getOperand(0), CurAuthInfo, NewAuthInfo, CGM);
1072 ConstPtr = llvm::ConstantExpr::getPtrToInt(ConstPtr, MemFnPtr->getType());
1073 return ConstantFoldInsertValueInstruction(Src, ConstPtr, 0);
1074}
1075
1076llvm::Constant *
1077ItaniumCXXABI::EmitMemberPointerConversion(const CastExpr *E,
1078 llvm::Constant *src) {
1079 assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
1080 E->getCastKind() == CK_BaseToDerivedMemberPointer ||
1081 E->getCastKind() == CK_ReinterpretMemberPointer);
1082
1083 QualType DstType = E->getType();
1084
1088
1089
1090 if (E->getCastKind() == CK_ReinterpretMemberPointer) return src;
1091
1092
1093 llvm::Constant *adj = getMemberPointerAdjustment(E);
1094 if (!adj) return src;
1095
1096 bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);
1097
1098 const MemberPointerType *destTy =
1100
1101
1102
1104
1105 if (src->isAllOnesValue()) return src;
1106
1107 if (isDerivedToBase)
1108 return llvm::ConstantExpr::getNSWSub(src, adj);
1109 else
1110 return llvm::ConstantExpr::getNSWAdd(src, adj);
1111 }
1112
1113
1114 if (UseARMMethodPtrABI) {
1116 offset <<= 1;
1117 adj = llvm::ConstantInt::get(adj->getType(), offset);
1118 }
1119
1120 llvm::Constant *srcAdj = src->getAggregateElement(1);
1121 llvm::Constant *dstAdj;
1122 if (isDerivedToBase)
1123 dstAdj = llvm::ConstantExpr::getNSWSub(srcAdj, adj);
1124 else
1125 dstAdj = llvm::ConstantExpr::getNSWAdd(srcAdj, adj);
1126
1127 llvm::Constant *res = ConstantFoldInsertValueInstruction(src, dstAdj, 1);
1128 assert(res != nullptr && "Folding must succeed");
1129 return res;
1130}
1131
1132llvm::Constant *
1133ItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
1134
1135
1137 return llvm::ConstantInt::get(CGM.PtrDiffTy, -1ULL, true);
1138
1139 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.PtrDiffTy, 0);
1140 llvm::Constant *Values[2] = { Zero, Zero };
1141 return llvm::ConstantStruct::getAnon(Values);
1142}
1143
1144llvm::Constant *
1145ItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
1146 CharUnits offset) {
1147
1148
1149
1150 return llvm::ConstantInt::get(CGM.PtrDiffTy, offset.getQuantity());
1151}
1152
1153llvm::Constant *
1154ItaniumCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
1156}
1157
1158llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD,
1159 CharUnits ThisAdjustment) {
1160 assert(MD->isInstance() && "Member function must not be static!");
1161
1162 CodeGenTypes &Types = CGM.getTypes();
1163
1164
1165 llvm::Constant *MemPtr[2];
1167 uint64_t Index = CGM.getItaniumVTableContext().getMethodVTableIndex(MD);
1169 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1170
1171 VTableOffset = Index * 4;
1172 } else {
1173 const ASTContext &Context = getContext();
1176 VTableOffset = Index * PointerWidth.getQuantity();
1177 }
1178
1179 if (UseARMMethodPtrABI) {
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201 const auto &Schema =
1202 CGM.getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers;
1203 if (Schema)
1204 MemPtr[0] = llvm::ConstantExpr::getPtrToInt(
1205 getSignedVirtualMemberFunctionPointer(MD), CGM.PtrDiffTy);
1206 else
1207 MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset);
1208
1209
1210 MemPtr[1] = llvm::ConstantInt::get(
1211 CGM.PtrDiffTy, 2 * ThisAdjustment.getQuantity() + !Schema);
1212 } else {
1213
1214
1215
1216
1217 MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset + 1);
1218 MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1220 }
1221 } else {
1222 const FunctionProtoType *FPT = MD->getType()->castAs();
1223 llvm::Type *Ty;
1224
1226
1228 } else {
1229
1230
1231 Ty = CGM.PtrDiffTy;
1232 }
1233 llvm::Constant *addr = CGM.getMemberFunctionPointer(MD, Ty);
1234
1235 MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, CGM.PtrDiffTy);
1236 MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1237 (UseARMMethodPtrABI ? 2 : 1) *
1239 }
1240
1241 return llvm::ConstantStruct::getAnon(MemPtr);
1242}
1243
1244llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP,
1245 QualType MPType) {
1246 const MemberPointerType *MPT = MPType->castAs();
1248 if (!MPD)
1249 return EmitNullMemberPointer(MPT);
1250
1251 CharUnits ThisAdjustment = getContext().getMemberPointerPathAdjustment(MP);
1252
1253 if (const CXXMethodDecl *MD = dyn_cast(MPD)) {
1254 llvm::Constant *Src = BuildMemberPointer(MD, ThisAdjustment);
1255 QualType SrcType = getContext().getMemberPointerType(
1256 MD->getType(), std::nullopt, MD->getParent());
1258 }
1259
1260 CharUnits FieldOffset =
1261 getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD));
1262 return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset);
1263}
1264
1265
1266
1267
1268
1269llvm::Value *
1270ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
1271 llvm::Value *L,
1272 llvm::Value *R,
1273 const MemberPointerType *MPT,
1274 bool Inequality) {
1275 CGBuilderTy &Builder = CGF.Builder;
1276
1277 llvm::ICmpInst::Predicate Eq;
1278 llvm::Instruction::BinaryOps And, Or;
1279 if (Inequality) {
1280 Eq = llvm::ICmpInst::ICMP_NE;
1281 And = llvm::Instruction::Or;
1282 Or = llvm::Instruction::And;
1283 } else {
1284 Eq = llvm::ICmpInst::ICMP_EQ;
1285 And = llvm::Instruction::And;
1286 Or = llvm::Instruction::Or;
1287 }
1288
1289
1290
1292 return Builder.CreateICmp(Eq, L, R);
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304 llvm::Value *LPtr = Builder.CreateExtractValue(L, 0, "lhs.memptr.ptr");
1305 llvm::Value *RPtr = Builder.CreateExtractValue(R, 0, "rhs.memptr.ptr");
1306
1307
1308
1309 llvm::Value *PtrEq = Builder.CreateICmp(Eq, LPtr, RPtr, "cmp.ptr");
1310
1311
1312
1313
1314 llvm::Value *Zero = llvm::Constant::getNullValue(LPtr->getType());
1315 llvm::Value *EqZero = Builder.CreateICmp(Eq, LPtr, Zero, "cmp.ptr.null");
1316
1317
1318
1319 llvm::Value *LAdj = Builder.CreateExtractValue(L, 1, "lhs.memptr.adj");
1320 llvm::Value *RAdj = Builder.CreateExtractValue(R, 1, "rhs.memptr.adj");
1321 llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj, "cmp.adj");
1322
1323
1324
1325 if (UseARMMethodPtrABI) {
1326 llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1);
1327
1328
1329 llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj, "or.adj");
1330 llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One);
1331 llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1, Zero,
1332 "cmp.or.adj");
1333 EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero);
1334 }
1335
1336
1337 llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq);
1339 Inequality ? "memptr.ne" : "memptr.eq");
1341}
1342
1343llvm::Value *
1344ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
1345 llvm::Value *MemPtr,
1346 const MemberPointerType *MPT) {
1347 CGBuilderTy &Builder = CGF.Builder;
1348
1349
1351 assert(MemPtr->getType() == CGM.PtrDiffTy);
1352 llvm::Value *NegativeOne =
1353 llvm::Constant::getAllOnesValue(MemPtr->getType());
1354 return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool");
1355 }
1356
1357
1358 llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0, "memptr.ptr");
1359
1360 llvm::Constant *Zero = llvm::ConstantInt::get(Ptr->getType(), 0);
1361 llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero, "memptr.tobool");
1362
1363
1364
1365 if (UseARMMethodPtrABI) {
1366 llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1);
1367 llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj");
1368 llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit");
1369 llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit, Zero,
1370 "memptr.isvirtual");
1371 Result = Builder.CreateOr(Result, IsVirtual);
1372 }
1373
1375}
1376
1377bool ItaniumCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
1378 const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl();
1379 if (!RD)
1380 return false;
1381
1382
1384 auto Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType());
1386 Align, CGM.getDataLayout().getAllocaAddrSpace(),
1387 false);
1388 return true;
1389 }
1390 return false;
1391}
1392
1393
1394
1395bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
1397}
1398
1399
1400
1401void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
1402 const CXXDeleteExpr *DE,
1403 Address Ptr,
1404 QualType ElementType,
1405 const CXXDestructorDecl *Dtor) {
1407 if (UseGlobalDelete) {
1408
1409
1410
1411
1414
1415
1416 llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64(
1417 CGF.IntPtrTy, VTable, -2, "complete-offset.ptr");
1420
1421
1423 CompletePtr =
1425
1426
1427
1429 ElementType);
1430 }
1431
1432
1433
1435 EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE,
1436 nullptr);
1437
1438 if (UseGlobalDelete)
1440}
1441
1442void ItaniumCXXABI::emitRethrow(CodeGenFunction &CGF, bool isNoReturn) {
1443
1444
1445 llvm::FunctionType *FTy =
1446 llvm::FunctionType::get(CGM.VoidTy, false);
1447
1448 llvm::FunctionCallee Fn = CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow");
1449
1450 if (isNoReturn)
1452 else
1454}
1455
1457
1458
1459 llvm::FunctionType *FTy =
1460 llvm::FunctionType::get(CGM.Int8PtrTy, CGM.SizeTy, false);
1461
1463}
1464
1466
1467
1468
1470 llvm::FunctionType *FTy =
1471 llvm::FunctionType::get(CGM.VoidTy, Args, false);
1472
1474}
1475
1476void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) {
1478
1479 llvm::Type *SizeTy = CGF.ConvertType(getContext().getSizeType());
1480 uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity();
1481
1484 AllocExceptionFn, llvm::ConstantInt::get(SizeTy, TypeSize), "exception");
1485
1488 E->getSubExpr(), Address(ExceptionPtr, CGM.Int8Ty, ExnAlign));
1489
1490
1491 llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType,
1492 true);
1493
1494
1495
1496 llvm::Constant *Dtor = nullptr;
1499
1500
1501
1502 const ASTContext &Ctx = getContext();
1504 FunctionProtoType::ExtProtoInfo());
1505
1506 CXXDestructorDecl *DtorD = Record->getDestructor();
1507 Dtor = CGM.getAddrOfCXXStructor(GlobalDecl(DtorD, Dtor_Complete));
1508 Dtor = CGM.getFunctionPointer(Dtor, DtorTy);
1509 }
1510 if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);
1511
1512 llvm::Value *args[] = { ExceptionPtr, TypeInfo, Dtor };
1514}
1515
1517
1518
1519
1520
1521
1522 llvm::Type *Int8PtrTy = CGF.Int8PtrTy;
1524 llvm::Type *PtrDiffTy =
1526
1527 llvm::Type *Args[4] = { Int8PtrTy, GlobInt8PtrTy, GlobInt8PtrTy, PtrDiffTy };
1528
1529 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
1530
1531
1533 FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
1534 FuncAttrs.addAttribute(llvm::Attribute::WillReturn);
1535 FuncAttrs.addMemoryAttr(llvm::MemoryEffects::readOnly());
1536 llvm::AttributeList Attrs = llvm::AttributeList::get(
1537 CGF.getLLVMContext(), llvm::AttributeList::FunctionIndex, FuncAttrs);
1538
1540}
1541
1543
1544 llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);
1546}
1547
1548
1549
1553 CXXBasePaths Paths(true, true,
1554 false);
1555
1556
1557
1560
1561 unsigned NumPublicPaths = 0;
1563
1564
1566 if (Path.Access != AS_public)
1567 continue;
1568
1569 ++NumPublicPaths;
1570
1572
1573
1574 if (PathElement.Base->isVirtual())
1576
1577 if (NumPublicPaths > 1)
1578 continue;
1579
1580
1581 const ASTRecordLayout &L = Context.getASTRecordLayout(PathElement.Class);
1583 PathElement.Base->getType()->getAsCXXRecordDecl());
1584 }
1585 }
1586
1587
1588 if (NumPublicPaths == 0)
1590
1591
1592 if (NumPublicPaths > 1)
1594
1595
1596
1597 return Offset;
1598}
1599
1601
1602 llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);
1603
1605}
1606
1607bool ItaniumCXXABI::shouldTypeidBeNullChecked(QualType SrcRecordTy) {
1608 return true;
1609}
1610
1611void ItaniumCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {
1614 Call->setDoesNotReturn();
1615 CGF.Builder.CreateUnreachable();
1616}
1617
1618llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF,
1619 QualType SrcRecordTy,
1620 Address ThisPtr,
1621 llvm::Type *StdTypeInfoPtrTy) {
1623 llvm::Value *Value = CGF.GetVTablePtr(ThisPtr, CGM.GlobalsInt8PtrTy,
1624 ClassDecl);
1625
1626 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1627
1629 CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),
1630 {Value, llvm::ConstantInt::get(CGM.Int32Ty, -4)});
1631 } else {
1632
1634 CGF.Builder.CreateConstInBoundsGEP1_64(StdTypeInfoPtrTy, Value, -1ULL);
1635 }
1638}
1639
1640bool ItaniumCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
1641 QualType SrcRecordTy) {
1642 return SrcIsPtr;
1643}
1644
1645llvm::Value *ItaniumCXXABI::emitDynamicCastCall(
1646 CodeGenFunction &CGF, Address ThisAddr, QualType SrcRecordTy,
1647 QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd) {
1648 llvm::Type *PtrDiffLTy =
1650
1651 llvm::Value *SrcRTTI =
1653 llvm::Value *DestRTTI =
1655
1656
1659 llvm::Value *OffsetHint = llvm::ConstantInt::get(
1660 PtrDiffLTy,
1662
1663
1665 if (CGM.getCodeGenOpts().PointerAuth.CXXVTablePointers) {
1666
1667
1668
1669
1670
1671 llvm::Value *Vtable =
1672 CGF.GetVTablePtr(ThisAddr, CGM.Int8PtrTy, SrcDecl,
1673 CodeGenFunction::VTableAuthMode::MustTrap);
1674 assert(Vtable);
1675 (void)Vtable;
1676 }
1677
1678 llvm::Value *args[] = {Value, SrcRTTI, DestRTTI, OffsetHint};
1680
1681
1682
1684 llvm::BasicBlock *BadCastBlock =
1686
1688 CGF.Builder.CreateCondBr(IsNull, BadCastBlock, CastEnd);
1689
1691 EmitBadCastCall(CGF);
1692 }
1693
1695}
1696
1697std::optionalCGCXXABI::ExactDynamicCastInfo
1698ItaniumCXXABI::getExactDynamicCastInfo(QualType SrcRecordTy, QualType DestTy,
1699 QualType DestRecordTy) {
1700 assert(shouldEmitExactDynamicCast(DestRecordTy));
1701
1702 ASTContext &Context = getContext();
1703
1704
1707 CXXBasePaths Paths(true, true,
1708 false);
1710
1711
1712
1713 std::optional Offset;
1714 for (const CXXBasePath &Path : Paths) {
1715
1717 continue;
1718
1719 CharUnits PathOffset;
1720 for (const CXXBasePathElement &PathElement : Path) {
1721
1722 const CXXRecordDecl *Base =
1723 PathElement.Base->getType()->getAsCXXRecordDecl();
1724 if (PathElement.Base->isVirtual()) {
1725
1726
1729 } else {
1730 const ASTRecordLayout &L =
1733 }
1734 }
1735
1736 if (!Offset)
1737 Offset = PathOffset;
1738 else if (Offset != PathOffset) {
1739
1740 return ExactDynamicCastInfo{true,
1742 }
1743 }
1744 if (!Offset)
1745 return std::nullopt;
1746 return ExactDynamicCastInfo{false, *Offset};
1747}
1748
1749llvm::Value *ItaniumCXXABI::emitExactDynamicCast(
1750 CodeGenFunction &CGF, Address ThisAddr, QualType SrcRecordTy,
1751 QualType DestTy, QualType DestRecordTy,
1752 const ExactDynamicCastInfo &ExactCastInfo, llvm::BasicBlock *CastSuccess,
1753 llvm::BasicBlock *CastFail) {
1756 auto AuthenticateVTable = [&](Address ThisAddr, const CXXRecordDecl *Decl) {
1757 if (!CGF.getLangOpts().PointerAuthCalls)
1758 return;
1760 CodeGenFunction::VTableAuthMode::MustTrap);
1761 };
1762
1763 bool PerformPostCastAuthentication = false;
1764 llvm::Value *VTable = nullptr;
1765 if (ExactCastInfo.RequiresCastToPrimaryBase) {
1766
1767
1768
1769
1770 llvm::Value *PrimaryBase =
1773 SrcDecl = DestDecl;
1774
1775
1776
1777 PerformPostCastAuthentication = CGF.getLangOpts().PointerAuthCalls;
1778 CGPointerAuthInfo StrippingAuthInfo(0, PointerAuthenticationMode::Strip,
1779 false, false, nullptr);
1782 if (PerformPostCastAuthentication)
1784 } else
1786
1787
1788
1789 llvm::Constant *ExpectedVTable = getVTableAddressPoint(
1790 BaseSubobject(SrcDecl, ExactCastInfo.Offset), DestDecl);
1791 llvm::Value *Success = CGF.Builder.CreateICmpEQ(VTable, ExpectedVTable);
1792 llvm::Value *AdjustedThisPtr = ThisAddr.emitRawPointer(CGF);
1793
1794 if (!ExactCastInfo.Offset.isZero()) {
1796 llvm::Constant *OffsetConstant =
1797 llvm::ConstantInt::get(CGF.PtrDiffTy, -Offset);
1799 OffsetConstant);
1800 PerformPostCastAuthentication = CGF.getLangOpts().PointerAuthCalls;
1801 }
1802
1803 if (PerformPostCastAuthentication) {
1804
1805
1806 llvm::BasicBlock *NonNullBlock = CGF.Builder.GetInsertBlock();
1807 llvm::BasicBlock *PostCastAuthSuccess =
1809 llvm::BasicBlock *PostCastAuthComplete =
1811 CGF.Builder.CreateCondBr(Success, PostCastAuthSuccess,
1812 PostCastAuthComplete);
1813 CGF.EmitBlock(PostCastAuthSuccess);
1814 Address AdjustedThisAddr =
1816 AuthenticateVTable(AdjustedThisAddr, DestDecl);
1817 CGF.EmitBranch(PostCastAuthComplete);
1818 CGF.EmitBlock(PostCastAuthComplete);
1819 llvm::PHINode *PHI = CGF.Builder.CreatePHI(AdjustedThisPtr->getType(), 2);
1820 PHI->addIncoming(AdjustedThisPtr, PostCastAuthSuccess);
1821 llvm::Value *NullValue =
1822 llvm::Constant::getNullValue(AdjustedThisPtr->getType());
1823 PHI->addIncoming(NullValue, NonNullBlock);
1824 AdjustedThisPtr = PHI;
1825 }
1826 CGF.Builder.CreateCondBr(Success, CastSuccess, CastFail);
1827 return AdjustedThisPtr;
1828}
1829
1830llvm::Value *ItaniumCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF,
1831 Address ThisAddr,
1832 QualType SrcRecordTy) {
1834 llvm::Value *OffsetToTop;
1835 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1836
1837 llvm::Value *VTable =
1839
1840
1841 OffsetToTop =
1842 CGF.Builder.CreateConstInBoundsGEP1_32(CGM.Int32Ty, VTable, -2U);
1845 } else {
1846 llvm::Type *PtrDiffLTy =
1848
1849
1850 llvm::Value *VTable =
1852
1853
1854 OffsetToTop =
1855 CGF.Builder.CreateConstInBoundsGEP1_64(PtrDiffLTy, VTable, -2ULL);
1857 PtrDiffLTy, OffsetToTop, CGF.getPointerAlign(), "offset.to.top");
1858 }
1859
1861 OffsetToTop);
1862}
1863
1864bool ItaniumCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
1867 Call->setDoesNotReturn();
1868 CGF.Builder.CreateUnreachable();
1869 return true;
1870}
1871
1872llvm::Value *
1873ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
1874 Address This,
1875 const CXXRecordDecl *ClassDecl,
1876 const CXXRecordDecl *BaseClassDecl) {
1877 llvm::Value *VTablePtr = CGF.GetVTablePtr(This, CGM.Int8PtrTy, ClassDecl);
1878 CharUnits VBaseOffsetOffset =
1879 CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl,
1880 BaseClassDecl);
1881 llvm::Value *VBaseOffsetPtr =
1882 CGF.Builder.CreateConstGEP1_64(
1884 "vbase.offset.ptr");
1885
1886 llvm::Value *VBaseOffset;
1887 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1890 "vbase.offset");
1891 } else {
1893 CGM.PtrDiffTy, VBaseOffsetPtr, CGF.getPointerAlign(), "vbase.offset");
1894 }
1895 return VBaseOffset;
1896}
1897
1898void ItaniumCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {
1899
1900 assert(CGM.getTarget().getCXXABI().hasConstructorVariants());
1901
1902
1903
1904 CGM.EmitGlobal(GlobalDecl(D, Ctor_Base));
1905
1906
1907
1909
1911 }
1912}
1913
1914CGCXXABI::AddedStructorArgCounts
1915ItaniumCXXABI::buildStructorSignature(GlobalDecl GD,
1916 SmallVectorImpl &ArgTys) {
1917 ASTContext &Context = getContext();
1918
1919
1920
1921
1922
1926 LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);
1928 ArgTys.insert(ArgTys.begin() + 1,
1930 return AddedStructorArgCounts::prefix(1);
1931 }
1932 return AddedStructorArgCounts{};
1933}
1934
1935void ItaniumCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) {
1936
1937
1938 CGM.EmitGlobal(GlobalDecl(D, Dtor_Base));
1939
1940
1941
1943
1944
1945
1946
1949}
1950
1951void ItaniumCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,
1952 QualType &ResTy,
1953 FunctionArgList &Params) {
1956
1957
1958 if (NeedsVTTParameter(CGF.CurGD)) {
1959 ASTContext &Context = getContext();
1960
1961
1962 LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);
1967 T, ImplicitParamKind::CXXVTT);
1968 Params.insert(Params.begin() + 1, VTTDecl);
1969 getStructorImplicitParamDecl(CGF) = VTTDecl;
1970 }
1971}
1972
1973void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
1974
1976 return;
1977
1978
1979
1980 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
1981
1982
1983 if (getStructorImplicitParamDecl(CGF)) {
1985 CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)), "vtt");
1986 }
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996 if (HasThisReturn(CGF.CurGD))
1998}
1999
2000CGCXXABI::AddedStructorArgs ItaniumCXXABI::getImplicitConstructorArgs(
2001 CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type,
2002 bool ForVirtualBase, bool Delegating) {
2003 if (!NeedsVTTParameter(GlobalDecl(D, Type)))
2004 return AddedStructorArgs{};
2005
2006
2007
2008
2009 llvm::Value *VTT =
2011 LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);
2012 QualType Q = getContext().getAddrSpaceQualType(getContext().VoidPtrTy, AS);
2013 QualType VTTTy = getContext().getPointerType(Q);
2014 return AddedStructorArgs::prefix({{VTT, VTTTy}});
2015}
2016
2017llvm::Value *ItaniumCXXABI::getCXXDestructorImplicitParam(
2018 CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type,
2019 bool ForVirtualBase, bool Delegating) {
2020 GlobalDecl GD(DD, Type);
2022}
2023
2024void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
2025 const CXXDestructorDecl *DD,
2028 QualType ThisTy) {
2029 GlobalDecl GD(DD, Type);
2030 llvm::Value *VTT =
2032 QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
2033
2035 if (getContext().getLangOpts().AppleKext &&
2038 else
2040
2042 ThisTy, VTT, VTTTy, nullptr);
2043}
2044
2045
2046template
2049 if (const auto *FD = dyn_cast(D)) {
2052 continue;
2054 return true;
2055 }
2056 }
2057
2058 return false;
2059}
2060
2062 llvm::GlobalVariable *VTable,
2064 if (VTable->getDLLStorageClass() !=
2065 llvm::GlobalVariable::DefaultStorageClass ||
2066 RD->hasAttr() || RD->hasAttr())
2067 return;
2068
2071 VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
2073 VTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
2074}
2075
2076void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
2077 const CXXRecordDecl *RD) {
2078 llvm::GlobalVariable *VTable = getAddrOfVTable(RD, CharUnits());
2079 if (VTable->hasInitializer())
2080 return;
2081
2082 ItaniumVTableContext &VTContext = CGM.getItaniumVTableContext();
2083 const VTableLayout &VTLayout = VTContext.getVTableLayout(RD);
2084 llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
2085 llvm::Constant *RTTI =
2086 CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getCanonicalTagType(RD));
2087
2088
2089 ConstantInitBuilder builder(CGM);
2090 auto components = builder.beginStruct();
2092 llvm::GlobalValue::isLocalLinkage(Linkage));
2093 components.finishAndSetAsInitializer(VTable);
2094
2095
2096 VTable->setLinkage(Linkage);
2097
2098 if (CGM.supportsCOMDAT() && VTable->isWeakForLinker())
2099 VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName()));
2100
2101 if (CGM.getTarget().hasPS4DLLImportExport())
2103
2104
2105 CGM.setGVProperties(VTable, RD);
2106
2107
2108
2109
2116 EmitFundamentalRTTIDescriptors(RD);
2117
2118
2119
2120
2121
2122
2123
2124 if (!VTable->isDeclarationForLinker() ||
2125 CGM.getCodeGenOpts().WholeProgramVTables ||
2126 CGM.getCodeGenOpts().DevirtualizeSpeculatively) {
2127 CGM.EmitVTableTypeMetadata(RD, VTable, VTLayout);
2128
2129
2130
2131 if (VTable->isDeclarationForLinker()) {
2132 assert(CGM.getCodeGenOpts().WholeProgramVTables ||
2133 CGM.getCodeGenOpts().DevirtualizeSpeculatively);
2134 CGM.addCompilerUsedGlobal(VTable);
2135 }
2136 }
2137
2140 if (!VTable->isDSOLocal())
2142 }
2143
2144
2145 if (CGDebugInfo *DI = CGM.getModuleDebugInfo())
2146 DI->emitVTableSymbol(VTable, RD);
2147}
2148
2149bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField(
2150 CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr) {
2152 return false;
2153 return NeedsVTTParameter(CGF.CurGD);
2154}
2155
2156llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor(
2157 CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base,
2158 const CXXRecordDecl *NearestVBase) {
2159
2160 if ((Base.getBase()->getNumVBases() || NearestVBase != nullptr) &&
2161 NeedsVTTParameter(CGF.CurGD)) {
2162 return getVTableAddressPointInStructorWithVTT(CGF, VTableClass, Base,
2163 NearestVBase);
2164 }
2165 return getVTableAddressPoint(Base, VTableClass);
2166}
2167
2168llvm::Constant *
2169ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base,
2170 const CXXRecordDecl *VTableClass) {
2171 llvm::GlobalValue *VTable = getAddrOfVTable(VTableClass, CharUnits());
2172
2173
2174
2175 const VTableLayout &Layout =
2176 CGM.getItaniumVTableContext().getVTableLayout(VTableClass);
2177 VTableLayout::AddressPointLocation AddressPoint =
2179 llvm::Value *Indices[] = {
2180 llvm::ConstantInt::get(CGM.Int32Ty, 0),
2181 llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.VTableIndex),
2182 llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.AddressPointIndex),
2183 };
2184
2185
2186
2187 unsigned ComponentSize =
2188 CGM.getDataLayout().getTypeAllocSize(CGM.getVTableComponentType());
2189 unsigned VTableSize =
2191 unsigned Offset = ComponentSize * AddressPoint.AddressPointIndex;
2192 llvm::ConstantRange InRange(
2193 llvm::APInt(32, (int)-Offset, true),
2194 llvm::APInt(32, (int)(VTableSize - Offset), true));
2195 return llvm::ConstantExpr::getGetElementPtr(
2196 VTable->getValueType(), VTable, Indices, true, InRange);
2197}
2198
2199llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
2200 CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base,
2201 const CXXRecordDecl *NearestVBase) {
2202 assert((Base.getBase()->getNumVBases() || NearestVBase != nullptr) &&
2203 NeedsVTTParameter(CGF.CurGD) && "This class doesn't have VTT");
2204
2205
2206 uint64_t VirtualPointerIndex =
2207 CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass, Base);
2208
2209
2210 llvm::Value *VTT = CGF.LoadCXXVTT();
2211 if (VirtualPointerIndex)
2213 VirtualPointerIndex);
2214
2215
2216 llvm::Value *AP =
2219
2222 GlobalDecl(),
2223 QualType());
2225 }
2226
2227 return AP;
2228}
2229
2230llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
2231 CharUnits VPtrOffset) {
2232 assert(VPtrOffset.isZero() && "Itanium ABI only supports zero vptr offsets");
2233
2234 llvm::GlobalVariable *&VTable = VTables[RD];
2235 if (VTable)
2236 return VTable;
2237
2238
2239 CGM.addDeferredVTable(RD);
2240
2241 SmallString<256> Name;
2242 llvm::raw_svector_ostream Out(Name);
2243 getMangleContext().mangleCXXVTable(RD, Out);
2244
2245 const VTableLayout &VTLayout =
2246 CGM.getItaniumVTableContext().getVTableLayout(RD);
2247 llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout);
2248
2249
2250
2251
2252 unsigned PAlign = CGM.getVtableGlobalVarAlignment();
2253
2254 VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
2255 Name, VTableType, llvm::GlobalValue::ExternalLinkage,
2256 getContext().toCharUnitsFromBits(PAlign).getAsAlign());
2257 VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2258
2259 if (CGM.getTarget().hasPS4DLLImportExport())
2261
2262 CGM.setGVProperties(VTable, RD);
2263 return VTable;
2264}
2265
2266CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
2267 GlobalDecl GD,
2268 Address This,
2269 llvm::Type *Ty,
2270 SourceLocation Loc) {
2271 llvm::Type *PtrTy = CGM.GlobalsInt8PtrTy;
2273 llvm::Value *VTable = CGF.GetVTablePtr(This, PtrTy, MethodDecl->getParent());
2274
2275 uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
2276 llvm::Value *VFunc, *VTableSlotPtr = nullptr;
2277 auto &Schema = CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers;
2278
2279 llvm::Type *ComponentTy = CGM.getVTables().getVTableComponentType();
2281 VTableIndex * CGM.getDataLayout().getTypeSizeInBits(ComponentTy) / 8;
2282
2285 PtrTy, ByteOffset);
2286 } else {
2288
2289 llvm::Value *VFuncLoad;
2290 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
2291 VFuncLoad = CGF.Builder.CreateCall(
2292 CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),
2293 {VTable, llvm::ConstantInt::get(CGM.Int32Ty, ByteOffset)});
2294 } else {
2295 VTableSlotPtr = CGF.Builder.CreateConstInBoundsGEP1_64(
2296 PtrTy, VTable, VTableIndex, "vfn");
2299 }
2300
2301
2302
2303
2304
2305
2306
2307 if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
2308 CGM.getCodeGenOpts().StrictVTablePointers) {
2309 if (auto *VFuncLoadInstr = dyn_castllvm::Instruction(VFuncLoad)) {
2310 VFuncLoadInstr->setMetadata(
2311 llvm::LLVMContext::MD_invariant_load,
2312 llvm::MDNode::get(CGM.getLLVMContext(),
2313 llvm::ArrayRef<llvm::Metadata *>()));
2314 }
2315 }
2316 VFunc = VFuncLoad;
2317 }
2318
2319 CGPointerAuthInfo PointerAuth;
2320 if (Schema) {
2321 assert(VTableSlotPtr && "virtual function pointer not set");
2322 GD = CGM.getItaniumVTableContext().findOriginalMethod(GD.getCanonicalDecl());
2323 PointerAuth = CGF.EmitPointerAuthInfo(Schema, VTableSlotPtr, GD, QualType());
2324 }
2325 CGCallee Callee(GD, VFunc, PointerAuth);
2327}
2328
2329llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
2330 CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType,
2331 Address This, DeleteOrMemberCallExpr E, llvm::CallBase **CallOrInvoke) {
2332 auto *CE = dyn_cast<const CXXMemberCallExpr *>(E);
2333 auto *D = dyn_cast<const CXXDeleteExpr *>(E);
2334 assert((CE != nullptr) ^ (D != nullptr));
2335 assert(CE == nullptr || CE->arguments().empty());
2337
2338 GlobalDecl GD(Dtor, DtorType);
2339 const CGFunctionInfo *FInfo =
2340 &CGM.getTypes().arrangeCXXStructorDeclaration(GD);
2343
2344 QualType ThisTy;
2345 if (CE) {
2346 ThisTy = CE->getObjectType();
2347 } else {
2348 ThisTy = D->getDestroyedType();
2349 }
2350
2352 nullptr, QualType(), nullptr, CallOrInvoke);
2353 return nullptr;
2354}
2355
2356void ItaniumCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) {
2357 CodeGenVTables &VTables = CGM.getVTables();
2358 llvm::GlobalVariable *VTT = VTables.GetAddrOfVTT(RD);
2360}
2361
2362bool ItaniumCXXABI::canSpeculativelyEmitVTableAsBaseClass(
2363 const CXXRecordDecl *RD) const {
2364
2365
2366 if (CGM.getLangOpts().AppleKext)
2367 return false;
2368
2369
2370
2371 if (isVTableHidden(RD))
2372 return false;
2373
2374 if (CGM.getCodeGenOpts().ForceEmitVTables)
2375 return true;
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391 if (hasAnyUnusedVirtualInlineFunction(RD))
2392 return false;
2393
2394
2395
2396
2397
2399 for (const auto &B : RD->bases()) {
2400 auto *BRD = B.getType()->getAsCXXRecordDecl();
2401 assert(BRD && "no class for base specifier");
2402 if (B.isVirtual() || !BRD->isDynamicClass())
2403 continue;
2404 if (!canSpeculativelyEmitVTableAsBaseClass(BRD))
2405 return false;
2406 }
2407 }
2408
2409 return true;
2410}
2411
2412bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const {
2413 if (!canSpeculativelyEmitVTableAsBaseClass(RD))
2414 return false;
2415
2417 return false;
2418
2419
2420
2421 for (const auto &B : RD->vbases()) {
2422 auto *BRD = B.getType()->getAsCXXRecordDecl();
2423 assert(BRD && "no class for base specifier");
2424 if (!BRD->isDynamicClass())
2425 continue;
2426 if (!canSpeculativelyEmitVTableAsBaseClass(BRD))
2427 return false;
2428 }
2429
2430 return true;
2431}
2435 int64_t NonVirtualAdjustment,
2436 int64_t VirtualAdjustment,
2437 bool IsReturnAdjustment) {
2438 if (!NonVirtualAdjustment && !VirtualAdjustment)
2440
2442
2443
2444 if (NonVirtualAdjustment && !IsReturnAdjustment) {
2447 }
2448
2449
2450 llvm::Value *ResultPtr;
2451 if (VirtualAdjustment) {
2452 llvm::Value *VTablePtr =
2454
2455 llvm::Value *Offset;
2456 llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64(
2457 CGF.Int8Ty, VTablePtr, VirtualAdjustment);
2459
2460 Offset =
2463 } else {
2464 llvm::Type *PtrDiffTy =
2466
2467
2470 }
2471
2473 V.emitRawPointer(CGF), Offset);
2474 } else {
2475 ResultPtr = V.emitRawPointer(CGF);
2476 }
2477
2478
2479
2480 if (NonVirtualAdjustment && IsReturnAdjustment) {
2481 ResultPtr = CGF.Builder.CreateConstInBoundsGEP1_64(CGF.Int8Ty, ResultPtr,
2482 NonVirtualAdjustment);
2483 }
2484
2485 return ResultPtr;
2486}
2487
2488llvm::Value *
2489ItaniumCXXABI::performThisAdjustment(CodeGenFunction &CGF, Address This,
2490 const CXXRecordDecl *UnadjustedClass,
2491 const ThunkInfo &TI) {
2494 false);
2495}
2496
2497llvm::Value *
2498ItaniumCXXABI::performReturnAdjustment(CodeGenFunction &CGF, Address Ret,
2499 const CXXRecordDecl *UnadjustedClass,
2500 const ReturnAdjustment &RA) {
2503 true);
2504}
2505
2506void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
2507 RValue RV, QualType ResultType) {
2509 return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType);
2510
2511
2513 RValue Undef = RValue::get(llvm::UndefValue::get(T));
2514 return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType);
2515}
2516
2517
2518
2519CharUnits ItaniumCXXABI::getArrayCookieSizeImpl(QualType elementType) {
2520
2521
2523 CGM.getContext().getPreferredTypeAlignInChars(elementType));
2524}
2525
2526Address ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
2527 Address NewPtr,
2528 llvm::Value *NumElements,
2529 const CXXNewExpr *expr,
2530 QualType ElementType) {
2531 assert(requiresArrayCookie(expr));
2532
2534
2535 ASTContext &Ctx = getContext();
2537
2538
2539 CharUnits CookieSize =
2541 assert(CookieSize == getArrayCookieSizeImpl(ElementType));
2542
2543
2544 Address CookiePtr = NewPtr;
2545 CharUnits CookieOffset = CookieSize - SizeSize;
2546 if (!CookieOffset.isZero())
2548
2549
2551 llvm::Instruction *SI = CGF.Builder.CreateStore(NumElements, NumElementsPtr);
2552
2553
2554 if (CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) && AS == 0 &&
2555 (expr->getOperatorNew()->isReplaceableGlobalAllocationFunction() ||
2556 CGM.getCodeGenOpts().SanitizeAddressPoisonCustomArrayCookie)) {
2557
2558 SI->setNoSanitizeMetadata();
2559 llvm::FunctionType *FTy =
2560 llvm::FunctionType::get(CGM.VoidTy, NumElementsPtr.getType(), false);
2561 llvm::FunctionCallee F =
2562 CGM.CreateRuntimeFunction(FTy, "__asan_poison_cxx_array_cookie");
2564 }
2565
2566
2567
2569}
2570
2571llvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
2572 Address allocPtr,
2573 CharUnits cookieSize) {
2574
2575 Address numElementsPtr = allocPtr;
2576 CharUnits numElementsOffset = cookieSize - CGF.getSizeSize();
2577 if (!numElementsOffset.isZero())
2578 numElementsPtr =
2580
2583 if (!CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) || AS != 0)
2585
2586
2587
2588
2589
2590 llvm::FunctionType *FTy =
2592 llvm::FunctionCallee F =
2593 CGM.CreateRuntimeFunction(FTy, "__asan_load_cxx_array_cookie");
2595}
2596
2597CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) {
2598
2599
2600
2601
2602
2603
2604
2605
2607 CGM.getContext().getTypeAlignInChars(elementType));
2608}
2609
2610Address ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
2611 Address newPtr,
2612 llvm::Value *numElements,
2613 const CXXNewExpr *expr,
2614 QualType elementType) {
2615 assert(requiresArrayCookie(expr));
2616
2617
2618 Address cookie = newPtr;
2619
2620
2622 llvm::Value *elementSize = llvm::ConstantInt::get(CGF.SizeTy,
2623 getContext().getTypeSizeInChars(elementType).getQuantity());
2625
2626
2629
2630
2631
2632 CharUnits cookieSize = ARMCXXABI::getArrayCookieSizeImpl(elementType);
2634}
2635
2636llvm::Value *ARMCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
2637 Address allocPtr,
2638 CharUnits cookieSize) {
2639
2640
2641 Address numElementsPtr
2643
2646}
2647
2648
2649
2651 llvm::PointerType *GuardPtrTy) {
2652
2653 llvm::FunctionType *FTy =
2655 GuardPtrTy, false);
2657 FTy, "__cxa_guard_acquire",
2659 llvm::AttributeList::FunctionIndex,
2660 llvm::Attribute::NoUnwind));
2661}
2662
2664 llvm::PointerType *GuardPtrTy) {
2665
2666 llvm::FunctionType *FTy =
2667 llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, false);
2669 FTy, "__cxa_guard_release",
2671 llvm::AttributeList::FunctionIndex,
2672 llvm::Attribute::NoUnwind));
2673}
2674
2676 llvm::PointerType *GuardPtrTy) {
2677
2678 llvm::FunctionType *FTy =
2679 llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, false);
2681 FTy, "__cxa_guard_abort",
2683 llvm::AttributeList::FunctionIndex,
2684 llvm::Attribute::NoUnwind));
2685}
2686
2687namespace {
2688 struct CallGuardAbort final : EHScopeStack::Cleanup {
2689 llvm::GlobalVariable *Guard;
2690 CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
2691
2692 void Emit(CodeGenFunction &CGF, Flags flags) override {
2694 Guard);
2695 }
2696 };
2697}
2698
2699
2700
2701void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
2702 const VarDecl &D,
2703 llvm::GlobalVariable *var,
2704 bool shouldPerformInit) {
2705 CGBuilderTy &Builder = CGF.Builder;
2706
2707
2708
2709 bool NonTemplateInline =
2712
2713
2714
2715
2716 bool threadsafe = getContext().getLangOpts().ThreadsafeStatics &&
2719
2720
2721
2722 bool useInt8GuardVariable = !threadsafe && var->hasInternalLinkage();
2723
2724 llvm::IntegerType *guardTy;
2725 CharUnits guardAlignment;
2726 if (useInt8GuardVariable) {
2727 guardTy = CGF.Int8Ty;
2729 } else {
2730
2731
2732 if (UseARMGuardVarABI) {
2733 guardTy = CGF.SizeTy;
2735 } else {
2737 guardAlignment =
2739 }
2740 }
2741 llvm::PointerType *guardPtrTy = llvm::PointerType::get(
2744
2745
2746
2747 llvm::GlobalVariable *guard = CGM.getStaticLocalDeclGuardAddress(&D);
2748 if (!guard) {
2749
2750 SmallString<256> guardName;
2751 {
2752 llvm::raw_svector_ostream out(guardName);
2753 getMangleContext().mangleStaticGuardVariable(&D, out);
2754 }
2755
2756
2757
2758
2759 guard = new llvm::GlobalVariable(CGM.getModule(), guardTy,
2760 false, var->getLinkage(),
2761 llvm::ConstantInt::get(guardTy, 0),
2762 guardName.str());
2763 guard->setDSOLocal(var->isDSOLocal());
2764 guard->setVisibility(var->getVisibility());
2765 guard->setDLLStorageClass(var->getDLLStorageClass());
2766
2767 guard->setThreadLocalMode(var->getThreadLocalMode());
2768 guard->setAlignment(guardAlignment.getAsAlign());
2769
2770
2771
2772
2773 llvm::Comdat *C = var->getComdat();
2775 (CGM.getTarget().getTriple().isOSBinFormatELF() ||
2776 CGM.getTarget().getTriple().isOSBinFormatWasm())) {
2777 guard->setComdat(C);
2778 } else if (CGM.supportsCOMDAT() && guard->isWeakForLinker()) {
2779 guard->setComdat(CGM.getModule().getOrInsertComdat(guard->getName()));
2780 }
2781
2782 CGM.setStaticLocalDeclGuardAddress(&D, guard);
2783 }
2784
2785 Address guardAddr = Address(guard, guard->getValueType(), guardAlignment);
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2809 llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
2810 if (!threadsafe || MaxInlineWidthInBits) {
2811
2812 llvm::LoadInst *LI =
2813 Builder.CreateLoad(guardAddr.withElementType(CGM.Int8Ty));
2814
2815
2816
2817
2818
2819
2820
2821 if (threadsafe)
2822 LI->setAtomic(llvm::AtomicOrdering::Acquire);
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844 llvm::Value *V =
2845 (UseARMGuardVarABI && !useInt8GuardVariable)
2846 ? Builder.CreateAnd(LI, llvm::ConstantInt::get(CGM.Int8Ty, 1))
2847 : LI;
2848 llvm::Value *NeedsInit = Builder.CreateIsNull(V, "guard.uninitialized");
2849
2850 llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check");
2851
2852
2854 CodeGenFunction::GuardKind::VariableGuard, &D);
2855
2857 }
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875 if (threadsafe) {
2876
2877 llvm::Value *V
2879
2881
2882 Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"),
2883 InitBlock, EndBlock);
2884
2885
2887
2890
2891
2892
2893 Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),
2895 }
2896
2897
2899
2900 if (threadsafe) {
2901
2903
2904
2908
2909
2910
2911 Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),
2913 }
2914
2916}
2917
2918
2920 llvm::FunctionCallee dtor,
2921 llvm::Constant *addr, bool TLS) {
2923 "unexpected call to emitGlobalDtorWithCXAAtExit");
2925 "__cxa_atexit is disabled");
2926 const char *Name = "__cxa_atexit";
2927 if (TLS) {
2929 Name = T.isOSDarwin() ? "_tlv_atexit" : "__cxa_thread_atexit";
2930 }
2931
2932
2933
2935
2936
2937 auto AddrAS = addr ? addr->getType()->getPointerAddressSpace() : 0;
2938 auto AddrPtrTy = AddrAS ? llvm::PointerType::get(CGF.getLLVMContext(), AddrAS)
2940
2941
2942 llvm::Constant *handle =
2945 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
2946
2947
2948 llvm::Type *paramTys[] = {dtorTy, AddrPtrTy, handle->getType()};
2949 llvm::FunctionType *atexitTy =
2950 llvm::FunctionType::get(CGF.IntTy, paramTys, false);
2951
2952
2954 if (llvm::Function *fn = dyn_castllvm::Function(atexit.getCallee()))
2955 fn->setDoesNotThrow();
2956
2959 false, false));
2961 Context.getFunctionType(Context.VoidTy, {Context.VoidPtrTy}, EPI);
2964
2965 if (!addr)
2966
2967
2968
2969
2970 addr = llvm::Constant::getNullValue(CGF.Int8PtrTy);
2971
2972 llvm::Value *args[] = {dtorCallee, addr, handle};
2974}
2975
2977 StringRef FnName) {
2978
2979
2980 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
2983
2984 return GlobalInitOrCleanupFn;
2985}
2986
2987void CodeGenModule::unregisterGlobalDtorsWithUnAtExit() {
2988 for (const auto &I : DtorsUsingAtExit) {
2989 int Priority = I.first;
2990 std::string GlobalCleanupFnName =
2991 std::string("__GLOBAL_cleanup_") + llvm::to_string(Priority);
2992
2993 llvm::Function *GlobalCleanupFn =
2995
2996 CodeGenFunction CGF(*this);
2997 CGF.StartFunction(GlobalDecl(), getContext().VoidTy, GlobalCleanupFn,
2998 getTypes().arrangeNullaryFunction(), FunctionArgList(),
2999 SourceLocation(), SourceLocation());
3001
3002
3003 llvm::FunctionType *dtorFuncTy = llvm::FunctionType::get(CGF.VoidTy, false);
3004
3005
3006
3007 const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second;
3008 auto itv = Dtors.rbegin();
3009 while (itv != Dtors.rend()) {
3010 llvm::Function *Dtor = *itv;
3011
3012
3013
3015 llvm::Value *NeedsDestruct =
3017
3018 llvm::BasicBlock *DestructCallBlock =
3021 (itv + 1) != Dtors.rend() ? "unatexit.call" : "destruct.end");
3022
3023
3024 CGF.Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock);
3025
3026 CGF.EmitBlock(DestructCallBlock);
3027
3028
3029 llvm::CallInst *CI = CGF.Builder.CreateCall(dtorFuncTy, Dtor);
3030
3031 CI->setCallingConv(Dtor->getCallingConv());
3032
3034
3035 itv++;
3036 }
3037
3039 AddGlobalDtor(GlobalCleanupFn, Priority);
3040 }
3041}
3042
3043void CodeGenModule::registerGlobalDtorsWithAtExit() {
3044 for (const auto &I : DtorsUsingAtExit) {
3045 int Priority = I.first;
3046 std::string GlobalInitFnName =
3047 std::string("__GLOBAL_init_") + llvm::to_string(Priority);
3048 llvm::Function *GlobalInitFn =
3050
3051 CodeGenFunction CGF(*this);
3052 CGF.StartFunction(GlobalDecl(), getContext().VoidTy, GlobalInitFn,
3053 getTypes().arrangeNullaryFunction(), FunctionArgList(),
3054 SourceLocation(), SourceLocation());
3056
3057
3058
3059
3060
3061
3062 const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second;
3063 for (auto *Dtor : Dtors) {
3064
3065
3066 if (getCodeGenOpts().CXAAtExit) {
3068 } else {
3069
3070
3072 }
3073 }
3074
3076 AddGlobalCtor(GlobalInitFn, Priority);
3077 }
3078
3079 if (getCXXABI().useSinitAndSterm())
3080 unregisterGlobalDtorsWithUnAtExit();
3081}
3082
3083
3084void ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
3085 llvm::FunctionCallee dtor,
3086 llvm::Constant *addr) {
3088 return;
3089
3090
3091 if (CGM.getLangOpts().HLSL)
3092 return CGM.AddCXXDtorEntry(dtor, addr);
3093
3094
3095
3096
3097
3098
3099 if (!CGM.getLangOpts().hasAtExit() && !D.isStaticLocal())
3101
3102
3103
3104
3105
3106 if (CGM.getCodeGenOpts().CXAAtExit || D.getTLSKind())
3108
3109
3110
3111 if (CGM.getLangOpts().AppleKext) {
3112
3113 return CGM.AddCXXDtorEntry(dtor, addr);
3114 }
3115
3117}
3118
3121 assert(!VD->isStaticLocal() && "static local VarDecls don't need wrappers!");
3122
3123
3126}
3127
3128
3129
3130
3131static llvm::GlobalValue::LinkageTypes
3133 llvm::GlobalValue::LinkageTypes VarLinkage =
3135
3136
3137 if (llvm::GlobalValue::isLocalLinkage(VarLinkage))
3138 return VarLinkage;
3139
3140
3142 if (!llvm::GlobalVariable::isLinkOnceLinkage(VarLinkage) &&
3143 !llvm::GlobalVariable::isWeakODRLinkage(VarLinkage))
3144 return VarLinkage;
3145 return llvm::GlobalValue::WeakODRLinkage;
3146}
3147
3148llvm::Function *
3149ItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD,
3150 llvm::Value *Val) {
3151
3152 SmallString<256> WrapperName;
3153 {
3154 llvm::raw_svector_ostream Out(WrapperName);
3155 getMangleContext().mangleItaniumThreadLocalWrapper(VD, Out);
3156 }
3157
3158
3159
3160 if (llvm::Value *V = CGM.getModule().getNamedValue(WrapperName))
3162
3163 QualType RetQT = VD->getType();
3166
3167 const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
3168 getContext().getPointerType(RetQT), FunctionArgList());
3169
3170 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FI);
3171 llvm::Function *Wrapper =
3173 WrapperName.str(), &CGM.getModule());
3174
3175 if (CGM.supportsCOMDAT() && Wrapper->isWeakForLinker())
3176 Wrapper->setComdat(CGM.getModule().getOrInsertComdat(Wrapper->getName()));
3177
3178 CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Wrapper, false);
3179
3180
3181 if (!Wrapper->hasLocalLinkage())
3183 llvm::GlobalVariable::isLinkOnceLinkage(Wrapper->getLinkage()) ||
3184 llvm::GlobalVariable::isWeakODRLinkage(Wrapper->getLinkage()) ||
3186 Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility);
3187
3189 Wrapper->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
3190 Wrapper->addFnAttr(llvm::Attribute::NoUnwind);
3191 }
3192
3193 ThreadWrappers.push_back({VD, Wrapper});
3194 return Wrapper;
3195}
3196
3197void ItaniumCXXABI::EmitThreadLocalInitFuncs(
3198 CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
3199 ArrayRef<llvm::Function *> CXXThreadLocalInits,
3200 ArrayRef<const VarDecl *> CXXThreadLocalInitVars) {
3201 llvm::Function *InitFunc = nullptr;
3202
3203
3204
3205 llvm::SmallVector<llvm::Function *, 8> OrderedInits;
3206 llvm::SmallDenseMap<const VarDecl *, llvm::Function *> UnorderedInits;
3207 for (unsigned I = 0; I != CXXThreadLocalInits.size(); ++I) {
3210 UnorderedInits[CXXThreadLocalInitVars[I]->getCanonicalDecl()] =
3211 CXXThreadLocalInits[I];
3212 else
3213 OrderedInits.push_back(CXXThreadLocalInits[I]);
3214 }
3215
3216 if (!OrderedInits.empty()) {
3217
3218 llvm::FunctionType *FTy =
3219 llvm::FunctionType::get(CGM.VoidTy, false);
3222 SourceLocation(),
3223 true);
3224 llvm::GlobalVariable *Guard = new llvm::GlobalVariable(
3226 llvm::GlobalVariable::InternalLinkage,
3227 llvm::ConstantInt::get(CGM.Int8Ty, 0), "__tls_guard");
3228 Guard->setThreadLocal(true);
3230
3232 Guard->setAlignment(GuardAlign.getAsAlign());
3233
3234 CodeGenFunction(CGM).GenerateCXXGlobalInitFunc(
3235 InitFunc, OrderedInits, ConstantAddress(Guard, CGM.Int8Ty, GuardAlign));
3236
3238 InitFunc->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
3239 InitFunc->addFnAttr(llvm::Attribute::NoUnwind);
3240 }
3241 }
3242
3243
3244
3245 for (const VarDecl *VD : CXXThreadLocals) {
3249 getOrCreateThreadLocalWrapper(VD, GV);
3250 }
3251 }
3252
3253
3254 for (auto VDAndWrapper : ThreadWrappers) {
3255 const VarDecl *VD = VDAndWrapper.first;
3256 llvm::GlobalVariable *Var =
3258 llvm::Function *Wrapper = VDAndWrapper.second;
3259
3260
3261
3262
3265 Wrapper->setLinkage(llvm::Function::ExternalLinkage);
3266 continue;
3267 }
3268
3269
3270
3271 if (Wrapper->getLinkage() == llvm::Function::WeakODRLinkage)
3272 Wrapper->setLinkage(llvm::Function::LinkOnceODRLinkage);
3273 }
3274
3276
3277
3278 SmallString<256> InitFnName;
3279 {
3280 llvm::raw_svector_ostream Out(InitFnName);
3281 getMangleContext().mangleItaniumThreadLocalInit(VD, Out);
3282 }
3283
3284 llvm::FunctionType *InitFnTy = llvm::FunctionType::get(CGM.VoidTy, false);
3285
3286
3287
3288
3289 llvm::GlobalValue *Init = nullptr;
3290 bool InitIsInitFunc = false;
3291 bool HasConstantInitialization = false;
3292 if (!usesThreadWrapperFunction(VD)) {
3293 HasConstantInitialization = true;
3295 InitIsInitFunc = true;
3296 llvm::Function *InitFuncToUse = InitFunc;
3298 InitFuncToUse = UnorderedInits.lookup(VD->getCanonicalDecl());
3299 if (InitFuncToUse)
3300 Init = llvm::GlobalAlias::create(Var->getLinkage(), InitFnName.str(),
3301 InitFuncToUse);
3302 } else {
3303
3304
3305
3306
3307 Init = llvm::Function::Create(InitFnTy,
3308 llvm::GlobalVariable::ExternalWeakLinkage,
3309 InitFnName.str(), &CGM.getModule());
3313 }
3314
3316 Init->setVisibility(Var->getVisibility());
3317
3318 if (!CGM.getTriple().isOSWindows() || ->hasExternalWeakLinkage())
3319 Init->setDSOLocal(Var->isDSOLocal());
3320 }
3321
3322 llvm::LLVMContext &Context = CGM.getModule().getContext();
3323
3324
3325
3326
3327
3328
3330 isEmittedWithConstantInitializer(VD, true) &&
3331 !mayNeedDestruction(VD)) {
3332
3333
3334
3335
3336 assert(Init == nullptr && "Expected Init to be null.");
3337
3338 llvm::Function *Func = llvm::Function::Create(
3339 InitFnTy, Var->getLinkage(), InitFnName.str(), &CGM.getModule());
3343 false);
3344
3345 llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Func);
3346 CGBuilderTy Builder(CGM, Entry);
3347 Builder.CreateRetVoid();
3348 }
3349
3350 llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Wrapper);
3351 CGBuilderTy Builder(CGM, Entry);
3352 if (HasConstantInitialization) {
3353
3354 } else if (InitIsInitFunc) {
3356 llvm::CallInst *CallVal = Builder.CreateCall(InitFnTy, Init);
3358 CallVal->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
3359 llvm::Function *Fn =
3361 Fn->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
3362 }
3363 }
3364 } else if (CGM.getTriple().isOSAIX()) {
3365
3366
3367
3368
3369
3370
3371
3372 Builder.CreateCall(InitFnTy, Init);
3373 } else {
3374
3375 llvm::Value *Have = Builder.CreateIsNotNull(Init);
3376 llvm::BasicBlock *InitBB = llvm::BasicBlock::Create(Context, "", Wrapper);
3377 llvm::BasicBlock *ExitBB = llvm::BasicBlock::Create(Context, "", Wrapper);
3378 Builder.CreateCondBr(Have, InitBB, ExitBB);
3379
3380 Builder.SetInsertPoint(InitBB);
3381 Builder.CreateCall(InitFnTy, Init);
3382 Builder.CreateBr(ExitBB);
3383
3384 Builder.SetInsertPoint(ExitBB);
3385 }
3386
3387
3388
3389 llvm::Value *Val = Builder.CreateThreadLocalAddress(Var);
3390
3393 Val = Builder.CreateAlignedLoad(Var->getValueType(), Val, Align);
3394 }
3395 Val = Builder.CreateAddrSpaceCast(Val, Wrapper->getReturnType());
3396
3397 Builder.CreateRet(Val);
3398 }
3399}
3400
3401LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
3402 const VarDecl *VD,
3403 QualType LValType) {
3405 llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Val);
3406
3407 llvm::CallInst *CallVal = CGF.Builder.CreateCall(Wrapper);
3408 CallVal->setCallingConv(Wrapper->getCallingConv());
3409
3410 LValue LV;
3413 else
3416
3417 return LV;
3418}
3419
3420
3421
3422bool ItaniumCXXABI::NeedsVTTParameter(GlobalDecl GD) {
3424
3425
3427 return false;
3428
3429
3431 return true;
3432
3433
3435 return true;
3436
3437 return false;
3438}
3439
3440llvm::Constant *
3441ItaniumCXXABI::getOrCreateVirtualFunctionPointerThunk(const CXXMethodDecl *MD) {
3442 SmallString<256> MethodName;
3443 llvm::raw_svector_ostream Out(MethodName);
3444 getMangleContext().mangleCXXName(MD, Out);
3445 MethodName += "_vfpthunk_";
3446 StringRef ThunkName = MethodName.str();
3447 llvm::Function *ThunkFn;
3448 if ((ThunkFn = cast_or_nullllvm::Function(
3449 CGM.getModule().getNamedValue(ThunkName))))
3450 return ThunkFn;
3451
3454 llvm::GlobalValue::LinkageTypes Linkage =
3456 : llvm::GlobalValue::InternalLinkage;
3457 ThunkFn =
3458 llvm::Function::Create(ThunkTy, Linkage, ThunkName, &CGM.getModule());
3459 if (Linkage == llvm::GlobalValue::LinkOnceODRLinkage)
3460 ThunkFn->setVisibility(llvm::GlobalValue::HiddenVisibility);
3461 assert(ThunkFn->getName() == ThunkName && "name was uniqued!");
3462
3465
3466
3467 ThunkFn->removeFnAttr(llvm::Attribute::StackProtect);
3468 ThunkFn->removeFnAttr(llvm::Attribute::StackProtectStrong);
3469 ThunkFn->removeFnAttr(llvm::Attribute::StackProtectReq);
3470
3471
3472 CodeGenFunction CGF(CGM);
3473 CGF.CurGD = GlobalDecl(MD);
3475
3476
3477 FunctionArgList FunctionArgs;
3479
3481 FunctionArgs, MD->getLocation(), SourceLocation());
3482 llvm::Value *ThisVal = loadIncomingCXXThis(CGF);
3483 setCXXABIThisValue(CGF, ThisVal);
3484
3485 CallArgList CallArgs;
3486 for (const VarDecl *VD : FunctionArgs)
3488
3489 const FunctionProtoType *FPT = MD->getType()->getAs();
3491 const CGFunctionInfo &CallInfo =
3494 getThisAddress(CGF), ThunkTy);
3495 llvm::CallBase *CallOrInvoke;
3496 CGF.EmitCall(CallInfo, Callee, ReturnValueSlot(), CallArgs, &CallOrInvoke,
3497 true, SourceLocation(), true);
3499 Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
3500 if (Call->getType()->isVoidTy())
3501 CGF.Builder.CreateRetVoid();
3502 else
3504
3505
3506
3509 return ThunkFn;
3510}
3511
3512namespace {
3513class ItaniumRTTIBuilder {
3514 CodeGenModule &CGM;
3515 llvm::LLVMContext &VMContext;
3516 const ItaniumCXXABI &CXXABI;
3517
3518
3519 SmallVector<llvm::Constant *, 16> Fields;
3520
3521
3522 llvm::GlobalVariable *
3523 GetAddrOfTypeName(QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage);
3524
3525
3526
3527 llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty);
3528
3529
3530 void BuildVTablePointer(const Type *Ty, llvm::Constant *StorageAddress);
3531
3532
3533
3534 void BuildSIClassTypeInfo(const CXXRecordDecl *RD);
3535
3536
3537
3538
3539 void BuildVMIClassTypeInfo(const CXXRecordDecl *RD);
3540
3541
3542
3543 void BuildPointerTypeInfo(QualType PointeeTy);
3544
3545
3546
3547 void BuildObjCObjectTypeInfo(const ObjCObjectType *Ty);
3548
3549
3550
3551 void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty);
3552
3553public:
3554 ItaniumRTTIBuilder(const ItaniumCXXABI &ABI)
3555 : CGM(ABI.CGM), VMContext(CGM.getModule().getContext()), CXXABI(ABI) {}
3556
3557
3558 enum {
3559
3560 PTI_Const = 0x1,
3561
3562
3563 PTI_Volatile = 0x2,
3564
3565
3566 PTI_Restrict = 0x4,
3567
3568
3569 PTI_Incomplete = 0x8,
3570
3571
3572
3573 PTI_ContainingClassIncomplete = 0x10,
3574
3575
3576
3577
3578
3579 PTI_Noexcept = 0x40,
3580 };
3581
3582
3583 enum {
3584
3585 VMI_NonDiamondRepeat = 0x1,
3586
3587
3588 VMI_DiamondShaped = 0x2
3589 };
3590
3591
3592 enum {
3593
3594 BCTI_Virtual = 0x1,
3595
3596
3597 BCTI_Public = 0x2
3598 };
3599
3600
3601
3602 llvm::Constant *BuildTypeInfo(QualType Ty);
3603
3604
3605 llvm::Constant *BuildTypeInfo(
3606 QualType Ty,
3607 llvm::GlobalVariable::LinkageTypes Linkage,
3608 llvm::GlobalValue::VisibilityTypes Visibility,
3609 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass);
3610};
3611}
3612
3613llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName(
3614 QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage) {
3615 SmallString<256> Name;
3616 llvm::raw_svector_ostream Out(Name);
3618
3619
3620
3621
3622 llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext,
3623 Name.substr(4));
3625
3628
3629 GV->setInitializer(Init);
3630
3631 return GV;
3632}
3633
3634llvm::Constant *
3635ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
3636
3637 SmallString<256> Name;
3638 llvm::raw_svector_ostream Out(Name);
3640
3641
3642 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name);
3643
3644 if (!GV) {
3645
3646
3647
3648
3649 GV = new llvm::GlobalVariable(
3651 true, llvm::GlobalValue::ExternalLinkage, nullptr, Name);
3654
3655
3658 GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
3660 }
3661 }
3662 }
3663
3664 return GV;
3665}
3666
3667
3668
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684 switch (Ty->getKind()) {
3685 case BuiltinType::Void:
3686 case BuiltinType::NullPtr:
3687 case BuiltinType::Bool:
3688 case BuiltinType::WChar_S:
3689 case BuiltinType::WChar_U:
3690 case BuiltinType::Char_U:
3691 case BuiltinType::Char_S:
3692 case BuiltinType::UChar:
3693 case BuiltinType::SChar:
3694 case BuiltinType::Short:
3695 case BuiltinType::UShort:
3696 case BuiltinType::Int:
3697 case BuiltinType::UInt:
3698 case BuiltinType::Long:
3699 case BuiltinType::ULong:
3700 case BuiltinType::LongLong:
3701 case BuiltinType::ULongLong:
3702 case BuiltinType::Half:
3703 case BuiltinType::Float:
3704 case BuiltinType::Double:
3705 case BuiltinType::LongDouble:
3706 case BuiltinType::Float16:
3707 case BuiltinType::Float128:
3708 case BuiltinType::Ibm128:
3709 case BuiltinType::Char8:
3710 case BuiltinType::Char16:
3711 case BuiltinType::Char32:
3712 case BuiltinType::Int128:
3713 case BuiltinType::UInt128:
3714 return true;
3715
3716#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
3717 case BuiltinType::Id:
3718#include "clang/Basic/OpenCLImageTypes.def"
3719#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
3720 case BuiltinType::Id:
3721#include "clang/Basic/OpenCLExtensionTypes.def"
3722 case BuiltinType::OCLSampler:
3723 case BuiltinType::OCLEvent:
3724 case BuiltinType::OCLClkEvent:
3725 case BuiltinType::OCLQueue:
3726 case BuiltinType::OCLReserveID:
3727#define SVE_TYPE(Name, Id, SingletonId) \
3728 case BuiltinType::Id:
3729#include "clang/Basic/AArch64ACLETypes.def"
3730#define PPC_VECTOR_TYPE(Name, Id, Size) \
3731 case BuiltinType::Id:
3732#include "clang/Basic/PPCTypes.def"
3733#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
3734#include "clang/Basic/RISCVVTypes.def"
3735#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
3736#include "clang/Basic/WebAssemblyReferenceTypes.def"
3737#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:
3738#include "clang/Basic/AMDGPUTypes.def"
3739#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
3740#include "clang/Basic/HLSLIntangibleTypes.def"
3741 case BuiltinType::ShortAccum:
3742 case BuiltinType::Accum:
3743 case BuiltinType::LongAccum:
3744 case BuiltinType::UShortAccum:
3745 case BuiltinType::UAccum:
3746 case BuiltinType::ULongAccum:
3747 case BuiltinType::ShortFract:
3748 case BuiltinType::Fract:
3749 case BuiltinType::LongFract:
3750 case BuiltinType::UShortFract:
3751 case BuiltinType::UFract:
3752 case BuiltinType::ULongFract:
3753 case BuiltinType::SatShortAccum:
3754 case BuiltinType::SatAccum:
3755 case BuiltinType::SatLongAccum:
3756 case BuiltinType::SatUShortAccum:
3757 case BuiltinType::SatUAccum:
3758 case BuiltinType::SatULongAccum:
3759 case BuiltinType::SatShortFract:
3760 case BuiltinType::SatFract:
3761 case BuiltinType::SatLongFract:
3762 case BuiltinType::SatUShortFract:
3763 case BuiltinType::SatUFract:
3764 case BuiltinType::SatULongFract:
3765 case BuiltinType::BFloat16:
3766 return false;
3767
3768 case BuiltinType::Dependent:
3769#define BUILTIN_TYPE(Id, SingletonId)
3770#define PLACEHOLDER_TYPE(Id, SingletonId) \
3771 case BuiltinType::Id:
3772#include "clang/AST/BuiltinTypes.def"
3773 llvm_unreachable("asking for RRTI for a placeholder type!");
3774
3775 case BuiltinType::ObjCId:
3776 case BuiltinType::ObjCClass:
3777 case BuiltinType::ObjCSel:
3778 llvm_unreachable("FIXME: Objective-C types are unsupported!");
3779 }
3780
3781 llvm_unreachable("Invalid BuiltinType Kind!");
3782}
3783
3786 const BuiltinType *BuiltinTy = dyn_cast(PointeeTy);
3787 if (!BuiltinTy)
3788 return false;
3789
3790
3793
3794 if (!Quals.empty())
3795 return false;
3796
3798}
3799
3800
3801
3803
3804 if (const BuiltinType *BuiltinTy = dyn_cast(Ty))
3806
3807
3808
3809 if (const PointerType *PointerTy = dyn_cast(Ty))
3811
3812 return false;
3813}
3814
3815
3816
3817
3818
3822
3823
3824
3825 if (!Context.getLangOpts().RTTI) return false;
3826
3827 if (const RecordType *RecordTy = dyn_cast(Ty)) {
3831 return false;
3832
3834 return false;
3835
3836
3837
3838
3839
3840 bool IsDLLImport = RD->hasAttr();
3841
3842
3843 if (CGM.getTriple().isOSCygMing())
3844 return false;
3845
3848 return true;
3849
3850 return IsDLLImport && !CGM.getTriple().isWindowsItaniumEnvironment()
3852 : true;
3853 }
3854 if (IsDLLImport)
3855 return true;
3856 }
3857
3858 return false;
3859}
3860
3861
3863 return !RecordTy->getDecl()->getDefinitionOrSelf()->isCompleteDefinition();
3864}
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3878 if (const RecordType *RecordTy = dyn_cast(Ty)) {
3880 return true;
3881 }
3882
3883 if (const PointerType *PointerTy = dyn_cast(Ty))
3885
3887 dyn_cast(Ty)) {
3888
3889 if (!MemberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition())
3890 return true;
3891
3893 }
3894
3895 return false;
3896}
3897
3898
3899
3900
3902
3904 return false;
3905
3906
3908
3909
3910 if (Base->isVirtual())
3911 return false;
3912
3913
3915 return false;
3916
3917
3918 auto *BaseDecl = Base->getType()->castAsCXXRecordDecl();
3919 if (!BaseDecl->isEmpty() &&
3921 return false;
3922
3923 return true;
3924}
3925
3926void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty,
3927 llvm::Constant *StorageAddress) {
3928
3929 static const char * const ClassTypeInfo =
3930 "_ZTVN10__cxxabiv117__class_type_infoE";
3931
3932 static const char * const SIClassTypeInfo =
3933 "_ZTVN10__cxxabiv120__si_class_type_infoE";
3934
3935 static const char * const VMIClassTypeInfo =
3936 "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
3937
3938 const char *VTableName = nullptr;
3939
3941#define TYPE(Class, Base)
3942#define ABSTRACT_TYPE(Class, Base)
3943#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
3944#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
3945#define DEPENDENT_TYPE(Class, Base) case Type::Class:
3946#include "clang/AST/TypeNodes.inc"
3947 llvm_unreachable("Non-canonical and dependent types shouldn't get here");
3948
3949 case Type::LValueReference:
3950 case Type::RValueReference:
3951 llvm_unreachable("References shouldn't get here");
3952
3953 case Type::Auto:
3954 case Type::DeducedTemplateSpecialization:
3955 llvm_unreachable("Undeduced type shouldn't get here");
3956
3957 case Type::Pipe:
3958 llvm_unreachable("Pipe types shouldn't get here");
3959
3960 case Type::ArrayParameter:
3961 llvm_unreachable("Array Parameter types should not get here.");
3962
3963 case Type::Builtin:
3964 case Type::BitInt:
3965
3966 case Type::Vector:
3967 case Type::ExtVector:
3968 case Type::ConstantMatrix:
3969 case Type::Complex:
3970 case Type::Atomic:
3971
3972 case Type::BlockPointer:
3973
3974 VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE";
3975 break;
3976
3977 case Type::ConstantArray:
3978 case Type::IncompleteArray:
3979 case Type::VariableArray:
3980
3981 VTableName = "_ZTVN10__cxxabiv117__array_type_infoE";
3982 break;
3983
3984 case Type::FunctionNoProto:
3985 case Type::FunctionProto:
3986
3987 VTableName = "_ZTVN10__cxxabiv120__function_type_infoE";
3988 break;
3989
3990 case Type::Enum:
3991
3992 VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE";
3993 break;
3994
3995 case Type::Record: {
3997 ->getDefinitionOrSelf();
3998
4000 VTableName = ClassTypeInfo;
4002 VTableName = SIClassTypeInfo;
4003 } else {
4004 VTableName = VMIClassTypeInfo;
4005 }
4006
4007 break;
4008 }
4009
4010 case Type::ObjCObject:
4011
4013
4014
4016 VTableName = ClassTypeInfo;
4017 break;
4018 }
4019
4021 [[fallthrough]];
4022
4023 case Type::ObjCInterface:
4025 VTableName = SIClassTypeInfo;
4026 } else {
4027 VTableName = ClassTypeInfo;
4028 }
4029 break;
4030
4031 case Type::ObjCObjectPointer:
4032 case Type::Pointer:
4033
4034 VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE";
4035 break;
4036
4037 case Type::MemberPointer:
4038
4039 VTableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";
4040 break;
4041
4042 case Type::HLSLAttributedResource:
4043 case Type::HLSLInlineSpirv:
4044 llvm_unreachable("HLSL doesn't support virtual functions");
4045 }
4046
4047 llvm::Constant *VTable = nullptr;
4048
4049
4051 VTable = CGM.getModule().getNamedAlias(VTableName);
4052 if (!VTable) {
4053 llvm::Type *Ty = llvm::ArrayType::get(CGM.GlobalsInt8PtrTy, 0);
4054 VTable = CGM.getModule().getOrInsertGlobal(VTableName, Ty);
4055 }
4056
4058
4059 llvm::Type *PtrDiffTy =
4061
4062
4064
4065
4066 llvm::Constant *Eight = llvm::ConstantInt::get(CGM.Int32Ty, 8);
4067 VTable =
4068 llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.Int8Ty, VTable, Eight);
4069 } else {
4070 llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
4071 VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.GlobalsInt8PtrTy,
4072 VTable, Two);
4073 }
4074
4075 if (const auto &Schema =
4078 VTable, Schema,
4079 Schema.isAddressDiscriminated() ? StorageAddress : nullptr,
4080 GlobalDecl(), QualType(Ty, 0));
4081
4082 Fields.push_back(VTable);
4083}
4084
4085
4086
4089
4090
4091
4092
4093
4094
4095
4096
4097
4099 return llvm::GlobalValue::InternalLinkage;
4100
4103 llvm_unreachable("Linkage hasn't been computed!");
4104
4108 return llvm::GlobalValue::InternalLinkage;
4109
4113
4114
4116 return llvm::GlobalValue::LinkOnceODRLinkage;
4117
4118 if (const RecordType *Record = dyn_cast(Ty)) {
4119 const auto *RD =
4121 if (RD->hasAttr())
4122 return llvm::GlobalValue::WeakODRLinkage;
4123 if (CGM.getTriple().isWindowsItaniumEnvironment())
4124 if (RD->hasAttr() &&
4126 return llvm::GlobalValue::ExternalLinkage;
4127
4131 }
4132
4133 return llvm::GlobalValue::LinkOnceODRLinkage;
4134 }
4135
4136 llvm_unreachable("Invalid linkage!");
4137}
4138
4139llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty) {
4140
4142
4143
4144 SmallString<256> Name;
4145 llvm::raw_svector_ostream Out(Name);
4147
4148 llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);
4149 if (OldGV && !OldGV->isDeclaration()) {
4150 assert(!OldGV->hasAvailableExternallyLinkage() &&
4151 "available_externally typeinfos not yet implemented");
4152
4153 return OldGV;
4154 }
4155
4156
4159 return GetAddrOfExternalRTTIDescriptor(Ty);
4160
4161
4163
4164
4165
4166 llvm::GlobalValue::VisibilityTypes llvmVisibility;
4167 if (llvm::GlobalValue::isLocalLinkage(Linkage))
4168
4169 llvmVisibility = llvm::GlobalValue::DefaultVisibility;
4170 else if (CXXABI.classifyRTTIUniqueness(Ty, Linkage) ==
4171 ItaniumCXXABI::RUK_NonUniqueHidden)
4172 llvmVisibility = llvm::GlobalValue::HiddenVisibility;
4173 else
4175
4176 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
4177 llvm::GlobalValue::DefaultStorageClass;
4179 if ((CGM.getTriple().isWindowsItaniumEnvironment() &&
4180 RD->hasAttr()) ||
4182 !llvm::GlobalValue::isLocalLinkage(Linkage) &&
4183 llvmVisibility == llvm::GlobalValue::DefaultVisibility))
4184 DLLStorageClass = llvm::GlobalValue::DLLExportStorageClass;
4185 }
4186 return BuildTypeInfo(Ty, Linkage, llvmVisibility, DLLStorageClass);
4187}
4188
4189llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
4190 QualType Ty,
4191 llvm::GlobalVariable::LinkageTypes Linkage,
4192 llvm::GlobalValue::VisibilityTypes Visibility,
4193 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) {
4194 SmallString<256> Name;
4195 llvm::raw_svector_ostream Out(Name);
4197 llvm::Module &M = CGM.getModule();
4198 llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name);
4199
4200 llvm::GlobalVariable *GV =
4201 new llvm::GlobalVariable(M, CGM.Int8Ty, true, Linkage,
4202 nullptr, Name);
4203
4204
4205 BuildVTablePointer(cast(Ty), GV);
4206
4207
4208 llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage);
4209 llvm::Constant *TypeNameField;
4210
4211
4212
4213 ItaniumCXXABI::RTTIUniquenessKind RTTIUniqueness =
4215 if (RTTIUniqueness != ItaniumCXXABI::RUK_Unique) {
4216
4217
4218 TypeNameField = llvm::ConstantExpr::getPtrToInt(TypeName, CGM.Int64Ty);
4219 llvm::Constant *flag =
4220 llvm::ConstantInt::get(CGM.Int64Ty, ((uint64_t)1) << 63);
4221 TypeNameField = llvm::ConstantExpr::getAdd(TypeNameField, flag);
4222 TypeNameField =
4223 llvm::ConstantExpr::getIntToPtr(TypeNameField, CGM.GlobalsInt8PtrTy);
4224 } else {
4226 }
4227 Fields.push_back(TypeNameField);
4228
4230#define TYPE(Class, Base)
4231#define ABSTRACT_TYPE(Class, Base)
4232#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
4233#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
4234#define DEPENDENT_TYPE(Class, Base) case Type::Class:
4235#include "clang/AST/TypeNodes.inc"
4236 llvm_unreachable("Non-canonical and dependent types shouldn't get here");
4237
4238
4239 case Type::Builtin:
4240 case Type::Vector:
4241 case Type::ExtVector:
4242 case Type::ConstantMatrix:
4243 case Type::Complex:
4244 case Type::BlockPointer:
4245
4246
4247 break;
4248
4249 case Type::LValueReference:
4250 case Type::RValueReference:
4251 llvm_unreachable("References shouldn't get here");
4252
4253 case Type::Auto:
4254 case Type::DeducedTemplateSpecialization:
4255 llvm_unreachable("Undeduced type shouldn't get here");
4256
4257 case Type::Pipe:
4258 break;
4259
4260 case Type::BitInt:
4261 break;
4262
4263 case Type::ConstantArray:
4264 case Type::IncompleteArray:
4265 case Type::VariableArray:
4266 case Type::ArrayParameter:
4267
4268
4269 break;
4270
4271 case Type::FunctionNoProto:
4272 case Type::FunctionProto:
4273
4274
4275 break;
4276
4277 case Type::Enum:
4278
4279
4280 break;
4281
4282 case Type::Record: {
4284 ->getDefinitionOrSelf();
4286
4287 break;
4288 }
4289
4291 BuildSIClassTypeInfo(RD);
4292 else
4293 BuildVMIClassTypeInfo(RD);
4294
4295 break;
4296 }
4297
4298 case Type::ObjCObject:
4299 case Type::ObjCInterface:
4301 break;
4302
4303 case Type::ObjCObjectPointer:
4305 break;
4306
4307 case Type::Pointer:
4309 break;
4310
4311 case Type::MemberPointer:
4313 break;
4314
4315 case Type::Atomic:
4316
4317 break;
4318
4319 case Type::HLSLAttributedResource:
4320 case Type::HLSLInlineSpirv:
4321 llvm_unreachable("HLSL doesn't support RTTI");
4322 }
4323
4324 GV->replaceInitializer(llvm::ConstantStruct::getAnon(Fields));
4325
4326
4327 auto GVDLLStorageClass = DLLStorageClass;
4329 GVDLLStorageClass != llvm::GlobalVariable::DLLExportStorageClass) {
4330 if (const RecordType *RecordTy = dyn_cast(Ty)) {
4331 const auto *RD =
4333 if (RD->hasAttr() ||
4335 GVDLLStorageClass = llvm::GlobalVariable::DLLExportStorageClass;
4336 }
4337 }
4338
4339
4340 if (OldGV) {
4341 GV->takeName(OldGV);
4342 OldGV->replaceAllUsesWith(GV);
4343 OldGV->eraseFromParent();
4344 }
4345
4347 GV->setComdat(M.getOrInsertComdat(GV->getName()));
4348
4351 GV->setAlignment(Align.getAsAlign());
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4370
4373
4374 TypeName->setDLLStorageClass(DLLStorageClass);
4375 GV->setDLLStorageClass(GVDLLStorageClass);
4376
4379
4380 return GV;
4381}
4382
4383
4384
4385void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {
4386
4387 const Type *T = OT->getBaseType().getTypePtr();
4389
4390
4391
4393
4395 ObjCInterfaceDecl *Super = Class->getSuperClass();
4396
4397
4398 if (!Super) return;
4399
4401
4402
4403 llvm::Constant *BaseTypeInfo =
4404 ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(SuperTy);
4405 Fields.push_back(BaseTypeInfo);
4406}
4407
4408
4409
4410void ItaniumRTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
4411
4412
4413
4414 llvm::Constant *BaseTypeInfo =
4416 Fields.push_back(BaseTypeInfo);
4417}
4418
4419namespace {
4420
4421
4422 struct SeenBases {
4423 llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases;
4424 llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases;
4425 };
4426}
4427
4428
4429
4430
4432 SeenBases &Bases) {
4433
4434 unsigned Flags = 0;
4435
4436 auto *BaseDecl = Base->getType()->castAsCXXRecordDecl();
4437 if (Base->isVirtual()) {
4438
4439 if (!Bases.VirtualBases.insert(BaseDecl).second) {
4440
4441
4442 Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped;
4443 } else {
4444 if (Bases.NonVirtualBases.count(BaseDecl))
4445 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
4446 }
4447 } else {
4448
4449 if (!Bases.NonVirtualBases.insert(BaseDecl).second) {
4450
4451
4452 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
4453 } else {
4454 if (Bases.VirtualBases.count(BaseDecl))
4455 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
4456 }
4457 }
4458
4459
4460 for (const auto &I : BaseDecl->bases())
4462
4463 return Flags;
4464}
4465
4467 unsigned Flags = 0;
4468 SeenBases Bases;
4469
4470
4471 for (const auto &I : RD->bases())
4473
4474 return Flags;
4475}
4476
4477
4478
4479
4480void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
4481 llvm::Type *UnsignedIntLTy =
4483
4484
4485
4486
4487
4489 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4490
4491
4492
4493
4494 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->getNumBases()));
4495
4497 return;
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4524 if (TI.getTriple().isOSCygMing() &&
4527 llvm::Type *OffsetFlagsLTy =
4529
4530 for (const auto &Base : RD->bases()) {
4531
4532 Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(Base.getType()));
4533
4534 auto *BaseDecl = Base.getType()->castAsCXXRecordDecl();
4535 int64_t OffsetFlags = 0;
4536
4537
4538
4539
4540
4541 CharUnits Offset;
4542 if (Base.isVirtual())
4543 Offset =
4545 else {
4548 };
4549
4551
4552
4553
4554 if (Base.isVirtual())
4555 OffsetFlags |= BCTI_Virtual;
4557 OffsetFlags |= BCTI_Public;
4558
4559 Fields.push_back(llvm::ConstantInt::getSigned(OffsetFlagsLTy, OffsetFlags));
4560 }
4561}
4562
4563
4564
4566 unsigned Flags = 0;
4567
4568 if (Type.isConstQualified())
4569 Flags |= ItaniumRTTIBuilder::PTI_Const;
4570 if (Type.isVolatileQualified())
4571 Flags |= ItaniumRTTIBuilder::PTI_Volatile;
4572 if (Type.isRestrictQualified())
4573 Flags |= ItaniumRTTIBuilder::PTI_Restrict;
4574 Type = Type.getUnqualifiedType();
4575
4576
4577
4578
4580 Flags |= ItaniumRTTIBuilder::PTI_Incomplete;
4581
4583 if (Proto->isNothrow()) {
4584 Flags |= ItaniumRTTIBuilder::PTI_Noexcept;
4586 }
4587 }
4588
4589 return Flags;
4590}
4591
4592
4593
4594void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
4595
4596
4597
4599
4600 llvm::Type *UnsignedIntLTy =
4602 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4603
4604
4605
4606
4607 llvm::Constant *PointeeTypeInfo =
4608 ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy);
4609 Fields.push_back(PointeeTypeInfo);
4610}
4611
4612
4613
4614void
4615ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
4617
4618
4619
4620
4622
4625 Flags |= PTI_ContainingClassIncomplete;
4626
4627 llvm::Type *UnsignedIntLTy =
4629 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4630
4631
4632
4633
4634 llvm::Constant *PointeeTypeInfo =
4635 ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy);
4636 Fields.push_back(PointeeTypeInfo);
4637
4638
4639
4640
4641
4643 Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(T));
4644}
4645
4646llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) {
4647 return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty);
4648}
4649
4650void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD) {
4651
4652 QualType FundamentalTypes[] = {
4653 getContext().VoidTy, getContext().NullPtrTy,
4654 getContext().BoolTy, getContext().WCharTy,
4655 getContext().CharTy, getContext().UnsignedCharTy,
4656 getContext().SignedCharTy, getContext().ShortTy,
4657 getContext().UnsignedShortTy, getContext().IntTy,
4658 getContext().UnsignedIntTy, getContext().LongTy,
4659 getContext().UnsignedLongTy, getContext().LongLongTy,
4660 getContext().UnsignedLongLongTy, getContext().Int128Ty,
4661 getContext().UnsignedInt128Ty, getContext().HalfTy,
4662 getContext().FloatTy, getContext().DoubleTy,
4663 getContext().LongDoubleTy, getContext().Float128Ty,
4664 getContext().Char8Ty, getContext().Char16Ty,
4665 getContext().Char32Ty
4666 };
4667 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
4669 ? llvm::GlobalValue::DLLExportStorageClass
4670 : llvm::GlobalValue::DefaultStorageClass;
4671 llvm::GlobalValue::VisibilityTypes Visibility =
4673 for (const QualType &FundamentalType : FundamentalTypes) {
4674 QualType PointerType = getContext().getPointerType(FundamentalType);
4675 QualType PointerTypeConst = getContext().getPointerType(
4676 FundamentalType.withConst());
4677 for (QualType Type : {FundamentalType, PointerType, PointerTypeConst})
4678 ItaniumRTTIBuilder(*this).BuildTypeInfo(
4679 Type, llvm::GlobalValue::ExternalLinkage,
4681 }
4682}
4683
4684
4685
4686ItaniumCXXABI::RTTIUniquenessKind ItaniumCXXABI::classifyRTTIUniqueness(
4687 QualType CanTy, llvm::GlobalValue::LinkageTypes Linkage) const {
4688 if (shouldRTTIBeUnique())
4689 return RUK_Unique;
4690
4691
4692 if (Linkage != llvm::GlobalValue::LinkOnceODRLinkage &&
4693 Linkage != llvm::GlobalValue::WeakODRLinkage)
4694 return RUK_Unique;
4695
4696
4698 return RUK_Unique;
4699
4700
4701 if (Linkage == llvm::GlobalValue::LinkOnceODRLinkage)
4702 return RUK_NonUniqueHidden;
4703
4704
4705
4706
4707 assert(Linkage == llvm::GlobalValue::WeakODRLinkage);
4708 return RUK_NonUniqueVisible;
4709}
4710
4711
4712namespace {
4713enum class StructorCodegen { Emit, RAUW, Alias, COMDAT };
4714}
4718 return StructorCodegen::Emit;
4719
4720
4721
4723 return StructorCodegen::Emit;
4724
4726 if (const auto *DD = dyn_cast(MD)) {
4728 } else {
4731 }
4733
4734 if (llvm::GlobalValue::isDiscardableIfUnused(Linkage))
4735 return StructorCodegen::RAUW;
4736
4737
4738 if (!llvm::GlobalAlias::isValidLinkage(Linkage))
4739 return StructorCodegen::RAUW;
4740
4741 if (llvm::GlobalValue::isWeakForLinker(Linkage)) {
4742
4745 return StructorCodegen::COMDAT;
4746 return StructorCodegen::Emit;
4747 }
4748
4749 return StructorCodegen::Alias;
4750}
4751
4756
4758 llvm::GlobalValue *Entry = CGM.GetGlobalValue(MangledName);
4759 if (Entry && !Entry->isDeclaration())
4760 return;
4761
4763
4764
4765 auto *Alias = llvm::GlobalAlias::create(Linkage, "", Aliasee);
4766
4767
4768 Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4769
4770
4771 if (Entry) {
4772 assert(Entry->getType() == Aliasee->getType() &&
4773 "declaration exists with different type");
4774 Alias->takeName(Entry);
4775 Entry->replaceAllUsesWith(Alias);
4776 Entry->eraseFromParent();
4777 } else {
4778 Alias->setName(MangledName);
4779 }
4780
4781
4783}
4784
4785void ItaniumCXXABI::emitCXXStructor(GlobalDecl GD) {
4787 auto *CD = dyn_cast(MD);
4789
4791
4794 GlobalDecl BaseDecl;
4795 if (CD)
4797 else
4799
4800 if (CGType == StructorCodegen::Alias || CGType == StructorCodegen::COMDAT) {
4802 return;
4803 }
4804
4805 if (CGType == StructorCodegen::RAUW) {
4809 return;
4810 }
4811 }
4812
4813
4814
4815
4816
4818 CGType != StructorCodegen::COMDAT &&
4820 return;
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4835
4836 if (CGType == StructorCodegen::COMDAT) {
4837 SmallString<256> Buffer;
4838 llvm::raw_svector_ostream Out(Buffer);
4839 if (DD)
4840 getMangleContext().mangleCXXDtorComdat(DD, Out);
4841 else
4842 getMangleContext().mangleCXXCtorComdat(CD, Out);
4843 llvm::Comdat *C = CGM.getModule().getOrInsertComdat(Out.str());
4845 } else {
4847 }
4848}
4849
4851
4852 llvm::FunctionType *FTy = llvm::FunctionType::get(
4854
4856}
4857
4859
4860 llvm::FunctionType *FTy =
4861 llvm::FunctionType::get(CGM.VoidTy, false);
4862
4864}
4865
4867
4868 llvm::FunctionType *FTy = llvm::FunctionType::get(
4870
4872}
4873
4874namespace {
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887 struct CallEndCatch final : EHScopeStack::Cleanup {
4888 CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {}
4889 bool MightThrow;
4890
4891 void Emit(CodeGenFunction &CGF, Flags flags) override {
4892 if (!MightThrow) {
4894 return;
4895 }
4896
4898 }
4899 };
4900}
4901
4902
4903
4904
4905
4906
4907
4909 llvm::Value *Exn,
4910 bool EndMightThrow) {
4911 llvm::CallInst *call =
4913
4914 CGF.EHStack.pushCleanup(
4916 EndMightThrow && !CGF.CGM.getLangOpts().AssumeNothrowExceptionDtor);
4917
4918 return call;
4919}
4920
4921
4922
4924 const VarDecl &CatchParam,
4927
4929
4933
4934
4935
4938 bool EndCatchMightThrow = CaughtType->isRecordType();
4939
4940
4941 llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow);
4942
4943
4944
4945
4946 if (const PointerType *PT = dyn_cast(CaughtType)) {
4948
4949
4950
4952
4953
4954
4955 unsigned HeaderSize =
4957 AdjustedExn =
4958 CGF.Builder.CreateConstGEP1_32(CGF.Int8Ty, Exn, HeaderSize);
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974 } else {
4975
4977
4978
4981 llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
4983
4984
4986 }
4987 }
4988
4989 llvm::Value *ExnCast =
4990 CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref");
4992 return;
4993 }
4994
4995
4998 llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false);
4999
5000
5001
5002 if (CatchType->hasPointerRepresentation()) {
5003 llvm::Value *CastExn =
5004 CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted");
5005
5009 [[fallthrough]];
5010
5015 return;
5016
5019 return;
5020 }
5021 llvm_unreachable("bad ownership qualifier!");
5022 }
5023
5024
5025
5027 LValue destLV = CGF.MakeAddrLValue(ParamAddr, CatchType);
5028 switch (TEK) {
5031 true);
5032 return;
5036 return;
5037 }
5039 llvm_unreachable("evaluation kind filtered out!");
5040 }
5041 llvm_unreachable("bad evaluation kind");
5042 }
5043
5044 assert(isa(CatchType) && "unexpected catch type!");
5045 auto catchRD = CatchType->getAsCXXRecordDecl();
5047
5049
5050
5051
5052 const Expr *copyExpr = CatchParam.getInit();
5053 if (!copyExpr) {
5054 llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true);
5055 Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy),
5056 LLVMCatchTy, caughtExnAlignment);
5057 LValue Dest = CGF.MakeAddrLValue(ParamAddr, CatchType);
5058 LValue Src = CGF.MakeAddrLValue(adjustedExn, CatchType);
5060 return;
5061 }
5062
5063
5064
5065 llvm::CallInst *rawAdjustedExn =
5067
5068
5069 Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy),
5070 LLVMCatchTy, caughtExnAlignment);
5071
5072
5073
5077
5078
5080
5081
5088
5089
5091
5092
5093 opaque.pop();
5094
5095
5097}
5098
5099
5100
5101void ItaniumCXXABI::emitBeginCatch(CodeGenFunction &CGF,
5102 const CXXCatchStmt *S) {
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5127 if (!CatchParam) {
5130 return;
5131 }
5132
5133
5135 {
5139 }
5141}
5142
5143
5144
5145
5149 C.VoidTy, {C.getPointerType(C.CharTy)});
5152 fnTy, "__clang_call_terminate", llvm::AttributeList(), true);
5153 llvm::Function *fn =
5155 if (fn->empty()) {
5158 fn->setDoesNotThrow();
5159 fn->setDoesNotReturn();
5160
5161
5162
5163
5164 fn->addFnAttr(llvm::Attribute::NoInline);
5165
5166
5167
5168 fn->setLinkage(llvm::Function::LinkOnceODRLinkage);
5169 fn->setVisibility(llvm::Function::HiddenVisibility);
5171 fn->setComdat(CGM.getModule().getOrInsertComdat(fn->getName()));
5172
5173
5174 llvm::BasicBlock *entry =
5175 llvm::BasicBlock::Create(CGM.getLLVMContext(), "", fn);
5177
5178
5179 llvm::Value *exn = &*fn->arg_begin();
5180
5181
5182 llvm::CallInst *catchCall = builder.CreateCall(getBeginCatchFn(CGM), exn);
5183 catchCall->setDoesNotThrow();
5184 catchCall->setCallingConv(CGM.getRuntimeCC());
5185
5186
5187 llvm::CallInst *termCall = builder.CreateCall(CGM.getTerminateFn());
5188 termCall->setDoesNotThrow();
5189 termCall->setDoesNotReturn();
5190 termCall->setCallingConv(CGM.getRuntimeCC());
5191
5192
5193 builder.CreateUnreachable();
5194 }
5195 return fnRef;
5196}
5197
5198llvm::CallInst *
5199ItaniumCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
5200 llvm::Value *Exn) {
5201
5202 if (Exn) {
5205 }
5207}
5208
5209std::pair<llvm::Value *, const CXXRecordDecl *>
5210ItaniumCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This,
5211 const CXXRecordDecl *RD) {
5213}
5214
5215llvm::Constant *
5216ItaniumCXXABI::getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD) {
5217 const CXXMethodDecl *origMD =
5221 llvm::Constant *thunk = getOrCreateVirtualFunctionPointerThunk(origMD);
5223 MD->getType(), std::nullopt, MD->getParent());
5225}
5226
5227void WebAssemblyCXXABI::emitBeginCatch(CodeGenFunction &CGF,
5228 const CXXCatchStmt *C) {
5230 CGF.EHStack.pushCleanup(
5232 ItaniumCXXABI::emitBeginCatch(CGF, C);
5233}
5234
5235llvm::CallInst *
5236WebAssemblyCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
5237 llvm::Value *Exn) {
5238
5239
5240
5241
5242
5243
5244
5248 }
5250}
5251
5252
5253void XLCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
5254 llvm::FunctionCallee Dtor,
5255 llvm::Constant *Addr) {
5257 llvm::PointerType *PtrTy = CGF.DefaultPtrTy;
5258
5259
5260 llvm::FunctionType *AtExitTy =
5261 llvm::FunctionType::get(CGM.IntTy, {CGM.IntTy, PtrTy}, true);
5262
5263
5264 llvm::FunctionCallee AtExit =
5266
5267
5269
5270
5271
5272 llvm::Value *NV = llvm::Constant::getNullValue(CGM.IntTy);
5274
5275
5276 return;
5277 }
5278
5279
5280 llvm::Function *DtorStub =
5282
5283
5285
5286
5287
5288 emitCXXStermFinalizer(D, DtorStub, Addr);
5289}
5290
5291void XLCXXABI::emitCXXStermFinalizer(const VarDecl &D, llvm::Function *dtorStub,
5292 llvm::Constant *addr) {
5293 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
5294 SmallString<256> FnName;
5295 {
5296 llvm::raw_svector_ostream Out(FnName);
5297 getMangleContext().mangleDynamicStermFinalizer(&D, Out);
5298 }
5299
5300
5303 FTy, FnName.str(), FI, D.getLocation());
5304
5305 CodeGenFunction CGF(CGM);
5306
5310
5311
5312
5313
5314
5316
5318
5319 llvm::BasicBlock *DestructCallBlock = CGF.createBasicBlock("destruct.call");
5320 llvm::BasicBlock *EndBlock = CGF.createBasicBlock("destruct.end");
5321
5322
5323
5324 CGF.Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock);
5325
5326 CGF.EmitBlock(DestructCallBlock);
5327
5328
5329 llvm::CallInst *CI = CGF.Builder.CreateCall(dtorStub);
5330
5331
5332 CI->setCallingConv(dtorStub->getCallingConv());
5333
5335
5337
5338 if (auto *IPA = D.getAttr()) {
5340 IPA->getPriority());
5343
5344
5345
5346
5348 } else {
5350 }
5351}
static void emitConstructorDestructorAlias(CIRGenModule &cgm, GlobalDecl aliasDecl, GlobalDecl targetDecl)
static CharUnits computeOffsetHint(ASTContext &astContext, const CXXRecordDecl *src, const CXXRecordDecl *dst)
static Address emitDynamicCastToVoid(CIRGenFunction &cgf, mlir::Location loc, QualType srcRecordTy, Address src)
static cir::GlobalLinkageKind getTypeInfoLinkage(CIRGenModule &cgm, QualType ty)
Return the linkage that the type info and type info name constants should have for the given type.
static mlir::Value emitExactDynamicCast(CIRGenItaniumCXXABI &abi, CIRGenFunction &cgf, mlir::Location loc, QualType srcRecordTy, QualType destRecordTy, cir::PointerType destCIRTy, bool isRefCast, Address src)
static cir::FuncOp getItaniumDynamicCastFn(CIRGenFunction &cgf)
static cir::FuncOp getBadCastFn(CIRGenFunction &cgf)
static StructorCodegen getCodegenToUse(CodeGenModule &CGM, const CXXMethodDecl *MD)
Definition ItaniumCXXABI.cpp:4715
static llvm::FunctionCallee getClangCallTerminateFn(CodeGenModule &CGM)
Get or define the following function: void @__clang_call_terminate(i8* exn) nounwind noreturn This co...
Definition ItaniumCXXABI.cpp:5146
static bool CXXRecordNonInlineHasAttr(const CXXRecordDecl *RD)
Definition ItaniumCXXABI.cpp:2047
static unsigned extractPBaseFlags(ASTContext &Ctx, QualType &Type)
Compute the flags for a __pbase_type_info, and remove the corresponding pieces from Type.
Definition ItaniumCXXABI.cpp:4565
static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, QualType Ty)
ShouldUseExternalRTTIDescriptor - Returns whether the type information for the given type exists some...
Definition ItaniumCXXABI.cpp:3819
static bool IsIncompleteClassType(const RecordType *RecordTy)
IsIncompleteClassType - Returns whether the given record type is incomplete.
Definition ItaniumCXXABI.cpp:3862
static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base, SeenBases &Bases)
ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in abi::__vmi_class_type_info.
Definition ItaniumCXXABI.cpp:4431
static llvm::FunctionCallee getBadTypeidFn(CodeGenFunction &CGF)
Definition ItaniumCXXABI.cpp:1600
static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF, llvm::FunctionCallee dtor, llvm::Constant *addr, bool TLS)
Register a global destructor using __cxa_atexit.
Definition ItaniumCXXABI.cpp:2919
static llvm::FunctionCallee getBeginCatchFn(CodeGenModule &CGM)
Definition ItaniumCXXABI.cpp:4850
static llvm::Constant * pointerAuthResignMemberFunctionPointer(llvm::Constant *Src, QualType DestType, QualType SrcType, CodeGenModule &CGM)
Definition ItaniumCXXABI.cpp:1049
static llvm::FunctionCallee getGuardReleaseFn(CodeGenModule &CGM, llvm::PointerType *GuardPtrTy)
Definition ItaniumCXXABI.cpp:2663
static llvm::Value * performTypeAdjustment(CodeGenFunction &CGF, Address InitialPtr, const CXXRecordDecl *UnadjustedClass, int64_t NonVirtualAdjustment, int64_t VirtualAdjustment, bool IsReturnAdjustment)
Definition ItaniumCXXABI.cpp:2432
static llvm::Function * createGlobalInitOrCleanupFn(CodeGen::CodeGenModule &CGM, StringRef FnName)
Definition ItaniumCXXABI.cpp:2976
static llvm::FunctionCallee getAllocateExceptionFn(CodeGenModule &CGM)
Definition ItaniumCXXABI.cpp:1456
static bool IsStandardLibraryRTTIDescriptor(QualType Ty)
IsStandardLibraryRTTIDescriptor - Returns whether the type information for the given type exists in t...
Definition ItaniumCXXABI.cpp:3802
static llvm::Value * CallBeginCatch(CodeGenFunction &CGF, llvm::Value *Exn, bool EndMightThrow)
Emits a call to __cxa_begin_catch and enters a cleanup to call __cxa_end_catch.
Definition ItaniumCXXABI.cpp:4908
static llvm::FunctionCallee getGuardAbortFn(CodeGenModule &CGM, llvm::PointerType *GuardPtrTy)
Definition ItaniumCXXABI.cpp:2675
static bool isThreadWrapperReplaceable(const VarDecl *VD, CodeGen::CodeGenModule &CGM)
Definition ItaniumCXXABI.cpp:3119
static void InitCatchParam(CodeGenFunction &CGF, const VarDecl &CatchParam, Address ParamAddr, SourceLocation Loc)
A "special initializer" callback for initializing a catch parameter during catch initialization.
Definition ItaniumCXXABI.cpp:4923
static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty)
TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type info for that type is de...
Definition ItaniumCXXABI.cpp:3669
static bool CanUseSingleInheritance(const CXXRecordDecl *RD)
Definition ItaniumCXXABI.cpp:3901
static llvm::FunctionCallee getEndCatchFn(CodeGenModule &CGM)
Definition ItaniumCXXABI.cpp:4858
static llvm::GlobalValue::LinkageTypes getThreadLocalWrapperLinkage(const VarDecl *VD, CodeGen::CodeGenModule &CGM)
Get the appropriate linkage for the wrapper function.
Definition ItaniumCXXABI.cpp:3132
static llvm::FunctionCallee getThrowFn(CodeGenModule &CGM)
Definition ItaniumCXXABI.cpp:1465
static void setVTableSelectiveDLLImportExport(CodeGenModule &CGM, llvm::GlobalVariable *VTable, const CXXRecordDecl *RD)
Definition ItaniumCXXABI.cpp:2061
static llvm::FunctionCallee getGuardAcquireFn(CodeGenModule &CGM, llvm::PointerType *GuardPtrTy)
Definition ItaniumCXXABI.cpp:2650
static bool ContainsIncompleteClassType(QualType Ty)
ContainsIncompleteClassType - Returns whether the given type contains an incomplete class type.
Definition ItaniumCXXABI.cpp:3877
static llvm::Constant * pointerAuthResignConstant(llvm::Value *Ptr, const CGPointerAuthInfo &CurAuthInfo, const CGPointerAuthInfo &NewAuthInfo, CodeGenModule &CGM)
Definition ItaniumCXXABI.cpp:909
static llvm::FunctionCallee getGetExceptionPtrFn(CodeGenModule &CGM)
Definition ItaniumCXXABI.cpp:4866
static void dtorTy(Block *, std::byte *Ptr, const Descriptor *)
llvm::MachO::Record Record
static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD)
static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D)
Determine what kind of template specialization the given declaration is.
static QualType getPointeeType(const MemRegion *R)
#define CXXABI(Name, Str)
C Language Family Type Representation.
a trap message and trap category.
const ValueDecl * getMemberPointerDecl() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceDecl *PrevDecl=nullptr) const
getObjCInterfaceType - Return the unique reference to the type for the specified ObjC interface decl.
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getFunctionTypeWithExceptionSpec(QualType Orig, const FunctionProtoType::ExceptionSpecInfo &ESI) const
Get a function type and produce the equivalent function type with the specified exception specificati...
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.
CharUnits getExnObjectAlignment() const
Return the alignment (in bytes) of the thrown exception object.
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
CharUnits getPreferredTypeAlignInChars(QualType T) const
Return the PreferredAlignment of a (complete) type T, in characters.
CanQualType UnsignedIntTy
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
QualType getMemberPointerType(QualType T, NestedNameSpecifier Qualifier, const CXXRecordDecl *Cls) const
Return the uniqued reference to the type for a member pointer to the specified type in the specified ...
const TargetInfo & getTargetInfo() const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
TargetCXXABI::Kind getCXXABIKind() const
Return the C++ ABI kind that should be used.
QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const
Return the uniqued reference to the type for an address space qualified type with the specified type ...
CanQualType getCanonicalTagType(const TagDecl *TD) const
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
This class is used for builtin types like 'int'.
Represents a path from a specific derived class (which is not represented as part of the path) to a p...
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
Represents a base class of a C++ class.
QualType getType() const
Retrieves the type of the base class.
SourceLocation getBeginLoc() const LLVM_READONLY
VarDecl * getExceptionDecl() const
FunctionDecl * getOperatorDelete() const
bool isGlobalDelete() const
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
CXXMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Represents a C++ struct/union/class.
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
unsigned getNumBases() const
Retrieves the number of base classes of this class.
base_class_iterator bases_begin()
const CXXBaseSpecifier * base_class_const_iterator
Iterator that traverses the base classes of a class.
base_class_range vbases()
bool isAbstract() const
Determine whether this class has a pure virtual function.
bool isDynamicClass() const
bool hasDefinition() const
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
const Expr * getSubExpr() const
static CanQual< Type > CreateUnsafe(QualType Other)
Qualifiers getQualifiers() const
Retrieve all qualifiers.
CastKind getCastKind() const
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
One - Construct a CharUnits quantity of one.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
PointerAuthOptions PointerAuth
Configuration for pointer-signing.
std::string SymbolPartition
The name of the partition that symbols are assigned to, specified with -fsymbol-partition (see https:...
static ABIArgInfo getIndirect(CharUnits Alignment, unsigned AddrSpace, bool ByVal=true, bool Realign=false, llvm::Type *Padding=nullptr)
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
unsigned getAddressSpace() const
Return the address space that this address resides in.
llvm::PointerType * getType() const
Return the type of the pointer value.
static AggValueSlot forAddr(Address addr, Qualifiers quals, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)
forAddr - Make a slot for an aggregate value.
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)
Apply TemporaryLocation if it is valid.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name="")
Given a pointer to i8, adjust it by a given constant offset.
llvm::Value * CreateIsNull(Address Addr, const Twine &Name="")
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::LoadInst * CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, CharUnits Align, const llvm::Twine &Name="")
Address CreateConstInBoundsGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = T* ... produce name = getelementptr inbounds addr, i64 index where i64 is actually the t...
Address CreateInBoundsGEP(Address Addr, ArrayRef< llvm::Value * > IdxList, llvm::Type *ElementType, CharUnits Align, const Twine &Name="")
Implements C++ ABI-specific code generation functions.
virtual llvm::CallInst * emitTerminateForUnexpectedException(CodeGenFunction &CGF, llvm::Value *Exn)
MangleContext & getMangleContext()
Gets the mangle context.
All available information about a concrete callee.
static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr, llvm::FunctionType *FTy)
static CGCallee forDirect(llvm::Constant *functionPtr, const CGCalleeInfo &abstractInfo=CGCalleeInfo())
CGFunctionInfo - Class to encapsulate the information about a function definition.
ABIArgInfo & getReturnInfo()
CanQualType getReturnType() const
llvm::Value * getDiscriminator() const
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
llvm::Value * GetVTablePtr(Address This, llvm::Type *VTableTy, const CXXRecordDecl *VTableClass, VTableAuthMode AuthMode=VTableAuthMode::Authenticate)
GetVTablePtr - Return the Value of the vtable pointer member pointed to by This.
GlobalDecl CurGD
CurGD - The GlobalDecl for the current function being compiled.
llvm::Constant * createAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor, llvm::Constant *Addr)
Create a stub function, suitable for being passed to atexit, which passes the given address to the gi...
llvm::Function * createTLSAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor, llvm::Constant *Addr, llvm::FunctionCallee &AtExit)
Create a stub function, suitable for being passed to __pt_atexit_np, which passes the given address t...
SanitizerSet SanOpts
Sanitizers enabled for this function.
void EmitARCInitWeak(Address addr, llvm::Value *value)
i8* @objc_initWeak(i8** addr, i8* value) Returns value.
llvm::Value * getExceptionFromSlot()
Returns the contents of the function's exception object and selector slots.
llvm::Type * ConvertType(QualType T)
void EmitNoreturnRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value * > args)
Emits a call or invoke to the given noreturn runtime function.
llvm::CallBase * EmitRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value * > args, const Twine &name="")
Emits a call or invoke instruction to the given runtime function.
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc)
EmitLoadOfComplex - Load a complex number from the specified l-value.
bool CurFuncIsThunk
In C++, whether we are code generating a thunk.
void registerGlobalDtorWithAtExit(const VarDecl &D, llvm::FunctionCallee fn, llvm::Constant *addr)
Call atexit() with a function that passes the given argument to the given function.
llvm::Constant * EmitCheckSourceLocation(SourceLocation Loc)
Emit a description of a source location in a format suitable for passing to a runtime sanitizer handl...
llvm::Value * getAsNaturalPointerTo(Address Addr, QualType PointeeType)
void EmitDelegateCallArg(CallArgList &args, const VarDecl *param, SourceLocation loc)
EmitDelegateCallArg - We are performing a delegate call; that is, the current function is delegating ...
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
const LangOptions & getLangOpts() const
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type, bool ForVirtualBase, bool Delegating, Address This, QualType ThisTy)
void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::GlobalVariable *GV, bool PerformInit)
EmitCXXGlobalVarDeclInit - Create the initializer for a C++ variable with global storage.
void pushCallObjectDeleteCleanup(const FunctionDecl *OperatorDelete, llvm::Value *CompletePtr, QualType ElementType)
llvm::Constant * EmitCheckTypeDescriptor(QualType T)
Emit a description of a type in a format suitable for passing to a runtime sanitizer handler.
void EmitAnyExprToExn(const Expr *E, Address Addr)
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
const TargetInfo & getTarget() const
CGCallee BuildAppleKextVirtualDestructorCall(const CXXDestructorDecl *DD, CXXDtorType Type, const CXXRecordDecl *RD)
BuildVirtualCall - This routine makes indirect vtable call for call to virtual destructors.
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
void EmitCheck(ArrayRef< std::pair< llvm::Value *, SanitizerKind::SanitizerOrdinal > > Checked, SanitizerHandler Check, ArrayRef< llvm::Constant * > StaticArgs, ArrayRef< llvm::Value * > DynamicArgs, const TrapReason *TR=nullptr)
Create a basic block that will either trap or call a handler function in the UBSan runtime with the p...
void EmitCXXGuardedInitBranch(llvm::Value *NeedsInit, llvm::BasicBlock *InitBlock, llvm::BasicBlock *NoInitBlock, GuardKind Kind, const VarDecl *D)
Emit a branch to select whether or not to perform guarded initialization.
CGDebugInfo * getDebugInfo()
LValue MakeRawAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, AlignmentSource Source=AlignmentSource::Type)
Same as MakeAddrLValue above except that the pointer is known to be unsigned.
llvm::AllocaInst * CreateTempAlloca(llvm::Type *Ty, const Twine &Name="tmp", llvm::Value *ArraySize=nullptr)
CreateTempAlloca - This creates an alloca and inserts it into the entry block if ArraySize is nullptr...
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)
EmitCall - Generate a call of the given function, expecting the given result type,...
CGPointerAuthInfo EmitPointerAuthInfo(const PointerAuthSchema &Schema, llvm::Value *StorageAddress, GlobalDecl SchemaDecl, QualType SchemaType)
Emit the concrete pointer authentication informaton for the given authentication schema.
void EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD, llvm::Value *VTable, SourceLocation Loc)
If whole-program virtual table optimization is enabled, emit an assumption that VTable is a member of...
llvm::Value * unregisterGlobalDtorWithUnAtExit(llvm::Constant *dtorStub)
Call unatexit() with function dtorStub.
llvm::Value * emitPointerAuthResign(llvm::Value *Pointer, QualType PointerType, const CGPointerAuthInfo &CurAuthInfo, const CGPointerAuthInfo &NewAuthInfo, bool IsKnownNonNull)
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
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 EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void registerGlobalDtorWithLLVM(const VarDecl &D, llvm::FunctionCallee fn, llvm::Constant *addr)
Registers the dtor using 'llvm.global_dtors' for platforms that do not support an 'atexit()' function...
llvm::Value * LoadCXXVTT()
LoadCXXVTT - Load the VTT parameter to base constructors/destructors have virtual bases.
llvm::Value * EmitARCRetainNonBlock(llvm::Value *value)
Retain the given object, with normal retain semantics.
llvm::Type * ConvertTypeForMem(QualType T)
CodeGenTypes & getTypes() const
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
void EmitAggExpr(const Expr *E, AggValueSlot AS)
EmitAggExpr - Emit the computation of the specified expression of aggregate type.
llvm::Value * GetVTTParameter(GlobalDecl GD, bool ForVirtualBase, bool Delegating)
GetVTTParameter - Return the VTT parameter that should be passed to a base constructor/destructor wit...
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID, bool NoMerge=false, const TrapReason *TR=nullptr)
Create a basic block that will call the trap intrinsic, and emit a conditional branch to it,...
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
llvm::Value * EmitVTableTypeCheckedLoad(const CXXRecordDecl *RD, llvm::Value *VTable, llvm::Type *VTableTy, uint64_t VTableByteOffset)
Emit a type checked load from the given vtable.
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
llvm::Instruction * CurrentFuncletPad
bool ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD)
Returns whether we should perform a type checked load when loading a virtual function for virtual cal...
llvm::LLVMContext & getLLVMContext()
void PopCleanupBlock(bool FallThroughIsBranchThrough=false, bool ForDeactivation=false)
PopCleanupBlock - Will pop the cleanup entry on the stack and process all branch fixups.
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...
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
QualType BuildFunctionArgList(GlobalDecl GD, FunctionArgList &Args)
llvm::Value * EmitPointerAuthAuth(const CGPointerAuthInfo &Info, llvm::Value *Pointer)
This class organizes the cross-function state that is used while generating LLVM code.
void AddCXXPrioritizedStermFinalizerEntry(llvm::Function *StermFinalizer, int Priority)
void setGVProperties(llvm::GlobalValue *GV, GlobalDecl GD) const
Set visibility, dllimport/dllexport and dso_local.
void AddCXXStermFinalizerToGlobalDtor(llvm::Function *StermFinalizer, int Priority)
Add an sterm finalizer to its own llvm.global_dtors entry.
llvm::GlobalVariable::ThreadLocalMode GetDefaultLLVMTLSModel() const
Get LLVM TLS mode from CodeGenOptions.
void setDSOLocal(llvm::GlobalValue *GV) const
llvm::Module & getModule() const
llvm::FunctionCallee CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeList ExtraAttrs=llvm::AttributeList(), bool Local=false, bool AssumeConvergent=false)
Create or return a runtime function declaration with the specified type and name.
CodeGenVTables & getVTables()
void AddCXXStermFinalizerEntry(llvm::FunctionCallee DtorFn)
Add an sterm finalizer to the C++ global cleanup function.
llvm::Constant * GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH=false)
Get the address of the RTTI descriptor for the given type.
llvm::Constant * getFunctionPointer(GlobalDecl GD, llvm::Type *Ty=nullptr)
Return the ABI-correct function pointer value for a reference to the given function.
CGPointerAuthInfo getMemberFunctionPointerAuthInfo(QualType FT)
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
bool shouldMapVisibilityToDLLExport(const NamedDecl *D) const
const TargetInfo & getTarget() const
bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D)
Try to emit a base destructor as an alias to its primary base-class destructor.
llvm::GlobalValue::LinkageTypes getLLVMLinkageVarDefinition(const VarDecl *VD)
Returns LLVM linkage for a declarator.
const llvm::DataLayout & getDataLayout() const
CGCXXABI & getCXXABI() const
static llvm::GlobalValue::VisibilityTypes GetLLVMVisibility(Visibility V)
llvm::Constant * getMemberFunctionPointer(const FunctionDecl *FD, llvm::Type *Ty=nullptr)
llvm::Function * codegenCXXStructor(GlobalDecl GD)
CharUnits getClassPointerAlignment(const CXXRecordDecl *CD)
Returns the assumed alignment of an opaque pointer to the given class.
const llvm::Triple & getTriple() const
llvm::GlobalVariable::LinkageTypes getFunctionLinkage(GlobalDecl GD)
llvm::Constant * CreateRuntimeVariable(llvm::Type *Ty, StringRef Name)
Create a new runtime global variable with the specified type and name.
CharUnits getDynamicOffsetAlignment(CharUnits ActualAlign, const CXXRecordDecl *Class, CharUnits ExpectedTargetAlign)
Given a class pointer with an actual known alignment, and the expected alignment of an object at a dy...
llvm::Constant * GetAddrOfGlobal(GlobalDecl GD, ForDefinition_t IsForDefinition=NotForDefinition)
ItaniumVTableContext & getItaniumVTableContext()
ASTContext & getContext() const
llvm::Constant * GetAddrOfGlobalVar(const VarDecl *D, llvm::Type *Ty=nullptr, ForDefinition_t IsForDefinition=NotForDefinition)
Return the llvm::Constant for the address of the given global variable.
bool supportsCOMDAT() const
const TargetCodeGenInfo & getTargetCodeGenInfo()
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
void SetCommonAttributes(GlobalDecl GD, llvm::GlobalValue *GV)
Set attributes which are common to any form of a global definition (alias, Objective-C method,...
llvm::GlobalVariable * CreateOrReplaceCXXRuntimeVariable(StringRef Name, llvm::Type *Ty, llvm::GlobalValue::LinkageTypes Linkage, llvm::Align Alignment)
Will return a global variable of the given type.
llvm::FunctionCallee getTerminateFn()
Get the declaration of std::terminate for the platform.
llvm::LLVMContext & getLLVMContext()
llvm::GlobalValue * GetGlobalValue(StringRef Ref)
void maybeSetTrivialComdat(const Decl &D, llvm::GlobalObject &GO)
LangAS GetGlobalVarAddressSpace(const VarDecl *D)
Return the AST address space of the underlying global variable for D, as determined by its declaratio...
llvm::GlobalVariable::LinkageTypes getVTableLinkage(const CXXRecordDecl *RD)
Return the appropriate linkage for the vtable, VTT, and type information of the given class.
void SetLLVMFunctionAttributes(GlobalDecl GD, const CGFunctionInfo &Info, llvm::Function *F, bool IsThunk)
Set the LLVM function attributes (sext, zext, etc).
void addReplacement(StringRef Name, llvm::Constant *C)
llvm::Constant * getConstantSignedPointer(llvm::Constant *Pointer, const PointerAuthSchema &Schema, llvm::Constant *StorageAddress, GlobalDecl SchemaDecl, QualType SchemaType)
Sign a constant pointer using the given scheme, producing a constant with the same IR type.
void SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F)
Set the LLVM function attributes which only apply to a function definition.
llvm::Function * CreateGlobalInitOrCleanUpFunction(llvm::FunctionType *ty, const Twine &name, const CGFunctionInfo &FI, SourceLocation Loc=SourceLocation(), bool TLS=false, llvm::GlobalVariable::LinkageTypes Linkage=llvm::GlobalVariable::InternalLinkage)
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
const CGFunctionInfo & arrangeCXXMethodDeclaration(const CXXMethodDecl *MD)
C++ methods have some special rules and also have implicit parameters.
const CodeGenOptions & getCodeGenOpts() const
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
bool isFuncTypeConvertible(const FunctionType *FT)
isFuncTypeConvertible - Utility to check whether a function type can be converted to an LLVM type (i....
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
const CGFunctionInfo & arrangeCXXMethodCall(const CallArgList &args, const FunctionProtoType *type, RequiredArgs required, unsigned numPrefixArgs)
Arrange a call to a C++ method, passing the given arguments.
const CGFunctionInfo & arrangeNullaryFunction()
A nullary function is a freestanding function of type 'void ()'.
llvm::GlobalVariable * GetAddrOfVTT(const CXXRecordDecl *RD)
GetAddrOfVTT - Get the address of the VTT for the given record decl.
void createVTableInitializer(ConstantStructBuilder &builder, const VTableLayout &layout, llvm::Constant *rtti, bool vtableHasLocalLinkage)
Add vtable components for the given vtable layout to the given global initializer.
void GenerateRelativeVTableAlias(llvm::GlobalVariable *VTable, llvm::StringRef AliasNameRef)
Generate a public facing alias for the vtable and make the vtable either hidden or private.
bool isVTableExternal(const CXXRecordDecl *RD)
At this point in the translation unit, does it appear that can we rely on the vtable being defined el...
void RemoveHwasanMetadata(llvm::GlobalValue *GV) const
Specify a global should not be instrumented with hwasan.
void EmitVTTDefinition(llvm::GlobalVariable *VTT, llvm::GlobalVariable::LinkageTypes Linkage, const CXXRecordDecl *RD)
EmitVTTDefinition - Emit the definition of the given vtable.
void pushTerminate()
Push a terminate handler on the stack.
void popTerminate()
Pops a terminate handler off the stack.
static RValue get(llvm::Value *V)
static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype, unsigned additional)
Compute the arguments required by the given formal prototype, given that there may be some additional...
virtual unsigned getSizeOfUnwindException() const
Determines the size of struct _Unwind_Exception on this platform, in 8-bit units.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool isTranslationUnit() const
decl_range noload_decls() const
noload_decls_begin/end - Iterate over the declarations stored in this context that are currently load...
SourceLocation getLocation() const
DeclContext * getDeclContext()
bool shouldEmitInExternalSource() const
Whether the definition of the declaration should be emitted in external sources.
This represents one expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
bool isInlined() const
Determine whether this function should be inlined, because it is either marked "inline" or "constexpr...
bool doesThisDeclarationHaveABody() const
Returns whether this specific declaration of the function has a body.
bool isPureVirtual() const
Whether this virtual function is pure, i.e.
Represents a prototype with parameter type info, e.g.
GlobalDecl - represents a global declaration.
GlobalDecl getWithCtorType(CXXCtorType Type)
CXXCtorType getCtorType() const
GlobalDecl getCanonicalDecl() const
GlobalDecl getWithDtorType(CXXDtorType Type)
CXXDtorType getDtorType() const
const Decl * getDecl() const
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
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.
bool isRelativeLayout() const
const VTableLayout & getVTableLayout(const CXXRecordDecl *RD)
CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, const CXXRecordDecl *VBase)
Return the offset in chars (relative to the vtable address point) where the offset of the virtual bas...
GlobalDecl findOriginalMethod(GlobalDecl GD)
Return the method that added the v-table slot that will be used to call the given method.
virtual void mangleCXXRTTI(QualType T, raw_ostream &)=0
virtual void mangleCXXRTTIName(QualType T, raw_ostream &, bool NormalizeIntegers=false)=0
A pointer to member type per C++ 8.3.3 - Pointers to members.
CXXRecordDecl * getMostRecentCXXRecordDecl() const
Note: this can trigger extra deserialization when external AST sources are used.
QualType getPointeeType() const
bool isMemberFunctionPointer() const
Returns true if the member type (i.e.
bool isMemberDataPointer() const
Returns true if the member type (i.e.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Visibility getVisibility() const
Determines the visibility of this entity.
bool isExternallyVisible() const
static const OpaqueValueExpr * findInCopyConstruct(const Expr *expr)
Given an expression which invokes a copy constructor — i.e.
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
A (possibly-)qualified type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
The collection of all-type qualifiers we support.
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
@ OCL_None
There is no lifetime qualification on this type.
@ OCL_Weak
Reading or writing from this object requires a barrier call.
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
ObjCLifetime getObjCLifetime() const
bool canPassInRegisters() const
Determine whether this class can be passed in registers.
Encodes a location in the source.
SourceLocation getBeginLoc() const LLVM_READONLY
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
unsigned getMaxAtomicInlineWidth() const
Return the maximum width lock-free atomic operation which can be inlined given the supported features...
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
virtual bool hasPS4DLLImportExport() const
uint64_t getPointerAlign(LangAS AddrSpace) const
unsigned getLongWidth() const
getLongWidth/Align - Return the size of 'signed long' and 'unsigned long' for this target,...
virtual bool hasFeature(StringRef Feature) const
Determine whether the given target has the given feature.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
CXXRecordDecl * castAsCXXRecordDecl() const
const T * castAs() const
Member-template castAs.
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Visibility getVisibility() const
Determine the visibility of this type.
bool isMemberFunctionPointerType() const
Linkage getLinkage() const
Determine the linkage of this type.
TypeClass getTypeClass() const
const T * getAs() const
Member-template getAs'.
bool isRecordType() const
AddressPointLocation getAddressPoint(BaseSubobject Base) const
size_t getVTableSize(size_t i) const
Represents a variable declaration or definition.
TLSKind getTLSKind() const
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
bool isNoDestroy(const ASTContext &) const
Is destruction of this variable entirely suppressed?
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
bool isInline() const
Whether this variable is (C++1z) inline.
const Expr * getInit() const
@ TLS_Dynamic
TLS with a dynamic initializer.
@ TLS_None
Not a TLS variable.
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
TemplateSpecializationKind getTemplateSpecializationKind() const
If this variable is an instantiation of a variable template or a static data member of a class templa...
llvm::Value * getCXXDestructorImplicitParam(CodeGenModule &CGM, llvm::BasicBlock *InsertBlock, llvm::BasicBlock::iterator InsertPoint, const CXXDestructorDecl *D, CXXDtorType Type, bool ForVirtualBase, bool Delegating)
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT, CGCXXABI &CXXABI)
bool classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, const ABIInfo &Info)
TypeEvaluationKind
The kind of evaluation to perform on values of a particular type.
@ NormalCleanup
Denotes a cleanup that should run when a scope is exited using normal control flow (falling off the e...
@ EHCleanup
Denotes a cleanup that should run when a scope is exited using exceptional control flow (a throw stat...
CGCXXABI * CreateItaniumCXXABI(CodeGenModule &CGM)
Creates an Itanium-family ABI.
Definition ItaniumCXXABI.cpp:569
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
constexpr Variable var(Literal L)
Returns the variable of L.
bool This(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
CXXCtorType
C++ constructor types.
@ Ctor_Base
Base object ctor.
@ Ctor_DefaultClosure
Default closure variant of a ctor.
@ Ctor_CopyingClosure
Copying closure variant of a ctor.
@ Ctor_Complete
Complete object ctor.
@ Ctor_Comdat
The COMDAT used for ctors.
@ Ctor_Unified
GCC-style unified dtor.
bool isa(CodeGen::Address addr)
bool isTemplateInstantiation(TemplateSpecializationKind Kind)
Determine whether this template specialization kind refers to an instantiation of an entity (as oppos...
@ Success
Annotation was successful.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
Linkage
Describes the different kinds of linkage (C++ [basic.link], C99 6.2.2) that an entity may have.
@ VisibleNone
No linkage according to the standard, but is visible from other translation units because of types de...
@ None
No linkage, which means that the entity is unique and can only be referred to from within its scope.
@ UniqueExternal
External linkage within a unique namespace.
@ Internal
Internal linkage, which indicates that the entity can be referred to from within the translation unit...
@ External
External linkage, which indicates that the entity can be referred to from other translation units.
@ Module
Module linkage, which indicates that the entity can be referred to from other translation units withi...
@ Result
The result type of a method or function.
const FunctionProtoType * T
CXXDtorType
C++ destructor types.
@ Dtor_VectorDeleting
Vector deleting dtor.
@ Dtor_Comdat
The COMDAT used for dtors.
@ Dtor_Unified
GCC-style unified dtor.
@ Dtor_Base
Base object dtor.
@ Dtor_Complete
Complete object dtor.
@ Dtor_Deleting
Deleting dtor.
bool isDiscardableGVALinkage(GVALinkage L)
@ Type
The name was classified as a type.
LangAS
Defines the address space values used by the address space qualifier of QualType.
U cast(CodeGen::Address addr)
@ Class
The "class" keyword introduces the elaborated-type-specifier.
@ EST_None
no exception specification
Visibility
Describes the different kinds of visibility that a declaration may have.
@ HiddenVisibility
Objects with "hidden" visibility are not seen by the dynamic linker.
@ DefaultVisibility
Objects with "default" visibility are seen by the dynamic linker and act like normal objects.
const half4 dst(half4 Src0, half4 Src1)
Represents an element in a path from a derived class to a base class.
const CXXRecordDecl * NearestVBase
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int64Ty
llvm::PointerType * GlobalsVoidPtrTy
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::IntegerType * CharTy
char
llvm::CallingConv::ID getRuntimeCC() const
llvm::IntegerType * SizeTy
llvm::PointerType * VoidPtrPtrTy
llvm::PointerType * GlobalsInt8PtrTy
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::IntegerType * IntTy
int
CharUnits getSizeSize() const
CharUnits getSizeAlign() const
llvm::PointerType * Int8PtrTy
llvm::IntegerType * PtrDiffTy
CharUnits getPointerAlign() const
llvm::PointerType * DefaultPtrTy
static const EHPersonality & get(CodeGenModule &CGM, const FunctionDecl *FD)
Extra information about a function prototype.
PointerAuthSchema CXXVTTVTablePointers
The ABI for C++ virtual table pointers as installed in a VTT.
PointerAuthSchema CXXTypeInfoVTablePointer
TypeInfo has external ABI requirements and is emitted without actually having parsed the libcxx defin...
union clang::ReturnAdjustment::VirtualAdjustment Virtual
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
bool has(SanitizerMask K) const
Check if a certain (single) sanitizer is enabled.
union clang::ThisAdjustment::VirtualAdjustment Virtual
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
ThisAdjustment This
The this pointer adjustment.
unsigned AddressPointIndex
struct clang::ReturnAdjustment::VirtualAdjustment::@103031170252120233124322035264172076254313213024 Itanium
int64_t VBaseOffsetOffset
The offset (in bytes), relative to the address point of the virtual base class offset.
struct clang::ThisAdjustment::VirtualAdjustment::@106065375072164260365214033034320247050276346205 Itanium
int64_t VCallOffsetOffset
The offset (in bytes), relative to the address point, of the virtual call offset.