blob: 11a8ea7e7cd50ff4aba8cb744d3df406658cefd6 [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;
23public:
24 RttiBuilder(CodeGenModule &cgm)
25 : CGM(cgm), VMContext(cgm.getModule().getContext()),
26 Int8PtrTy(llvm::Type::getInt8PtrTy(VMContext)) { }
27
Mike Stumpcbcd4e52009-11-14 23:32:21 +000028 /// BuildVtableRef - Build a reference to a vtable.
29 llvm::Constant *BuildVtableRef(const char *Name) {
30 // Build a descriptor for Name
Mike Stumpc7a05bd2009-11-14 15:55:18 +000031 llvm::Constant *GV = CGM.getModule().getGlobalVariable(Name);
32 if (GV)
33 GV = llvm::ConstantExpr::getBitCast(GV,
34 llvm::PointerType::get(Int8PtrTy, 0));
35 else {
36 llvm::GlobalVariable::LinkageTypes linktype;
37 linktype = llvm::GlobalValue::ExternalLinkage;
38 GV = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy,
39 true, linktype, 0, Name);
Mike Stumpcbcd4e52009-11-14 23:32:21 +000040 }
Mike Stumpc7a05bd2009-11-14 15:55:18 +000041 llvm::Constant *C;
42 C = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 2);
43 C = llvm::ConstantExpr::getInBoundsGetElementPtr(GV, &C, 1);
44 return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
45 }
Mike Stumpcbcd4e52009-11-14 23:32:21 +000046
Mike Stump2b1bf312009-11-14 14:25:18 +000047 llvm::Constant *BuildName(const CXXRecordDecl *RD) {
48 llvm::SmallString<256> OutName;
49 llvm::raw_svector_ostream Out(OutName);
50 mangleCXXRttiName(CGM.getMangleContext(),
51 CGM.getContext().getTagDeclType(RD), Out);
Mike Stumpcbcd4e52009-11-14 23:32:21 +000052
Mike Stump2b1bf312009-11-14 14:25:18 +000053 llvm::GlobalVariable::LinkageTypes linktype;
54 linktype = llvm::GlobalValue::LinkOnceODRLinkage;
55
56 llvm::Constant *C;
57 C = llvm::ConstantArray::get(VMContext, Out.str().substr(4));
Mike Stumpcbcd4e52009-11-14 23:32:21 +000058
Mike Stump2b1bf312009-11-14 14:25:18 +000059 llvm::Constant *s = new llvm::GlobalVariable(CGM.getModule(), C->getType(),
60 true, linktype, C,
61 Out.str());
62 s = llvm::ConstantExpr::getBitCast(s, Int8PtrTy);
63 return s;
64 };
Mike Stumpc7a05bd2009-11-14 15:55:18 +000065
Mike Stumpcbcd4e52009-11-14 23:32:21 +000066 /// - BuildFlags - Build a psABI __flags value for __vmi_class_type_info.
67 llvm::Constant *BuildFlags(int f) {
68 return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), f);
69 }
70
71 /// BuildBaseCount - Build a psABI __base_count value for
72 /// __vmi_class_type_info.
73 llvm::Constant *BuildBaseCount(unsigned c) {
74 return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), c);
75 }
76
77 llvm::Constant *Buildclass_type_infoRef(const CXXRecordDecl *RD) {
Mike Stumpc7a05bd2009-11-14 15:55:18 +000078 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Mike Stumpcbcd4e52009-11-14 23:32:21 +000079 llvm::Constant *C;
Mike Stumpc7a05bd2009-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);
86 mangleCXXRtti(CGM.getMangleContext(), CGM.getContext().getTagDeclType(RD),
87 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
101 llvm::Constant *Buildclass_type_info(const CXXRecordDecl *RD) {
102 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
103 llvm::Constant *C;
104
105 if (!CGM.getContext().getLangOptions().Rtti)
106 return llvm::Constant::getNullValue(Int8PtrTy);
107
108 llvm::SmallString<256> OutName;
109 llvm::raw_svector_ostream Out(OutName);
110 mangleCXXRtti(CGM.getMangleContext(), CGM.getContext().getTagDeclType(RD),
111 Out);
112
113 llvm::GlobalVariable *GV;
114 GV = CGM.getModule().getGlobalVariable(Out.str());
115 if (GV && !GV->isDeclaration())
116 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
117
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000118 llvm::GlobalVariable::LinkageTypes linktype;
119 linktype = llvm::GlobalValue::LinkOnceODRLinkage;
120 std::vector<llvm::Constant *> info;
121
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000122 if (RD->getNumBases() == 0)
123 C = BuildVtableRef("_ZTVN10__cxxabiv117__class_type_infoE");
124 // FIXME: Add si_class_type_info optimization
125 else
126 C = BuildVtableRef("_ZTVN10__cxxabiv121__vmi_class_type_infoE");
127 info.push_back(C);
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000128 info.push_back(BuildName(RD));
129
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000130 // If we have no bases, there are no more fields.
131 if (RD->getNumBases()) {
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000132
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000133 // FIXME: Calculate is_diamond and non-diamond repeated inheritance, 3 is
134 // conservative.
135 info.push_back(BuildFlags(3));
136 info.push_back(BuildBaseCount(RD->getNumBases()));
137
138 const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
139 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
140 e = RD->bases_end(); i != e; ++i) {
141 const CXXRecordDecl *Base =
142 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
143 info.push_back(CGM.GenerateRtti(Base));
144 int64_t offset;
145 if (!i->isVirtual())
146 offset = Layout.getBaseClassOffset(Base);
147 else
148 offset = CGM.getVtableInfo().getVirtualBaseOffsetIndex(RD, Base);
149 offset <<= 8;
150 // Now set the flags.
151 offset += i->isVirtual() ? 1 : 0;;
152 offset += i->getAccessSpecifier() == AS_public ? 2 : 0;
153 const llvm::Type *LongTy =
154 CGM.getTypes().ConvertType(CGM.getContext().LongTy);
155 C = llvm::ConstantInt::get(LongTy, offset);
156 info.push_back(C);
157 }
158 }
159
160 std::vector<const llvm::Type *> Types(info.size());
161 for (unsigned i=0; i<info.size(); ++i)
162 Types[i] = info[i]->getType();
163 // llvm::StructType *Ty = llvm::StructType::get(VMContext, Types, true);
164 C = llvm::ConstantStruct::get(VMContext, &info[0], info.size(), false);
165
166 if (GV == 0)
167 GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, linktype,
168 C, Out.str());
169 else {
170 llvm::GlobalVariable *OGV = GV;
171 GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, linktype,
172 C, Out.str());
173 GV->takeName(OGV);
174 llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV, OGV->getType());
175 OGV->replaceAllUsesWith(NewPtr);
176 OGV->eraseFromParent();
177 }
178 return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
179
180#if 0
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000181 llvm::ArrayType *type = llvm::ArrayType::get(Int8PtrTy, info.size());
182 C = llvm::ConstantArray::get(type, info);
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000183 llvm::Constant *Rtti =
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000184 new llvm::GlobalVariable(CGM.getModule(), type, true, linktype, C,
185 Out.str());
186 Rtti = llvm::ConstantExpr::getBitCast(Rtti, Int8PtrTy);
187 return Rtti;
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000188#endif
Mike Stumpc7a05bd2009-11-14 15:55:18 +0000189 }
Mike Stump2b1bf312009-11-14 14:25:18 +0000190};
191
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000192llvm::Constant *CodeGenModule::GenerateRttiRef(const CXXRecordDecl *RD) {
193 RttiBuilder b(*this);
194
195 return b.Buildclass_type_infoRef(RD);
196}
197
Anders Carlsson656e4c12009-10-10 20:49:04 +0000198llvm::Constant *CodeGenModule::GenerateRtti(const CXXRecordDecl *RD) {
Mike Stump2b1bf312009-11-14 14:25:18 +0000199 RttiBuilder b(*this);
200
Mike Stumpcbcd4e52009-11-14 23:32:21 +0000201 return b.Buildclass_type_info(RD);
Anders Carlsson656e4c12009-10-10 20:49:04 +0000202}