blob: 1fb8f8308c9ecf5f92a4e7c1f428f85c8f48dbcb [file] [log] [blame]
Anders Carlsson5d58a1d2009-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
84 const llvm::Type *LongTy =
85 CGM.getTypes().ConvertType(CGM.getContext().LongTy);
86 const llvm::Type *Int8PtrTy =
87 llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(VMContext));
88
89 llvm::Value *OffsetVal = llvm::ConstantInt::get(LongTy, Offset);
90
91 // Apply the offset.
92 BaseValue = Builder.CreateBitCast(BaseValue, Int8PtrTy);
93 BaseValue = Builder.CreateGEP(BaseValue, OffsetVal, "add.ptr");
94
95 QualType BTy =
96 getContext().getCanonicalType(
97 getContext().getTypeDeclType(const_cast<CXXRecordDecl*>(BaseClassDecl)));
98
99 // Cast back.
100 const llvm::Type *BasePtr = llvm::PointerType::getUnqual(ConvertType(BTy));
101 BaseValue = Builder.CreateBitCast(BaseValue, BasePtr);
102
103 return BaseValue;
104}