summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2013-04-30 20:15:14 +0000
committerReid Kleckner <reid@kleckner.net>2013-04-30 20:15:14 +0000
commit700c3eea1e5eca4a203151d53a9a3f7f20265dbc (patch)
treea9eff1ced1473ad315a6f27f93538acb8f28ffbc /clang/lib/CodeGen
parent7153251ab52eb4dfac05bd319da1d173ce9ef245 (diff)
downloadbcm5719-llvm-700c3eea1e5eca4a203151d53a9a3f7f20265dbc.tar.gz
bcm5719-llvm-700c3eea1e5eca4a203151d53a9a3f7f20265dbc.zip
[ms-cxxabi] Implement member pointer comparisons
Summary: Like Itanium, comparisons are basically bitwise comparisons of the two values, with an exception for null member function pointers. If two function pointers are null, only the function pointer field matters for comparison purposes. The rest of the bits can be arbitrary. We take advantage of this in isZeroInitializable(), and it may matter once we start emitting conversions. Reviewers: rjmccall CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D695 llvm-svn: 180800
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/MicrosoftCXXABI.cpp72
1 files changed, 72 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 92bc538f207..d22a5e90728 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -149,6 +149,12 @@ public:
virtual llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
CharUnits offset);
+ virtual llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF,
+ llvm::Value *L,
+ llvm::Value *R,
+ const MemberPointerType *MPT,
+ bool Inequality);
+
virtual llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
llvm::Value *MemPtr,
const MemberPointerType *MPT);
@@ -415,6 +421,10 @@ static bool hasVBPtrOffsetField(MSInheritanceModel Inheritance) {
return Inheritance == MSIM_Unspecified;
}
+static bool hasOnlyOneField(MSInheritanceModel Inheritance) {
+ return Inheritance <= MSIM_SinglePolymorphic;
+}
+
// Only member pointers to functions need a this adjustment, since it can be
// combined with the field offset for data pointers.
static bool hasNonVirtualBaseAdjustmentField(const MemberPointerType *MPT,
@@ -531,6 +541,68 @@ MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
return llvm::ConstantStruct::getAnon(fields);
}
+/// Member pointers are the same if they're either bitwise identical *or* both
+/// null. Null-ness for function members is determined by the first field,
+/// while for data member pointers we must compare all fields.
+llvm::Value *
+MicrosoftCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
+ llvm::Value *L,
+ llvm::Value *R,
+ const MemberPointerType *MPT,
+ bool Inequality) {
+ CGBuilderTy &Builder = CGF.Builder;
+
+ // Handle != comparisons by switching the sense of all boolean operations.
+ 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;
+ }
+
+ // If this is a single field member pointer (single inheritance), this is a
+ // single icmp.
+ const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
+ MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
+ if (hasOnlyOneField(Inheritance))
+ return Builder.CreateICmp(Eq, L, R);
+
+ // Compare the first field.
+ llvm::Value *L0 = Builder.CreateExtractValue(L, 0, "lhs.0");
+ llvm::Value *R0 = Builder.CreateExtractValue(R, 0, "rhs.0");
+ llvm::Value *Cmp0 = Builder.CreateICmp(Eq, L0, R0, "memptr.cmp.first");
+
+ // Compare everything other than the first field.
+ llvm::Value *Res = 0;
+ llvm::StructType *LType = cast<llvm::StructType>(L->getType());
+ for (unsigned I = 1, E = LType->getNumElements(); I != E; ++I) {
+ llvm::Value *LF = Builder.CreateExtractValue(L, I);
+ llvm::Value *RF = Builder.CreateExtractValue(R, I);
+ llvm::Value *Cmp = Builder.CreateICmp(Eq, LF, RF, "memptr.cmp.rest");
+ if (Res)
+ Res = Builder.CreateBinOp(And, Res, Cmp);
+ else
+ Res = Cmp;
+ }
+
+ // Check if the first field is 0 if this is a function pointer.
+ if (MPT->isMemberFunctionPointer()) {
+ // (l1 == r1 && ...) || l0 == 0
+ llvm::Value *Zero = llvm::Constant::getNullValue(L0->getType());
+ llvm::Value *IsZero = Builder.CreateICmp(Eq, L0, Zero, "memptr.cmp.iszero");
+ Res = Builder.CreateBinOp(Or, Res, IsZero);
+ }
+
+ // Combine the comparison of the first field, which must always be true for
+ // this comparison to succeeed.
+ return Builder.CreateBinOp(And, Res, Cmp0, "memptr.cmp");
+}
+
llvm::Value *
MicrosoftCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
llvm::Value *MemPtr,
OpenPOWER on IntegriCloud