blob: 01767466e8b515beb5b3c6dc06536ba53184947a [file] [log] [blame]
Anders Carlsson6ce51fd2009-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 Stump103a0842009-11-17 23:45:57 +000014#include "clang/AST/Type.h"
Mike Stumpf5b28692009-11-14 23:32:21 +000015#include "clang/AST/RecordLayout.h"
Mike Stumpdb72c892009-11-17 21:44:24 +000016#include "CodeGenModule.h"
Anders Carlsson6ce51fd2009-10-10 20:49:04 +000017using namespace clang;
18using namespace CodeGen;
19
Mike Stump14718422009-11-14 14:25:18 +000020class RttiBuilder {
21 CodeGenModule &CGM; // Per-module state.
22 llvm::LLVMContext &VMContext;
23 const llvm::Type *Int8PtrTy;
Mike Stump4c808df2009-11-15 03:28:10 +000024 llvm::SmallSet<const CXXRecordDecl *, 16> SeenVBase;
25 llvm::SmallSet<const CXXRecordDecl *, 32> SeenBase;
Mike Stump14718422009-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 Stumpf5b28692009-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 Stump1acec6a2009-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 Stumpf5b28692009-11-14 23:32:21 +000043 }
Mike Stump1acec6a2009-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 Stumpf5b28692009-11-14 23:32:21 +000049
Mike Stumpdb72c892009-11-17 21:44:24 +000050 llvm::Constant *BuildName(QualType Ty) {
Mike Stump14718422009-11-14 14:25:18 +000051 llvm::SmallString<256> OutName;
52 llvm::raw_svector_ostream Out(OutName);
Mike Stumpdb72c892009-11-17 21:44:24 +000053 mangleCXXRttiName(CGM.getMangleContext(), Ty, Out);
Mike Stumpf5b28692009-11-14 23:32:21 +000054
Mike Stump14718422009-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 Stumpf5b28692009-11-14 23:32:21 +000060
Mike Stump14718422009-11-14 14:25:18 +000061 llvm::Constant *s = new llvm::GlobalVariable(CGM.getModule(), C->getType(),
62 true, linktype, C,
63 Out.str());
64 s = llvm::ConstantExpr::getBitCast(s, Int8PtrTy);
65 return s;
66 };
Mike Stump1acec6a2009-11-14 15:55:18 +000067
Mike Stumpf5b28692009-11-14 23:32:21 +000068 /// - BuildFlags - Build a psABI __flags value for __vmi_class_type_info.
69 llvm::Constant *BuildFlags(int f) {
70 return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), f);
71 }
72
73 /// BuildBaseCount - Build a psABI __base_count value for
74 /// __vmi_class_type_info.
75 llvm::Constant *BuildBaseCount(unsigned c) {
76 return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), c);
77 }
78
Mike Stump3f75d552009-11-17 02:16:21 +000079 llvm::Constant *BuildTypeRef(QualType Ty) {
Mike Stumpf5b28692009-11-14 23:32:21 +000080 llvm::Constant *C;
Mike Stump1acec6a2009-11-14 15:55:18 +000081
82 if (!CGM.getContext().getLangOptions().Rtti)
83 return llvm::Constant::getNullValue(Int8PtrTy);
84
85 llvm::SmallString<256> OutName;
86 llvm::raw_svector_ostream Out(OutName);
Mike Stump3f75d552009-11-17 02:16:21 +000087 mangleCXXRtti(CGM.getMangleContext(), Ty, Out);
Mike Stumpf5b28692009-11-14 23:32:21 +000088
89 C = CGM.getModule().getGlobalVariable(Out.str());
90 if (C)
91 return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
92
93 llvm::GlobalVariable::LinkageTypes linktype;
94 linktype = llvm::GlobalValue::ExternalLinkage;;
95
96 C = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy, true, linktype,
97 0, Out.str());
98 return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
99 }
100
Mike Stump3f75d552009-11-17 02:16:21 +0000101 llvm::Constant *Buildclass_type_infoRef(const CXXRecordDecl *RD) {
102 return BuildTypeRef(CGM.getContext().getTagDeclType(RD));
103 }
104
Mike Stump4c808df2009-11-15 03:28:10 +0000105 /// CalculateFlags - Calculate the flags for the __vmi_class_type_info
106 /// datastructure. 1 for non-diamond repeated inheritance, 2 for a dimond
107 /// shaped class.
108 int CalculateFlags(const CXXRecordDecl*RD) {
109 int flags = 0;
110 if (SeenBase.count(RD))
111 flags |= 1;
112 else
113 SeenBase.insert(RD);
114 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
115 e = RD->bases_end(); i != e; ++i) {
116 const CXXRecordDecl *Base =
117 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
118 if (i->isVirtual()) {
119 if (SeenVBase.count(Base))
120 flags |= 2;
121 else
122 SeenVBase.insert(Base);
123 }
124 flags |= CalculateFlags(Base);
125 }
126 return flags;
127 }
128
129 bool SimpleInheritance(const CXXRecordDecl *RD) {
130 if (RD->getNumBases() != 1)
131 return false;
132 CXXRecordDecl::base_class_const_iterator i = RD->bases_begin();
133 if (i->isVirtual())
134 return false;
135 if (i->getAccessSpecifier() != AS_public)
136 return false;
137
138 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
139 const CXXRecordDecl *Base =
140 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
141 if (Layout.getBaseClassOffset(Base) != 0)
142 return false;
143 return true;
144 }
145
Mike Stump96b96d52009-11-17 23:11:22 +0000146 llvm::Constant *finish(std::vector<llvm::Constant *> &info,
147 llvm::GlobalVariable *GV,
Mike Stumpc5d2ed72009-11-18 03:21:29 +0000148 llvm::StringRef Name, bool Extern) {
Mike Stump96b96d52009-11-17 23:11:22 +0000149 llvm::GlobalVariable::LinkageTypes linktype;
150 linktype = llvm::GlobalValue::LinkOnceODRLinkage;
Mike Stumpf5b28692009-11-14 23:32:21 +0000151
Mike Stump96b96d52009-11-17 23:11:22 +0000152 llvm::Constant *C;
153 C = llvm::ConstantStruct::get(VMContext, &info[0], info.size(), false);
154
155 if (GV == 0)
156 GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
157 linktype, C, Name);
158 else {
159 llvm::GlobalVariable *OGV = GV;
160 GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
161 linktype, C, Name);
162 GV->takeName(OGV);
163 llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV,
164 OGV->getType());
165 OGV->replaceAllUsesWith(NewPtr);
166 OGV->eraseFromParent();
167 }
Mike Stumpc5d2ed72009-11-18 03:21:29 +0000168 if (!Extern)
169 GV->setVisibility(llvm::GlobalVariable::HiddenVisibility);
Mike Stump96b96d52009-11-17 23:11:22 +0000170 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
171 }
172
173
174 llvm::Constant *Buildclass_type_info(const CXXRecordDecl *RD) {
Mike Stumpf5b28692009-11-14 23:32:21 +0000175 if (!CGM.getContext().getLangOptions().Rtti)
176 return llvm::Constant::getNullValue(Int8PtrTy);
177
Mike Stump96b96d52009-11-17 23:11:22 +0000178 llvm::Constant *C;
179
Mike Stumpf5b28692009-11-14 23:32:21 +0000180 llvm::SmallString<256> OutName;
181 llvm::raw_svector_ostream Out(OutName);
182 mangleCXXRtti(CGM.getMangleContext(), CGM.getContext().getTagDeclType(RD),
183 Out);
184
185 llvm::GlobalVariable *GV;
186 GV = CGM.getModule().getGlobalVariable(Out.str());
187 if (GV && !GV->isDeclaration())
188 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
189
Mike Stump1acec6a2009-11-14 15:55:18 +0000190 std::vector<llvm::Constant *> info;
191
Mike Stump4c808df2009-11-15 03:28:10 +0000192 bool simple = false;
Mike Stumpf5b28692009-11-14 23:32:21 +0000193 if (RD->getNumBases() == 0)
194 C = BuildVtableRef("_ZTVN10__cxxabiv117__class_type_infoE");
Mike Stump4c808df2009-11-15 03:28:10 +0000195 else if (SimpleInheritance(RD)) {
196 simple = true;
197 C = BuildVtableRef("_ZTVN10__cxxabiv120__si_class_type_infoE");
198 } else
Mike Stumpf5b28692009-11-14 23:32:21 +0000199 C = BuildVtableRef("_ZTVN10__cxxabiv121__vmi_class_type_infoE");
200 info.push_back(C);
Mike Stumpdb72c892009-11-17 21:44:24 +0000201 info.push_back(BuildName(CGM.getContext().getTagDeclType(RD)));
Mike Stump1acec6a2009-11-14 15:55:18 +0000202
Mike Stumpf5b28692009-11-14 23:32:21 +0000203 // If we have no bases, there are no more fields.
204 if (RD->getNumBases()) {
Mike Stump4c808df2009-11-15 03:28:10 +0000205 if (!simple) {
206 info.push_back(BuildFlags(CalculateFlags(RD)));
207 info.push_back(BuildBaseCount(RD->getNumBases()));
208 }
Mike Stumpf5b28692009-11-14 23:32:21 +0000209
210 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
211 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
212 e = RD->bases_end(); i != e; ++i) {
213 const CXXRecordDecl *Base =
214 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
Mike Stump4c808df2009-11-15 03:28:10 +0000215 info.push_back(CGM.GenerateRttiRef(Base));
216 if (simple)
217 break;
Mike Stumpf5b28692009-11-14 23:32:21 +0000218 int64_t offset;
219 if (!i->isVirtual())
Mike Stump4c808df2009-11-15 03:28:10 +0000220 offset = Layout.getBaseClassOffset(Base)/8;
Mike Stumpf5b28692009-11-14 23:32:21 +0000221 else
222 offset = CGM.getVtableInfo().getVirtualBaseOffsetIndex(RD, Base);
223 offset <<= 8;
224 // Now set the flags.
225 offset += i->isVirtual() ? 1 : 0;;
226 offset += i->getAccessSpecifier() == AS_public ? 2 : 0;
227 const llvm::Type *LongTy =
228 CGM.getTypes().ConvertType(CGM.getContext().LongTy);
229 C = llvm::ConstantInt::get(LongTy, offset);
230 info.push_back(C);
231 }
232 }
233
Mike Stumpc5d2ed72009-11-18 03:21:29 +0000234 bool Extern = CGM.getDeclVisibilityMode(RD) != LangOptions::Hidden;
235
236 return finish(info, GV, Out.str(), Extern);
Mike Stump1acec6a2009-11-14 15:55:18 +0000237 }
Mike Stump3f75d552009-11-17 02:16:21 +0000238
Mike Stumpdb72c892009-11-17 21:44:24 +0000239 /// - BuildFlags - Build a __flags value for __pbase_type_info.
240 llvm::Constant *BuildInt(int f) {
241 return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), f);
242 }
243
244 llvm::Constant *BuildType2(QualType Ty) {
245 if (const RecordType *RT = Ty.getTypePtr()->getAs<RecordType>())
246 if (const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()))
247 return Buildclass_type_info(RD);
248 return BuildType(Ty);
249 }
250
251 llvm::Constant *BuildPointerType(QualType Ty) {
Mike Stumpdb72c892009-11-17 21:44:24 +0000252 llvm::Constant *C;
253
254 llvm::SmallString<256> OutName;
255 llvm::raw_svector_ostream Out(OutName);
256 mangleCXXRtti(CGM.getMangleContext(), Ty, Out);
257
258 llvm::GlobalVariable *GV;
259 GV = CGM.getModule().getGlobalVariable(Out.str());
260 if (GV && !GV->isDeclaration())
261 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
262
Mike Stumpdb72c892009-11-17 21:44:24 +0000263 std::vector<llvm::Constant *> info;
264
265 QualType PTy = Ty->getPointeeType();
Mike Stumpdb72c892009-11-17 21:44:24 +0000266 QualType BTy;
Mike Stumpdb72c892009-11-17 21:44:24 +0000267 bool PtrMem = false;
Mike Stump6fdfea62009-11-17 22:33:00 +0000268 if (const MemberPointerType *MPT = dyn_cast<MemberPointerType>(Ty)) {
269 PtrMem = true;
270 BTy = QualType(MPT->getClass(), 0);
271 PTy = MPT->getPointeeType();
272 }
Mike Stumpdb72c892009-11-17 21:44:24 +0000273
274 if (PtrMem)
275 C = BuildVtableRef("_ZTVN10__cxxabiv129__pointer_to_member_type_infoE");
276 else
277 C = BuildVtableRef("_ZTVN10__cxxabiv119__pointer_type_infoE");
278 info.push_back(C);
279 info.push_back(BuildName(Ty));
280 Qualifiers Q = PTy.getQualifiers();
281 PTy = CGM.getContext().getCanonicalType(PTy).getUnqualifiedType();
282 int flags = 0;
283 flags += Q.hasConst() ? 0x1 : 0;
284 flags += Q.hasVolatile() ? 0x2 : 0;
285 flags += Q.hasRestrict() ? 0x4 : 0;
286 flags += Ty.getTypePtr()->isIncompleteType() ? 0x8 : 0;
287 if (PtrMem && BTy.getTypePtr()->isIncompleteType())
288 flags += 0x10;
Mike Stump4aaf79a2009-11-17 23:51:10 +0000289
Mike Stumpdb72c892009-11-17 21:44:24 +0000290 info.push_back(BuildInt(flags));
291 info.push_back(BuildInt(0));
292 info.push_back(BuildType2(PTy));
293
294 if (PtrMem)
295 info.push_back(BuildType2(BTy));
Mike Stump4aaf79a2009-11-17 23:51:10 +0000296
Mike Stumpc5d2ed72009-11-18 03:21:29 +0000297 return finish(info, GV, Out.str(), false);
Mike Stump96b96d52009-11-17 23:11:22 +0000298 }
Mike Stumpdb72c892009-11-17 21:44:24 +0000299
Mike Stump103a0842009-11-17 23:45:57 +0000300 llvm::Constant *BuildSimpleType(QualType Ty, const char *vtbl) {
Mike Stump96b96d52009-11-17 23:11:22 +0000301 llvm::Constant *C;
302
303 llvm::SmallString<256> OutName;
304 llvm::raw_svector_ostream Out(OutName);
305 mangleCXXRtti(CGM.getMangleContext(), Ty, Out);
306
307 llvm::GlobalVariable *GV;
308 GV = CGM.getModule().getGlobalVariable(Out.str());
309 if (GV && !GV->isDeclaration())
310 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
311
312 std::vector<llvm::Constant *> info;
313
Mike Stump103a0842009-11-17 23:45:57 +0000314 C = BuildVtableRef(vtbl);
Mike Stump96b96d52009-11-17 23:11:22 +0000315 info.push_back(C);
316 info.push_back(BuildName(Ty));
Mike Stump4aaf79a2009-11-17 23:51:10 +0000317
Mike Stumpc5d2ed72009-11-18 03:21:29 +0000318 return finish(info, GV, Out.str(), false);
Mike Stumpdb72c892009-11-17 21:44:24 +0000319 }
320
Mike Stump3f75d552009-11-17 02:16:21 +0000321 llvm::Constant *BuildType(QualType Ty) {
322 const clang::Type &Type
323 = *CGM.getContext().getCanonicalType(Ty).getTypePtr();
324 switch (Type.getTypeClass()) {
325 default: {
Mike Stump3f75d552009-11-17 02:16:21 +0000326 assert(0 && "typeid expression");
Mike Stump3f75d552009-11-17 02:16:21 +0000327 return llvm::Constant::getNullValue(Int8PtrTy);
328 }
329
330 case Type::Builtin: {
331 // We expect all type_info objects for builtin types to be in the library.
332 return BuildTypeRef(Ty);
333 }
Mike Stump8f5e6772009-11-17 02:57:13 +0000334
335 case Type::Pointer: {
336 QualType PTy = Ty->getPointeeType();
337 Qualifiers Q = PTy.getQualifiers();
338 Q.removeConst();
339 // T* and const T* for all builtin types T are expected in the library.
340 if (isa<BuiltinType>(PTy) && Q.empty())
341 return BuildTypeRef(Ty);
342
Mike Stumpdb72c892009-11-17 21:44:24 +0000343 return BuildPointerType(Ty);
Mike Stump8f5e6772009-11-17 02:57:13 +0000344 }
Mike Stump6fdfea62009-11-17 22:33:00 +0000345 case Type::MemberPointer:
346 return BuildPointerType(Ty);
Mike Stump96b96d52009-11-17 23:11:22 +0000347 case Type::FunctionProto:
Mike Stump103a0842009-11-17 23:45:57 +0000348 case Type::FunctionNoProto:
349 return BuildSimpleType(Ty, "_ZTVN10__cxxabiv120__function_type_infoE");
350 case Type::ConstantArray:
351 case Type::IncompleteArray:
352 case Type::VariableArray:
353 case Type::Vector:
354 case Type::ExtVector:
355 return BuildSimpleType(Ty, "_ZTVN10__cxxabiv117__array_type_infoE");
356 case Type::Enum:
357 return BuildSimpleType(Ty, "_ZTVN10__cxxabiv116__enum_type_infoE");
Mike Stump3f75d552009-11-17 02:16:21 +0000358 }
359 }
Mike Stump14718422009-11-14 14:25:18 +0000360};
361
Mike Stumpf5b28692009-11-14 23:32:21 +0000362llvm::Constant *CodeGenModule::GenerateRttiRef(const CXXRecordDecl *RD) {
363 RttiBuilder b(*this);
364
365 return b.Buildclass_type_infoRef(RD);
366}
367
Anders Carlsson6ce51fd2009-10-10 20:49:04 +0000368llvm::Constant *CodeGenModule::GenerateRtti(const CXXRecordDecl *RD) {
Mike Stump14718422009-11-14 14:25:18 +0000369 RttiBuilder b(*this);
370
Mike Stumpf5b28692009-11-14 23:32:21 +0000371 return b.Buildclass_type_info(RD);
Anders Carlsson6ce51fd2009-10-10 20:49:04 +0000372}
Mike Stump3f75d552009-11-17 02:16:21 +0000373
374llvm::Constant *CodeGenModule::GenerateRttiNonClass(QualType Ty) {
375 RttiBuilder b(*this);
376
377 return b.BuildType(Ty);
378}