Deleted Added
sdiff udiff text old ( 200583 ) new ( 201361 )
full compact
1//===--- CGClass.cpp - Emit LLVM Code for C++ classes ---------------------===//
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 classes
11//
12//===----------------------------------------------------------------------===//
13
14#include "CodeGenFunction.h"
15#include "clang/AST/CXXInheritance.h"
16#include "clang/AST/RecordLayout.h"
17
18using namespace clang;
19using namespace CodeGen;
20
21static uint64_t
22ComputeNonVirtualBaseClassOffset(ASTContext &Context, CXXBasePaths &Paths,
23 unsigned Start) {
24 uint64_t Offset = 0;
25
26 const CXXBasePath &Path = Paths.front();
27 for (unsigned i = Start, e = Path.size(); i != e; ++i) {
28 const CXXBasePathElement& Element = Path[i];
29
30 // Get the layout.
31 const ASTRecordLayout &Layout = Context.getASTRecordLayout(Element.Class);
32
33 const CXXBaseSpecifier *BS = Element.Base;
34 assert(!BS->isVirtual() && "Should not see virtual bases here!");
35
36 const CXXRecordDecl *Base =
37 cast<CXXRecordDecl>(BS->getType()->getAs<RecordType>()->getDecl());
38
39 // Add the offset.
40 Offset += Layout.getBaseClassOffset(Base) / 8;
41 }
42
43 return Offset;
44}
45
46llvm::Constant *
47CodeGenModule::GetCXXBaseClassOffset(const CXXRecordDecl *ClassDecl,
48 const CXXRecordDecl *BaseClassDecl) {
49 if (ClassDecl == BaseClassDecl)
50 return 0;
51
52 CXXBasePaths Paths(/*FindAmbiguities=*/false,
53 /*RecordPaths=*/true, /*DetectVirtual=*/false);
54 if (!const_cast<CXXRecordDecl *>(ClassDecl)->
55 isDerivedFrom(const_cast<CXXRecordDecl *>(BaseClassDecl), Paths)) {
56 assert(false && "Class must be derived from the passed in base class!");
57 return 0;
58 }
59
60 uint64_t Offset = ComputeNonVirtualBaseClassOffset(getContext(), Paths, 0);
61 if (!Offset)
62 return 0;
63
64 const llvm::Type *PtrDiffTy =
65 Types.ConvertType(getContext().getPointerDiffType());
66
67 return llvm::ConstantInt::get(PtrDiffTy, Offset);
68}
69
70static llvm::Value *GetCXXBaseClassOffset(CodeGenFunction &CGF,
71 llvm::Value *BaseValue,
72 const CXXRecordDecl *ClassDecl,
73 const CXXRecordDecl *BaseClassDecl) {
74 CXXBasePaths Paths(/*FindAmbiguities=*/false,
75 /*RecordPaths=*/true, /*DetectVirtual=*/false);
76 if (!const_cast<CXXRecordDecl *>(ClassDecl)->
77 isDerivedFrom(const_cast<CXXRecordDecl *>(BaseClassDecl), Paths)) {
78 assert(false && "Class must be derived from the passed in base class!");
79 return 0;
80 }
81
82 unsigned Start = 0;
83 llvm::Value *VirtualOffset = 0;
84
85 const CXXBasePath &Path = Paths.front();
86 const CXXRecordDecl *VBase = 0;
87 for (unsigned i = 0, e = Path.size(); i != e; ++i) {
88 const CXXBasePathElement& Element = Path[i];
89 if (Element.Base->isVirtual()) {
90 Start = i+1;
91 QualType VBaseType = Element.Base->getType();
92 VBase = cast<CXXRecordDecl>(VBaseType->getAs<RecordType>()->getDecl());
93 }
94 }
95 if (VBase)
96 VirtualOffset =
97 CGF.GetVirtualCXXBaseClassOffset(BaseValue, ClassDecl, VBase);
98
99 uint64_t Offset =
100 ComputeNonVirtualBaseClassOffset(CGF.getContext(), Paths, Start);
101
102 if (!Offset)
103 return VirtualOffset;
104
105 const llvm::Type *PtrDiffTy =
106 CGF.ConvertType(CGF.getContext().getPointerDiffType());
107 llvm::Value *NonVirtualOffset = llvm::ConstantInt::get(PtrDiffTy, Offset);
108
109 if (VirtualOffset)
110 return CGF.Builder.CreateAdd(VirtualOffset, NonVirtualOffset);
111
112 return NonVirtualOffset;
113}
114
115// FIXME: This probably belongs in CGVtable, but it relies on
116// the static function ComputeNonVirtualBaseClassOffset, so we should make that
117// a CodeGenModule member function as well.
118ThunkAdjustment
119CodeGenModule::ComputeThunkAdjustment(const CXXRecordDecl *ClassDecl,
120 const CXXRecordDecl *BaseClassDecl) {
121 CXXBasePaths Paths(/*FindAmbiguities=*/false,
122 /*RecordPaths=*/true, /*DetectVirtual=*/false);
123 if (!const_cast<CXXRecordDecl *>(ClassDecl)->
124 isDerivedFrom(const_cast<CXXRecordDecl *>(BaseClassDecl), Paths)) {
125 assert(false && "Class must be derived from the passed in base class!");
126 return ThunkAdjustment();
127 }
128
129 unsigned Start = 0;
130 uint64_t VirtualOffset = 0;
131
132 const CXXBasePath &Path = Paths.front();
133 const CXXRecordDecl *VBase = 0;
134 for (unsigned i = 0, e = Path.size(); i != e; ++i) {
135 const CXXBasePathElement& Element = Path[i];
136 if (Element.Base->isVirtual()) {
137 Start = i+1;
138 QualType VBaseType = Element.Base->getType();
139 VBase = cast<CXXRecordDecl>(VBaseType->getAs<RecordType>()->getDecl());
140 }
141 }
142 if (VBase)
143 VirtualOffset =
144 getVtableInfo().getVirtualBaseOffsetIndex(ClassDecl, BaseClassDecl);
145
146 uint64_t Offset =
147 ComputeNonVirtualBaseClassOffset(getContext(), Paths, Start);
148 return ThunkAdjustment(Offset, VirtualOffset);
149}
150
151llvm::Value *
152CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value,
153 const CXXRecordDecl *ClassDecl,
154 const CXXRecordDecl *BaseClassDecl,
155 bool NullCheckValue) {
156 QualType BTy =
157 getContext().getCanonicalType(
158 getContext().getTypeDeclType(const_cast<CXXRecordDecl*>(BaseClassDecl)));
159 const llvm::Type *BasePtrTy = llvm::PointerType::getUnqual(ConvertType(BTy));
160
161 if (ClassDecl == BaseClassDecl) {
162 // Just cast back.
163 return Builder.CreateBitCast(Value, BasePtrTy);
164 }
165
166 llvm::BasicBlock *CastNull = 0;
167 llvm::BasicBlock *CastNotNull = 0;
168 llvm::BasicBlock *CastEnd = 0;
169
170 if (NullCheckValue) {
171 CastNull = createBasicBlock("cast.null");
172 CastNotNull = createBasicBlock("cast.notnull");
173 CastEnd = createBasicBlock("cast.end");
174
175 llvm::Value *IsNull =
176 Builder.CreateICmpEQ(Value,
177 llvm::Constant::getNullValue(Value->getType()));
178 Builder.CreateCondBr(IsNull, CastNull, CastNotNull);
179 EmitBlock(CastNotNull);
180 }
181
182 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
183
184 llvm::Value *Offset =
185 GetCXXBaseClassOffset(*this, Value, ClassDecl, BaseClassDecl);
186
187 if (Offset) {
188 // Apply the offset.
189 Value = Builder.CreateBitCast(Value, Int8PtrTy);
190 Value = Builder.CreateGEP(Value, Offset, "add.ptr");
191 }
192
193 // Cast back.
194 Value = Builder.CreateBitCast(Value, BasePtrTy);
195
196 if (NullCheckValue) {
197 Builder.CreateBr(CastEnd);
198 EmitBlock(CastNull);
199 Builder.CreateBr(CastEnd);
200 EmitBlock(CastEnd);
201
202 llvm::PHINode *PHI = Builder.CreatePHI(Value->getType());
203 PHI->reserveOperandSpace(2);
204 PHI->addIncoming(Value, CastNotNull);
205 PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()),
206 CastNull);
207 Value = PHI;
208 }
209
210 return Value;
211}
212
213llvm::Value *
214CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value,
215 const CXXRecordDecl *ClassDecl,
216 const CXXRecordDecl *DerivedClassDecl,
217 bool NullCheckValue) {
218 QualType DerivedTy =
219 getContext().getCanonicalType(
220 getContext().getTypeDeclType(const_cast<CXXRecordDecl*>(DerivedClassDecl)));
221 const llvm::Type *DerivedPtrTy = ConvertType(DerivedTy)->getPointerTo();
222
223 if (ClassDecl == DerivedClassDecl) {
224 // Just cast back.
225 return Builder.CreateBitCast(Value, DerivedPtrTy);
226 }
227
228 llvm::BasicBlock *CastNull = 0;
229 llvm::BasicBlock *CastNotNull = 0;
230 llvm::BasicBlock *CastEnd = 0;
231
232 if (NullCheckValue) {
233 CastNull = createBasicBlock("cast.null");
234 CastNotNull = createBasicBlock("cast.notnull");
235 CastEnd = createBasicBlock("cast.end");
236
237 llvm::Value *IsNull =
238 Builder.CreateICmpEQ(Value,
239 llvm::Constant::getNullValue(Value->getType()));
240 Builder.CreateCondBr(IsNull, CastNull, CastNotNull);
241 EmitBlock(CastNotNull);
242 }
243
244 llvm::Value *Offset = GetCXXBaseClassOffset(*this, Value, DerivedClassDecl,
245 ClassDecl);
246 if (Offset) {
247 // Apply the offset.
248 Value = Builder.CreatePtrToInt(Value, Offset->getType());
249 Value = Builder.CreateSub(Value, Offset);
250 Value = Builder.CreateIntToPtr(Value, DerivedPtrTy);
251 } else {
252 // Just cast.
253 Value = Builder.CreateBitCast(Value, DerivedPtrTy);
254 }
255
256 if (NullCheckValue) {
257 Builder.CreateBr(CastEnd);
258 EmitBlock(CastNull);
259 Builder.CreateBr(CastEnd);
260 EmitBlock(CastEnd);
261
262 llvm::PHINode *PHI = Builder.CreatePHI(Value->getType());
263 PHI->reserveOperandSpace(2);
264 PHI->addIncoming(Value, CastNotNull);
265 PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()),
266 CastNull);
267 Value = PHI;
268 }
269
270 return Value;
271}