| Warren Hunt | 5c2b4ea | 2014-05-23 16:07:43 +0000 | [diff] [blame] | 1 | //===--- 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 | |
| 21 | using namespace clang; |
| 22 | using 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 Hunt | 51ec916 | 2014-05-23 16:26:32 +0000 | [diff] [blame] | 55 | static llvm::StructType *getClassHierarchyDescriptorType(CodeGenModule &CGM); |
| Warren Hunt | 5c2b4ea | 2014-05-23 16:07:43 +0000 | [diff] [blame] | 56 | |
| 57 | static 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 | |
| 70 | static 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 | |
| 85 | static 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 | |
| 100 | static 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 | |
| 113 | static 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 | |
| 123 | namespace { |
| 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. |
| 131 | struct 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. |
| 153 | uint32_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. |
| 186 | struct 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. |
| 218 | static 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. |
| 226 | static void |
| 227 | detectAmbiguousBases(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 | |
| 248 | llvm::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 | |
| 297 | llvm::GlobalVariable * |
| 298 | MSRTTIBuilder::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 | |
| 324 | llvm::GlobalVariable * |
| 325 | MSRTTIBuilder::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 | |
| 366 | llvm::GlobalVariable * |
| 367 | MSRTTIBuilder::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. |
| 410 | llvm::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 | |
| 443 | llvm::GlobalVariable * |
| 444 | CodeGenModule::getMSCompleteObjectLocator(const CXXRecordDecl *RD, |
| 445 | const VPtrInfo *Info) { |
| 446 | return MSRTTIBuilder(*this, RD).getCompleteObjectLocator(Info); |
| 447 | } |