blob: c7044e59873c7c0daa98cbe51ab682b8a10a4bc7 [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 Stumpcbcd4e52009-11-14 23:32:21 +000014#include "clang/AST/RecordLayout.h"
Mike Stump61c38012009-11-17 21:44:24 +000015#include "CodeGenModule.h"
Anders Carlsson656e4c12009-10-10 20:49:04 +000016using namespace clang;
17using namespace CodeGen;
18
Mike Stump2b1bf312009-11-14 14:25:18 +000019class RttiBuilder {
20 CodeGenModule &CGM; // Per-module state.
21 llvm::LLVMContext &VMContext;
22 const llvm::Type *Int8PtrTy;
Mike Stumpa8285a82009-11-15 03:28:10 +000023 llvm::SmallSet<const CXXRecordDecl *, 16> SeenVBase;
24 llvm::SmallSet<const CXXRecordDecl *, 32> SeenBase;
Mike Stump2b1bf312009-11-14 14:25:18 +000025public:
26 RttiBuilder(CodeGenModule &cgm)
27 : CGM(cgm), VMContext(cgm.getModule().getContext()),
28 Int8PtrTy(llvm::Type::getInt8PtrTy(VMContext)) { }
29
Mike Stumpcbcd4e52009-11-14 23:32:21 +000030 /// BuildVtableRef - Build a reference to a vtable.
31 llvm::Constant *BuildVtableRef(const char *Name) {
32 // Build a descriptor for Name
Mike Stumpc7a05bd2009-11-14 15:55:18 +000033 llvm::Constant *GV = CGM.getModule().getGlobalVariable(Name);
34 if (GV)
35 GV = llvm::ConstantExpr::getBitCast(GV,
36 llvm::PointerType::get(Int8PtrTy, 0));
37 else {
38 llvm::GlobalVariable::LinkageTypes linktype;
39 linktype = llvm::GlobalValue::ExternalLinkage;
40 GV = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy,
41 true, linktype, 0, Name);
Mike Stumpcbcd4e52009-11-14 23:32:21 +000042 }
Mike Stumpc7a05bd2009-11-14 15:55:18 +000043 llvm::Constant *C;
44 C = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 2);
45 C = llvm::ConstantExpr::getInBoundsGetElementPtr(GV, &C, 1);
46 return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
47 }
Mike Stumpcbcd4e52009-11-14 23:32:21 +000048
Mike Stump61c38012009-11-17 21:44:24 +000049 llvm::Constant *BuildName(QualType Ty) {
Mike Stump2b1bf312009-11-14 14:25:18 +000050 llvm::SmallString<256> OutName;
51 llvm::raw_svector_ostream Out(OutName);
Mike Stump61c38012009-11-17 21:44:24 +000052 mangleCXXRttiName(CGM.getMangleContext(), Ty, Out);
Mike Stumpcbcd4e52009-11-14 23:32:21 +000053
Mike Stump2b1bf312009-11-14 14:25:18 +000054 llvm::GlobalVariable::LinkageTypes linktype;
55 linktype = llvm::GlobalValue::LinkOnceODRLinkage;
56
57 llvm::Constant *C;
58 C = llvm::ConstantArray::get(VMContext, Out.str().substr(4));
Mike Stumpcbcd4e52009-11-14 23:32:21 +000059
Mike Stump2b1bf312009-11-14 14:25:18 +000060 llvm::Constant *s = new llvm::GlobalVariable(CGM.getModule(), C->getType(),
61 true, linktype, C,
62 Out.str());
63 s = llvm::ConstantExpr::getBitCast(s, Int8PtrTy);
64 return s;
65 };
Mike Stumpc7a05bd2009-11-14 15:55:18 +000066
Mike Stumpcbcd4e52009-11-14 23:32:21 +000067 /// - BuildFlags - Build a psABI __flags value for __vmi_class_type_info.
68 llvm::Constant *BuildFlags(int f) {
69 return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), f);
70 }
71
72 /// BuildBaseCount - Build a psABI __base_count value for
73 /// __vmi_class_type_info.
74 llvm::Constant *BuildBaseCount(unsigned c) {
75 return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), c);
76 }
77
Mike Stumpea2c0b52009-11-17 02:16:21 +000078 llvm::Constant *BuildTypeRef(QualType Ty) {
Mike Stumpc7a05bd2009-11-14 15:55:18 +000079 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Mike Stumpcbcd4e52009-11-14 23:32:21 +000080 llvm::Constant *C;
Mike Stumpc7a05bd2009-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 Stumpea2c0b52009-11-17 02:16:21 +000087 mangleCXXRtti(CGM.getMangleContext(), Ty, Out);
Mike Stumpcbcd4e52009-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 Stumpea2c0b52009-11-17 02:16:21 +0000101 llvm::Constant *Buildclass_type_infoRef(const CXXRecordDecl *RD) {
102 return BuildTypeRef(CGM.getContext().getTagDeclType(RD));
103 }
104
Mike Stumpa8285a82009-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 Stumpcbcd4e52009-11-14 23:32:21 +0000146 llvm::Constant *Buildclass_type_info(const CXXRecordDecl *RD) {
147 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
148 llvm::Constant *C;
149
150 if (!CGM.getContext().getLangOptions().Rtti)
151 return llvm::Constant::getNullValue(Int8PtrTy);
152
153 llvm::SmallString<256> OutName;
154 llvm::raw_svector_ostream Out(OutName);
155 mangleCXXRtti(CGM.getMangleContext(), CGM.getContext().getTagDeclType(RD),
156 Out);
157
158 llvm::GlobalVariable *GV;
159 GV = CGM.getModule().getGlobalVariable(Out.str());
160 if (GV && !GV->isDeclaration())
161 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
162
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000163 llvm::GlobalVariable::LinkageTypes linktype;
164 linktype = llvm::GlobalValue::LinkOnceODRLinkage;
165 std::vector<llvm::Constant *> info;
166
Mike Stumpa8285a82009-11-15 03:28:10 +0000167 bool simple = false;
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000168 if (RD->getNumBases() == 0)
169 C = BuildVtableRef("_ZTVN10__cxxabiv117__class_type_infoE");
Mike Stumpa8285a82009-11-15 03:28:10 +0000170 else if (SimpleInheritance(RD)) {
171 simple = true;
172 C = BuildVtableRef("_ZTVN10__cxxabiv120__si_class_type_infoE");
173 } else
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000174 C = BuildVtableRef("_ZTVN10__cxxabiv121__vmi_class_type_infoE");
175 info.push_back(C);
Mike Stump61c38012009-11-17 21:44:24 +0000176 info.push_back(BuildName(CGM.getContext().getTagDeclType(RD)));
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000177
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000178 // If we have no bases, there are no more fields.
179 if (RD->getNumBases()) {
Mike Stumpa8285a82009-11-15 03:28:10 +0000180 if (!simple) {
181 info.push_back(BuildFlags(CalculateFlags(RD)));
182 info.push_back(BuildBaseCount(RD->getNumBases()));
183 }
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000184
185 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
186 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
187 e = RD->bases_end(); i != e; ++i) {
188 const CXXRecordDecl *Base =
189 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
Mike Stumpa8285a82009-11-15 03:28:10 +0000190 info.push_back(CGM.GenerateRttiRef(Base));
191 if (simple)
192 break;
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000193 int64_t offset;
194 if (!i->isVirtual())
Mike Stumpa8285a82009-11-15 03:28:10 +0000195 offset = Layout.getBaseClassOffset(Base)/8;
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000196 else
197 offset = CGM.getVtableInfo().getVirtualBaseOffsetIndex(RD, Base);
198 offset <<= 8;
199 // Now set the flags.
200 offset += i->isVirtual() ? 1 : 0;;
201 offset += i->getAccessSpecifier() == AS_public ? 2 : 0;
202 const llvm::Type *LongTy =
203 CGM.getTypes().ConvertType(CGM.getContext().LongTy);
204 C = llvm::ConstantInt::get(LongTy, offset);
205 info.push_back(C);
206 }
207 }
208
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000209 C = llvm::ConstantStruct::get(VMContext, &info[0], info.size(), false);
210
211 if (GV == 0)
212 GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, linktype,
213 C, Out.str());
214 else {
215 llvm::GlobalVariable *OGV = GV;
216 GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, linktype,
217 C, Out.str());
218 GV->takeName(OGV);
219 llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV, OGV->getType());
220 OGV->replaceAllUsesWith(NewPtr);
221 OGV->eraseFromParent();
222 }
223 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
224
225#if 0
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000226 llvm::ArrayType *type = llvm::ArrayType::get(Int8PtrTy, info.size());
227 C = llvm::ConstantArray::get(type, info);
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000228 llvm::Constant *Rtti =
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000229 new llvm::GlobalVariable(CGM.getModule(), type, true, linktype, C,
230 Out.str());
231 Rtti = llvm::ConstantExpr::getBitCast(Rtti, Int8PtrTy);
232 return Rtti;
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000233#endif
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000234 }
Mike Stumpea2c0b52009-11-17 02:16:21 +0000235
Mike Stump61c38012009-11-17 21:44:24 +0000236 /// - BuildFlags - Build a __flags value for __pbase_type_info.
237 llvm::Constant *BuildInt(int f) {
238 return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), f);
239 }
240
241 llvm::Constant *BuildType2(QualType Ty) {
242 if (const RecordType *RT = Ty.getTypePtr()->getAs<RecordType>())
243 if (const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()))
244 return Buildclass_type_info(RD);
245 return BuildType(Ty);
246 }
247
248 llvm::Constant *BuildPointerType(QualType Ty) {
249 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
250 llvm::Constant *C;
251
252 llvm::SmallString<256> OutName;
253 llvm::raw_svector_ostream Out(OutName);
254 mangleCXXRtti(CGM.getMangleContext(), Ty, Out);
255
256 llvm::GlobalVariable *GV;
257 GV = CGM.getModule().getGlobalVariable(Out.str());
258 if (GV && !GV->isDeclaration())
259 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
260
261 llvm::GlobalVariable::LinkageTypes linktype;
262 linktype = llvm::GlobalValue::LinkOnceODRLinkage;
263 std::vector<llvm::Constant *> info;
264
265 QualType PTy = Ty->getPointeeType();
266 // FIXME: ptr-mem data
267 QualType BTy;
268 // FIXME: ptr-mem data
269 bool PtrMem = false;
270
271 if (PtrMem)
272 C = BuildVtableRef("_ZTVN10__cxxabiv129__pointer_to_member_type_infoE");
273 else
274 C = BuildVtableRef("_ZTVN10__cxxabiv119__pointer_type_infoE");
275 info.push_back(C);
276 info.push_back(BuildName(Ty));
277 Qualifiers Q = PTy.getQualifiers();
278 PTy = CGM.getContext().getCanonicalType(PTy).getUnqualifiedType();
279 int flags = 0;
280 flags += Q.hasConst() ? 0x1 : 0;
281 flags += Q.hasVolatile() ? 0x2 : 0;
282 flags += Q.hasRestrict() ? 0x4 : 0;
283 flags += Ty.getTypePtr()->isIncompleteType() ? 0x8 : 0;
284 if (PtrMem && BTy.getTypePtr()->isIncompleteType())
285 flags += 0x10;
286
287 info.push_back(BuildInt(flags));
288 info.push_back(BuildInt(0));
289 info.push_back(BuildType2(PTy));
290
291 if (PtrMem)
292 info.push_back(BuildType2(BTy));
293
294 C = llvm::ConstantStruct::get(VMContext, &info[0], info.size(), false);
295
296 if (GV == 0)
297 GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
298 linktype, C, Out.str());
299 else {
300 llvm::GlobalVariable *OGV = GV;
301 GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
302 linktype, C, Out.str());
303 GV->takeName(OGV);
304 llvm::Constant *NewPtr
305 = llvm::ConstantExpr::getBitCast(GV, OGV->getType());
306 OGV->replaceAllUsesWith(NewPtr);
307 OGV->eraseFromParent();
308 }
309 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
310 }
311
Mike Stumpea2c0b52009-11-17 02:16:21 +0000312 llvm::Constant *BuildType(QualType Ty) {
313 const clang::Type &Type
314 = *CGM.getContext().getCanonicalType(Ty).getTypePtr();
315 switch (Type.getTypeClass()) {
316 default: {
317 // FIXME: Add all the missing types, such as pointer, array...
318 assert(0 && "typeid expression");
319 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
320 return llvm::Constant::getNullValue(Int8PtrTy);
321 }
322
323 case Type::Builtin: {
324 // We expect all type_info objects for builtin types to be in the library.
325 return BuildTypeRef(Ty);
326 }
Mike Stump21f5d5d2009-11-17 02:57:13 +0000327
328 case Type::Pointer: {
329 QualType PTy = Ty->getPointeeType();
330 Qualifiers Q = PTy.getQualifiers();
331 Q.removeConst();
332 // T* and const T* for all builtin types T are expected in the library.
333 if (isa<BuiltinType>(PTy) && Q.empty())
334 return BuildTypeRef(Ty);
335
Mike Stump61c38012009-11-17 21:44:24 +0000336 return BuildPointerType(Ty);
Mike Stump21f5d5d2009-11-17 02:57:13 +0000337 }
Mike Stumpea2c0b52009-11-17 02:16:21 +0000338 }
339 }
Mike Stump2b1bf312009-11-14 14:25:18 +0000340};
341
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000342llvm::Constant *CodeGenModule::GenerateRttiRef(const CXXRecordDecl *RD) {
343 RttiBuilder b(*this);
344
345 return b.Buildclass_type_infoRef(RD);
346}
347
Anders Carlsson656e4c12009-10-10 20:49:04 +0000348llvm::Constant *CodeGenModule::GenerateRtti(const CXXRecordDecl *RD) {
Mike Stump2b1bf312009-11-14 14:25:18 +0000349 RttiBuilder b(*this);
350
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000351 return b.Buildclass_type_info(RD);
Anders Carlsson656e4c12009-10-10 20:49:04 +0000352}
Mike Stumpea2c0b52009-11-17 02:16:21 +0000353
354llvm::Constant *CodeGenModule::GenerateRttiNonClass(QualType Ty) {
355 RttiBuilder b(*this);
356
357 return b.BuildType(Ty);
358}