blob: a5d6a7ff5e3d4a2bf7ff99becef35022b9ac053e [file] [log] [blame]
Mike Stumpde050572009-12-02 18:57:08 +00001//===--- CGCXXRTTI.cpp - Emit LLVM Code for C++ RTTI descriptors ----------===//
Anders Carlsson656e4c12009-10-10 20:49:04 +00002//
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
Mike Stumpae9b2be2009-11-17 23:45:57 +000014#include "clang/AST/Type.h"
Mike Stumpcbcd4e52009-11-14 23:32:21 +000015#include "clang/AST/RecordLayout.h"
Mike Stump61c38012009-11-17 21:44:24 +000016#include "CodeGenModule.h"
Anders Carlsson656e4c12009-10-10 20:49:04 +000017using namespace clang;
18using namespace CodeGen;
19
Mike Stump92f2fe22009-12-02 19:07:44 +000020namespace {
Mike Stumpde050572009-12-02 18:57:08 +000021class RTTIBuilder {
Mike Stump2b1bf312009-11-14 14:25:18 +000022 CodeGenModule &CGM; // Per-module state.
23 llvm::LLVMContext &VMContext;
24 const llvm::Type *Int8PtrTy;
Mike Stumpa8285a82009-11-15 03:28:10 +000025 llvm::SmallSet<const CXXRecordDecl *, 16> SeenVBase;
26 llvm::SmallSet<const CXXRecordDecl *, 32> SeenBase;
Anders Carlsson44636d12009-12-11 16:41:51 +000027
Anders Carlsson23440772009-12-17 05:06:03 +000028 std::vector<llvm::Constant *> Info;
29
Anders Carlssond6baec82009-12-11 01:27:37 +000030 // Type info flags.
31 enum {
32 /// TI_Const - Type has const qualifier.
33 TI_Const = 0x1,
34
35 /// TI_Volatile - Type has volatile qualifier.
36 TI_Volatile = 0x2,
37
38 /// TI_Restrict - Type has restrict qualifier.
39 TI_Restrict = 0x4,
40
41 /// TI_Incomplete - Type is incomplete.
42 TI_Incomplete = 0x8,
43
44 /// TI_ContainingClassIncomplete - Containing class is incomplete.
45 /// (in pointer to member).
46 TI_ContainingClassIncomplete = 0x10
47 };
48
Anders Carlsson1d7088d2009-12-17 07:09:17 +000049 /// GetAddrOfExternalRTTIDescriptor - Returns the constant for the RTTI
50 /// descriptor of the given type.
51 llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty);
52
Mike Stump2b1bf312009-11-14 14:25:18 +000053public:
Mike Stumpde050572009-12-02 18:57:08 +000054 RTTIBuilder(CodeGenModule &cgm)
Mike Stump2b1bf312009-11-14 14:25:18 +000055 : CGM(cgm), VMContext(cgm.getModule().getContext()),
56 Int8PtrTy(llvm::Type::getInt8PtrTy(VMContext)) { }
57
Mike Stumpcbcd4e52009-11-14 23:32:21 +000058 /// BuildVtableRef - Build a reference to a vtable.
59 llvm::Constant *BuildVtableRef(const char *Name) {
60 // Build a descriptor for Name
Mike Stumpc7a05bd2009-11-14 15:55:18 +000061 llvm::Constant *GV = CGM.getModule().getGlobalVariable(Name);
62 if (GV)
63 GV = llvm::ConstantExpr::getBitCast(GV,
64 llvm::PointerType::get(Int8PtrTy, 0));
65 else {
66 llvm::GlobalVariable::LinkageTypes linktype;
67 linktype = llvm::GlobalValue::ExternalLinkage;
68 GV = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy,
69 true, linktype, 0, Name);
Mike Stumpcbcd4e52009-11-14 23:32:21 +000070 }
Mike Stumpc7a05bd2009-11-14 15:55:18 +000071 llvm::Constant *C;
72 C = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 2);
73 C = llvm::ConstantExpr::getInBoundsGetElementPtr(GV, &C, 1);
74 return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
75 }
Mike Stumpcbcd4e52009-11-14 23:32:21 +000076
Anders Carlsson31b7f522009-12-11 02:46:30 +000077 // FIXME: This should be removed, and clients should pass in the linkage
78 // directly instead.
79 static inline llvm::GlobalVariable::LinkageTypes
80 GetLinkageFromExternFlag(bool Extern) {
81 if (Extern)
82 return llvm::GlobalValue::WeakODRLinkage;
83
84 return llvm::GlobalValue::InternalLinkage;
85 }
86
87 // FIXME: This should be removed, and clients should pass in the linkage
88 // directly instead.
Mike Stump58588942009-11-19 01:08:19 +000089 llvm::Constant *BuildName(QualType Ty, bool Hidden, bool Extern) {
Anders Carlsson31b7f522009-12-11 02:46:30 +000090 return BuildName(Ty, Hidden, GetLinkageFromExternFlag(Extern));
91 }
92
93 llvm::Constant *BuildName(QualType Ty, bool Hidden,
94 llvm::GlobalVariable::LinkageTypes Linkage) {
Mike Stump2b1bf312009-11-14 14:25:18 +000095 llvm::SmallString<256> OutName;
Mike Stumpde050572009-12-02 18:57:08 +000096 CGM.getMangleContext().mangleCXXRTTIName(Ty, OutName);
Daniel Dunbar94fd26d2009-11-21 09:06:22 +000097 llvm::StringRef Name = OutName.str();
Mike Stumpcbcd4e52009-11-14 23:32:21 +000098
Anders Carlsson31b7f522009-12-11 02:46:30 +000099 llvm::GlobalVariable *OGV = CGM.getModule().getGlobalVariable(Name);
100 if (OGV && !OGV->isDeclaration())
101 return llvm::ConstantExpr::getBitCast(OGV, Int8PtrTy);
Mike Stump58588942009-11-19 01:08:19 +0000102
Anders Carlsson31b7f522009-12-11 02:46:30 +0000103 llvm::Constant *C = llvm::ConstantArray::get(VMContext, Name.substr(4));
Mike Stump2b1bf312009-11-14 14:25:18 +0000104
Anders Carlsson31b7f522009-12-11 02:46:30 +0000105 llvm::GlobalVariable *GV =
106 new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, Linkage,
107 C, Name);
Mike Stump58588942009-11-19 01:08:19 +0000108 if (OGV) {
109 GV->takeName(OGV);
110 llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV,
111 OGV->getType());
112 OGV->replaceAllUsesWith(NewPtr);
113 OGV->eraseFromParent();
114 }
Mike Stump582b0372009-11-18 03:46:51 +0000115 if (Hidden)
116 GV->setVisibility(llvm::GlobalVariable::HiddenVisibility);
117 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
Daniel Dunbar7177dee2009-12-19 17:50:07 +0000118 }
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000119
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000120 /// - BuildFlags - Build a psABI __flags value for __vmi_class_type_info.
121 llvm::Constant *BuildFlags(int f) {
122 return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), f);
123 }
124
125 /// BuildBaseCount - Build a psABI __base_count value for
126 /// __vmi_class_type_info.
127 llvm::Constant *BuildBaseCount(unsigned c) {
128 return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), c);
129 }
130
Mike Stumpa8285a82009-11-15 03:28:10 +0000131 /// CalculateFlags - Calculate the flags for the __vmi_class_type_info
132 /// datastructure. 1 for non-diamond repeated inheritance, 2 for a dimond
133 /// shaped class.
134 int CalculateFlags(const CXXRecordDecl*RD) {
135 int flags = 0;
136 if (SeenBase.count(RD))
137 flags |= 1;
138 else
139 SeenBase.insert(RD);
140 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
141 e = RD->bases_end(); i != e; ++i) {
142 const CXXRecordDecl *Base =
143 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
144 if (i->isVirtual()) {
145 if (SeenVBase.count(Base))
146 flags |= 2;
147 else
148 SeenVBase.insert(Base);
149 }
150 flags |= CalculateFlags(Base);
151 }
152 return flags;
153 }
154
155 bool SimpleInheritance(const CXXRecordDecl *RD) {
156 if (RD->getNumBases() != 1)
157 return false;
158 CXXRecordDecl::base_class_const_iterator i = RD->bases_begin();
159 if (i->isVirtual())
160 return false;
161 if (i->getAccessSpecifier() != AS_public)
162 return false;
163
164 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
165 const CXXRecordDecl *Base =
166 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
167 if (Layout.getBaseClassOffset(Base) != 0)
168 return false;
169 return true;
170 }
171
Anders Carlssonab6faf32009-12-17 05:10:59 +0000172 llvm::Constant *finish(llvm::GlobalVariable *GV,
Anders Carlsson31b7f522009-12-11 02:46:30 +0000173 llvm::StringRef Name, bool Hidden,
174 llvm::GlobalVariable::LinkageTypes Linkage) {
175 llvm::Constant *C =
Anders Carlssonab6faf32009-12-17 05:10:59 +0000176 llvm::ConstantStruct::get(VMContext, &Info[0], Info.size(),
177 /*Packed=*/false);
Mike Stump64989f02009-11-17 23:11:22 +0000178
Mike Stump58588942009-11-19 01:08:19 +0000179 llvm::GlobalVariable *OGV = GV;
Anders Carlsson31b7f522009-12-11 02:46:30 +0000180 GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, Linkage,
Mike Stump58588942009-11-19 01:08:19 +0000181 C, Name);
182 if (OGV) {
Mike Stump64989f02009-11-17 23:11:22 +0000183 GV->takeName(OGV);
184 llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV,
185 OGV->getType());
186 OGV->replaceAllUsesWith(NewPtr);
187 OGV->eraseFromParent();
188 }
Mike Stump582b0372009-11-18 03:46:51 +0000189 if (Hidden)
Mike Stump88a4a622009-11-18 03:21:29 +0000190 GV->setVisibility(llvm::GlobalVariable::HiddenVisibility);
Mike Stump64989f02009-11-17 23:11:22 +0000191 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
192 }
193
194
Anders Carlsson31b7f522009-12-11 02:46:30 +0000195 llvm::Constant *
196 Buildclass_type_info(const CXXRecordDecl *RD,
197 llvm::GlobalVariable::LinkageTypes Linkage) {
Anders Carlsson23440772009-12-17 05:06:03 +0000198 assert(Info.empty() && "Info vector must be empty!");
Anders Carlsson44636d12009-12-11 16:41:51 +0000199
Mike Stump64989f02009-11-17 23:11:22 +0000200 llvm::Constant *C;
201
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000202 llvm::SmallString<256> OutName;
Mike Stumpde050572009-12-02 18:57:08 +0000203 CGM.getMangleContext().mangleCXXRTTI(CGM.getContext().getTagDeclType(RD),
Daniel Dunbar94fd26d2009-11-21 09:06:22 +0000204 OutName);
205 llvm::StringRef Name = OutName.str();
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000206
207 llvm::GlobalVariable *GV;
Mike Stump58588942009-11-19 01:08:19 +0000208 GV = CGM.getModule().getGlobalVariable(Name);
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000209 if (GV && !GV->isDeclaration())
210 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
211
Anders Carlsson31b7f522009-12-11 02:46:30 +0000212 // If we're in an anonymous namespace, then we always want internal linkage.
Eli Friedman470fb732009-12-11 20:48:18 +0000213 if (RD->isInAnonymousNamespace() || !RD->hasLinkage())
Anders Carlsson31b7f522009-12-11 02:46:30 +0000214 Linkage = llvm::GlobalVariable::InternalLinkage;
215
Mike Stump582b0372009-11-18 03:46:51 +0000216 bool Hidden = CGM.getDeclVisibilityMode(RD) == LangOptions::Hidden;
217
Mike Stumpa8285a82009-11-15 03:28:10 +0000218 bool simple = false;
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000219 if (RD->getNumBases() == 0)
220 C = BuildVtableRef("_ZTVN10__cxxabiv117__class_type_infoE");
Mike Stumpa8285a82009-11-15 03:28:10 +0000221 else if (SimpleInheritance(RD)) {
222 simple = true;
223 C = BuildVtableRef("_ZTVN10__cxxabiv120__si_class_type_infoE");
224 } else
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000225 C = BuildVtableRef("_ZTVN10__cxxabiv121__vmi_class_type_infoE");
Anders Carlsson23440772009-12-17 05:06:03 +0000226 Info.push_back(C);
227 Info.push_back(BuildName(CGM.getContext().getTagDeclType(RD), Hidden,
Anders Carlsson31b7f522009-12-11 02:46:30 +0000228 Linkage));
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000229
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000230 // If we have no bases, there are no more fields.
231 if (RD->getNumBases()) {
Mike Stumpa8285a82009-11-15 03:28:10 +0000232 if (!simple) {
Anders Carlsson23440772009-12-17 05:06:03 +0000233 Info.push_back(BuildFlags(CalculateFlags(RD)));
234 Info.push_back(BuildBaseCount(RD->getNumBases()));
Mike Stumpa8285a82009-11-15 03:28:10 +0000235 }
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000236
237 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
238 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
239 e = RD->bases_end(); i != e; ++i) {
Anders Carlsson1d7088d2009-12-17 07:09:17 +0000240 QualType BaseType = i->getType();
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000241 const CXXRecordDecl *Base =
Anders Carlsson1d7088d2009-12-17 07:09:17 +0000242 cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
243 Info.push_back(CGM.GetAddrOfRTTIDescriptor(BaseType));
Mike Stumpa8285a82009-11-15 03:28:10 +0000244 if (simple)
245 break;
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000246 int64_t offset;
247 if (!i->isVirtual())
Mike Stumpa8285a82009-11-15 03:28:10 +0000248 offset = Layout.getBaseClassOffset(Base)/8;
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000249 else
250 offset = CGM.getVtableInfo().getVirtualBaseOffsetIndex(RD, Base);
251 offset <<= 8;
252 // Now set the flags.
253 offset += i->isVirtual() ? 1 : 0;;
254 offset += i->getAccessSpecifier() == AS_public ? 2 : 0;
255 const llvm::Type *LongTy =
256 CGM.getTypes().ConvertType(CGM.getContext().LongTy);
257 C = llvm::ConstantInt::get(LongTy, offset);
Anders Carlsson23440772009-12-17 05:06:03 +0000258 Info.push_back(C);
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000259 }
260 }
261
Anders Carlssonab6faf32009-12-17 05:10:59 +0000262 return finish(GV, Name, Hidden, Linkage);
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000263 }
Mike Stumpea2c0b52009-11-17 02:16:21 +0000264
Mike Stump61c38012009-11-17 21:44:24 +0000265 /// - BuildFlags - Build a __flags value for __pbase_type_info.
Anders Carlssond6baec82009-12-11 01:27:37 +0000266 llvm::Constant *BuildInt(unsigned n) {
267 return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), n);
Mike Stump61c38012009-11-17 21:44:24 +0000268 }
269
Mike Stump58588942009-11-19 01:08:19 +0000270 bool DecideExtern(QualType Ty) {
271 // For this type, see if all components are never in an anonymous namespace.
272 if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>())
273 return (DecideExtern(MPT->getPointeeType())
274 && DecideExtern(QualType(MPT->getClass(), 0)));
275 if (const PointerType *PT = Ty->getAs<PointerType>())
276 return DecideExtern(PT->getPointeeType());
277 if (const RecordType *RT = Ty->getAs<RecordType>())
278 if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
Eli Friedman470fb732009-12-11 20:48:18 +0000279 return !RD->isInAnonymousNamespace() && RD->hasLinkage();
Mike Stump58588942009-11-19 01:08:19 +0000280 return true;
281 }
282
283 bool DecideHidden(QualType Ty) {
284 // For this type, see if all components are never hidden.
285 if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>())
286 return (DecideHidden(MPT->getPointeeType())
287 && DecideHidden(QualType(MPT->getClass(), 0)));
288 if (const PointerType *PT = Ty->getAs<PointerType>())
289 return DecideHidden(PT->getPointeeType());
290 if (const RecordType *RT = Ty->getAs<RecordType>())
291 if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
292 return CGM.getDeclVisibilityMode(RD) == LangOptions::Hidden;
293 return false;
294 }
295
Mike Stump61c38012009-11-17 21:44:24 +0000296 llvm::Constant *BuildPointerType(QualType Ty) {
Anders Carlsson23440772009-12-17 05:06:03 +0000297 assert(Info.empty() && "Info vector must be empty!");
Anders Carlsson44636d12009-12-11 16:41:51 +0000298
Mike Stump61c38012009-11-17 21:44:24 +0000299 llvm::Constant *C;
300
301 llvm::SmallString<256> OutName;
Mike Stumpde050572009-12-02 18:57:08 +0000302 CGM.getMangleContext().mangleCXXRTTI(Ty, OutName);
Daniel Dunbar94fd26d2009-11-21 09:06:22 +0000303 llvm::StringRef Name = OutName.str();
Mike Stump61c38012009-11-17 21:44:24 +0000304
305 llvm::GlobalVariable *GV;
Mike Stump58588942009-11-19 01:08:19 +0000306 GV = CGM.getModule().getGlobalVariable(Name);
Mike Stump61c38012009-11-17 21:44:24 +0000307 if (GV && !GV->isDeclaration())
308 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
309
Mike Stump58588942009-11-19 01:08:19 +0000310 bool Extern = DecideExtern(Ty);
311 bool Hidden = DecideHidden(Ty);
Mike Stump582b0372009-11-18 03:46:51 +0000312
Anders Carlssond6baec82009-12-11 01:27:37 +0000313 const MemberPointerType *PtrMemTy = dyn_cast<MemberPointerType>(Ty);
314 QualType PointeeTy;
315
316 if (PtrMemTy)
317 PointeeTy = PtrMemTy->getPointeeType();
318 else
319 PointeeTy = Ty->getPointeeType();
Mike Stump61c38012009-11-17 21:44:24 +0000320
Anders Carlssond6baec82009-12-11 01:27:37 +0000321 if (PtrMemTy)
Mike Stump61c38012009-11-17 21:44:24 +0000322 C = BuildVtableRef("_ZTVN10__cxxabiv129__pointer_to_member_type_infoE");
323 else
324 C = BuildVtableRef("_ZTVN10__cxxabiv119__pointer_type_infoE");
Anders Carlssond6baec82009-12-11 01:27:37 +0000325
Anders Carlsson23440772009-12-17 05:06:03 +0000326 Info.push_back(C);
327 Info.push_back(BuildName(Ty, Hidden, Extern));
Anders Carlssond6baec82009-12-11 01:27:37 +0000328 Qualifiers Q = PointeeTy.getQualifiers();
329
330 PointeeTy =
331 CGM.getContext().getCanonicalType(PointeeTy).getUnqualifiedType();
332
333 unsigned Flags = 0;
334 if (Q.hasConst())
335 Flags |= TI_Const;
336 if (Q.hasVolatile())
337 Flags |= TI_Volatile;
338 if (Q.hasRestrict())
339 Flags |= TI_Restrict;
340
341 if (Ty->isIncompleteType())
342 Flags |= TI_Incomplete;
343
344 if (PtrMemTy && PtrMemTy->getClass()->isIncompleteType())
345 Flags |= TI_ContainingClassIncomplete;
346
Anders Carlsson23440772009-12-17 05:06:03 +0000347 Info.push_back(BuildInt(Flags));
348 Info.push_back(BuildInt(0));
349 Info.push_back(RTTIBuilder(CGM).BuildType(PointeeTy));
Mike Stump61c38012009-11-17 21:44:24 +0000350
Anders Carlssond6baec82009-12-11 01:27:37 +0000351 if (PtrMemTy)
Anders Carlsson23440772009-12-17 05:06:03 +0000352 Info.push_back(RTTIBuilder(CGM).BuildType(
353 QualType(PtrMemTy->getClass(), 0)));
Mike Stump265df622009-11-17 23:51:10 +0000354
Mike Stump58588942009-11-19 01:08:19 +0000355 // We always generate these as hidden, only the name isn't hidden.
Anders Carlssonab6faf32009-12-17 05:10:59 +0000356 return finish(GV, Name, /*Hidden=*/true, GetLinkageFromExternFlag(Extern));
Mike Stump64989f02009-11-17 23:11:22 +0000357 }
Mike Stump61c38012009-11-17 21:44:24 +0000358
Mike Stumpae9b2be2009-11-17 23:45:57 +0000359 llvm::Constant *BuildSimpleType(QualType Ty, const char *vtbl) {
Mike Stump64989f02009-11-17 23:11:22 +0000360 llvm::SmallString<256> OutName;
Mike Stumpde050572009-12-02 18:57:08 +0000361 CGM.getMangleContext().mangleCXXRTTI(Ty, OutName);
Daniel Dunbar94fd26d2009-11-21 09:06:22 +0000362 llvm::StringRef Name = OutName.str();
Mike Stump64989f02009-11-17 23:11:22 +0000363
364 llvm::GlobalVariable *GV;
Mike Stump58588942009-11-19 01:08:19 +0000365 GV = CGM.getModule().getGlobalVariable(Name);
Mike Stump64989f02009-11-17 23:11:22 +0000366 if (GV && !GV->isDeclaration())
367 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
368
Mike Stump58588942009-11-19 01:08:19 +0000369 bool Extern = DecideExtern(Ty);
370 bool Hidden = DecideHidden(Ty);
Mike Stump582b0372009-11-18 03:46:51 +0000371
Anders Carlssonab6faf32009-12-17 05:10:59 +0000372 Info.push_back(BuildVtableRef(vtbl));
373 Info.push_back(BuildName(Ty, Hidden, Extern));
Anders Carlsson3bf190e2009-12-13 23:47:29 +0000374
Mike Stump58588942009-11-19 01:08:19 +0000375 // We always generate these as hidden, only the name isn't hidden.
Anders Carlssonab6faf32009-12-17 05:10:59 +0000376 return finish(GV, Name, /*Hidden=*/true,
377 GetLinkageFromExternFlag(Extern));
Mike Stump61c38012009-11-17 21:44:24 +0000378 }
379
Anders Carlsson31b7f522009-12-11 02:46:30 +0000380 /// BuildType - Builds the type info for the given type.
Mike Stumpea2c0b52009-11-17 02:16:21 +0000381 llvm::Constant *BuildType(QualType Ty) {
382 const clang::Type &Type
383 = *CGM.getContext().getCanonicalType(Ty).getTypePtr();
Mike Stump7e1365a2009-11-20 00:31:50 +0000384
385 if (const RecordType *RT = Ty.getTypePtr()->getAs<RecordType>())
386 if (const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()))
Anders Carlsson31b7f522009-12-11 02:46:30 +0000387 return BuildClassTypeInfo(RD);
Mike Stump7e1365a2009-11-20 00:31:50 +0000388
Mike Stumpea2c0b52009-11-17 02:16:21 +0000389 switch (Type.getTypeClass()) {
390 default: {
Mike Stumpea2c0b52009-11-17 02:16:21 +0000391 assert(0 && "typeid expression");
Mike Stumpea2c0b52009-11-17 02:16:21 +0000392 return llvm::Constant::getNullValue(Int8PtrTy);
393 }
394
395 case Type::Builtin: {
396 // We expect all type_info objects for builtin types to be in the library.
Anders Carlsson1d7088d2009-12-17 07:09:17 +0000397 return GetAddrOfExternalRTTIDescriptor(Ty);
Mike Stumpea2c0b52009-11-17 02:16:21 +0000398 }
Mike Stump21f5d5d2009-11-17 02:57:13 +0000399
400 case Type::Pointer: {
401 QualType PTy = Ty->getPointeeType();
402 Qualifiers Q = PTy.getQualifiers();
403 Q.removeConst();
404 // T* and const T* for all builtin types T are expected in the library.
405 if (isa<BuiltinType>(PTy) && Q.empty())
Anders Carlsson1d7088d2009-12-17 07:09:17 +0000406 return GetAddrOfExternalRTTIDescriptor(Ty);
Mike Stump21f5d5d2009-11-17 02:57:13 +0000407
Mike Stump61c38012009-11-17 21:44:24 +0000408 return BuildPointerType(Ty);
Mike Stump21f5d5d2009-11-17 02:57:13 +0000409 }
Mike Stump5fae8562009-11-17 22:33:00 +0000410 case Type::MemberPointer:
411 return BuildPointerType(Ty);
Mike Stump64989f02009-11-17 23:11:22 +0000412 case Type::FunctionProto:
Mike Stumpae9b2be2009-11-17 23:45:57 +0000413 case Type::FunctionNoProto:
414 return BuildSimpleType(Ty, "_ZTVN10__cxxabiv120__function_type_infoE");
415 case Type::ConstantArray:
416 case Type::IncompleteArray:
417 case Type::VariableArray:
418 case Type::Vector:
419 case Type::ExtVector:
420 return BuildSimpleType(Ty, "_ZTVN10__cxxabiv117__array_type_infoE");
421 case Type::Enum:
422 return BuildSimpleType(Ty, "_ZTVN10__cxxabiv116__enum_type_infoE");
Mike Stumpea2c0b52009-11-17 02:16:21 +0000423 }
424 }
Anders Carlsson31b7f522009-12-11 02:46:30 +0000425
426 /// BuildClassTypeInfo - Builds the class type info (or a reference to it)
427 /// for the given record decl.
428 llvm::Constant *BuildClassTypeInfo(const CXXRecordDecl *RD) {
429 const CXXMethodDecl *KeyFunction = 0;
430
431 if (RD->isDynamicClass())
432 KeyFunction = CGM.getContext().getKeyFunction(RD);
433
434 if (KeyFunction) {
435 // If the key function is defined in this translation unit, then the RTTI
436 // related constants should also be emitted here, with external linkage.
437 if (KeyFunction->getBody())
438 return Buildclass_type_info(RD, llvm::GlobalValue::ExternalLinkage);
439
440 // Otherwise, we just want a reference to the type info.
Anders Carlsson1d7088d2009-12-17 07:09:17 +0000441 QualType Ty = CGM.getContext().getTagDeclType(RD);
442 return GetAddrOfExternalRTTIDescriptor(Ty);
Anders Carlsson31b7f522009-12-11 02:46:30 +0000443 }
444
445 // If there is no key function (or if the record doesn't have any virtual
446 // member functions or virtual bases), emit the type info with weak_odr
447 // linkage.
448 return Buildclass_type_info(RD, llvm::GlobalValue::WeakODRLinkage);
449 }
Mike Stump2b1bf312009-11-14 14:25:18 +0000450};
Mike Stump92f2fe22009-12-02 19:07:44 +0000451}
Mike Stump2b1bf312009-11-14 14:25:18 +0000452
Anders Carlsson1d7088d2009-12-17 07:09:17 +0000453llvm::Constant *RTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
454 // Mangle the RTTI name.
455 llvm::SmallString<256> OutName;
456 CGM.getMangleContext().mangleCXXRTTI(Ty, OutName);
457 llvm::StringRef Name = OutName.str();
458
459 // Look for an existing global variable.
460 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
461
462 if (!GV) {
463 // Create a new global variable.
464 GV = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy, /*Constant=*/true,
465 llvm::GlobalValue::ExternalLinkage, 0, Name);
Anders Carlsson31b7f522009-12-11 02:46:30 +0000466 }
467
Anders Carlsson1d7088d2009-12-17 07:09:17 +0000468 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
Anders Carlsson31b7f522009-12-11 02:46:30 +0000469}
470
Anders Carlsson1d7088d2009-12-17 07:09:17 +0000471llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty) {
Anders Carlsson31b7f522009-12-11 02:46:30 +0000472 if (!getContext().getLangOptions().RTTI) {
473 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
474 return llvm::Constant::getNullValue(Int8PtrTy);
475 }
476
477 return RTTIBuilder(*this).BuildType(Ty);
478}