Add a new GetAddressOfBaseClass overload that takes a base path and. Use it for derived-to-base casts.
llvm-svn: 102270
This commit is contained in:
parent
c779e99540
commit
d829a02514
|
@ -19,6 +19,35 @@
|
|||
using namespace clang;
|
||||
using namespace CodeGen;
|
||||
|
||||
static uint64_t
|
||||
ComputeNonVirtualBaseClassOffset(ASTContext &Context,
|
||||
const CXXRecordDecl *DerivedClass,
|
||||
CXXBaseSpecifierArray::iterator Start,
|
||||
CXXBaseSpecifierArray::iterator End) {
|
||||
uint64_t Offset = 0;
|
||||
|
||||
const CXXRecordDecl *RD = DerivedClass;
|
||||
|
||||
for (CXXBaseSpecifierArray::iterator I = Start; I != End; ++I) {
|
||||
const CXXBaseSpecifier *Base = *I;
|
||||
assert(!Base->isVirtual() && "Should not see virtual bases here!");
|
||||
|
||||
// Get the layout.
|
||||
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
|
||||
|
||||
const CXXRecordDecl *BaseDecl =
|
||||
cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
|
||||
|
||||
// Add the offset.
|
||||
Offset += Layout.getBaseClassOffset(BaseDecl);
|
||||
|
||||
RD = BaseDecl;
|
||||
}
|
||||
|
||||
// FIXME: We should not use / 8 here.
|
||||
return Offset / 8;
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
ComputeNonVirtualBaseClassOffset(ASTContext &Context,
|
||||
const CXXBasePath &Path,
|
||||
|
@ -132,6 +161,81 @@ ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, llvm::Value *ThisPtr,
|
|||
return ThisPtr;
|
||||
}
|
||||
|
||||
llvm::Value *
|
||||
CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value,
|
||||
const CXXRecordDecl *ClassDecl,
|
||||
const CXXBaseSpecifierArray &BasePath,
|
||||
bool NullCheckValue) {
|
||||
assert(!BasePath.empty() && "Base path should not be empty!");
|
||||
|
||||
CXXBaseSpecifierArray::iterator Start = BasePath.begin();
|
||||
const CXXRecordDecl *VBase = 0;
|
||||
|
||||
// Get the virtual base.
|
||||
if ((*Start)->isVirtual()) {
|
||||
VBase =
|
||||
cast<CXXRecordDecl>((*Start)->getType()->getAs<RecordType>()->getDecl());
|
||||
++Start;
|
||||
}
|
||||
|
||||
uint64_t NonVirtualOffset =
|
||||
ComputeNonVirtualBaseClassOffset(getContext(), VBase ? VBase : ClassDecl,
|
||||
Start, BasePath.end());
|
||||
|
||||
// Get the base pointer type.
|
||||
const llvm::Type *BasePtrTy =
|
||||
llvm::PointerType::getUnqual(ConvertType((BasePath.end()[-1])->getType()));
|
||||
|
||||
if (!NonVirtualOffset && !VBase) {
|
||||
// Just cast back.
|
||||
return Builder.CreateBitCast(Value, BasePtrTy);
|
||||
}
|
||||
|
||||
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(Value,
|
||||
llvm::Constant::getNullValue(Value->getType()));
|
||||
Builder.CreateCondBr(IsNull, CastNull, CastNotNull);
|
||||
EmitBlock(CastNotNull);
|
||||
}
|
||||
|
||||
llvm::Value *VirtualOffset = 0;
|
||||
|
||||
if (VBase)
|
||||
VirtualOffset = GetVirtualBaseClassOffset(Value, ClassDecl, VBase);
|
||||
|
||||
// Apply the offsets.
|
||||
Value = ApplyNonVirtualAndVirtualOffset(*this, Value, NonVirtualOffset,
|
||||
VirtualOffset);
|
||||
|
||||
// Cast back.
|
||||
Value = Builder.CreateBitCast(Value, BasePtrTy);
|
||||
|
||||
if (NullCheckValue) {
|
||||
Builder.CreateBr(CastEnd);
|
||||
EmitBlock(CastNull);
|
||||
Builder.CreateBr(CastEnd);
|
||||
EmitBlock(CastEnd);
|
||||
|
||||
llvm::PHINode *PHI = Builder.CreatePHI(Value->getType());
|
||||
PHI->reserveOperandSpace(2);
|
||||
PHI->addIncoming(Value, CastNotNull);
|
||||
PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()),
|
||||
CastNull);
|
||||
Value = PHI;
|
||||
}
|
||||
|
||||
return Value;
|
||||
}
|
||||
|
||||
llvm::Value *
|
||||
CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value,
|
||||
const CXXRecordDecl *Class,
|
||||
|
|
|
@ -840,15 +840,9 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
|
|||
CXXRecordDecl *DerivedClassDecl =
|
||||
cast<CXXRecordDecl>(DerivedClassTy->getDecl());
|
||||
|
||||
const RecordType *BaseClassTy =
|
||||
DestTy->getAs<PointerType>()->getPointeeType()->getAs<RecordType>();
|
||||
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseClassTy->getDecl());
|
||||
|
||||
Value *Src = Visit(const_cast<Expr*>(E));
|
||||
|
||||
bool NullCheckValue = ShouldNullCheckClassCastValue(CE);
|
||||
return CGF.GetAddressOfBaseClass(Src, DerivedClassDecl, BaseClassDecl,
|
||||
NullCheckValue);
|
||||
return CGF.GetAddressOfBaseClass(Visit(E), DerivedClassDecl,
|
||||
CE->getBasePath(),
|
||||
ShouldNullCheckClassCastValue(CE));
|
||||
}
|
||||
case CastExpr::CK_Dynamic: {
|
||||
Value *V = Visit(const_cast<Expr*>(E));
|
||||
|
|
|
@ -787,7 +787,11 @@ public:
|
|||
const CXXRecordDecl *ClassDecl,
|
||||
const CXXRecordDecl *BaseClassDecl,
|
||||
bool NullCheckValue);
|
||||
|
||||
llvm::Value *GetAddressOfBaseClass(llvm::Value *Value,
|
||||
const CXXRecordDecl *ClassDecl,
|
||||
const CXXBaseSpecifierArray &BasePath,
|
||||
bool NullCheckValue);
|
||||
|
||||
llvm::Value *GetAddressOfDerivedClass(llvm::Value *Value,
|
||||
const CXXRecordDecl *ClassDecl,
|
||||
const CXXRecordDecl *DerivedClassDecl,
|
||||
|
|
Loading…
Reference in New Issue