[PATCH] [ms-cxxabi] Implement member pointer comparisons

John McCall rjmccall at apple.com
Tue Apr 30 10:20:13 PDT 2013


On Apr 19, 2013, at 11:51 AM, Reid Kleckner <rnk at google.com> wrote:
> 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.
> 
> http://llvm-reviews.chandlerc.com/D695
> 
> Files:
>  lib/CodeGen/MicrosoftCXXABI.cpp
>  test/CodeGenCXX/microsoft-abi-member-pointers.cpp
> 
> Index: lib/CodeGen/MicrosoftCXXABI.cpp
> ===================================================================
> --- lib/CodeGen/MicrosoftCXXABI.cpp
> +++ lib/CodeGen/MicrosoftCXXABI.cpp
> @@ -149,6 +149,12 @@
>   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 @@
>   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,66 @@
>   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;
> +  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;
> +  }

Please leave a comment explaining what you're doing here.

> +  // 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);
> +
> +  // Compare everything other than the first field.
> +  llvm::Value *Res = 0;
> +  for (unsigned I = 1, E = cast<llvm::StructType>(L->getType())->getNumElements();
> +       I != E; ++I) {
> +    llvm::Value *LField = Builder.CreateExtractValue(L, I);
> +    llvm::Value *RField = Builder.CreateExtractValue(R, I);
> +    llvm::Value *Cmp = Builder.CreateICmp(Eq, LField, RField);
> +    if (Res)
> +      Res = Builder.CreateBinOp(And, Res, Cmp, "memptr.tobool");

The value labels you're using here seem to be for a different operation.

Otherwise, this all seems to look good.

John.



More information about the cfe-commits mailing list