blob: b2ff2327afbe00c1230b707572818bf2753a90c8 [file] [log] [blame]
Anders Carlsson9a57c5a2009-09-12 04:27:24 +00001//===--- CGCXXClass.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/RecordLayout.h"
16using namespace clang;
17using namespace CodeGen;
18
19static bool
20GetNestedPaths(llvm::SmallVectorImpl<const CXXRecordDecl *> &NestedBasePaths,
21 const CXXRecordDecl *ClassDecl,
22 const CXXRecordDecl *BaseClassDecl) {
23 for (CXXRecordDecl::base_class_const_iterator i = ClassDecl->bases_begin(),
24 e = ClassDecl->bases_end(); i != e; ++i) {
25 if (i->isVirtual())
26 continue;
27 const CXXRecordDecl *Base =
28 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
29 if (Base == BaseClassDecl) {
30 NestedBasePaths.push_back(BaseClassDecl);
31 return true;
32 }
33 }
34 // BaseClassDecl not an immediate base of ClassDecl.
35 for (CXXRecordDecl::base_class_const_iterator i = ClassDecl->bases_begin(),
36 e = ClassDecl->bases_end(); i != e; ++i) {
37 if (i->isVirtual())
38 continue;
39 const CXXRecordDecl *Base =
40 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
41 if (GetNestedPaths(NestedBasePaths, Base, BaseClassDecl)) {
42 NestedBasePaths.push_back(Base);
43 return true;
44 }
45 }
46 return false;
47}
48
49static uint64_t ComputeBaseClassOffset(ASTContext &Context,
50 const CXXRecordDecl *ClassDecl,
51 const CXXRecordDecl *BaseClassDecl) {
52 uint64_t Offset = 0;
53
54 llvm::SmallVector<const CXXRecordDecl *, 16> NestedBasePaths;
55 GetNestedPaths(NestedBasePaths, ClassDecl, BaseClassDecl);
56 assert(NestedBasePaths.size() > 0 &&
57 "AddressCXXOfBaseClass - inheritence path failed");
58 NestedBasePaths.push_back(ClassDecl);
59
60 for (unsigned i = NestedBasePaths.size() - 1; i > 0; i--) {
61 const CXXRecordDecl *DerivedClass = NestedBasePaths[i];
62 const CXXRecordDecl *BaseClass = NestedBasePaths[i-1];
63 const ASTRecordLayout &Layout =
64 Context.getASTRecordLayout(DerivedClass);
65
66 Offset += Layout.getBaseClassOffset(BaseClass) / 8;
67 }
68
69 return Offset;
70}
71
72llvm::Value *
73CodeGenFunction::GetAddressCXXOfBaseClass(llvm::Value *BaseValue,
74 const CXXRecordDecl *ClassDecl,
75 const CXXRecordDecl *BaseClassDecl,
76 bool NullCheckValue) {
77 if (ClassDecl == BaseClassDecl)
78 return BaseValue;
79
80
81 uint64_t Offset = ComputeBaseClassOffset(getContext(),
82 ClassDecl, BaseClassDecl);
83
Anders Carlsson360e7d02009-09-12 06:04:24 +000084 llvm::BasicBlock *CastNull = 0;
85 llvm::BasicBlock *CastNotNull = 0;
86 llvm::BasicBlock *CastEnd = 0;
87
88 if (NullCheckValue) {
89 CastNull = createBasicBlock("cast.null");
90 CastNotNull = createBasicBlock("cast.notnull");
91 CastEnd = createBasicBlock("cast.end");
92
93 llvm::Value *IsNull =
94 Builder.CreateICmpEQ(BaseValue,
95 llvm::Constant::getNullValue(BaseValue->getType()));
96 Builder.CreateCondBr(IsNull, CastNull, CastNotNull);
97 EmitBlock(CastNotNull);
98 }
99
Anders Carlsson9a57c5a2009-09-12 04:27:24 +0000100 const llvm::Type *LongTy =
101 CGM.getTypes().ConvertType(CGM.getContext().LongTy);
102 const llvm::Type *Int8PtrTy =
103 llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(VMContext));
104
105 llvm::Value *OffsetVal = llvm::ConstantInt::get(LongTy, Offset);
106
107 // Apply the offset.
108 BaseValue = Builder.CreateBitCast(BaseValue, Int8PtrTy);
109 BaseValue = Builder.CreateGEP(BaseValue, OffsetVal, "add.ptr");
110
111 QualType BTy =
112 getContext().getCanonicalType(
113 getContext().getTypeDeclType(const_cast<CXXRecordDecl*>(BaseClassDecl)));
114
115 // Cast back.
116 const llvm::Type *BasePtr = llvm::PointerType::getUnqual(ConvertType(BTy));
117 BaseValue = Builder.CreateBitCast(BaseValue, BasePtr);
Anders Carlsson360e7d02009-09-12 06:04:24 +0000118
119 if (NullCheckValue) {
120 Builder.CreateBr(CastEnd);
121 EmitBlock(CastNull);
122 Builder.CreateBr(CastEnd);
123 EmitBlock(CastEnd);
124
125 llvm::PHINode *PHI = Builder.CreatePHI(BaseValue->getType());
126 PHI->reserveOperandSpace(2);
127 PHI->addIncoming(BaseValue, CastNotNull);
128 PHI->addIncoming(llvm::Constant::getNullValue(BaseValue->getType()),
129 CastNull);
130 BaseValue = PHI;
131 }
Anders Carlsson9a57c5a2009-09-12 04:27:24 +0000132
133 return BaseValue;
134}