blob: 0eb8100af56f070eeb9afab04f6917d946cce4b0 [file] [log] [blame]
Warren Hunt5c2b4ea2014-05-23 16:07:43 +00001//===--- CGCXXRTTI.cpp - Emit LLVM Code for C++ RTTI descriptors ----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This contains code dealing with C++ code generation of RTTI descriptors.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CodeGenModule.h"
15#include "CGCXXABI.h"
16#include "CGObjCRuntime.h"
17#include "clang/AST/RecordLayout.h"
18#include "clang/AST/Type.h"
19#include "clang/Frontend/CodeGenOptions.h"
20
21using namespace clang;
22using namespace CodeGen;
23
24// MS RTTI Overview:
25// The run time type information emitted by cl.exe contains 5 distinct types of
26// structures. Many of them reference each other.
27//
28// TypeInfo: Static classes that are returned by typeid.
29//
30// CompleteObjectLocator: Referenced by vftables. They contain information
31// required for dynamic casting, including OffsetFromTop. They also contain
32// a reference to the TypeInfo for the type and a reference to the
33// CompleteHierarchyDescriptor for the type.
34//
35// ClassHieararchyDescriptor: Contains information about a class hierarchy.
36// Used during dynamic_cast to walk a class hierarchy. References a base
37// class array and the size of said array.
38//
39// BaseClassArray: Contains a list of classes in a hierarchy. BaseClassArray is
40// somewhat of a misnomer because the most derived class is also in the list
41// as well as multiple copies of virtual bases (if they occur multiple times
42// in the hiearchy.) The BaseClassArray contains one BaseClassDescriptor for
43// every path in the hierarchy, in pre-order depth first order. Note, we do
44// not declare a specific llvm type for BaseClassArray, it's merely an array
45// of BaseClassDescriptor pointers.
46//
47// BaseClassDescriptor: Contains information about a class in a class hierarchy.
48// BaseClassDescriptor is also somewhat of a misnomer for the same reason that
49// BaseClassArray is. It contains information about a class within a
50// hierarchy such as: is this base is ambiguous and what is its offset in the
51// vbtable. The names of the BaseClassDescriptors have all of their fields
52// mangled into them so they can be aggressively deduplicated by the linker.
53
54// 5 routines for constructing the llvm types for MS RTTI structs.
Warren Hunt51ec9162014-05-23 16:26:32 +000055static llvm::StructType *getClassHierarchyDescriptorType(CodeGenModule &CGM);
Warren Hunt5c2b4ea2014-05-23 16:07:43 +000056
57static llvm::StructType *getTypeDescriptorType(CodeGenModule &CGM,
58 StringRef TypeInfoString) {
59 llvm::SmallString<32> TDTypeName("MSRTTITypeDescriptor");
60 TDTypeName += TypeInfoString.size();
61 if (auto Type = CGM.getModule().getTypeByName(TDTypeName))
62 return Type;
63 llvm::Type *FieldTypes[] = {
64 CGM.Int8PtrPtrTy,
65 CGM.Int8PtrTy,
66 llvm::ArrayType::get(CGM.Int8Ty, TypeInfoString.size() + 1)};
67 return llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, TDTypeName);
68}
69
70static llvm::StructType *getBaseClassDescriptorType(CodeGenModule &CGM) {
71 static const char Name[] = "MSRTTIBaseClassDescriptor";
72 if (auto Type = CGM.getModule().getTypeByName(Name))
73 return Type;
74 llvm::Type *FieldTypes[] = {
75 CGM.Int8PtrTy,
76 CGM.IntTy,
77 CGM.IntTy,
78 CGM.IntTy,
79 CGM.IntTy,
80 CGM.IntTy,
81 getClassHierarchyDescriptorType(CGM)->getPointerTo()};
82 return llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, Name);
83}
84
85static llvm::StructType *getClassHierarchyDescriptorType(CodeGenModule &CGM) {
86 static const char Name[] = "MSRTTIClassHierarchyDescriptor";
87 if (auto Type = CGM.getModule().getTypeByName(Name))
88 return Type;
89 // Forward declare RTTIClassHierarchyDescriptor to break a cycle.
90 llvm::StructType *Type = llvm::StructType::create(CGM.getLLVMContext(), Name);
91 llvm::Type *FieldTypes[] = {
92 CGM.IntTy,
93 CGM.IntTy,
94 CGM.IntTy,
95 getBaseClassDescriptorType(CGM)->getPointerTo()->getPointerTo()};
96 Type->setBody(FieldTypes);
97 return Type;
98}
99
100static llvm::StructType *getCompleteObjectLocatorType(CodeGenModule &CGM) {
101 static const char Name[] = "MSRTTICompleteObjectLocator";
102 if (auto Type = CGM.getModule().getTypeByName(Name))
103 return Type;
104 llvm::Type *FieldTypes[] = {
105 CGM.IntTy,
106 CGM.IntTy,
107 CGM.IntTy,
108 CGM.Int8PtrTy,
109 getClassHierarchyDescriptorType(CGM)->getPointerTo() };
110 return llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, Name);
111}
112
113static llvm::GlobalVariable *getTypeInfoVTable(CodeGenModule &CGM) {
114 StringRef MangledName("\01??_7type_info@@6B@");
115 if (auto VTable = CGM.getModule().getNamedGlobal(MangledName))
116 return VTable;
117 return new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy,
118 /*Constant=*/true,
119 llvm::GlobalVariable::ExternalLinkage,
120 /*Initializer=*/0, MangledName);
121}
122
123namespace {
124
125/// \brief A Helper struct that stores information about a class in a class
126/// hierarchy. The information stored in these structs struct is used during
127/// the generation of ClassHierarchyDescriptors and BaseClassDescriptors.
128// During RTTI creation, MSRTTIClasses are stored in a contiguous array with
129// implicit depth first pre-order tree connectivity. getFirstChild and
130// getNextSibling allow us to walk the tree efficiently.
131struct MSRTTIClass {
132 enum {
133 IsPrivateOnPath = 1 | 8,
134 IsAmbiguous = 2,
135 IsPrivate = 4,
136 IsVirtual = 16,
137 HasHierarchyDescriptor = 64
138 };
139 MSRTTIClass(const CXXRecordDecl *RD) : RD(RD) {}
140 uint32_t initialize(const MSRTTIClass *Parent,
141 const CXXBaseSpecifier *Specifier);
142
143 MSRTTIClass *getFirstChild() { return this + 1; }
144 static MSRTTIClass *getNextChild(MSRTTIClass *Child) {
145 return Child + 1 + Child->NumBases;
146 }
147
148 const CXXRecordDecl *RD, *VirtualRoot;
149 uint32_t Flags, NumBases, OffsetInVBase;
150};
151
152/// \brief Recursively initialize the base class array.
153uint32_t MSRTTIClass::initialize(const MSRTTIClass *Parent,
154 const CXXBaseSpecifier *Specifier) {
155 Flags = HasHierarchyDescriptor;
156 if (!Parent) {
157 VirtualRoot = 0;
158 OffsetInVBase = 0;
159 } else {
160 if (Specifier->getAccessSpecifier() != AS_public)
161 Flags |= IsPrivate | IsPrivateOnPath;
162 if (Specifier->isVirtual()) {
163 Flags |= IsVirtual;
164 VirtualRoot = RD;
165 OffsetInVBase = 0;
166 } else {
167 if (Parent->Flags & IsPrivateOnPath)
168 Flags |= IsPrivateOnPath;
169 VirtualRoot = Parent->VirtualRoot;
170 OffsetInVBase = Parent->OffsetInVBase + RD->getASTContext()
171 .getASTRecordLayout(Parent->RD).getBaseClassOffset(RD).getQuantity();
172 }
173 }
174 NumBases = 0;
175 MSRTTIClass *Child = getFirstChild();
176 for (const CXXBaseSpecifier &Base : RD->bases()) {
177 NumBases += Child->initialize(this, &Base) + 1;
178 Child = getNextChild(Child);
179 }
180 return NumBases;
181}
182
183/// \brief An ephemeral helper class for building MS RTTI types. It caches some
184/// calls to the module and information about the most derived class in a
185/// hierarchy.
186struct MSRTTIBuilder {
187 enum {
188 HasBranchingHierarchy = 1,
189 HasVirtualBranchingHierarchy = 2,
190 HasAmbiguousBases = 4
191 };
192
193 MSRTTIBuilder(CodeGenModule &CGM, const CXXRecordDecl *RD)
194 : CGM(CGM), Context(CGM.getContext()), VMContext(CGM.getLLVMContext()),
195 Module(CGM.getModule()), RD(RD), Linkage(CGM.getVTableLinkage(RD)),
196 Mangler(
197 cast<MicrosoftMangleContext>(CGM.getCXXABI().getMangleContext())) {}
198
199 llvm::GlobalVariable *getBaseClassDescriptor(const MSRTTIClass &Classes);
200 llvm::GlobalVariable *
201 getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes);
202 llvm::GlobalVariable *getClassHierarchyDescriptor();
203 llvm::GlobalVariable *getCompleteObjectLocator(const VPtrInfo *Info);
204
205 CodeGenModule &CGM;
206 ASTContext &Context;
207 llvm::LLVMContext &VMContext;
208 llvm::Module &Module;
209 const CXXRecordDecl *RD;
210 llvm::GlobalVariable::LinkageTypes Linkage;
211 MicrosoftMangleContext &Mangler;
212};
213
214} // namespace
215
216/// \brief Recursively serializes a class hierarchy in pre-order depth first
217/// order.
218static void serializeClassHierarchy(SmallVectorImpl<MSRTTIClass> &Classes,
219 const CXXRecordDecl *RD) {
220 Classes.push_back(MSRTTIClass(RD));
221 for (const CXXBaseSpecifier &Base : RD->bases())
222 serializeClassHierarchy(Classes, Base.getType()->getAsCXXRecordDecl());
223}
224
225/// \brief Find ambiguity among base classes.
226static void
227detectAmbiguousBases(SmallVectorImpl<MSRTTIClass> &Classes) {
228 llvm::SmallPtrSet<const CXXRecordDecl *, 8> VirtualBases;
229 llvm::SmallPtrSet<const CXXRecordDecl *, 8> UniqueBases;
230 llvm::SmallPtrSet<const CXXRecordDecl *, 8> AmbiguousBases;
231 for (MSRTTIClass *Class = &Classes.front(); Class <= &Classes.back();) {
232 if ((Class->Flags & MSRTTIClass::IsVirtual) &&
233 !VirtualBases.insert(Class->RD)) {
234 Class = MSRTTIClass::getNextChild(Class);
235 continue;
236 }
237 if (!UniqueBases.insert(Class->RD))
238 AmbiguousBases.insert(Class->RD);
239 Class++;
240 }
241 if (AmbiguousBases.empty())
242 return;
243 for (MSRTTIClass &Class : Classes)
244 if (AmbiguousBases.count(Class.RD))
245 Class.Flags |= MSRTTIClass::IsAmbiguous;
246}
247
248llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() {
249 SmallString<256> MangledName;
250 {
251 llvm::raw_svector_ostream Out(MangledName);
252 Mangler.mangleCXXRTTIClassHierarchyDescriptor(RD, Out);
253 }
254
255 // Check to see if we've already declared this ClassHierarchyDescriptor.
256 if (auto CHD = Module.getNamedGlobal(MangledName))
257 return CHD;
258
259 // Serialize the class hierarchy and initalize the CHD Fields.
260 SmallVector<MSRTTIClass, 8> Classes;
261 serializeClassHierarchy(Classes, RD);
262 Classes.front().initialize(/*Parent=*/0, /*Specifier=*/0);
263 detectAmbiguousBases(Classes);
264 int Flags = 0;
265 for (auto Class : Classes) {
266 if (Class.RD->getNumBases() > 1)
267 Flags |= HasBranchingHierarchy;
268 // Note: cl.exe does not calculate "HasAmbiguousBases" correctly. We
269 // believe the field isn't actually used.
270 if (Class.Flags & MSRTTIClass::IsAmbiguous)
271 Flags |= HasAmbiguousBases;
272 }
273 if ((Flags & HasBranchingHierarchy) && RD->getNumVBases() != 0)
274 Flags |= HasVirtualBranchingHierarchy;
275 // These gep indices are used to get the address of the first element of the
276 // base class array.
277 llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.IntTy, 0),
278 llvm::ConstantInt::get(CGM.IntTy, 0)};
279
280 // Forward declare the class hierarchy descriptor
281 auto Type = getClassHierarchyDescriptorType(CGM);
282 auto CHD = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
283 /*Initializer=*/0, MangledName.c_str());
284
285 // Initialize the base class ClassHierarchyDescriptor.
286 llvm::Constant *Fields[] = {
287 llvm::ConstantInt::get(CGM.IntTy, 0), // Unknown
288 llvm::ConstantInt::get(CGM.IntTy, Flags),
289 llvm::ConstantInt::get(CGM.IntTy, Classes.size()),
290 llvm::ConstantExpr::getInBoundsGetElementPtr(
291 getBaseClassArray(Classes),
292 llvm::ArrayRef<llvm::Value *>(GEPIndices))};
293 CHD->setInitializer(llvm::ConstantStruct::get(Type, Fields));
294 return CHD;
295}
296
297llvm::GlobalVariable *
298MSRTTIBuilder::getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes) {
299 SmallString<256> MangledName;
300 {
301 llvm::raw_svector_ostream Out(MangledName);
302 Mangler.mangleCXXRTTIBaseClassArray(RD, Out);
303 }
304
305 // Foward declare the base class array.
306 // cl.exe pads the base class array with 1 (in 32 bit mode) or 4 (in 64 bit
307 // mode) bytes of padding. We provide a pointer sized amount of padding by
308 // adding +1 to Classes.size(). The sections have pointer alignment and are
309 // marked pick-any so it shouldn't matter.
310 auto PtrType = getBaseClassDescriptorType(CGM)->getPointerTo();
311 auto ArrayType = llvm::ArrayType::get(PtrType, Classes.size() + 1);
312 auto BCA = new llvm::GlobalVariable(Module, ArrayType,
313 /*Constant=*/true, Linkage, /*Initializer=*/0, MangledName.c_str());
314
315 // Initialize the BaseClassArray.
316 SmallVector<llvm::Constant *, 8> BaseClassArrayData;
317 for (MSRTTIClass &Class : Classes)
318 BaseClassArrayData.push_back(getBaseClassDescriptor(Class));
319 BaseClassArrayData.push_back(llvm::ConstantPointerNull::get(PtrType));
320 BCA->setInitializer(llvm::ConstantArray::get(ArrayType, BaseClassArrayData));
321 return BCA;
322}
323
324llvm::GlobalVariable *
325MSRTTIBuilder::getBaseClassDescriptor(const MSRTTIClass &Class) {
326 // Compute the fields for the BaseClassDescriptor. They are computed up front
327 // because they are mangled into the name of the object.
328 uint32_t OffsetInVBTable = 0;
329 int32_t VBPtrOffset = -1;
330 if (Class.VirtualRoot) {
331 auto &VTableContext = CGM.getMicrosoftVTableContext();
332 OffsetInVBTable = VTableContext.getVBTableIndex(RD, Class.VirtualRoot) * 4;
333 VBPtrOffset = Context.getASTRecordLayout(RD).getVBPtrOffset().getQuantity();
334 }
335
336 SmallString<256> MangledName;
337 {
338 llvm::raw_svector_ostream Out(MangledName);
339 Mangler.mangleCXXRTTIBaseClassDescriptor(Class.RD, Class.OffsetInVBase,
340 VBPtrOffset, OffsetInVBTable,
341 Class.Flags, Out);
342 }
343
344 // Check to see if we've already declared declared this object.
345 if (auto BCD = Module.getNamedGlobal(MangledName))
346 return BCD;
347
348 // Forward declare the base class descriptor.
349 auto Type = getBaseClassDescriptorType(CGM);
350 auto BCD = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
351 /*Initializer=*/0, MangledName.c_str());
352
353 // Initialize the BaseClassDescriptor.
354 llvm::Constant *Fields[] = {
355 CGM.getMSTypeDescriptor(Context.getTypeDeclType(Class.RD)),
356 llvm::ConstantInt::get(CGM.IntTy, Class.NumBases),
357 llvm::ConstantInt::get(CGM.IntTy, Class.OffsetInVBase),
358 llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset),
359 llvm::ConstantInt::get(CGM.IntTy, OffsetInVBTable),
360 llvm::ConstantInt::get(CGM.IntTy, Class.Flags),
361 MSRTTIBuilder(CGM, Class.RD).getClassHierarchyDescriptor()};
362 BCD->setInitializer(llvm::ConstantStruct::get(Type, Fields));
363 return BCD;
364}
365
366llvm::GlobalVariable *
367MSRTTIBuilder::getCompleteObjectLocator(const VPtrInfo *Info) {
368 SmallString<256> MangledName;
369 {
370 llvm::raw_svector_ostream Out(MangledName);
371 Mangler.mangleCXXRTTICompleteObjectLocator(RD, Info->MangledPath, Out);
372 }
373
374 // Check to see if we've already computed this complete object locator.
375 if (auto COL = Module.getNamedGlobal(MangledName))
376 return COL;
377
378 // Compute the fields of the complete object locator.
379 int OffsetToTop = Info->FullOffsetInMDC.getQuantity();
380 int VFPtrOffset = 0;
381 // The offset includes the vtordisp if one exists.
382 if (const CXXRecordDecl *VBase = Info->getVBaseWithVPtr())
383 if (Context.getASTRecordLayout(RD)
384 .getVBaseOffsetsMap()
385 .find(VBase)
386 ->second.hasVtorDisp())
387 VFPtrOffset = Info->NonVirtualOffset.getQuantity() + 4;
388
389 // Forward declare the complete object locator.
390 llvm::StructType *Type = getCompleteObjectLocatorType(CGM);
391 auto COL = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
392 /*Initializer=*/0, MangledName.c_str());
393
394 // Initialize the CompleteObjectLocator.
395 llvm::Constant *Fields[] = {
396 llvm::ConstantInt::get(CGM.IntTy, 0), // IsDeltaEncoded
397 llvm::ConstantInt::get(CGM.IntTy, OffsetToTop),
398 llvm::ConstantInt::get(CGM.IntTy, VFPtrOffset),
399 CGM.getMSTypeDescriptor(Context.getTypeDeclType(RD)),
400 getClassHierarchyDescriptor()};
401 COL->setInitializer(llvm::ConstantStruct::get(Type, Fields));
402 return COL;
403}
404
405
406/// \brief Gets a TypeDescriptor. Returns a llvm::Constant * rather than a
407/// llvm::GlobalVariable * because different type descriptors have different
408/// types, and need to be abstracted. They are abstracting by casting the
409/// address to an Int8PtrTy.
410llvm::Constant *CodeGenModule::getMSTypeDescriptor(QualType Type) {
411 auto &Mangler(cast<MicrosoftMangleContext>(getCXXABI().getMangleContext()));
412 SmallString<256> MangledName, TypeInfoString;
413 {
414 llvm::raw_svector_ostream Out(MangledName);
415 Mangler.mangleCXXRTTI(Type, Out);
416 }
417
418 // Check to see if we've already declared this TypeDescriptor.
419 if (auto TypeDescriptor = getModule().getNamedGlobal(MangledName))
420 return llvm::ConstantExpr::getBitCast(TypeDescriptor, Int8PtrTy);
421
422 // Compute the fields for the TypeDescriptor.
423 {
424 llvm::raw_svector_ostream Out(TypeInfoString);
425 Mangler.mangleCXXRTTIName(Type, Out);
426 }
427
428 // Declare and initialize the TypeDescriptor.
429 llvm::Constant *Fields[] = {
430 getTypeInfoVTable(*this), // VFPtr
431 llvm::ConstantPointerNull::get(Int8PtrTy), // Runtime data
432 llvm::ConstantDataArray::getString(VMContext, TypeInfoString)};
433 auto TypeDescriptorType = getTypeDescriptorType(*this, TypeInfoString);
434 return llvm::ConstantExpr::getBitCast(
435 new llvm::GlobalVariable(
436 getModule(), TypeDescriptorType, /*Constant=*/false,
437 getTypeInfoLinkage(Type),
438 llvm::ConstantStruct::get(TypeDescriptorType, Fields),
439 MangledName.c_str()),
440 Int8PtrTy);
441}
442
443llvm::GlobalVariable *
444CodeGenModule::getMSCompleteObjectLocator(const CXXRecordDecl *RD,
445 const VPtrInfo *Info) {
446 return MSRTTIBuilder(*this, RD).getCompleteObjectLocator(Info);
447}