1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | #include "CGCXXABI.h" |
21 | #include "CGCleanup.h" |
22 | #include "CGRecordLayout.h" |
23 | #include "CGVTables.h" |
24 | #include "CodeGenFunction.h" |
25 | #include "CodeGenModule.h" |
26 | #include "TargetInfo.h" |
27 | #include "clang/CodeGen/ConstantInitBuilder.h" |
28 | #include "clang/AST/Mangle.h" |
29 | #include "clang/AST/Type.h" |
30 | #include "clang/AST/StmtCXX.h" |
31 | #include "llvm/IR/DataLayout.h" |
32 | #include "llvm/IR/GlobalValue.h" |
33 | #include "llvm/IR/Instructions.h" |
34 | #include "llvm/IR/Intrinsics.h" |
35 | #include "llvm/IR/Value.h" |
36 | #include "llvm/Support/ScopedPrinter.h" |
37 | |
38 | using namespace clang; |
39 | using namespace CodeGen; |
40 | |
41 | namespace { |
42 | class ItaniumCXXABI : public CodeGen::CGCXXABI { |
43 | |
44 | llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables; |
45 | |
46 | protected: |
47 | bool UseARMMethodPtrABI; |
48 | bool UseARMGuardVarABI; |
49 | bool Use32BitVTableOffsetABI; |
50 | |
51 | ItaniumMangleContext &getMangleContext() { |
52 | return cast<ItaniumMangleContext>(CodeGen::CGCXXABI::getMangleContext()); |
53 | } |
54 | |
55 | public: |
56 | ItaniumCXXABI(CodeGen::CodeGenModule &CGM, |
57 | bool UseARMMethodPtrABI = false, |
58 | bool UseARMGuardVarABI = false) : |
59 | CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI), |
60 | UseARMGuardVarABI(UseARMGuardVarABI), |
61 | Use32BitVTableOffsetABI(false) { } |
62 | |
63 | bool classifyReturnType(CGFunctionInfo &FI) const override; |
64 | |
65 | bool passClassIndirect(const CXXRecordDecl *RD) const { |
66 | return !canCopyArgument(RD); |
67 | } |
68 | |
69 | RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override { |
70 | |
71 | if (passClassIndirect(RD)) |
72 | return RAA_Indirect; |
73 | return RAA_Default; |
74 | } |
75 | |
76 | bool isThisCompleteObject(GlobalDecl GD) const override { |
77 | |
78 | |
79 | if (isa<CXXDestructorDecl>(GD.getDecl())) { |
80 | switch (GD.getDtorType()) { |
81 | case Dtor_Complete: |
82 | case Dtor_Deleting: |
83 | return true; |
84 | |
85 | case Dtor_Base: |
86 | return false; |
87 | |
88 | case Dtor_Comdat: |
89 | llvm_unreachable("emitting dtor comdat as function?"); |
90 | } |
91 | llvm_unreachable("bad dtor kind"); |
92 | } |
93 | if (isa<CXXConstructorDecl>(GD.getDecl())) { |
94 | switch (GD.getCtorType()) { |
95 | case Ctor_Complete: |
96 | return true; |
97 | |
98 | case Ctor_Base: |
99 | return false; |
100 | |
101 | case Ctor_CopyingClosure: |
102 | case Ctor_DefaultClosure: |
103 | llvm_unreachable("closure ctors in Itanium ABI?"); |
104 | |
105 | case Ctor_Comdat: |
106 | llvm_unreachable("emitting ctor comdat as function?"); |
107 | } |
108 | llvm_unreachable("bad dtor kind"); |
109 | } |
110 | |
111 | |
112 | return false; |
113 | } |
114 | |
115 | bool isZeroInitializable(const MemberPointerType *MPT) override; |
116 | |
117 | llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT) override; |
118 | |
119 | CGCallee |
120 | EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, |
121 | const Expr *E, |
122 | Address This, |
123 | llvm::Value *&ThisPtrForCall, |
124 | llvm::Value *MemFnPtr, |
125 | const MemberPointerType *MPT) override; |
126 | |
127 | llvm::Value * |
128 | EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E, |
129 | Address Base, |
130 | llvm::Value *MemPtr, |
131 | const MemberPointerType *MPT) override; |
132 | |
133 | llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF, |
134 | const CastExpr *E, |
135 | llvm::Value *Src) override; |
136 | llvm::Constant *EmitMemberPointerConversion(const CastExpr *E, |
137 | llvm::Constant *Src) override; |
138 | |
139 | llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT) override; |
140 | |
141 | llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD) override; |
142 | llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT, |
143 | CharUnits offset) override; |
144 | llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT) override; |
145 | llvm::Constant *BuildMemberPointer(const CXXMethodDecl *MD, |
146 | CharUnits ThisAdjustment); |
147 | |
148 | llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF, |
149 | llvm::Value *L, llvm::Value *R, |
150 | const MemberPointerType *MPT, |
151 | bool Inequality) override; |
152 | |
153 | llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF, |
154 | llvm::Value *Addr, |
155 | const MemberPointerType *MPT) override; |
156 | |
157 | void emitVirtualObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, |
158 | Address Ptr, QualType ElementType, |
159 | const CXXDestructorDecl *Dtor) override; |
160 | |
161 | |
162 | |
163 | |
164 | |
165 | |
166 | |
167 | |
168 | |
169 | CharUnits getAlignmentOfExnObject() { |
170 | auto align = CGM.getContext().getTargetDefaultAlignForAttributeAligned(); |
171 | return CGM.getContext().toCharUnitsFromBits(align); |
172 | } |
173 | |
174 | void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) override; |
175 | void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) override; |
176 | |
177 | void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override; |
178 | |
179 | llvm::CallInst * |
180 | emitTerminateForUnexpectedException(CodeGenFunction &CGF, |
181 | llvm::Value *Exn) override; |
182 | |
183 | void EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD); |
184 | llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override; |
185 | CatchTypeInfo |
186 | getAddrOfCXXCatchHandlerType(QualType Ty, |
187 | QualType CatchHandlerType) override { |
188 | return CatchTypeInfo{getAddrOfRTTIDescriptor(Ty), 0}; |
189 | } |
190 | |
191 | bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy) override; |
192 | void EmitBadTypeidCall(CodeGenFunction &CGF) override; |
193 | llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy, |
194 | Address ThisPtr, |
195 | llvm::Type *StdTypeInfoPtrTy) override; |
196 | |
197 | bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr, |
198 | QualType SrcRecordTy) override; |
199 | |
200 | llvm::Value *EmitDynamicCastCall(CodeGenFunction &CGF, Address Value, |
201 | QualType SrcRecordTy, QualType DestTy, |
202 | QualType DestRecordTy, |
203 | llvm::BasicBlock *CastEnd) override; |
204 | |
205 | llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF, Address Value, |
206 | QualType SrcRecordTy, |
207 | QualType DestTy) override; |
208 | |
209 | bool EmitBadCastCall(CodeGenFunction &CGF) override; |
210 | |
211 | llvm::Value * |
212 | GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This, |
213 | const CXXRecordDecl *ClassDecl, |
214 | const CXXRecordDecl *BaseClassDecl) override; |
215 | |
216 | void EmitCXXConstructors(const CXXConstructorDecl *D) override; |
217 | |
218 | AddedStructorArgs |
219 | buildStructorSignature(GlobalDecl GD, |
220 | SmallVectorImpl<CanQualType> &ArgTys) override; |
221 | |
222 | bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor, |
223 | CXXDtorType DT) const override { |
224 | |
225 | |
226 | |
227 | return false; |
228 | } |
229 | |
230 | void EmitCXXDestructors(const CXXDestructorDecl *D) override; |
231 | |
232 | void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy, |
233 | FunctionArgList &Params) override; |
234 | |
235 | void EmitInstanceFunctionProlog(CodeGenFunction &CGF) override; |
236 | |
237 | AddedStructorArgs |
238 | addImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D, |
239 | CXXCtorType Type, bool ForVirtualBase, |
240 | bool Delegating, CallArgList &Args) override; |
241 | |
242 | void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, |
243 | CXXDtorType Type, bool ForVirtualBase, |
244 | bool Delegating, Address This) override; |
245 | |
246 | void emitVTableDefinitions(CodeGenVTables &CGVT, |
247 | const CXXRecordDecl *RD) override; |
248 | |
249 | bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF, |
250 | CodeGenFunction::VPtr Vptr) override; |
251 | |
252 | bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass) override { |
253 | return true; |
254 | } |
255 | |
256 | llvm::Constant * |
257 | getVTableAddressPoint(BaseSubobject Base, |
258 | const CXXRecordDecl *VTableClass) override; |
259 | |
260 | llvm::Value *getVTableAddressPointInStructor( |
261 | CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, |
262 | BaseSubobject Base, const CXXRecordDecl *NearestVBase) override; |
263 | |
264 | llvm::Value *getVTableAddressPointInStructorWithVTT( |
265 | CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, |
266 | BaseSubobject Base, const CXXRecordDecl *NearestVBase); |
267 | |
268 | llvm::Constant * |
269 | getVTableAddressPointForConstExpr(BaseSubobject Base, |
270 | const CXXRecordDecl *VTableClass) override; |
271 | |
272 | llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, |
273 | CharUnits VPtrOffset) override; |
274 | |
275 | CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD, |
276 | Address This, llvm::Type *Ty, |
277 | SourceLocation Loc) override; |
278 | |
279 | llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF, |
280 | const CXXDestructorDecl *Dtor, |
281 | CXXDtorType DtorType, |
282 | Address This, |
283 | const CXXMemberCallExpr *CE) override; |
284 | |
285 | void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override; |
286 | |
287 | bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override; |
288 | bool canSpeculativelyEmitVTableAsBaseClass(const CXXRecordDecl *RD) const; |
289 | |
290 | void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD, |
291 | bool ReturnAdjustment) override { |
292 | |
293 | |
294 | if (ForVTable && !Thunk->hasLocalLinkage()) |
295 | Thunk->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage); |
296 | CGM.setGVProperties(Thunk, GD); |
297 | } |
298 | |
299 | bool exportThunk() override { return true; } |
300 | |
301 | llvm::Value *performThisAdjustment(CodeGenFunction &CGF, Address This, |
302 | const ThisAdjustment &TA) override; |
303 | |
304 | llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, Address Ret, |
305 | const ReturnAdjustment &RA) override; |
306 | |
307 | size_t getSrcArgforCopyCtor(const CXXConstructorDecl *, |
308 | FunctionArgList &Args) const override { |
309 | (0) . __assert_fail ("!Args.empty() && \"expected the arglist to not be empty!\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 309, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!Args.empty() && "expected the arglist to not be empty!"); |
310 | return Args.size() - 1; |
311 | } |
312 | |
313 | StringRef GetPureVirtualCallName() override { return "__cxa_pure_virtual"; } |
314 | StringRef GetDeletedVirtualCallName() override |
315 | { return "__cxa_deleted_virtual"; } |
316 | |
317 | CharUnits getArrayCookieSizeImpl(QualType elementType) override; |
318 | Address InitializeArrayCookie(CodeGenFunction &CGF, |
319 | Address NewPtr, |
320 | llvm::Value *NumElements, |
321 | const CXXNewExpr *expr, |
322 | QualType ElementType) override; |
323 | llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, |
324 | Address allocPtr, |
325 | CharUnits cookieSize) override; |
326 | |
327 | void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, |
328 | llvm::GlobalVariable *DeclPtr, |
329 | bool PerformInit) override; |
330 | void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, |
331 | llvm::FunctionCallee dtor, |
332 | llvm::Constant *addr) override; |
333 | |
334 | llvm::Function *getOrCreateThreadLocalWrapper(const VarDecl *VD, |
335 | llvm::Value *Val); |
336 | void EmitThreadLocalInitFuncs( |
337 | CodeGenModule &CGM, |
338 | ArrayRef<const VarDecl *> CXXThreadLocals, |
339 | ArrayRef<llvm::Function *> CXXThreadLocalInits, |
340 | ArrayRef<const VarDecl *> CXXThreadLocalInitVars) override; |
341 | |
342 | bool usesThreadWrapperFunction() const override { return true; } |
343 | LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD, |
344 | QualType LValType) override; |
345 | |
346 | bool NeedsVTTParameter(GlobalDecl GD) override; |
347 | |
348 | |
349 | |
350 | protected: |
351 | |
352 | |
353 | virtual bool shouldRTTIBeUnique() const { return true; } |
354 | |
355 | public: |
356 | |
357 | enum RTTIUniquenessKind { |
358 | |
359 | |
360 | RUK_Unique, |
361 | |
362 | |
363 | |
364 | RUK_NonUniqueHidden, |
365 | |
366 | |
367 | |
368 | |
369 | RUK_NonUniqueVisible |
370 | }; |
371 | |
372 | |
373 | |
374 | RTTIUniquenessKind |
375 | classifyRTTIUniqueness(QualType CanTy, |
376 | llvm::GlobalValue::LinkageTypes Linkage) const; |
377 | friend class ItaniumRTTIBuilder; |
378 | |
379 | void emitCXXStructor(GlobalDecl GD) override; |
380 | |
381 | std::pair<llvm::Value *, const CXXRecordDecl *> |
382 | LoadVTablePtr(CodeGenFunction &CGF, Address This, |
383 | const CXXRecordDecl *RD) override; |
384 | |
385 | private: |
386 | bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const { |
387 | const auto &VtableLayout = |
388 | CGM.getItaniumVTableContext().getVTableLayout(RD); |
389 | |
390 | for (const auto &VtableComponent : VtableLayout.vtable_components()) { |
391 | |
392 | if (!VtableComponent.isUsedFunctionPointerKind()) |
393 | continue; |
394 | |
395 | const CXXMethodDecl *Method = VtableComponent.getFunctionDecl(); |
396 | if (!Method->getCanonicalDecl()->isInlined()) |
397 | continue; |
398 | |
399 | StringRef Name = CGM.getMangledName(VtableComponent.getGlobalDecl()); |
400 | auto *Entry = CGM.GetGlobalValue(Name); |
401 | |
402 | |
403 | |
404 | |
405 | |
406 | if (!Entry || Entry->isDeclaration()) |
407 | return true; |
408 | } |
409 | return false; |
410 | } |
411 | |
412 | bool isVTableHidden(const CXXRecordDecl *RD) const { |
413 | const auto &VtableLayout = |
414 | CGM.getItaniumVTableContext().getVTableLayout(RD); |
415 | |
416 | for (const auto &VtableComponent : VtableLayout.vtable_components()) { |
417 | if (VtableComponent.isRTTIKind()) { |
418 | const CXXRecordDecl *RTTIDecl = VtableComponent.getRTTIDecl(); |
419 | if (RTTIDecl->getVisibility() == Visibility::HiddenVisibility) |
420 | return true; |
421 | } else if (VtableComponent.isUsedFunctionPointerKind()) { |
422 | const CXXMethodDecl *Method = VtableComponent.getFunctionDecl(); |
423 | if (Method->getVisibility() == Visibility::HiddenVisibility && |
424 | !Method->isDefined()) |
425 | return true; |
426 | } |
427 | } |
428 | return false; |
429 | } |
430 | }; |
431 | |
432 | class ARMCXXABI : public ItaniumCXXABI { |
433 | public: |
434 | ARMCXXABI(CodeGen::CodeGenModule &CGM) : |
435 | ItaniumCXXABI(CGM, true, |
436 | true) {} |
437 | |
438 | bool HasThisReturn(GlobalDecl GD) const override { |
439 | return (isa<CXXConstructorDecl>(GD.getDecl()) || ( |
440 | isa<CXXDestructorDecl>(GD.getDecl()) && |
441 | GD.getDtorType() != Dtor_Deleting)); |
442 | } |
443 | |
444 | void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, |
445 | QualType ResTy) override; |
446 | |
447 | CharUnits getArrayCookieSizeImpl(QualType elementType) override; |
448 | Address InitializeArrayCookie(CodeGenFunction &CGF, |
449 | Address NewPtr, |
450 | llvm::Value *NumElements, |
451 | const CXXNewExpr *expr, |
452 | QualType ElementType) override; |
453 | llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, Address allocPtr, |
454 | CharUnits cookieSize) override; |
455 | }; |
456 | |
457 | class iOS64CXXABI : public ARMCXXABI { |
458 | public: |
459 | iOS64CXXABI(CodeGen::CodeGenModule &CGM) : ARMCXXABI(CGM) { |
460 | Use32BitVTableOffsetABI = true; |
461 | } |
462 | |
463 | |
464 | bool shouldRTTIBeUnique() const override { return false; } |
465 | }; |
466 | |
467 | class WebAssemblyCXXABI final : public ItaniumCXXABI { |
468 | public: |
469 | explicit WebAssemblyCXXABI(CodeGen::CodeGenModule &CGM) |
470 | : ItaniumCXXABI(CGM, , |
471 | ) {} |
472 | void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override; |
473 | |
474 | private: |
475 | bool HasThisReturn(GlobalDecl GD) const override { |
476 | return isa<CXXConstructorDecl>(GD.getDecl()) || |
477 | (isa<CXXDestructorDecl>(GD.getDecl()) && |
478 | GD.getDtorType() != Dtor_Deleting); |
479 | } |
480 | bool canCallMismatchedFunctionType() const override { return false; } |
481 | }; |
482 | } |
483 | |
484 | CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) { |
485 | switch (CGM.getTarget().getCXXABI().getKind()) { |
486 | |
487 | |
488 | case TargetCXXABI::GenericARM: |
489 | case TargetCXXABI::iOS: |
490 | case TargetCXXABI::WatchOS: |
491 | return new ARMCXXABI(CGM); |
492 | |
493 | case TargetCXXABI::iOS64: |
494 | return new iOS64CXXABI(CGM); |
495 | |
496 | |
497 | |
498 | |
499 | case TargetCXXABI::GenericAArch64: |
500 | return new ItaniumCXXABI(CGM, true, |
501 | true); |
502 | |
503 | case TargetCXXABI::GenericMIPS: |
504 | return new ItaniumCXXABI(CGM, true); |
505 | |
506 | case TargetCXXABI::WebAssembly: |
507 | return new WebAssemblyCXXABI(CGM); |
508 | |
509 | case TargetCXXABI::GenericItanium: |
510 | if (CGM.getContext().getTargetInfo().getTriple().getArch() |
511 | == llvm::Triple::le32) { |
512 | |
513 | |
514 | |
515 | return new ItaniumCXXABI(CGM, true, |
516 | false); |
517 | } |
518 | return new ItaniumCXXABI(CGM); |
519 | |
520 | case TargetCXXABI::Microsoft: |
521 | llvm_unreachable("Microsoft ABI is not Itanium-based"); |
522 | } |
523 | llvm_unreachable("bad ABI kind"); |
524 | } |
525 | |
526 | llvm::Type * |
527 | ItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) { |
528 | if (MPT->isMemberDataPointer()) |
529 | return CGM.PtrDiffTy; |
530 | return llvm::StructType::get(CGM.PtrDiffTy, CGM.PtrDiffTy); |
531 | } |
532 | |
533 | |
534 | |
535 | |
536 | |
537 | |
538 | |
539 | |
540 | |
541 | |
542 | |
543 | |
544 | |
545 | |
546 | |
547 | |
548 | |
549 | |
550 | |
551 | |
552 | |
553 | CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( |
554 | CodeGenFunction &CGF, const Expr *E, Address ThisAddr, |
555 | llvm::Value *&ThisPtrForCall, |
556 | llvm::Value *MemFnPtr, const MemberPointerType *MPT) { |
557 | CGBuilderTy &Builder = CGF.Builder; |
558 | |
559 | const FunctionProtoType *FPT = |
560 | MPT->getPointeeType()->getAs<FunctionProtoType>(); |
561 | const CXXRecordDecl *RD = |
562 | cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl()); |
563 | |
564 | llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType( |
565 | CGM.getTypes().arrangeCXXMethodType(RD, FPT, )); |
566 | |
567 | llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1); |
568 | |
569 | llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("memptr.virtual"); |
570 | llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("memptr.nonvirtual"); |
571 | llvm::BasicBlock *FnEnd = CGF.createBasicBlock("memptr.end"); |
572 | |
573 | |
574 | llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1, "memptr.adj"); |
575 | |
576 | |
577 | llvm::Value *Adj = RawAdj; |
578 | if (UseARMMethodPtrABI) |
579 | Adj = Builder.CreateAShr(Adj, ptrdiff_1, "memptr.adj.shifted"); |
580 | |
581 | |
582 | |
583 | llvm::Value *This = ThisAddr.getPointer(); |
584 | llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy()); |
585 | Ptr = Builder.CreateInBoundsGEP(Ptr, Adj); |
586 | This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted"); |
587 | ThisPtrForCall = This; |
588 | |
589 | |
590 | llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0, "memptr.ptr"); |
591 | |
592 | |
593 | |
594 | llvm::Value *IsVirtual; |
595 | if (UseARMMethodPtrABI) |
596 | IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1); |
597 | else |
598 | IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1); |
599 | IsVirtual = Builder.CreateIsNotNull(IsVirtual, "memptr.isvirtual"); |
600 | Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual); |
601 | |
602 | |
603 | |
604 | |
605 | CGF.EmitBlock(FnVirtual); |
606 | |
607 | |
608 | llvm::Type *VTableTy = Builder.getInt8PtrTy(); |
609 | CharUnits VTablePtrAlign = |
610 | CGF.CGM.getDynamicOffsetAlignment(ThisAddr.getAlignment(), RD, |
611 | CGF.getPointerAlign()); |
612 | llvm::Value *VTable = |
613 | CGF.GetVTablePtr(Address(This, VTablePtrAlign), VTableTy, RD); |
614 | |
615 | |
616 | |
617 | |
618 | llvm::Value *VTableOffset = FnAsInt; |
619 | if (!UseARMMethodPtrABI) |
620 | VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1); |
621 | if (Use32BitVTableOffsetABI) { |
622 | VTableOffset = Builder.CreateTrunc(VTableOffset, CGF.Int32Ty); |
623 | VTableOffset = Builder.CreateZExt(VTableOffset, CGM.PtrDiffTy); |
624 | } |
625 | |
626 | llvm::Value *VFPAddr = Builder.CreateGEP(VTable, VTableOffset); |
627 | |
628 | |
629 | |
630 | llvm::Constant *CheckSourceLocation; |
631 | llvm::Constant *CheckTypeDesc; |
632 | bool ShouldEmitCFICheck = CGF.SanOpts.has(SanitizerKind::CFIMFCall) && |
633 | CGM.HasHiddenLTOVisibility(RD); |
634 | if (ShouldEmitCFICheck) { |
635 | CodeGenFunction::SanitizerScope SanScope(&CGF); |
636 | |
637 | CheckSourceLocation = CGF.EmitCheckSourceLocation(E->getBeginLoc()); |
638 | CheckTypeDesc = CGF.EmitCheckTypeDescriptor(QualType(MPT, 0)); |
639 | llvm::Constant *StaticData[] = { |
640 | llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_VMFCall), |
641 | CheckSourceLocation, |
642 | CheckTypeDesc, |
643 | }; |
644 | |
645 | llvm::Metadata *MD = |
646 | CGM.CreateMetadataIdentifierForVirtualMemPtrType(QualType(MPT, 0)); |
647 | llvm::Value *TypeId = llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD); |
648 | |
649 | llvm::Value *TypeTest = Builder.CreateCall( |
650 | CGM.getIntrinsic(llvm::Intrinsic::type_test), {VFPAddr, TypeId}); |
651 | |
652 | if (CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIMFCall)) { |
653 | CGF.EmitTrapCheck(TypeTest); |
654 | } else { |
655 | llvm::Value *AllVtables = llvm::MetadataAsValue::get( |
656 | CGM.getLLVMContext(), |
657 | llvm::MDString::get(CGM.getLLVMContext(), "all-vtables")); |
658 | llvm::Value *ValidVtable = Builder.CreateCall( |
659 | CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables}); |
660 | CGF.EmitCheck(std::make_pair(TypeTest, SanitizerKind::CFIMFCall), |
661 | SanitizerHandler::CFICheckFail, StaticData, |
662 | {VTable, ValidVtable}); |
663 | } |
664 | |
665 | FnVirtual = Builder.GetInsertBlock(); |
666 | } |
667 | |
668 | |
669 | VFPAddr = Builder.CreateBitCast(VFPAddr, FTy->getPointerTo()->getPointerTo()); |
670 | llvm::Value *VirtualFn = Builder.CreateAlignedLoad( |
671 | VFPAddr, CGF.getPointerAlign(), "memptr.virtualfn"); |
672 | CGF.EmitBranch(FnEnd); |
673 | |
674 | |
675 | |
676 | CGF.EmitBlock(FnNonVirtual); |
677 | llvm::Value *NonVirtualFn = |
678 | Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo(), "memptr.nonvirtualfn"); |
679 | |
680 | |
681 | if (ShouldEmitCFICheck) { |
682 | CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl(); |
683 | if (RD->hasDefinition()) { |
684 | CodeGenFunction::SanitizerScope SanScope(&CGF); |
685 | |
686 | llvm::Constant *StaticData[] = { |
687 | llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_NVMFCall), |
688 | CheckSourceLocation, |
689 | CheckTypeDesc, |
690 | }; |
691 | |
692 | llvm::Value *Bit = Builder.getFalse(); |
693 | llvm::Value *CastedNonVirtualFn = |
694 | Builder.CreateBitCast(NonVirtualFn, CGF.Int8PtrTy); |
695 | for (const CXXRecordDecl *Base : CGM.getMostBaseClasses(RD)) { |
696 | llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType( |
697 | getContext().getMemberPointerType( |
698 | MPT->getPointeeType(), |
699 | getContext().getRecordType(Base).getTypePtr())); |
700 | llvm::Value *TypeId = |
701 | llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD); |
702 | |
703 | llvm::Value *TypeTest = |
704 | Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test), |
705 | {CastedNonVirtualFn, TypeId}); |
706 | Bit = Builder.CreateOr(Bit, TypeTest); |
707 | } |
708 | |
709 | CGF.EmitCheck(std::make_pair(Bit, SanitizerKind::CFIMFCall), |
710 | SanitizerHandler::CFICheckFail, StaticData, |
711 | {CastedNonVirtualFn, llvm::UndefValue::get(CGF.IntPtrTy)}); |
712 | |
713 | FnNonVirtual = Builder.GetInsertBlock(); |
714 | } |
715 | } |
716 | |
717 | |
718 | CGF.EmitBlock(FnEnd); |
719 | llvm::PHINode *CalleePtr = Builder.CreatePHI(FTy->getPointerTo(), 2); |
720 | CalleePtr->addIncoming(VirtualFn, FnVirtual); |
721 | CalleePtr->addIncoming(NonVirtualFn, FnNonVirtual); |
722 | |
723 | CGCallee Callee(FPT, CalleePtr); |
724 | return Callee; |
725 | } |
726 | |
727 | |
728 | |
729 | llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress( |
730 | CodeGenFunction &CGF, const Expr *E, Address Base, llvm::Value *MemPtr, |
731 | const MemberPointerType *MPT) { |
732 | getType() == CGM.PtrDiffTy", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 732, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(MemPtr->getType() == CGM.PtrDiffTy); |
733 | |
734 | CGBuilderTy &Builder = CGF.Builder; |
735 | |
736 | |
737 | Base = Builder.CreateElementBitCast(Base, CGF.Int8Ty); |
738 | |
739 | |
740 | llvm::Value *Addr = |
741 | Builder.CreateInBoundsGEP(Base.getPointer(), MemPtr, "memptr.offset"); |
742 | |
743 | |
744 | |
745 | llvm::Type *PType = CGF.ConvertTypeForMem(MPT->getPointeeType()) |
746 | ->getPointerTo(Base.getAddressSpace()); |
747 | return Builder.CreateBitCast(Addr, PType); |
748 | } |
749 | |
750 | |
751 | |
752 | |
753 | |
754 | |
755 | |
756 | |
757 | |
758 | |
759 | |
760 | |
761 | |
762 | |
763 | |
764 | |
765 | |
766 | |
767 | |
768 | |
769 | |
770 | |
771 | |
772 | |
773 | llvm::Value * |
774 | ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, |
775 | const CastExpr *E, |
776 | llvm::Value *src) { |
777 | getCastKind() == CK_DerivedToBaseMemberPointer || E->getCastKind() == CK_BaseToDerivedMemberPointer || E->getCastKind() == CK_ReinterpretMemberPointer", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 779, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || |
778 | getCastKind() == CK_DerivedToBaseMemberPointer || E->getCastKind() == CK_BaseToDerivedMemberPointer || E->getCastKind() == CK_ReinterpretMemberPointer", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 779, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> E->getCastKind() == CK_BaseToDerivedMemberPointer || |
779 | getCastKind() == CK_DerivedToBaseMemberPointer || E->getCastKind() == CK_BaseToDerivedMemberPointer || E->getCastKind() == CK_ReinterpretMemberPointer", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 779, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> E->getCastKind() == CK_ReinterpretMemberPointer); |
780 | |
781 | |
782 | if (E->getCastKind() == CK_ReinterpretMemberPointer) return src; |
783 | |
784 | |
785 | if (isa<llvm::Constant>(src)) |
786 | return EmitMemberPointerConversion(E, cast<llvm::Constant>(src)); |
787 | |
788 | llvm::Constant *adj = getMemberPointerAdjustment(E); |
789 | if (!adj) return src; |
790 | |
791 | CGBuilderTy &Builder = CGF.Builder; |
792 | bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer); |
793 | |
794 | const MemberPointerType *destTy = |
795 | E->getType()->castAs<MemberPointerType>(); |
796 | |
797 | |
798 | |
799 | if (destTy->isMemberDataPointer()) { |
800 | llvm::Value *dst; |
801 | if (isDerivedToBase) |
802 | dst = Builder.CreateNSWSub(src, adj, "adj"); |
803 | else |
804 | dst = Builder.CreateNSWAdd(src, adj, "adj"); |
805 | |
806 | |
807 | llvm::Value *null = llvm::Constant::getAllOnesValue(src->getType()); |
808 | llvm::Value *isNull = Builder.CreateICmpEQ(src, null, "memptr.isnull"); |
809 | return Builder.CreateSelect(isNull, src, dst); |
810 | } |
811 | |
812 | |
813 | if (UseARMMethodPtrABI) { |
814 | uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue(); |
815 | offset <<= 1; |
816 | adj = llvm::ConstantInt::get(adj->getType(), offset); |
817 | } |
818 | |
819 | llvm::Value *srcAdj = Builder.CreateExtractValue(src, 1, "src.adj"); |
820 | llvm::Value *dstAdj; |
821 | if (isDerivedToBase) |
822 | dstAdj = Builder.CreateNSWSub(srcAdj, adj, "adj"); |
823 | else |
824 | dstAdj = Builder.CreateNSWAdd(srcAdj, adj, "adj"); |
825 | |
826 | return Builder.CreateInsertValue(src, dstAdj, 1); |
827 | } |
828 | |
829 | llvm::Constant * |
830 | ItaniumCXXABI::EmitMemberPointerConversion(const CastExpr *E, |
831 | llvm::Constant *src) { |
832 | getCastKind() == CK_DerivedToBaseMemberPointer || E->getCastKind() == CK_BaseToDerivedMemberPointer || E->getCastKind() == CK_ReinterpretMemberPointer", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 834, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || |
833 | getCastKind() == CK_DerivedToBaseMemberPointer || E->getCastKind() == CK_BaseToDerivedMemberPointer || E->getCastKind() == CK_ReinterpretMemberPointer", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 834, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> E->getCastKind() == CK_BaseToDerivedMemberPointer || |
834 | getCastKind() == CK_DerivedToBaseMemberPointer || E->getCastKind() == CK_BaseToDerivedMemberPointer || E->getCastKind() == CK_ReinterpretMemberPointer", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 834, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> E->getCastKind() == CK_ReinterpretMemberPointer); |
835 | |
836 | |
837 | if (E->getCastKind() == CK_ReinterpretMemberPointer) return src; |
838 | |
839 | |
840 | llvm::Constant *adj = getMemberPointerAdjustment(E); |
841 | if (!adj) return src; |
842 | |
843 | bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer); |
844 | |
845 | const MemberPointerType *destTy = |
846 | E->getType()->castAs<MemberPointerType>(); |
847 | |
848 | |
849 | |
850 | if (destTy->isMemberDataPointer()) { |
851 | |
852 | if (src->isAllOnesValue()) return src; |
853 | |
854 | if (isDerivedToBase) |
855 | return llvm::ConstantExpr::getNSWSub(src, adj); |
856 | else |
857 | return llvm::ConstantExpr::getNSWAdd(src, adj); |
858 | } |
859 | |
860 | |
861 | if (UseARMMethodPtrABI) { |
862 | uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue(); |
863 | offset <<= 1; |
864 | adj = llvm::ConstantInt::get(adj->getType(), offset); |
865 | } |
866 | |
867 | llvm::Constant *srcAdj = llvm::ConstantExpr::getExtractValue(src, 1); |
868 | llvm::Constant *dstAdj; |
869 | if (isDerivedToBase) |
870 | dstAdj = llvm::ConstantExpr::getNSWSub(srcAdj, adj); |
871 | else |
872 | dstAdj = llvm::ConstantExpr::getNSWAdd(srcAdj, adj); |
873 | |
874 | return llvm::ConstantExpr::getInsertValue(src, dstAdj, 1); |
875 | } |
876 | |
877 | llvm::Constant * |
878 | ItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { |
879 | |
880 | |
881 | if (MPT->isMemberDataPointer()) |
882 | return llvm::ConstantInt::get(CGM.PtrDiffTy, -1ULL, ); |
883 | |
884 | llvm::Constant *Zero = llvm::ConstantInt::get(CGM.PtrDiffTy, 0); |
885 | llvm::Constant *Values[2] = { Zero, Zero }; |
886 | return llvm::ConstantStruct::getAnon(Values); |
887 | } |
888 | |
889 | llvm::Constant * |
890 | ItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, |
891 | CharUnits offset) { |
892 | |
893 | |
894 | |
895 | return llvm::ConstantInt::get(CGM.PtrDiffTy, offset.getQuantity()); |
896 | } |
897 | |
898 | llvm::Constant * |
899 | ItaniumCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { |
900 | return BuildMemberPointer(MD, CharUnits::Zero()); |
901 | } |
902 | |
903 | llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD, |
904 | CharUnits ThisAdjustment) { |
905 | (0) . __assert_fail ("MD->isInstance() && \"Member function must not be static!\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 905, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(MD->isInstance() && "Member function must not be static!"); |
906 | |
907 | CodeGenTypes &Types = CGM.getTypes(); |
908 | |
909 | |
910 | llvm::Constant *MemPtr[2]; |
911 | if (MD->isVirtual()) { |
912 | uint64_t Index = CGM.getItaniumVTableContext().getMethodVTableIndex(MD); |
913 | |
914 | const ASTContext &Context = getContext(); |
915 | CharUnits PointerWidth = |
916 | Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); |
917 | uint64_t VTableOffset = (Index * PointerWidth.getQuantity()); |
918 | |
919 | if (UseARMMethodPtrABI) { |
920 | |
921 | |
922 | |
923 | |
924 | |
925 | |
926 | MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset); |
927 | MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy, |
928 | 2 * ThisAdjustment.getQuantity() + 1); |
929 | } else { |
930 | |
931 | |
932 | |
933 | |
934 | MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset + 1); |
935 | MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy, |
936 | ThisAdjustment.getQuantity()); |
937 | } |
938 | } else { |
939 | const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); |
940 | llvm::Type *Ty; |
941 | |
942 | if (Types.isFuncTypeConvertible(FPT)) { |
943 | |
944 | Ty = Types.GetFunctionType(Types.arrangeCXXMethodDeclaration(MD)); |
945 | } else { |
946 | |
947 | |
948 | Ty = CGM.PtrDiffTy; |
949 | } |
950 | llvm::Constant *addr = CGM.GetAddrOfFunction(MD, Ty); |
951 | |
952 | MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, CGM.PtrDiffTy); |
953 | MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy, |
954 | (UseARMMethodPtrABI ? 2 : 1) * |
955 | ThisAdjustment.getQuantity()); |
956 | } |
957 | |
958 | return llvm::ConstantStruct::getAnon(MemPtr); |
959 | } |
960 | |
961 | llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP, |
962 | QualType MPType) { |
963 | const MemberPointerType *MPT = MPType->castAs<MemberPointerType>(); |
964 | const ValueDecl *MPD = MP.getMemberPointerDecl(); |
965 | if (!MPD) |
966 | return EmitNullMemberPointer(MPT); |
967 | |
968 | CharUnits ThisAdjustment = getMemberPointerPathAdjustment(MP); |
969 | |
970 | if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) |
971 | return BuildMemberPointer(MD, ThisAdjustment); |
972 | |
973 | CharUnits FieldOffset = |
974 | getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD)); |
975 | return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset); |
976 | } |
977 | |
978 | |
979 | |
980 | |
981 | |
982 | llvm::Value * |
983 | ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF, |
984 | llvm::Value *L, |
985 | llvm::Value *R, |
986 | const MemberPointerType *MPT, |
987 | bool Inequality) { |
988 | CGBuilderTy &Builder = CGF.Builder; |
989 | |
990 | llvm::ICmpInst::Predicate Eq; |
991 | llvm::Instruction::BinaryOps And, Or; |
992 | if (Inequality) { |
993 | Eq = llvm::ICmpInst::ICMP_NE; |
994 | And = llvm::Instruction::Or; |
995 | Or = llvm::Instruction::And; |
996 | } else { |
997 | Eq = llvm::ICmpInst::ICMP_EQ; |
998 | And = llvm::Instruction::And; |
999 | Or = llvm::Instruction::Or; |
1000 | } |
1001 | |
1002 | |
1003 | |
1004 | if (MPT->isMemberDataPointer()) |
1005 | return Builder.CreateICmp(Eq, L, R); |
1006 | |
1007 | |
1008 | |
1009 | |
1010 | |
1011 | |
1012 | |
1013 | |
1014 | |
1015 | |
1016 | |
1017 | llvm::Value *LPtr = Builder.CreateExtractValue(L, 0, "lhs.memptr.ptr"); |
1018 | llvm::Value *RPtr = Builder.CreateExtractValue(R, 0, "rhs.memptr.ptr"); |
1019 | |
1020 | |
1021 | |
1022 | llvm::Value *PtrEq = Builder.CreateICmp(Eq, LPtr, RPtr, "cmp.ptr"); |
1023 | |
1024 | |
1025 | |
1026 | |
1027 | llvm::Value *Zero = llvm::Constant::getNullValue(LPtr->getType()); |
1028 | llvm::Value *EqZero = Builder.CreateICmp(Eq, LPtr, Zero, "cmp.ptr.null"); |
1029 | |
1030 | |
1031 | |
1032 | llvm::Value *LAdj = Builder.CreateExtractValue(L, 1, "lhs.memptr.adj"); |
1033 | llvm::Value *RAdj = Builder.CreateExtractValue(R, 1, "rhs.memptr.adj"); |
1034 | llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj, "cmp.adj"); |
1035 | |
1036 | |
1037 | |
1038 | if (UseARMMethodPtrABI) { |
1039 | llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1); |
1040 | |
1041 | |
1042 | llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj, "or.adj"); |
1043 | llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One); |
1044 | llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1, Zero, |
1045 | "cmp.or.adj"); |
1046 | EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero); |
1047 | } |
1048 | |
1049 | |
1050 | llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq); |
1051 | Result = Builder.CreateBinOp(And, PtrEq, Result, |
1052 | Inequality ? "memptr.ne" : "memptr.eq"); |
1053 | return Result; |
1054 | } |
1055 | |
1056 | llvm::Value * |
1057 | ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF, |
1058 | llvm::Value *MemPtr, |
1059 | const MemberPointerType *MPT) { |
1060 | CGBuilderTy &Builder = CGF.Builder; |
1061 | |
1062 | |
1063 | if (MPT->isMemberDataPointer()) { |
1064 | getType() == CGM.PtrDiffTy", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 1064, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(MemPtr->getType() == CGM.PtrDiffTy); |
1065 | llvm::Value *NegativeOne = |
1066 | llvm::Constant::getAllOnesValue(MemPtr->getType()); |
1067 | return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool"); |
1068 | } |
1069 | |
1070 | |
1071 | llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0, "memptr.ptr"); |
1072 | |
1073 | llvm::Constant *Zero = llvm::ConstantInt::get(Ptr->getType(), 0); |
1074 | llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero, "memptr.tobool"); |
1075 | |
1076 | |
1077 | |
1078 | if (UseARMMethodPtrABI) { |
1079 | llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1); |
1080 | llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj"); |
1081 | llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit"); |
1082 | llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit, Zero, |
1083 | "memptr.isvirtual"); |
1084 | Result = Builder.CreateOr(Result, IsVirtual); |
1085 | } |
1086 | |
1087 | return Result; |
1088 | } |
1089 | |
1090 | bool ItaniumCXXABI::classifyReturnType(CGFunctionInfo &FI) const { |
1091 | const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl(); |
1092 | if (!RD) |
1093 | return false; |
1094 | |
1095 | |
1096 | if (passClassIndirect(RD)) { |
1097 | auto Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType()); |
1098 | FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, ); |
1099 | return true; |
1100 | } |
1101 | return false; |
1102 | } |
1103 | |
1104 | |
1105 | |
1106 | bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) { |
1107 | return MPT->isMemberFunctionPointer(); |
1108 | } |
1109 | |
1110 | |
1111 | |
1112 | void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, |
1113 | const CXXDeleteExpr *DE, |
1114 | Address Ptr, |
1115 | QualType ElementType, |
1116 | const CXXDestructorDecl *Dtor) { |
1117 | bool UseGlobalDelete = DE->isGlobalDelete(); |
1118 | if (UseGlobalDelete) { |
1119 | |
1120 | |
1121 | |
1122 | |
1123 | auto *ClassDecl = |
1124 | cast<CXXRecordDecl>(ElementType->getAs<RecordType>()->getDecl()); |
1125 | llvm::Value *VTable = |
1126 | CGF.GetVTablePtr(Ptr, CGF.IntPtrTy->getPointerTo(), ClassDecl); |
1127 | |
1128 | |
1129 | llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64( |
1130 | VTable, -2, "complete-offset.ptr"); |
1131 | llvm::Value *Offset = |
1132 | CGF.Builder.CreateAlignedLoad(OffsetPtr, CGF.getPointerAlign()); |
1133 | |
1134 | |
1135 | llvm::Value *CompletePtr = |
1136 | CGF.Builder.CreateBitCast(Ptr.getPointer(), CGF.Int8PtrTy); |
1137 | CompletePtr = CGF.Builder.CreateInBoundsGEP(CompletePtr, Offset); |
1138 | |
1139 | |
1140 | |
1141 | CGF.pushCallObjectDeleteCleanup(DE->getOperatorDelete(), CompletePtr, |
1142 | ElementType); |
1143 | } |
1144 | |
1145 | |
1146 | |
1147 | CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting; |
1148 | EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, ); |
1149 | |
1150 | if (UseGlobalDelete) |
1151 | CGF.PopCleanupBlock(); |
1152 | } |
1153 | |
1154 | void ItaniumCXXABI::emitRethrow(CodeGenFunction &CGF, bool isNoReturn) { |
1155 | |
1156 | |
1157 | llvm::FunctionType *FTy = |
1158 | llvm::FunctionType::get(CGM.VoidTy, ); |
1159 | |
1160 | llvm::FunctionCallee Fn = CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow"); |
1161 | |
1162 | if (isNoReturn) |
1163 | CGF.EmitNoreturnRuntimeCallOrInvoke(Fn, None); |
1164 | else |
1165 | CGF.EmitRuntimeCallOrInvoke(Fn); |
1166 | } |
1167 | |
1168 | static llvm::FunctionCallee getAllocateExceptionFn(CodeGenModule &CGM) { |
1169 | |
1170 | |
1171 | llvm::FunctionType *FTy = |
1172 | llvm::FunctionType::get(CGM.Int8PtrTy, CGM.SizeTy, ); |
1173 | |
1174 | return CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception"); |
1175 | } |
1176 | |
1177 | static llvm::FunctionCallee getThrowFn(CodeGenModule &CGM) { |
1178 | |
1179 | |
1180 | |
1181 | llvm::Type *Args[3] = { CGM.Int8PtrTy, CGM.Int8PtrTy, CGM.Int8PtrTy }; |
1182 | llvm::FunctionType *FTy = |
1183 | llvm::FunctionType::get(CGM.VoidTy, Args, ); |
1184 | |
1185 | return CGM.CreateRuntimeFunction(FTy, "__cxa_throw"); |
1186 | } |
1187 | |
1188 | void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) { |
1189 | QualType ThrowType = E->getSubExpr()->getType(); |
1190 | |
1191 | llvm::Type *SizeTy = CGF.ConvertType(getContext().getSizeType()); |
1192 | uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity(); |
1193 | |
1194 | llvm::FunctionCallee AllocExceptionFn = getAllocateExceptionFn(CGM); |
1195 | llvm::CallInst *ExceptionPtr = CGF.EmitNounwindRuntimeCall( |
1196 | AllocExceptionFn, llvm::ConstantInt::get(SizeTy, TypeSize), "exception"); |
1197 | |
1198 | CharUnits ExnAlign = getAlignmentOfExnObject(); |
1199 | CGF.EmitAnyExprToExn(E->getSubExpr(), Address(ExceptionPtr, ExnAlign)); |
1200 | |
1201 | |
1202 | llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType, |
1203 | ); |
1204 | |
1205 | |
1206 | |
1207 | llvm::Constant *Dtor = nullptr; |
1208 | if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) { |
1209 | CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl()); |
1210 | if (!Record->hasTrivialDestructor()) { |
1211 | CXXDestructorDecl *DtorD = Record->getDestructor(); |
1212 | Dtor = CGM.getAddrOfCXXStructor(GlobalDecl(DtorD, Dtor_Complete)); |
1213 | Dtor = llvm::ConstantExpr::getBitCast(Dtor, CGM.Int8PtrTy); |
1214 | } |
1215 | } |
1216 | if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy); |
1217 | |
1218 | llvm::Value *args[] = { ExceptionPtr, TypeInfo, Dtor }; |
1219 | CGF.EmitNoreturnRuntimeCallOrInvoke(getThrowFn(CGM), args); |
1220 | } |
1221 | |
1222 | static llvm::FunctionCallee getItaniumDynamicCastFn(CodeGenFunction &CGF) { |
1223 | |
1224 | |
1225 | |
1226 | |
1227 | |
1228 | llvm::Type *Int8PtrTy = CGF.Int8PtrTy; |
1229 | llvm::Type *PtrDiffTy = |
1230 | CGF.ConvertType(CGF.getContext().getPointerDiffType()); |
1231 | |
1232 | llvm::Type *Args[4] = { Int8PtrTy, Int8PtrTy, Int8PtrTy, PtrDiffTy }; |
1233 | |
1234 | llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false); |
1235 | |
1236 | |
1237 | llvm::Attribute::AttrKind FuncAttrs[] = { llvm::Attribute::NoUnwind, |
1238 | llvm::Attribute::ReadOnly }; |
1239 | llvm::AttributeList Attrs = llvm::AttributeList::get( |
1240 | CGF.getLLVMContext(), llvm::AttributeList::FunctionIndex, FuncAttrs); |
1241 | |
1242 | return CGF.CGM.CreateRuntimeFunction(FTy, "__dynamic_cast", Attrs); |
1243 | } |
1244 | |
1245 | static llvm::FunctionCallee getBadCastFn(CodeGenFunction &CGF) { |
1246 | |
1247 | llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false); |
1248 | return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_cast"); |
1249 | } |
1250 | |
1251 | |
1252 | |
1253 | static CharUnits computeOffsetHint(ASTContext &Context, |
1254 | const CXXRecordDecl *Src, |
1255 | const CXXRecordDecl *Dst) { |
1256 | CXXBasePaths Paths(, , |
1257 | ); |
1258 | |
1259 | |
1260 | |
1261 | if (!Dst->isDerivedFrom(Src, Paths)) |
1262 | return CharUnits::fromQuantity(-2ULL); |
1263 | |
1264 | unsigned NumPublicPaths = 0; |
1265 | CharUnits Offset; |
1266 | |
1267 | |
1268 | for (const CXXBasePath &Path : Paths) { |
1269 | if (Path.Access != AS_public) |
1270 | continue; |
1271 | |
1272 | ++NumPublicPaths; |
1273 | |
1274 | for (const CXXBasePathElement &PathElement : Path) { |
1275 | |
1276 | |
1277 | if (PathElement.Base->isVirtual()) |
1278 | return CharUnits::fromQuantity(-1ULL); |
1279 | |
1280 | if (NumPublicPaths > 1) |
1281 | continue; |
1282 | |
1283 | |
1284 | const ASTRecordLayout &L = Context.getASTRecordLayout(PathElement.Class); |
1285 | Offset += L.getBaseClassOffset( |
1286 | PathElement.Base->getType()->getAsCXXRecordDecl()); |
1287 | } |
1288 | } |
1289 | |
1290 | |
1291 | if (NumPublicPaths == 0) |
1292 | return CharUnits::fromQuantity(-2ULL); |
1293 | |
1294 | |
1295 | if (NumPublicPaths > 1) |
1296 | return CharUnits::fromQuantity(-3ULL); |
1297 | |
1298 | |
1299 | |
1300 | return Offset; |
1301 | } |
1302 | |
1303 | static llvm::FunctionCallee getBadTypeidFn(CodeGenFunction &CGF) { |
1304 | |
1305 | llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false); |
1306 | |
1307 | return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid"); |
1308 | } |
1309 | |
1310 | bool ItaniumCXXABI::shouldTypeidBeNullChecked(bool IsDeref, |
1311 | QualType SrcRecordTy) { |
1312 | return IsDeref; |
1313 | } |
1314 | |
1315 | void ItaniumCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) { |
1316 | llvm::FunctionCallee Fn = getBadTypeidFn(CGF); |
1317 | llvm::CallBase *Call = CGF.EmitRuntimeCallOrInvoke(Fn); |
1318 | Call->setDoesNotReturn(); |
1319 | CGF.Builder.CreateUnreachable(); |
1320 | } |
1321 | |
1322 | llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF, |
1323 | QualType SrcRecordTy, |
1324 | Address ThisPtr, |
1325 | llvm::Type *StdTypeInfoPtrTy) { |
1326 | auto *ClassDecl = |
1327 | cast<CXXRecordDecl>(SrcRecordTy->getAs<RecordType>()->getDecl()); |
1328 | llvm::Value *Value = |
1329 | CGF.GetVTablePtr(ThisPtr, StdTypeInfoPtrTy->getPointerTo(), ClassDecl); |
1330 | |
1331 | |
1332 | Value = CGF.Builder.CreateConstInBoundsGEP1_64(Value, -1ULL); |
1333 | return CGF.Builder.CreateAlignedLoad(Value, CGF.getPointerAlign()); |
1334 | } |
1335 | |
1336 | bool ItaniumCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr, |
1337 | QualType SrcRecordTy) { |
1338 | return SrcIsPtr; |
1339 | } |
1340 | |
1341 | llvm::Value *ItaniumCXXABI::EmitDynamicCastCall( |
1342 | CodeGenFunction &CGF, Address ThisAddr, QualType SrcRecordTy, |
1343 | QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd) { |
1344 | llvm::Type *PtrDiffLTy = |
1345 | CGF.ConvertType(CGF.getContext().getPointerDiffType()); |
1346 | llvm::Type *DestLTy = CGF.ConvertType(DestTy); |
1347 | |
1348 | llvm::Value *SrcRTTI = |
1349 | CGF.CGM.GetAddrOfRTTIDescriptor(SrcRecordTy.getUnqualifiedType()); |
1350 | llvm::Value *DestRTTI = |
1351 | CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType()); |
1352 | |
1353 | |
1354 | const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl(); |
1355 | const CXXRecordDecl *DestDecl = DestRecordTy->getAsCXXRecordDecl(); |
1356 | llvm::Value *OffsetHint = llvm::ConstantInt::get( |
1357 | PtrDiffLTy, |
1358 | computeOffsetHint(CGF.getContext(), SrcDecl, DestDecl).getQuantity()); |
1359 | |
1360 | |
1361 | llvm::Value *Value = ThisAddr.getPointer(); |
1362 | Value = CGF.EmitCastToVoidPtr(Value); |
1363 | |
1364 | llvm::Value *args[] = {Value, SrcRTTI, DestRTTI, OffsetHint}; |
1365 | Value = CGF.EmitNounwindRuntimeCall(getItaniumDynamicCastFn(CGF), args); |
1366 | Value = CGF.Builder.CreateBitCast(Value, DestLTy); |
1367 | |
1368 | |
1369 | |
1370 | if (DestTy->isReferenceType()) { |
1371 | llvm::BasicBlock *BadCastBlock = |
1372 | CGF.createBasicBlock("dynamic_cast.bad_cast"); |
1373 | |
1374 | llvm::Value *IsNull = CGF.Builder.CreateIsNull(Value); |
1375 | CGF.Builder.CreateCondBr(IsNull, BadCastBlock, CastEnd); |
1376 | |
1377 | CGF.EmitBlock(BadCastBlock); |
1378 | EmitBadCastCall(CGF); |
1379 | } |
1380 | |
1381 | return Value; |
1382 | } |
1383 | |
1384 | llvm::Value *ItaniumCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF, |
1385 | Address ThisAddr, |
1386 | QualType SrcRecordTy, |
1387 | QualType DestTy) { |
1388 | llvm::Type *PtrDiffLTy = |
1389 | CGF.ConvertType(CGF.getContext().getPointerDiffType()); |
1390 | llvm::Type *DestLTy = CGF.ConvertType(DestTy); |
1391 | |
1392 | auto *ClassDecl = |
1393 | cast<CXXRecordDecl>(SrcRecordTy->getAs<RecordType>()->getDecl()); |
1394 | |
1395 | llvm::Value *VTable = CGF.GetVTablePtr(ThisAddr, PtrDiffLTy->getPointerTo(), |
1396 | ClassDecl); |
1397 | |
1398 | |
1399 | llvm::Value *OffsetToTop = |
1400 | CGF.Builder.CreateConstInBoundsGEP1_64(VTable, -2ULL); |
1401 | OffsetToTop = |
1402 | CGF.Builder.CreateAlignedLoad(OffsetToTop, CGF.getPointerAlign(), |
1403 | "offset.to.top"); |
1404 | |
1405 | |
1406 | llvm::Value *Value = ThisAddr.getPointer(); |
1407 | Value = CGF.EmitCastToVoidPtr(Value); |
1408 | Value = CGF.Builder.CreateInBoundsGEP(Value, OffsetToTop); |
1409 | |
1410 | return CGF.Builder.CreateBitCast(Value, DestLTy); |
1411 | } |
1412 | |
1413 | bool ItaniumCXXABI::EmitBadCastCall(CodeGenFunction &CGF) { |
1414 | llvm::FunctionCallee Fn = getBadCastFn(CGF); |
1415 | llvm::CallBase *Call = CGF.EmitRuntimeCallOrInvoke(Fn); |
1416 | Call->setDoesNotReturn(); |
1417 | CGF.Builder.CreateUnreachable(); |
1418 | return true; |
1419 | } |
1420 | |
1421 | llvm::Value * |
1422 | ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF, |
1423 | Address This, |
1424 | const CXXRecordDecl *ClassDecl, |
1425 | const CXXRecordDecl *BaseClassDecl) { |
1426 | llvm::Value *VTablePtr = CGF.GetVTablePtr(This, CGM.Int8PtrTy, ClassDecl); |
1427 | CharUnits VBaseOffsetOffset = |
1428 | CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl, |
1429 | BaseClassDecl); |
1430 | |
1431 | llvm::Value *VBaseOffsetPtr = |
1432 | CGF.Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetOffset.getQuantity(), |
1433 | "vbase.offset.ptr"); |
1434 | VBaseOffsetPtr = CGF.Builder.CreateBitCast(VBaseOffsetPtr, |
1435 | CGM.PtrDiffTy->getPointerTo()); |
1436 | |
1437 | llvm::Value *VBaseOffset = |
1438 | CGF.Builder.CreateAlignedLoad(VBaseOffsetPtr, CGF.getPointerAlign(), |
1439 | "vbase.offset"); |
1440 | |
1441 | return VBaseOffset; |
1442 | } |
1443 | |
1444 | void ItaniumCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) { |
1445 | |
1446 | assert(CGM.getTarget().getCXXABI().hasConstructorVariants()); |
1447 | |
1448 | |
1449 | |
1450 | CGM.EmitGlobal(GlobalDecl(D, Ctor_Base)); |
1451 | |
1452 | |
1453 | |
1454 | if (!D->getParent()->isAbstract()) { |
1455 | |
1456 | CGM.EmitGlobal(GlobalDecl(D, Ctor_Complete)); |
1457 | } |
1458 | } |
1459 | |
1460 | CGCXXABI::AddedStructorArgs |
1461 | ItaniumCXXABI::buildStructorSignature(GlobalDecl GD, |
1462 | SmallVectorImpl<CanQualType> &ArgTys) { |
1463 | ASTContext &Context = getContext(); |
1464 | |
1465 | |
1466 | |
1467 | |
1468 | |
1469 | if ((isa<CXXConstructorDecl>(GD.getDecl()) ? GD.getCtorType() == Ctor_Base |
1470 | : GD.getDtorType() == Dtor_Base) && |
1471 | cast<CXXMethodDecl>(GD.getDecl())->getParent()->getNumVBases() != 0) { |
1472 | ArgTys.insert(ArgTys.begin() + 1, |
1473 | Context.getPointerType(Context.VoidPtrTy)); |
1474 | return AddedStructorArgs::prefix(1); |
1475 | } |
1476 | return AddedStructorArgs{}; |
1477 | } |
1478 | |
1479 | void ItaniumCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) { |
1480 | |
1481 | |
1482 | CGM.EmitGlobal(GlobalDecl(D, Dtor_Base)); |
1483 | |
1484 | |
1485 | |
1486 | CGM.EmitGlobal(GlobalDecl(D, Dtor_Complete)); |
1487 | |
1488 | |
1489 | |
1490 | |
1491 | if (D->isVirtual()) |
1492 | CGM.EmitGlobal(GlobalDecl(D, Dtor_Deleting)); |
1493 | } |
1494 | |
1495 | void ItaniumCXXABI::addImplicitStructorParams(CodeGenFunction &CGF, |
1496 | QualType &ResTy, |
1497 | FunctionArgList &Params) { |
1498 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); |
1499 | (MD) || isa(MD)", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 1499, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)); |
1500 | |
1501 | |
1502 | if (NeedsVTTParameter(CGF.CurGD)) { |
1503 | ASTContext &Context = getContext(); |
1504 | |
1505 | |
1506 | QualType T = Context.getPointerType(Context.VoidPtrTy); |
1507 | auto *VTTDecl = ImplicitParamDecl::Create( |
1508 | Context, , MD->getLocation(), &Context.Idents.get("vtt"), |
1509 | T, ImplicitParamDecl::CXXVTT); |
1510 | Params.insert(Params.begin() + 1, VTTDecl); |
1511 | getStructorImplicitParamDecl(CGF) = VTTDecl; |
1512 | } |
1513 | } |
1514 | |
1515 | void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { |
1516 | |
1517 | if (CGF.CurFuncDecl && CGF.CurFuncDecl->hasAttr<NakedAttr>()) |
1518 | return; |
1519 | |
1520 | |
1521 | |
1522 | setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF)); |
1523 | |
1524 | |
1525 | if (getStructorImplicitParamDecl(CGF)) { |
1526 | getStructorImplicitParamValue(CGF) = CGF.Builder.CreateLoad( |
1527 | CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)), "vtt"); |
1528 | } |
1529 | |
1530 | |
1531 | |
1532 | |
1533 | |
1534 | |
1535 | |
1536 | |
1537 | |
1538 | if (HasThisReturn(CGF.CurGD)) |
1539 | CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue); |
1540 | } |
1541 | |
1542 | CGCXXABI::AddedStructorArgs ItaniumCXXABI::addImplicitConstructorArgs( |
1543 | CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type, |
1544 | bool ForVirtualBase, bool Delegating, CallArgList &Args) { |
1545 | if (!NeedsVTTParameter(GlobalDecl(D, Type))) |
1546 | return AddedStructorArgs{}; |
1547 | |
1548 | |
1549 | llvm::Value *VTT = |
1550 | CGF.GetVTTParameter(GlobalDecl(D, Type), ForVirtualBase, Delegating); |
1551 | QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy); |
1552 | Args.insert(Args.begin() + 1, CallArg(RValue::get(VTT), VTTTy)); |
1553 | return AddedStructorArgs::prefix(1); |
1554 | } |
1555 | |
1556 | void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF, |
1557 | const CXXDestructorDecl *DD, |
1558 | CXXDtorType Type, bool ForVirtualBase, |
1559 | bool Delegating, Address This) { |
1560 | GlobalDecl GD(DD, Type); |
1561 | llvm::Value *VTT = CGF.GetVTTParameter(GD, ForVirtualBase, Delegating); |
1562 | QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy); |
1563 | |
1564 | CGCallee Callee; |
1565 | if (getContext().getLangOpts().AppleKext && |
1566 | Type != Dtor_Base && DD->isVirtual()) |
1567 | Callee = CGF.BuildAppleKextVirtualDestructorCall(DD, Type, DD->getParent()); |
1568 | else |
1569 | Callee = CGCallee::forDirect(CGM.getAddrOfCXXStructor(GD), GD); |
1570 | |
1571 | CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), VTT, VTTTy, nullptr); |
1572 | } |
1573 | |
1574 | void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, |
1575 | const CXXRecordDecl *RD) { |
1576 | llvm::GlobalVariable *VTable = getAddrOfVTable(RD, CharUnits()); |
1577 | if (VTable->hasInitializer()) |
1578 | return; |
1579 | |
1580 | ItaniumVTableContext &VTContext = CGM.getItaniumVTableContext(); |
1581 | const VTableLayout &VTLayout = VTContext.getVTableLayout(RD); |
1582 | llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD); |
1583 | llvm::Constant *RTTI = |
1584 | CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getTagDeclType(RD)); |
1585 | |
1586 | |
1587 | ConstantInitBuilder Builder(CGM); |
1588 | auto Components = Builder.beginStruct(); |
1589 | CGVT.createVTableInitializer(Components, VTLayout, RTTI); |
1590 | Components.finishAndSetAsInitializer(VTable); |
1591 | |
1592 | |
1593 | VTable->setLinkage(Linkage); |
1594 | |
1595 | if (CGM.supportsCOMDAT() && VTable->isWeakForLinker()) |
1596 | VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName())); |
1597 | |
1598 | |
1599 | CGM.setGVProperties(VTable, RD); |
1600 | |
1601 | |
1602 | |
1603 | |
1604 | const DeclContext *DC = RD->getDeclContext(); |
1605 | if (RD->getIdentifier() && |
1606 | RD->getIdentifier()->isStr("__fundamental_type_info") && |
1607 | isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() && |
1608 | cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") && |
1609 | DC->getParent()->isTranslationUnit()) |
1610 | EmitFundamentalRTTIDescriptors(RD); |
1611 | |
1612 | if (!VTable->isDeclarationForLinker()) |
1613 | CGM.EmitVTableTypeMetadata(VTable, VTLayout); |
1614 | } |
1615 | |
1616 | bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField( |
1617 | CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr) { |
1618 | if (Vptr.NearestVBase == nullptr) |
1619 | return false; |
1620 | return NeedsVTTParameter(CGF.CurGD); |
1621 | } |
1622 | |
1623 | llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor( |
1624 | CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, |
1625 | const CXXRecordDecl *NearestVBase) { |
1626 | |
1627 | if ((Base.getBase()->getNumVBases() || NearestVBase != nullptr) && |
1628 | NeedsVTTParameter(CGF.CurGD)) { |
1629 | return getVTableAddressPointInStructorWithVTT(CGF, VTableClass, Base, |
1630 | NearestVBase); |
1631 | } |
1632 | return getVTableAddressPoint(Base, VTableClass); |
1633 | } |
1634 | |
1635 | llvm::Constant * |
1636 | ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base, |
1637 | const CXXRecordDecl *VTableClass) { |
1638 | llvm::GlobalValue *VTable = getAddrOfVTable(VTableClass, CharUnits()); |
1639 | |
1640 | |
1641 | |
1642 | VTableLayout::AddressPointLocation AddressPoint = |
1643 | CGM.getItaniumVTableContext() |
1644 | .getVTableLayout(VTableClass) |
1645 | .getAddressPoint(Base); |
1646 | llvm::Value *Indices[] = { |
1647 | llvm::ConstantInt::get(CGM.Int32Ty, 0), |
1648 | llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.VTableIndex), |
1649 | llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.AddressPointIndex), |
1650 | }; |
1651 | |
1652 | return llvm::ConstantExpr::getGetElementPtr(VTable->getValueType(), VTable, |
1653 | Indices, , |
1654 | ); |
1655 | } |
1656 | |
1657 | llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT( |
1658 | CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, |
1659 | const CXXRecordDecl *NearestVBase) { |
1660 | (0) . __assert_fail ("(Base.getBase()->getNumVBases() || NearestVBase != nullptr) && NeedsVTTParameter(CGF.CurGD) && \"This class doesn't have VTT\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 1661, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert((Base.getBase()->getNumVBases() || NearestVBase != nullptr) && |
1661 | (0) . __assert_fail ("(Base.getBase()->getNumVBases() || NearestVBase != nullptr) && NeedsVTTParameter(CGF.CurGD) && \"This class doesn't have VTT\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 1661, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> NeedsVTTParameter(CGF.CurGD) && "This class doesn't have VTT"); |
1662 | |
1663 | |
1664 | uint64_t VirtualPointerIndex = |
1665 | CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass, Base); |
1666 | |
1667 | |
1668 | llvm::Value *VTT = CGF.LoadCXXVTT(); |
1669 | if (VirtualPointerIndex) |
1670 | VTT = CGF.Builder.CreateConstInBoundsGEP1_64(VTT, VirtualPointerIndex); |
1671 | |
1672 | |
1673 | return CGF.Builder.CreateAlignedLoad(VTT, CGF.getPointerAlign()); |
1674 | } |
1675 | |
1676 | llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr( |
1677 | BaseSubobject Base, const CXXRecordDecl *VTableClass) { |
1678 | return getVTableAddressPoint(Base, VTableClass); |
1679 | } |
1680 | |
1681 | llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, |
1682 | CharUnits VPtrOffset) { |
1683 | (0) . __assert_fail ("VPtrOffset.isZero() && \"Itanium ABI only supports zero vptr offsets\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 1683, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(VPtrOffset.isZero() && "Itanium ABI only supports zero vptr offsets"); |
1684 | |
1685 | llvm::GlobalVariable *&VTable = VTables[RD]; |
1686 | if (VTable) |
1687 | return VTable; |
1688 | |
1689 | |
1690 | CGM.addDeferredVTable(RD); |
1691 | |
1692 | SmallString<256> Name; |
1693 | llvm::raw_svector_ostream Out(Name); |
1694 | getMangleContext().mangleCXXVTable(RD, Out); |
1695 | |
1696 | const VTableLayout &VTLayout = |
1697 | CGM.getItaniumVTableContext().getVTableLayout(RD); |
1698 | llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout); |
1699 | |
1700 | |
1701 | |
1702 | |
1703 | unsigned PAlign = CGM.getTarget().getPointerAlign(0); |
1704 | |
1705 | VTable = CGM.CreateOrReplaceCXXRuntimeVariable( |
1706 | Name, VTableType, llvm::GlobalValue::ExternalLinkage, |
1707 | getContext().toCharUnitsFromBits(PAlign).getQuantity()); |
1708 | VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); |
1709 | |
1710 | CGM.setGVProperties(VTable, RD); |
1711 | |
1712 | return VTable; |
1713 | } |
1714 | |
1715 | CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, |
1716 | GlobalDecl GD, |
1717 | Address This, |
1718 | llvm::Type *Ty, |
1719 | SourceLocation Loc) { |
1720 | Ty = Ty->getPointerTo()->getPointerTo(); |
1721 | auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl()); |
1722 | llvm::Value *VTable = CGF.GetVTablePtr(This, Ty, MethodDecl->getParent()); |
1723 | |
1724 | uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD); |
1725 | llvm::Value *VFunc; |
1726 | if (CGF.ShouldEmitVTableTypeCheckedLoad(MethodDecl->getParent())) { |
1727 | VFunc = CGF.EmitVTableTypeCheckedLoad( |
1728 | MethodDecl->getParent(), VTable, |
1729 | VTableIndex * CGM.getContext().getTargetInfo().getPointerWidth(0) / 8); |
1730 | } else { |
1731 | CGF.EmitTypeMetadataCodeForVCall(MethodDecl->getParent(), VTable, Loc); |
1732 | |
1733 | llvm::Value *VFuncPtr = |
1734 | CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn"); |
1735 | auto *VFuncLoad = |
1736 | CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign()); |
1737 | |
1738 | |
1739 | |
1740 | |
1741 | |
1742 | |
1743 | |
1744 | if (CGM.getCodeGenOpts().OptimizationLevel > 0 && |
1745 | CGM.getCodeGenOpts().StrictVTablePointers) |
1746 | VFuncLoad->setMetadata( |
1747 | llvm::LLVMContext::MD_invariant_load, |
1748 | llvm::MDNode::get(CGM.getLLVMContext(), |
1749 | llvm::ArrayRef<llvm::Metadata *>())); |
1750 | VFunc = VFuncLoad; |
1751 | } |
1752 | |
1753 | CGCallee Callee(GD, VFunc); |
1754 | return Callee; |
1755 | } |
1756 | |
1757 | llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall( |
1758 | CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, |
1759 | Address This, const CXXMemberCallExpr *CE) { |
1760 | arg_begin() == CE->arg_end()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 1760, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(CE == nullptr || CE->arg_begin() == CE->arg_end()); |
1761 | assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete); |
1762 | |
1763 | GlobalDecl GD(Dtor, DtorType); |
1764 | const CGFunctionInfo *FInfo = |
1765 | &CGM.getTypes().arrangeCXXStructorDeclaration(GD); |
1766 | llvm::FunctionType *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo); |
1767 | CGCallee Callee = CGCallee::forVirtual(CE, GD, This, Ty); |
1768 | |
1769 | CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), nullptr, QualType(), |
1770 | nullptr); |
1771 | return nullptr; |
1772 | } |
1773 | |
1774 | void ItaniumCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) { |
1775 | CodeGenVTables &VTables = CGM.getVTables(); |
1776 | llvm::GlobalVariable *VTT = VTables.GetAddrOfVTT(RD); |
1777 | VTables.EmitVTTDefinition(VTT, CGM.getVTableLinkage(RD), RD); |
1778 | } |
1779 | |
1780 | bool ItaniumCXXABI::canSpeculativelyEmitVTableAsBaseClass( |
1781 | const CXXRecordDecl *RD) const { |
1782 | |
1783 | |
1784 | if (CGM.getLangOpts().AppleKext) |
1785 | return false; |
1786 | |
1787 | |
1788 | |
1789 | if (isVTableHidden(RD)) |
1790 | return false; |
1791 | |
1792 | if (CGM.getCodeGenOpts().ForceEmitVTables) |
1793 | return true; |
1794 | |
1795 | |
1796 | |
1797 | |
1798 | |
1799 | if (hasAnyUnusedVirtualInlineFunction(RD)) |
1800 | return false; |
1801 | |
1802 | |
1803 | |
1804 | |
1805 | |
1806 | if (RD->getNumVBases()) { |
1807 | for (const auto &B : RD->bases()) { |
1808 | auto *BRD = B.getType()->getAsCXXRecordDecl(); |
1809 | (0) . __assert_fail ("BRD && \"no class for base specifier\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 1809, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(BRD && "no class for base specifier"); |
1810 | if (B.isVirtual() || !BRD->isDynamicClass()) |
1811 | continue; |
1812 | if (!canSpeculativelyEmitVTableAsBaseClass(BRD)) |
1813 | return false; |
1814 | } |
1815 | } |
1816 | |
1817 | return true; |
1818 | } |
1819 | |
1820 | bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const { |
1821 | if (!canSpeculativelyEmitVTableAsBaseClass(RD)) |
1822 | return false; |
1823 | |
1824 | |
1825 | |
1826 | for (const auto &B : RD->vbases()) { |
1827 | auto *BRD = B.getType()->getAsCXXRecordDecl(); |
1828 | (0) . __assert_fail ("BRD && \"no class for base specifier\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 1828, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(BRD && "no class for base specifier"); |
1829 | if (!BRD->isDynamicClass()) |
1830 | continue; |
1831 | if (!canSpeculativelyEmitVTableAsBaseClass(BRD)) |
1832 | return false; |
1833 | } |
1834 | |
1835 | return true; |
1836 | } |
1837 | static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF, |
1838 | Address InitialPtr, |
1839 | int64_t NonVirtualAdjustment, |
1840 | int64_t VirtualAdjustment, |
1841 | bool IsReturnAdjustment) { |
1842 | if (!NonVirtualAdjustment && !VirtualAdjustment) |
1843 | return InitialPtr.getPointer(); |
1844 | |
1845 | Address V = CGF.Builder.CreateElementBitCast(InitialPtr, CGF.Int8Ty); |
1846 | |
1847 | |
1848 | if (NonVirtualAdjustment && !IsReturnAdjustment) { |
1849 | V = CGF.Builder.CreateConstInBoundsByteGEP(V, |
1850 | CharUnits::fromQuantity(NonVirtualAdjustment)); |
1851 | } |
1852 | |
1853 | |
1854 | llvm::Value *ResultPtr; |
1855 | if (VirtualAdjustment) { |
1856 | llvm::Type *PtrDiffTy = |
1857 | CGF.ConvertType(CGF.getContext().getPointerDiffType()); |
1858 | |
1859 | Address VTablePtrPtr = CGF.Builder.CreateElementBitCast(V, CGF.Int8PtrTy); |
1860 | llvm::Value *VTablePtr = CGF.Builder.CreateLoad(VTablePtrPtr); |
1861 | |
1862 | llvm::Value *OffsetPtr = |
1863 | CGF.Builder.CreateConstInBoundsGEP1_64(VTablePtr, VirtualAdjustment); |
1864 | |
1865 | OffsetPtr = CGF.Builder.CreateBitCast(OffsetPtr, PtrDiffTy->getPointerTo()); |
1866 | |
1867 | |
1868 | llvm::Value *Offset = |
1869 | CGF.Builder.CreateAlignedLoad(OffsetPtr, CGF.getPointerAlign()); |
1870 | |
1871 | |
1872 | ResultPtr = CGF.Builder.CreateInBoundsGEP(V.getPointer(), Offset); |
1873 | } else { |
1874 | ResultPtr = V.getPointer(); |
1875 | } |
1876 | |
1877 | |
1878 | |
1879 | if (NonVirtualAdjustment && IsReturnAdjustment) { |
1880 | ResultPtr = CGF.Builder.CreateConstInBoundsGEP1_64(ResultPtr, |
1881 | NonVirtualAdjustment); |
1882 | } |
1883 | |
1884 | |
1885 | return CGF.Builder.CreateBitCast(ResultPtr, InitialPtr.getType()); |
1886 | } |
1887 | |
1888 | llvm::Value *ItaniumCXXABI::performThisAdjustment(CodeGenFunction &CGF, |
1889 | Address This, |
1890 | const ThisAdjustment &TA) { |
1891 | return performTypeAdjustment(CGF, This, TA.NonVirtual, |
1892 | TA.Virtual.Itanium.VCallOffsetOffset, |
1893 | ); |
1894 | } |
1895 | |
1896 | llvm::Value * |
1897 | ItaniumCXXABI::performReturnAdjustment(CodeGenFunction &CGF, Address Ret, |
1898 | const ReturnAdjustment &RA) { |
1899 | return performTypeAdjustment(CGF, Ret, RA.NonVirtual, |
1900 | RA.Virtual.Itanium.VBaseOffsetOffset, |
1901 | ); |
1902 | } |
1903 | |
1904 | void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, |
1905 | RValue RV, QualType ResultType) { |
1906 | if (!isa<CXXDestructorDecl>(CGF.CurGD.getDecl())) |
1907 | return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType); |
1908 | |
1909 | |
1910 | llvm::Type *T = CGF.ReturnValue.getElementType(); |
1911 | RValue Undef = RValue::get(llvm::UndefValue::get(T)); |
1912 | return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType); |
1913 | } |
1914 | |
1915 | |
1916 | |
1917 | CharUnits ItaniumCXXABI::getArrayCookieSizeImpl(QualType elementType) { |
1918 | |
1919 | |
1920 | return std::max(CharUnits::fromQuantity(CGM.SizeSizeInBytes), |
1921 | CGM.getContext().getTypeAlignInChars(elementType)); |
1922 | } |
1923 | |
1924 | Address ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, |
1925 | Address NewPtr, |
1926 | llvm::Value *NumElements, |
1927 | const CXXNewExpr *expr, |
1928 | QualType ElementType) { |
1929 | assert(requiresArrayCookie(expr)); |
1930 | |
1931 | unsigned AS = NewPtr.getAddressSpace(); |
1932 | |
1933 | ASTContext &Ctx = getContext(); |
1934 | CharUnits SizeSize = CGF.getSizeSize(); |
1935 | |
1936 | |
1937 | CharUnits CookieSize = |
1938 | std::max(SizeSize, Ctx.getTypeAlignInChars(ElementType)); |
1939 | assert(CookieSize == getArrayCookieSizeImpl(ElementType)); |
1940 | |
1941 | |
1942 | Address CookiePtr = NewPtr; |
1943 | CharUnits CookieOffset = CookieSize - SizeSize; |
1944 | if (!CookieOffset.isZero()) |
1945 | CookiePtr = CGF.Builder.CreateConstInBoundsByteGEP(CookiePtr, CookieOffset); |
1946 | |
1947 | |
1948 | Address NumElementsPtr = |
1949 | CGF.Builder.CreateElementBitCast(CookiePtr, CGF.SizeTy); |
1950 | llvm::Instruction *SI = CGF.Builder.CreateStore(NumElements, NumElementsPtr); |
1951 | |
1952 | |
1953 | if (CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) && AS == 0 && |
1954 | (expr->getOperatorNew()->isReplaceableGlobalAllocationFunction() || |
1955 | CGM.getCodeGenOpts().SanitizeAddressPoisonCustomArrayCookie)) { |
1956 | |
1957 | CGM.getSanitizerMetadata()->disableSanitizerForInstruction(SI); |
1958 | llvm::FunctionType *FTy = |
1959 | llvm::FunctionType::get(CGM.VoidTy, NumElementsPtr.getType(), false); |
1960 | llvm::FunctionCallee F = |
1961 | CGM.CreateRuntimeFunction(FTy, "__asan_poison_cxx_array_cookie"); |
1962 | CGF.Builder.CreateCall(F, NumElementsPtr.getPointer()); |
1963 | } |
1964 | |
1965 | |
1966 | |
1967 | return CGF.Builder.CreateConstInBoundsByteGEP(NewPtr, CookieSize); |
1968 | } |
1969 | |
1970 | llvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, |
1971 | Address allocPtr, |
1972 | CharUnits cookieSize) { |
1973 | |
1974 | Address numElementsPtr = allocPtr; |
1975 | CharUnits numElementsOffset = cookieSize - CGF.getSizeSize(); |
1976 | if (!numElementsOffset.isZero()) |
1977 | numElementsPtr = |
1978 | CGF.Builder.CreateConstInBoundsByteGEP(numElementsPtr, numElementsOffset); |
1979 | |
1980 | unsigned AS = allocPtr.getAddressSpace(); |
1981 | numElementsPtr = CGF.Builder.CreateElementBitCast(numElementsPtr, CGF.SizeTy); |
1982 | if (!CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) || AS != 0) |
1983 | return CGF.Builder.CreateLoad(numElementsPtr); |
1984 | |
1985 | |
1986 | |
1987 | |
1988 | |
1989 | llvm::FunctionType *FTy = |
1990 | llvm::FunctionType::get(CGF.SizeTy, CGF.SizeTy->getPointerTo(0), false); |
1991 | llvm::FunctionCallee F = |
1992 | CGM.CreateRuntimeFunction(FTy, "__asan_load_cxx_array_cookie"); |
1993 | return CGF.Builder.CreateCall(F, numElementsPtr.getPointer()); |
1994 | } |
1995 | |
1996 | CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) { |
1997 | |
1998 | |
1999 | |
2000 | |
2001 | |
2002 | |
2003 | |
2004 | |
2005 | return std::max(CharUnits::fromQuantity(2 * CGM.SizeSizeInBytes), |
2006 | CGM.getContext().getTypeAlignInChars(elementType)); |
2007 | } |
2008 | |
2009 | Address ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, |
2010 | Address newPtr, |
2011 | llvm::Value *numElements, |
2012 | const CXXNewExpr *expr, |
2013 | QualType elementType) { |
2014 | assert(requiresArrayCookie(expr)); |
2015 | |
2016 | |
2017 | Address cookie = newPtr; |
2018 | |
2019 | |
2020 | cookie = CGF.Builder.CreateElementBitCast(cookie, CGF.SizeTy); |
2021 | llvm::Value *elementSize = llvm::ConstantInt::get(CGF.SizeTy, |
2022 | getContext().getTypeSizeInChars(elementType).getQuantity()); |
2023 | CGF.Builder.CreateStore(elementSize, cookie); |
2024 | |
2025 | |
2026 | cookie = CGF.Builder.CreateConstInBoundsGEP(cookie, 1); |
2027 | CGF.Builder.CreateStore(numElements, cookie); |
2028 | |
2029 | |
2030 | |
2031 | CharUnits cookieSize = ARMCXXABI::getArrayCookieSizeImpl(elementType); |
2032 | return CGF.Builder.CreateConstInBoundsByteGEP(newPtr, cookieSize); |
2033 | } |
2034 | |
2035 | llvm::Value *ARMCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, |
2036 | Address allocPtr, |
2037 | CharUnits cookieSize) { |
2038 | |
2039 | |
2040 | Address numElementsPtr |
2041 | = CGF.Builder.CreateConstInBoundsByteGEP(allocPtr, CGF.getSizeSize()); |
2042 | |
2043 | numElementsPtr = CGF.Builder.CreateElementBitCast(numElementsPtr, CGF.SizeTy); |
2044 | return CGF.Builder.CreateLoad(numElementsPtr); |
2045 | } |
2046 | |
2047 | |
2048 | |
2049 | static llvm::FunctionCallee getGuardAcquireFn(CodeGenModule &CGM, |
2050 | llvm::PointerType *GuardPtrTy) { |
2051 | |
2052 | llvm::FunctionType *FTy = |
2053 | llvm::FunctionType::get(CGM.getTypes().ConvertType(CGM.getContext().IntTy), |
2054 | GuardPtrTy, ); |
2055 | return CGM.CreateRuntimeFunction( |
2056 | FTy, "__cxa_guard_acquire", |
2057 | llvm::AttributeList::get(CGM.getLLVMContext(), |
2058 | llvm::AttributeList::FunctionIndex, |
2059 | llvm::Attribute::NoUnwind)); |
2060 | } |
2061 | |
2062 | static llvm::FunctionCallee getGuardReleaseFn(CodeGenModule &CGM, |
2063 | llvm::PointerType *GuardPtrTy) { |
2064 | |
2065 | llvm::FunctionType *FTy = |
2066 | llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, ); |
2067 | return CGM.CreateRuntimeFunction( |
2068 | FTy, "__cxa_guard_release", |
2069 | llvm::AttributeList::get(CGM.getLLVMContext(), |
2070 | llvm::AttributeList::FunctionIndex, |
2071 | llvm::Attribute::NoUnwind)); |
2072 | } |
2073 | |
2074 | static llvm::FunctionCallee getGuardAbortFn(CodeGenModule &CGM, |
2075 | llvm::PointerType *GuardPtrTy) { |
2076 | |
2077 | llvm::FunctionType *FTy = |
2078 | llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, ); |
2079 | return CGM.CreateRuntimeFunction( |
2080 | FTy, "__cxa_guard_abort", |
2081 | llvm::AttributeList::get(CGM.getLLVMContext(), |
2082 | llvm::AttributeList::FunctionIndex, |
2083 | llvm::Attribute::NoUnwind)); |
2084 | } |
2085 | |
2086 | namespace { |
2087 | struct CallGuardAbort final : EHScopeStack::Cleanup { |
2088 | llvm::GlobalVariable *Guard; |
2089 | CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {} |
2090 | |
2091 | void Emit(CodeGenFunction &CGF, Flags flags) override { |
2092 | CGF.EmitNounwindRuntimeCall(getGuardAbortFn(CGF.CGM, Guard->getType()), |
2093 | Guard); |
2094 | } |
2095 | }; |
2096 | } |
2097 | |
2098 | |
2099 | |
2100 | void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, |
2101 | const VarDecl &D, |
2102 | llvm::GlobalVariable *var, |
2103 | bool shouldPerformInit) { |
2104 | CGBuilderTy &Builder = CGF.Builder; |
2105 | |
2106 | |
2107 | |
2108 | bool NonTemplateInline = |
2109 | D.isInline() && |
2110 | !isTemplateInstantiation(D.getTemplateSpecializationKind()); |
2111 | |
2112 | |
2113 | |
2114 | |
2115 | bool threadsafe = getContext().getLangOpts().ThreadsafeStatics && |
2116 | (D.isLocalVarDecl() || NonTemplateInline) && |
2117 | !D.getTLSKind(); |
2118 | |
2119 | |
2120 | |
2121 | bool useInt8GuardVariable = !threadsafe && var->hasInternalLinkage(); |
2122 | |
2123 | llvm::IntegerType *guardTy; |
2124 | CharUnits guardAlignment; |
2125 | if (useInt8GuardVariable) { |
2126 | guardTy = CGF.Int8Ty; |
2127 | guardAlignment = CharUnits::One(); |
2128 | } else { |
2129 | |
2130 | |
2131 | if (UseARMGuardVarABI) { |
2132 | guardTy = CGF.SizeTy; |
2133 | guardAlignment = CGF.getSizeAlign(); |
2134 | } else { |
2135 | guardTy = CGF.Int64Ty; |
2136 | guardAlignment = CharUnits::fromQuantity( |
2137 | CGM.getDataLayout().getABITypeAlignment(guardTy)); |
2138 | } |
2139 | } |
2140 | llvm::PointerType *guardPtrTy = guardTy->getPointerTo(); |
2141 | |
2142 | |
2143 | |
2144 | llvm::GlobalVariable *guard = CGM.getStaticLocalDeclGuardAddress(&D); |
2145 | if (!guard) { |
2146 | |
2147 | SmallString<256> guardName; |
2148 | { |
2149 | llvm::raw_svector_ostream out(guardName); |
2150 | getMangleContext().mangleStaticGuardVariable(&D, out); |
2151 | } |
2152 | |
2153 | |
2154 | |
2155 | guard = new llvm::GlobalVariable(CGM.getModule(), guardTy, |
2156 | false, var->getLinkage(), |
2157 | llvm::ConstantInt::get(guardTy, 0), |
2158 | guardName.str()); |
2159 | guard->setDSOLocal(var->isDSOLocal()); |
2160 | guard->setVisibility(var->getVisibility()); |
2161 | |
2162 | guard->setThreadLocalMode(var->getThreadLocalMode()); |
2163 | guard->setAlignment(guardAlignment.getQuantity()); |
2164 | |
2165 | |
2166 | |
2167 | |
2168 | llvm::Comdat *C = var->getComdat(); |
2169 | if (!D.isLocalVarDecl() && C && |
2170 | (CGM.getTarget().getTriple().isOSBinFormatELF() || |
2171 | CGM.getTarget().getTriple().isOSBinFormatWasm())) { |
2172 | guard->setComdat(C); |
2173 | |
2174 | |
2175 | |
2176 | if (!NonTemplateInline) |
2177 | CGF.CurFn->setComdat(C); |
2178 | } else if (CGM.supportsCOMDAT() && guard->isWeakForLinker()) { |
2179 | guard->setComdat(CGM.getModule().getOrInsertComdat(guard->getName())); |
2180 | } |
2181 | |
2182 | CGM.setStaticLocalDeclGuardAddress(&D, guard); |
2183 | } |
2184 | |
2185 | Address guardAddr = Address(guard, guardAlignment); |
2186 | |
2187 | |
2188 | |
2189 | |
2190 | |
2191 | |
2192 | |
2193 | |
2194 | |
2195 | |
2196 | |
2197 | |
2198 | |
2199 | |
2200 | |
2201 | |
2202 | |
2203 | |
2204 | |
2205 | llvm::LoadInst *LI = |
2206 | Builder.CreateLoad(Builder.CreateElementBitCast(guardAddr, CGM.Int8Ty)); |
2207 | |
2208 | |
2209 | |
2210 | |
2211 | |
2212 | |
2213 | |
2214 | if (threadsafe) |
2215 | LI->setAtomic(llvm::AtomicOrdering::Acquire); |
2216 | |
2217 | |
2218 | |
2219 | |
2220 | |
2221 | |
2222 | |
2223 | |
2224 | |
2225 | |
2226 | |
2227 | |
2228 | |
2229 | |
2230 | |
2231 | |
2232 | |
2233 | |
2234 | |
2235 | |
2236 | |
2237 | llvm::Value *V = |
2238 | (UseARMGuardVarABI && !useInt8GuardVariable) |
2239 | ? Builder.CreateAnd(LI, llvm::ConstantInt::get(CGM.Int8Ty, 1)) |
2240 | : LI; |
2241 | llvm::Value *NeedsInit = Builder.CreateIsNull(V, "guard.uninitialized"); |
2242 | |
2243 | llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check"); |
2244 | llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end"); |
2245 | |
2246 | |
2247 | CGF.EmitCXXGuardedInitBranch(NeedsInit, InitCheckBlock, EndBlock, |
2248 | CodeGenFunction::GuardKind::VariableGuard, &D); |
2249 | |
2250 | CGF.EmitBlock(InitCheckBlock); |
2251 | |
2252 | |
2253 | if (threadsafe) { |
2254 | |
2255 | llvm::Value *V |
2256 | = CGF.EmitNounwindRuntimeCall(getGuardAcquireFn(CGM, guardPtrTy), guard); |
2257 | |
2258 | llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init"); |
2259 | |
2260 | Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"), |
2261 | InitBlock, EndBlock); |
2262 | |
2263 | |
2264 | CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, guard); |
2265 | |
2266 | CGF.EmitBlock(InitBlock); |
2267 | } |
2268 | |
2269 | |
2270 | CGF.EmitCXXGlobalVarDeclInit(D, var, shouldPerformInit); |
2271 | |
2272 | if (threadsafe) { |
2273 | |
2274 | CGF.PopCleanupBlock(); |
2275 | |
2276 | |
2277 | CGF.EmitNounwindRuntimeCall(getGuardReleaseFn(CGM, guardPtrTy), |
2278 | guardAddr.getPointer()); |
2279 | } else { |
2280 | Builder.CreateStore(llvm::ConstantInt::get(guardTy, 1), guardAddr); |
2281 | } |
2282 | |
2283 | CGF.EmitBlock(EndBlock); |
2284 | } |
2285 | |
2286 | |
2287 | static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF, |
2288 | llvm::FunctionCallee dtor, |
2289 | llvm::Constant *addr, bool TLS) { |
2290 | const char *Name = "__cxa_atexit"; |
2291 | if (TLS) { |
2292 | const llvm::Triple &T = CGF.getTarget().getTriple(); |
2293 | Name = T.isOSDarwin() ? "_tlv_atexit" : "__cxa_thread_atexit"; |
2294 | } |
2295 | |
2296 | |
2297 | |
2298 | |
2299 | llvm::Type *dtorTy = |
2300 | llvm::FunctionType::get(CGF.VoidTy, CGF.Int8PtrTy, false)->getPointerTo(); |
2301 | |
2302 | |
2303 | llvm::Type *paramTys[] = { dtorTy, CGF.Int8PtrTy, CGF.Int8PtrTy }; |
2304 | llvm::FunctionType *atexitTy = |
2305 | llvm::FunctionType::get(CGF.IntTy, paramTys, false); |
2306 | |
2307 | |
2308 | llvm::FunctionCallee atexit = CGF.CGM.CreateRuntimeFunction(atexitTy, Name); |
2309 | if (llvm::Function *fn = dyn_cast<llvm::Function>(atexit.getCallee())) |
2310 | fn->setDoesNotThrow(); |
2311 | |
2312 | |
2313 | llvm::Constant *handle = |
2314 | CGF.CGM.CreateRuntimeVariable(CGF.Int8Ty, "__dso_handle"); |
2315 | auto *GV = cast<llvm::GlobalValue>(handle->stripPointerCasts()); |
2316 | GV->setVisibility(llvm::GlobalValue::HiddenVisibility); |
2317 | |
2318 | if (!addr) |
2319 | |
2320 | |
2321 | |
2322 | |
2323 | addr = llvm::Constant::getNullValue(CGF.Int8PtrTy); |
2324 | |
2325 | llvm::Value *args[] = {llvm::ConstantExpr::getBitCast( |
2326 | cast<llvm::Constant>(dtor.getCallee()), dtorTy), |
2327 | llvm::ConstantExpr::getBitCast(addr, CGF.Int8PtrTy), |
2328 | handle}; |
2329 | CGF.EmitNounwindRuntimeCall(atexit, args); |
2330 | } |
2331 | |
2332 | void CodeGenModule::registerGlobalDtorsWithAtExit() { |
2333 | for (const auto I : DtorsUsingAtExit) { |
2334 | int Priority = I.first; |
2335 | const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second; |
2336 | |
2337 | |
2338 | |
2339 | |
2340 | |
2341 | |
2342 | |
2343 | |
2344 | CodeGenFunction CGF(*this); |
2345 | std::string GlobalInitFnName = |
2346 | std::string("__GLOBAL_init_") + llvm::to_string(Priority); |
2347 | llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); |
2348 | llvm::Function *GlobalInitFn = CreateGlobalInitOrDestructFunction( |
2349 | FTy, GlobalInitFnName, getTypes().arrangeNullaryFunction(), |
2350 | SourceLocation()); |
2351 | ASTContext &Ctx = getContext(); |
2352 | QualType ReturnTy = Ctx.VoidTy; |
2353 | QualType FunctionTy = Ctx.getFunctionType(ReturnTy, llvm::None, {}); |
2354 | FunctionDecl *FD = FunctionDecl::Create( |
2355 | Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), |
2356 | &Ctx.Idents.get(GlobalInitFnName), FunctionTy, nullptr, SC_Static, |
2357 | false, false); |
2358 | CGF.StartFunction(GlobalDecl(FD), ReturnTy, GlobalInitFn, |
2359 | getTypes().arrangeNullaryFunction(), FunctionArgList(), |
2360 | SourceLocation(), SourceLocation()); |
2361 | |
2362 | for (auto *Dtor : Dtors) { |
2363 | |
2364 | |
2365 | if (getCodeGenOpts().CXAAtExit) |
2366 | emitGlobalDtorWithCXAAtExit(CGF, Dtor, nullptr, false); |
2367 | else |
2368 | CGF.registerGlobalDtorWithAtExit(Dtor); |
2369 | } |
2370 | |
2371 | CGF.FinishFunction(); |
2372 | AddGlobalCtor(GlobalInitFn, Priority, nullptr); |
2373 | } |
2374 | } |
2375 | |
2376 | |
2377 | void ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, |
2378 | llvm::FunctionCallee dtor, |
2379 | llvm::Constant *addr) { |
2380 | if (D.isNoDestroy(CGM.getContext())) |
2381 | return; |
2382 | |
2383 | |
2384 | if (CGM.getCodeGenOpts().CXAAtExit) |
2385 | return emitGlobalDtorWithCXAAtExit(CGF, dtor, addr, D.getTLSKind()); |
2386 | |
2387 | if (D.getTLSKind()) |
2388 | CGM.ErrorUnsupported(&D, "non-trivial TLS destruction"); |
2389 | |
2390 | |
2391 | |
2392 | if (CGM.getLangOpts().AppleKext) { |
2393 | |
2394 | return CGM.AddCXXDtorEntry(dtor, addr); |
2395 | } |
2396 | |
2397 | CGF.registerGlobalDtorWithAtExit(D, dtor, addr); |
2398 | } |
2399 | |
2400 | static bool isThreadWrapperReplaceable(const VarDecl *VD, |
2401 | CodeGen::CodeGenModule &CGM) { |
2402 | (0) . __assert_fail ("!VD->isStaticLocal() && \"static local VarDecls don't need wrappers!\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 2402, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!VD->isStaticLocal() && "static local VarDecls don't need wrappers!"); |
2403 | |
2404 | |
2405 | return VD->getTLSKind() == VarDecl::TLS_Dynamic && |
2406 | CGM.getTarget().getTriple().isOSDarwin(); |
2407 | } |
2408 | |
2409 | |
2410 | |
2411 | |
2412 | static llvm::GlobalValue::LinkageTypes |
2413 | getThreadLocalWrapperLinkage(const VarDecl *VD, CodeGen::CodeGenModule &CGM) { |
2414 | llvm::GlobalValue::LinkageTypes VarLinkage = |
2415 | CGM.getLLVMLinkageVarDefinition(VD, ); |
2416 | |
2417 | |
2418 | if (llvm::GlobalValue::isLocalLinkage(VarLinkage)) |
2419 | return VarLinkage; |
2420 | |
2421 | |
2422 | if (isThreadWrapperReplaceable(VD, CGM)) |
2423 | if (!llvm::GlobalVariable::isLinkOnceLinkage(VarLinkage) && |
2424 | !llvm::GlobalVariable::isWeakODRLinkage(VarLinkage)) |
2425 | return VarLinkage; |
2426 | return llvm::GlobalValue::WeakODRLinkage; |
2427 | } |
2428 | |
2429 | llvm::Function * |
2430 | ItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD, |
2431 | llvm::Value *Val) { |
2432 | |
2433 | SmallString<256> WrapperName; |
2434 | { |
2435 | llvm::raw_svector_ostream Out(WrapperName); |
2436 | getMangleContext().mangleItaniumThreadLocalWrapper(VD, Out); |
2437 | } |
2438 | |
2439 | |
2440 | |
2441 | if (llvm::Value *V = CGM.getModule().getNamedValue(WrapperName)) |
2442 | return cast<llvm::Function>(V); |
2443 | |
2444 | QualType RetQT = VD->getType(); |
2445 | if (RetQT->isReferenceType()) |
2446 | RetQT = RetQT.getNonReferenceType(); |
2447 | |
2448 | const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( |
2449 | getContext().getPointerType(RetQT), FunctionArgList()); |
2450 | |
2451 | llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FI); |
2452 | llvm::Function *Wrapper = |
2453 | llvm::Function::Create(FnTy, getThreadLocalWrapperLinkage(VD, CGM), |
2454 | WrapperName.str(), &CGM.getModule()); |
2455 | |
2456 | CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Wrapper); |
2457 | |
2458 | if (VD->hasDefinition()) |
2459 | CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Wrapper); |
2460 | |
2461 | |
2462 | if (!Wrapper->hasLocalLinkage()) |
2463 | if (!isThreadWrapperReplaceable(VD, CGM) || |
2464 | llvm::GlobalVariable::isLinkOnceLinkage(Wrapper->getLinkage()) || |
2465 | llvm::GlobalVariable::isWeakODRLinkage(Wrapper->getLinkage()) || |
2466 | VD->getVisibility() == HiddenVisibility) |
2467 | Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility); |
2468 | |
2469 | if (isThreadWrapperReplaceable(VD, CGM)) { |
2470 | Wrapper->setCallingConv(llvm::CallingConv::CXX_FAST_TLS); |
2471 | Wrapper->addFnAttr(llvm::Attribute::NoUnwind); |
2472 | } |
2473 | return Wrapper; |
2474 | } |
2475 | |
2476 | void ItaniumCXXABI::EmitThreadLocalInitFuncs( |
2477 | CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals, |
2478 | ArrayRef<llvm::Function *> CXXThreadLocalInits, |
2479 | ArrayRef<const VarDecl *> CXXThreadLocalInitVars) { |
2480 | llvm::Function *InitFunc = nullptr; |
2481 | |
2482 | |
2483 | |
2484 | llvm::SmallVector<llvm::Function *, 8> OrderedInits; |
2485 | llvm::SmallDenseMap<const VarDecl *, llvm::Function *> UnorderedInits; |
2486 | for (unsigned I = 0; I != CXXThreadLocalInits.size(); ++I) { |
2487 | if (isTemplateInstantiation( |
2488 | CXXThreadLocalInitVars[I]->getTemplateSpecializationKind())) |
2489 | UnorderedInits[CXXThreadLocalInitVars[I]->getCanonicalDecl()] = |
2490 | CXXThreadLocalInits[I]; |
2491 | else |
2492 | OrderedInits.push_back(CXXThreadLocalInits[I]); |
2493 | } |
2494 | |
2495 | if (!OrderedInits.empty()) { |
2496 | |
2497 | llvm::FunctionType *FTy = |
2498 | llvm::FunctionType::get(CGM.VoidTy, ); |
2499 | const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); |
2500 | InitFunc = CGM.CreateGlobalInitOrDestructFunction(FTy, "__tls_init", FI, |
2501 | SourceLocation(), |
2502 | ); |
2503 | llvm::GlobalVariable *Guard = new llvm::GlobalVariable( |
2504 | CGM.getModule(), CGM.Int8Ty, , |
2505 | llvm::GlobalVariable::InternalLinkage, |
2506 | llvm::ConstantInt::get(CGM.Int8Ty, 0), "__tls_guard"); |
2507 | Guard->setThreadLocal(true); |
2508 | |
2509 | CharUnits GuardAlign = CharUnits::One(); |
2510 | Guard->setAlignment(GuardAlign.getQuantity()); |
2511 | |
2512 | CodeGenFunction(CGM).GenerateCXXGlobalInitFunc( |
2513 | InitFunc, OrderedInits, ConstantAddress(Guard, GuardAlign)); |
2514 | |
2515 | if (CGM.getTarget().getTriple().isOSDarwin()) { |
2516 | InitFunc->setCallingConv(llvm::CallingConv::CXX_FAST_TLS); |
2517 | InitFunc->addFnAttr(llvm::Attribute::NoUnwind); |
2518 | } |
2519 | } |
2520 | |
2521 | |
2522 | for (const VarDecl *VD : CXXThreadLocals) { |
2523 | llvm::GlobalVariable *Var = |
2524 | cast<llvm::GlobalVariable>(CGM.GetGlobalValue(CGM.getMangledName(VD))); |
2525 | llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Var); |
2526 | |
2527 | |
2528 | |
2529 | |
2530 | if (isThreadWrapperReplaceable(VD, CGM) && !VD->hasDefinition()) { |
2531 | Wrapper->setLinkage(llvm::Function::ExternalLinkage); |
2532 | continue; |
2533 | } |
2534 | |
2535 | |
2536 | SmallString<256> InitFnName; |
2537 | { |
2538 | llvm::raw_svector_ostream Out(InitFnName); |
2539 | getMangleContext().mangleItaniumThreadLocalInit(VD, Out); |
2540 | } |
2541 | |
2542 | llvm::FunctionType *InitFnTy = llvm::FunctionType::get(CGM.VoidTy, false); |
2543 | |
2544 | |
2545 | |
2546 | |
2547 | llvm::GlobalValue *Init = nullptr; |
2548 | bool InitIsInitFunc = false; |
2549 | if (VD->hasDefinition()) { |
2550 | InitIsInitFunc = true; |
2551 | llvm::Function *InitFuncToUse = InitFunc; |
2552 | if (isTemplateInstantiation(VD->getTemplateSpecializationKind())) |
2553 | InitFuncToUse = UnorderedInits.lookup(VD->getCanonicalDecl()); |
2554 | if (InitFuncToUse) |
2555 | Init = llvm::GlobalAlias::create(Var->getLinkage(), InitFnName.str(), |
2556 | InitFuncToUse); |
2557 | } else { |
2558 | |
2559 | |
2560 | |
2561 | |
2562 | Init = llvm::Function::Create(InitFnTy, |
2563 | llvm::GlobalVariable::ExternalWeakLinkage, |
2564 | InitFnName.str(), &CGM.getModule()); |
2565 | const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); |
2566 | CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, |
2567 | cast<llvm::Function>(Init)); |
2568 | } |
2569 | |
2570 | if (Init) { |
2571 | Init->setVisibility(Var->getVisibility()); |
2572 | Init->setDSOLocal(Var->isDSOLocal()); |
2573 | } |
2574 | |
2575 | llvm::LLVMContext &Context = CGM.getModule().getContext(); |
2576 | llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Wrapper); |
2577 | CGBuilderTy Builder(CGM, Entry); |
2578 | if (InitIsInitFunc) { |
2579 | if (Init) { |
2580 | llvm::CallInst *CallVal = Builder.CreateCall(InitFnTy, Init); |
2581 | if (isThreadWrapperReplaceable(VD, CGM)) { |
2582 | CallVal->setCallingConv(llvm::CallingConv::CXX_FAST_TLS); |
2583 | llvm::Function *Fn = |
2584 | cast<llvm::Function>(cast<llvm::GlobalAlias>(Init)->getAliasee()); |
2585 | Fn->setCallingConv(llvm::CallingConv::CXX_FAST_TLS); |
2586 | } |
2587 | } |
2588 | } else { |
2589 | |
2590 | llvm::Value *Have = Builder.CreateIsNotNull(Init); |
2591 | llvm::BasicBlock *InitBB = llvm::BasicBlock::Create(Context, "", Wrapper); |
2592 | llvm::BasicBlock *ExitBB = llvm::BasicBlock::Create(Context, "", Wrapper); |
2593 | Builder.CreateCondBr(Have, InitBB, ExitBB); |
2594 | |
2595 | Builder.SetInsertPoint(InitBB); |
2596 | Builder.CreateCall(InitFnTy, Init); |
2597 | Builder.CreateBr(ExitBB); |
2598 | |
2599 | Builder.SetInsertPoint(ExitBB); |
2600 | } |
2601 | |
2602 | |
2603 | |
2604 | llvm::Value *Val = Var; |
2605 | if (VD->getType()->isReferenceType()) { |
2606 | CharUnits Align = CGM.getContext().getDeclAlign(VD); |
2607 | Val = Builder.CreateAlignedLoad(Val, Align); |
2608 | } |
2609 | if (Val->getType() != Wrapper->getReturnType()) |
2610 | Val = Builder.CreatePointerBitCastOrAddrSpaceCast( |
2611 | Val, Wrapper->getReturnType(), ""); |
2612 | Builder.CreateRet(Val); |
2613 | } |
2614 | } |
2615 | |
2616 | LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, |
2617 | const VarDecl *VD, |
2618 | QualType LValType) { |
2619 | llvm::Value *Val = CGF.CGM.GetAddrOfGlobalVar(VD); |
2620 | llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Val); |
2621 | |
2622 | llvm::CallInst *CallVal = CGF.Builder.CreateCall(Wrapper); |
2623 | CallVal->setCallingConv(Wrapper->getCallingConv()); |
2624 | |
2625 | LValue LV; |
2626 | if (VD->getType()->isReferenceType()) |
2627 | LV = CGF.MakeNaturalAlignAddrLValue(CallVal, LValType); |
2628 | else |
2629 | LV = CGF.MakeAddrLValue(CallVal, LValType, |
2630 | CGF.getContext().getDeclAlign(VD)); |
2631 | |
2632 | return LV; |
2633 | } |
2634 | |
2635 | |
2636 | |
2637 | bool ItaniumCXXABI::NeedsVTTParameter(GlobalDecl GD) { |
2638 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); |
2639 | |
2640 | |
2641 | if (!MD->getParent()->getNumVBases()) |
2642 | return false; |
2643 | |
2644 | |
2645 | if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base) |
2646 | return true; |
2647 | |
2648 | |
2649 | if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base) |
2650 | return true; |
2651 | |
2652 | return false; |
2653 | } |
2654 | |
2655 | namespace { |
2656 | class ItaniumRTTIBuilder { |
2657 | CodeGenModule &CGM; |
2658 | llvm::LLVMContext &VMContext; |
2659 | const ItaniumCXXABI &CXXABI; |
2660 | |
2661 | |
2662 | SmallVector<llvm::Constant *, 16> Fields; |
2663 | |
2664 | |
2665 | llvm::GlobalVariable * |
2666 | GetAddrOfTypeName(QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage); |
2667 | |
2668 | |
2669 | |
2670 | llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty); |
2671 | |
2672 | |
2673 | void BuildVTablePointer(const Type *Ty); |
2674 | |
2675 | |
2676 | |
2677 | void BuildSIClassTypeInfo(const CXXRecordDecl *RD); |
2678 | |
2679 | |
2680 | |
2681 | |
2682 | void BuildVMIClassTypeInfo(const CXXRecordDecl *RD); |
2683 | |
2684 | |
2685 | |
2686 | void BuildPointerTypeInfo(QualType PointeeTy); |
2687 | |
2688 | |
2689 | |
2690 | void BuildObjCObjectTypeInfo(const ObjCObjectType *Ty); |
2691 | |
2692 | |
2693 | |
2694 | void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty); |
2695 | |
2696 | public: |
2697 | ItaniumRTTIBuilder(const ItaniumCXXABI &ABI) |
2698 | : CGM(ABI.CGM), VMContext(CGM.getModule().getContext()), CXXABI(ABI) {} |
2699 | |
2700 | |
2701 | enum { |
2702 | |
2703 | PTI_Const = 0x1, |
2704 | |
2705 | |
2706 | PTI_Volatile = 0x2, |
2707 | |
2708 | |
2709 | PTI_Restrict = 0x4, |
2710 | |
2711 | |
2712 | PTI_Incomplete = 0x8, |
2713 | |
2714 | |
2715 | |
2716 | PTI_ContainingClassIncomplete = 0x10, |
2717 | |
2718 | |
2719 | |
2720 | |
2721 | |
2722 | PTI_Noexcept = 0x40, |
2723 | }; |
2724 | |
2725 | |
2726 | enum { |
2727 | |
2728 | VMI_NonDiamondRepeat = 0x1, |
2729 | |
2730 | |
2731 | VMI_DiamondShaped = 0x2 |
2732 | }; |
2733 | |
2734 | |
2735 | enum { |
2736 | |
2737 | BCTI_Virtual = 0x1, |
2738 | |
2739 | |
2740 | BCTI_Public = 0x2 |
2741 | }; |
2742 | |
2743 | |
2744 | |
2745 | llvm::Constant *BuildTypeInfo(QualType Ty); |
2746 | |
2747 | |
2748 | llvm::Constant *BuildTypeInfo( |
2749 | QualType Ty, |
2750 | llvm::GlobalVariable::LinkageTypes Linkage, |
2751 | llvm::GlobalValue::VisibilityTypes Visibility, |
2752 | llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass); |
2753 | }; |
2754 | } |
2755 | |
2756 | llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName( |
2757 | QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage) { |
2758 | SmallString<256> Name; |
2759 | llvm::raw_svector_ostream Out(Name); |
2760 | CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out); |
2761 | |
2762 | |
2763 | |
2764 | |
2765 | llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext, |
2766 | Name.substr(4)); |
2767 | auto Align = CGM.getContext().getTypeAlignInChars(CGM.getContext().CharTy); |
2768 | |
2769 | llvm::GlobalVariable *GV = CGM.CreateOrReplaceCXXRuntimeVariable( |
2770 | Name, Init->getType(), Linkage, Align.getQuantity()); |
2771 | |
2772 | GV->setInitializer(Init); |
2773 | |
2774 | return GV; |
2775 | } |
2776 | |
2777 | llvm::Constant * |
2778 | ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) { |
2779 | |
2780 | SmallString<256> Name; |
2781 | llvm::raw_svector_ostream Out(Name); |
2782 | CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out); |
2783 | |
2784 | |
2785 | llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name); |
2786 | |
2787 | if (!GV) { |
2788 | |
2789 | |
2790 | |
2791 | |
2792 | GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy, |
2793 | , |
2794 | llvm::GlobalValue::ExternalLinkage, nullptr, |
2795 | Name); |
2796 | const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); |
2797 | CGM.setGVProperties(GV, RD); |
2798 | } |
2799 | |
2800 | return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy); |
2801 | } |
2802 | |
2803 | |
2804 | |
2805 | static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) { |
2806 | |
2807 | |
2808 | |
2809 | |
2810 | |
2811 | |
2812 | |
2813 | |
2814 | |
2815 | |
2816 | |
2817 | |
2818 | |
2819 | |
2820 | switch (Ty->getKind()) { |
2821 | case BuiltinType::Void: |
2822 | case BuiltinType::NullPtr: |
2823 | case BuiltinType::Bool: |
2824 | case BuiltinType::WChar_S: |
2825 | case BuiltinType::WChar_U: |
2826 | case BuiltinType::Char_U: |
2827 | case BuiltinType::Char_S: |
2828 | case BuiltinType::UChar: |
2829 | case BuiltinType::SChar: |
2830 | case BuiltinType::Short: |
2831 | case BuiltinType::UShort: |
2832 | case BuiltinType::Int: |
2833 | case BuiltinType::UInt: |
2834 | case BuiltinType::Long: |
2835 | case BuiltinType::ULong: |
2836 | case BuiltinType::LongLong: |
2837 | case BuiltinType::ULongLong: |
2838 | case BuiltinType::Half: |
2839 | case BuiltinType::Float: |
2840 | case BuiltinType::Double: |
2841 | case BuiltinType::LongDouble: |
2842 | case BuiltinType::Float16: |
2843 | case BuiltinType::Float128: |
2844 | case BuiltinType::Char8: |
2845 | case BuiltinType::Char16: |
2846 | case BuiltinType::Char32: |
2847 | case BuiltinType::Int128: |
2848 | case BuiltinType::UInt128: |
2849 | return true; |
2850 | |
2851 | #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ |
2852 | case BuiltinType::Id: |
2853 | #include "clang/Basic/OpenCLImageTypes.def" |
2854 | #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ |
2855 | case BuiltinType::Id: |
2856 | #include "clang/Basic/OpenCLExtensionTypes.def" |
2857 | case BuiltinType::OCLSampler: |
2858 | case BuiltinType::OCLEvent: |
2859 | case BuiltinType::OCLClkEvent: |
2860 | case BuiltinType::OCLQueue: |
2861 | case BuiltinType::OCLReserveID: |
2862 | case BuiltinType::ShortAccum: |
2863 | case BuiltinType::Accum: |
2864 | case BuiltinType::LongAccum: |
2865 | case BuiltinType::UShortAccum: |
2866 | case BuiltinType::UAccum: |
2867 | case BuiltinType::ULongAccum: |
2868 | case BuiltinType::ShortFract: |
2869 | case BuiltinType::Fract: |
2870 | case BuiltinType::LongFract: |
2871 | case BuiltinType::UShortFract: |
2872 | case BuiltinType::UFract: |
2873 | case BuiltinType::ULongFract: |
2874 | case BuiltinType::SatShortAccum: |
2875 | case BuiltinType::SatAccum: |
2876 | case BuiltinType::SatLongAccum: |
2877 | case BuiltinType::SatUShortAccum: |
2878 | case BuiltinType::SatUAccum: |
2879 | case BuiltinType::SatULongAccum: |
2880 | case BuiltinType::SatShortFract: |
2881 | case BuiltinType::SatFract: |
2882 | case BuiltinType::SatLongFract: |
2883 | case BuiltinType::SatUShortFract: |
2884 | case BuiltinType::SatUFract: |
2885 | case BuiltinType::SatULongFract: |
2886 | return false; |
2887 | |
2888 | case BuiltinType::Dependent: |
2889 | #define BUILTIN_TYPE(Id, SingletonId) |
2890 | #define PLACEHOLDER_TYPE(Id, SingletonId) \ |
2891 | case BuiltinType::Id: |
2892 | #include "clang/AST/BuiltinTypes.def" |
2893 | llvm_unreachable("asking for RRTI for a placeholder type!"); |
2894 | |
2895 | case BuiltinType::ObjCId: |
2896 | case BuiltinType::ObjCClass: |
2897 | case BuiltinType::ObjCSel: |
2898 | llvm_unreachable("FIXME: Objective-C types are unsupported!"); |
2899 | } |
2900 | |
2901 | llvm_unreachable("Invalid BuiltinType Kind!"); |
2902 | } |
2903 | |
2904 | static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) { |
2905 | QualType PointeeTy = PointerTy->getPointeeType(); |
2906 | const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy); |
2907 | if (!BuiltinTy) |
2908 | return false; |
2909 | |
2910 | |
2911 | Qualifiers Quals = PointeeTy.getQualifiers(); |
2912 | Quals.removeConst(); |
2913 | |
2914 | if (!Quals.empty()) |
2915 | return false; |
2916 | |
2917 | return TypeInfoIsInStandardLibrary(BuiltinTy); |
2918 | } |
2919 | |
2920 | |
2921 | |
2922 | static bool IsStandardLibraryRTTIDescriptor(QualType Ty) { |
2923 | |
2924 | if (const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty)) |
2925 | return TypeInfoIsInStandardLibrary(BuiltinTy); |
2926 | |
2927 | |
2928 | |
2929 | if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty)) |
2930 | return TypeInfoIsInStandardLibrary(PointerTy); |
2931 | |
2932 | return false; |
2933 | } |
2934 | |
2935 | |
2936 | |
2937 | |
2938 | |
2939 | static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, |
2940 | QualType Ty) { |
2941 | ASTContext &Context = CGM.getContext(); |
2942 | |
2943 | |
2944 | |
2945 | if (!Context.getLangOpts().RTTI) return false; |
2946 | |
2947 | if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) { |
2948 | const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl()); |
2949 | if (!RD->hasDefinition()) |
2950 | return false; |
2951 | |
2952 | if (!RD->isDynamicClass()) |
2953 | return false; |
2954 | |
2955 | |
2956 | |
2957 | |
2958 | |
2959 | bool IsDLLImport = RD->hasAttr<DLLImportAttr>(); |
2960 | |
2961 | |
2962 | if (CGM.getTriple().isWindowsGNUEnvironment() && IsDLLImport) |
2963 | return false; |
2964 | |
2965 | if (CGM.getVTables().isVTableExternal(RD)) |
2966 | return IsDLLImport && !CGM.getTriple().isWindowsItaniumEnvironment() |
2967 | ? false |
2968 | : true; |
2969 | |
2970 | if (IsDLLImport) |
2971 | return true; |
2972 | } |
2973 | |
2974 | return false; |
2975 | } |
2976 | |
2977 | |
2978 | static bool IsIncompleteClassType(const RecordType *RecordTy) { |
2979 | return !RecordTy->getDecl()->isCompleteDefinition(); |
2980 | } |
2981 | |
2982 | |
2983 | |
2984 | |
2985 | |
2986 | |
2987 | |
2988 | |
2989 | |
2990 | |
2991 | |
2992 | |
2993 | static bool ContainsIncompleteClassType(QualType Ty) { |
2994 | if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) { |
2995 | if (IsIncompleteClassType(RecordTy)) |
2996 | return true; |
2997 | } |
2998 | |
2999 | if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty)) |
3000 | return ContainsIncompleteClassType(PointerTy->getPointeeType()); |
3001 | |
3002 | if (const MemberPointerType *MemberPointerTy = |
3003 | dyn_cast<MemberPointerType>(Ty)) { |
3004 | |
3005 | const RecordType *ClassType = cast<RecordType>(MemberPointerTy->getClass()); |
3006 | if (IsIncompleteClassType(ClassType)) |
3007 | return true; |
3008 | |
3009 | return ContainsIncompleteClassType(MemberPointerTy->getPointeeType()); |
3010 | } |
3011 | |
3012 | return false; |
3013 | } |
3014 | |
3015 | |
3016 | |
3017 | |
3018 | static bool CanUseSingleInheritance(const CXXRecordDecl *RD) { |
3019 | |
3020 | if (RD->getNumBases() != 1) |
3021 | return false; |
3022 | |
3023 | |
3024 | CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(); |
3025 | |
3026 | |
3027 | if (Base->isVirtual()) |
3028 | return false; |
3029 | |
3030 | |
3031 | if (Base->getAccessSpecifier() != AS_public) |
3032 | return false; |
3033 | |
3034 | |
3035 | const CXXRecordDecl *BaseDecl = |
3036 | cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); |
3037 | if (!BaseDecl->isEmpty() && |
3038 | BaseDecl->isDynamicClass() != RD->isDynamicClass()) |
3039 | return false; |
3040 | |
3041 | return true; |
3042 | } |
3043 | |
3044 | void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) { |
3045 | |
3046 | static const char * const ClassTypeInfo = |
3047 | "_ZTVN10__cxxabiv117__class_type_infoE"; |
3048 | |
3049 | static const char * const SIClassTypeInfo = |
3050 | "_ZTVN10__cxxabiv120__si_class_type_infoE"; |
3051 | |
3052 | static const char * const VMIClassTypeInfo = |
3053 | "_ZTVN10__cxxabiv121__vmi_class_type_infoE"; |
3054 | |
3055 | const char *VTableName = nullptr; |
3056 | |
3057 | switch (Ty->getTypeClass()) { |
3058 | #define TYPE(Class, Base) |
3059 | #define ABSTRACT_TYPE(Class, Base) |
3060 | #define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class: |
3061 | #define NON_CANONICAL_TYPE(Class, Base) case Type::Class: |
3062 | #define DEPENDENT_TYPE(Class, Base) case Type::Class: |
3063 | #include "clang/AST/TypeNodes.def" |
3064 | llvm_unreachable("Non-canonical and dependent types shouldn't get here"); |
3065 | |
3066 | case Type::LValueReference: |
3067 | case Type::RValueReference: |
3068 | llvm_unreachable("References shouldn't get here"); |
3069 | |
3070 | case Type::Auto: |
3071 | case Type::DeducedTemplateSpecialization: |
3072 | llvm_unreachable("Undeduced type shouldn't get here"); |
3073 | |
3074 | case Type::Pipe: |
3075 | llvm_unreachable("Pipe types shouldn't get here"); |
3076 | |
3077 | case Type::Builtin: |
3078 | |
3079 | case Type::Vector: |
3080 | case Type::ExtVector: |
3081 | case Type::Complex: |
3082 | case Type::Atomic: |
3083 | |
3084 | case Type::BlockPointer: |
3085 | |
3086 | VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE"; |
3087 | break; |
3088 | |
3089 | case Type::ConstantArray: |
3090 | case Type::IncompleteArray: |
3091 | case Type::VariableArray: |
3092 | |
3093 | VTableName = "_ZTVN10__cxxabiv117__array_type_infoE"; |
3094 | break; |
3095 | |
3096 | case Type::FunctionNoProto: |
3097 | case Type::FunctionProto: |
3098 | |
3099 | VTableName = "_ZTVN10__cxxabiv120__function_type_infoE"; |
3100 | break; |
3101 | |
3102 | case Type::Enum: |
3103 | |
3104 | VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE"; |
3105 | break; |
3106 | |
3107 | case Type::Record: { |
3108 | const CXXRecordDecl *RD = |
3109 | cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl()); |
3110 | |
3111 | if (!RD->hasDefinition() || !RD->getNumBases()) { |
3112 | VTableName = ClassTypeInfo; |
3113 | } else if (CanUseSingleInheritance(RD)) { |
3114 | VTableName = SIClassTypeInfo; |
3115 | } else { |
3116 | VTableName = VMIClassTypeInfo; |
3117 | } |
3118 | |
3119 | break; |
3120 | } |
3121 | |
3122 | case Type::ObjCObject: |
3123 | |
3124 | Ty = cast<ObjCObjectType>(Ty)->getBaseType().getTypePtr(); |
3125 | |
3126 | |
3127 | if (isa<BuiltinType>(Ty)) { |
3128 | VTableName = ClassTypeInfo; |
3129 | break; |
3130 | } |
3131 | |
3132 | (Ty)", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 3132, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isa<ObjCInterfaceType>(Ty)); |
3133 | LLVM_FALLTHROUGH; |
3134 | |
3135 | case Type::ObjCInterface: |
3136 | if (cast<ObjCInterfaceType>(Ty)->getDecl()->getSuperClass()) { |
3137 | VTableName = SIClassTypeInfo; |
3138 | } else { |
3139 | VTableName = ClassTypeInfo; |
3140 | } |
3141 | break; |
3142 | |
3143 | case Type::ObjCObjectPointer: |
3144 | case Type::Pointer: |
3145 | |
3146 | VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE"; |
3147 | break; |
3148 | |
3149 | case Type::MemberPointer: |
3150 | |
3151 | VTableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE"; |
3152 | break; |
3153 | } |
3154 | |
3155 | llvm::Constant *VTable = |
3156 | CGM.getModule().getOrInsertGlobal(VTableName, CGM.Int8PtrTy); |
3157 | CGM.setDSOLocal(cast<llvm::GlobalValue>(VTable->stripPointerCasts())); |
3158 | |
3159 | llvm::Type *PtrDiffTy = |
3160 | CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType()); |
3161 | |
3162 | |
3163 | llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2); |
3164 | VTable = |
3165 | llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.Int8PtrTy, VTable, Two); |
3166 | VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy); |
3167 | |
3168 | Fields.push_back(VTable); |
3169 | } |
3170 | |
3171 | |
3172 | |
3173 | static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM, |
3174 | QualType Ty) { |
3175 | |
3176 | |
3177 | |
3178 | |
3179 | |
3180 | |
3181 | |
3182 | |
3183 | |
3184 | if (ContainsIncompleteClassType(Ty)) |
3185 | return llvm::GlobalValue::InternalLinkage; |
3186 | |
3187 | switch (Ty->getLinkage()) { |
3188 | case NoLinkage: |
3189 | case InternalLinkage: |
3190 | case UniqueExternalLinkage: |
3191 | return llvm::GlobalValue::InternalLinkage; |
3192 | |
3193 | case VisibleNoLinkage: |
3194 | case ModuleInternalLinkage: |
3195 | case ModuleLinkage: |
3196 | case ExternalLinkage: |
3197 | |
3198 | |
3199 | if (!CGM.getLangOpts().RTTI) |
3200 | return llvm::GlobalValue::LinkOnceODRLinkage; |
3201 | |
3202 | if (const RecordType *Record = dyn_cast<RecordType>(Ty)) { |
3203 | const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl()); |
3204 | if (RD->hasAttr<WeakAttr>()) |
3205 | return llvm::GlobalValue::WeakODRLinkage; |
3206 | if (CGM.getTriple().isWindowsItaniumEnvironment()) |
3207 | if (RD->hasAttr<DLLImportAttr>() && |
3208 | ShouldUseExternalRTTIDescriptor(CGM, Ty)) |
3209 | return llvm::GlobalValue::ExternalLinkage; |
3210 | |
3211 | if (RD->isDynamicClass() && |
3212 | !CGM.getContext() |
3213 | .getTargetInfo() |
3214 | .getTriple() |
3215 | .isWindowsGNUEnvironment()) |
3216 | return CGM.getVTableLinkage(RD); |
3217 | } |
3218 | |
3219 | return llvm::GlobalValue::LinkOnceODRLinkage; |
3220 | } |
3221 | |
3222 | llvm_unreachable("Invalid linkage!"); |
3223 | } |
3224 | |
3225 | llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty) { |
3226 | |
3227 | Ty = Ty.getCanonicalType(); |
3228 | |
3229 | |
3230 | SmallString<256> Name; |
3231 | llvm::raw_svector_ostream Out(Name); |
3232 | CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out); |
3233 | |
3234 | llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name); |
3235 | if (OldGV && !OldGV->isDeclaration()) { |
3236 | (0) . __assert_fail ("!OldGV->hasAvailableExternallyLinkage() && \"available_externally typeinfos not yet implemented\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 3237, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!OldGV->hasAvailableExternallyLinkage() && |
3237 | (0) . __assert_fail ("!OldGV->hasAvailableExternallyLinkage() && \"available_externally typeinfos not yet implemented\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 3237, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "available_externally typeinfos not yet implemented"); |
3238 | |
3239 | return llvm::ConstantExpr::getBitCast(OldGV, CGM.Int8PtrTy); |
3240 | } |
3241 | |
3242 | |
3243 | if (IsStandardLibraryRTTIDescriptor(Ty) || |
3244 | ShouldUseExternalRTTIDescriptor(CGM, Ty)) |
3245 | return GetAddrOfExternalRTTIDescriptor(Ty); |
3246 | |
3247 | |
3248 | llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(CGM, Ty); |
3249 | |
3250 | |
3251 | |
3252 | llvm::GlobalValue::VisibilityTypes llvmVisibility; |
3253 | if (llvm::GlobalValue::isLocalLinkage(Linkage)) |
3254 | |
3255 | llvmVisibility = llvm::GlobalValue::DefaultVisibility; |
3256 | else if (CXXABI.classifyRTTIUniqueness(Ty, Linkage) == |
3257 | ItaniumCXXABI::RUK_NonUniqueHidden) |
3258 | llvmVisibility = llvm::GlobalValue::HiddenVisibility; |
3259 | else |
3260 | llvmVisibility = CodeGenModule::GetLLVMVisibility(Ty->getVisibility()); |
3261 | |
3262 | llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass = |
3263 | llvm::GlobalValue::DefaultStorageClass; |
3264 | if (CGM.getTriple().isWindowsItaniumEnvironment()) { |
3265 | auto RD = Ty->getAsCXXRecordDecl(); |
3266 | if (RD && RD->hasAttr<DLLExportAttr>()) |
3267 | DLLStorageClass = llvm::GlobalValue::DLLExportStorageClass; |
3268 | } |
3269 | |
3270 | return BuildTypeInfo(Ty, Linkage, llvmVisibility, DLLStorageClass); |
3271 | } |
3272 | |
3273 | llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo( |
3274 | QualType Ty, |
3275 | llvm::GlobalVariable::LinkageTypes Linkage, |
3276 | llvm::GlobalValue::VisibilityTypes Visibility, |
3277 | llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) { |
3278 | |
3279 | BuildVTablePointer(cast<Type>(Ty)); |
3280 | |
3281 | |
3282 | llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage); |
3283 | llvm::Constant *TypeNameField; |
3284 | |
3285 | |
3286 | |
3287 | ItaniumCXXABI::RTTIUniquenessKind RTTIUniqueness = |
3288 | CXXABI.classifyRTTIUniqueness(Ty, Linkage); |
3289 | if (RTTIUniqueness != ItaniumCXXABI::RUK_Unique) { |
3290 | |
3291 | |
3292 | TypeNameField = llvm::ConstantExpr::getPtrToInt(TypeName, CGM.Int64Ty); |
3293 | llvm::Constant *flag = |
3294 | llvm::ConstantInt::get(CGM.Int64Ty, ((uint64_t)1) << 63); |
3295 | TypeNameField = llvm::ConstantExpr::getAdd(TypeNameField, flag); |
3296 | TypeNameField = |
3297 | llvm::ConstantExpr::getIntToPtr(TypeNameField, CGM.Int8PtrTy); |
3298 | } else { |
3299 | TypeNameField = llvm::ConstantExpr::getBitCast(TypeName, CGM.Int8PtrTy); |
3300 | } |
3301 | Fields.push_back(TypeNameField); |
3302 | |
3303 | switch (Ty->getTypeClass()) { |
3304 | #define TYPE(Class, Base) |
3305 | #define ABSTRACT_TYPE(Class, Base) |
3306 | #define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class: |
3307 | #define NON_CANONICAL_TYPE(Class, Base) case Type::Class: |
3308 | #define DEPENDENT_TYPE(Class, Base) case Type::Class: |
3309 | #include "clang/AST/TypeNodes.def" |
3310 | llvm_unreachable("Non-canonical and dependent types shouldn't get here"); |
3311 | |
3312 | |
3313 | case Type::Builtin: |
3314 | case Type::Vector: |
3315 | case Type::ExtVector: |
3316 | case Type::Complex: |
3317 | case Type::BlockPointer: |
3318 | |
3319 | |
3320 | break; |
3321 | |
3322 | case Type::LValueReference: |
3323 | case Type::RValueReference: |
3324 | llvm_unreachable("References shouldn't get here"); |
3325 | |
3326 | case Type::Auto: |
3327 | case Type::DeducedTemplateSpecialization: |
3328 | llvm_unreachable("Undeduced type shouldn't get here"); |
3329 | |
3330 | case Type::Pipe: |
3331 | llvm_unreachable("Pipe type shouldn't get here"); |
3332 | |
3333 | case Type::ConstantArray: |
3334 | case Type::IncompleteArray: |
3335 | case Type::VariableArray: |
3336 | |
3337 | |
3338 | break; |
3339 | |
3340 | case Type::FunctionNoProto: |
3341 | case Type::FunctionProto: |
3342 | |
3343 | |
3344 | break; |
3345 | |
3346 | case Type::Enum: |
3347 | |
3348 | |
3349 | break; |
3350 | |
3351 | case Type::Record: { |
3352 | const CXXRecordDecl *RD = |
3353 | cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl()); |
3354 | if (!RD->hasDefinition() || !RD->getNumBases()) { |
3355 | |
3356 | break; |
3357 | } |
3358 | |
3359 | if (CanUseSingleInheritance(RD)) |
3360 | BuildSIClassTypeInfo(RD); |
3361 | else |
3362 | BuildVMIClassTypeInfo(RD); |
3363 | |
3364 | break; |
3365 | } |
3366 | |
3367 | case Type::ObjCObject: |
3368 | case Type::ObjCInterface: |
3369 | BuildObjCObjectTypeInfo(cast<ObjCObjectType>(Ty)); |
3370 | break; |
3371 | |
3372 | case Type::ObjCObjectPointer: |
3373 | BuildPointerTypeInfo(cast<ObjCObjectPointerType>(Ty)->getPointeeType()); |
3374 | break; |
3375 | |
3376 | case Type::Pointer: |
3377 | BuildPointerTypeInfo(cast<PointerType>(Ty)->getPointeeType()); |
3378 | break; |
3379 | |
3380 | case Type::MemberPointer: |
3381 | BuildPointerToMemberTypeInfo(cast<MemberPointerType>(Ty)); |
3382 | break; |
3383 | |
3384 | case Type::Atomic: |
3385 | |
3386 | break; |
3387 | } |
3388 | |
3389 | llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields); |
3390 | |
3391 | SmallString<256> Name; |
3392 | llvm::raw_svector_ostream Out(Name); |
3393 | CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out); |
3394 | llvm::Module &M = CGM.getModule(); |
3395 | llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name); |
3396 | llvm::GlobalVariable *GV = |
3397 | new llvm::GlobalVariable(M, Init->getType(), |
3398 | , Linkage, Init, Name); |
3399 | |
3400 | |
3401 | if (OldGV) { |
3402 | GV->takeName(OldGV); |
3403 | llvm::Constant *NewPtr = |
3404 | llvm::ConstantExpr::getBitCast(GV, OldGV->getType()); |
3405 | OldGV->replaceAllUsesWith(NewPtr); |
3406 | OldGV->eraseFromParent(); |
3407 | } |
3408 | |
3409 | if (CGM.supportsCOMDAT() && GV->isWeakForLinker()) |
3410 | GV->setComdat(M.getOrInsertComdat(GV->getName())); |
3411 | |
3412 | CharUnits Align = |
3413 | CGM.getContext().toCharUnitsFromBits(CGM.getTarget().getPointerAlign(0)); |
3414 | GV->setAlignment(Align.getQuantity()); |
3415 | |
3416 | |
3417 | |
3418 | |
3419 | |
3420 | |
3421 | |
3422 | |
3423 | |
3424 | |
3425 | |
3426 | |
3427 | |
3428 | |
3429 | |
3430 | |
3431 | TypeName->setVisibility(Visibility); |
3432 | CGM.setDSOLocal(TypeName); |
3433 | |
3434 | GV->setVisibility(Visibility); |
3435 | CGM.setDSOLocal(GV); |
3436 | |
3437 | TypeName->setDLLStorageClass(DLLStorageClass); |
3438 | GV->setDLLStorageClass(DLLStorageClass); |
3439 | |
3440 | return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy); |
3441 | } |
3442 | |
3443 | |
3444 | |
3445 | void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) { |
3446 | |
3447 | const Type *T = OT->getBaseType().getTypePtr(); |
3448 | (T) || isa(T)", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 3448, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isa<BuiltinType>(T) || isa<ObjCInterfaceType>(T)); |
3449 | |
3450 | |
3451 | |
3452 | if (isa<BuiltinType>(T)) return; |
3453 | |
3454 | ObjCInterfaceDecl *Class = cast<ObjCInterfaceType>(T)->getDecl(); |
3455 | ObjCInterfaceDecl *Super = Class->getSuperClass(); |
3456 | |
3457 | |
3458 | if (!Super) return; |
3459 | |
3460 | QualType SuperTy = CGM.getContext().getObjCInterfaceType(Super); |
3461 | |
3462 | |
3463 | llvm::Constant *BaseTypeInfo = |
3464 | ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(SuperTy); |
3465 | Fields.push_back(BaseTypeInfo); |
3466 | } |
3467 | |
3468 | |
3469 | |
3470 | void ItaniumRTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) { |
3471 | |
3472 | |
3473 | |
3474 | llvm::Constant *BaseTypeInfo = |
3475 | ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(RD->bases_begin()->getType()); |
3476 | Fields.push_back(BaseTypeInfo); |
3477 | } |
3478 | |
3479 | namespace { |
3480 | |
3481 | |
3482 | struct SeenBases { |
3483 | llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases; |
3484 | llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases; |
3485 | }; |
3486 | } |
3487 | |
3488 | |
3489 | |
3490 | |
3491 | static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base, |
3492 | SeenBases &Bases) { |
3493 | |
3494 | unsigned Flags = 0; |
3495 | |
3496 | const CXXRecordDecl *BaseDecl = |
3497 | cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); |
3498 | |
3499 | if (Base->isVirtual()) { |
3500 | |
3501 | if (!Bases.VirtualBases.insert(BaseDecl).second) { |
3502 | |
3503 | |
3504 | Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped; |
3505 | } else { |
3506 | if (Bases.NonVirtualBases.count(BaseDecl)) |
3507 | Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat; |
3508 | } |
3509 | } else { |
3510 | |
3511 | if (!Bases.NonVirtualBases.insert(BaseDecl).second) { |
3512 | |
3513 | |
3514 | Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat; |
3515 | } else { |
3516 | if (Bases.VirtualBases.count(BaseDecl)) |
3517 | Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat; |
3518 | } |
3519 | } |
3520 | |
3521 | |
3522 | for (const auto &I : BaseDecl->bases()) |
3523 | Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases); |
3524 | |
3525 | return Flags; |
3526 | } |
3527 | |
3528 | static unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) { |
3529 | unsigned Flags = 0; |
3530 | SeenBases Bases; |
3531 | |
3532 | |
3533 | for (const auto &I : RD->bases()) |
3534 | Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases); |
3535 | |
3536 | return Flags; |
3537 | } |
3538 | |
3539 | |
3540 | |
3541 | |
3542 | void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) { |
3543 | llvm::Type *UnsignedIntLTy = |
3544 | CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy); |
3545 | |
3546 | |
3547 | |
3548 | |
3549 | |
3550 | unsigned Flags = ComputeVMIClassTypeInfoFlags(RD); |
3551 | Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags)); |
3552 | |
3553 | |
3554 | |
3555 | |
3556 | Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->getNumBases())); |
3557 | |
3558 | if (!RD->getNumBases()) |
3559 | return; |
3560 | |
3561 | |
3562 | |
3563 | |
3564 | |
3565 | |
3566 | |
3567 | |
3568 | |
3569 | |
3570 | |
3571 | |
3572 | |
3573 | |
3574 | |
3575 | |
3576 | |
3577 | |
3578 | |
3579 | |
3580 | |
3581 | |
3582 | |
3583 | |
3584 | QualType OffsetFlagsTy = CGM.getContext().LongTy; |
3585 | const TargetInfo &TI = CGM.getContext().getTargetInfo(); |
3586 | if (TI.getTriple().isOSCygMing() && TI.getPointerWidth(0) > TI.getLongWidth()) |
3587 | OffsetFlagsTy = CGM.getContext().LongLongTy; |
3588 | llvm::Type *OffsetFlagsLTy = |
3589 | CGM.getTypes().ConvertType(OffsetFlagsTy); |
3590 | |
3591 | for (const auto &Base : RD->bases()) { |
3592 | |
3593 | Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(Base.getType())); |
3594 | |
3595 | const CXXRecordDecl *BaseDecl = |
3596 | cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl()); |
3597 | |
3598 | int64_t OffsetFlags = 0; |
3599 | |
3600 | |
3601 | |
3602 | |
3603 | |
3604 | CharUnits Offset; |
3605 | if (Base.isVirtual()) |
3606 | Offset = |
3607 | CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(RD, BaseDecl); |
3608 | else { |
3609 | const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); |
3610 | Offset = Layout.getBaseClassOffset(BaseDecl); |
3611 | }; |
3612 | |
3613 | OffsetFlags = uint64_t(Offset.getQuantity()) << 8; |
3614 | |
3615 | |
3616 | |
3617 | if (Base.isVirtual()) |
3618 | OffsetFlags |= BCTI_Virtual; |
3619 | if (Base.getAccessSpecifier() == AS_public) |
3620 | OffsetFlags |= BCTI_Public; |
3621 | |
3622 | Fields.push_back(llvm::ConstantInt::get(OffsetFlagsLTy, OffsetFlags)); |
3623 | } |
3624 | } |
3625 | |
3626 | |
3627 | |
3628 | static unsigned (ASTContext &Ctx, QualType &Type) { |
3629 | unsigned Flags = 0; |
3630 | |
3631 | if (Type.isConstQualified()) |
3632 | Flags |= ItaniumRTTIBuilder::PTI_Const; |
3633 | if (Type.isVolatileQualified()) |
3634 | Flags |= ItaniumRTTIBuilder::PTI_Volatile; |
3635 | if (Type.isRestrictQualified()) |
3636 | Flags |= ItaniumRTTIBuilder::PTI_Restrict; |
3637 | Type = Type.getUnqualifiedType(); |
3638 | |
3639 | |
3640 | |
3641 | |
3642 | if (ContainsIncompleteClassType(Type)) |
3643 | Flags |= ItaniumRTTIBuilder::PTI_Incomplete; |
3644 | |
3645 | if (auto *Proto = Type->getAs<FunctionProtoType>()) { |
3646 | if (Proto->isNothrow()) { |
3647 | Flags |= ItaniumRTTIBuilder::PTI_Noexcept; |
3648 | Type = Ctx.getFunctionTypeWithExceptionSpec(Type, EST_None); |
3649 | } |
3650 | } |
3651 | |
3652 | return Flags; |
3653 | } |
3654 | |
3655 | |
3656 | |
3657 | void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) { |
3658 | |
3659 | |
3660 | |
3661 | unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy); |
3662 | |
3663 | llvm::Type *UnsignedIntLTy = |
3664 | CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy); |
3665 | Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags)); |
3666 | |
3667 | |
3668 | |
3669 | |
3670 | llvm::Constant *PointeeTypeInfo = |
3671 | ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy); |
3672 | Fields.push_back(PointeeTypeInfo); |
3673 | } |
3674 | |
3675 | |
3676 | |
3677 | void |
3678 | ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) { |
3679 | QualType PointeeTy = Ty->getPointeeType(); |
3680 | |
3681 | |
3682 | |
3683 | |
3684 | unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy); |
3685 | |
3686 | const RecordType *ClassType = cast<RecordType>(Ty->getClass()); |
3687 | if (IsIncompleteClassType(ClassType)) |
3688 | Flags |= PTI_ContainingClassIncomplete; |
3689 | |
3690 | llvm::Type *UnsignedIntLTy = |
3691 | CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy); |
3692 | Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags)); |
3693 | |
3694 | |
3695 | |
3696 | |
3697 | llvm::Constant *PointeeTypeInfo = |
3698 | ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy); |
3699 | Fields.push_back(PointeeTypeInfo); |
3700 | |
3701 | |
3702 | |
3703 | |
3704 | |
3705 | Fields.push_back( |
3706 | ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(QualType(ClassType, 0))); |
3707 | } |
3708 | |
3709 | llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) { |
3710 | return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty); |
3711 | } |
3712 | |
3713 | void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD) { |
3714 | |
3715 | QualType FundamentalTypes[] = { |
3716 | getContext().VoidTy, getContext().NullPtrTy, |
3717 | getContext().BoolTy, getContext().WCharTy, |
3718 | getContext().CharTy, getContext().UnsignedCharTy, |
3719 | getContext().SignedCharTy, getContext().ShortTy, |
3720 | getContext().UnsignedShortTy, getContext().IntTy, |
3721 | getContext().UnsignedIntTy, getContext().LongTy, |
3722 | getContext().UnsignedLongTy, getContext().LongLongTy, |
3723 | getContext().UnsignedLongLongTy, getContext().Int128Ty, |
3724 | getContext().UnsignedInt128Ty, getContext().HalfTy, |
3725 | getContext().FloatTy, getContext().DoubleTy, |
3726 | getContext().LongDoubleTy, getContext().Float128Ty, |
3727 | getContext().Char8Ty, getContext().Char16Ty, |
3728 | getContext().Char32Ty |
3729 | }; |
3730 | llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass = |
3731 | RD->hasAttr<DLLExportAttr>() |
3732 | ? llvm::GlobalValue::DLLExportStorageClass |
3733 | : llvm::GlobalValue::DefaultStorageClass; |
3734 | llvm::GlobalValue::VisibilityTypes Visibility = |
3735 | CodeGenModule::GetLLVMVisibility(RD->getVisibility()); |
3736 | for (const QualType &FundamentalType : FundamentalTypes) { |
3737 | QualType PointerType = getContext().getPointerType(FundamentalType); |
3738 | QualType PointerTypeConst = getContext().getPointerType( |
3739 | FundamentalType.withConst()); |
3740 | for (QualType Type : {FundamentalType, PointerType, PointerTypeConst}) |
3741 | ItaniumRTTIBuilder(*this).BuildTypeInfo( |
3742 | Type, llvm::GlobalValue::ExternalLinkage, |
3743 | Visibility, DLLStorageClass); |
3744 | } |
3745 | } |
3746 | |
3747 | |
3748 | |
3749 | ItaniumCXXABI::RTTIUniquenessKind ItaniumCXXABI::classifyRTTIUniqueness( |
3750 | QualType CanTy, llvm::GlobalValue::LinkageTypes Linkage) const { |
3751 | if (shouldRTTIBeUnique()) |
3752 | return RUK_Unique; |
3753 | |
3754 | |
3755 | if (Linkage != llvm::GlobalValue::LinkOnceODRLinkage && |
3756 | Linkage != llvm::GlobalValue::WeakODRLinkage) |
3757 | return RUK_Unique; |
3758 | |
3759 | |
3760 | if (CanTy->getVisibility() != DefaultVisibility) |
3761 | return RUK_Unique; |
3762 | |
3763 | |
3764 | if (Linkage == llvm::GlobalValue::LinkOnceODRLinkage) |
3765 | return RUK_NonUniqueHidden; |
3766 | |
3767 | |
3768 | |
3769 | |
3770 | assert(Linkage == llvm::GlobalValue::WeakODRLinkage); |
3771 | return RUK_NonUniqueVisible; |
3772 | } |
3773 | |
3774 | |
3775 | namespace { |
3776 | enum class StructorCodegen { Emit, RAUW, Alias, COMDAT }; |
3777 | } |
3778 | static StructorCodegen getCodegenToUse(CodeGenModule &CGM, |
3779 | const CXXMethodDecl *MD) { |
3780 | if (!CGM.getCodeGenOpts().CXXCtorDtorAliases) |
3781 | return StructorCodegen::Emit; |
3782 | |
3783 | |
3784 | |
3785 | if (MD->getParent()->getNumVBases()) |
3786 | return StructorCodegen::Emit; |
3787 | |
3788 | GlobalDecl AliasDecl; |
3789 | if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) { |
3790 | AliasDecl = GlobalDecl(DD, Dtor_Complete); |
3791 | } else { |
3792 | const auto *CD = cast<CXXConstructorDecl>(MD); |
3793 | AliasDecl = GlobalDecl(CD, Ctor_Complete); |
3794 | } |
3795 | llvm::GlobalValue::LinkageTypes Linkage = CGM.getFunctionLinkage(AliasDecl); |
3796 | |
3797 | if (llvm::GlobalValue::isDiscardableIfUnused(Linkage)) |
3798 | return StructorCodegen::RAUW; |
3799 | |
3800 | |
3801 | if (!llvm::GlobalAlias::isValidLinkage(Linkage)) |
3802 | return StructorCodegen::RAUW; |
3803 | |
3804 | if (llvm::GlobalValue::isWeakForLinker(Linkage)) { |
3805 | |
3806 | if (CGM.getTarget().getTriple().isOSBinFormatELF() || |
3807 | CGM.getTarget().getTriple().isOSBinFormatWasm()) |
3808 | return StructorCodegen::COMDAT; |
3809 | return StructorCodegen::Emit; |
3810 | } |
3811 | |
3812 | return StructorCodegen::Alias; |
3813 | } |
3814 | |
3815 | static void emitConstructorDestructorAlias(CodeGenModule &CGM, |
3816 | GlobalDecl AliasDecl, |
3817 | GlobalDecl TargetDecl) { |
3818 | llvm::GlobalValue::LinkageTypes Linkage = CGM.getFunctionLinkage(AliasDecl); |
3819 | |
3820 | StringRef MangledName = CGM.getMangledName(AliasDecl); |
3821 | llvm::GlobalValue *Entry = CGM.GetGlobalValue(MangledName); |
3822 | if (Entry && !Entry->isDeclaration()) |
3823 | return; |
3824 | |
3825 | auto *Aliasee = cast<llvm::GlobalValue>(CGM.GetAddrOfGlobal(TargetDecl)); |
3826 | |
3827 | |
3828 | auto *Alias = llvm::GlobalAlias::create(Linkage, "", Aliasee); |
3829 | |
3830 | |
3831 | Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); |
3832 | |
3833 | |
3834 | if (Entry) { |
3835 | (0) . __assert_fail ("Entry->getType() == Aliasee->getType() && \"declaration exists with different type\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 3836, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Entry->getType() == Aliasee->getType() && |
3836 | (0) . __assert_fail ("Entry->getType() == Aliasee->getType() && \"declaration exists with different type\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 3836, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "declaration exists with different type"); |
3837 | Alias->takeName(Entry); |
3838 | Entry->replaceAllUsesWith(Alias); |
3839 | Entry->eraseFromParent(); |
3840 | } else { |
3841 | Alias->setName(MangledName); |
3842 | } |
3843 | |
3844 | |
3845 | CGM.SetCommonAttributes(AliasDecl, Alias); |
3846 | } |
3847 | |
3848 | void ItaniumCXXABI::emitCXXStructor(GlobalDecl GD) { |
3849 | auto *MD = cast<CXXMethodDecl>(GD.getDecl()); |
3850 | auto *CD = dyn_cast<CXXConstructorDecl>(MD); |
3851 | const CXXDestructorDecl *DD = CD ? nullptr : cast<CXXDestructorDecl>(MD); |
3852 | |
3853 | StructorCodegen CGType = getCodegenToUse(CGM, MD); |
3854 | |
3855 | if (CD ? GD.getCtorType() == Ctor_Complete |
3856 | : GD.getDtorType() == Dtor_Complete) { |
3857 | GlobalDecl BaseDecl; |
3858 | if (CD) |
3859 | BaseDecl = GD.getWithCtorType(Ctor_Base); |
3860 | else |
3861 | BaseDecl = GD.getWithDtorType(Dtor_Base); |
3862 | |
3863 | if (CGType == StructorCodegen::Alias || CGType == StructorCodegen::COMDAT) { |
3864 | emitConstructorDestructorAlias(CGM, GD, BaseDecl); |
3865 | return; |
3866 | } |
3867 | |
3868 | if (CGType == StructorCodegen::RAUW) { |
3869 | StringRef MangledName = CGM.getMangledName(GD); |
3870 | auto *Aliasee = CGM.GetAddrOfGlobal(BaseDecl); |
3871 | CGM.addReplacement(MangledName, Aliasee); |
3872 | return; |
3873 | } |
3874 | } |
3875 | |
3876 | |
3877 | |
3878 | |
3879 | |
3880 | if (DD && GD.getDtorType() == Dtor_Base && |
3881 | CGType != StructorCodegen::COMDAT && |
3882 | !CGM.TryEmitBaseDestructorAsAlias(DD)) |
3883 | return; |
3884 | |
3885 | |
3886 | |
3887 | |
3888 | |
3889 | |
3890 | |
3891 | |
3892 | |
3893 | |
3894 | |
3895 | |
3896 | |
3897 | llvm::Function *Fn = CGM.codegenCXXStructor(GD); |
3898 | |
3899 | if (CGType == StructorCodegen::COMDAT) { |
3900 | SmallString<256> Buffer; |
3901 | llvm::raw_svector_ostream Out(Buffer); |
3902 | if (DD) |
3903 | getMangleContext().mangleCXXDtorComdat(DD, Out); |
3904 | else |
3905 | getMangleContext().mangleCXXCtorComdat(CD, Out); |
3906 | llvm::Comdat *C = CGM.getModule().getOrInsertComdat(Out.str()); |
3907 | Fn->setComdat(C); |
3908 | } else { |
3909 | CGM.maybeSetTrivialComdat(*MD, *Fn); |
3910 | } |
3911 | } |
3912 | |
3913 | static llvm::FunctionCallee getBeginCatchFn(CodeGenModule &CGM) { |
3914 | |
3915 | llvm::FunctionType *FTy = llvm::FunctionType::get( |
3916 | CGM.Int8PtrTy, CGM.Int8PtrTy, ); |
3917 | |
3918 | return CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch"); |
3919 | } |
3920 | |
3921 | static llvm::FunctionCallee getEndCatchFn(CodeGenModule &CGM) { |
3922 | |
3923 | llvm::FunctionType *FTy = |
3924 | llvm::FunctionType::get(CGM.VoidTy, ); |
3925 | |
3926 | return CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch"); |
3927 | } |
3928 | |
3929 | static llvm::FunctionCallee getGetExceptionPtrFn(CodeGenModule &CGM) { |
3930 | |
3931 | llvm::FunctionType *FTy = llvm::FunctionType::get( |
3932 | CGM.Int8PtrTy, CGM.Int8PtrTy, ); |
3933 | |
3934 | return CGM.CreateRuntimeFunction(FTy, "__cxa_get_exception_ptr"); |
3935 | } |
3936 | |
3937 | namespace { |
3938 | |
3939 | |
3940 | |
3941 | |
3942 | |
3943 | |
3944 | |
3945 | |
3946 | |
3947 | |
3948 | |
3949 | |
3950 | struct CallEndCatch final : EHScopeStack::Cleanup { |
3951 | CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {} |
3952 | bool MightThrow; |
3953 | |
3954 | void Emit(CodeGenFunction &CGF, Flags flags) override { |
3955 | if (!MightThrow) { |
3956 | CGF.EmitNounwindRuntimeCall(getEndCatchFn(CGF.CGM)); |
3957 | return; |
3958 | } |
3959 | |
3960 | CGF.EmitRuntimeCallOrInvoke(getEndCatchFn(CGF.CGM)); |
3961 | } |
3962 | }; |
3963 | } |
3964 | |
3965 | |
3966 | |
3967 | |
3968 | |
3969 | static llvm::Value *CallBeginCatch(CodeGenFunction &CGF, |
3970 | llvm::Value *Exn, |
3971 | bool EndMightThrow) { |
3972 | llvm::CallInst *call = |
3973 | CGF.EmitNounwindRuntimeCall(getBeginCatchFn(CGF.CGM), Exn); |
3974 | |
3975 | CGF.EHStack.pushCleanup<CallEndCatch>(NormalAndEHCleanup, EndMightThrow); |
3976 | |
3977 | return call; |
3978 | } |
3979 | |
3980 | |
3981 | |
3982 | static void InitCatchParam(CodeGenFunction &CGF, |
3983 | const VarDecl &CatchParam, |
3984 | Address ParamAddr, |
3985 | SourceLocation Loc) { |
3986 | |
3987 | llvm::Value *Exn = CGF.getExceptionFromSlot(); |
3988 | |
3989 | CanQualType CatchType = |
3990 | CGF.CGM.getContext().getCanonicalType(CatchParam.getType()); |
3991 | llvm::Type *LLVMCatchTy = CGF.ConvertTypeForMem(CatchType); |
3992 | |
3993 | |
3994 | |
3995 | if (isa<ReferenceType>(CatchType)) { |
3996 | QualType CaughtType = cast<ReferenceType>(CatchType)->getPointeeType(); |
3997 | bool EndCatchMightThrow = CaughtType->isRecordType(); |
3998 | |
3999 | |
4000 | llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow); |
4001 | |
4002 | |
4003 | |
4004 | |
4005 | if (const PointerType *PT = dyn_cast<PointerType>(CaughtType)) { |
4006 | QualType PointeeType = PT->getPointeeType(); |
4007 | |
4008 | |
4009 | |
4010 | if (!PointeeType->isRecordType()) { |
4011 | |
4012 | |
4013 | |
4014 | unsigned = |
4015 | CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException(); |
4016 | AdjustedExn = CGF.Builder.CreateConstGEP1_32(Exn, HeaderSize); |
4017 | |
4018 | |
4019 | |
4020 | |
4021 | |
4022 | |
4023 | |
4024 | |
4025 | |
4026 | |
4027 | |
4028 | |
4029 | |
4030 | |
4031 | |
4032 | } else { |
4033 | |
4034 | llvm::Type *PtrTy = |
4035 | cast<llvm::PointerType>(LLVMCatchTy)->getElementType(); |
4036 | |
4037 | |
4038 | Address ExnPtrTmp = |
4039 | CGF.CreateTempAlloca(PtrTy, CGF.getPointerAlign(), "exn.byref.tmp"); |
4040 | llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy); |
4041 | CGF.Builder.CreateStore(Casted, ExnPtrTmp); |
4042 | |
4043 | |
4044 | AdjustedExn = ExnPtrTmp.getPointer(); |
4045 | } |
4046 | } |
4047 | |
4048 | llvm::Value *ExnCast = |
4049 | CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref"); |
4050 | CGF.Builder.CreateStore(ExnCast, ParamAddr); |
4051 | return; |
4052 | } |
4053 | |
4054 | |
4055 | TypeEvaluationKind TEK = CGF.getEvaluationKind(CatchType); |
4056 | if (TEK != TEK_Aggregate) { |
4057 | llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false); |
4058 | |
4059 | |
4060 | |
4061 | if (CatchType->hasPointerRepresentation()) { |
4062 | llvm::Value *CastExn = |
4063 | CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted"); |
4064 | |
4065 | switch (CatchType.getQualifiers().getObjCLifetime()) { |
4066 | case Qualifiers::OCL_Strong: |
4067 | CastExn = CGF.EmitARCRetainNonBlock(CastExn); |
4068 | LLVM_FALLTHROUGH; |
4069 | |
4070 | case Qualifiers::OCL_None: |
4071 | case Qualifiers::OCL_ExplicitNone: |
4072 | case Qualifiers::OCL_Autoreleasing: |
4073 | CGF.Builder.CreateStore(CastExn, ParamAddr); |
4074 | return; |
4075 | |
4076 | case Qualifiers::OCL_Weak: |
4077 | CGF.EmitARCInitWeak(ParamAddr, CastExn); |
4078 | return; |
4079 | } |
4080 | llvm_unreachable("bad ownership qualifier!"); |
4081 | } |
4082 | |
4083 | |
4084 | |
4085 | llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); |
4086 | llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy); |
4087 | |
4088 | LValue srcLV = CGF.MakeNaturalAlignAddrLValue(Cast, CatchType); |
4089 | LValue destLV = CGF.MakeAddrLValue(ParamAddr, CatchType); |
4090 | switch (TEK) { |
4091 | case TEK_Complex: |
4092 | CGF.EmitStoreOfComplex(CGF.EmitLoadOfComplex(srcLV, Loc), destLV, |
4093 | true); |
4094 | return; |
4095 | case TEK_Scalar: { |
4096 | llvm::Value *ExnLoad = CGF.EmitLoadOfScalar(srcLV, Loc); |
4097 | CGF.EmitStoreOfScalar(ExnLoad, destLV, true); |
4098 | return; |
4099 | } |
4100 | case TEK_Aggregate: |
4101 | llvm_unreachable("evaluation kind filtered out!"); |
4102 | } |
4103 | llvm_unreachable("bad evaluation kind"); |
4104 | } |
4105 | |
4106 | (0) . __assert_fail ("isa(CatchType) && \"unexpected catch type!\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ItaniumCXXABI.cpp", 4106, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isa<RecordType>(CatchType) && "unexpected catch type!"); |
4107 | auto catchRD = CatchType->getAsCXXRecordDecl(); |
4108 | CharUnits caughtExnAlignment = CGF.CGM.getClassPointerAlignment(catchRD); |
4109 | |
4110 | llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); |
4111 | |
4112 | |
4113 | |
4114 | const Expr *copyExpr = CatchParam.getInit(); |
4115 | if (!copyExpr) { |
4116 | llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true); |
4117 | Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy), |
4118 | caughtExnAlignment); |
4119 | LValue Dest = CGF.MakeAddrLValue(ParamAddr, CatchType); |
4120 | LValue Src = CGF.MakeAddrLValue(adjustedExn, CatchType); |
4121 | CGF.EmitAggregateCopy(Dest, Src, CatchType, AggValueSlot::DoesNotOverlap); |
4122 | return; |
4123 | } |
4124 | |
4125 | |
4126 | |
4127 | llvm::CallInst *rawAdjustedExn = |
4128 | CGF.EmitNounwindRuntimeCall(getGetExceptionPtrFn(CGF.CGM), Exn); |
4129 | |
4130 | |
4131 | Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy), |
4132 | caughtExnAlignment); |
4133 | |
4134 | |
4135 | |
4136 | CodeGenFunction::OpaqueValueMapping |
4137 | opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr), |
4138 | CGF.MakeAddrLValue(adjustedExn, CatchParam.getType())); |
4139 | |
4140 | |
4141 | CGF.EHStack.pushTerminate(); |
4142 | |
4143 | |
4144 | CGF.EmitAggExpr(copyExpr, |
4145 | AggValueSlot::forAddr(ParamAddr, Qualifiers(), |
4146 | AggValueSlot::IsNotDestructed, |
4147 | AggValueSlot::DoesNotNeedGCBarriers, |
4148 | AggValueSlot::IsNotAliased, |
4149 | AggValueSlot::DoesNotOverlap)); |
4150 | |
4151 | |
4152 | CGF.EHStack.popTerminate(); |
4153 | |
4154 | |
4155 | opaque.pop(); |
4156 | |
4157 | |
4158 | CallBeginCatch(CGF, Exn, true); |
4159 | } |
4160 | |
4161 | |
4162 | |
4163 | void ItaniumCXXABI::emitBeginCatch(CodeGenFunction &CGF, |
4164 | const CXXCatchStmt *S) { |
4165 | |
4166 | |
4167 | |
4168 | |
4169 | |
4170 | |
4171 | |
4172 | |
4173 | |
4174 | |
4175 | |
4176 | |
4177 | |
4178 | |
4179 | |
4180 | |
4181 | |
4182 | |
4183 | |
4184 | |
4185 | |
4186 | |
4187 | |
4188 | VarDecl *CatchParam = S->getExceptionDecl(); |
4189 | if (!CatchParam) { |
4190 | llvm::Value *Exn = CGF.getExceptionFromSlot(); |
4191 | CallBeginCatch(CGF, Exn, true); |
4192 | return; |
4193 | } |
4194 | |
4195 | |
4196 | CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam); |
4197 | InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF), S->getBeginLoc()); |
4198 | CGF.EmitAutoVarCleanups(var); |
4199 | } |
4200 | |
4201 | |
4202 | |
4203 | |
4204 | static llvm::FunctionCallee getClangCallTerminateFn(CodeGenModule &CGM) { |
4205 | llvm::FunctionType *fnTy = |
4206 | llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, ); |
4207 | llvm::FunctionCallee fnRef = CGM.CreateRuntimeFunction( |
4208 | fnTy, "__clang_call_terminate", llvm::AttributeList(), ); |
4209 | llvm::Function *fn = |
4210 | cast<llvm::Function>(fnRef.getCallee()->stripPointerCasts()); |
4211 | if (fn->empty()) { |
4212 | fn->setDoesNotThrow(); |
4213 | fn->setDoesNotReturn(); |
4214 | |
4215 | |
4216 | |
4217 | |
4218 | fn->addFnAttr(llvm::Attribute::NoInline); |
4219 | |
4220 | |
4221 | |
4222 | fn->setLinkage(llvm::Function::LinkOnceODRLinkage); |
4223 | fn->setVisibility(llvm::Function::HiddenVisibility); |
4224 | if (CGM.supportsCOMDAT()) |
4225 | fn->setComdat(CGM.getModule().getOrInsertComdat(fn->getName())); |
4226 | |
4227 | |
4228 | llvm::BasicBlock *entry = |
4229 | llvm::BasicBlock::Create(CGM.getLLVMContext(), "", fn); |
4230 | CGBuilderTy builder(CGM, entry); |
4231 | |
4232 | |
4233 | llvm::Value *exn = &*fn->arg_begin(); |
4234 | |
4235 | |
4236 | llvm::CallInst *catchCall = builder.CreateCall(getBeginCatchFn(CGM), exn); |
4237 | catchCall->setDoesNotThrow(); |
4238 | catchCall->setCallingConv(CGM.getRuntimeCC()); |
4239 | |
4240 | |
4241 | llvm::CallInst *termCall = builder.CreateCall(CGM.getTerminateFn()); |
4242 | termCall->setDoesNotThrow(); |
4243 | termCall->setDoesNotReturn(); |
4244 | termCall->setCallingConv(CGM.getRuntimeCC()); |
4245 | |
4246 | |
4247 | builder.CreateUnreachable(); |
4248 | } |
4249 | return fnRef; |
4250 | } |
4251 | |
4252 | llvm::CallInst * |
4253 | ItaniumCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF, |
4254 | llvm::Value *Exn) { |
4255 | |
4256 | if (Exn) { |
4257 | assert(CGF.CGM.getLangOpts().CPlusPlus); |
4258 | return CGF.EmitNounwindRuntimeCall(getClangCallTerminateFn(CGF.CGM), Exn); |
4259 | } |
4260 | return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn()); |
4261 | } |
4262 | |
4263 | std::pair<llvm::Value *, const CXXRecordDecl *> |
4264 | ItaniumCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This, |
4265 | const CXXRecordDecl *RD) { |
4266 | return {CGF.GetVTablePtr(This, CGM.Int8PtrTy, RD), RD}; |
4267 | } |
4268 | |
4269 | void WebAssemblyCXXABI::emitBeginCatch(CodeGenFunction &CGF, |
4270 | const CXXCatchStmt *C) { |
4271 | if (CGF.getTarget().hasFeature("exception-handling")) |
4272 | CGF.EHStack.pushCleanup<CatchRetScope>( |
4273 | NormalCleanup, cast<llvm::CatchPadInst>(CGF.CurrentFuncletPad)); |
4274 | ItaniumCXXABI::emitBeginCatch(CGF, C); |
4275 | } |
4276 | |