зеркало из https://github.com/microsoft/clang-1.git
Abstract out member-pointer conversions.
Pretty much everything having to do with member pointers is ABI-specific. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111770 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
a7e6845660
Коммит
3023def6be
|
@ -358,16 +358,21 @@ CodeGenFunction::BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type,
|
||||||
|
|
||||||
CGCXXABI::~CGCXXABI() {}
|
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 *CGCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
|
||||||
llvm::Value *&This,
|
llvm::Value *&This,
|
||||||
llvm::Value *MemPtr,
|
llvm::Value *MemPtr,
|
||||||
const MemberPointerType *MPT) {
|
const MemberPointerType *MPT) {
|
||||||
Diagnostic &Diags = CGF.CGM.getDiags();
|
ErrorUnsupportedABI(CGF, "calls through member pointers");
|
||||||
unsigned DiagID =
|
|
||||||
Diags.getCustomDiagID(Diagnostic::Error,
|
|
||||||
"cannot yet compile member pointer calls in this ABI");
|
|
||||||
Diags.Report(CGF.getContext().getFullLoc(CGF.CurCodeDecl->getLocation()),
|
|
||||||
DiagID);
|
|
||||||
|
|
||||||
const FunctionProtoType *FPT =
|
const FunctionProtoType *FPT =
|
||||||
MPT->getPointeeType()->getAs<FunctionProtoType>();
|
MPT->getPointeeType()->getAs<FunctionProtoType>();
|
||||||
|
@ -379,3 +384,11 @@ llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
|
||||||
FPT->isVariadic());
|
FPT->isVariadic());
|
||||||
return llvm::Constant::getNullValue(FTy->getPointerTo());
|
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 {
|
namespace clang {
|
||||||
|
class CastExpr;
|
||||||
class MemberPointerType;
|
class MemberPointerType;
|
||||||
|
|
||||||
namespace CodeGen {
|
namespace CodeGen {
|
||||||
|
@ -40,6 +41,12 @@ public:
|
||||||
llvm::Value *&This,
|
llvm::Value *&This,
|
||||||
llvm::Value *MemPtr,
|
llvm::Value *MemPtr,
|
||||||
const MemberPointerType *MPT);
|
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.
|
/// Creates an instance of a C++ ABI class.
|
||||||
|
|
|
@ -323,38 +323,14 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
|
||||||
llvm::Value *Src = CGF.CreateMemTemp(SrcType, "tmp");
|
llvm::Value *Src = CGF.CreateMemTemp(SrcType, "tmp");
|
||||||
CGF.EmitAggExpr(E->getSubExpr(), Src, SrcType.isVolatileQualified());
|
CGF.EmitAggExpr(E->getSubExpr(), Src, SrcType.isVolatileQualified());
|
||||||
|
|
||||||
llvm::Value *SrcPtr = Builder.CreateStructGEP(Src, 0, "src.ptr");
|
// Note that the AST doesn't distinguish between checked and
|
||||||
SrcPtr = Builder.CreateLoad(SrcPtr);
|
// unchecked member pointer conversions, so we always have to
|
||||||
|
// implement checked conversions here. This is inefficient for
|
||||||
llvm::Value *SrcAdj = Builder.CreateStructGEP(Src, 1, "src.adj");
|
// ABIs where an actual null check is thus required; fortunately,
|
||||||
SrcAdj = Builder.CreateLoad(SrcAdj);
|
// the Itanium and ARM ABIs ignore the adjustment value when
|
||||||
|
// considering null-ness.
|
||||||
llvm::Value *DstPtr = Builder.CreateStructGEP(DestPtr, 0, "dst.ptr");
|
CGF.CGM.getCXXABI().EmitMemberPointerConversion(CGF, E, Src,
|
||||||
Builder.CreateStore(SrcPtr, DstPtr, VolatileDest);
|
DestPtr, 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);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,12 @@ public:
|
||||||
llvm::Value *&This,
|
llvm::Value *&This,
|
||||||
llvm::Value *MemFnPtr,
|
llvm::Value *MemFnPtr,
|
||||||
const MemberPointerType *MPT);
|
const MemberPointerType *MPT);
|
||||||
|
|
||||||
|
void EmitMemberPointerConversion(CodeGenFunction &CGF,
|
||||||
|
const CastExpr *E,
|
||||||
|
llvm::Value *Src,
|
||||||
|
llvm::Value *Dest,
|
||||||
|
bool VolatileDest);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ARMCXXABI : public ItaniumCXXABI {
|
class ARMCXXABI : public ItaniumCXXABI {
|
||||||
|
@ -168,3 +174,54 @@ ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
|
||||||
Callee->addIncoming(NonVirtualFn, FnNonVirtual);
|
Callee->addIncoming(NonVirtualFn, FnNonVirtual);
|
||||||
return Callee;
|
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);
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче