blob: 3d76bcd9651706b08b21279623b0756ff6fae316 [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"
15using namespace clang;
16using namespace CodeGen;
17
Mike Stump2b1bf312009-11-14 14:25:18 +000018class RttiBuilder {
19 CodeGenModule &CGM; // Per-module state.
20 llvm::LLVMContext &VMContext;
21 const llvm::Type *Int8PtrTy;
22public:
23 RttiBuilder(CodeGenModule &cgm)
24 : CGM(cgm), VMContext(cgm.getModule().getContext()),
25 Int8PtrTy(llvm::Type::getInt8PtrTy(VMContext)) { }
26
Mike Stumpc7a05bd2009-11-14 15:55:18 +000027 llvm::Constant *Buildclass_type_infoDesc() {
28 // Build a descriptor for class_type_info.
29 llvm::StringRef Name = "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
30 llvm::Constant *GV = CGM.getModule().getGlobalVariable(Name);
31 if (GV)
32 GV = llvm::ConstantExpr::getBitCast(GV,
33 llvm::PointerType::get(Int8PtrTy, 0));
34 else {
35 llvm::GlobalVariable::LinkageTypes linktype;
36 linktype = llvm::GlobalValue::ExternalLinkage;
37 GV = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy,
38 true, linktype, 0, Name);
39 }
40 llvm::Constant *C;
41 C = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 2);
42 C = llvm::ConstantExpr::getInBoundsGetElementPtr(GV, &C, 1);
43 return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
44 }
45
Mike Stump2b1bf312009-11-14 14:25:18 +000046 llvm::Constant *BuildName(const CXXRecordDecl *RD) {
47 llvm::SmallString<256> OutName;
48 llvm::raw_svector_ostream Out(OutName);
49 mangleCXXRttiName(CGM.getMangleContext(),
50 CGM.getContext().getTagDeclType(RD), Out);
51
52 llvm::GlobalVariable::LinkageTypes linktype;
53 linktype = llvm::GlobalValue::LinkOnceODRLinkage;
54
55 llvm::Constant *C;
56 C = llvm::ConstantArray::get(VMContext, Out.str().substr(4));
57
58 llvm::Constant *s = new llvm::GlobalVariable(CGM.getModule(), C->getType(),
59 true, linktype, C,
60 Out.str());
61 s = llvm::ConstantExpr::getBitCast(s, Int8PtrTy);
62 return s;
63 };
Mike Stumpc7a05bd2009-11-14 15:55:18 +000064
65 llvm::Constant *Buildclass_type_info(const CXXRecordDecl *RD) {
66 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
67
68 if (!CGM.getContext().getLangOptions().Rtti)
69 return llvm::Constant::getNullValue(Int8PtrTy);
70
71 llvm::SmallString<256> OutName;
72 llvm::raw_svector_ostream Out(OutName);
73 mangleCXXRtti(CGM.getMangleContext(), CGM.getContext().getTagDeclType(RD),
74 Out);
75
76 llvm::GlobalVariable::LinkageTypes linktype;
77 linktype = llvm::GlobalValue::LinkOnceODRLinkage;
78 std::vector<llvm::Constant *> info;
79
80 info.push_back(Buildclass_type_infoDesc());
81 info.push_back(BuildName(RD));
82
83 // FIXME: rest of rtti bits
84
85 llvm::Constant *C;
86 llvm::ArrayType *type = llvm::ArrayType::get(Int8PtrTy, info.size());
87 C = llvm::ConstantArray::get(type, info);
88 llvm::Constant *Rtti =
89 new llvm::GlobalVariable(CGM.getModule(), type, true, linktype, C,
90 Out.str());
91 Rtti = llvm::ConstantExpr::getBitCast(Rtti, Int8PtrTy);
92 return Rtti;
93 }
Mike Stump2b1bf312009-11-14 14:25:18 +000094};
95
Anders Carlsson656e4c12009-10-10 20:49:04 +000096llvm::Constant *CodeGenModule::GenerateRtti(const CXXRecordDecl *RD) {
Mike Stump2b1bf312009-11-14 14:25:18 +000097 RttiBuilder b(*this);
98
Mike Stumpc7a05bd2009-11-14 15:55:18 +000099 return b.Buildclass_type_info(RD);
Anders Carlsson656e4c12009-10-10 20:49:04 +0000100}