blob: de26f543f6349ba23a08f3f6ec0598a89aec24ec [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
14#include "CodeGenModule.h"
Mike Stumpcbcd4e52009-11-14 23:32:21 +000015#include "clang/AST/RecordLayout.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 Stump2b1bf312009-11-14 14:25:18 +000049 llvm::Constant *BuildName(const CXXRecordDecl *RD) {
50 llvm::SmallString<256> OutName;
51 llvm::raw_svector_ostream Out(OutName);
52 mangleCXXRttiName(CGM.getMangleContext(),
53 CGM.getContext().getTagDeclType(RD), 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 Stump2b1bf312009-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 Stumpc7a05bd2009-11-14 15:55:18 +000067
Mike Stumpcbcd4e52009-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 Stumpea2c0b52009-11-17 02:16:21 +000079 llvm::Constant *BuildTypeRef(QualType Ty) {
Mike Stumpc7a05bd2009-11-14 15:55:18 +000080 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Mike Stumpcbcd4e52009-11-14 23:32:21 +000081 llvm::Constant *C;
Mike Stumpc7a05bd2009-11-14 15:55:18 +000082
83 if (!CGM.getContext().getLangOptions().Rtti)
84 return llvm::Constant::getNullValue(Int8PtrTy);
85
86 llvm::SmallString<256> OutName;
87 llvm::raw_svector_ostream Out(OutName);
Mike Stumpea2c0b52009-11-17 02:16:21 +000088 mangleCXXRtti(CGM.getMangleContext(), Ty, Out);
Mike Stumpcbcd4e52009-11-14 23:32:21 +000089
90 C = CGM.getModule().getGlobalVariable(Out.str());
91 if (C)
92 return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
93
94 llvm::GlobalVariable::LinkageTypes linktype;
95 linktype = llvm::GlobalValue::ExternalLinkage;;
96
97 C = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy, true, linktype,
98 0, Out.str());
99 return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
100 }
101
Mike Stumpea2c0b52009-11-17 02:16:21 +0000102 llvm::Constant *Buildclass_type_infoRef(const CXXRecordDecl *RD) {
103 return BuildTypeRef(CGM.getContext().getTagDeclType(RD));
104 }
105
Mike Stumpa8285a82009-11-15 03:28:10 +0000106 /// CalculateFlags - Calculate the flags for the __vmi_class_type_info
107 /// datastructure. 1 for non-diamond repeated inheritance, 2 for a dimond
108 /// shaped class.
109 int CalculateFlags(const CXXRecordDecl*RD) {
110 int flags = 0;
111 if (SeenBase.count(RD))
112 flags |= 1;
113 else
114 SeenBase.insert(RD);
115 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
116 e = RD->bases_end(); i != e; ++i) {
117 const CXXRecordDecl *Base =
118 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
119 if (i->isVirtual()) {
120 if (SeenVBase.count(Base))
121 flags |= 2;
122 else
123 SeenVBase.insert(Base);
124 }
125 flags |= CalculateFlags(Base);
126 }
127 return flags;
128 }
129
130 bool SimpleInheritance(const CXXRecordDecl *RD) {
131 if (RD->getNumBases() != 1)
132 return false;
133 CXXRecordDecl::base_class_const_iterator i = RD->bases_begin();
134 if (i->isVirtual())
135 return false;
136 if (i->getAccessSpecifier() != AS_public)
137 return false;
138
139 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
140 const CXXRecordDecl *Base =
141 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
142 if (Layout.getBaseClassOffset(Base) != 0)
143 return false;
144 return true;
145 }
146
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000147 llvm::Constant *Buildclass_type_info(const CXXRecordDecl *RD) {
148 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
149 llvm::Constant *C;
150
151 if (!CGM.getContext().getLangOptions().Rtti)
152 return llvm::Constant::getNullValue(Int8PtrTy);
153
154 llvm::SmallString<256> OutName;
155 llvm::raw_svector_ostream Out(OutName);
156 mangleCXXRtti(CGM.getMangleContext(), CGM.getContext().getTagDeclType(RD),
157 Out);
158
159 llvm::GlobalVariable *GV;
160 GV = CGM.getModule().getGlobalVariable(Out.str());
161 if (GV && !GV->isDeclaration())
162 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
163
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000164 llvm::GlobalVariable::LinkageTypes linktype;
165 linktype = llvm::GlobalValue::LinkOnceODRLinkage;
166 std::vector<llvm::Constant *> info;
167
Mike Stumpa8285a82009-11-15 03:28:10 +0000168 bool simple = false;
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000169 if (RD->getNumBases() == 0)
170 C = BuildVtableRef("_ZTVN10__cxxabiv117__class_type_infoE");
Mike Stumpa8285a82009-11-15 03:28:10 +0000171 else if (SimpleInheritance(RD)) {
172 simple = true;
173 C = BuildVtableRef("_ZTVN10__cxxabiv120__si_class_type_infoE");
174 } else
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000175 C = BuildVtableRef("_ZTVN10__cxxabiv121__vmi_class_type_infoE");
176 info.push_back(C);
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000177 info.push_back(BuildName(RD));
178
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000179 // If we have no bases, there are no more fields.
180 if (RD->getNumBases()) {
Mike Stumpa8285a82009-11-15 03:28:10 +0000181 if (!simple) {
182 info.push_back(BuildFlags(CalculateFlags(RD)));
183 info.push_back(BuildBaseCount(RD->getNumBases()));
184 }
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000185
186 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
187 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
188 e = RD->bases_end(); i != e; ++i) {
189 const CXXRecordDecl *Base =
190 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
Mike Stumpa8285a82009-11-15 03:28:10 +0000191 info.push_back(CGM.GenerateRttiRef(Base));
192 if (simple)
193 break;
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000194 int64_t offset;
195 if (!i->isVirtual())
Mike Stumpa8285a82009-11-15 03:28:10 +0000196 offset = Layout.getBaseClassOffset(Base)/8;
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000197 else
198 offset = CGM.getVtableInfo().getVirtualBaseOffsetIndex(RD, Base);
199 offset <<= 8;
200 // Now set the flags.
201 offset += i->isVirtual() ? 1 : 0;;
202 offset += i->getAccessSpecifier() == AS_public ? 2 : 0;
203 const llvm::Type *LongTy =
204 CGM.getTypes().ConvertType(CGM.getContext().LongTy);
205 C = llvm::ConstantInt::get(LongTy, offset);
206 info.push_back(C);
207 }
208 }
209
210 std::vector<const llvm::Type *> Types(info.size());
211 for (unsigned i=0; i<info.size(); ++i)
212 Types[i] = info[i]->getType();
213 // llvm::StructType *Ty = llvm::StructType::get(VMContext, Types, true);
214 C = llvm::ConstantStruct::get(VMContext, &info[0], info.size(), false);
215
216 if (GV == 0)
217 GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, linktype,
218 C, Out.str());
219 else {
220 llvm::GlobalVariable *OGV = GV;
221 GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, linktype,
222 C, Out.str());
223 GV->takeName(OGV);
224 llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV, OGV->getType());
225 OGV->replaceAllUsesWith(NewPtr);
226 OGV->eraseFromParent();
227 }
228 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
229
230#if 0
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000231 llvm::ArrayType *type = llvm::ArrayType::get(Int8PtrTy, info.size());
232 C = llvm::ConstantArray::get(type, info);
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000233 llvm::Constant *Rtti =
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000234 new llvm::GlobalVariable(CGM.getModule(), type, true, linktype, C,
235 Out.str());
236 Rtti = llvm::ConstantExpr::getBitCast(Rtti, Int8PtrTy);
237 return Rtti;
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000238#endif
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000239 }
Mike Stumpea2c0b52009-11-17 02:16:21 +0000240
241 llvm::Constant *BuildType(QualType Ty) {
242 const clang::Type &Type
243 = *CGM.getContext().getCanonicalType(Ty).getTypePtr();
244 switch (Type.getTypeClass()) {
245 default: {
246 // FIXME: Add all the missing types, such as pointer, array...
247 assert(0 && "typeid expression");
248 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
249 return llvm::Constant::getNullValue(Int8PtrTy);
250 }
251
252 case Type::Builtin: {
253 // We expect all type_info objects for builtin types to be in the library.
254 return BuildTypeRef(Ty);
255 }
Mike Stump21f5d5d2009-11-17 02:57:13 +0000256
257 case Type::Pointer: {
258 QualType PTy = Ty->getPointeeType();
259 Qualifiers Q = PTy.getQualifiers();
260 Q.removeConst();
261 // T* and const T* for all builtin types T are expected in the library.
262 if (isa<BuiltinType>(PTy) && Q.empty())
263 return BuildTypeRef(Ty);
264
265 assert(0 && "typeid expression");
266 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
267 return llvm::Constant::getNullValue(Int8PtrTy);
268 }
Mike Stumpea2c0b52009-11-17 02:16:21 +0000269 }
270 }
Mike Stump2b1bf312009-11-14 14:25:18 +0000271};
272
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000273llvm::Constant *CodeGenModule::GenerateRttiRef(const CXXRecordDecl *RD) {
274 RttiBuilder b(*this);
275
276 return b.Buildclass_type_infoRef(RD);
277}
278
Anders Carlsson656e4c12009-10-10 20:49:04 +0000279llvm::Constant *CodeGenModule::GenerateRtti(const CXXRecordDecl *RD) {
Mike Stump2b1bf312009-11-14 14:25:18 +0000280 RttiBuilder b(*this);
281
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000282 return b.Buildclass_type_info(RD);
Anders Carlsson656e4c12009-10-10 20:49:04 +0000283}
Mike Stumpea2c0b52009-11-17 02:16:21 +0000284
285llvm::Constant *CodeGenModule::GenerateRttiNonClass(QualType Ty) {
286 RttiBuilder b(*this);
287
288 return b.BuildType(Ty);
289}