forked from OSchip/llvm-project
Abstract out member-pointer conversions.
Pretty much everything having to do with member pointers is ABI-specific. llvm-svn: 111770
This commit is contained in:
parent
2807d4a58b
commit
a8bbb82c55
|
@ -358,16 +358,21 @@ CodeGenFunction::BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type,
|
|||
|
||||
CGCXXABI::~CGCXXABI() {}
|
||||
|
||||
static void ErrorUnsupportedABI(CodeGenFunction &CGF,
|
||||
llvm::StringRef S) {
|
||||
Diagnostic &Diags = CGF.CGM.getDiags();
|
||||
unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error,
|
||||
"cannot yet compile %s in this ABI");
|
||||
Diags.Report(CGF.getContext().getFullLoc(CGF.CurCodeDecl->getLocation()),
|
||||
DiagID)
|
||||
<< S;
|
||||
}
|
||||
|
||||
llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
|
||||
llvm::Value *&This,
|
||||
llvm::Value *MemPtr,
|
||||
const MemberPointerType *MPT) {
|
||||
Diagnostic &Diags = CGF.CGM.getDiags();
|
||||
unsigned DiagID =
|
||||
Diags.getCustomDiagID(Diagnostic::Error,
|
||||
"cannot yet compile member pointer calls in this ABI");
|
||||
Diags.Report(CGF.getContext().getFullLoc(CGF.CurCodeDecl->getLocation()),
|
||||
DiagID);
|
||||
ErrorUnsupportedABI(CGF, "calls through member pointers");
|
||||
|
||||
const FunctionProtoType *FPT =
|
||||
MPT->getPointeeType()->getAs<FunctionProtoType>();
|
||||
|
@ -379,3 +384,11 @@ llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
|
|||
FPT->isVariadic());
|
||||
return llvm::Constant::getNullValue(FTy->getPointerTo());
|
||||
}
|
||||
|
||||
void CGCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
|
||||
const CastExpr *E,
|
||||
llvm::Value *Src,
|
||||
llvm::Value *Dest,
|
||||
bool VolatileDest) {
|
||||
ErrorUnsupportedABI(CGF, "member pointer conversions");
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace llvm {
|
|||
}
|
||||
|
||||
namespace clang {
|
||||
class CastExpr;
|
||||
class MemberPointerType;
|
||||
|
||||
namespace CodeGen {
|
||||
|
@ -40,6 +41,12 @@ public:
|
|||
llvm::Value *&This,
|
||||
llvm::Value *MemPtr,
|
||||
const MemberPointerType *MPT);
|
||||
|
||||
virtual void EmitMemberPointerConversion(CodeGenFunction &CGF,
|
||||
const CastExpr *E,
|
||||
llvm::Value *Src,
|
||||
llvm::Value *Dest,
|
||||
bool VolatileDest);
|
||||
};
|
||||
|
||||
/// Creates an instance of a C++ ABI class.
|
||||
|
|
|
@ -323,38 +323,14 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
|
|||
llvm::Value *Src = CGF.CreateMemTemp(SrcType, "tmp");
|
||||
CGF.EmitAggExpr(E->getSubExpr(), Src, SrcType.isVolatileQualified());
|
||||
|
||||
llvm::Value *SrcPtr = Builder.CreateStructGEP(Src, 0, "src.ptr");
|
||||
SrcPtr = Builder.CreateLoad(SrcPtr);
|
||||
|
||||
llvm::Value *SrcAdj = Builder.CreateStructGEP(Src, 1, "src.adj");
|
||||
SrcAdj = Builder.CreateLoad(SrcAdj);
|
||||
|
||||
llvm::Value *DstPtr = Builder.CreateStructGEP(DestPtr, 0, "dst.ptr");
|
||||
Builder.CreateStore(SrcPtr, DstPtr, VolatileDest);
|
||||
|
||||
llvm::Value *DstAdj = Builder.CreateStructGEP(DestPtr, 1, "dst.adj");
|
||||
|
||||
// Now See if we need to update the adjustment.
|
||||
const CXXRecordDecl *BaseDecl =
|
||||
cast<CXXRecordDecl>(SrcType->getAs<MemberPointerType>()->
|
||||
getClass()->getAs<RecordType>()->getDecl());
|
||||
const CXXRecordDecl *DerivedDecl =
|
||||
cast<CXXRecordDecl>(E->getType()->getAs<MemberPointerType>()->
|
||||
getClass()->getAs<RecordType>()->getDecl());
|
||||
if (E->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer)
|
||||
std::swap(DerivedDecl, BaseDecl);
|
||||
|
||||
if (llvm::Constant *Adj =
|
||||
CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl,
|
||||
E->path_begin(),
|
||||
E->path_end())) {
|
||||
if (E->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer)
|
||||
SrcAdj = Builder.CreateSub(SrcAdj, Adj, "adj");
|
||||
else
|
||||
SrcAdj = Builder.CreateAdd(SrcAdj, Adj, "adj");
|
||||
}
|
||||
|
||||
Builder.CreateStore(SrcAdj, DstAdj, VolatileDest);
|
||||
// Note that the AST doesn't distinguish between checked and
|
||||
// unchecked member pointer conversions, so we always have to
|
||||
// implement checked conversions here. This is inefficient for
|
||||
// ABIs where an actual null check is thus required; fortunately,
|
||||
// the Itanium and ARM ABIs ignore the adjustment value when
|
||||
// considering null-ness.
|
||||
CGF.CGM.getCXXABI().EmitMemberPointerConversion(CGF, E, Src,
|
||||
DestPtr, VolatileDest);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,12 @@ public:
|
|||
llvm::Value *&This,
|
||||
llvm::Value *MemFnPtr,
|
||||
const MemberPointerType *MPT);
|
||||
|
||||
void EmitMemberPointerConversion(CodeGenFunction &CGF,
|
||||
const CastExpr *E,
|
||||
llvm::Value *Src,
|
||||
llvm::Value *Dest,
|
||||
bool VolatileDest);
|
||||
};
|
||||
|
||||
class ARMCXXABI : public ItaniumCXXABI {
|
||||
|
@ -168,3 +174,54 @@ ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
|
|||
Callee->addIncoming(NonVirtualFn, FnNonVirtual);
|
||||
return Callee;
|
||||
}
|
||||
|
||||
/// Perform a derived-to-base or base-to-derived member pointer conversion.
|
||||
void ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
|
||||
const CastExpr *E,
|
||||
llvm::Value *Src,
|
||||
llvm::Value *Dest,
|
||||
bool VolatileDest) {
|
||||
assert(E->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer ||
|
||||
E->getCastKind() == CastExpr::CK_BaseToDerivedMemberPointer);
|
||||
|
||||
CGBuilderTy &Builder = CGF.Builder;
|
||||
|
||||
const MemberPointerType *SrcTy =
|
||||
E->getSubExpr()->getType()->getAs<MemberPointerType>();
|
||||
const MemberPointerType *DestTy = E->getType()->getAs<MemberPointerType>();
|
||||
|
||||
const CXXRecordDecl *SrcDecl = SrcTy->getClass()->getAsCXXRecordDecl();
|
||||
const CXXRecordDecl *DestDecl = DestTy->getClass()->getAsCXXRecordDecl();
|
||||
|
||||
llvm::Value *SrcPtr = Builder.CreateStructGEP(Src, 0, "src.ptr");
|
||||
SrcPtr = Builder.CreateLoad(SrcPtr);
|
||||
|
||||
llvm::Value *SrcAdj = Builder.CreateStructGEP(Src, 1, "src.adj");
|
||||
SrcAdj = Builder.CreateLoad(SrcAdj);
|
||||
|
||||
llvm::Value *DstPtr = Builder.CreateStructGEP(Dest, 0, "dst.ptr");
|
||||
Builder.CreateStore(SrcPtr, DstPtr, VolatileDest);
|
||||
|
||||
llvm::Value *DstAdj = Builder.CreateStructGEP(Dest, 1, "dst.adj");
|
||||
|
||||
bool DerivedToBase =
|
||||
E->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer;
|
||||
|
||||
const CXXRecordDecl *BaseDecl, *DerivedDecl;
|
||||
if (DerivedToBase)
|
||||
DerivedDecl = SrcDecl, BaseDecl = DestDecl;
|
||||
else
|
||||
BaseDecl = SrcDecl, DerivedDecl = DestDecl;
|
||||
|
||||
if (llvm::Constant *Adj =
|
||||
CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl,
|
||||
E->path_begin(),
|
||||
E->path_end())) {
|
||||
if (DerivedToBase)
|
||||
SrcAdj = Builder.CreateSub(SrcAdj, Adj, "adj");
|
||||
else
|
||||
SrcAdj = Builder.CreateAdd(SrcAdj, Adj, "adj");
|
||||
}
|
||||
|
||||
Builder.CreateStore(SrcAdj, DstAdj, VolatileDest);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue