1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | #include "CGCXXABI.h" |
17 | #include "CGCleanup.h" |
18 | #include "CGVTables.h" |
19 | #include "CodeGenModule.h" |
20 | #include "CodeGenTypes.h" |
21 | #include "TargetInfo.h" |
22 | #include "clang/CodeGen/ConstantInitBuilder.h" |
23 | #include "clang/AST/Decl.h" |
24 | #include "clang/AST/DeclCXX.h" |
25 | #include "clang/AST/StmtCXX.h" |
26 | #include "clang/AST/VTableBuilder.h" |
27 | #include "llvm/ADT/StringExtras.h" |
28 | #include "llvm/ADT/StringSet.h" |
29 | #include "llvm/IR/Intrinsics.h" |
30 | |
31 | using namespace clang; |
32 | using namespace CodeGen; |
33 | |
34 | namespace { |
35 | |
36 | |
37 | struct VBTableGlobals { |
38 | const VPtrInfoVector *VBTables; |
39 | SmallVector<llvm::GlobalVariable *, 2> Globals; |
40 | }; |
41 | |
42 | class MicrosoftCXXABI : public CGCXXABI { |
43 | public: |
44 | MicrosoftCXXABI(CodeGenModule &CGM) |
45 | : CGCXXABI(CGM), BaseClassDescriptorType(nullptr), |
46 | ClassHierarchyDescriptorType(nullptr), |
47 | CompleteObjectLocatorType(nullptr), CatchableTypeType(nullptr), |
48 | ThrowInfoType(nullptr) {} |
49 | |
50 | bool HasThisReturn(GlobalDecl GD) const override; |
51 | bool hasMostDerivedReturn(GlobalDecl GD) const override; |
52 | |
53 | bool classifyReturnType(CGFunctionInfo &FI) const override; |
54 | |
55 | RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override; |
56 | |
57 | bool isSRetParameterAfterThis() const override { return true; } |
58 | |
59 | bool isThisCompleteObject(GlobalDecl GD) const override { |
60 | |
61 | |
62 | if (isa<CXXDestructorDecl>(GD.getDecl())) { |
63 | switch (GD.getDtorType()) { |
64 | case Dtor_Complete: |
65 | case Dtor_Deleting: |
66 | return true; |
67 | |
68 | case Dtor_Base: |
69 | return false; |
70 | |
71 | case Dtor_Comdat: llvm_unreachable("emitting dtor comdat as function?"); |
72 | } |
73 | llvm_unreachable("bad dtor kind"); |
74 | } |
75 | |
76 | |
77 | return false; |
78 | } |
79 | |
80 | size_t getSrcArgforCopyCtor(const CXXConstructorDecl *CD, |
81 | FunctionArgList &Args) const override { |
82 | (0) . __assert_fail ("Args.size() >= 2 && \"expected the arglist to have at least two args!\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 83, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Args.size() >= 2 && |
83 | (0) . __assert_fail ("Args.size() >= 2 && \"expected the arglist to have at least two args!\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 83, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "expected the arglist to have at least two args!"); |
84 | |
85 | |
86 | if (CD->getParent()->getNumVBases() > 0 && |
87 | CD->getType()->castAs<FunctionProtoType>()->isVariadic()) |
88 | return 2; |
89 | return 1; |
90 | } |
91 | |
92 | std::vector<CharUnits> getVBPtrOffsets(const CXXRecordDecl *RD) override { |
93 | std::vector<CharUnits> VBPtrOffsets; |
94 | const ASTContext &Context = getContext(); |
95 | const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); |
96 | |
97 | const VBTableGlobals &VBGlobals = enumerateVBTables(RD); |
98 | for (const std::unique_ptr<VPtrInfo> &VBT : *VBGlobals.VBTables) { |
99 | const ASTRecordLayout &SubobjectLayout = |
100 | Context.getASTRecordLayout(VBT->IntroducingObject); |
101 | CharUnits Offs = VBT->NonVirtualOffset; |
102 | Offs += SubobjectLayout.getVBPtrOffset(); |
103 | if (VBT->getVBaseWithVPtr()) |
104 | Offs += Layout.getVBaseClassOffset(VBT->getVBaseWithVPtr()); |
105 | VBPtrOffsets.push_back(Offs); |
106 | } |
107 | llvm::array_pod_sort(VBPtrOffsets.begin(), VBPtrOffsets.end()); |
108 | return VBPtrOffsets; |
109 | } |
110 | |
111 | StringRef GetPureVirtualCallName() override { return "_purecall"; } |
112 | StringRef GetDeletedVirtualCallName() override { return "_purecall"; } |
113 | |
114 | void emitVirtualObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, |
115 | Address Ptr, QualType ElementType, |
116 | const CXXDestructorDecl *Dtor) override; |
117 | |
118 | void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) override; |
119 | void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) override; |
120 | |
121 | void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override; |
122 | |
123 | llvm::GlobalVariable *getMSCompleteObjectLocator(const CXXRecordDecl *RD, |
124 | const VPtrInfo &Info); |
125 | |
126 | llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override; |
127 | CatchTypeInfo |
128 | getAddrOfCXXCatchHandlerType(QualType Ty, QualType CatchHandlerType) override; |
129 | |
130 | |
131 | CatchTypeInfo getCatchAllTypeInfo() override { |
132 | return CatchTypeInfo{nullptr, 0x40}; |
133 | } |
134 | |
135 | bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy) override; |
136 | void EmitBadTypeidCall(CodeGenFunction &CGF) override; |
137 | llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy, |
138 | Address ThisPtr, |
139 | llvm::Type *StdTypeInfoPtrTy) override; |
140 | |
141 | bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr, |
142 | QualType SrcRecordTy) override; |
143 | |
144 | llvm::Value *EmitDynamicCastCall(CodeGenFunction &CGF, Address Value, |
145 | QualType SrcRecordTy, QualType DestTy, |
146 | QualType DestRecordTy, |
147 | llvm::BasicBlock *CastEnd) override; |
148 | |
149 | llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF, Address Value, |
150 | QualType SrcRecordTy, |
151 | QualType DestTy) override; |
152 | |
153 | bool EmitBadCastCall(CodeGenFunction &CGF) override; |
154 | bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override { |
155 | return false; |
156 | } |
157 | |
158 | llvm::Value * |
159 | GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This, |
160 | const CXXRecordDecl *ClassDecl, |
161 | const CXXRecordDecl *BaseClassDecl) override; |
162 | |
163 | llvm::BasicBlock * |
164 | EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, |
165 | const CXXRecordDecl *RD) override; |
166 | |
167 | llvm::BasicBlock * |
168 | EmitDtorCompleteObjectHandler(CodeGenFunction &CGF); |
169 | |
170 | void initializeHiddenVirtualInheritanceMembers(CodeGenFunction &CGF, |
171 | const CXXRecordDecl *RD) override; |
172 | |
173 | void EmitCXXConstructors(const CXXConstructorDecl *D) override; |
174 | |
175 | |
176 | |
177 | |
178 | |
179 | |
180 | |
181 | |
182 | |
183 | |
184 | |
185 | |
186 | |
187 | |
188 | |
189 | |
190 | |
191 | |
192 | |
193 | |
194 | |
195 | |
196 | |
197 | |
198 | |
199 | |
200 | |
201 | |
202 | |
203 | |
204 | |
205 | |
206 | |
207 | AddedStructorArgs |
208 | buildStructorSignature(GlobalDecl GD, |
209 | SmallVectorImpl<CanQualType> &ArgTys) override; |
210 | |
211 | |
212 | bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor, |
213 | CXXDtorType DT) const override { |
214 | return DT != Dtor_Base; |
215 | } |
216 | |
217 | void setCXXDestructorDLLStorage(llvm::GlobalValue *GV, |
218 | const CXXDestructorDecl *Dtor, |
219 | CXXDtorType DT) const override; |
220 | |
221 | llvm::GlobalValue::LinkageTypes |
222 | getCXXDestructorLinkage(GVALinkage Linkage, const CXXDestructorDecl *Dtor, |
223 | CXXDtorType DT) const override; |
224 | |
225 | void EmitCXXDestructors(const CXXDestructorDecl *D) override; |
226 | |
227 | const CXXRecordDecl * |
228 | getThisArgumentTypeForMethod(const CXXMethodDecl *MD) override { |
229 | if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD)) { |
230 | MethodVFTableLocation ML = |
231 | CGM.getMicrosoftVTableContext().getMethodVFTableLocation(MD); |
232 | |
233 | |
234 | |
235 | |
236 | |
237 | |
238 | if (ML.VBase || !ML.VFPtrOffset.isZero()) |
239 | return nullptr; |
240 | } |
241 | return MD->getParent(); |
242 | } |
243 | |
244 | Address |
245 | adjustThisArgumentForVirtualFunctionCall(CodeGenFunction &CGF, GlobalDecl GD, |
246 | Address This, |
247 | bool VirtualCall) override; |
248 | |
249 | void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy, |
250 | FunctionArgList &Params) override; |
251 | |
252 | void EmitInstanceFunctionProlog(CodeGenFunction &CGF) override; |
253 | |
254 | AddedStructorArgs |
255 | addImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D, |
256 | CXXCtorType Type, bool ForVirtualBase, |
257 | bool Delegating, CallArgList &Args) override; |
258 | |
259 | void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, |
260 | CXXDtorType Type, bool ForVirtualBase, |
261 | bool Delegating, Address This) override; |
262 | |
263 | void emitVTableTypeMetadata(const VPtrInfo &Info, const CXXRecordDecl *RD, |
264 | llvm::GlobalVariable *VTable); |
265 | |
266 | void emitVTableDefinitions(CodeGenVTables &CGVT, |
267 | const CXXRecordDecl *RD) override; |
268 | |
269 | bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF, |
270 | CodeGenFunction::VPtr Vptr) override; |
271 | |
272 | |
273 | |
274 | bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass) override { |
275 | return !VTableClass->hasAttr<MSNoVTableAttr>(); |
276 | } |
277 | |
278 | llvm::Constant * |
279 | getVTableAddressPoint(BaseSubobject Base, |
280 | const CXXRecordDecl *VTableClass) override; |
281 | |
282 | llvm::Value *getVTableAddressPointInStructor( |
283 | CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, |
284 | BaseSubobject Base, const CXXRecordDecl *NearestVBase) override; |
285 | |
286 | llvm::Constant * |
287 | getVTableAddressPointForConstExpr(BaseSubobject Base, |
288 | const CXXRecordDecl *VTableClass) override; |
289 | |
290 | llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, |
291 | CharUnits VPtrOffset) override; |
292 | |
293 | CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD, |
294 | Address This, llvm::Type *Ty, |
295 | SourceLocation Loc) override; |
296 | |
297 | llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF, |
298 | const CXXDestructorDecl *Dtor, |
299 | CXXDtorType DtorType, |
300 | Address This, |
301 | const CXXMemberCallExpr *CE) override; |
302 | |
303 | void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD, |
304 | CallArgList &CallArgs) override { |
305 | (0) . __assert_fail ("GD.getDtorType() == Dtor_Deleting && \"Only deleting destructor thunks are available in this ABI\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 306, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(GD.getDtorType() == Dtor_Deleting && |
306 | (0) . __assert_fail ("GD.getDtorType() == Dtor_Deleting && \"Only deleting destructor thunks are available in this ABI\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 306, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Only deleting destructor thunks are available in this ABI"); |
307 | CallArgs.add(RValue::get(getStructorImplicitParamValue(CGF)), |
308 | getContext().IntTy); |
309 | } |
310 | |
311 | void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override; |
312 | |
313 | llvm::GlobalVariable * |
314 | getAddrOfVBTable(const VPtrInfo &VBT, const CXXRecordDecl *RD, |
315 | llvm::GlobalVariable::LinkageTypes Linkage); |
316 | |
317 | llvm::GlobalVariable * |
318 | getAddrOfVirtualDisplacementMap(const CXXRecordDecl *SrcRD, |
319 | const CXXRecordDecl *DstRD) { |
320 | SmallString<256> OutName; |
321 | llvm::raw_svector_ostream Out(OutName); |
322 | getMangleContext().mangleCXXVirtualDisplacementMap(SrcRD, DstRD, Out); |
323 | StringRef MangledName = OutName.str(); |
324 | |
325 | if (auto *VDispMap = CGM.getModule().getNamedGlobal(MangledName)) |
326 | return VDispMap; |
327 | |
328 | MicrosoftVTableContext &VTContext = CGM.getMicrosoftVTableContext(); |
329 | unsigned NumEntries = 1 + SrcRD->getNumVBases(); |
330 | SmallVector<llvm::Constant *, 4> Map(NumEntries, |
331 | llvm::UndefValue::get(CGM.IntTy)); |
332 | Map[0] = llvm::ConstantInt::get(CGM.IntTy, 0); |
333 | bool AnyDifferent = false; |
334 | for (const auto &I : SrcRD->vbases()) { |
335 | const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl(); |
336 | if (!DstRD->isVirtuallyDerivedFrom(VBase)) |
337 | continue; |
338 | |
339 | unsigned SrcVBIndex = VTContext.getVBTableIndex(SrcRD, VBase); |
340 | unsigned DstVBIndex = VTContext.getVBTableIndex(DstRD, VBase); |
341 | Map[SrcVBIndex] = llvm::ConstantInt::get(CGM.IntTy, DstVBIndex * 4); |
342 | AnyDifferent |= SrcVBIndex != DstVBIndex; |
343 | } |
344 | |
345 | if (!AnyDifferent) |
346 | return nullptr; |
347 | |
348 | llvm::ArrayType *VDispMapTy = llvm::ArrayType::get(CGM.IntTy, Map.size()); |
349 | llvm::Constant *Init = llvm::ConstantArray::get(VDispMapTy, Map); |
350 | llvm::GlobalValue::LinkageTypes Linkage = |
351 | SrcRD->isExternallyVisible() && DstRD->isExternallyVisible() |
352 | ? llvm::GlobalValue::LinkOnceODRLinkage |
353 | : llvm::GlobalValue::InternalLinkage; |
354 | auto *VDispMap = new llvm::GlobalVariable( |
355 | CGM.getModule(), VDispMapTy, , Linkage, |
356 | Init, MangledName); |
357 | return VDispMap; |
358 | } |
359 | |
360 | void emitVBTableDefinition(const VPtrInfo &VBT, const CXXRecordDecl *RD, |
361 | llvm::GlobalVariable *GV) const; |
362 | |
363 | void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, |
364 | GlobalDecl GD, bool ReturnAdjustment) override { |
365 | GVALinkage Linkage = |
366 | getContext().GetGVALinkageForFunction(cast<FunctionDecl>(GD.getDecl())); |
367 | |
368 | if (Linkage == GVA_Internal) |
369 | Thunk->setLinkage(llvm::GlobalValue::InternalLinkage); |
370 | else if (ReturnAdjustment) |
371 | Thunk->setLinkage(llvm::GlobalValue::WeakODRLinkage); |
372 | else |
373 | Thunk->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage); |
374 | } |
375 | |
376 | bool exportThunk() override { return false; } |
377 | |
378 | llvm::Value *performThisAdjustment(CodeGenFunction &CGF, Address This, |
379 | const ThisAdjustment &TA) override; |
380 | |
381 | llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, Address Ret, |
382 | const ReturnAdjustment &RA) override; |
383 | |
384 | void EmitThreadLocalInitFuncs( |
385 | CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals, |
386 | ArrayRef<llvm::Function *> CXXThreadLocalInits, |
387 | ArrayRef<const VarDecl *> CXXThreadLocalInitVars) override; |
388 | |
389 | bool usesThreadWrapperFunction() const override { return false; } |
390 | LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD, |
391 | QualType LValType) override; |
392 | |
393 | void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, |
394 | llvm::GlobalVariable *DeclPtr, |
395 | bool PerformInit) override; |
396 | void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, |
397 | llvm::FunctionCallee Dtor, |
398 | llvm::Constant *Addr) override; |
399 | |
400 | |
401 | |
402 | |
403 | |
404 | |
405 | |
406 | |
407 | |
408 | |
409 | |
410 | |
411 | |
412 | |
413 | |
414 | |
415 | |
416 | |
417 | |
418 | |
419 | |
420 | |
421 | |
422 | |
423 | bool requiresArrayCookie(const CXXDeleteExpr *expr, |
424 | QualType elementType) override; |
425 | bool requiresArrayCookie(const CXXNewExpr *expr) override; |
426 | CharUnits getArrayCookieSizeImpl(QualType type) override; |
427 | Address InitializeArrayCookie(CodeGenFunction &CGF, |
428 | Address NewPtr, |
429 | llvm::Value *NumElements, |
430 | const CXXNewExpr *expr, |
431 | QualType ElementType) override; |
432 | llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, |
433 | Address allocPtr, |
434 | CharUnits cookieSize) override; |
435 | |
436 | friend struct MSRTTIBuilder; |
437 | |
438 | bool isImageRelative() const { |
439 | return CGM.getTarget().getPointerWidth() == 64; |
440 | } |
441 | |
442 | |
443 | llvm::StructType *getTypeDescriptorType(StringRef TypeInfoString) { |
444 | llvm::SmallString<32> TDTypeName("rtti.TypeDescriptor"); |
445 | TDTypeName += llvm::utostr(TypeInfoString.size()); |
446 | llvm::StructType *&TypeDescriptorType = |
447 | TypeDescriptorTypeMap[TypeInfoString.size()]; |
448 | if (TypeDescriptorType) |
449 | return TypeDescriptorType; |
450 | llvm::Type *FieldTypes[] = { |
451 | CGM.Int8PtrPtrTy, |
452 | CGM.Int8PtrTy, |
453 | llvm::ArrayType::get(CGM.Int8Ty, TypeInfoString.size() + 1)}; |
454 | TypeDescriptorType = |
455 | llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, TDTypeName); |
456 | return TypeDescriptorType; |
457 | } |
458 | |
459 | llvm::Type *getImageRelativeType(llvm::Type *PtrType) { |
460 | if (!isImageRelative()) |
461 | return PtrType; |
462 | return CGM.IntTy; |
463 | } |
464 | |
465 | llvm::StructType *getBaseClassDescriptorType() { |
466 | if (BaseClassDescriptorType) |
467 | return BaseClassDescriptorType; |
468 | llvm::Type *FieldTypes[] = { |
469 | getImageRelativeType(CGM.Int8PtrTy), |
470 | CGM.IntTy, |
471 | CGM.IntTy, |
472 | CGM.IntTy, |
473 | CGM.IntTy, |
474 | CGM.IntTy, |
475 | getImageRelativeType(getClassHierarchyDescriptorType()->getPointerTo()), |
476 | }; |
477 | BaseClassDescriptorType = llvm::StructType::create( |
478 | CGM.getLLVMContext(), FieldTypes, "rtti.BaseClassDescriptor"); |
479 | return BaseClassDescriptorType; |
480 | } |
481 | |
482 | llvm::StructType *getClassHierarchyDescriptorType() { |
483 | if (ClassHierarchyDescriptorType) |
484 | return ClassHierarchyDescriptorType; |
485 | |
486 | ClassHierarchyDescriptorType = llvm::StructType::create( |
487 | CGM.getLLVMContext(), "rtti.ClassHierarchyDescriptor"); |
488 | llvm::Type *FieldTypes[] = { |
489 | CGM.IntTy, |
490 | CGM.IntTy, |
491 | CGM.IntTy, |
492 | getImageRelativeType( |
493 | getBaseClassDescriptorType()->getPointerTo()->getPointerTo()), |
494 | }; |
495 | ClassHierarchyDescriptorType->setBody(FieldTypes); |
496 | return ClassHierarchyDescriptorType; |
497 | } |
498 | |
499 | llvm::StructType *getCompleteObjectLocatorType() { |
500 | if (CompleteObjectLocatorType) |
501 | return CompleteObjectLocatorType; |
502 | CompleteObjectLocatorType = llvm::StructType::create( |
503 | CGM.getLLVMContext(), "rtti.CompleteObjectLocator"); |
504 | llvm::Type *FieldTypes[] = { |
505 | CGM.IntTy, |
506 | CGM.IntTy, |
507 | CGM.IntTy, |
508 | getImageRelativeType(CGM.Int8PtrTy), |
509 | getImageRelativeType(getClassHierarchyDescriptorType()->getPointerTo()), |
510 | getImageRelativeType(CompleteObjectLocatorType), |
511 | }; |
512 | llvm::ArrayRef<llvm::Type *> FieldTypesRef(FieldTypes); |
513 | if (!isImageRelative()) |
514 | FieldTypesRef = FieldTypesRef.drop_back(); |
515 | CompleteObjectLocatorType->setBody(FieldTypesRef); |
516 | return CompleteObjectLocatorType; |
517 | } |
518 | |
519 | llvm::GlobalVariable *getImageBase() { |
520 | StringRef Name = "__ImageBase"; |
521 | if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name)) |
522 | return GV; |
523 | |
524 | auto *GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8Ty, |
525 | , |
526 | llvm::GlobalValue::ExternalLinkage, |
527 | , Name); |
528 | CGM.setDSOLocal(GV); |
529 | return GV; |
530 | } |
531 | |
532 | llvm::Constant *getImageRelativeConstant(llvm::Constant *PtrVal) { |
533 | if (!isImageRelative()) |
534 | return PtrVal; |
535 | |
536 | if (PtrVal->isNullValue()) |
537 | return llvm::Constant::getNullValue(CGM.IntTy); |
538 | |
539 | llvm::Constant *ImageBaseAsInt = |
540 | llvm::ConstantExpr::getPtrToInt(getImageBase(), CGM.IntPtrTy); |
541 | llvm::Constant *PtrValAsInt = |
542 | llvm::ConstantExpr::getPtrToInt(PtrVal, CGM.IntPtrTy); |
543 | llvm::Constant *Diff = |
544 | llvm::ConstantExpr::getSub(PtrValAsInt, ImageBaseAsInt, |
545 | , ); |
546 | return llvm::ConstantExpr::getTrunc(Diff, CGM.IntTy); |
547 | } |
548 | |
549 | private: |
550 | MicrosoftMangleContext &getMangleContext() { |
551 | return cast<MicrosoftMangleContext>(CodeGen::CGCXXABI::getMangleContext()); |
552 | } |
553 | |
554 | llvm::Constant *getZeroInt() { |
555 | return llvm::ConstantInt::get(CGM.IntTy, 0); |
556 | } |
557 | |
558 | llvm::Constant *getAllOnesInt() { |
559 | return llvm::Constant::getAllOnesValue(CGM.IntTy); |
560 | } |
561 | |
562 | CharUnits getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD) override; |
563 | |
564 | void |
565 | GetNullMemberPointerFields(const MemberPointerType *MPT, |
566 | llvm::SmallVectorImpl<llvm::Constant *> &fields); |
567 | |
568 | |
569 | |
570 | |
571 | llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF, |
572 | Address Base, |
573 | llvm::Value *VBPtrOffset, |
574 | llvm::Value *VBTableOffset, |
575 | llvm::Value **VBPtr = nullptr); |
576 | |
577 | llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF, |
578 | Address Base, |
579 | int32_t VBPtrOffset, |
580 | int32_t VBTableOffset, |
581 | llvm::Value **VBPtr = nullptr) { |
582 | (0) . __assert_fail ("VBTableOffset % 4 == 0 && \"should be byte offset into table of i32s\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 582, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(VBTableOffset % 4 == 0 && "should be byte offset into table of i32s"); |
583 | llvm::Value *VBPOffset = llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset), |
584 | *VBTOffset = llvm::ConstantInt::get(CGM.IntTy, VBTableOffset); |
585 | return GetVBaseOffsetFromVBPtr(CGF, Base, VBPOffset, VBTOffset, VBPtr); |
586 | } |
587 | |
588 | std::tuple<Address, llvm::Value *, const CXXRecordDecl *> |
589 | performBaseAdjustment(CodeGenFunction &CGF, Address Value, |
590 | QualType SrcRecordTy); |
591 | |
592 | |
593 | |
594 | llvm::Value *AdjustVirtualBase(CodeGenFunction &CGF, const Expr *E, |
595 | const CXXRecordDecl *RD, Address Base, |
596 | llvm::Value *VirtualBaseAdjustmentOffset, |
597 | llvm::Value *VBPtrOffset ); |
598 | |
599 | |
600 | |
601 | llvm::Constant *EmitFullMemberPointer(llvm::Constant *FirstField, |
602 | bool IsMemberFunction, |
603 | const CXXRecordDecl *RD, |
604 | CharUnits NonVirtualBaseAdjustment, |
605 | unsigned VBTableIndex); |
606 | |
607 | bool MemberPointerConstantIsNull(const MemberPointerType *MPT, |
608 | llvm::Constant *MP); |
609 | |
610 | |
611 | void EmitVBPtrStores(CodeGenFunction &CGF, const CXXRecordDecl *RD); |
612 | |
613 | |
614 | const VBTableGlobals &enumerateVBTables(const CXXRecordDecl *RD); |
615 | |
616 | |
617 | llvm::Function *EmitVirtualMemPtrThunk(const CXXMethodDecl *MD, |
618 | const MethodVFTableLocation &ML); |
619 | |
620 | public: |
621 | llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT) override; |
622 | |
623 | bool isZeroInitializable(const MemberPointerType *MPT) override; |
624 | |
625 | bool isMemberPointerConvertible(const MemberPointerType *MPT) const override { |
626 | const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); |
627 | return RD->hasAttr<MSInheritanceAttr>(); |
628 | } |
629 | |
630 | llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT) override; |
631 | |
632 | llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT, |
633 | CharUnits offset) override; |
634 | llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD) override; |
635 | llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT) override; |
636 | |
637 | llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF, |
638 | llvm::Value *L, |
639 | llvm::Value *R, |
640 | const MemberPointerType *MPT, |
641 | bool Inequality) override; |
642 | |
643 | llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF, |
644 | llvm::Value *MemPtr, |
645 | const MemberPointerType *MPT) override; |
646 | |
647 | llvm::Value * |
648 | EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E, |
649 | Address Base, llvm::Value *MemPtr, |
650 | const MemberPointerType *MPT) override; |
651 | |
652 | llvm::Value *EmitNonNullMemberPointerConversion( |
653 | const MemberPointerType *SrcTy, const MemberPointerType *DstTy, |
654 | CastKind CK, CastExpr::path_const_iterator PathBegin, |
655 | CastExpr::path_const_iterator PathEnd, llvm::Value *Src, |
656 | CGBuilderTy &Builder); |
657 | |
658 | llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF, |
659 | const CastExpr *E, |
660 | llvm::Value *Src) override; |
661 | |
662 | llvm::Constant *EmitMemberPointerConversion(const CastExpr *E, |
663 | llvm::Constant *Src) override; |
664 | |
665 | llvm::Constant *EmitMemberPointerConversion( |
666 | const MemberPointerType *SrcTy, const MemberPointerType *DstTy, |
667 | CastKind CK, CastExpr::path_const_iterator PathBegin, |
668 | CastExpr::path_const_iterator PathEnd, llvm::Constant *Src); |
669 | |
670 | CGCallee |
671 | EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E, |
672 | Address This, llvm::Value *&ThisPtrForCall, |
673 | llvm::Value *MemPtr, |
674 | const MemberPointerType *MPT) override; |
675 | |
676 | void emitCXXStructor(GlobalDecl GD) override; |
677 | |
678 | llvm::StructType *getCatchableTypeType() { |
679 | if (CatchableTypeType) |
680 | return CatchableTypeType; |
681 | llvm::Type *FieldTypes[] = { |
682 | CGM.IntTy, |
683 | getImageRelativeType(CGM.Int8PtrTy), |
684 | CGM.IntTy, |
685 | CGM.IntTy, |
686 | CGM.IntTy, |
687 | CGM.IntTy, |
688 | getImageRelativeType(CGM.Int8PtrTy) |
689 | }; |
690 | CatchableTypeType = llvm::StructType::create( |
691 | CGM.getLLVMContext(), FieldTypes, "eh.CatchableType"); |
692 | return CatchableTypeType; |
693 | } |
694 | |
695 | llvm::StructType *getCatchableTypeArrayType(uint32_t NumEntries) { |
696 | llvm::StructType *&CatchableTypeArrayType = |
697 | CatchableTypeArrayTypeMap[NumEntries]; |
698 | if (CatchableTypeArrayType) |
699 | return CatchableTypeArrayType; |
700 | |
701 | llvm::SmallString<23> CTATypeName("eh.CatchableTypeArray."); |
702 | CTATypeName += llvm::utostr(NumEntries); |
703 | llvm::Type *CTType = |
704 | getImageRelativeType(getCatchableTypeType()->getPointerTo()); |
705 | llvm::Type *FieldTypes[] = { |
706 | CGM.IntTy, |
707 | llvm::ArrayType::get(CTType, NumEntries) |
708 | }; |
709 | CatchableTypeArrayType = |
710 | llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, CTATypeName); |
711 | return CatchableTypeArrayType; |
712 | } |
713 | |
714 | llvm::StructType *getThrowInfoType() { |
715 | if (ThrowInfoType) |
716 | return ThrowInfoType; |
717 | llvm::Type *FieldTypes[] = { |
718 | CGM.IntTy, |
719 | getImageRelativeType(CGM.Int8PtrTy), |
720 | getImageRelativeType(CGM.Int8PtrTy), |
721 | getImageRelativeType(CGM.Int8PtrTy) |
722 | }; |
723 | ThrowInfoType = llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, |
724 | "eh.ThrowInfo"); |
725 | return ThrowInfoType; |
726 | } |
727 | |
728 | llvm::FunctionCallee getThrowFn() { |
729 | |
730 | |
731 | llvm::Type *Args[] = {CGM.Int8PtrTy, getThrowInfoType()->getPointerTo()}; |
732 | llvm::FunctionType *FTy = |
733 | llvm::FunctionType::get(CGM.VoidTy, Args, ); |
734 | llvm::FunctionCallee Throw = |
735 | CGM.CreateRuntimeFunction(FTy, "_CxxThrowException"); |
736 | |
737 | if (CGM.getTarget().getTriple().getArch() == llvm::Triple::x86) { |
738 | if (auto *Fn = dyn_cast<llvm::Function>(Throw.getCallee())) |
739 | Fn->setCallingConv(llvm::CallingConv::X86_StdCall); |
740 | } |
741 | return Throw; |
742 | } |
743 | |
744 | llvm::Function *getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD, |
745 | CXXCtorType CT); |
746 | |
747 | llvm::Constant *getCatchableType(QualType T, |
748 | uint32_t NVOffset = 0, |
749 | int32_t VBPtrOffset = -1, |
750 | uint32_t VBIndex = 0); |
751 | |
752 | llvm::GlobalVariable *getCatchableTypeArray(QualType T); |
753 | |
754 | llvm::GlobalVariable *getThrowInfo(QualType T) override; |
755 | |
756 | std::pair<llvm::Value *, const CXXRecordDecl *> |
757 | LoadVTablePtr(CodeGenFunction &CGF, Address This, |
758 | const CXXRecordDecl *RD) override; |
759 | |
760 | private: |
761 | typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy; |
762 | typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *> VTablesMapTy; |
763 | typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalValue *> VFTablesMapTy; |
764 | |
765 | VFTablesMapTy VFTablesMap; |
766 | VTablesMapTy VTablesMap; |
767 | |
768 | |
769 | llvm::SmallPtrSet<const CXXRecordDecl *, 4> DeferredVFTables; |
770 | |
771 | |
772 | |
773 | llvm::DenseMap<const CXXRecordDecl *, VBTableGlobals> VBTablesMap; |
774 | |
775 | |
776 | |
777 | struct GuardInfo { |
778 | GuardInfo() : Guard(nullptr), BitIndex(0) {} |
779 | llvm::GlobalVariable *Guard; |
780 | unsigned BitIndex; |
781 | }; |
782 | |
783 | |
784 | |
785 | llvm::DenseMap<const DeclContext *, GuardInfo> GuardVariableMap; |
786 | llvm::DenseMap<const DeclContext *, GuardInfo> ThreadLocalGuardVariableMap; |
787 | llvm::DenseMap<const DeclContext *, unsigned> ThreadSafeGuardNumMap; |
788 | |
789 | llvm::DenseMap<size_t, llvm::StructType *> TypeDescriptorTypeMap; |
790 | llvm::StructType *BaseClassDescriptorType; |
791 | llvm::StructType *ClassHierarchyDescriptorType; |
792 | llvm::StructType *CompleteObjectLocatorType; |
793 | |
794 | llvm::DenseMap<QualType, llvm::GlobalVariable *> CatchableTypeArrays; |
795 | |
796 | llvm::StructType *CatchableTypeType; |
797 | llvm::DenseMap<uint32_t, llvm::StructType *> CatchableTypeArrayTypeMap; |
798 | llvm::StructType *ThrowInfoType; |
799 | }; |
800 | |
801 | } |
802 | |
803 | CGCXXABI::RecordArgABI |
804 | MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const { |
805 | switch (CGM.getTarget().getTriple().getArch()) { |
806 | default: |
807 | |
808 | return RAA_Default; |
809 | |
810 | case llvm::Triple::thumb: |
811 | |
812 | |
813 | |
814 | return !canCopyArgument(RD) ? RAA_Indirect : RAA_Default; |
815 | |
816 | case llvm::Triple::x86: |
817 | |
818 | |
819 | |
820 | |
821 | |
822 | |
823 | if (!canCopyArgument(RD)) |
824 | return RAA_DirectInMemory; |
825 | |
826 | |
827 | |
828 | return RAA_Default; |
829 | |
830 | case llvm::Triple::x86_64: |
831 | case llvm::Triple::aarch64: |
832 | return !canCopyArgument(RD) ? RAA_Indirect : RAA_Default; |
833 | } |
834 | |
835 | llvm_unreachable("invalid enum"); |
836 | } |
837 | |
838 | void MicrosoftCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, |
839 | const CXXDeleteExpr *DE, |
840 | Address Ptr, |
841 | QualType ElementType, |
842 | const CXXDestructorDecl *Dtor) { |
843 | |
844 | |
845 | bool UseGlobalDelete = DE->isGlobalDelete(); |
846 | CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting; |
847 | llvm::Value *MDThis = |
848 | EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, ); |
849 | if (UseGlobalDelete) |
850 | CGF.EmitDeleteCall(DE->getOperatorDelete(), MDThis, ElementType); |
851 | } |
852 | |
853 | void MicrosoftCXXABI::emitRethrow(CodeGenFunction &CGF, bool isNoReturn) { |
854 | llvm::Value *Args[] = { |
855 | llvm::ConstantPointerNull::get(CGM.Int8PtrTy), |
856 | llvm::ConstantPointerNull::get(getThrowInfoType()->getPointerTo())}; |
857 | llvm::FunctionCallee Fn = getThrowFn(); |
858 | if (isNoReturn) |
859 | CGF.EmitNoreturnRuntimeCallOrInvoke(Fn, Args); |
860 | else |
861 | CGF.EmitRuntimeCallOrInvoke(Fn, Args); |
862 | } |
863 | |
864 | void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF, |
865 | const CXXCatchStmt *S) { |
866 | |
867 | |
868 | VarDecl *CatchParam = S->getExceptionDecl(); |
869 | llvm::BasicBlock *CatchPadBB = CGF.Builder.GetInsertBlock(); |
870 | llvm::CatchPadInst *CPI = |
871 | cast<llvm::CatchPadInst>(CatchPadBB->getFirstNonPHI()); |
872 | CGF.CurrentFuncletPad = CPI; |
873 | |
874 | |
875 | |
876 | if (!CatchParam || !CatchParam->getDeclName()) { |
877 | CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI); |
878 | return; |
879 | } |
880 | |
881 | CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam); |
882 | CPI->setArgOperand(2, var.getObjectAddress(CGF).getPointer()); |
883 | CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI); |
884 | CGF.EmitAutoVarCleanups(var); |
885 | } |
886 | |
887 | |
888 | |
889 | |
890 | std::tuple<Address, llvm::Value *, const CXXRecordDecl *> |
891 | MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address Value, |
892 | QualType SrcRecordTy) { |
893 | Value = CGF.Builder.CreateBitCast(Value, CGF.Int8PtrTy); |
894 | const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl(); |
895 | const ASTContext &Context = getContext(); |
896 | |
897 | |
898 | |
899 | |
900 | if (Context.getASTRecordLayout(SrcDecl).hasExtendableVFPtr()) |
901 | return std::make_tuple(Value, llvm::ConstantInt::get(CGF.Int32Ty, 0), |
902 | SrcDecl); |
903 | |
904 | |
905 | |
906 | const CXXRecordDecl *PolymorphicBase = nullptr; |
907 | for (auto &Base : SrcDecl->vbases()) { |
908 | const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); |
909 | if (Context.getASTRecordLayout(BaseDecl).hasExtendableVFPtr()) { |
910 | PolymorphicBase = BaseDecl; |
911 | break; |
912 | } |
913 | } |
914 | (0) . __assert_fail ("PolymorphicBase && \"polymorphic class has no apparent vfptr?\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 914, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(PolymorphicBase && "polymorphic class has no apparent vfptr?"); |
915 | |
916 | llvm::Value *Offset = |
917 | GetVirtualBaseClassOffset(CGF, Value, SrcDecl, PolymorphicBase); |
918 | llvm::Value *Ptr = CGF.Builder.CreateInBoundsGEP(Value.getPointer(), Offset); |
919 | CharUnits VBaseAlign = |
920 | CGF.CGM.getVBaseAlignment(Value.getAlignment(), SrcDecl, PolymorphicBase); |
921 | return std::make_tuple(Address(Ptr, VBaseAlign), Offset, PolymorphicBase); |
922 | } |
923 | |
924 | bool MicrosoftCXXABI::shouldTypeidBeNullChecked(bool IsDeref, |
925 | QualType SrcRecordTy) { |
926 | const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl(); |
927 | return IsDeref && |
928 | !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr(); |
929 | } |
930 | |
931 | static llvm::CallBase *emitRTtypeidCall(CodeGenFunction &CGF, |
932 | llvm::Value *Argument) { |
933 | llvm::Type *ArgTypes[] = {CGF.Int8PtrTy}; |
934 | llvm::FunctionType *FTy = |
935 | llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false); |
936 | llvm::Value *Args[] = {Argument}; |
937 | llvm::FunctionCallee Fn = CGF.CGM.CreateRuntimeFunction(FTy, "__RTtypeid"); |
938 | return CGF.EmitRuntimeCallOrInvoke(Fn, Args); |
939 | } |
940 | |
941 | void MicrosoftCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) { |
942 | llvm::CallBase *Call = |
943 | emitRTtypeidCall(CGF, llvm::Constant::getNullValue(CGM.VoidPtrTy)); |
944 | Call->setDoesNotReturn(); |
945 | CGF.Builder.CreateUnreachable(); |
946 | } |
947 | |
948 | llvm::Value *MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF, |
949 | QualType SrcRecordTy, |
950 | Address ThisPtr, |
951 | llvm::Type *StdTypeInfoPtrTy) { |
952 | std::tie(ThisPtr, std::ignore, std::ignore) = |
953 | performBaseAdjustment(CGF, ThisPtr, SrcRecordTy); |
954 | llvm::CallBase *Typeid = emitRTtypeidCall(CGF, ThisPtr.getPointer()); |
955 | return CGF.Builder.CreateBitCast(Typeid, StdTypeInfoPtrTy); |
956 | } |
957 | |
958 | bool MicrosoftCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr, |
959 | QualType SrcRecordTy) { |
960 | const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl(); |
961 | return SrcIsPtr && |
962 | !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr(); |
963 | } |
964 | |
965 | llvm::Value *MicrosoftCXXABI::EmitDynamicCastCall( |
966 | CodeGenFunction &CGF, Address This, QualType SrcRecordTy, |
967 | QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd) { |
968 | llvm::Type *DestLTy = CGF.ConvertType(DestTy); |
969 | |
970 | llvm::Value *SrcRTTI = |
971 | CGF.CGM.GetAddrOfRTTIDescriptor(SrcRecordTy.getUnqualifiedType()); |
972 | llvm::Value *DestRTTI = |
973 | CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType()); |
974 | |
975 | llvm::Value *Offset; |
976 | std::tie(This, Offset, std::ignore) = |
977 | performBaseAdjustment(CGF, This, SrcRecordTy); |
978 | llvm::Value *ThisPtr = This.getPointer(); |
979 | Offset = CGF.Builder.CreateTrunc(Offset, CGF.Int32Ty); |
980 | |
981 | |
982 | |
983 | |
984 | |
985 | |
986 | |
987 | llvm::Type *ArgTypes[] = {CGF.Int8PtrTy, CGF.Int32Ty, CGF.Int8PtrTy, |
988 | CGF.Int8PtrTy, CGF.Int32Ty}; |
989 | llvm::FunctionCallee Function = CGF.CGM.CreateRuntimeFunction( |
990 | llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false), |
991 | "__RTDynamicCast"); |
992 | llvm::Value *Args[] = { |
993 | ThisPtr, Offset, SrcRTTI, DestRTTI, |
994 | llvm::ConstantInt::get(CGF.Int32Ty, DestTy->isReferenceType())}; |
995 | ThisPtr = CGF.EmitRuntimeCallOrInvoke(Function, Args); |
996 | return CGF.Builder.CreateBitCast(ThisPtr, DestLTy); |
997 | } |
998 | |
999 | llvm::Value * |
1000 | MicrosoftCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF, Address Value, |
1001 | QualType SrcRecordTy, |
1002 | QualType DestTy) { |
1003 | std::tie(Value, std::ignore, std::ignore) = |
1004 | performBaseAdjustment(CGF, Value, SrcRecordTy); |
1005 | |
1006 | |
1007 | |
1008 | llvm::Type *ArgTypes[] = {CGF.Int8PtrTy}; |
1009 | llvm::FunctionCallee Function = CGF.CGM.CreateRuntimeFunction( |
1010 | llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false), |
1011 | "__RTCastToVoid"); |
1012 | llvm::Value *Args[] = {Value.getPointer()}; |
1013 | return CGF.EmitRuntimeCall(Function, Args); |
1014 | } |
1015 | |
1016 | bool MicrosoftCXXABI::EmitBadCastCall(CodeGenFunction &CGF) { |
1017 | return false; |
1018 | } |
1019 | |
1020 | llvm::Value *MicrosoftCXXABI::GetVirtualBaseClassOffset( |
1021 | CodeGenFunction &CGF, Address This, const CXXRecordDecl *ClassDecl, |
1022 | const CXXRecordDecl *BaseClassDecl) { |
1023 | const ASTContext &Context = getContext(); |
1024 | int64_t VBPtrChars = |
1025 | Context.getASTRecordLayout(ClassDecl).getVBPtrOffset().getQuantity(); |
1026 | llvm::Value *VBPtrOffset = llvm::ConstantInt::get(CGM.PtrDiffTy, VBPtrChars); |
1027 | CharUnits IntSize = Context.getTypeSizeInChars(Context.IntTy); |
1028 | CharUnits VBTableChars = |
1029 | IntSize * |
1030 | CGM.getMicrosoftVTableContext().getVBTableIndex(ClassDecl, BaseClassDecl); |
1031 | llvm::Value *VBTableOffset = |
1032 | llvm::ConstantInt::get(CGM.IntTy, VBTableChars.getQuantity()); |
1033 | |
1034 | llvm::Value *VBPtrToNewBase = |
1035 | GetVBaseOffsetFromVBPtr(CGF, This, VBPtrOffset, VBTableOffset); |
1036 | VBPtrToNewBase = |
1037 | CGF.Builder.CreateSExtOrBitCast(VBPtrToNewBase, CGM.PtrDiffTy); |
1038 | return CGF.Builder.CreateNSWAdd(VBPtrOffset, VBPtrToNewBase); |
1039 | } |
1040 | |
1041 | bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD) const { |
1042 | return isa<CXXConstructorDecl>(GD.getDecl()); |
1043 | } |
1044 | |
1045 | static bool isDeletingDtor(GlobalDecl GD) { |
1046 | return isa<CXXDestructorDecl>(GD.getDecl()) && |
1047 | GD.getDtorType() == Dtor_Deleting; |
1048 | } |
1049 | |
1050 | bool MicrosoftCXXABI::hasMostDerivedReturn(GlobalDecl GD) const { |
1051 | return isDeletingDtor(GD); |
1052 | } |
1053 | |
1054 | bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI) const { |
1055 | const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl(); |
1056 | if (!RD) |
1057 | return false; |
1058 | |
1059 | CharUnits Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType()); |
1060 | if (FI.isInstanceMethod()) { |
1061 | |
1062 | |
1063 | FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, ); |
1064 | FI.getReturnInfo().setSRetAfterThis(FI.isInstanceMethod()); |
1065 | |
1066 | |
1067 | |
1068 | |
1069 | FI.getReturnInfo().setSuppressSRet(CGM.getTarget().getTriple().getArch() == |
1070 | llvm::Triple::aarch64); |
1071 | return true; |
1072 | } else if (!RD->isPOD()) { |
1073 | |
1074 | FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, ); |
1075 | |
1076 | |
1077 | |
1078 | |
1079 | FI.getReturnInfo().setSuppressSRet(CGM.getTarget().getTriple().getArch() == |
1080 | llvm::Triple::aarch64); |
1081 | return true; |
1082 | } |
1083 | |
1084 | |
1085 | return false; |
1086 | } |
1087 | |
1088 | llvm::BasicBlock * |
1089 | MicrosoftCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, |
1090 | const CXXRecordDecl *RD) { |
1091 | llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF); |
1092 | (0) . __assert_fail ("IsMostDerivedClass && \"ctor for a class with virtual bases must have an implicit parameter\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 1093, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(IsMostDerivedClass && |
1093 | (0) . __assert_fail ("IsMostDerivedClass && \"ctor for a class with virtual bases must have an implicit parameter\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 1093, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "ctor for a class with virtual bases must have an implicit parameter"); |
1094 | llvm::Value *IsCompleteObject = |
1095 | CGF.Builder.CreateIsNotNull(IsMostDerivedClass, "is_complete_object"); |
1096 | |
1097 | llvm::BasicBlock *CallVbaseCtorsBB = CGF.createBasicBlock("ctor.init_vbases"); |
1098 | llvm::BasicBlock *SkipVbaseCtorsBB = CGF.createBasicBlock("ctor.skip_vbases"); |
1099 | CGF.Builder.CreateCondBr(IsCompleteObject, |
1100 | CallVbaseCtorsBB, SkipVbaseCtorsBB); |
1101 | |
1102 | CGF.EmitBlock(CallVbaseCtorsBB); |
1103 | |
1104 | |
1105 | EmitVBPtrStores(CGF, RD); |
1106 | |
1107 | |
1108 | |
1109 | return SkipVbaseCtorsBB; |
1110 | } |
1111 | |
1112 | llvm::BasicBlock * |
1113 | MicrosoftCXXABI::EmitDtorCompleteObjectHandler(CodeGenFunction &CGF) { |
1114 | llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF); |
1115 | (0) . __assert_fail ("IsMostDerivedClass && \"ctor for a class with virtual bases must have an implicit parameter\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 1116, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(IsMostDerivedClass && |
1116 | (0) . __assert_fail ("IsMostDerivedClass && \"ctor for a class with virtual bases must have an implicit parameter\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 1116, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "ctor for a class with virtual bases must have an implicit parameter"); |
1117 | llvm::Value *IsCompleteObject = |
1118 | CGF.Builder.CreateIsNotNull(IsMostDerivedClass, "is_complete_object"); |
1119 | |
1120 | llvm::BasicBlock *CallVbaseDtorsBB = CGF.createBasicBlock("Dtor.dtor_vbases"); |
1121 | llvm::BasicBlock *SkipVbaseDtorsBB = CGF.createBasicBlock("Dtor.skip_vbases"); |
1122 | CGF.Builder.CreateCondBr(IsCompleteObject, |
1123 | CallVbaseDtorsBB, SkipVbaseDtorsBB); |
1124 | |
1125 | CGF.EmitBlock(CallVbaseDtorsBB); |
1126 | |
1127 | |
1128 | return SkipVbaseDtorsBB; |
1129 | } |
1130 | |
1131 | void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers( |
1132 | CodeGenFunction &CGF, const CXXRecordDecl *RD) { |
1133 | |
1134 | |
1135 | |
1136 | |
1137 | |
1138 | |
1139 | |
1140 | |
1141 | |
1142 | |
1143 | |
1144 | |
1145 | |
1146 | const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); |
1147 | typedef ASTRecordLayout::VBaseOffsetsMapTy VBOffsets; |
1148 | const VBOffsets &VBaseMap = Layout.getVBaseOffsetsMap(); |
1149 | CGBuilderTy &Builder = CGF.Builder; |
1150 | |
1151 | unsigned AS = getThisAddress(CGF).getAddressSpace(); |
1152 | llvm::Value *Int8This = nullptr; |
1153 | |
1154 | for (const CXXBaseSpecifier &S : RD->vbases()) { |
1155 | const CXXRecordDecl *VBase = S.getType()->getAsCXXRecordDecl(); |
1156 | auto I = VBaseMap.find(VBase); |
1157 | assert(I != VBaseMap.end()); |
1158 | if (!I->second.hasVtorDisp()) |
1159 | continue; |
1160 | |
1161 | llvm::Value *VBaseOffset = |
1162 | GetVirtualBaseClassOffset(CGF, getThisAddress(CGF), RD, VBase); |
1163 | uint64_t ConstantVBaseOffset = I->second.VBaseOffset.getQuantity(); |
1164 | |
1165 | |
1166 | llvm::Value *VtorDispValue = Builder.CreateSub( |
1167 | VBaseOffset, llvm::ConstantInt::get(CGM.PtrDiffTy, ConstantVBaseOffset), |
1168 | "vtordisp.value"); |
1169 | VtorDispValue = Builder.CreateTruncOrBitCast(VtorDispValue, CGF.Int32Ty); |
1170 | |
1171 | if (!Int8This) |
1172 | Int8This = Builder.CreateBitCast(getThisValue(CGF), |
1173 | CGF.Int8Ty->getPointerTo(AS)); |
1174 | llvm::Value *VtorDispPtr = Builder.CreateInBoundsGEP(Int8This, VBaseOffset); |
1175 | |
1176 | VtorDispPtr = Builder.CreateConstGEP1_32(VtorDispPtr, -4); |
1177 | VtorDispPtr = Builder.CreateBitCast( |
1178 | VtorDispPtr, CGF.Int32Ty->getPointerTo(AS), "vtordisp.ptr"); |
1179 | |
1180 | Builder.CreateAlignedStore(VtorDispValue, VtorDispPtr, |
1181 | CharUnits::fromQuantity(4)); |
1182 | } |
1183 | } |
1184 | |
1185 | static bool hasDefaultCXXMethodCC(ASTContext &Context, |
1186 | const CXXMethodDecl *MD) { |
1187 | CallingConv ExpectedCallingConv = Context.getDefaultCallingConvention( |
1188 | , ); |
1189 | CallingConv ActualCallingConv = |
1190 | MD->getType()->getAs<FunctionProtoType>()->getCallConv(); |
1191 | return ExpectedCallingConv == ActualCallingConv; |
1192 | } |
1193 | |
1194 | void MicrosoftCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) { |
1195 | |
1196 | CGM.EmitGlobal(GlobalDecl(D, Ctor_Complete)); |
1197 | |
1198 | |
1199 | |
1200 | |
1201 | |
1202 | if (D->hasAttr<DLLExportAttr>() && D->isDefaultConstructor()) |
1203 | if (!hasDefaultCXXMethodCC(getContext(), D) || D->getNumParams() != 0) { |
1204 | llvm::Function *Fn = getAddrOfCXXCtorClosure(D, Ctor_DefaultClosure); |
1205 | Fn->setLinkage(llvm::GlobalValue::WeakODRLinkage); |
1206 | CGM.setGVProperties(Fn, D); |
1207 | } |
1208 | } |
1209 | |
1210 | void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF, |
1211 | const CXXRecordDecl *RD) { |
1212 | Address This = getThisAddress(CGF); |
1213 | This = CGF.Builder.CreateElementBitCast(This, CGM.Int8Ty, "this.int8"); |
1214 | const ASTContext &Context = getContext(); |
1215 | const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); |
1216 | |
1217 | const VBTableGlobals &VBGlobals = enumerateVBTables(RD); |
1218 | for (unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) { |
1219 | const std::unique_ptr<VPtrInfo> &VBT = (*VBGlobals.VBTables)[I]; |
1220 | llvm::GlobalVariable *GV = VBGlobals.Globals[I]; |
1221 | const ASTRecordLayout &SubobjectLayout = |
1222 | Context.getASTRecordLayout(VBT->IntroducingObject); |
1223 | CharUnits Offs = VBT->NonVirtualOffset; |
1224 | Offs += SubobjectLayout.getVBPtrOffset(); |
1225 | if (VBT->getVBaseWithVPtr()) |
1226 | Offs += Layout.getVBaseClassOffset(VBT->getVBaseWithVPtr()); |
1227 | Address VBPtr = CGF.Builder.CreateConstInBoundsByteGEP(This, Offs); |
1228 | llvm::Value *GVPtr = |
1229 | CGF.Builder.CreateConstInBoundsGEP2_32(GV->getValueType(), GV, 0, 0); |
1230 | VBPtr = CGF.Builder.CreateElementBitCast(VBPtr, GVPtr->getType(), |
1231 | "vbptr." + VBT->ObjectWithVPtr->getName()); |
1232 | CGF.Builder.CreateStore(GVPtr, VBPtr); |
1233 | } |
1234 | } |
1235 | |
1236 | CGCXXABI::AddedStructorArgs |
1237 | MicrosoftCXXABI::buildStructorSignature(GlobalDecl GD, |
1238 | SmallVectorImpl<CanQualType> &ArgTys) { |
1239 | AddedStructorArgs Added; |
1240 | |
1241 | if (isa<CXXDestructorDecl>(GD.getDecl()) && |
1242 | GD.getDtorType() == Dtor_Deleting) { |
1243 | |
1244 | ArgTys.push_back(getContext().IntTy); |
1245 | ++Added.Suffix; |
1246 | } |
1247 | auto *CD = dyn_cast<CXXConstructorDecl>(GD.getDecl()); |
1248 | if (!CD) |
1249 | return Added; |
1250 | |
1251 | |
1252 | |
1253 | |
1254 | const CXXRecordDecl *Class = CD->getParent(); |
1255 | const FunctionProtoType *FPT = CD->getType()->castAs<FunctionProtoType>(); |
1256 | if (Class->getNumVBases()) { |
1257 | if (FPT->isVariadic()) { |
1258 | ArgTys.insert(ArgTys.begin() + 1, getContext().IntTy); |
1259 | ++Added.Prefix; |
1260 | } else { |
1261 | ArgTys.push_back(getContext().IntTy); |
1262 | ++Added.Suffix; |
1263 | } |
1264 | } |
1265 | |
1266 | return Added; |
1267 | } |
1268 | |
1269 | void MicrosoftCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV, |
1270 | const CXXDestructorDecl *Dtor, |
1271 | CXXDtorType DT) const { |
1272 | |
1273 | |
1274 | if (DT == Dtor_Deleting) { |
1275 | GV->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); |
1276 | } else { |
1277 | const NamedDecl *ND = Dtor; |
1278 | CGM.setDLLImportDLLExport(GV, ND); |
1279 | } |
1280 | } |
1281 | |
1282 | llvm::GlobalValue::LinkageTypes MicrosoftCXXABI::getCXXDestructorLinkage( |
1283 | GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const { |
1284 | |
1285 | |
1286 | if (Linkage == GVA_Internal) |
1287 | return llvm::GlobalValue::InternalLinkage; |
1288 | |
1289 | switch (DT) { |
1290 | case Dtor_Base: |
1291 | |
1292 | |
1293 | return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage, |
1294 | ); |
1295 | case Dtor_Complete: |
1296 | |
1297 | |
1298 | |
1299 | if (Dtor->hasAttr<DLLExportAttr>()) |
1300 | return llvm::GlobalValue::WeakODRLinkage; |
1301 | if (Dtor->hasAttr<DLLImportAttr>()) |
1302 | return llvm::GlobalValue::AvailableExternallyLinkage; |
1303 | return llvm::GlobalValue::LinkOnceODRLinkage; |
1304 | case Dtor_Deleting: |
1305 | |
1306 | |
1307 | |
1308 | return llvm::GlobalValue::LinkOnceODRLinkage; |
1309 | case Dtor_Comdat: |
1310 | llvm_unreachable("MS C++ ABI does not support comdat dtors"); |
1311 | } |
1312 | llvm_unreachable("invalid dtor type"); |
1313 | } |
1314 | |
1315 | void MicrosoftCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) { |
1316 | |
1317 | |
1318 | CGM.EmitGlobal(GlobalDecl(D, Dtor_Base)); |
1319 | } |
1320 | |
1321 | CharUnits |
1322 | MicrosoftCXXABI::getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD) { |
1323 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); |
1324 | |
1325 | if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { |
1326 | |
1327 | |
1328 | if (GD.getDtorType() == Dtor_Complete) |
1329 | return CharUnits(); |
1330 | |
1331 | |
1332 | |
1333 | GD = GlobalDecl(DD, Dtor_Deleting); |
1334 | } |
1335 | |
1336 | MethodVFTableLocation ML = |
1337 | CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD); |
1338 | CharUnits Adjustment = ML.VFPtrOffset; |
1339 | |
1340 | |
1341 | |
1342 | |
1343 | |
1344 | if (isa<CXXDestructorDecl>(MD)) |
1345 | Adjustment = CharUnits::Zero(); |
1346 | |
1347 | if (ML.VBase) { |
1348 | const ASTRecordLayout &DerivedLayout = |
1349 | getContext().getASTRecordLayout(MD->getParent()); |
1350 | Adjustment += DerivedLayout.getVBaseClassOffset(ML.VBase); |
1351 | } |
1352 | |
1353 | return Adjustment; |
1354 | } |
1355 | |
1356 | Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall( |
1357 | CodeGenFunction &CGF, GlobalDecl GD, Address This, |
1358 | bool VirtualCall) { |
1359 | if (!VirtualCall) { |
1360 | |
1361 | |
1362 | CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(GD); |
1363 | if (Adjustment.isZero()) |
1364 | return This; |
1365 | |
1366 | This = CGF.Builder.CreateElementBitCast(This, CGF.Int8Ty); |
1367 | assert(Adjustment.isPositive()); |
1368 | return CGF.Builder.CreateConstByteGEP(This, Adjustment); |
1369 | } |
1370 | |
1371 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); |
1372 | |
1373 | GlobalDecl LookupGD = GD; |
1374 | if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { |
1375 | |
1376 | |
1377 | if (GD.getDtorType() == Dtor_Complete) |
1378 | return This; |
1379 | |
1380 | |
1381 | |
1382 | LookupGD = GlobalDecl(DD, Dtor_Deleting); |
1383 | } |
1384 | MethodVFTableLocation ML = |
1385 | CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD); |
1386 | |
1387 | CharUnits StaticOffset = ML.VFPtrOffset; |
1388 | |
1389 | |
1390 | |
1391 | |
1392 | if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base) |
1393 | StaticOffset = CharUnits::Zero(); |
1394 | |
1395 | Address Result = This; |
1396 | if (ML.VBase) { |
1397 | Result = CGF.Builder.CreateElementBitCast(Result, CGF.Int8Ty); |
1398 | |
1399 | const CXXRecordDecl *Derived = MD->getParent(); |
1400 | const CXXRecordDecl *VBase = ML.VBase; |
1401 | llvm::Value *VBaseOffset = |
1402 | GetVirtualBaseClassOffset(CGF, Result, Derived, VBase); |
1403 | llvm::Value *VBasePtr = |
1404 | CGF.Builder.CreateInBoundsGEP(Result.getPointer(), VBaseOffset); |
1405 | CharUnits VBaseAlign = |
1406 | CGF.CGM.getVBaseAlignment(Result.getAlignment(), Derived, VBase); |
1407 | Result = Address(VBasePtr, VBaseAlign); |
1408 | } |
1409 | if (!StaticOffset.isZero()) { |
1410 | assert(StaticOffset.isPositive()); |
1411 | Result = CGF.Builder.CreateElementBitCast(Result, CGF.Int8Ty); |
1412 | if (ML.VBase) { |
1413 | |
1414 | |
1415 | |
1416 | |
1417 | Result = CGF.Builder.CreateConstByteGEP(Result, StaticOffset); |
1418 | } else { |
1419 | Result = CGF.Builder.CreateConstInBoundsByteGEP(Result, StaticOffset); |
1420 | } |
1421 | } |
1422 | return Result; |
1423 | } |
1424 | |
1425 | void MicrosoftCXXABI::addImplicitStructorParams(CodeGenFunction &CGF, |
1426 | QualType &ResTy, |
1427 | FunctionArgList &Params) { |
1428 | ASTContext &Context = getContext(); |
1429 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); |
1430 | (MD) || isa(MD)", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 1430, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)); |
1431 | if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) { |
1432 | auto *IsMostDerived = ImplicitParamDecl::Create( |
1433 | Context, , CGF.CurGD.getDecl()->getLocation(), |
1434 | &Context.Idents.get("is_most_derived"), Context.IntTy, |
1435 | ImplicitParamDecl::Other); |
1436 | |
1437 | |
1438 | const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); |
1439 | if (FPT->isVariadic()) |
1440 | Params.insert(Params.begin() + 1, IsMostDerived); |
1441 | else |
1442 | Params.push_back(IsMostDerived); |
1443 | getStructorImplicitParamDecl(CGF) = IsMostDerived; |
1444 | } else if (isDeletingDtor(CGF.CurGD)) { |
1445 | auto *ShouldDelete = ImplicitParamDecl::Create( |
1446 | Context, , CGF.CurGD.getDecl()->getLocation(), |
1447 | &Context.Idents.get("should_call_delete"), Context.IntTy, |
1448 | ImplicitParamDecl::Other); |
1449 | Params.push_back(ShouldDelete); |
1450 | getStructorImplicitParamDecl(CGF) = ShouldDelete; |
1451 | } |
1452 | } |
1453 | |
1454 | void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { |
1455 | |
1456 | if (CGF.CurFuncDecl && CGF.CurFuncDecl->hasAttr<NakedAttr>()) |
1457 | return; |
1458 | |
1459 | |
1460 | |
1461 | |
1462 | |
1463 | |
1464 | |
1465 | |
1466 | |
1467 | |
1468 | |
1469 | |
1470 | |
1471 | llvm::Value *This = loadIncomingCXXThis(CGF); |
1472 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); |
1473 | if (!CGF.CurFuncIsThunk && MD->isVirtual()) { |
1474 | CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(CGF.CurGD); |
1475 | if (!Adjustment.isZero()) { |
1476 | unsigned AS = cast<llvm::PointerType>(This->getType())->getAddressSpace(); |
1477 | llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS), |
1478 | *thisTy = This->getType(); |
1479 | This = CGF.Builder.CreateBitCast(This, charPtrTy); |
1480 | assert(Adjustment.isPositive()); |
1481 | This = CGF.Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, This, |
1482 | -Adjustment.getQuantity()); |
1483 | This = CGF.Builder.CreateBitCast(This, thisTy, "this.adjusted"); |
1484 | } |
1485 | } |
1486 | setCXXABIThisValue(CGF, This); |
1487 | |
1488 | |
1489 | |
1490 | |
1491 | |
1492 | |
1493 | |
1494 | |
1495 | |
1496 | if (HasThisReturn(CGF.CurGD)) |
1497 | CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue); |
1498 | else if (hasMostDerivedReturn(CGF.CurGD)) |
1499 | CGF.Builder.CreateStore(CGF.EmitCastToVoidPtr(getThisValue(CGF)), |
1500 | CGF.ReturnValue); |
1501 | |
1502 | if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) { |
1503 | (0) . __assert_fail ("getStructorImplicitParamDecl(CGF) && \"no implicit parameter for a constructor with virtual bases?\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 1504, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(getStructorImplicitParamDecl(CGF) && |
1504 | (0) . __assert_fail ("getStructorImplicitParamDecl(CGF) && \"no implicit parameter for a constructor with virtual bases?\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 1504, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "no implicit parameter for a constructor with virtual bases?"); |
1505 | getStructorImplicitParamValue(CGF) |
1506 | = CGF.Builder.CreateLoad( |
1507 | CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)), |
1508 | "is_most_derived"); |
1509 | } |
1510 | |
1511 | if (isDeletingDtor(CGF.CurGD)) { |
1512 | (0) . __assert_fail ("getStructorImplicitParamDecl(CGF) && \"no implicit parameter for a deleting destructor?\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 1513, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(getStructorImplicitParamDecl(CGF) && |
1513 | (0) . __assert_fail ("getStructorImplicitParamDecl(CGF) && \"no implicit parameter for a deleting destructor?\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 1513, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "no implicit parameter for a deleting destructor?"); |
1514 | getStructorImplicitParamValue(CGF) |
1515 | = CGF.Builder.CreateLoad( |
1516 | CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)), |
1517 | "should_call_delete"); |
1518 | } |
1519 | } |
1520 | |
1521 | CGCXXABI::AddedStructorArgs MicrosoftCXXABI::addImplicitConstructorArgs( |
1522 | CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type, |
1523 | bool ForVirtualBase, bool Delegating, CallArgList &Args) { |
1524 | assert(Type == Ctor_Complete || Type == Ctor_Base); |
1525 | |
1526 | |
1527 | if (!D->getParent()->getNumVBases()) |
1528 | return AddedStructorArgs{}; |
1529 | |
1530 | |
1531 | const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>(); |
1532 | llvm::Value *MostDerivedArg; |
1533 | if (Delegating) { |
1534 | MostDerivedArg = getStructorImplicitParamValue(CGF); |
1535 | } else { |
1536 | MostDerivedArg = llvm::ConstantInt::get(CGM.Int32Ty, Type == Ctor_Complete); |
1537 | } |
1538 | RValue RV = RValue::get(MostDerivedArg); |
1539 | if (FPT->isVariadic()) { |
1540 | Args.insert(Args.begin() + 1, CallArg(RV, getContext().IntTy)); |
1541 | return AddedStructorArgs::prefix(1); |
1542 | } |
1543 | Args.add(RV, getContext().IntTy); |
1544 | return AddedStructorArgs::suffix(1); |
1545 | } |
1546 | |
1547 | void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, |
1548 | const CXXDestructorDecl *DD, |
1549 | CXXDtorType Type, bool ForVirtualBase, |
1550 | bool Delegating, Address This) { |
1551 | |
1552 | |
1553 | |
1554 | if (Type == Dtor_Complete && DD->getParent()->getNumVBases() == 0) |
1555 | Type = Dtor_Base; |
1556 | |
1557 | GlobalDecl GD(DD, Type); |
1558 | CGCallee Callee = CGCallee::forDirect(CGM.getAddrOfCXXStructor(GD), GD); |
1559 | |
1560 | if (DD->isVirtual()) { |
1561 | (0) . __assert_fail ("Type != CXXDtorType..Dtor_Deleting && \"The deleting destructor should only be called via a virtual call\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 1562, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Type != CXXDtorType::Dtor_Deleting && |
1562 | (0) . __assert_fail ("Type != CXXDtorType..Dtor_Deleting && \"The deleting destructor should only be called via a virtual call\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 1562, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "The deleting destructor should only be called via a virtual call"); |
1563 | This = adjustThisArgumentForVirtualFunctionCall(CGF, GlobalDecl(DD, Type), |
1564 | This, false); |
1565 | } |
1566 | |
1567 | llvm::BasicBlock *BaseDtorEndBB = nullptr; |
1568 | if (ForVirtualBase && isa<CXXConstructorDecl>(CGF.CurCodeDecl)) { |
1569 | BaseDtorEndBB = EmitDtorCompleteObjectHandler(CGF); |
1570 | } |
1571 | |
1572 | CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), |
1573 | , |
1574 | (), nullptr); |
1575 | if (BaseDtorEndBB) { |
1576 | |
1577 | CGF.Builder.CreateBr(BaseDtorEndBB); |
1578 | CGF.EmitBlock(BaseDtorEndBB); |
1579 | } |
1580 | } |
1581 | |
1582 | void MicrosoftCXXABI::emitVTableTypeMetadata(const VPtrInfo &Info, |
1583 | const CXXRecordDecl *RD, |
1584 | llvm::GlobalVariable *VTable) { |
1585 | if (!CGM.getCodeGenOpts().LTOUnit) |
1586 | return; |
1587 | |
1588 | |
1589 | |
1590 | |
1591 | CharUnits AddressPoint = |
1592 | getContext().getLangOpts().RTTIData |
1593 | ? getContext().toCharUnitsFromBits( |
1594 | getContext().getTargetInfo().getPointerWidth(0)) |
1595 | : CharUnits::Zero(); |
1596 | |
1597 | if (Info.PathToIntroducingObject.empty()) { |
1598 | CGM.AddVTableTypeMetadata(VTable, AddressPoint, RD); |
1599 | return; |
1600 | } |
1601 | |
1602 | |
1603 | CGM.AddVTableTypeMetadata(VTable, AddressPoint, |
1604 | Info.PathToIntroducingObject.back()); |
1605 | |
1606 | |
1607 | |
1608 | for (unsigned I = Info.PathToIntroducingObject.size() - 1; I != 0; --I) { |
1609 | const CXXRecordDecl *DerivedRD = Info.PathToIntroducingObject[I - 1]; |
1610 | const CXXRecordDecl *BaseRD = Info.PathToIntroducingObject[I]; |
1611 | |
1612 | const ASTRecordLayout &Layout = |
1613 | getContext().getASTRecordLayout(DerivedRD); |
1614 | CharUnits Offset; |
1615 | auto VBI = Layout.getVBaseOffsetsMap().find(BaseRD); |
1616 | if (VBI == Layout.getVBaseOffsetsMap().end()) |
1617 | Offset = Layout.getBaseClassOffset(BaseRD); |
1618 | else |
1619 | Offset = VBI->second.VBaseOffset; |
1620 | if (!Offset.isZero()) |
1621 | return; |
1622 | CGM.AddVTableTypeMetadata(VTable, AddressPoint, DerivedRD); |
1623 | } |
1624 | |
1625 | |
1626 | if (Info.FullOffsetInMDC.isZero()) |
1627 | CGM.AddVTableTypeMetadata(VTable, AddressPoint, RD); |
1628 | } |
1629 | |
1630 | void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, |
1631 | const CXXRecordDecl *RD) { |
1632 | MicrosoftVTableContext &VFTContext = CGM.getMicrosoftVTableContext(); |
1633 | const VPtrInfoVector &VFPtrs = VFTContext.getVFPtrOffsets(RD); |
1634 | |
1635 | for (const std::unique_ptr<VPtrInfo>& Info : VFPtrs) { |
1636 | llvm::GlobalVariable *VTable = getAddrOfVTable(RD, Info->FullOffsetInMDC); |
1637 | if (VTable->hasInitializer()) |
1638 | continue; |
1639 | |
1640 | const VTableLayout &VTLayout = |
1641 | VFTContext.getVFTableLayout(RD, Info->FullOffsetInMDC); |
1642 | |
1643 | llvm::Constant *RTTI = nullptr; |
1644 | if (any_of(VTLayout.vtable_components(), |
1645 | [](const VTableComponent &VTC) { return VTC.isRTTIKind(); })) |
1646 | RTTI = getMSCompleteObjectLocator(RD, *Info); |
1647 | |
1648 | ConstantInitBuilder Builder(CGM); |
1649 | auto Components = Builder.beginStruct(); |
1650 | CGVT.createVTableInitializer(Components, VTLayout, RTTI); |
1651 | Components.finishAndSetAsInitializer(VTable); |
1652 | |
1653 | emitVTableTypeMetadata(*Info, RD, VTable); |
1654 | } |
1655 | } |
1656 | |
1657 | bool MicrosoftCXXABI::isVirtualOffsetNeededForVTableField( |
1658 | CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr) { |
1659 | return Vptr.NearestVBase != nullptr; |
1660 | } |
1661 | |
1662 | llvm::Value *MicrosoftCXXABI::getVTableAddressPointInStructor( |
1663 | CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, |
1664 | const CXXRecordDecl *NearestVBase) { |
1665 | llvm::Constant *VTableAddressPoint = getVTableAddressPoint(Base, VTableClass); |
1666 | if (!VTableAddressPoint) { |
1667 | getNumVBases() && !getContext().getASTRecordLayout(Base.getBase()).hasOwnVFPtr()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 1668, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Base.getBase()->getNumVBases() && |
1668 | getNumVBases() && !getContext().getASTRecordLayout(Base.getBase()).hasOwnVFPtr()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 1668, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> !getContext().getASTRecordLayout(Base.getBase()).hasOwnVFPtr()); |
1669 | } |
1670 | return VTableAddressPoint; |
1671 | } |
1672 | |
1673 | static void mangleVFTableName(MicrosoftMangleContext &MangleContext, |
1674 | const CXXRecordDecl *RD, const VPtrInfo &VFPtr, |
1675 | SmallString<256> &Name) { |
1676 | llvm::raw_svector_ostream Out(Name); |
1677 | MangleContext.mangleCXXVFTable(RD, VFPtr.MangledPath, Out); |
1678 | } |
1679 | |
1680 | llvm::Constant * |
1681 | MicrosoftCXXABI::getVTableAddressPoint(BaseSubobject Base, |
1682 | const CXXRecordDecl *VTableClass) { |
1683 | (void)getAddrOfVTable(VTableClass, Base.getBaseOffset()); |
1684 | VFTableIdTy ID(VTableClass, Base.getBaseOffset()); |
1685 | return VFTablesMap[ID]; |
1686 | } |
1687 | |
1688 | llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr( |
1689 | BaseSubobject Base, const CXXRecordDecl *VTableClass) { |
1690 | llvm::Constant *VFTable = getVTableAddressPoint(Base, VTableClass); |
1691 | (0) . __assert_fail ("VFTable && \"Couldn't find a vftable for the given base?\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 1691, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(VFTable && "Couldn't find a vftable for the given base?"); |
1692 | return VFTable; |
1693 | } |
1694 | |
1695 | llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, |
1696 | CharUnits VPtrOffset) { |
1697 | |
1698 | |
1699 | |
1700 | |
1701 | VFTableIdTy ID(RD, VPtrOffset); |
1702 | VTablesMapTy::iterator I; |
1703 | bool Inserted; |
1704 | std::tie(I, Inserted) = VTablesMap.insert(std::make_pair(ID, nullptr)); |
1705 | if (!Inserted) |
1706 | return I->second; |
1707 | |
1708 | llvm::GlobalVariable *&VTable = I->second; |
1709 | |
1710 | MicrosoftVTableContext &VTContext = CGM.getMicrosoftVTableContext(); |
1711 | const VPtrInfoVector &VFPtrs = VTContext.getVFPtrOffsets(RD); |
1712 | |
1713 | if (DeferredVFTables.insert(RD).second) { |
1714 | |
1715 | |
1716 | CGM.addDeferredVTable(RD); |
1717 | |
1718 | #ifndef NDEBUG |
1719 | |
1720 | |
1721 | llvm::StringSet<> ObservedMangledNames; |
1722 | for (size_t J = 0, F = VFPtrs.size(); J != F; ++J) { |
1723 | SmallString<256> Name; |
1724 | mangleVFTableName(getMangleContext(), RD, *VFPtrs[J], Name); |
1725 | if (!ObservedMangledNames.insert(Name.str()).second) |
1726 | llvm_unreachable("Already saw this mangling before?"); |
1727 | } |
1728 | #endif |
1729 | } |
1730 | |
1731 | const std::unique_ptr<VPtrInfo> *VFPtrI = std::find_if( |
1732 | VFPtrs.begin(), VFPtrs.end(), [&](const std::unique_ptr<VPtrInfo>& VPI) { |
1733 | return VPI->FullOffsetInMDC == VPtrOffset; |
1734 | }); |
1735 | if (VFPtrI == VFPtrs.end()) { |
1736 | VFTablesMap[ID] = nullptr; |
1737 | return nullptr; |
1738 | } |
1739 | const std::unique_ptr<VPtrInfo> &VFPtr = *VFPtrI; |
1740 | |
1741 | SmallString<256> VFTableName; |
1742 | mangleVFTableName(getMangleContext(), RD, *VFPtr, VFTableName); |
1743 | |
1744 | |
1745 | |
1746 | |
1747 | |
1748 | |
1749 | |
1750 | |
1751 | llvm::GlobalValue::LinkageTypes VFTableLinkage = |
1752 | RD->hasAttr<DLLImportAttr>() ? llvm::GlobalValue::LinkOnceODRLinkage |
1753 | : CGM.getVTableLinkage(RD); |
1754 | bool VFTableComesFromAnotherTU = |
1755 | llvm::GlobalValue::isAvailableExternallyLinkage(VFTableLinkage) || |
1756 | llvm::GlobalValue::isExternalLinkage(VFTableLinkage); |
1757 | bool VTableAliasIsRequred = |
1758 | !VFTableComesFromAnotherTU && getContext().getLangOpts().RTTIData; |
1759 | |
1760 | if (llvm::GlobalValue *VFTable = |
1761 | CGM.getModule().getNamedGlobal(VFTableName)) { |
1762 | VFTablesMap[ID] = VFTable; |
1763 | VTable = VTableAliasIsRequred |
1764 | ? cast<llvm::GlobalVariable>( |
1765 | cast<llvm::GlobalAlias>(VFTable)->getBaseObject()) |
1766 | : cast<llvm::GlobalVariable>(VFTable); |
1767 | return VTable; |
1768 | } |
1769 | |
1770 | const VTableLayout &VTLayout = |
1771 | VTContext.getVFTableLayout(RD, VFPtr->FullOffsetInMDC); |
1772 | llvm::GlobalValue::LinkageTypes VTableLinkage = |
1773 | VTableAliasIsRequred ? llvm::GlobalValue::PrivateLinkage : VFTableLinkage; |
1774 | |
1775 | StringRef VTableName = VTableAliasIsRequred ? StringRef() : VFTableName.str(); |
1776 | |
1777 | llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout); |
1778 | |
1779 | |
1780 | |
1781 | llvm::GlobalValue *VFTable; |
1782 | VTable = new llvm::GlobalVariable(CGM.getModule(), VTableType, |
1783 | , VTableLinkage, |
1784 | , VTableName); |
1785 | VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); |
1786 | |
1787 | llvm::Comdat *C = nullptr; |
1788 | if (!VFTableComesFromAnotherTU && |
1789 | (llvm::GlobalValue::isWeakForLinker(VFTableLinkage) || |
1790 | (llvm::GlobalValue::isLocalLinkage(VFTableLinkage) && |
1791 | VTableAliasIsRequred))) |
1792 | C = CGM.getModule().getOrInsertComdat(VFTableName.str()); |
1793 | |
1794 | |
1795 | |
1796 | |
1797 | if (VTableAliasIsRequred) { |
1798 | llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.Int32Ty, 0), |
1799 | llvm::ConstantInt::get(CGM.Int32Ty, 0), |
1800 | llvm::ConstantInt::get(CGM.Int32Ty, 1)}; |
1801 | |
1802 | |
1803 | llvm::Constant *VTableGEP = llvm::ConstantExpr::getInBoundsGetElementPtr( |
1804 | VTable->getValueType(), VTable, GEPIndices); |
1805 | if (llvm::GlobalValue::isWeakForLinker(VFTableLinkage)) { |
1806 | VFTableLinkage = llvm::GlobalValue::ExternalLinkage; |
1807 | if (C) |
1808 | C->setSelectionKind(llvm::Comdat::Largest); |
1809 | } |
1810 | VFTable = llvm::GlobalAlias::create(CGM.Int8PtrTy, |
1811 | , VFTableLinkage, |
1812 | VFTableName.str(), VTableGEP, |
1813 | &CGM.getModule()); |
1814 | VFTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); |
1815 | } else { |
1816 | |
1817 | |
1818 | |
1819 | |
1820 | VFTable = VTable; |
1821 | } |
1822 | if (C) |
1823 | VTable->setComdat(C); |
1824 | |
1825 | if (RD->hasAttr<DLLExportAttr>()) |
1826 | VFTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); |
1827 | |
1828 | VFTablesMap[ID] = VFTable; |
1829 | return VTable; |
1830 | } |
1831 | |
1832 | CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, |
1833 | GlobalDecl GD, |
1834 | Address This, |
1835 | llvm::Type *Ty, |
1836 | SourceLocation Loc) { |
1837 | CGBuilderTy &Builder = CGF.Builder; |
1838 | |
1839 | Ty = Ty->getPointerTo()->getPointerTo(); |
1840 | Address VPtr = |
1841 | adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true); |
1842 | |
1843 | auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl()); |
1844 | llvm::Value *VTable = CGF.GetVTablePtr(VPtr, Ty, MethodDecl->getParent()); |
1845 | |
1846 | MicrosoftVTableContext &VFTContext = CGM.getMicrosoftVTableContext(); |
1847 | MethodVFTableLocation ML = VFTContext.getMethodVFTableLocation(GD); |
1848 | |
1849 | |
1850 | |
1851 | auto getObjectWithVPtr = [&] { |
1852 | return llvm::find_if(VFTContext.getVFPtrOffsets( |
1853 | ML.VBase ? ML.VBase : MethodDecl->getParent()), |
1854 | [&](const std::unique_ptr<VPtrInfo> &Info) { |
1855 | return Info->FullOffsetInMDC == ML.VFPtrOffset; |
1856 | }) |
1857 | ->get() |
1858 | ->ObjectWithVPtr; |
1859 | }; |
1860 | |
1861 | llvm::Value *VFunc; |
1862 | if (CGF.ShouldEmitVTableTypeCheckedLoad(MethodDecl->getParent())) { |
1863 | VFunc = CGF.EmitVTableTypeCheckedLoad( |
1864 | getObjectWithVPtr(), VTable, |
1865 | ML.Index * CGM.getContext().getTargetInfo().getPointerWidth(0) / 8); |
1866 | } else { |
1867 | if (CGM.getCodeGenOpts().PrepareForLTO) |
1868 | CGF.EmitTypeMetadataCodeForVCall(getObjectWithVPtr(), VTable, Loc); |
1869 | |
1870 | llvm::Value *VFuncPtr = |
1871 | Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn"); |
1872 | VFunc = Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign()); |
1873 | } |
1874 | |
1875 | CGCallee Callee(GD, VFunc); |
1876 | return Callee; |
1877 | } |
1878 | |
1879 | llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall( |
1880 | CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, |
1881 | Address This, const CXXMemberCallExpr *CE) { |
1882 | arg_begin() == CE->arg_end()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 1882, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(CE == nullptr || CE->arg_begin() == CE->arg_end()); |
1883 | assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete); |
1884 | |
1885 | |
1886 | |
1887 | GlobalDecl GD(Dtor, Dtor_Deleting); |
1888 | const CGFunctionInfo *FInfo = |
1889 | &CGM.getTypes().arrangeCXXStructorDeclaration(GD); |
1890 | llvm::FunctionType *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo); |
1891 | CGCallee Callee = CGCallee::forVirtual(CE, GD, This, Ty); |
1892 | |
1893 | ASTContext &Context = getContext(); |
1894 | llvm::Value *ImplicitParam = llvm::ConstantInt::get( |
1895 | llvm::IntegerType::getInt32Ty(CGF.getLLVMContext()), |
1896 | DtorType == Dtor_Deleting); |
1897 | |
1898 | This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true); |
1899 | RValue RV = CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), |
1900 | ImplicitParam, Context.IntTy, CE); |
1901 | return RV.getScalarVal(); |
1902 | } |
1903 | |
1904 | const VBTableGlobals & |
1905 | MicrosoftCXXABI::enumerateVBTables(const CXXRecordDecl *RD) { |
1906 | |
1907 | |
1908 | llvm::DenseMap<const CXXRecordDecl*, VBTableGlobals>::iterator Entry; |
1909 | bool Added; |
1910 | std::tie(Entry, Added) = |
1911 | VBTablesMap.insert(std::make_pair(RD, VBTableGlobals())); |
1912 | VBTableGlobals &VBGlobals = Entry->second; |
1913 | if (!Added) |
1914 | return VBGlobals; |
1915 | |
1916 | MicrosoftVTableContext &Context = CGM.getMicrosoftVTableContext(); |
1917 | VBGlobals.VBTables = &Context.enumerateVBTables(RD); |
1918 | |
1919 | |
1920 | |
1921 | llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD); |
1922 | for (VPtrInfoVector::const_iterator I = VBGlobals.VBTables->begin(), |
1923 | E = VBGlobals.VBTables->end(); |
1924 | I != E; ++I) { |
1925 | VBGlobals.Globals.push_back(getAddrOfVBTable(**I, RD, Linkage)); |
1926 | } |
1927 | |
1928 | return VBGlobals; |
1929 | } |
1930 | |
1931 | llvm::Function * |
1932 | MicrosoftCXXABI::EmitVirtualMemPtrThunk(const CXXMethodDecl *MD, |
1933 | const MethodVFTableLocation &ML) { |
1934 | (0) . __assert_fail ("!isa(MD) && !isa(MD) && \"can't form pointers to ctors or virtual dtors\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 1935, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!isa<CXXConstructorDecl>(MD) && !isa<CXXDestructorDecl>(MD) && |
1935 | (0) . __assert_fail ("!isa(MD) && !isa(MD) && \"can't form pointers to ctors or virtual dtors\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 1935, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "can't form pointers to ctors or virtual dtors"); |
1936 | |
1937 | |
1938 | SmallString<256> ThunkName; |
1939 | llvm::raw_svector_ostream Out(ThunkName); |
1940 | getMangleContext().mangleVirtualMemPtrThunk(MD, ML, Out); |
1941 | |
1942 | |
1943 | if (llvm::GlobalValue *GV = CGM.getModule().getNamedValue(ThunkName)) |
1944 | return cast<llvm::Function>(GV); |
1945 | |
1946 | |
1947 | const CGFunctionInfo &FnInfo = |
1948 | CGM.getTypes().arrangeUnprototypedMustTailThunk(MD); |
1949 | llvm::FunctionType *ThunkTy = CGM.getTypes().GetFunctionType(FnInfo); |
1950 | llvm::Function *ThunkFn = |
1951 | llvm::Function::Create(ThunkTy, llvm::Function::ExternalLinkage, |
1952 | ThunkName.str(), &CGM.getModule()); |
1953 | (0) . __assert_fail ("ThunkFn->getName() == ThunkName && \"name was uniqued!\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 1953, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(ThunkFn->getName() == ThunkName && "name was uniqued!"); |
1954 | |
1955 | ThunkFn->setLinkage(MD->isExternallyVisible() |
1956 | ? llvm::GlobalValue::LinkOnceODRLinkage |
1957 | : llvm::GlobalValue::InternalLinkage); |
1958 | if (MD->isExternallyVisible()) |
1959 | ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName())); |
1960 | |
1961 | CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn); |
1962 | CGM.SetLLVMFunctionAttributesForDefinition(MD, ThunkFn); |
1963 | |
1964 | |
1965 | |
1966 | |
1967 | |
1968 | ThunkFn->addFnAttr("thunk"); |
1969 | |
1970 | |
1971 | ThunkFn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None); |
1972 | |
1973 | |
1974 | CodeGenFunction CGF(CGM); |
1975 | CGF.CurGD = GlobalDecl(MD); |
1976 | CGF.CurFuncIsThunk = true; |
1977 | |
1978 | |
1979 | |
1980 | FunctionArgList FunctionArgs; |
1981 | buildThisParam(CGF, FunctionArgs); |
1982 | |
1983 | |
1984 | CGF.StartFunction(GlobalDecl(), FnInfo.getReturnType(), ThunkFn, FnInfo, |
1985 | FunctionArgs, MD->getLocation(), SourceLocation()); |
1986 | setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF)); |
1987 | |
1988 | |
1989 | |
1990 | llvm::Value *VTable = CGF.GetVTablePtr( |
1991 | getThisAddress(CGF), ThunkTy->getPointerTo()->getPointerTo(), MD->getParent()); |
1992 | |
1993 | llvm::Value *VFuncPtr = |
1994 | CGF.Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn"); |
1995 | llvm::Value *Callee = |
1996 | CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign()); |
1997 | |
1998 | CGF.EmitMustTailThunk(MD, getThisValue(CGF), {ThunkTy, Callee}); |
1999 | |
2000 | return ThunkFn; |
2001 | } |
2002 | |
2003 | void MicrosoftCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) { |
2004 | const VBTableGlobals &VBGlobals = enumerateVBTables(RD); |
2005 | for (unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) { |
2006 | const std::unique_ptr<VPtrInfo>& VBT = (*VBGlobals.VBTables)[I]; |
2007 | llvm::GlobalVariable *GV = VBGlobals.Globals[I]; |
2008 | if (GV->isDeclaration()) |
2009 | emitVBTableDefinition(*VBT, RD, GV); |
2010 | } |
2011 | } |
2012 | |
2013 | llvm::GlobalVariable * |
2014 | MicrosoftCXXABI::getAddrOfVBTable(const VPtrInfo &VBT, const CXXRecordDecl *RD, |
2015 | llvm::GlobalVariable::LinkageTypes Linkage) { |
2016 | SmallString<256> OutName; |
2017 | llvm::raw_svector_ostream Out(OutName); |
2018 | getMangleContext().mangleCXXVBTable(RD, VBT.MangledPath, Out); |
2019 | StringRef Name = OutName.str(); |
2020 | |
2021 | llvm::ArrayType *VBTableType = |
2022 | llvm::ArrayType::get(CGM.IntTy, 1 + VBT.ObjectWithVPtr->getNumVBases()); |
2023 | |
2024 | (0) . __assert_fail ("!CGM.getModule().getNamedGlobal(Name) && \"vbtable with this name already exists. mangling bug?\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 2025, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!CGM.getModule().getNamedGlobal(Name) && |
2025 | (0) . __assert_fail ("!CGM.getModule().getNamedGlobal(Name) && \"vbtable with this name already exists. mangling bug?\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 2025, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "vbtable with this name already exists: mangling bug?"); |
2026 | CharUnits Alignment = |
2027 | CGM.getContext().getTypeAlignInChars(CGM.getContext().IntTy); |
2028 | llvm::GlobalVariable *GV = CGM.CreateOrReplaceCXXRuntimeVariable( |
2029 | Name, VBTableType, Linkage, Alignment.getQuantity()); |
2030 | GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); |
2031 | |
2032 | if (RD->hasAttr<DLLImportAttr>()) |
2033 | GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); |
2034 | else if (RD->hasAttr<DLLExportAttr>()) |
2035 | GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); |
2036 | |
2037 | if (!GV->hasExternalLinkage()) |
2038 | emitVBTableDefinition(VBT, RD, GV); |
2039 | |
2040 | return GV; |
2041 | } |
2042 | |
2043 | void MicrosoftCXXABI::emitVBTableDefinition(const VPtrInfo &VBT, |
2044 | const CXXRecordDecl *RD, |
2045 | llvm::GlobalVariable *GV) const { |
2046 | const CXXRecordDecl *ObjectWithVPtr = VBT.ObjectWithVPtr; |
2047 | |
2048 | (0) . __assert_fail ("RD->getNumVBases() && ObjectWithVPtr->getNumVBases() && \"should only emit vbtables for classes with vbtables\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 2049, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(RD->getNumVBases() && ObjectWithVPtr->getNumVBases() && |
2049 | (0) . __assert_fail ("RD->getNumVBases() && ObjectWithVPtr->getNumVBases() && \"should only emit vbtables for classes with vbtables\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 2049, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "should only emit vbtables for classes with vbtables"); |
2050 | |
2051 | const ASTRecordLayout &BaseLayout = |
2052 | getContext().getASTRecordLayout(VBT.IntroducingObject); |
2053 | const ASTRecordLayout &DerivedLayout = getContext().getASTRecordLayout(RD); |
2054 | |
2055 | SmallVector<llvm::Constant *, 4> Offsets(1 + ObjectWithVPtr->getNumVBases(), |
2056 | nullptr); |
2057 | |
2058 | |
2059 | CharUnits VBPtrOffset = BaseLayout.getVBPtrOffset(); |
2060 | Offsets[0] = llvm::ConstantInt::get(CGM.IntTy, -VBPtrOffset.getQuantity()); |
2061 | |
2062 | MicrosoftVTableContext &Context = CGM.getMicrosoftVTableContext(); |
2063 | for (const auto &I : ObjectWithVPtr->vbases()) { |
2064 | const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl(); |
2065 | CharUnits Offset = DerivedLayout.getVBaseClassOffset(VBase); |
2066 | assert(!Offset.isNegative()); |
2067 | |
2068 | |
2069 | CharUnits CompleteVBPtrOffset = VBT.NonVirtualOffset + VBPtrOffset; |
2070 | if (VBT.getVBaseWithVPtr()) |
2071 | CompleteVBPtrOffset += |
2072 | DerivedLayout.getVBaseClassOffset(VBT.getVBaseWithVPtr()); |
2073 | Offset -= CompleteVBPtrOffset; |
2074 | |
2075 | unsigned VBIndex = Context.getVBTableIndex(ObjectWithVPtr, VBase); |
2076 | (0) . __assert_fail ("Offsets[VBIndex] == nullptr && \"The same vbindex seen twice?\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 2076, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Offsets[VBIndex] == nullptr && "The same vbindex seen twice?"); |
2077 | Offsets[VBIndex] = llvm::ConstantInt::get(CGM.IntTy, Offset.getQuantity()); |
2078 | } |
2079 | |
2080 | (cast(GV->getType()) ->getElementType())->getNumElements()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 2082, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Offsets.size() == |
2081 | (cast(GV->getType()) ->getElementType())->getNumElements()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 2082, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> cast<llvm::ArrayType>(cast<llvm::PointerType>(GV->getType()) |
2082 | (cast(GV->getType()) ->getElementType())->getNumElements()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 2082, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> ->getElementType())->getNumElements()); |
2083 | llvm::ArrayType *VBTableType = |
2084 | llvm::ArrayType::get(CGM.IntTy, Offsets.size()); |
2085 | llvm::Constant *Init = llvm::ConstantArray::get(VBTableType, Offsets); |
2086 | GV->setInitializer(Init); |
2087 | |
2088 | if (RD->hasAttr<DLLImportAttr>()) |
2089 | GV->setLinkage(llvm::GlobalVariable::AvailableExternallyLinkage); |
2090 | } |
2091 | |
2092 | llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF, |
2093 | Address This, |
2094 | const ThisAdjustment &TA) { |
2095 | if (TA.isEmpty()) |
2096 | return This.getPointer(); |
2097 | |
2098 | This = CGF.Builder.CreateElementBitCast(This, CGF.Int8Ty); |
2099 | |
2100 | llvm::Value *V; |
2101 | if (TA.Virtual.isEmpty()) { |
2102 | V = This.getPointer(); |
2103 | } else { |
2104 | assert(TA.Virtual.Microsoft.VtordispOffset < 0); |
2105 | |
2106 | Address VtorDispPtr = |
2107 | CGF.Builder.CreateConstInBoundsByteGEP(This, |
2108 | CharUnits::fromQuantity(TA.Virtual.Microsoft.VtordispOffset)); |
2109 | VtorDispPtr = CGF.Builder.CreateElementBitCast(VtorDispPtr, CGF.Int32Ty); |
2110 | llvm::Value *VtorDisp = CGF.Builder.CreateLoad(VtorDispPtr, "vtordisp"); |
2111 | V = CGF.Builder.CreateGEP(This.getPointer(), |
2112 | CGF.Builder.CreateNeg(VtorDisp)); |
2113 | |
2114 | |
2115 | |
2116 | |
2117 | |
2118 | if (TA.Virtual.Microsoft.VBPtrOffset) { |
2119 | |
2120 | |
2121 | |
2122 | 0", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 2122, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(TA.Virtual.Microsoft.VBPtrOffset > 0); |
2123 | = 0", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 2123, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(TA.Virtual.Microsoft.VBOffsetOffset >= 0); |
2124 | llvm::Value *VBPtr; |
2125 | llvm::Value *VBaseOffset = |
2126 | GetVBaseOffsetFromVBPtr(CGF, Address(V, CGF.getPointerAlign()), |
2127 | -TA.Virtual.Microsoft.VBPtrOffset, |
2128 | TA.Virtual.Microsoft.VBOffsetOffset, &VBPtr); |
2129 | V = CGF.Builder.CreateInBoundsGEP(VBPtr, VBaseOffset); |
2130 | } |
2131 | } |
2132 | |
2133 | if (TA.NonVirtual) { |
2134 | |
2135 | |
2136 | |
2137 | V = CGF.Builder.CreateConstGEP1_32(V, TA.NonVirtual); |
2138 | } |
2139 | |
2140 | |
2141 | return V; |
2142 | } |
2143 | |
2144 | llvm::Value * |
2145 | MicrosoftCXXABI::performReturnAdjustment(CodeGenFunction &CGF, Address Ret, |
2146 | const ReturnAdjustment &RA) { |
2147 | if (RA.isEmpty()) |
2148 | return Ret.getPointer(); |
2149 | |
2150 | auto OrigTy = Ret.getType(); |
2151 | Ret = CGF.Builder.CreateElementBitCast(Ret, CGF.Int8Ty); |
2152 | |
2153 | llvm::Value *V = Ret.getPointer(); |
2154 | if (RA.Virtual.Microsoft.VBIndex) { |
2155 | 0", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 2155, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(RA.Virtual.Microsoft.VBIndex > 0); |
2156 | int32_t IntSize = CGF.getIntSize().getQuantity(); |
2157 | llvm::Value *VBPtr; |
2158 | llvm::Value *VBaseOffset = |
2159 | GetVBaseOffsetFromVBPtr(CGF, Ret, RA.Virtual.Microsoft.VBPtrOffset, |
2160 | IntSize * RA.Virtual.Microsoft.VBIndex, &VBPtr); |
2161 | V = CGF.Builder.CreateInBoundsGEP(VBPtr, VBaseOffset); |
2162 | } |
2163 | |
2164 | if (RA.NonVirtual) |
2165 | V = CGF.Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, V, RA.NonVirtual); |
2166 | |
2167 | |
2168 | return CGF.Builder.CreateBitCast(V, OrigTy); |
2169 | } |
2170 | |
2171 | bool MicrosoftCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr, |
2172 | QualType elementType) { |
2173 | |
2174 | |
2175 | return elementType.isDestructedType(); |
2176 | } |
2177 | |
2178 | bool MicrosoftCXXABI::requiresArrayCookie(const CXXNewExpr *expr) { |
2179 | |
2180 | |
2181 | return expr->getAllocatedType().isDestructedType(); |
2182 | } |
2183 | |
2184 | CharUnits MicrosoftCXXABI::getArrayCookieSizeImpl(QualType type) { |
2185 | |
2186 | |
2187 | ASTContext &Ctx = getContext(); |
2188 | return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()), |
2189 | Ctx.getTypeAlignInChars(type)); |
2190 | } |
2191 | |
2192 | llvm::Value *MicrosoftCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, |
2193 | Address allocPtr, |
2194 | CharUnits cookieSize) { |
2195 | Address numElementsPtr = |
2196 | CGF.Builder.CreateElementBitCast(allocPtr, CGF.SizeTy); |
2197 | return CGF.Builder.CreateLoad(numElementsPtr); |
2198 | } |
2199 | |
2200 | Address MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, |
2201 | Address newPtr, |
2202 | llvm::Value *numElements, |
2203 | const CXXNewExpr *expr, |
2204 | QualType elementType) { |
2205 | assert(requiresArrayCookie(expr)); |
2206 | |
2207 | |
2208 | CharUnits cookieSize = getArrayCookieSizeImpl(elementType); |
2209 | |
2210 | |
2211 | Address cookiePtr = newPtr; |
2212 | |
2213 | |
2214 | Address numElementsPtr |
2215 | = CGF.Builder.CreateElementBitCast(cookiePtr, CGF.SizeTy); |
2216 | CGF.Builder.CreateStore(numElements, numElementsPtr); |
2217 | |
2218 | |
2219 | |
2220 | return CGF.Builder.CreateConstInBoundsByteGEP(newPtr, cookieSize); |
2221 | } |
2222 | |
2223 | static void emitGlobalDtorWithTLRegDtor(CodeGenFunction &CGF, const VarDecl &VD, |
2224 | llvm::FunctionCallee Dtor, |
2225 | llvm::Constant *Addr) { |
2226 | |
2227 | llvm::Constant *DtorStub = CGF.createAtExitStub(VD, Dtor, Addr); |
2228 | |
2229 | |
2230 | llvm::FunctionType *TLRegDtorTy = llvm::FunctionType::get( |
2231 | CGF.IntTy, DtorStub->getType(), ); |
2232 | |
2233 | llvm::FunctionCallee TLRegDtor = CGF.CGM.CreateRuntimeFunction( |
2234 | TLRegDtorTy, "__tlregdtor", llvm::AttributeList(), ); |
2235 | if (llvm::Function *TLRegDtorFn = |
2236 | dyn_cast<llvm::Function>(TLRegDtor.getCallee())) |
2237 | TLRegDtorFn->setDoesNotThrow(); |
2238 | |
2239 | CGF.EmitNounwindRuntimeCall(TLRegDtor, DtorStub); |
2240 | } |
2241 | |
2242 | void MicrosoftCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, |
2243 | llvm::FunctionCallee Dtor, |
2244 | llvm::Constant *Addr) { |
2245 | if (D.isNoDestroy(CGM.getContext())) |
2246 | return; |
2247 | |
2248 | if (D.getTLSKind()) |
2249 | return emitGlobalDtorWithTLRegDtor(CGF, D, Dtor, Addr); |
2250 | |
2251 | |
2252 | CGF.registerGlobalDtorWithAtExit(D, Dtor, Addr); |
2253 | } |
2254 | |
2255 | void MicrosoftCXXABI::EmitThreadLocalInitFuncs( |
2256 | CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals, |
2257 | ArrayRef<llvm::Function *> CXXThreadLocalInits, |
2258 | ArrayRef<const VarDecl *> CXXThreadLocalInitVars) { |
2259 | if (CXXThreadLocalInits.empty()) |
2260 | return; |
2261 | |
2262 | CGM.AppendLinkerOptions(CGM.getTarget().getTriple().getArch() == |
2263 | llvm::Triple::x86 |
2264 | ? "/include:___dyn_tls_init@12" |
2265 | : "/include:__dyn_tls_init"); |
2266 | |
2267 | |
2268 | |
2269 | |
2270 | auto AddToXDU = [&CGM](llvm::Function *InitFunc) { |
2271 | llvm::GlobalVariable *InitFuncPtr = new llvm::GlobalVariable( |
2272 | CGM.getModule(), InitFunc->getType(), , |
2273 | llvm::GlobalVariable::InternalLinkage, InitFunc, |
2274 | Twine(InitFunc->getName(), "$initializer$")); |
2275 | InitFuncPtr->setSection(".CRT$XDU"); |
2276 | |
2277 | |
2278 | CGM.addUsedGlobal(InitFuncPtr); |
2279 | return InitFuncPtr; |
2280 | }; |
2281 | |
2282 | std::vector<llvm::Function *> NonComdatInits; |
2283 | for (size_t I = 0, E = CXXThreadLocalInitVars.size(); I != E; ++I) { |
2284 | llvm::GlobalVariable *GV = cast<llvm::GlobalVariable>( |
2285 | CGM.GetGlobalValue(CGM.getMangledName(CXXThreadLocalInitVars[I]))); |
2286 | llvm::Function *F = CXXThreadLocalInits[I]; |
2287 | |
2288 | |
2289 | if (llvm::Comdat *C = GV->getComdat()) |
2290 | AddToXDU(F)->setComdat(C); |
2291 | else |
2292 | NonComdatInits.push_back(F); |
2293 | } |
2294 | |
2295 | if (!NonComdatInits.empty()) { |
2296 | llvm::FunctionType *FTy = |
2297 | llvm::FunctionType::get(CGM.VoidTy, ); |
2298 | llvm::Function *InitFunc = CGM.CreateGlobalInitOrDestructFunction( |
2299 | FTy, "__tls_init", CGM.getTypes().arrangeNullaryFunction(), |
2300 | SourceLocation(), ); |
2301 | CodeGenFunction(CGM).GenerateCXXGlobalInitFunc(InitFunc, NonComdatInits); |
2302 | |
2303 | AddToXDU(InitFunc); |
2304 | } |
2305 | } |
2306 | |
2307 | LValue MicrosoftCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, |
2308 | const VarDecl *VD, |
2309 | QualType LValType) { |
2310 | CGF.CGM.ErrorUnsupported(VD, "thread wrappers"); |
2311 | return LValue(); |
2312 | } |
2313 | |
2314 | static ConstantAddress getInitThreadEpochPtr(CodeGenModule &CGM) { |
2315 | StringRef VarName("_Init_thread_epoch"); |
2316 | CharUnits Align = CGM.getIntAlign(); |
2317 | if (auto *GV = CGM.getModule().getNamedGlobal(VarName)) |
2318 | return ConstantAddress(GV, Align); |
2319 | auto *GV = new llvm::GlobalVariable( |
2320 | CGM.getModule(), CGM.IntTy, |
2321 | , llvm::GlobalVariable::ExternalLinkage, |
2322 | , VarName, |
2323 | , llvm::GlobalVariable::GeneralDynamicTLSModel); |
2324 | GV->setAlignment(Align.getQuantity()); |
2325 | return ConstantAddress(GV, Align); |
2326 | } |
2327 | |
2328 | static llvm::FunctionCallee (CodeGenModule &CGM) { |
2329 | llvm::FunctionType *FTy = |
2330 | llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()), |
2331 | CGM.IntTy->getPointerTo(), ); |
2332 | return CGM.CreateRuntimeFunction( |
2333 | FTy, "_Init_thread_header", |
2334 | llvm::AttributeList::get(CGM.getLLVMContext(), |
2335 | llvm::AttributeList::FunctionIndex, |
2336 | llvm::Attribute::NoUnwind), |
2337 | ); |
2338 | } |
2339 | |
2340 | static llvm::FunctionCallee (CodeGenModule &CGM) { |
2341 | llvm::FunctionType *FTy = |
2342 | llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()), |
2343 | CGM.IntTy->getPointerTo(), ); |
2344 | return CGM.CreateRuntimeFunction( |
2345 | FTy, "_Init_thread_footer", |
2346 | llvm::AttributeList::get(CGM.getLLVMContext(), |
2347 | llvm::AttributeList::FunctionIndex, |
2348 | llvm::Attribute::NoUnwind), |
2349 | ); |
2350 | } |
2351 | |
2352 | static llvm::FunctionCallee getInitThreadAbortFn(CodeGenModule &CGM) { |
2353 | llvm::FunctionType *FTy = |
2354 | llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()), |
2355 | CGM.IntTy->getPointerTo(), ); |
2356 | return CGM.CreateRuntimeFunction( |
2357 | FTy, "_Init_thread_abort", |
2358 | llvm::AttributeList::get(CGM.getLLVMContext(), |
2359 | llvm::AttributeList::FunctionIndex, |
2360 | llvm::Attribute::NoUnwind), |
2361 | ); |
2362 | } |
2363 | |
2364 | namespace { |
2365 | struct ResetGuardBit final : EHScopeStack::Cleanup { |
2366 | Address Guard; |
2367 | unsigned GuardNum; |
2368 | ResetGuardBit(Address Guard, unsigned GuardNum) |
2369 | : Guard(Guard), GuardNum(GuardNum) {} |
2370 | |
2371 | void Emit(CodeGenFunction &CGF, Flags flags) override { |
2372 | |
2373 | |
2374 | CGBuilderTy &Builder = CGF.Builder; |
2375 | llvm::LoadInst *LI = Builder.CreateLoad(Guard); |
2376 | llvm::ConstantInt *Mask = |
2377 | llvm::ConstantInt::get(CGF.IntTy, ~(1ULL << GuardNum)); |
2378 | Builder.CreateStore(Builder.CreateAnd(LI, Mask), Guard); |
2379 | } |
2380 | }; |
2381 | |
2382 | struct CallInitThreadAbort final : EHScopeStack::Cleanup { |
2383 | llvm::Value *Guard; |
2384 | CallInitThreadAbort(Address Guard) : Guard(Guard.getPointer()) {} |
2385 | |
2386 | void Emit(CodeGenFunction &CGF, Flags flags) override { |
2387 | |
2388 | CGF.EmitNounwindRuntimeCall(getInitThreadAbortFn(CGF.CGM), Guard); |
2389 | } |
2390 | }; |
2391 | } |
2392 | |
2393 | void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, |
2394 | llvm::GlobalVariable *GV, |
2395 | bool PerformInit) { |
2396 | |
2397 | if (!D.isStaticLocal()) { |
2398 | hasWeakLinkage() || GV->hasLinkOnceLinkage()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 2398, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()); |
2399 | |
2400 | llvm::Function *F = CGF.CurFn; |
2401 | F->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage); |
2402 | F->setComdat(CGM.getModule().getOrInsertComdat(F->getName())); |
2403 | CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit); |
2404 | return; |
2405 | } |
2406 | |
2407 | bool ThreadlocalStatic = D.getTLSKind(); |
2408 | bool ThreadsafeStatic = getContext().getLangOpts().ThreadsafeStatics; |
2409 | |
2410 | |
2411 | |
2412 | bool HasPerVariableGuard = ThreadsafeStatic && !ThreadlocalStatic; |
2413 | |
2414 | CGBuilderTy &Builder = CGF.Builder; |
2415 | llvm::IntegerType *GuardTy = CGF.Int32Ty; |
2416 | llvm::ConstantInt *Zero = llvm::ConstantInt::get(GuardTy, 0); |
2417 | CharUnits GuardAlign = CharUnits::fromQuantity(4); |
2418 | |
2419 | |
2420 | GuardInfo *GI = nullptr; |
2421 | if (ThreadlocalStatic) |
2422 | GI = &ThreadLocalGuardVariableMap[D.getDeclContext()]; |
2423 | else if (!ThreadsafeStatic) |
2424 | GI = &GuardVariableMap[D.getDeclContext()]; |
2425 | |
2426 | llvm::GlobalVariable *GuardVar = GI ? GI->Guard : nullptr; |
2427 | unsigned GuardNum; |
2428 | if (D.isExternallyVisible()) { |
2429 | |
2430 | |
2431 | GuardNum = getContext().getStaticLocalNumber(&D); |
2432 | 0", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 2432, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(GuardNum > 0); |
2433 | GuardNum--; |
2434 | } else if (HasPerVariableGuard) { |
2435 | GuardNum = ThreadSafeGuardNumMap[D.getDeclContext()]++; |
2436 | } else { |
2437 | |
2438 | GuardNum = GI->BitIndex++; |
2439 | } |
2440 | |
2441 | if (!HasPerVariableGuard && GuardNum >= 32) { |
2442 | if (D.isExternallyVisible()) |
2443 | ErrorUnsupportedABI(CGF, "more than 32 guarded initializations"); |
2444 | GuardNum %= 32; |
2445 | GuardVar = nullptr; |
2446 | } |
2447 | |
2448 | if (!GuardVar) { |
2449 | |
2450 | SmallString<256> GuardName; |
2451 | { |
2452 | llvm::raw_svector_ostream Out(GuardName); |
2453 | if (HasPerVariableGuard) |
2454 | getMangleContext().mangleThreadSafeStaticGuardVariable(&D, GuardNum, |
2455 | Out); |
2456 | else |
2457 | getMangleContext().mangleStaticGuardVariable(&D, Out); |
2458 | } |
2459 | |
2460 | |
2461 | |
2462 | GuardVar = |
2463 | new llvm::GlobalVariable(CGM.getModule(), GuardTy, , |
2464 | GV->getLinkage(), Zero, GuardName.str()); |
2465 | GuardVar->setVisibility(GV->getVisibility()); |
2466 | GuardVar->setDLLStorageClass(GV->getDLLStorageClass()); |
2467 | GuardVar->setAlignment(GuardAlign.getQuantity()); |
2468 | if (GuardVar->isWeakForLinker()) |
2469 | GuardVar->setComdat( |
2470 | CGM.getModule().getOrInsertComdat(GuardVar->getName())); |
2471 | if (D.getTLSKind()) |
2472 | GuardVar->setThreadLocal(true); |
2473 | if (GI && !HasPerVariableGuard) |
2474 | GI->Guard = GuardVar; |
2475 | } |
2476 | |
2477 | ConstantAddress GuardAddr(GuardVar, GuardAlign); |
2478 | |
2479 | (0) . __assert_fail ("GuardVar->getLinkage() == GV->getLinkage() && \"static local from the same function had different linkage\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 2480, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(GuardVar->getLinkage() == GV->getLinkage() && |
2480 | (0) . __assert_fail ("GuardVar->getLinkage() == GV->getLinkage() && \"static local from the same function had different linkage\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 2480, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "static local from the same function had different linkage"); |
2481 | |
2482 | if (!HasPerVariableGuard) { |
2483 | |
2484 | |
2485 | |
2486 | |
2487 | |
2488 | |
2489 | |
2490 | llvm::ConstantInt *Bit = llvm::ConstantInt::get(GuardTy, 1ULL << GuardNum); |
2491 | llvm::LoadInst *LI = Builder.CreateLoad(GuardAddr); |
2492 | llvm::Value *NeedsInit = |
2493 | Builder.CreateICmpEQ(Builder.CreateAnd(LI, Bit), Zero); |
2494 | llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init"); |
2495 | llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end"); |
2496 | CGF.EmitCXXGuardedInitBranch(NeedsInit, InitBlock, EndBlock, |
2497 | CodeGenFunction::GuardKind::VariableGuard, &D); |
2498 | |
2499 | |
2500 | |
2501 | CGF.EmitBlock(InitBlock); |
2502 | Builder.CreateStore(Builder.CreateOr(LI, Bit), GuardAddr); |
2503 | CGF.EHStack.pushCleanup<ResetGuardBit>(EHCleanup, GuardAddr, GuardNum); |
2504 | CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit); |
2505 | CGF.PopCleanupBlock(); |
2506 | Builder.CreateBr(EndBlock); |
2507 | |
2508 | |
2509 | CGF.EmitBlock(EndBlock); |
2510 | } else { |
2511 | |
2512 | |
2513 | |
2514 | |
2515 | |
2516 | |
2517 | |
2518 | |
2519 | |
2520 | |
2521 | |
2522 | |
2523 | |
2524 | llvm::LoadInst *FirstGuardLoad = Builder.CreateLoad(GuardAddr); |
2525 | FirstGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered); |
2526 | llvm::LoadInst *InitThreadEpoch = |
2527 | Builder.CreateLoad(getInitThreadEpochPtr(CGM)); |
2528 | llvm::Value *IsUninitialized = |
2529 | Builder.CreateICmpSGT(FirstGuardLoad, InitThreadEpoch); |
2530 | llvm::BasicBlock *AttemptInitBlock = CGF.createBasicBlock("init.attempt"); |
2531 | llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end"); |
2532 | CGF.EmitCXXGuardedInitBranch(IsUninitialized, AttemptInitBlock, EndBlock, |
2533 | CodeGenFunction::GuardKind::VariableGuard, &D); |
2534 | |
2535 | |
2536 | |
2537 | CGF.EmitBlock(AttemptInitBlock); |
2538 | CGF.EmitNounwindRuntimeCall(getInitThreadHeaderFn(CGM), |
2539 | GuardAddr.getPointer()); |
2540 | llvm::LoadInst *SecondGuardLoad = Builder.CreateLoad(GuardAddr); |
2541 | SecondGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered); |
2542 | llvm::Value *ShouldDoInit = |
2543 | Builder.CreateICmpEQ(SecondGuardLoad, getAllOnesInt()); |
2544 | llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init"); |
2545 | Builder.CreateCondBr(ShouldDoInit, InitBlock, EndBlock); |
2546 | |
2547 | |
2548 | CGF.EmitBlock(InitBlock); |
2549 | CGF.EHStack.pushCleanup<CallInitThreadAbort>(EHCleanup, GuardAddr); |
2550 | CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit); |
2551 | CGF.PopCleanupBlock(); |
2552 | CGF.EmitNounwindRuntimeCall(getInitThreadFooterFn(CGM), |
2553 | GuardAddr.getPointer()); |
2554 | Builder.CreateBr(EndBlock); |
2555 | |
2556 | CGF.EmitBlock(EndBlock); |
2557 | } |
2558 | } |
2559 | |
2560 | bool MicrosoftCXXABI::isZeroInitializable(const MemberPointerType *MPT) { |
2561 | |
2562 | |
2563 | if (MPT->isMemberFunctionPointer()) |
2564 | return true; |
2565 | |
2566 | |
2567 | |
2568 | |
2569 | const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); |
2570 | MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); |
2571 | return (!MSInheritanceAttr::hasVBTableOffsetField(Inheritance) && |
2572 | RD->nullFieldOffsetIsZero()); |
2573 | } |
2574 | |
2575 | llvm::Type * |
2576 | MicrosoftCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) { |
2577 | const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); |
2578 | MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); |
2579 | llvm::SmallVector<llvm::Type *, 4> fields; |
2580 | if (MPT->isMemberFunctionPointer()) |
2581 | fields.push_back(CGM.VoidPtrTy); |
2582 | else |
2583 | fields.push_back(CGM.IntTy); |
2584 | |
2585 | if (MSInheritanceAttr::hasNVOffsetField(MPT->isMemberFunctionPointer(), |
2586 | Inheritance)) |
2587 | fields.push_back(CGM.IntTy); |
2588 | if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) |
2589 | fields.push_back(CGM.IntTy); |
2590 | if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance)) |
2591 | fields.push_back(CGM.IntTy); |
2592 | |
2593 | if (fields.size() == 1) |
2594 | return fields[0]; |
2595 | return llvm::StructType::get(CGM.getLLVMContext(), fields); |
2596 | } |
2597 | |
2598 | void MicrosoftCXXABI:: |
2599 | GetNullMemberPointerFields(const MemberPointerType *MPT, |
2600 | llvm::SmallVectorImpl<llvm::Constant *> &fields) { |
2601 | assert(fields.empty()); |
2602 | const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); |
2603 | MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); |
2604 | if (MPT->isMemberFunctionPointer()) { |
2605 | |
2606 | fields.push_back(llvm::Constant::getNullValue(CGM.VoidPtrTy)); |
2607 | } else { |
2608 | if (RD->nullFieldOffsetIsZero()) |
2609 | fields.push_back(getZeroInt()); |
2610 | else |
2611 | fields.push_back(getAllOnesInt()); |
2612 | } |
2613 | |
2614 | if (MSInheritanceAttr::hasNVOffsetField(MPT->isMemberFunctionPointer(), |
2615 | Inheritance)) |
2616 | fields.push_back(getZeroInt()); |
2617 | if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) |
2618 | fields.push_back(getZeroInt()); |
2619 | if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance)) |
2620 | fields.push_back(getAllOnesInt()); |
2621 | } |
2622 | |
2623 | llvm::Constant * |
2624 | MicrosoftCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { |
2625 | llvm::SmallVector<llvm::Constant *, 4> fields; |
2626 | GetNullMemberPointerFields(MPT, fields); |
2627 | if (fields.size() == 1) |
2628 | return fields[0]; |
2629 | llvm::Constant *Res = llvm::ConstantStruct::getAnon(fields); |
2630 | getType() == ConvertMemberPointerType(MPT)", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 2630, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Res->getType() == ConvertMemberPointerType(MPT)); |
2631 | return Res; |
2632 | } |
2633 | |
2634 | llvm::Constant * |
2635 | MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField, |
2636 | bool IsMemberFunction, |
2637 | const CXXRecordDecl *RD, |
2638 | CharUnits NonVirtualBaseAdjustment, |
2639 | unsigned VBTableIndex) { |
2640 | MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); |
2641 | |
2642 | |
2643 | |
2644 | if (MSInheritanceAttr::hasOnlyOneField(IsMemberFunction, Inheritance)) |
2645 | return FirstField; |
2646 | |
2647 | llvm::SmallVector<llvm::Constant *, 4> fields; |
2648 | fields.push_back(FirstField); |
2649 | |
2650 | if (MSInheritanceAttr::hasNVOffsetField(IsMemberFunction, Inheritance)) |
2651 | fields.push_back(llvm::ConstantInt::get( |
2652 | CGM.IntTy, NonVirtualBaseAdjustment.getQuantity())); |
2653 | |
2654 | if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) { |
2655 | CharUnits Offs = CharUnits::Zero(); |
2656 | if (VBTableIndex) |
2657 | Offs = getContext().getASTRecordLayout(RD).getVBPtrOffset(); |
2658 | fields.push_back(llvm::ConstantInt::get(CGM.IntTy, Offs.getQuantity())); |
2659 | } |
2660 | |
2661 | |
2662 | if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance)) |
2663 | fields.push_back(llvm::ConstantInt::get(CGM.IntTy, VBTableIndex)); |
2664 | |
2665 | return llvm::ConstantStruct::getAnon(fields); |
2666 | } |
2667 | |
2668 | llvm::Constant * |
2669 | MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, |
2670 | CharUnits offset) { |
2671 | const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); |
2672 | if (RD->getMSInheritanceModel() == |
2673 | MSInheritanceAttr::Keyword_virtual_inheritance) |
2674 | offset -= getContext().getOffsetOfBaseWithVBPtr(RD); |
2675 | llvm::Constant *FirstField = |
2676 | llvm::ConstantInt::get(CGM.IntTy, offset.getQuantity()); |
2677 | return EmitFullMemberPointer(FirstField, , RD, |
2678 | CharUnits::Zero(), ); |
2679 | } |
2680 | |
2681 | llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const APValue &MP, |
2682 | QualType MPType) { |
2683 | const MemberPointerType *DstTy = MPType->castAs<MemberPointerType>(); |
2684 | const ValueDecl *MPD = MP.getMemberPointerDecl(); |
2685 | if (!MPD) |
2686 | return EmitNullMemberPointer(DstTy); |
2687 | |
2688 | ASTContext &Ctx = getContext(); |
2689 | ArrayRef<const CXXRecordDecl *> MemberPointerPath = MP.getMemberPointerPath(); |
2690 | |
2691 | llvm::Constant *C; |
2692 | if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) { |
2693 | C = EmitMemberFunctionPointer(MD); |
2694 | } else { |
2695 | CharUnits FieldOffset = Ctx.toCharUnitsFromBits(Ctx.getFieldOffset(MPD)); |
2696 | C = EmitMemberDataPointer(DstTy, FieldOffset); |
2697 | } |
2698 | |
2699 | if (!MemberPointerPath.empty()) { |
2700 | const CXXRecordDecl *SrcRD = cast<CXXRecordDecl>(MPD->getDeclContext()); |
2701 | const Type *SrcRecTy = Ctx.getTypeDeclType(SrcRD).getTypePtr(); |
2702 | const MemberPointerType *SrcTy = |
2703 | Ctx.getMemberPointerType(DstTy->getPointeeType(), SrcRecTy) |
2704 | ->castAs<MemberPointerType>(); |
2705 | |
2706 | bool DerivedMember = MP.isMemberPointerToDerivedMember(); |
2707 | SmallVector<const CXXBaseSpecifier *, 4> DerivedToBasePath; |
2708 | const CXXRecordDecl *PrevRD = SrcRD; |
2709 | for (const CXXRecordDecl *PathElem : MemberPointerPath) { |
2710 | const CXXRecordDecl *Base = nullptr; |
2711 | const CXXRecordDecl *Derived = nullptr; |
2712 | if (DerivedMember) { |
2713 | Base = PathElem; |
2714 | Derived = PrevRD; |
2715 | } else { |
2716 | Base = PrevRD; |
2717 | Derived = PathElem; |
2718 | } |
2719 | for (const CXXBaseSpecifier &BS : Derived->bases()) |
2720 | if (BS.getType()->getAsCXXRecordDecl()->getCanonicalDecl() == |
2721 | Base->getCanonicalDecl()) |
2722 | DerivedToBasePath.push_back(&BS); |
2723 | PrevRD = PathElem; |
2724 | } |
2725 | assert(DerivedToBasePath.size() == MemberPointerPath.size()); |
2726 | |
2727 | CastKind CK = DerivedMember ? CK_DerivedToBaseMemberPointer |
2728 | : CK_BaseToDerivedMemberPointer; |
2729 | C = EmitMemberPointerConversion(SrcTy, DstTy, CK, DerivedToBasePath.begin(), |
2730 | DerivedToBasePath.end(), C); |
2731 | } |
2732 | return C; |
2733 | } |
2734 | |
2735 | llvm::Constant * |
2736 | MicrosoftCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { |
2737 | (0) . __assert_fail ("MD->isInstance() && \"Member function must not be static!\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 2737, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(MD->isInstance() && "Member function must not be static!"); |
2738 | |
2739 | CharUnits NonVirtualBaseAdjustment = CharUnits::Zero(); |
2740 | const CXXRecordDecl *RD = MD->getParent()->getMostRecentNonInjectedDecl(); |
2741 | CodeGenTypes &Types = CGM.getTypes(); |
2742 | |
2743 | unsigned VBTableIndex = 0; |
2744 | llvm::Constant *FirstField; |
2745 | const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); |
2746 | if (!MD->isVirtual()) { |
2747 | llvm::Type *Ty; |
2748 | |
2749 | if (Types.isFuncTypeConvertible(FPT)) { |
2750 | |
2751 | Ty = Types.GetFunctionType(Types.arrangeCXXMethodDeclaration(MD)); |
2752 | } else { |
2753 | |
2754 | |
2755 | Ty = CGM.PtrDiffTy; |
2756 | } |
2757 | FirstField = CGM.GetAddrOfFunction(MD, Ty); |
2758 | } else { |
2759 | auto &VTableContext = CGM.getMicrosoftVTableContext(); |
2760 | MethodVFTableLocation ML = VTableContext.getMethodVFTableLocation(MD); |
2761 | FirstField = EmitVirtualMemPtrThunk(MD, ML); |
2762 | |
2763 | NonVirtualBaseAdjustment += ML.VFPtrOffset; |
2764 | if (ML.VBase) |
2765 | VBTableIndex = VTableContext.getVBTableIndex(RD, ML.VBase) * 4; |
2766 | } |
2767 | |
2768 | if (VBTableIndex == 0 && |
2769 | RD->getMSInheritanceModel() == |
2770 | MSInheritanceAttr::Keyword_virtual_inheritance) |
2771 | NonVirtualBaseAdjustment -= getContext().getOffsetOfBaseWithVBPtr(RD); |
2772 | |
2773 | |
2774 | FirstField = llvm::ConstantExpr::getBitCast(FirstField, CGM.VoidPtrTy); |
2775 | return EmitFullMemberPointer(FirstField, , RD, |
2776 | NonVirtualBaseAdjustment, VBTableIndex); |
2777 | } |
2778 | |
2779 | |
2780 | |
2781 | |
2782 | llvm::Value * |
2783 | MicrosoftCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF, |
2784 | llvm::Value *L, |
2785 | llvm::Value *R, |
2786 | const MemberPointerType *MPT, |
2787 | bool Inequality) { |
2788 | CGBuilderTy &Builder = CGF.Builder; |
2789 | |
2790 | |
2791 | llvm::ICmpInst::Predicate Eq; |
2792 | llvm::Instruction::BinaryOps And, Or; |
2793 | if (Inequality) { |
2794 | Eq = llvm::ICmpInst::ICMP_NE; |
2795 | And = llvm::Instruction::Or; |
2796 | Or = llvm::Instruction::And; |
2797 | } else { |
2798 | Eq = llvm::ICmpInst::ICMP_EQ; |
2799 | And = llvm::Instruction::And; |
2800 | Or = llvm::Instruction::Or; |
2801 | } |
2802 | |
2803 | |
2804 | |
2805 | const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); |
2806 | MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); |
2807 | if (MSInheritanceAttr::hasOnlyOneField(MPT->isMemberFunctionPointer(), |
2808 | Inheritance)) |
2809 | return Builder.CreateICmp(Eq, L, R); |
2810 | |
2811 | |
2812 | llvm::Value *L0 = Builder.CreateExtractValue(L, 0, "lhs.0"); |
2813 | llvm::Value *R0 = Builder.CreateExtractValue(R, 0, "rhs.0"); |
2814 | llvm::Value *Cmp0 = Builder.CreateICmp(Eq, L0, R0, "memptr.cmp.first"); |
2815 | |
2816 | |
2817 | llvm::Value *Res = nullptr; |
2818 | llvm::StructType *LType = cast<llvm::StructType>(L->getType()); |
2819 | for (unsigned I = 1, E = LType->getNumElements(); I != E; ++I) { |
2820 | llvm::Value *LF = Builder.CreateExtractValue(L, I); |
2821 | llvm::Value *RF = Builder.CreateExtractValue(R, I); |
2822 | llvm::Value *Cmp = Builder.CreateICmp(Eq, LF, RF, "memptr.cmp.rest"); |
2823 | if (Res) |
2824 | Res = Builder.CreateBinOp(And, Res, Cmp); |
2825 | else |
2826 | Res = Cmp; |
2827 | } |
2828 | |
2829 | |
2830 | if (MPT->isMemberFunctionPointer()) { |
2831 | |
2832 | llvm::Value *Zero = llvm::Constant::getNullValue(L0->getType()); |
2833 | llvm::Value *IsZero = Builder.CreateICmp(Eq, L0, Zero, "memptr.cmp.iszero"); |
2834 | Res = Builder.CreateBinOp(Or, Res, IsZero); |
2835 | } |
2836 | |
2837 | |
2838 | |
2839 | return Builder.CreateBinOp(And, Res, Cmp0, "memptr.cmp"); |
2840 | } |
2841 | |
2842 | llvm::Value * |
2843 | MicrosoftCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF, |
2844 | llvm::Value *MemPtr, |
2845 | const MemberPointerType *MPT) { |
2846 | CGBuilderTy &Builder = CGF.Builder; |
2847 | llvm::SmallVector<llvm::Constant *, 4> fields; |
2848 | |
2849 | if (MPT->isMemberFunctionPointer()) |
2850 | fields.push_back(llvm::Constant::getNullValue(CGM.VoidPtrTy)); |
2851 | else |
2852 | GetNullMemberPointerFields(MPT, fields); |
2853 | assert(!fields.empty()); |
2854 | llvm::Value *FirstField = MemPtr; |
2855 | if (MemPtr->getType()->isStructTy()) |
2856 | FirstField = Builder.CreateExtractValue(MemPtr, 0); |
2857 | llvm::Value *Res = Builder.CreateICmpNE(FirstField, fields[0], "memptr.cmp0"); |
2858 | |
2859 | |
2860 | |
2861 | if (MPT->isMemberFunctionPointer()) |
2862 | return Res; |
2863 | |
2864 | |
2865 | for (int I = 1, E = fields.size(); I < E; ++I) { |
2866 | llvm::Value *Field = Builder.CreateExtractValue(MemPtr, I); |
2867 | llvm::Value *Next = Builder.CreateICmpNE(Field, fields[I], "memptr.cmp"); |
2868 | Res = Builder.CreateOr(Res, Next, "memptr.tobool"); |
2869 | } |
2870 | return Res; |
2871 | } |
2872 | |
2873 | bool MicrosoftCXXABI::MemberPointerConstantIsNull(const MemberPointerType *MPT, |
2874 | llvm::Constant *Val) { |
2875 | |
2876 | if (MPT->isMemberFunctionPointer()) { |
2877 | llvm::Constant *FirstField = Val->getType()->isStructTy() ? |
2878 | Val->getAggregateElement(0U) : Val; |
2879 | return FirstField->isNullValue(); |
2880 | } |
2881 | |
2882 | |
2883 | |
2884 | if (isZeroInitializable(MPT) && Val->isNullValue()) |
2885 | return true; |
2886 | |
2887 | |
2888 | |
2889 | llvm::SmallVector<llvm::Constant *, 4> Fields; |
2890 | GetNullMemberPointerFields(MPT, Fields); |
2891 | if (Fields.size() == 1) { |
2892 | getType()->isIntegerTy()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 2892, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Val->getType()->isIntegerTy()); |
2893 | return Val == Fields[0]; |
2894 | } |
2895 | |
2896 | unsigned I, E; |
2897 | for (I = 0, E = Fields.size(); I != E; ++I) { |
2898 | if (Val->getAggregateElement(I) != Fields[I]) |
2899 | break; |
2900 | } |
2901 | return I == E; |
2902 | } |
2903 | |
2904 | llvm::Value * |
2905 | MicrosoftCXXABI::GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF, |
2906 | Address This, |
2907 | llvm::Value *VBPtrOffset, |
2908 | llvm::Value *VBTableOffset, |
2909 | llvm::Value **VBPtrOut) { |
2910 | CGBuilderTy &Builder = CGF.Builder; |
2911 | |
2912 | This = Builder.CreateElementBitCast(This, CGM.Int8Ty); |
2913 | llvm::Value *VBPtr = |
2914 | Builder.CreateInBoundsGEP(This.getPointer(), VBPtrOffset, "vbptr"); |
2915 | if (VBPtrOut) *VBPtrOut = VBPtr; |
2916 | VBPtr = Builder.CreateBitCast(VBPtr, |
2917 | CGM.Int32Ty->getPointerTo(0)->getPointerTo(This.getAddressSpace())); |
2918 | |
2919 | CharUnits VBPtrAlign; |
2920 | if (auto CI = dyn_cast<llvm::ConstantInt>(VBPtrOffset)) { |
2921 | VBPtrAlign = This.getAlignment().alignmentAtOffset( |
2922 | CharUnits::fromQuantity(CI->getSExtValue())); |
2923 | } else { |
2924 | VBPtrAlign = CGF.getPointerAlign(); |
2925 | } |
2926 | |
2927 | llvm::Value *VBTable = Builder.CreateAlignedLoad(VBPtr, VBPtrAlign, "vbtable"); |
2928 | |
2929 | |
2930 | llvm::Value *VBTableIndex = Builder.CreateAShr( |
2931 | VBTableOffset, llvm::ConstantInt::get(VBTableOffset->getType(), 2), |
2932 | "vbtindex", ); |
2933 | |
2934 | |
2935 | llvm::Value *VBaseOffs = Builder.CreateInBoundsGEP(VBTable, VBTableIndex); |
2936 | VBaseOffs = Builder.CreateBitCast(VBaseOffs, CGM.Int32Ty->getPointerTo(0)); |
2937 | return Builder.CreateAlignedLoad(VBaseOffs, CharUnits::fromQuantity(4), |
2938 | "vbase_offs"); |
2939 | } |
2940 | |
2941 | |
2942 | |
2943 | llvm::Value *MicrosoftCXXABI::AdjustVirtualBase( |
2944 | CodeGenFunction &CGF, const Expr *E, const CXXRecordDecl *RD, |
2945 | Address Base, llvm::Value *VBTableOffset, llvm::Value *VBPtrOffset) { |
2946 | CGBuilderTy &Builder = CGF.Builder; |
2947 | Base = Builder.CreateElementBitCast(Base, CGM.Int8Ty); |
2948 | llvm::BasicBlock *OriginalBB = nullptr; |
2949 | llvm::BasicBlock *SkipAdjustBB = nullptr; |
2950 | llvm::BasicBlock *VBaseAdjustBB = nullptr; |
2951 | |
2952 | |
2953 | |
2954 | |
2955 | |
2956 | if (VBPtrOffset) { |
2957 | OriginalBB = Builder.GetInsertBlock(); |
2958 | VBaseAdjustBB = CGF.createBasicBlock("memptr.vadjust"); |
2959 | SkipAdjustBB = CGF.createBasicBlock("memptr.skip_vadjust"); |
2960 | llvm::Value *IsVirtual = |
2961 | Builder.CreateICmpNE(VBTableOffset, getZeroInt(), |
2962 | "memptr.is_vbase"); |
2963 | Builder.CreateCondBr(IsVirtual, VBaseAdjustBB, SkipAdjustBB); |
2964 | CGF.EmitBlock(VBaseAdjustBB); |
2965 | } |
2966 | |
2967 | |
2968 | |
2969 | if (!VBPtrOffset) { |
2970 | CharUnits offs = CharUnits::Zero(); |
2971 | if (!RD->hasDefinition()) { |
2972 | DiagnosticsEngine &Diags = CGF.CGM.getDiags(); |
2973 | unsigned DiagID = Diags.getCustomDiagID( |
2974 | DiagnosticsEngine::Error, |
2975 | "member pointer representation requires a " |
2976 | "complete class type for %0 to perform this expression"); |
2977 | Diags.Report(E->getExprLoc(), DiagID) << RD << E->getSourceRange(); |
2978 | } else if (RD->getNumVBases()) |
2979 | offs = getContext().getASTRecordLayout(RD).getVBPtrOffset(); |
2980 | VBPtrOffset = llvm::ConstantInt::get(CGM.IntTy, offs.getQuantity()); |
2981 | } |
2982 | llvm::Value *VBPtr = nullptr; |
2983 | llvm::Value *VBaseOffs = |
2984 | GetVBaseOffsetFromVBPtr(CGF, Base, VBPtrOffset, VBTableOffset, &VBPtr); |
2985 | llvm::Value *AdjustedBase = Builder.CreateInBoundsGEP(VBPtr, VBaseOffs); |
2986 | |
2987 | |
2988 | if (VBaseAdjustBB) { |
2989 | Builder.CreateBr(SkipAdjustBB); |
2990 | CGF.EmitBlock(SkipAdjustBB); |
2991 | llvm::PHINode *Phi = Builder.CreatePHI(CGM.Int8PtrTy, 2, "memptr.base"); |
2992 | Phi->addIncoming(Base.getPointer(), OriginalBB); |
2993 | Phi->addIncoming(AdjustedBase, VBaseAdjustBB); |
2994 | return Phi; |
2995 | } |
2996 | return AdjustedBase; |
2997 | } |
2998 | |
2999 | llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress( |
3000 | CodeGenFunction &CGF, const Expr *E, Address Base, llvm::Value *MemPtr, |
3001 | const MemberPointerType *MPT) { |
3002 | isMemberDataPointer()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 3002, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(MPT->isMemberDataPointer()); |
3003 | unsigned AS = Base.getAddressSpace(); |
3004 | llvm::Type *PType = |
3005 | CGF.ConvertTypeForMem(MPT->getPointeeType())->getPointerTo(AS); |
3006 | CGBuilderTy &Builder = CGF.Builder; |
3007 | const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); |
3008 | MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); |
3009 | |
3010 | |
3011 | |
3012 | llvm::Value *FieldOffset = MemPtr; |
3013 | llvm::Value *VirtualBaseAdjustmentOffset = nullptr; |
3014 | llvm::Value *VBPtrOffset = nullptr; |
3015 | if (MemPtr->getType()->isStructTy()) { |
3016 | |
3017 | unsigned I = 0; |
3018 | FieldOffset = Builder.CreateExtractValue(MemPtr, I++); |
3019 | if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) |
3020 | VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++); |
3021 | if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance)) |
3022 | VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++); |
3023 | } |
3024 | |
3025 | llvm::Value *Addr; |
3026 | if (VirtualBaseAdjustmentOffset) { |
3027 | Addr = AdjustVirtualBase(CGF, E, RD, Base, VirtualBaseAdjustmentOffset, |
3028 | VBPtrOffset); |
3029 | } else { |
3030 | Addr = Base.getPointer(); |
3031 | } |
3032 | |
3033 | |
3034 | Addr = Builder.CreateBitCast(Addr, CGF.Int8Ty->getPointerTo(AS)); |
3035 | |
3036 | |
3037 | Addr = Builder.CreateInBoundsGEP(Addr, FieldOffset, "memptr.offset"); |
3038 | |
3039 | |
3040 | |
3041 | return Builder.CreateBitCast(Addr, PType); |
3042 | } |
3043 | |
3044 | llvm::Value * |
3045 | MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, |
3046 | const CastExpr *E, |
3047 | llvm::Value *Src) { |
3048 | getCastKind() == CK_DerivedToBaseMemberPointer || E->getCastKind() == CK_BaseToDerivedMemberPointer || E->getCastKind() == CK_ReinterpretMemberPointer", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 3050, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || |
3049 | getCastKind() == CK_DerivedToBaseMemberPointer || E->getCastKind() == CK_BaseToDerivedMemberPointer || E->getCastKind() == CK_ReinterpretMemberPointer", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 3050, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> E->getCastKind() == CK_BaseToDerivedMemberPointer || |
3050 | getCastKind() == CK_DerivedToBaseMemberPointer || E->getCastKind() == CK_BaseToDerivedMemberPointer || E->getCastKind() == CK_ReinterpretMemberPointer", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 3050, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> E->getCastKind() == CK_ReinterpretMemberPointer); |
3051 | |
3052 | |
3053 | if (isa<llvm::Constant>(Src)) |
3054 | return EmitMemberPointerConversion(E, cast<llvm::Constant>(Src)); |
3055 | |
3056 | |
3057 | |
3058 | const MemberPointerType *SrcTy = |
3059 | E->getSubExpr()->getType()->castAs<MemberPointerType>(); |
3060 | const MemberPointerType *DstTy = E->getType()->castAs<MemberPointerType>(); |
3061 | bool IsFunc = SrcTy->isMemberFunctionPointer(); |
3062 | |
3063 | |
3064 | bool IsReinterpret = E->getCastKind() == CK_ReinterpretMemberPointer; |
3065 | if (IsReinterpret && IsFunc) |
3066 | return Src; |
3067 | |
3068 | CXXRecordDecl *SrcRD = SrcTy->getMostRecentCXXRecordDecl(); |
3069 | CXXRecordDecl *DstRD = DstTy->getMostRecentCXXRecordDecl(); |
3070 | if (IsReinterpret && |
3071 | SrcRD->nullFieldOffsetIsZero() == DstRD->nullFieldOffsetIsZero()) |
3072 | return Src; |
3073 | |
3074 | CGBuilderTy &Builder = CGF.Builder; |
3075 | |
3076 | |
3077 | llvm::Value *IsNotNull = EmitMemberPointerIsNotNull(CGF, Src, SrcTy); |
3078 | llvm::Constant *DstNull = EmitNullMemberPointer(DstTy); |
3079 | |
3080 | |
3081 | |
3082 | if (IsReinterpret) { |
3083 | |
3084 | |
3085 | getType() == DstNull->getType()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 3085, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Src->getType() == DstNull->getType()); |
3086 | return Builder.CreateSelect(IsNotNull, Src, DstNull); |
3087 | } |
3088 | |
3089 | llvm::BasicBlock *OriginalBB = Builder.GetInsertBlock(); |
3090 | llvm::BasicBlock *ConvertBB = CGF.createBasicBlock("memptr.convert"); |
3091 | llvm::BasicBlock *ContinueBB = CGF.createBasicBlock("memptr.converted"); |
3092 | Builder.CreateCondBr(IsNotNull, ConvertBB, ContinueBB); |
3093 | CGF.EmitBlock(ConvertBB); |
3094 | |
3095 | llvm::Value *Dst = EmitNonNullMemberPointerConversion( |
3096 | SrcTy, DstTy, E->getCastKind(), E->path_begin(), E->path_end(), Src, |
3097 | Builder); |
3098 | |
3099 | Builder.CreateBr(ContinueBB); |
3100 | |
3101 | |
3102 | CGF.EmitBlock(ContinueBB); |
3103 | llvm::PHINode *Phi = Builder.CreatePHI(DstNull->getType(), 2, "memptr.converted"); |
3104 | Phi->addIncoming(DstNull, OriginalBB); |
3105 | Phi->addIncoming(Dst, ConvertBB); |
3106 | return Phi; |
3107 | } |
3108 | |
3109 | llvm::Value *MicrosoftCXXABI::EmitNonNullMemberPointerConversion( |
3110 | const MemberPointerType *SrcTy, const MemberPointerType *DstTy, CastKind CK, |
3111 | CastExpr::path_const_iterator PathBegin, |
3112 | CastExpr::path_const_iterator PathEnd, llvm::Value *Src, |
3113 | CGBuilderTy &Builder) { |
3114 | const CXXRecordDecl *SrcRD = SrcTy->getMostRecentCXXRecordDecl(); |
3115 | const CXXRecordDecl *DstRD = DstTy->getMostRecentCXXRecordDecl(); |
3116 | MSInheritanceAttr::Spelling SrcInheritance = SrcRD->getMSInheritanceModel(); |
3117 | MSInheritanceAttr::Spelling DstInheritance = DstRD->getMSInheritanceModel(); |
3118 | bool IsFunc = SrcTy->isMemberFunctionPointer(); |
3119 | bool IsConstant = isa<llvm::Constant>(Src); |
3120 | |
3121 | |
3122 | llvm::Value *FirstField = Src; |
3123 | llvm::Value *NonVirtualBaseAdjustment = getZeroInt(); |
3124 | llvm::Value *VirtualBaseAdjustmentOffset = getZeroInt(); |
3125 | llvm::Value *VBPtrOffset = getZeroInt(); |
3126 | if (!MSInheritanceAttr::hasOnlyOneField(IsFunc, SrcInheritance)) { |
3127 | |
3128 | unsigned I = 0; |
3129 | FirstField = Builder.CreateExtractValue(Src, I++); |
3130 | if (MSInheritanceAttr::hasNVOffsetField(IsFunc, SrcInheritance)) |
3131 | NonVirtualBaseAdjustment = Builder.CreateExtractValue(Src, I++); |
3132 | if (MSInheritanceAttr::hasVBPtrOffsetField(SrcInheritance)) |
3133 | VBPtrOffset = Builder.CreateExtractValue(Src, I++); |
3134 | if (MSInheritanceAttr::hasVBTableOffsetField(SrcInheritance)) |
3135 | VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(Src, I++); |
3136 | } |
3137 | |
3138 | bool IsDerivedToBase = (CK == CK_DerivedToBaseMemberPointer); |
3139 | const MemberPointerType *DerivedTy = IsDerivedToBase ? SrcTy : DstTy; |
3140 | const CXXRecordDecl *DerivedClass = DerivedTy->getMostRecentCXXRecordDecl(); |
3141 | |
3142 | |
3143 | |
3144 | llvm::Value *&NVAdjustField = IsFunc ? NonVirtualBaseAdjustment : FirstField; |
3145 | |
3146 | |
3147 | |
3148 | |
3149 | |
3150 | |
3151 | llvm::Value *SrcVBIndexEqZero = |
3152 | Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt()); |
3153 | if (SrcInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) { |
3154 | if (int64_t SrcOffsetToFirstVBase = |
3155 | getContext().getOffsetOfBaseWithVBPtr(SrcRD).getQuantity()) { |
3156 | llvm::Value *UndoSrcAdjustment = Builder.CreateSelect( |
3157 | SrcVBIndexEqZero, |
3158 | llvm::ConstantInt::get(CGM.IntTy, SrcOffsetToFirstVBase), |
3159 | getZeroInt()); |
3160 | NVAdjustField = Builder.CreateNSWAdd(NVAdjustField, UndoSrcAdjustment); |
3161 | } |
3162 | } |
3163 | |
3164 | |
3165 | |
3166 | |
3167 | |
3168 | |
3169 | |
3170 | |
3171 | llvm::Constant *BaseClassOffset = llvm::ConstantInt::get( |
3172 | CGM.IntTy, |
3173 | CGM.computeNonVirtualBaseClassOffset(DerivedClass, PathBegin, PathEnd) |
3174 | .getQuantity()); |
3175 | |
3176 | llvm::Value *NVDisp; |
3177 | if (IsDerivedToBase) |
3178 | NVDisp = Builder.CreateNSWSub(NVAdjustField, BaseClassOffset, "adj"); |
3179 | else |
3180 | NVDisp = Builder.CreateNSWAdd(NVAdjustField, BaseClassOffset, "adj"); |
3181 | |
3182 | NVAdjustField = Builder.CreateSelect(SrcVBIndexEqZero, NVDisp, getZeroInt()); |
3183 | |
3184 | |
3185 | |
3186 | llvm::Value *DstVBIndexEqZero = SrcVBIndexEqZero; |
3187 | if (MSInheritanceAttr::hasVBTableOffsetField(DstInheritance) && |
3188 | MSInheritanceAttr::hasVBTableOffsetField(SrcInheritance)) { |
3189 | if (llvm::GlobalVariable *VDispMap = |
3190 | getAddrOfVirtualDisplacementMap(SrcRD, DstRD)) { |
3191 | llvm::Value *VBIndex = Builder.CreateExactUDiv( |
3192 | VirtualBaseAdjustmentOffset, llvm::ConstantInt::get(CGM.IntTy, 4)); |
3193 | if (IsConstant) { |
3194 | llvm::Constant *Mapping = VDispMap->getInitializer(); |
3195 | VirtualBaseAdjustmentOffset = |
3196 | Mapping->getAggregateElement(cast<llvm::Constant>(VBIndex)); |
3197 | } else { |
3198 | llvm::Value *Idxs[] = {getZeroInt(), VBIndex}; |
3199 | VirtualBaseAdjustmentOffset = |
3200 | Builder.CreateAlignedLoad(Builder.CreateInBoundsGEP(VDispMap, Idxs), |
3201 | CharUnits::fromQuantity(4)); |
3202 | } |
3203 | |
3204 | DstVBIndexEqZero = |
3205 | Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt()); |
3206 | } |
3207 | } |
3208 | |
3209 | |
3210 | |
3211 | if (MSInheritanceAttr::hasVBPtrOffsetField(DstInheritance)) { |
3212 | llvm::Value *DstVBPtrOffset = llvm::ConstantInt::get( |
3213 | CGM.IntTy, |
3214 | getContext().getASTRecordLayout(DstRD).getVBPtrOffset().getQuantity()); |
3215 | VBPtrOffset = |
3216 | Builder.CreateSelect(DstVBIndexEqZero, getZeroInt(), DstVBPtrOffset); |
3217 | } |
3218 | |
3219 | |
3220 | |
3221 | |
3222 | if (DstInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) { |
3223 | if (int64_t DstOffsetToFirstVBase = |
3224 | getContext().getOffsetOfBaseWithVBPtr(DstRD).getQuantity()) { |
3225 | llvm::Value *DoDstAdjustment = Builder.CreateSelect( |
3226 | DstVBIndexEqZero, |
3227 | llvm::ConstantInt::get(CGM.IntTy, DstOffsetToFirstVBase), |
3228 | getZeroInt()); |
3229 | NVAdjustField = Builder.CreateNSWSub(NVAdjustField, DoDstAdjustment); |
3230 | } |
3231 | } |
3232 | |
3233 | |
3234 | llvm::Value *Dst; |
3235 | if (MSInheritanceAttr::hasOnlyOneField(IsFunc, DstInheritance)) { |
3236 | Dst = FirstField; |
3237 | } else { |
3238 | Dst = llvm::UndefValue::get(ConvertMemberPointerType(DstTy)); |
3239 | unsigned Idx = 0; |
3240 | Dst = Builder.CreateInsertValue(Dst, FirstField, Idx++); |
3241 | if (MSInheritanceAttr::hasNVOffsetField(IsFunc, DstInheritance)) |
3242 | Dst = Builder.CreateInsertValue(Dst, NonVirtualBaseAdjustment, Idx++); |
3243 | if (MSInheritanceAttr::hasVBPtrOffsetField(DstInheritance)) |
3244 | Dst = Builder.CreateInsertValue(Dst, VBPtrOffset, Idx++); |
3245 | if (MSInheritanceAttr::hasVBTableOffsetField(DstInheritance)) |
3246 | Dst = Builder.CreateInsertValue(Dst, VirtualBaseAdjustmentOffset, Idx++); |
3247 | } |
3248 | return Dst; |
3249 | } |
3250 | |
3251 | llvm::Constant * |
3252 | MicrosoftCXXABI::EmitMemberPointerConversion(const CastExpr *E, |
3253 | llvm::Constant *Src) { |
3254 | const MemberPointerType *SrcTy = |
3255 | E->getSubExpr()->getType()->castAs<MemberPointerType>(); |
3256 | const MemberPointerType *DstTy = E->getType()->castAs<MemberPointerType>(); |
3257 | |
3258 | CastKind CK = E->getCastKind(); |
3259 | |
3260 | return EmitMemberPointerConversion(SrcTy, DstTy, CK, E->path_begin(), |
3261 | E->path_end(), Src); |
3262 | } |
3263 | |
3264 | llvm::Constant *MicrosoftCXXABI::EmitMemberPointerConversion( |
3265 | const MemberPointerType *SrcTy, const MemberPointerType *DstTy, CastKind CK, |
3266 | CastExpr::path_const_iterator PathBegin, |
3267 | CastExpr::path_const_iterator PathEnd, llvm::Constant *Src) { |
3268 | assert(CK == CK_DerivedToBaseMemberPointer || |
3269 | CK == CK_BaseToDerivedMemberPointer || |
3270 | CK == CK_ReinterpretMemberPointer); |
3271 | |
3272 | |
3273 | if (MemberPointerConstantIsNull(SrcTy, Src)) |
3274 | return EmitNullMemberPointer(DstTy); |
3275 | |
3276 | |
3277 | |
3278 | |
3279 | if (CK == CK_ReinterpretMemberPointer) |
3280 | return Src; |
3281 | |
3282 | CGBuilderTy Builder(CGM, CGM.getLLVMContext()); |
3283 | auto *Dst = cast<llvm::Constant>(EmitNonNullMemberPointerConversion( |
3284 | SrcTy, DstTy, CK, PathBegin, PathEnd, Src, Builder)); |
3285 | |
3286 | return Dst; |
3287 | } |
3288 | |
3289 | CGCallee MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer( |
3290 | CodeGenFunction &CGF, const Expr *E, Address This, |
3291 | llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr, |
3292 | const MemberPointerType *MPT) { |
3293 | isMemberFunctionPointer()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 3293, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(MPT->isMemberFunctionPointer()); |
3294 | const FunctionProtoType *FPT = |
3295 | MPT->getPointeeType()->castAs<FunctionProtoType>(); |
3296 | const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); |
3297 | llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType( |
3298 | CGM.getTypes().arrangeCXXMethodType(RD, FPT, )); |
3299 | CGBuilderTy &Builder = CGF.Builder; |
3300 | |
3301 | MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); |
3302 | |
3303 | |
3304 | |
3305 | llvm::Value *FunctionPointer = MemPtr; |
3306 | llvm::Value *NonVirtualBaseAdjustment = nullptr; |
3307 | llvm::Value *VirtualBaseAdjustmentOffset = nullptr; |
3308 | llvm::Value *VBPtrOffset = nullptr; |
3309 | if (MemPtr->getType()->isStructTy()) { |
3310 | |
3311 | unsigned I = 0; |
3312 | FunctionPointer = Builder.CreateExtractValue(MemPtr, I++); |
3313 | if (MSInheritanceAttr::hasNVOffsetField(MPT, Inheritance)) |
3314 | NonVirtualBaseAdjustment = Builder.CreateExtractValue(MemPtr, I++); |
3315 | if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) |
3316 | VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++); |
3317 | if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance)) |
3318 | VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++); |
3319 | } |
3320 | |
3321 | if (VirtualBaseAdjustmentOffset) { |
3322 | ThisPtrForCall = AdjustVirtualBase(CGF, E, RD, This, |
3323 | VirtualBaseAdjustmentOffset, VBPtrOffset); |
3324 | } else { |
3325 | ThisPtrForCall = This.getPointer(); |
3326 | } |
3327 | |
3328 | if (NonVirtualBaseAdjustment) { |
3329 | |
3330 | llvm::Value *Ptr = Builder.CreateBitCast(ThisPtrForCall, CGF.Int8PtrTy); |
3331 | Ptr = Builder.CreateInBoundsGEP(Ptr, NonVirtualBaseAdjustment); |
3332 | ThisPtrForCall = Builder.CreateBitCast(Ptr, ThisPtrForCall->getType(), |
3333 | "this.adjusted"); |
3334 | } |
3335 | |
3336 | FunctionPointer = |
3337 | Builder.CreateBitCast(FunctionPointer, FTy->getPointerTo()); |
3338 | CGCallee Callee(FPT, FunctionPointer); |
3339 | return Callee; |
3340 | } |
3341 | |
3342 | CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) { |
3343 | return new MicrosoftCXXABI(CGM); |
3344 | } |
3345 | |
3346 | |
3347 | |
3348 | |
3349 | |
3350 | |
3351 | |
3352 | |
3353 | |
3354 | |
3355 | |
3356 | |
3357 | |
3358 | |
3359 | |
3360 | |
3361 | |
3362 | |
3363 | |
3364 | |
3365 | |
3366 | |
3367 | |
3368 | |
3369 | |
3370 | |
3371 | |
3372 | |
3373 | |
3374 | |
3375 | |
3376 | static llvm::GlobalVariable *getTypeInfoVTable(CodeGenModule &CGM) { |
3377 | StringRef MangledName("??_7type_info@@6B@"); |
3378 | if (auto VTable = CGM.getModule().getNamedGlobal(MangledName)) |
3379 | return VTable; |
3380 | return new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy, |
3381 | , |
3382 | llvm::GlobalVariable::ExternalLinkage, |
3383 | , MangledName); |
3384 | } |
3385 | |
3386 | namespace { |
3387 | |
3388 | |
3389 | |
3390 | |
3391 | |
3392 | |
3393 | |
3394 | struct MSRTTIClass { |
3395 | enum { |
3396 | IsPrivateOnPath = 1 | 8, |
3397 | IsAmbiguous = 2, |
3398 | IsPrivate = 4, |
3399 | IsVirtual = 16, |
3400 | HasHierarchyDescriptor = 64 |
3401 | }; |
3402 | MSRTTIClass(const CXXRecordDecl *RD) : RD(RD) {} |
3403 | uint32_t initialize(const MSRTTIClass *Parent, |
3404 | const CXXBaseSpecifier *Specifier); |
3405 | |
3406 | MSRTTIClass *getFirstChild() { return this + 1; } |
3407 | static MSRTTIClass *getNextChild(MSRTTIClass *Child) { |
3408 | return Child + 1 + Child->NumBases; |
3409 | } |
3410 | |
3411 | const CXXRecordDecl *RD, *VirtualRoot; |
3412 | uint32_t Flags, NumBases, OffsetInVBase; |
3413 | }; |
3414 | |
3415 | |
3416 | uint32_t MSRTTIClass::initialize(const MSRTTIClass *Parent, |
3417 | const CXXBaseSpecifier *Specifier) { |
3418 | Flags = HasHierarchyDescriptor; |
3419 | if (!Parent) { |
3420 | VirtualRoot = nullptr; |
3421 | OffsetInVBase = 0; |
3422 | } else { |
3423 | if (Specifier->getAccessSpecifier() != AS_public) |
3424 | Flags |= IsPrivate | IsPrivateOnPath; |
3425 | if (Specifier->isVirtual()) { |
3426 | Flags |= IsVirtual; |
3427 | VirtualRoot = RD; |
3428 | OffsetInVBase = 0; |
3429 | } else { |
3430 | if (Parent->Flags & IsPrivateOnPath) |
3431 | Flags |= IsPrivateOnPath; |
3432 | VirtualRoot = Parent->VirtualRoot; |
3433 | OffsetInVBase = Parent->OffsetInVBase + RD->getASTContext() |
3434 | .getASTRecordLayout(Parent->RD).getBaseClassOffset(RD).getQuantity(); |
3435 | } |
3436 | } |
3437 | NumBases = 0; |
3438 | MSRTTIClass *Child = getFirstChild(); |
3439 | for (const CXXBaseSpecifier &Base : RD->bases()) { |
3440 | NumBases += Child->initialize(this, &Base) + 1; |
3441 | Child = getNextChild(Child); |
3442 | } |
3443 | return NumBases; |
3444 | } |
3445 | |
3446 | static llvm::GlobalValue::LinkageTypes getLinkageForRTTI(QualType Ty) { |
3447 | switch (Ty->getLinkage()) { |
3448 | case NoLinkage: |
3449 | case InternalLinkage: |
3450 | case UniqueExternalLinkage: |
3451 | return llvm::GlobalValue::InternalLinkage; |
3452 | |
3453 | case VisibleNoLinkage: |
3454 | case ModuleInternalLinkage: |
3455 | case ModuleLinkage: |
3456 | case ExternalLinkage: |
3457 | return llvm::GlobalValue::LinkOnceODRLinkage; |
3458 | } |
3459 | llvm_unreachable("Invalid linkage!"); |
3460 | } |
3461 | |
3462 | |
3463 | |
3464 | |
3465 | struct MSRTTIBuilder { |
3466 | enum { |
3467 | HasBranchingHierarchy = 1, |
3468 | HasVirtualBranchingHierarchy = 2, |
3469 | HasAmbiguousBases = 4 |
3470 | }; |
3471 | |
3472 | MSRTTIBuilder(MicrosoftCXXABI &ABI, const CXXRecordDecl *RD) |
3473 | : CGM(ABI.CGM), Context(CGM.getContext()), |
3474 | VMContext(CGM.getLLVMContext()), Module(CGM.getModule()), RD(RD), |
3475 | Linkage(getLinkageForRTTI(CGM.getContext().getTagDeclType(RD))), |
3476 | ABI(ABI) {} |
3477 | |
3478 | llvm::GlobalVariable *getBaseClassDescriptor(const MSRTTIClass &Classes); |
3479 | llvm::GlobalVariable * |
3480 | getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes); |
3481 | llvm::GlobalVariable *getClassHierarchyDescriptor(); |
3482 | llvm::GlobalVariable *getCompleteObjectLocator(const VPtrInfo &Info); |
3483 | |
3484 | CodeGenModule &CGM; |
3485 | ASTContext &Context; |
3486 | llvm::LLVMContext &VMContext; |
3487 | llvm::Module &Module; |
3488 | const CXXRecordDecl *RD; |
3489 | llvm::GlobalVariable::LinkageTypes Linkage; |
3490 | MicrosoftCXXABI &ABI; |
3491 | }; |
3492 | |
3493 | } |
3494 | |
3495 | |
3496 | |
3497 | static void serializeClassHierarchy(SmallVectorImpl<MSRTTIClass> &Classes, |
3498 | const CXXRecordDecl *RD) { |
3499 | Classes.push_back(MSRTTIClass(RD)); |
3500 | for (const CXXBaseSpecifier &Base : RD->bases()) |
3501 | serializeClassHierarchy(Classes, Base.getType()->getAsCXXRecordDecl()); |
3502 | } |
3503 | |
3504 | |
3505 | static void |
3506 | detectAmbiguousBases(SmallVectorImpl<MSRTTIClass> &Classes) { |
3507 | llvm::SmallPtrSet<const CXXRecordDecl *, 8> VirtualBases; |
3508 | llvm::SmallPtrSet<const CXXRecordDecl *, 8> UniqueBases; |
3509 | llvm::SmallPtrSet<const CXXRecordDecl *, 8> AmbiguousBases; |
3510 | for (MSRTTIClass *Class = &Classes.front(); Class <= &Classes.back();) { |
3511 | if ((Class->Flags & MSRTTIClass::IsVirtual) && |
3512 | !VirtualBases.insert(Class->RD).second) { |
3513 | Class = MSRTTIClass::getNextChild(Class); |
3514 | continue; |
3515 | } |
3516 | if (!UniqueBases.insert(Class->RD).second) |
3517 | AmbiguousBases.insert(Class->RD); |
3518 | Class++; |
3519 | } |
3520 | if (AmbiguousBases.empty()) |
3521 | return; |
3522 | for (MSRTTIClass &Class : Classes) |
3523 | if (AmbiguousBases.count(Class.RD)) |
3524 | Class.Flags |= MSRTTIClass::IsAmbiguous; |
3525 | } |
3526 | |
3527 | llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() { |
3528 | SmallString<256> MangledName; |
3529 | { |
3530 | llvm::raw_svector_ostream Out(MangledName); |
3531 | ABI.getMangleContext().mangleCXXRTTIClassHierarchyDescriptor(RD, Out); |
3532 | } |
3533 | |
3534 | |
3535 | if (auto CHD = Module.getNamedGlobal(MangledName)) |
3536 | return CHD; |
3537 | |
3538 | |
3539 | SmallVector<MSRTTIClass, 8> Classes; |
3540 | serializeClassHierarchy(Classes, RD); |
3541 | Classes.front().initialize(, ); |
3542 | detectAmbiguousBases(Classes); |
3543 | int Flags = 0; |
3544 | for (auto Class : Classes) { |
3545 | if (Class.RD->getNumBases() > 1) |
3546 | Flags |= HasBranchingHierarchy; |
3547 | |
3548 | |
3549 | if (Class.Flags & MSRTTIClass::IsAmbiguous) |
3550 | Flags |= HasAmbiguousBases; |
3551 | } |
3552 | if ((Flags & HasBranchingHierarchy) && RD->getNumVBases() != 0) |
3553 | Flags |= HasVirtualBranchingHierarchy; |
3554 | |
3555 | |
3556 | llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.IntTy, 0), |
3557 | llvm::ConstantInt::get(CGM.IntTy, 0)}; |
3558 | |
3559 | |
3560 | auto Type = ABI.getClassHierarchyDescriptorType(); |
3561 | auto CHD = new llvm::GlobalVariable(Module, Type, , Linkage, |
3562 | , |
3563 | MangledName); |
3564 | if (CHD->isWeakForLinker()) |
3565 | CHD->setComdat(CGM.getModule().getOrInsertComdat(CHD->getName())); |
3566 | |
3567 | auto *Bases = getBaseClassArray(Classes); |
3568 | |
3569 | |
3570 | llvm::Constant *Fields[] = { |
3571 | llvm::ConstantInt::get(CGM.IntTy, 0), |
3572 | llvm::ConstantInt::get(CGM.IntTy, Flags), |
3573 | llvm::ConstantInt::get(CGM.IntTy, Classes.size()), |
3574 | ABI.getImageRelativeConstant(llvm::ConstantExpr::getInBoundsGetElementPtr( |
3575 | Bases->getValueType(), Bases, |
3576 | llvm::ArrayRef<llvm::Value *>(GEPIndices))), |
3577 | }; |
3578 | CHD->setInitializer(llvm::ConstantStruct::get(Type, Fields)); |
3579 | return CHD; |
3580 | } |
3581 | |
3582 | llvm::GlobalVariable * |
3583 | MSRTTIBuilder::getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes) { |
3584 | SmallString<256> MangledName; |
3585 | { |
3586 | llvm::raw_svector_ostream Out(MangledName); |
3587 | ABI.getMangleContext().mangleCXXRTTIBaseClassArray(RD, Out); |
3588 | } |
3589 | |
3590 | |
3591 | |
3592 | |
3593 | |
3594 | |
3595 | llvm::Type *PtrType = ABI.getImageRelativeType( |
3596 | ABI.getBaseClassDescriptorType()->getPointerTo()); |
3597 | auto *ArrType = llvm::ArrayType::get(PtrType, Classes.size() + 1); |
3598 | auto *BCA = |
3599 | new llvm::GlobalVariable(Module, ArrType, |
3600 | , Linkage, |
3601 | , MangledName); |
3602 | if (BCA->isWeakForLinker()) |
3603 | BCA->setComdat(CGM.getModule().getOrInsertComdat(BCA->getName())); |
3604 | |
3605 | |
3606 | SmallVector<llvm::Constant *, 8> BaseClassArrayData; |
3607 | for (MSRTTIClass &Class : Classes) |
3608 | BaseClassArrayData.push_back( |
3609 | ABI.getImageRelativeConstant(getBaseClassDescriptor(Class))); |
3610 | BaseClassArrayData.push_back(llvm::Constant::getNullValue(PtrType)); |
3611 | BCA->setInitializer(llvm::ConstantArray::get(ArrType, BaseClassArrayData)); |
3612 | return BCA; |
3613 | } |
3614 | |
3615 | llvm::GlobalVariable * |
3616 | MSRTTIBuilder::getBaseClassDescriptor(const MSRTTIClass &Class) { |
3617 | |
3618 | |
3619 | uint32_t OffsetInVBTable = 0; |
3620 | int32_t VBPtrOffset = -1; |
3621 | if (Class.VirtualRoot) { |
3622 | auto &VTableContext = CGM.getMicrosoftVTableContext(); |
3623 | OffsetInVBTable = VTableContext.getVBTableIndex(RD, Class.VirtualRoot) * 4; |
3624 | VBPtrOffset = Context.getASTRecordLayout(RD).getVBPtrOffset().getQuantity(); |
3625 | } |
3626 | |
3627 | SmallString<256> MangledName; |
3628 | { |
3629 | llvm::raw_svector_ostream Out(MangledName); |
3630 | ABI.getMangleContext().mangleCXXRTTIBaseClassDescriptor( |
3631 | Class.RD, Class.OffsetInVBase, VBPtrOffset, OffsetInVBTable, |
3632 | Class.Flags, Out); |
3633 | } |
3634 | |
3635 | |
3636 | if (auto BCD = Module.getNamedGlobal(MangledName)) |
3637 | return BCD; |
3638 | |
3639 | |
3640 | auto Type = ABI.getBaseClassDescriptorType(); |
3641 | auto BCD = |
3642 | new llvm::GlobalVariable(Module, Type, , Linkage, |
3643 | , MangledName); |
3644 | if (BCD->isWeakForLinker()) |
3645 | BCD->setComdat(CGM.getModule().getOrInsertComdat(BCD->getName())); |
3646 | |
3647 | |
3648 | llvm::Constant *Fields[] = { |
3649 | ABI.getImageRelativeConstant( |
3650 | ABI.getAddrOfRTTIDescriptor(Context.getTypeDeclType(Class.RD))), |
3651 | llvm::ConstantInt::get(CGM.IntTy, Class.NumBases), |
3652 | llvm::ConstantInt::get(CGM.IntTy, Class.OffsetInVBase), |
3653 | llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset), |
3654 | llvm::ConstantInt::get(CGM.IntTy, OffsetInVBTable), |
3655 | llvm::ConstantInt::get(CGM.IntTy, Class.Flags), |
3656 | ABI.getImageRelativeConstant( |
3657 | MSRTTIBuilder(ABI, Class.RD).getClassHierarchyDescriptor()), |
3658 | }; |
3659 | BCD->setInitializer(llvm::ConstantStruct::get(Type, Fields)); |
3660 | return BCD; |
3661 | } |
3662 | |
3663 | llvm::GlobalVariable * |
3664 | MSRTTIBuilder::getCompleteObjectLocator(const VPtrInfo &Info) { |
3665 | SmallString<256> MangledName; |
3666 | { |
3667 | llvm::raw_svector_ostream Out(MangledName); |
3668 | ABI.getMangleContext().mangleCXXRTTICompleteObjectLocator(RD, Info.MangledPath, Out); |
3669 | } |
3670 | |
3671 | |
3672 | if (auto COL = Module.getNamedGlobal(MangledName)) |
3673 | return COL; |
3674 | |
3675 | |
3676 | int OffsetToTop = Info.FullOffsetInMDC.getQuantity(); |
3677 | int VFPtrOffset = 0; |
3678 | |
3679 | if (const CXXRecordDecl *VBase = Info.getVBaseWithVPtr()) |
3680 | if (Context.getASTRecordLayout(RD) |
3681 | .getVBaseOffsetsMap() |
3682 | .find(VBase) |
3683 | ->second.hasVtorDisp()) |
3684 | VFPtrOffset = Info.NonVirtualOffset.getQuantity() + 4; |
3685 | |
3686 | |
3687 | llvm::StructType *Type = ABI.getCompleteObjectLocatorType(); |
3688 | auto COL = new llvm::GlobalVariable(Module, Type, , Linkage, |
3689 | , MangledName); |
3690 | |
3691 | |
3692 | llvm::Constant *Fields[] = { |
3693 | llvm::ConstantInt::get(CGM.IntTy, ABI.isImageRelative()), |
3694 | llvm::ConstantInt::get(CGM.IntTy, OffsetToTop), |
3695 | llvm::ConstantInt::get(CGM.IntTy, VFPtrOffset), |
3696 | ABI.getImageRelativeConstant( |
3697 | CGM.GetAddrOfRTTIDescriptor(Context.getTypeDeclType(RD))), |
3698 | ABI.getImageRelativeConstant(getClassHierarchyDescriptor()), |
3699 | ABI.getImageRelativeConstant(COL), |
3700 | }; |
3701 | llvm::ArrayRef<llvm::Constant *> FieldsRef(Fields); |
3702 | if (!ABI.isImageRelative()) |
3703 | FieldsRef = FieldsRef.drop_back(); |
3704 | COL->setInitializer(llvm::ConstantStruct::get(Type, FieldsRef)); |
3705 | if (COL->isWeakForLinker()) |
3706 | COL->setComdat(CGM.getModule().getOrInsertComdat(COL->getName())); |
3707 | return COL; |
3708 | } |
3709 | |
3710 | static QualType decomposeTypeForEH(ASTContext &Context, QualType T, |
3711 | bool &IsConst, bool &IsVolatile, |
3712 | bool &IsUnaligned) { |
3713 | T = Context.getExceptionObjectType(T); |
3714 | |
3715 | |
3716 | |
3717 | |
3718 | |
3719 | |
3720 | IsConst = false; |
3721 | IsVolatile = false; |
3722 | IsUnaligned = false; |
3723 | QualType PointeeType = T->getPointeeType(); |
3724 | if (!PointeeType.isNull()) { |
3725 | IsConst = PointeeType.isConstQualified(); |
3726 | IsVolatile = PointeeType.isVolatileQualified(); |
3727 | IsUnaligned = PointeeType.getQualifiers().hasUnaligned(); |
3728 | } |
3729 | |
3730 | |
3731 | |
3732 | if (const auto *MPTy = T->getAs<MemberPointerType>()) |
3733 | T = Context.getMemberPointerType(PointeeType.getUnqualifiedType(), |
3734 | MPTy->getClass()); |
3735 | |
3736 | |
3737 | |
3738 | if (T->isPointerType()) |
3739 | T = Context.getPointerType(PointeeType.getUnqualifiedType()); |
3740 | |
3741 | return T; |
3742 | } |
3743 | |
3744 | CatchTypeInfo |
3745 | MicrosoftCXXABI::getAddrOfCXXCatchHandlerType(QualType Type, |
3746 | QualType CatchHandlerType) { |
3747 | |
3748 | |
3749 | |
3750 | bool IsConst, IsVolatile, IsUnaligned; |
3751 | Type = |
3752 | decomposeTypeForEH(getContext(), Type, IsConst, IsVolatile, IsUnaligned); |
3753 | |
3754 | bool IsReference = CatchHandlerType->isReferenceType(); |
3755 | |
3756 | uint32_t Flags = 0; |
3757 | if (IsConst) |
3758 | Flags |= 1; |
3759 | if (IsVolatile) |
3760 | Flags |= 2; |
3761 | if (IsUnaligned) |
3762 | Flags |= 4; |
3763 | if (IsReference) |
3764 | Flags |= 8; |
3765 | |
3766 | return CatchTypeInfo{getAddrOfRTTIDescriptor(Type)->stripPointerCasts(), |
3767 | Flags}; |
3768 | } |
3769 | |
3770 | |
3771 | |
3772 | |
3773 | |
3774 | llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType Type) { |
3775 | SmallString<256> MangledName; |
3776 | { |
3777 | llvm::raw_svector_ostream Out(MangledName); |
3778 | getMangleContext().mangleCXXRTTI(Type, Out); |
3779 | } |
3780 | |
3781 | |
3782 | if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName)) |
3783 | return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy); |
3784 | |
3785 | |
3786 | |
3787 | |
3788 | |
3789 | SmallString<256> TypeInfoString; |
3790 | { |
3791 | llvm::raw_svector_ostream Out(TypeInfoString); |
3792 | getMangleContext().mangleCXXRTTIName(Type, Out); |
3793 | } |
3794 | |
3795 | |
3796 | llvm::Constant *Fields[] = { |
3797 | getTypeInfoVTable(CGM), |
3798 | llvm::ConstantPointerNull::get(CGM.Int8PtrTy), |
3799 | llvm::ConstantDataArray::getString(CGM.getLLVMContext(), TypeInfoString)}; |
3800 | llvm::StructType *TypeDescriptorType = |
3801 | getTypeDescriptorType(TypeInfoString); |
3802 | auto *Var = new llvm::GlobalVariable( |
3803 | CGM.getModule(), TypeDescriptorType, , |
3804 | getLinkageForRTTI(Type), |
3805 | llvm::ConstantStruct::get(TypeDescriptorType, Fields), |
3806 | MangledName); |
3807 | if (Var->isWeakForLinker()) |
3808 | Var->setComdat(CGM.getModule().getOrInsertComdat(Var->getName())); |
3809 | return llvm::ConstantExpr::getBitCast(Var, CGM.Int8PtrTy); |
3810 | } |
3811 | |
3812 | |
3813 | llvm::GlobalVariable * |
3814 | MicrosoftCXXABI::getMSCompleteObjectLocator(const CXXRecordDecl *RD, |
3815 | const VPtrInfo &Info) { |
3816 | return MSRTTIBuilder(*this, RD).getCompleteObjectLocator(Info); |
3817 | } |
3818 | |
3819 | void MicrosoftCXXABI::emitCXXStructor(GlobalDecl GD) { |
3820 | if (auto *ctor = dyn_cast<CXXConstructorDecl>(GD.getDecl())) { |
3821 | |
3822 | llvm::Function *Fn = |
3823 | CGM.codegenCXXStructor(GD.getWithCtorType(Ctor_Complete)); |
3824 | CGM.maybeSetTrivialComdat(*ctor, *Fn); |
3825 | return; |
3826 | } |
3827 | |
3828 | auto *dtor = cast<CXXDestructorDecl>(GD.getDecl()); |
3829 | |
3830 | |
3831 | |
3832 | |
3833 | if (GD.getDtorType() == Dtor_Complete && |
3834 | dtor->getParent()->getNumVBases() == 0) |
3835 | GD = GD.getWithDtorType(Dtor_Base); |
3836 | |
3837 | |
3838 | |
3839 | |
3840 | |
3841 | if (GD.getDtorType() == Dtor_Base && !CGM.TryEmitBaseDestructorAsAlias(dtor)) |
3842 | return; |
3843 | |
3844 | llvm::Function *Fn = CGM.codegenCXXStructor(GD); |
3845 | if (Fn->isWeakForLinker()) |
3846 | Fn->setComdat(CGM.getModule().getOrInsertComdat(Fn->getName())); |
3847 | } |
3848 | |
3849 | llvm::Function * |
3850 | MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD, |
3851 | CXXCtorType CT) { |
3852 | assert(CT == Ctor_CopyingClosure || CT == Ctor_DefaultClosure); |
3853 | |
3854 | |
3855 | SmallString<256> ThunkName; |
3856 | llvm::raw_svector_ostream Out(ThunkName); |
3857 | getMangleContext().mangleCXXCtor(CD, CT, Out); |
3858 | |
3859 | |
3860 | if (llvm::GlobalValue *GV = CGM.getModule().getNamedValue(ThunkName)) |
3861 | return cast<llvm::Function>(GV); |
3862 | |
3863 | |
3864 | const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeMSCtorClosure(CD, CT); |
3865 | llvm::FunctionType *ThunkTy = CGM.getTypes().GetFunctionType(FnInfo); |
3866 | const CXXRecordDecl *RD = CD->getParent(); |
3867 | QualType RecordTy = getContext().getRecordType(RD); |
3868 | llvm::Function *ThunkFn = llvm::Function::Create( |
3869 | ThunkTy, getLinkageForRTTI(RecordTy), ThunkName.str(), &CGM.getModule()); |
3870 | ThunkFn->setCallingConv(static_cast<llvm::CallingConv::ID>( |
3871 | FnInfo.getEffectiveCallingConvention())); |
3872 | if (ThunkFn->isWeakForLinker()) |
3873 | ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName())); |
3874 | bool IsCopy = CT == Ctor_CopyingClosure; |
3875 | |
3876 | |
3877 | CodeGenFunction CGF(CGM); |
3878 | CGF.CurGD = GlobalDecl(CD, Ctor_Complete); |
3879 | |
3880 | |
3881 | FunctionArgList FunctionArgs; |
3882 | |
3883 | |
3884 | buildThisParam(CGF, FunctionArgs); |
3885 | |
3886 | |
3887 | |
3888 | ImplicitParamDecl SrcParam( |
3889 | getContext(), , SourceLocation(), |
3890 | &getContext().Idents.get("src"), |
3891 | getContext().getLValueReferenceType(RecordTy, |
3892 | ), |
3893 | ImplicitParamDecl::Other); |
3894 | if (IsCopy) |
3895 | FunctionArgs.push_back(&SrcParam); |
3896 | |
3897 | |
3898 | |
3899 | |
3900 | ImplicitParamDecl IsMostDerived(getContext(), , |
3901 | SourceLocation(), |
3902 | &getContext().Idents.get("is_most_derived"), |
3903 | getContext().IntTy, ImplicitParamDecl::Other); |
3904 | |
3905 | if (RD->getNumVBases() > 0) |
3906 | FunctionArgs.push_back(&IsMostDerived); |
3907 | |
3908 | |
3909 | auto NL = ApplyDebugLocation::CreateEmpty(CGF); |
3910 | CGF.StartFunction(GlobalDecl(), FnInfo.getReturnType(), ThunkFn, FnInfo, |
3911 | FunctionArgs, CD->getLocation(), SourceLocation()); |
3912 | |
3913 | auto AL = ApplyDebugLocation::CreateArtificial(CGF); |
3914 | setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF)); |
3915 | llvm::Value *This = getThisValue(CGF); |
3916 | |
3917 | llvm::Value *SrcVal = |
3918 | IsCopy ? CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&SrcParam), "src") |
3919 | : nullptr; |
3920 | |
3921 | CallArgList Args; |
3922 | |
3923 | |
3924 | Args.add(RValue::get(This), CD->getThisType()); |
3925 | |
3926 | |
3927 | if (SrcVal) |
3928 | Args.add(RValue::get(SrcVal), SrcParam.getType()); |
3929 | |
3930 | |
3931 | SmallVector<const Stmt *, 4> ArgVec; |
3932 | ArrayRef<ParmVarDecl *> params = CD->parameters().drop_front(IsCopy ? 1 : 0); |
3933 | for (const ParmVarDecl *PD : params) { |
3934 | (0) . __assert_fail ("PD->hasDefaultArg() && \"ctor closure lacks default args\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 3934, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(PD->hasDefaultArg() && "ctor closure lacks default args"); |
3935 | ArgVec.push_back(PD->getDefaultArg()); |
3936 | } |
3937 | |
3938 | CodeGenFunction::RunCleanupsScope Cleanups(CGF); |
3939 | |
3940 | const auto *FPT = CD->getType()->castAs<FunctionProtoType>(); |
3941 | CGF.EmitCallArgs(Args, FPT, llvm::makeArrayRef(ArgVec), CD, IsCopy ? 1 : 0); |
3942 | |
3943 | |
3944 | AddedStructorArgs = |
3945 | addImplicitConstructorArgs(CGF, CD, Ctor_Complete, |
3946 | , |
3947 | , Args); |
3948 | |
3949 | llvm::Constant *CalleePtr = |
3950 | CGM.getAddrOfCXXStructor(GlobalDecl(CD, Ctor_Complete)); |
3951 | CGCallee Callee = |
3952 | CGCallee::forDirect(CalleePtr, GlobalDecl(CD, Ctor_Complete)); |
3953 | const CGFunctionInfo &CalleeInfo = CGM.getTypes().arrangeCXXConstructorCall( |
3954 | Args, CD, Ctor_Complete, ExtraArgs.Prefix, ExtraArgs.Suffix); |
3955 | CGF.EmitCall(CalleeInfo, Callee, ReturnValueSlot(), Args); |
3956 | |
3957 | Cleanups.ForceCleanup(); |
3958 | |
3959 | |
3960 | |
3961 | CGF.FinishFunction(SourceLocation()); |
3962 | |
3963 | return ThunkFn; |
3964 | } |
3965 | |
3966 | llvm::Constant *MicrosoftCXXABI::getCatchableType(QualType T, |
3967 | uint32_t NVOffset, |
3968 | int32_t VBPtrOffset, |
3969 | uint32_t VBIndex) { |
3970 | isReferenceType()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 3970, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!T->isReferenceType()); |
3971 | |
3972 | CXXRecordDecl *RD = T->getAsCXXRecordDecl(); |
3973 | const CXXConstructorDecl *CD = |
3974 | RD ? CGM.getContext().getCopyConstructorForExceptionObject(RD) : nullptr; |
3975 | CXXCtorType CT = Ctor_Complete; |
3976 | if (CD) |
3977 | if (!hasDefaultCXXMethodCC(getContext(), CD) || CD->getNumParams() != 1) |
3978 | CT = Ctor_CopyingClosure; |
3979 | |
3980 | uint32_t Size = getContext().getTypeSizeInChars(T).getQuantity(); |
3981 | SmallString<256> MangledName; |
3982 | { |
3983 | llvm::raw_svector_ostream Out(MangledName); |
3984 | getMangleContext().mangleCXXCatchableType(T, CD, CT, Size, NVOffset, |
3985 | VBPtrOffset, VBIndex, Out); |
3986 | } |
3987 | if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName)) |
3988 | return getImageRelativeConstant(GV); |
3989 | |
3990 | |
3991 | |
3992 | llvm::Constant *TD = getImageRelativeConstant(getAddrOfRTTIDescriptor(T)); |
3993 | |
3994 | |
3995 | |
3996 | llvm::Constant *CopyCtor; |
3997 | if (CD) { |
3998 | if (CT == Ctor_CopyingClosure) |
3999 | CopyCtor = getAddrOfCXXCtorClosure(CD, Ctor_CopyingClosure); |
4000 | else |
4001 | CopyCtor = CGM.getAddrOfCXXStructor(GlobalDecl(CD, Ctor_Complete)); |
4002 | |
4003 | CopyCtor = llvm::ConstantExpr::getBitCast(CopyCtor, CGM.Int8PtrTy); |
4004 | } else { |
4005 | CopyCtor = llvm::Constant::getNullValue(CGM.Int8PtrTy); |
4006 | } |
4007 | CopyCtor = getImageRelativeConstant(CopyCtor); |
4008 | |
4009 | bool IsScalar = !RD; |
4010 | bool HasVirtualBases = false; |
4011 | bool IsStdBadAlloc = false; |
4012 | QualType PointeeType = T; |
4013 | if (T->isPointerType()) |
4014 | PointeeType = T->getPointeeType(); |
4015 | if (const CXXRecordDecl *RD = PointeeType->getAsCXXRecordDecl()) { |
4016 | HasVirtualBases = RD->getNumVBases() > 0; |
4017 | if (IdentifierInfo *II = RD->getIdentifier()) |
4018 | IsStdBadAlloc = II->isStr("bad_alloc") && RD->isInStdNamespace(); |
4019 | } |
4020 | |
4021 | |
4022 | |
4023 | uint32_t Flags = 0; |
4024 | if (IsScalar) |
4025 | Flags |= 1; |
4026 | if (HasVirtualBases) |
4027 | Flags |= 4; |
4028 | if (IsStdBadAlloc) |
4029 | Flags |= 16; |
4030 | |
4031 | llvm::Constant *Fields[] = { |
4032 | llvm::ConstantInt::get(CGM.IntTy, Flags), |
4033 | TD, |
4034 | llvm::ConstantInt::get(CGM.IntTy, NVOffset), |
4035 | llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset), |
4036 | llvm::ConstantInt::get(CGM.IntTy, VBIndex), |
4037 | llvm::ConstantInt::get(CGM.IntTy, Size), |
4038 | CopyCtor |
4039 | }; |
4040 | llvm::StructType *CTType = getCatchableTypeType(); |
4041 | auto *GV = new llvm::GlobalVariable( |
4042 | CGM.getModule(), CTType, , getLinkageForRTTI(T), |
4043 | llvm::ConstantStruct::get(CTType, Fields), MangledName); |
4044 | GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); |
4045 | GV->setSection(".xdata"); |
4046 | if (GV->isWeakForLinker()) |
4047 | GV->setComdat(CGM.getModule().getOrInsertComdat(GV->getName())); |
4048 | return getImageRelativeConstant(GV); |
4049 | } |
4050 | |
4051 | llvm::GlobalVariable *MicrosoftCXXABI::getCatchableTypeArray(QualType T) { |
4052 | isReferenceType()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/MicrosoftCXXABI.cpp", 4052, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!T->isReferenceType()); |
4053 | |
4054 | |
4055 | llvm::GlobalVariable *&CTA = CatchableTypeArrays[T]; |
4056 | if (CTA) |
4057 | return CTA; |
4058 | |
4059 | |
4060 | |
4061 | |
4062 | llvm::SmallSetVector<llvm::Constant *, 2> CatchableTypes; |
4063 | |
4064 | |
4065 | |
4066 | |
4067 | |
4068 | |
4069 | |
4070 | |
4071 | |
4072 | const CXXRecordDecl *MostDerivedClass = nullptr; |
4073 | bool IsPointer = T->isPointerType(); |
4074 | if (IsPointer) |
4075 | MostDerivedClass = T->getPointeeType()->getAsCXXRecordDecl(); |
4076 | else |
4077 | MostDerivedClass = T->getAsCXXRecordDecl(); |
4078 | |
4079 | |
4080 | if (MostDerivedClass) { |
4081 | const ASTContext &Context = getContext(); |
4082 | const ASTRecordLayout &MostDerivedLayout = |
4083 | Context.getASTRecordLayout(MostDerivedClass); |
4084 | MicrosoftVTableContext &VTableContext = CGM.getMicrosoftVTableContext(); |
4085 | SmallVector<MSRTTIClass, 8> Classes; |
4086 | serializeClassHierarchy(Classes, MostDerivedClass); |
4087 | Classes.front().initialize(, ); |
4088 | detectAmbiguousBases(Classes); |
4089 | for (const MSRTTIClass &Class : Classes) { |
4090 | |
4091 | if (Class.Flags & |
4092 | (MSRTTIClass::IsPrivateOnPath | MSRTTIClass::IsAmbiguous)) |
4093 | continue; |
4094 | |
4095 | uint32_t OffsetInVBTable = 0; |
4096 | int32_t VBPtrOffset = -1; |
4097 | if (Class.VirtualRoot) { |
4098 | OffsetInVBTable = |
4099 | VTableContext.getVBTableIndex(MostDerivedClass, Class.VirtualRoot)*4; |
4100 | VBPtrOffset = MostDerivedLayout.getVBPtrOffset().getQuantity(); |
4101 | } |
4102 | |
4103 | |
4104 | |
4105 | QualType RTTITy = QualType(Class.RD->getTypeForDecl(), 0); |
4106 | if (IsPointer) |
4107 | RTTITy = Context.getPointerType(RTTITy); |
4108 | CatchableTypes.insert(getCatchableType(RTTITy, Class.OffsetInVBase, |
4109 | VBPtrOffset, OffsetInVBTable)); |
4110 | } |
4111 | } |
4112 | |
4113 | |
4114 | |
4115 | |
4116 | |
4117 | CatchableTypes.insert(getCatchableType(T)); |
4118 | |
4119 | |
4120 | |
4121 | |
4122 | |
4123 | |
4124 | |
4125 | |
4126 | |
4127 | |
4128 | |
4129 | if (IsPointer && T->getPointeeType()->isObjectType()) |
4130 | CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy)); |
4131 | |
4132 | |
4133 | |
4134 | |
4135 | |
4136 | |
4137 | |
4138 | |
4139 | |
4140 | if (T->isNullPtrType()) |
4141 | CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy)); |
4142 | |
4143 | uint32_t NumEntries = CatchableTypes.size(); |
4144 | llvm::Type *CTType = |
4145 | getImageRelativeType(getCatchableTypeType()->getPointerTo()); |
4146 | llvm::ArrayType *AT = llvm::ArrayType::get(CTType, NumEntries); |
4147 | llvm::StructType *CTAType = getCatchableTypeArrayType(NumEntries); |
4148 | llvm::Constant *Fields[] = { |
4149 | llvm::ConstantInt::get(CGM.IntTy, NumEntries), |
4150 | llvm::ConstantArray::get( |
4151 | AT, llvm::makeArrayRef(CatchableTypes.begin(), |
4152 | CatchableTypes.end())) |
4153 | }; |
4154 | SmallString<256> MangledName; |
4155 | { |
4156 | llvm::raw_svector_ostream Out(MangledName); |
4157 | getMangleContext().mangleCXXCatchableTypeArray(T, NumEntries, Out); |
4158 | } |
4159 | CTA = new llvm::GlobalVariable( |
4160 | CGM.getModule(), CTAType, , getLinkageForRTTI(T), |
4161 | llvm::ConstantStruct::get(CTAType, Fields), MangledName); |
4162 | CTA->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); |
4163 | CTA->setSection(".xdata"); |
4164 | if (CTA->isWeakForLinker()) |
4165 | CTA->setComdat(CGM.getModule().getOrInsertComdat(CTA->getName())); |
4166 | return CTA; |
4167 | } |
4168 | |
4169 | llvm::GlobalVariable *MicrosoftCXXABI::getThrowInfo(QualType T) { |
4170 | bool IsConst, IsVolatile, IsUnaligned; |
4171 | T = decomposeTypeForEH(getContext(), T, IsConst, IsVolatile, IsUnaligned); |
4172 | |
4173 | |
4174 | |
4175 | llvm::GlobalVariable *CTA = getCatchableTypeArray(T); |
4176 | |
4177 | |
4178 | |
4179 | |
4180 | uint32_t NumEntries = |
4181 | cast<llvm::ConstantInt>(CTA->getInitializer()->getAggregateElement(0U)) |
4182 | ->getLimitedValue(); |
4183 | |
4184 | SmallString<256> MangledName; |
4185 | { |
4186 | llvm::raw_svector_ostream Out(MangledName); |
4187 | getMangleContext().mangleCXXThrowInfo(T, IsConst, IsVolatile, IsUnaligned, |
4188 | NumEntries, Out); |
4189 | } |
4190 | |
4191 | |
4192 | |
4193 | if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName)) |
4194 | return GV; |
4195 | |
4196 | |
4197 | |
4198 | |
4199 | uint32_t Flags = 0; |
4200 | if (IsConst) |
4201 | Flags |= 1; |
4202 | if (IsVolatile) |
4203 | Flags |= 2; |
4204 | if (IsUnaligned) |
4205 | Flags |= 4; |
4206 | |
4207 | |
4208 | |
4209 | llvm::Constant *CleanupFn = llvm::Constant::getNullValue(CGM.Int8PtrTy); |
4210 | if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) |
4211 | if (CXXDestructorDecl *DtorD = RD->getDestructor()) |
4212 | if (!DtorD->isTrivial()) |
4213 | CleanupFn = llvm::ConstantExpr::getBitCast( |
4214 | CGM.getAddrOfCXXStructor(GlobalDecl(DtorD, Dtor_Complete)), |
4215 | CGM.Int8PtrTy); |
4216 | |
4217 | llvm::Constant *ForwardCompat = |
4218 | getImageRelativeConstant(llvm::Constant::getNullValue(CGM.Int8PtrTy)); |
4219 | llvm::Constant *PointerToCatchableTypes = getImageRelativeConstant( |
4220 | llvm::ConstantExpr::getBitCast(CTA, CGM.Int8PtrTy)); |
4221 | llvm::StructType *TIType = getThrowInfoType(); |
4222 | llvm::Constant *Fields[] = { |
4223 | llvm::ConstantInt::get(CGM.IntTy, Flags), |
4224 | getImageRelativeConstant(CleanupFn), |
4225 | ForwardCompat, |
4226 | PointerToCatchableTypes |
4227 | }; |
4228 | auto *GV = new llvm::GlobalVariable( |
4229 | CGM.getModule(), TIType, , getLinkageForRTTI(T), |
4230 | llvm::ConstantStruct::get(TIType, Fields), StringRef(MangledName)); |
4231 | GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); |
4232 | GV->setSection(".xdata"); |
4233 | if (GV->isWeakForLinker()) |
4234 | GV->setComdat(CGM.getModule().getOrInsertComdat(GV->getName())); |
4235 | return GV; |
4236 | } |
4237 | |
4238 | void MicrosoftCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) { |
4239 | const Expr *SubExpr = E->getSubExpr(); |
4240 | QualType ThrowType = SubExpr->getType(); |
4241 | |
4242 | |
4243 | Address AI = CGF.CreateMemTemp(ThrowType); |
4244 | CGF.EmitAnyExprToMem(SubExpr, AI, ThrowType.getQualifiers(), |
4245 | ); |
4246 | |
4247 | |
4248 | |
4249 | llvm::GlobalVariable *TI = getThrowInfo(ThrowType); |
4250 | |
4251 | |
4252 | llvm::Value *Args[] = { |
4253 | CGF.Builder.CreateBitCast(AI.getPointer(), CGM.Int8PtrTy), |
4254 | TI |
4255 | }; |
4256 | CGF.EmitNoreturnRuntimeCallOrInvoke(getThrowFn(), Args); |
4257 | } |
4258 | |
4259 | std::pair<llvm::Value *, const CXXRecordDecl *> |
4260 | MicrosoftCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This, |
4261 | const CXXRecordDecl *RD) { |
4262 | std::tie(This, std::ignore, RD) = |
4263 | performBaseAdjustment(CGF, This, QualType(RD->getTypeForDecl(), 0)); |
4264 | return {CGF.GetVTablePtr(This, CGM.Int8PtrTy, RD), RD}; |
4265 | } |
4266 | |