| //===--- CGCXXClass.cpp - Emit LLVM Code for C++ classes ------------------===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | // | 
 | // This contains code dealing with C++ code generation of classes | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "CodeGenFunction.h" | 
 | #include "clang/AST/RecordLayout.h" | 
 | using namespace clang; | 
 | using namespace CodeGen; | 
 |  | 
 | static bool | 
 | GetNestedPaths(llvm::SmallVectorImpl<const CXXRecordDecl *> &NestedBasePaths, | 
 |                const CXXRecordDecl *ClassDecl, | 
 |                const CXXRecordDecl *BaseClassDecl) { | 
 |   for (CXXRecordDecl::base_class_const_iterator i = ClassDecl->bases_begin(), | 
 |       e = ClassDecl->bases_end(); i != e; ++i) { | 
 |     if (i->isVirtual()) | 
 |       continue; | 
 |     const CXXRecordDecl *Base = | 
 |       cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); | 
 |     if (Base == BaseClassDecl) { | 
 |       NestedBasePaths.push_back(BaseClassDecl); | 
 |       return true; | 
 |     } | 
 |   } | 
 |   // BaseClassDecl not an immediate base of ClassDecl. | 
 |   for (CXXRecordDecl::base_class_const_iterator i = ClassDecl->bases_begin(), | 
 |        e = ClassDecl->bases_end(); i != e; ++i) { | 
 |     if (i->isVirtual()) | 
 |       continue; | 
 |     const CXXRecordDecl *Base = | 
 |       cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); | 
 |     if (GetNestedPaths(NestedBasePaths, Base, BaseClassDecl)) { | 
 |       NestedBasePaths.push_back(Base); | 
 |       return true; | 
 |     } | 
 |   } | 
 |   return false; | 
 | } | 
 |  | 
 | static uint64_t ComputeBaseClassOffset(ASTContext &Context, | 
 |                                        const CXXRecordDecl *ClassDecl, | 
 |                                        const CXXRecordDecl *BaseClassDecl) { | 
 |     uint64_t Offset = 0; | 
 |  | 
 |     llvm::SmallVector<const CXXRecordDecl *, 16> NestedBasePaths; | 
 |     GetNestedPaths(NestedBasePaths, ClassDecl, BaseClassDecl); | 
 |     assert(NestedBasePaths.size() > 0 && | 
 |            "AddressCXXOfBaseClass - inheritence path failed"); | 
 |     NestedBasePaths.push_back(ClassDecl); | 
 |      | 
 |     for (unsigned i = NestedBasePaths.size() - 1; i > 0; i--) { | 
 |         const CXXRecordDecl *DerivedClass = NestedBasePaths[i]; | 
 |         const CXXRecordDecl *BaseClass = NestedBasePaths[i-1]; | 
 |         const ASTRecordLayout &Layout =  | 
 |             Context.getASTRecordLayout(DerivedClass); | 
 |          | 
 |         Offset += Layout.getBaseClassOffset(BaseClass) / 8; | 
 |     } | 
 |      | 
 |     return Offset; | 
 | } | 
 |  | 
 | llvm::Value * | 
 | CodeGenFunction::GetAddressCXXOfBaseClass(llvm::Value *BaseValue, | 
 |                                           const CXXRecordDecl *ClassDecl, | 
 |                                           const CXXRecordDecl *BaseClassDecl, | 
 |                                           bool NullCheckValue) { | 
 |   if (ClassDecl == BaseClassDecl) | 
 |     return BaseValue; | 
 |  | 
 |  | 
 |   uint64_t Offset = ComputeBaseClassOffset(getContext(),  | 
 |                                            ClassDecl, BaseClassDecl); | 
 |  | 
 |   llvm::BasicBlock *CastNull = 0; | 
 |   llvm::BasicBlock *CastNotNull = 0; | 
 |   llvm::BasicBlock *CastEnd = 0; | 
 |    | 
 |   if (NullCheckValue) { | 
 |     CastNull = createBasicBlock("cast.null"); | 
 |     CastNotNull = createBasicBlock("cast.notnull"); | 
 |     CastEnd = createBasicBlock("cast.end"); | 
 |      | 
 |     llvm::Value *IsNull =  | 
 |       Builder.CreateICmpEQ(BaseValue, | 
 |                            llvm::Constant::getNullValue(BaseValue->getType())); | 
 |     Builder.CreateCondBr(IsNull, CastNull, CastNotNull); | 
 |     EmitBlock(CastNotNull); | 
 |   } | 
 |    | 
 |   const llvm::Type *LongTy =  | 
 |     CGM.getTypes().ConvertType(CGM.getContext().LongTy); | 
 |   const llvm::Type *Int8PtrTy =  | 
 |     llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(VMContext)); | 
 |    | 
 |   llvm::Value *OffsetVal = llvm::ConstantInt::get(LongTy, Offset); | 
 |    | 
 |   // Apply the offset. | 
 |   BaseValue = Builder.CreateBitCast(BaseValue, Int8PtrTy); | 
 |   BaseValue = Builder.CreateGEP(BaseValue, OffsetVal, "add.ptr"); | 
 |    | 
 |   QualType BTy = | 
 |     getContext().getCanonicalType( | 
 |       getContext().getTypeDeclType(const_cast<CXXRecordDecl*>(BaseClassDecl))); | 
 |    | 
 |   // Cast back. | 
 |   const llvm::Type *BasePtr = llvm::PointerType::getUnqual(ConvertType(BTy)); | 
 |   BaseValue = Builder.CreateBitCast(BaseValue, BasePtr); | 
 |   | 
 |   if (NullCheckValue) { | 
 |     Builder.CreateBr(CastEnd); | 
 |     EmitBlock(CastNull); | 
 |     Builder.CreateBr(CastEnd); | 
 |     EmitBlock(CastEnd); | 
 |      | 
 |     llvm::PHINode *PHI = Builder.CreatePHI(BaseValue->getType()); | 
 |     PHI->reserveOperandSpace(2); | 
 |     PHI->addIncoming(BaseValue, CastNotNull); | 
 |     PHI->addIncoming(llvm::Constant::getNullValue(BaseValue->getType()),  | 
 |                      CastNull); | 
 |     BaseValue = PHI; | 
 |   } | 
 |    | 
 |   return BaseValue; | 
 | } |