blob: e18843d5cf3f1b32e86cdc10a83f03d929f0cd3f [file] [log] [blame]
Anders Carlsson656e4c12009-10-10 20:49:04 +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
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 Stump2b1bf312009-11-14 14:25:18 +000020class RttiBuilder {
21 CodeGenModule &CGM; // Per-module state.
22 llvm::LLVMContext &VMContext;
23 const llvm::Type *Int8PtrTy;
Mike Stumpa8285a82009-11-15 03:28:10 +000024 llvm::SmallSet<const CXXRecordDecl *, 16> SeenVBase;
25 llvm::SmallSet<const CXXRecordDecl *, 32> SeenBase;
Mike Stump2b1bf312009-11-14 14:25:18 +000026public:
27 RttiBuilder(CodeGenModule &cgm)
28 : CGM(cgm), VMContext(cgm.getModule().getContext()),
29 Int8PtrTy(llvm::Type::getInt8PtrTy(VMContext)) { }
30
Mike Stumpcbcd4e52009-11-14 23:32:21 +000031 /// BuildVtableRef - Build a reference to a vtable.
32 llvm::Constant *BuildVtableRef(const char *Name) {
33 // Build a descriptor for Name
Mike Stumpc7a05bd2009-11-14 15:55:18 +000034 llvm::Constant *GV = CGM.getModule().getGlobalVariable(Name);
35 if (GV)
36 GV = llvm::ConstantExpr::getBitCast(GV,
37 llvm::PointerType::get(Int8PtrTy, 0));
38 else {
39 llvm::GlobalVariable::LinkageTypes linktype;
40 linktype = llvm::GlobalValue::ExternalLinkage;
41 GV = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy,
42 true, linktype, 0, Name);
Mike Stumpcbcd4e52009-11-14 23:32:21 +000043 }
Mike Stumpc7a05bd2009-11-14 15:55:18 +000044 llvm::Constant *C;
45 C = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 2);
46 C = llvm::ConstantExpr::getInBoundsGetElementPtr(GV, &C, 1);
47 return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
48 }
Mike Stumpcbcd4e52009-11-14 23:32:21 +000049
Mike Stump582b0372009-11-18 03:46:51 +000050 llvm::Constant *BuildName(QualType Ty, bool Hidden) {
Mike Stump2b1bf312009-11-14 14:25:18 +000051 llvm::SmallString<256> OutName;
52 llvm::raw_svector_ostream Out(OutName);
Mike Stump61c38012009-11-17 21:44:24 +000053 mangleCXXRttiName(CGM.getMangleContext(), Ty, Out);
Mike Stumpcbcd4e52009-11-14 23:32:21 +000054
Mike Stump2b1bf312009-11-14 14:25:18 +000055 llvm::GlobalVariable::LinkageTypes linktype;
56 linktype = llvm::GlobalValue::LinkOnceODRLinkage;
57
58 llvm::Constant *C;
59 C = llvm::ConstantArray::get(VMContext, Out.str().substr(4));
Mike Stumpcbcd4e52009-11-14 23:32:21 +000060
Mike Stump582b0372009-11-18 03:46:51 +000061 llvm::GlobalVariable * GV = new llvm::GlobalVariable(CGM.getModule(),
62 C->getType(),
63 true, linktype, C,
64 Out.str());
65 if (Hidden)
66 GV->setVisibility(llvm::GlobalVariable::HiddenVisibility);
67 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
Mike Stump2b1bf312009-11-14 14:25:18 +000068 };
Mike Stumpc7a05bd2009-11-14 15:55:18 +000069
Mike Stumpcbcd4e52009-11-14 23:32:21 +000070 /// - BuildFlags - Build a psABI __flags value for __vmi_class_type_info.
71 llvm::Constant *BuildFlags(int f) {
72 return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), f);
73 }
74
75 /// BuildBaseCount - Build a psABI __base_count value for
76 /// __vmi_class_type_info.
77 llvm::Constant *BuildBaseCount(unsigned c) {
78 return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), c);
79 }
80
Mike Stumpea2c0b52009-11-17 02:16:21 +000081 llvm::Constant *BuildTypeRef(QualType Ty) {
Mike Stumpcbcd4e52009-11-14 23:32:21 +000082 llvm::Constant *C;
Mike Stumpc7a05bd2009-11-14 15:55:18 +000083
84 if (!CGM.getContext().getLangOptions().Rtti)
85 return llvm::Constant::getNullValue(Int8PtrTy);
86
87 llvm::SmallString<256> OutName;
88 llvm::raw_svector_ostream Out(OutName);
Mike Stumpea2c0b52009-11-17 02:16:21 +000089 mangleCXXRtti(CGM.getMangleContext(), Ty, Out);
Mike Stumpcbcd4e52009-11-14 23:32:21 +000090
91 C = CGM.getModule().getGlobalVariable(Out.str());
92 if (C)
93 return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
94
95 llvm::GlobalVariable::LinkageTypes linktype;
96 linktype = llvm::GlobalValue::ExternalLinkage;;
97
98 C = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy, true, linktype,
99 0, Out.str());
100 return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
101 }
102
Mike Stumpea2c0b52009-11-17 02:16:21 +0000103 llvm::Constant *Buildclass_type_infoRef(const CXXRecordDecl *RD) {
104 return BuildTypeRef(CGM.getContext().getTagDeclType(RD));
105 }
106
Mike Stumpa8285a82009-11-15 03:28:10 +0000107 /// CalculateFlags - Calculate the flags for the __vmi_class_type_info
108 /// datastructure. 1 for non-diamond repeated inheritance, 2 for a dimond
109 /// shaped class.
110 int CalculateFlags(const CXXRecordDecl*RD) {
111 int flags = 0;
112 if (SeenBase.count(RD))
113 flags |= 1;
114 else
115 SeenBase.insert(RD);
116 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
117 e = RD->bases_end(); i != e; ++i) {
118 const CXXRecordDecl *Base =
119 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
120 if (i->isVirtual()) {
121 if (SeenVBase.count(Base))
122 flags |= 2;
123 else
124 SeenVBase.insert(Base);
125 }
126 flags |= CalculateFlags(Base);
127 }
128 return flags;
129 }
130
131 bool SimpleInheritance(const CXXRecordDecl *RD) {
132 if (RD->getNumBases() != 1)
133 return false;
134 CXXRecordDecl::base_class_const_iterator i = RD->bases_begin();
135 if (i->isVirtual())
136 return false;
137 if (i->getAccessSpecifier() != AS_public)
138 return false;
139
140 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
141 const CXXRecordDecl *Base =
142 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
143 if (Layout.getBaseClassOffset(Base) != 0)
144 return false;
145 return true;
146 }
147
Mike Stump64989f02009-11-17 23:11:22 +0000148 llvm::Constant *finish(std::vector<llvm::Constant *> &info,
149 llvm::GlobalVariable *GV,
Mike Stump582b0372009-11-18 03:46:51 +0000150 llvm::StringRef Name, bool Hidden) {
Mike Stump64989f02009-11-17 23:11:22 +0000151 llvm::GlobalVariable::LinkageTypes linktype;
152 linktype = llvm::GlobalValue::LinkOnceODRLinkage;
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000153
Mike Stump64989f02009-11-17 23:11:22 +0000154 llvm::Constant *C;
155 C = llvm::ConstantStruct::get(VMContext, &info[0], info.size(), false);
156
157 if (GV == 0)
158 GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
159 linktype, C, Name);
160 else {
161 llvm::GlobalVariable *OGV = GV;
162 GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
163 linktype, C, Name);
164 GV->takeName(OGV);
165 llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV,
166 OGV->getType());
167 OGV->replaceAllUsesWith(NewPtr);
168 OGV->eraseFromParent();
169 }
Mike Stump582b0372009-11-18 03:46:51 +0000170 if (Hidden)
Mike Stump88a4a622009-11-18 03:21:29 +0000171 GV->setVisibility(llvm::GlobalVariable::HiddenVisibility);
Mike Stump64989f02009-11-17 23:11:22 +0000172 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
173 }
174
175
176 llvm::Constant *Buildclass_type_info(const CXXRecordDecl *RD) {
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000177 if (!CGM.getContext().getLangOptions().Rtti)
178 return llvm::Constant::getNullValue(Int8PtrTy);
179
Mike Stump64989f02009-11-17 23:11:22 +0000180 llvm::Constant *C;
181
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000182 llvm::SmallString<256> OutName;
183 llvm::raw_svector_ostream Out(OutName);
184 mangleCXXRtti(CGM.getMangleContext(), CGM.getContext().getTagDeclType(RD),
185 Out);
186
187 llvm::GlobalVariable *GV;
188 GV = CGM.getModule().getGlobalVariable(Out.str());
189 if (GV && !GV->isDeclaration())
190 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
191
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000192 std::vector<llvm::Constant *> info;
193
Mike Stump582b0372009-11-18 03:46:51 +0000194 bool Hidden = CGM.getDeclVisibilityMode(RD) == LangOptions::Hidden;
195
Mike Stumpa8285a82009-11-15 03:28:10 +0000196 bool simple = false;
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000197 if (RD->getNumBases() == 0)
198 C = BuildVtableRef("_ZTVN10__cxxabiv117__class_type_infoE");
Mike Stumpa8285a82009-11-15 03:28:10 +0000199 else if (SimpleInheritance(RD)) {
200 simple = true;
201 C = BuildVtableRef("_ZTVN10__cxxabiv120__si_class_type_infoE");
202 } else
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000203 C = BuildVtableRef("_ZTVN10__cxxabiv121__vmi_class_type_infoE");
204 info.push_back(C);
Mike Stump582b0372009-11-18 03:46:51 +0000205 info.push_back(BuildName(CGM.getContext().getTagDeclType(RD), Hidden));
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000206
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000207 // If we have no bases, there are no more fields.
208 if (RD->getNumBases()) {
Mike Stumpa8285a82009-11-15 03:28:10 +0000209 if (!simple) {
210 info.push_back(BuildFlags(CalculateFlags(RD)));
211 info.push_back(BuildBaseCount(RD->getNumBases()));
212 }
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000213
214 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
215 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
216 e = RD->bases_end(); i != e; ++i) {
217 const CXXRecordDecl *Base =
218 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
Mike Stumpa8285a82009-11-15 03:28:10 +0000219 info.push_back(CGM.GenerateRttiRef(Base));
220 if (simple)
221 break;
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000222 int64_t offset;
223 if (!i->isVirtual())
Mike Stumpa8285a82009-11-15 03:28:10 +0000224 offset = Layout.getBaseClassOffset(Base)/8;
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000225 else
226 offset = CGM.getVtableInfo().getVirtualBaseOffsetIndex(RD, Base);
227 offset <<= 8;
228 // Now set the flags.
229 offset += i->isVirtual() ? 1 : 0;;
230 offset += i->getAccessSpecifier() == AS_public ? 2 : 0;
231 const llvm::Type *LongTy =
232 CGM.getTypes().ConvertType(CGM.getContext().LongTy);
233 C = llvm::ConstantInt::get(LongTy, offset);
234 info.push_back(C);
235 }
236 }
237
Mike Stump582b0372009-11-18 03:46:51 +0000238 return finish(info, GV, Out.str(), Hidden);
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000239 }
Mike Stumpea2c0b52009-11-17 02:16:21 +0000240
Mike Stump61c38012009-11-17 21:44:24 +0000241 /// - BuildFlags - Build a __flags value for __pbase_type_info.
242 llvm::Constant *BuildInt(int f) {
243 return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), f);
244 }
245
246 llvm::Constant *BuildType2(QualType Ty) {
247 if (const RecordType *RT = Ty.getTypePtr()->getAs<RecordType>())
248 if (const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()))
249 return Buildclass_type_info(RD);
250 return BuildType(Ty);
251 }
252
253 llvm::Constant *BuildPointerType(QualType Ty) {
Mike Stump61c38012009-11-17 21:44:24 +0000254 llvm::Constant *C;
255
256 llvm::SmallString<256> OutName;
257 llvm::raw_svector_ostream Out(OutName);
258 mangleCXXRtti(CGM.getMangleContext(), Ty, Out);
259
260 llvm::GlobalVariable *GV;
261 GV = CGM.getModule().getGlobalVariable(Out.str());
262 if (GV && !GV->isDeclaration())
263 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
264
Mike Stump61c38012009-11-17 21:44:24 +0000265 std::vector<llvm::Constant *> info;
266
Mike Stump582b0372009-11-18 03:46:51 +0000267 // FIXME: pointer to hidden should be hidden, we should be able to
268 // grab a bit off the type for this.
269 bool Hidden = false;
270
Mike Stump61c38012009-11-17 21:44:24 +0000271 QualType PTy = Ty->getPointeeType();
Mike Stump61c38012009-11-17 21:44:24 +0000272 QualType BTy;
Mike Stump61c38012009-11-17 21:44:24 +0000273 bool PtrMem = false;
Mike Stump5fae8562009-11-17 22:33:00 +0000274 if (const MemberPointerType *MPT = dyn_cast<MemberPointerType>(Ty)) {
275 PtrMem = true;
276 BTy = QualType(MPT->getClass(), 0);
277 PTy = MPT->getPointeeType();
278 }
Mike Stump61c38012009-11-17 21:44:24 +0000279
280 if (PtrMem)
281 C = BuildVtableRef("_ZTVN10__cxxabiv129__pointer_to_member_type_infoE");
282 else
283 C = BuildVtableRef("_ZTVN10__cxxabiv119__pointer_type_infoE");
284 info.push_back(C);
Mike Stump582b0372009-11-18 03:46:51 +0000285 info.push_back(BuildName(Ty, Hidden));
Mike Stump61c38012009-11-17 21:44:24 +0000286 Qualifiers Q = PTy.getQualifiers();
287 PTy = CGM.getContext().getCanonicalType(PTy).getUnqualifiedType();
288 int flags = 0;
289 flags += Q.hasConst() ? 0x1 : 0;
290 flags += Q.hasVolatile() ? 0x2 : 0;
291 flags += Q.hasRestrict() ? 0x4 : 0;
292 flags += Ty.getTypePtr()->isIncompleteType() ? 0x8 : 0;
293 if (PtrMem && BTy.getTypePtr()->isIncompleteType())
294 flags += 0x10;
Mike Stump265df622009-11-17 23:51:10 +0000295
Mike Stump61c38012009-11-17 21:44:24 +0000296 info.push_back(BuildInt(flags));
297 info.push_back(BuildInt(0));
298 info.push_back(BuildType2(PTy));
299
300 if (PtrMem)
301 info.push_back(BuildType2(BTy));
Mike Stump265df622009-11-17 23:51:10 +0000302
Mike Stump582b0372009-11-18 03:46:51 +0000303 return finish(info, GV, Out.str(), true);
Mike Stump64989f02009-11-17 23:11:22 +0000304 }
Mike Stump61c38012009-11-17 21:44:24 +0000305
Mike Stumpae9b2be2009-11-17 23:45:57 +0000306 llvm::Constant *BuildSimpleType(QualType Ty, const char *vtbl) {
Mike Stump64989f02009-11-17 23:11:22 +0000307 llvm::Constant *C;
308
309 llvm::SmallString<256> OutName;
310 llvm::raw_svector_ostream Out(OutName);
311 mangleCXXRtti(CGM.getMangleContext(), Ty, Out);
312
313 llvm::GlobalVariable *GV;
314 GV = CGM.getModule().getGlobalVariable(Out.str());
315 if (GV && !GV->isDeclaration())
316 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
317
318 std::vector<llvm::Constant *> info;
319
Mike Stump582b0372009-11-18 03:46:51 +0000320 // FIXME: pointer to hidden should be hidden, we should be able to
321 // grab a bit off the type for this.
322 bool Hidden = false;
323
Mike Stumpae9b2be2009-11-17 23:45:57 +0000324 C = BuildVtableRef(vtbl);
Mike Stump64989f02009-11-17 23:11:22 +0000325 info.push_back(C);
Mike Stump582b0372009-11-18 03:46:51 +0000326 info.push_back(BuildName(Ty, Hidden));
Mike Stump265df622009-11-17 23:51:10 +0000327
Mike Stump582b0372009-11-18 03:46:51 +0000328 return finish(info, GV, Out.str(), true);
Mike Stump61c38012009-11-17 21:44:24 +0000329 }
330
Mike Stumpea2c0b52009-11-17 02:16:21 +0000331 llvm::Constant *BuildType(QualType Ty) {
332 const clang::Type &Type
333 = *CGM.getContext().getCanonicalType(Ty).getTypePtr();
334 switch (Type.getTypeClass()) {
335 default: {
Mike Stumpea2c0b52009-11-17 02:16:21 +0000336 assert(0 && "typeid expression");
Mike Stumpea2c0b52009-11-17 02:16:21 +0000337 return llvm::Constant::getNullValue(Int8PtrTy);
338 }
339
340 case Type::Builtin: {
341 // We expect all type_info objects for builtin types to be in the library.
342 return BuildTypeRef(Ty);
343 }
Mike Stump21f5d5d2009-11-17 02:57:13 +0000344
345 case Type::Pointer: {
346 QualType PTy = Ty->getPointeeType();
347 Qualifiers Q = PTy.getQualifiers();
348 Q.removeConst();
349 // T* and const T* for all builtin types T are expected in the library.
350 if (isa<BuiltinType>(PTy) && Q.empty())
351 return BuildTypeRef(Ty);
352
Mike Stump61c38012009-11-17 21:44:24 +0000353 return BuildPointerType(Ty);
Mike Stump21f5d5d2009-11-17 02:57:13 +0000354 }
Mike Stump5fae8562009-11-17 22:33:00 +0000355 case Type::MemberPointer:
356 return BuildPointerType(Ty);
Mike Stump64989f02009-11-17 23:11:22 +0000357 case Type::FunctionProto:
Mike Stumpae9b2be2009-11-17 23:45:57 +0000358 case Type::FunctionNoProto:
359 return BuildSimpleType(Ty, "_ZTVN10__cxxabiv120__function_type_infoE");
360 case Type::ConstantArray:
361 case Type::IncompleteArray:
362 case Type::VariableArray:
363 case Type::Vector:
364 case Type::ExtVector:
365 return BuildSimpleType(Ty, "_ZTVN10__cxxabiv117__array_type_infoE");
366 case Type::Enum:
367 return BuildSimpleType(Ty, "_ZTVN10__cxxabiv116__enum_type_infoE");
Mike Stumpea2c0b52009-11-17 02:16:21 +0000368 }
369 }
Mike Stump2b1bf312009-11-14 14:25:18 +0000370};
371
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000372llvm::Constant *CodeGenModule::GenerateRttiRef(const CXXRecordDecl *RD) {
373 RttiBuilder b(*this);
374
375 return b.Buildclass_type_infoRef(RD);
376}
377
Anders Carlsson656e4c12009-10-10 20:49:04 +0000378llvm::Constant *CodeGenModule::GenerateRtti(const CXXRecordDecl *RD) {
Mike Stump2b1bf312009-11-14 14:25:18 +0000379 RttiBuilder b(*this);
380
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000381 return b.Buildclass_type_info(RD);
Anders Carlsson656e4c12009-10-10 20:49:04 +0000382}
Mike Stumpea2c0b52009-11-17 02:16:21 +0000383
384llvm::Constant *CodeGenModule::GenerateRttiNonClass(QualType Ty) {
385 RttiBuilder b(*this);
386
387 return b.BuildType(Ty);
388}