[cfe-commits] r111774 - in /cfe/trunk/lib/CodeGen: CGCXX.cpp CGCXXABI.h CGExpr.cpp CGExprScalar.cpp ItaniumCXXABI.cpp
John McCall
rjmccall at apple.com
Sun Aug 22 01:30:07 PDT 2010
Author: rjmccall
Date: Sun Aug 22 03:30:07 2010
New Revision: 111774
URL: http://llvm.org/viewvc/llvm-project?rev=111774&view=rev
Log:
Extract member function pointer comparison and null comparison into
the ABI code. Implement correct semantics for these on ARM.
I believe this completes the implementation of member function pointers
on ARM.
I think I'm going to switch member function pointers over to be
non-aggregates while I have all this in mind.
Modified:
cfe/trunk/lib/CodeGen/CGCXX.cpp
cfe/trunk/lib/CodeGen/CGCXXABI.h
cfe/trunk/lib/CodeGen/CGExpr.cpp
cfe/trunk/lib/CodeGen/CGExprScalar.cpp
cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=111774&r1=111773&r2=111774&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Sun Aug 22 03:30:07 2010
@@ -369,6 +369,24 @@
ErrorUnsupportedABI(CGF, "member function pointers");
}
+llvm::Value *
+CGCXXABI::EmitMemberFunctionPointerComparison(CodeGenFunction &CGF,
+ llvm::Value *L,
+ llvm::Value *R,
+ const MemberPointerType *MPT,
+ bool Inequality) {
+ ErrorUnsupportedABI(CGF, "member function pointer comparison");
+ return CGF.Builder.getFalse();
+}
+
+llvm::Value *
+CGCXXABI::EmitMemberFunctionPointerIsNotNull(CodeGenFunction &CGF,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT) {
+ ErrorUnsupportedABI(CGF, "member function pointer null testing");
+ return CGF.Builder.getFalse();
+}
+
llvm::Constant *
CGCXXABI::EmitMemberFunctionPointerConversion(llvm::Constant *C,
const CastExpr *E) {
Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=111774&r1=111773&r2=111774&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Sun Aug 22 03:30:07 2010
@@ -77,6 +77,18 @@
const CXXMethodDecl *MD,
llvm::Value *DestPtr,
bool VolatileDest);
+
+ virtual llvm::Value *
+ EmitMemberFunctionPointerComparison(CodeGenFunction &CGF,
+ llvm::Value *L,
+ llvm::Value *R,
+ const MemberPointerType *MPT,
+ bool Inequality);
+
+ virtual llvm::Value *
+ EmitMemberFunctionPointerIsNotNull(CodeGenFunction &CGF,
+ llvm::Value *Addr,
+ const MemberPointerType *MPT);
};
/// Creates an instance of a C++ ABI class.
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=111774&r1=111773&r2=111774&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Sun Aug 22 03:30:07 2010
@@ -69,17 +69,9 @@
if (E->getType()->isMemberFunctionPointerType()) {
LValue LV = EmitAggExprToLValue(E);
- // Get the pointer.
- llvm::Value *FuncPtr = Builder.CreateStructGEP(LV.getAddress(), 0,
- "src.ptr");
- FuncPtr = Builder.CreateLoad(FuncPtr);
-
- llvm::Value *IsNotNull =
- Builder.CreateICmpNE(FuncPtr,
- llvm::Constant::getNullValue(FuncPtr->getType()),
- "tobool");
-
- return IsNotNull;
+ return CGM.getCXXABI().EmitMemberFunctionPointerIsNotNull(CGF,
+ LV.getAddress(),
+ E->getType()->getAs<MemberPointerType>());
}
if (!E->getType()->isAnyComplexType())
return EmitScalarConversion(EmitScalarExpr(E), E->getType(), BoolTy);
Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=111774&r1=111773&r2=111774&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Sun Aug 22 03:30:07 2010
@@ -1802,32 +1802,13 @@
Value *Result;
QualType LHSTy = E->getLHS()->getType();
if (LHSTy->isMemberFunctionPointerType()) {
+ assert(E->getOpcode() == BinaryOperator::EQ ||
+ E->getOpcode() == BinaryOperator::NE);
Value *LHSPtr = CGF.EmitAnyExprToTemp(E->getLHS()).getAggregateAddr();
Value *RHSPtr = CGF.EmitAnyExprToTemp(E->getRHS()).getAggregateAddr();
- llvm::Value *LHSFunc = Builder.CreateStructGEP(LHSPtr, 0);
- LHSFunc = Builder.CreateLoad(LHSFunc);
- llvm::Value *RHSFunc = Builder.CreateStructGEP(RHSPtr, 0);
- RHSFunc = Builder.CreateLoad(RHSFunc);
- Value *ResultF = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc,
- LHSFunc, RHSFunc, "cmp.func");
- Value *NullPtr = llvm::Constant::getNullValue(LHSFunc->getType());
- Value *ResultNull = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc,
- LHSFunc, NullPtr, "cmp.null");
- llvm::Value *LHSAdj = Builder.CreateStructGEP(LHSPtr, 1);
- LHSAdj = Builder.CreateLoad(LHSAdj);
- llvm::Value *RHSAdj = Builder.CreateStructGEP(RHSPtr, 1);
- RHSAdj = Builder.CreateLoad(RHSAdj);
- Value *ResultA = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc,
- LHSAdj, RHSAdj, "cmp.adj");
- if (E->getOpcode() == BinaryOperator::EQ) {
- Result = Builder.CreateOr(ResultNull, ResultA, "or.na");
- Result = Builder.CreateAnd(Result, ResultF, "and.f");
- } else {
- assert(E->getOpcode() == BinaryOperator::NE &&
- "Member pointer comparison other than == or != ?");
- Result = Builder.CreateAnd(ResultNull, ResultA, "and.na");
- Result = Builder.CreateOr(Result, ResultF, "or.f");
- }
+ Result = CGF.CGM.getCXXABI().EmitMemberFunctionPointerComparison(
+ CGF, LHSPtr, RHSPtr, LHSTy->getAs<MemberPointerType>(),
+ E->getOpcode() == BinaryOperator::NE);
} else if (!LHSTy->isAnyComplexType()) {
Value *LHS = Visit(E->getLHS());
Value *RHS = Visit(E->getRHS());
Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=111774&r1=111773&r2=111774&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Sun Aug 22 03:30:07 2010
@@ -73,6 +73,16 @@
llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD);
+ llvm::Value *EmitMemberFunctionPointerComparison(CodeGenFunction &CGF,
+ llvm::Value *L,
+ llvm::Value *R,
+ const MemberPointerType *MPT,
+ bool Inequality);
+
+ llvm::Value *EmitMemberFunctionPointerIsNotNull(CodeGenFunction &CGF,
+ llvm::Value *Addr,
+ const MemberPointerType *MPT);
+
private:
void GetMemberFunctionPointer(const CXXMethodDecl *MD,
llvm::Constant *(&Array)[2]);
@@ -405,6 +415,108 @@
Builder.CreateStore(Values[1], AdjPtr, VolatileDest);
}
+/// The comparison algorithm is pretty easy: the member pointers are
+/// the same if they're either bitwise identical *or* both null.
+///
+/// ARM is different here only because null-ness is more complicated.
+llvm::Value *
+ItaniumCXXABI::EmitMemberFunctionPointerComparison(CodeGenFunction &CGF,
+ llvm::Value *L,
+ llvm::Value *R,
+ const MemberPointerType *MPT,
+ bool Inequality) {
+ CGBuilderTy &Builder = CGF.Builder;
+
+ llvm::Value *LPtr = Builder.CreateLoad(Builder.CreateStructGEP(L, 0),
+ "lhs.memptr.ptr");
+ llvm::Value *RPtr = Builder.CreateLoad(Builder.CreateStructGEP(R, 0),
+ "rhs.memptr.ptr");
+
+ // The Itanium tautology is:
+ // (L == R) <==> (L.ptr == R.ptr /\ (L.ptr == 0 \/ L.adj == R.adj))
+ // The ARM tautology is:
+ // (L == R) <==> (L.ptr == R.ptr /\
+ // (L.adj == R.adj \/
+ // (L.ptr == 0 /\ ((L.adj|R.adj) & 1) == 0)))
+ // The inequality tautologies have exactly the same structure, except
+ // applying De Morgan's laws.
+
+ llvm::ICmpInst::Predicate Eq;
+ llvm::Instruction::BinaryOps And, Or;
+ if (Inequality) {
+ Eq = llvm::ICmpInst::ICMP_NE;
+ And = llvm::Instruction::Or;
+ Or = llvm::Instruction::And;
+ } else {
+ Eq = llvm::ICmpInst::ICMP_EQ;
+ And = llvm::Instruction::And;
+ Or = llvm::Instruction::Or;
+ }
+
+ // This condition tests whether L.ptr == R.ptr. This must always be
+ // true for equality to hold.
+ llvm::Value *PtrEq = Builder.CreateICmp(Eq, LPtr, RPtr, "cmp.ptr");
+
+ // This condition, together with the assumption that L.ptr == R.ptr,
+ // tests whether the pointers are both null. ARM imposes an extra
+ // condition.
+ llvm::Value *Zero = llvm::Constant::getNullValue(LPtr->getType());
+ llvm::Value *EqZero = Builder.CreateICmp(Eq, LPtr, Zero, "cmp.ptr.null");
+
+ // This condition tests whether L.adj == R.adj. If this isn't
+ // true, the pointers are unequal unless they're both null.
+ llvm::Value *LAdj = Builder.CreateLoad(Builder.CreateStructGEP(L, 1),
+ "lhs.memptr.adj");
+ llvm::Value *RAdj = Builder.CreateLoad(Builder.CreateStructGEP(R, 1),
+ "rhs.memptr.adj");
+ llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj, "cmp.adj");
+
+ // Null member function pointers on ARM clear the low bit of Adj,
+ // so the zero condition has to check that neither low bit is set.
+ if (IsARM) {
+ llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1);
+
+ // Compute (l.adj | r.adj) & 1 and test it against zero.
+ llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj, "or.adj");
+ llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One);
+ llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1, Zero,
+ "cmp.or.adj");
+ EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero);
+ }
+
+ // Tie together all our conditions.
+ llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq);
+ Result = Builder.CreateBinOp(And, PtrEq, Result,
+ Inequality ? "memptr.ne" : "memptr.eq");
+ return Result;
+}
+
+llvm::Value *
+ItaniumCXXABI::EmitMemberFunctionPointerIsNotNull(CodeGenFunction &CGF,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT) {
+ CGBuilderTy &Builder = CGF.Builder;
+
+ // In Itanium, a member function pointer is null if 'ptr' is null.
+ llvm::Value *Ptr =
+ Builder.CreateLoad(Builder.CreateStructGEP(MemPtr, 0), "memptr.ptr");
+
+ llvm::Constant *Zero = llvm::ConstantInt::get(Ptr->getType(), 0);
+ llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero, "memptr.tobool");
+
+ // In ARM, it's that, plus the low bit of 'adj' must be zero.
+ if (IsARM) {
+ llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1);
+ llvm::Value *Adj =
+ Builder.CreateLoad(Builder.CreateStructGEP(MemPtr, 1), "memptr.adj");
+ llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit");
+ llvm::Value *IsNotVirtual = Builder.CreateICmpEQ(VirtualBit, Zero,
+ "memptr.notvirtual");
+ Result = Builder.CreateAnd(Result, IsNotVirtual);
+ }
+
+ return Result;
+}
bool ItaniumCXXABI::RequiresNonZeroInitializer(QualType T) {
return CGM.getTypes().ContainsPointerToDataMember(T);
More information about the cfe-commits
mailing list