blob: 46d7b67efb22ad67610b844a2cf2b30219fb289c [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 Stumpf5b28692009-11-14 23:32:21 +000014#include "clang/AST/RecordLayout.h"
Mike Stumpdb72c892009-11-17 21:44:24 +000015#include "CodeGenModule.h"
Anders Carlsson6ce51fd2009-10-10 20:49:04 +000016using namespace clang;
17using namespace CodeGen;
18
Mike Stump14718422009-11-14 14:25:18 +000019class RttiBuilder {
20 CodeGenModule &CGM; // Per-module state.
21 llvm::LLVMContext &VMContext;
22 const llvm::Type *Int8PtrTy;
Mike Stump4c808df2009-11-15 03:28:10 +000023 llvm::SmallSet<const CXXRecordDecl *, 16> SeenVBase;
24 llvm::SmallSet<const CXXRecordDecl *, 32> SeenBase;
Mike Stump14718422009-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 Stumpf5b28692009-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 Stump1acec6a2009-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 Stumpf5b28692009-11-14 23:32:21 +000042 }
Mike Stump1acec6a2009-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 Stumpf5b28692009-11-14 23:32:21 +000048
Mike Stumpdb72c892009-11-17 21:44:24 +000049 llvm::Constant *BuildName(QualType Ty) {
Mike Stump14718422009-11-14 14:25:18 +000050 llvm::SmallString<256> OutName;
51 llvm::raw_svector_ostream Out(OutName);
Mike Stumpdb72c892009-11-17 21:44:24 +000052 mangleCXXRttiName(CGM.getMangleContext(), Ty, Out);
Mike Stumpf5b28692009-11-14 23:32:21 +000053
Mike Stump14718422009-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 Stumpf5b28692009-11-14 23:32:21 +000059
Mike Stump14718422009-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 Stump1acec6a2009-11-14 15:55:18 +000066
Mike Stumpf5b28692009-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 Stump3f75d552009-11-17 02:16:21 +000078 llvm::Constant *BuildTypeRef(QualType Ty) {
Mike Stumpf5b28692009-11-14 23:32:21 +000079 llvm::Constant *C;
Mike Stump1acec6a2009-11-14 15:55:18 +000080
81 if (!CGM.getContext().getLangOptions().Rtti)
82 return llvm::Constant::getNullValue(Int8PtrTy);
83
84 llvm::SmallString<256> OutName;
85 llvm::raw_svector_ostream Out(OutName);
Mike Stump3f75d552009-11-17 02:16:21 +000086 mangleCXXRtti(CGM.getMangleContext(), Ty, Out);
Mike Stumpf5b28692009-11-14 23:32:21 +000087
88 C = CGM.getModule().getGlobalVariable(Out.str());
89 if (C)
90 return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
91
92 llvm::GlobalVariable::LinkageTypes linktype;
93 linktype = llvm::GlobalValue::ExternalLinkage;;
94
95 C = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy, true, linktype,
96 0, Out.str());
97 return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
98 }
99
Mike Stump3f75d552009-11-17 02:16:21 +0000100 llvm::Constant *Buildclass_type_infoRef(const CXXRecordDecl *RD) {
101 return BuildTypeRef(CGM.getContext().getTagDeclType(RD));
102 }
103
Mike Stump4c808df2009-11-15 03:28:10 +0000104 /// CalculateFlags - Calculate the flags for the __vmi_class_type_info
105 /// datastructure. 1 for non-diamond repeated inheritance, 2 for a dimond
106 /// shaped class.
107 int CalculateFlags(const CXXRecordDecl*RD) {
108 int flags = 0;
109 if (SeenBase.count(RD))
110 flags |= 1;
111 else
112 SeenBase.insert(RD);
113 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
114 e = RD->bases_end(); i != e; ++i) {
115 const CXXRecordDecl *Base =
116 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
117 if (i->isVirtual()) {
118 if (SeenVBase.count(Base))
119 flags |= 2;
120 else
121 SeenVBase.insert(Base);
122 }
123 flags |= CalculateFlags(Base);
124 }
125 return flags;
126 }
127
128 bool SimpleInheritance(const CXXRecordDecl *RD) {
129 if (RD->getNumBases() != 1)
130 return false;
131 CXXRecordDecl::base_class_const_iterator i = RD->bases_begin();
132 if (i->isVirtual())
133 return false;
134 if (i->getAccessSpecifier() != AS_public)
135 return false;
136
137 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
138 const CXXRecordDecl *Base =
139 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
140 if (Layout.getBaseClassOffset(Base) != 0)
141 return false;
142 return true;
143 }
144
Mike Stump96b96d52009-11-17 23:11:22 +0000145 llvm::Constant *finish(std::vector<llvm::Constant *> &info,
146 llvm::GlobalVariable *GV,
147 llvm::StringRef Name) {
148 llvm::GlobalVariable::LinkageTypes linktype;
149 linktype = llvm::GlobalValue::LinkOnceODRLinkage;
Mike Stumpf5b28692009-11-14 23:32:21 +0000150
Mike Stump96b96d52009-11-17 23:11:22 +0000151 llvm::Constant *C;
152 C = llvm::ConstantStruct::get(VMContext, &info[0], info.size(), false);
153
154 if (GV == 0)
155 GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
156 linktype, C, Name);
157 else {
158 llvm::GlobalVariable *OGV = GV;
159 GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
160 linktype, C, Name);
161 GV->takeName(OGV);
162 llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV,
163 OGV->getType());
164 OGV->replaceAllUsesWith(NewPtr);
165 OGV->eraseFromParent();
166 }
167 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
168 }
169
170
171 llvm::Constant *Buildclass_type_info(const CXXRecordDecl *RD) {
Mike Stumpf5b28692009-11-14 23:32:21 +0000172 if (!CGM.getContext().getLangOptions().Rtti)
173 return llvm::Constant::getNullValue(Int8PtrTy);
174
Mike Stump96b96d52009-11-17 23:11:22 +0000175 llvm::Constant *C;
176
Mike Stumpf5b28692009-11-14 23:32:21 +0000177 llvm::SmallString<256> OutName;
178 llvm::raw_svector_ostream Out(OutName);
179 mangleCXXRtti(CGM.getMangleContext(), CGM.getContext().getTagDeclType(RD),
180 Out);
181
182 llvm::GlobalVariable *GV;
183 GV = CGM.getModule().getGlobalVariable(Out.str());
184 if (GV && !GV->isDeclaration())
185 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
186
Mike Stump1acec6a2009-11-14 15:55:18 +0000187 std::vector<llvm::Constant *> info;
188
Mike Stump4c808df2009-11-15 03:28:10 +0000189 bool simple = false;
Mike Stumpf5b28692009-11-14 23:32:21 +0000190 if (RD->getNumBases() == 0)
191 C = BuildVtableRef("_ZTVN10__cxxabiv117__class_type_infoE");
Mike Stump4c808df2009-11-15 03:28:10 +0000192 else if (SimpleInheritance(RD)) {
193 simple = true;
194 C = BuildVtableRef("_ZTVN10__cxxabiv120__si_class_type_infoE");
195 } else
Mike Stumpf5b28692009-11-14 23:32:21 +0000196 C = BuildVtableRef("_ZTVN10__cxxabiv121__vmi_class_type_infoE");
197 info.push_back(C);
Mike Stumpdb72c892009-11-17 21:44:24 +0000198 info.push_back(BuildName(CGM.getContext().getTagDeclType(RD)));
Mike Stump1acec6a2009-11-14 15:55:18 +0000199
Mike Stumpf5b28692009-11-14 23:32:21 +0000200 // If we have no bases, there are no more fields.
201 if (RD->getNumBases()) {
Mike Stump4c808df2009-11-15 03:28:10 +0000202 if (!simple) {
203 info.push_back(BuildFlags(CalculateFlags(RD)));
204 info.push_back(BuildBaseCount(RD->getNumBases()));
205 }
Mike Stumpf5b28692009-11-14 23:32:21 +0000206
207 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
208 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
209 e = RD->bases_end(); i != e; ++i) {
210 const CXXRecordDecl *Base =
211 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
Mike Stump4c808df2009-11-15 03:28:10 +0000212 info.push_back(CGM.GenerateRttiRef(Base));
213 if (simple)
214 break;
Mike Stumpf5b28692009-11-14 23:32:21 +0000215 int64_t offset;
216 if (!i->isVirtual())
Mike Stump4c808df2009-11-15 03:28:10 +0000217 offset = Layout.getBaseClassOffset(Base)/8;
Mike Stumpf5b28692009-11-14 23:32:21 +0000218 else
219 offset = CGM.getVtableInfo().getVirtualBaseOffsetIndex(RD, Base);
220 offset <<= 8;
221 // Now set the flags.
222 offset += i->isVirtual() ? 1 : 0;;
223 offset += i->getAccessSpecifier() == AS_public ? 2 : 0;
224 const llvm::Type *LongTy =
225 CGM.getTypes().ConvertType(CGM.getContext().LongTy);
226 C = llvm::ConstantInt::get(LongTy, offset);
227 info.push_back(C);
228 }
229 }
230
Mike Stump96b96d52009-11-17 23:11:22 +0000231 return finish(info, GV, Out.str());
Mike Stump1acec6a2009-11-14 15:55:18 +0000232 }
Mike Stump3f75d552009-11-17 02:16:21 +0000233
Mike Stumpdb72c892009-11-17 21:44:24 +0000234 /// - BuildFlags - Build a __flags value for __pbase_type_info.
235 llvm::Constant *BuildInt(int f) {
236 return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), f);
237 }
238
239 llvm::Constant *BuildType2(QualType Ty) {
240 if (const RecordType *RT = Ty.getTypePtr()->getAs<RecordType>())
241 if (const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()))
242 return Buildclass_type_info(RD);
243 return BuildType(Ty);
244 }
245
246 llvm::Constant *BuildPointerType(QualType Ty) {
Mike Stumpdb72c892009-11-17 21:44:24 +0000247 llvm::Constant *C;
248
249 llvm::SmallString<256> OutName;
250 llvm::raw_svector_ostream Out(OutName);
251 mangleCXXRtti(CGM.getMangleContext(), Ty, Out);
252
253 llvm::GlobalVariable *GV;
254 GV = CGM.getModule().getGlobalVariable(Out.str());
255 if (GV && !GV->isDeclaration())
256 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
257
258 llvm::GlobalVariable::LinkageTypes linktype;
259 linktype = llvm::GlobalValue::LinkOnceODRLinkage;
260 std::vector<llvm::Constant *> info;
261
262 QualType PTy = Ty->getPointeeType();
Mike Stumpdb72c892009-11-17 21:44:24 +0000263 QualType BTy;
Mike Stumpdb72c892009-11-17 21:44:24 +0000264 bool PtrMem = false;
Mike Stump6fdfea62009-11-17 22:33:00 +0000265 if (const MemberPointerType *MPT = dyn_cast<MemberPointerType>(Ty)) {
266 PtrMem = true;
267 BTy = QualType(MPT->getClass(), 0);
268 PTy = MPT->getPointeeType();
269 }
Mike Stumpdb72c892009-11-17 21:44:24 +0000270
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
Mike Stump96b96d52009-11-17 23:11:22 +0000294 return finish(info, GV, Out.str());
295 }
Mike Stumpdb72c892009-11-17 21:44:24 +0000296
Mike Stump96b96d52009-11-17 23:11:22 +0000297 llvm::Constant *BuildFunctionType(QualType Ty) {
298 llvm::Constant *C;
299
300 llvm::SmallString<256> OutName;
301 llvm::raw_svector_ostream Out(OutName);
302 mangleCXXRtti(CGM.getMangleContext(), Ty, Out);
303
304 llvm::GlobalVariable *GV;
305 GV = CGM.getModule().getGlobalVariable(Out.str());
306 if (GV && !GV->isDeclaration())
307 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
308
309 std::vector<llvm::Constant *> info;
310
311 QualType PTy = Ty->getPointeeType();
312 QualType BTy;
313 bool PtrMem = false;
314 if (const MemberPointerType *MPT = dyn_cast<MemberPointerType>(Ty)) {
315 PtrMem = true;
316 BTy = QualType(MPT->getClass(), 0);
317 PTy = MPT->getPointeeType();
Mike Stumpdb72c892009-11-17 21:44:24 +0000318 }
Mike Stump96b96d52009-11-17 23:11:22 +0000319
320 C = BuildVtableRef("_ZTVN10__cxxabiv120__function_type_infoE");
321 info.push_back(C);
322 info.push_back(BuildName(Ty));
323
324 return finish(info, GV, Out.str());
Mike Stumpdb72c892009-11-17 21:44:24 +0000325 }
326
Mike Stump3f75d552009-11-17 02:16:21 +0000327 llvm::Constant *BuildType(QualType Ty) {
328 const clang::Type &Type
329 = *CGM.getContext().getCanonicalType(Ty).getTypePtr();
330 switch (Type.getTypeClass()) {
331 default: {
Mike Stump96b96d52009-11-17 23:11:22 +0000332 // FIXME: Add all the missing types, such as array...
Mike Stump3f75d552009-11-17 02:16:21 +0000333 assert(0 && "typeid expression");
Mike Stump3f75d552009-11-17 02:16:21 +0000334 return llvm::Constant::getNullValue(Int8PtrTy);
335 }
336
337 case Type::Builtin: {
338 // We expect all type_info objects for builtin types to be in the library.
339 return BuildTypeRef(Ty);
340 }
Mike Stump8f5e6772009-11-17 02:57:13 +0000341
342 case Type::Pointer: {
343 QualType PTy = Ty->getPointeeType();
344 Qualifiers Q = PTy.getQualifiers();
345 Q.removeConst();
346 // T* and const T* for all builtin types T are expected in the library.
347 if (isa<BuiltinType>(PTy) && Q.empty())
348 return BuildTypeRef(Ty);
349
Mike Stumpdb72c892009-11-17 21:44:24 +0000350 return BuildPointerType(Ty);
Mike Stump8f5e6772009-11-17 02:57:13 +0000351 }
Mike Stump6fdfea62009-11-17 22:33:00 +0000352 case Type::MemberPointer:
353 return BuildPointerType(Ty);
Mike Stump96b96d52009-11-17 23:11:22 +0000354 case Type::FunctionProto:
355 return BuildFunctionType(Ty);
Mike Stump3f75d552009-11-17 02:16:21 +0000356 }
357 }
Mike Stump14718422009-11-14 14:25:18 +0000358};
359
Mike Stumpf5b28692009-11-14 23:32:21 +0000360llvm::Constant *CodeGenModule::GenerateRttiRef(const CXXRecordDecl *RD) {
361 RttiBuilder b(*this);
362
363 return b.Buildclass_type_infoRef(RD);
364}
365
Anders Carlsson6ce51fd2009-10-10 20:49:04 +0000366llvm::Constant *CodeGenModule::GenerateRtti(const CXXRecordDecl *RD) {
Mike Stump14718422009-11-14 14:25:18 +0000367 RttiBuilder b(*this);
368
Mike Stumpf5b28692009-11-14 23:32:21 +0000369 return b.Buildclass_type_info(RD);
Anders Carlsson6ce51fd2009-10-10 20:49:04 +0000370}
Mike Stump3f75d552009-11-17 02:16:21 +0000371
372llvm::Constant *CodeGenModule::GenerateRttiNonClass(QualType Ty) {
373 RttiBuilder b(*this);
374
375 return b.BuildType(Ty);
376}