From ea266cad53e3d49771fa38103913d3ec7a166694 Mon Sep 17 00:00:00 2001
From: dim <dim@FreeBSD.org>
Date: Mon, 10 Jun 2013 20:45:12 +0000
Subject: Vendor import of clang tags/RELEASE_33/final r183502 (effectively,
 3.3 release):
 http://llvm.org/svn/llvm-project/cfe/tags/RELEASE_33/final@183502

---
 lib/CodeGen/MicrosoftCXXABI.cpp | 488 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 436 insertions(+), 52 deletions(-)

(limited to 'lib/CodeGen/MicrosoftCXXABI.cpp')

diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index 00b15c9..f5242ea 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -28,6 +28,17 @@ class MicrosoftCXXABI : public CGCXXABI {
 public:
   MicrosoftCXXABI(CodeGenModule &CGM) : CGCXXABI(CGM) {}
 
+  bool isReturnTypeIndirect(const CXXRecordDecl *RD) const {
+    // Structures that are not C++03 PODs are always indirect.
+    return !RD->isPOD();
+  }
+
+  RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const {
+    if (RD->hasNonTrivialCopyConstructor())
+      return RAA_DirectInMemory;
+    return RAA_Default;
+  }
+
   StringRef GetPureVirtualCallName() { return "_purecall"; }
   // No known support for deleted functions in MSVC yet, so this choice is
   // arbitrary.
@@ -111,21 +122,46 @@ public:
   static bool needThisReturn(GlobalDecl GD);
 
 private:
-  llvm::Constant *getSimpleNullMemberPointer(const MemberPointerType *MPT);
-
-  llvm::Constant *getZeroPtrDiff() {
-    return llvm::ConstantInt::get(CGM.PtrDiffTy, 0);
+  llvm::Constant *getZeroInt() {
+    return llvm::ConstantInt::get(CGM.IntTy, 0);
   }
 
-  llvm::Constant *getAllOnesPtrDiff() {
-    return  llvm::Constant::getAllOnesValue(CGM.PtrDiffTy);
+  llvm::Constant *getAllOnesInt() {
+    return  llvm::Constant::getAllOnesValue(CGM.IntTy);
   }
 
+  void
+  GetNullMemberPointerFields(const MemberPointerType *MPT,
+                             llvm::SmallVectorImpl<llvm::Constant *> &fields);
+
+  llvm::Value *AdjustVirtualBase(CodeGenFunction &CGF, const CXXRecordDecl *RD,
+                                 llvm::Value *Base,
+                                 llvm::Value *VirtualBaseAdjustmentOffset,
+                                 llvm::Value *VBPtrOffset /* optional */);
+
+  /// \brief Emits a full member pointer with the fields common to data and
+  /// function member pointers.
+  llvm::Constant *EmitFullMemberPointer(llvm::Constant *FirstField,
+                                        bool IsMemberFunction,
+                                        const CXXRecordDecl *RD);
+
 public:
+  virtual llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT);
+
+  virtual bool isZeroInitializable(const MemberPointerType *MPT);
+
   virtual llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
 
   virtual llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
                                                 CharUnits offset);
+  virtual llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
+  virtual llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT);
+
+  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,
@@ -136,6 +172,12 @@ public:
                                                     llvm::Value *MemPtr,
                                                   const MemberPointerType *MPT);
 
+  virtual llvm::Value *
+  EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
+                                  llvm::Value *&This,
+                                  llvm::Value *MemPtr,
+                                  const MemberPointerType *MPT);
+
 };
 
 }
@@ -375,49 +417,259 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
   // Not sure whether we want thread-safe static local variables as VS
   // doesn't make them thread-safe.
 
+  if (D.getTLSKind())
+    CGM.ErrorUnsupported(&D, "dynamic TLS initialization");
+
   // Emit the initializer and add a global destructor if appropriate.
   CGF.EmitCXXGlobalVarDeclInit(D, DeclPtr, PerformInit);
 }
 
-// Returns true for member pointer types that we know how to represent with a
-// simple ptrdiff_t.  Currently we only know how to emit, test, and load member
-// data pointers for complete single inheritance classes.
-static bool isSimpleMemberPointer(const MemberPointerType *MPT) {
+// Member pointer helpers.
+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(bool IsMemberFunction,
+                                             MSInheritanceModel Inheritance) {
+  return (IsMemberFunction && Inheritance >= MSIM_Multiple);
+}
+
+static bool hasVirtualBaseAdjustmentField(MSInheritanceModel Inheritance) {
+  return Inheritance >= MSIM_Virtual;
+}
+
+// Use zero for the field offset of a null data member pointer if we can
+// guarantee that zero is not a valid field offset, or if the member pointer has
+// multiple fields.  Polymorphic classes have a vfptr at offset zero, so we can
+// use zero for null.  If there are multiple fields, we can use zero even if it
+// is a valid field offset because null-ness testing will check the other
+// fields.
+static bool nullFieldOffsetIsZero(MSInheritanceModel Inheritance) {
+  return Inheritance != MSIM_Multiple && Inheritance != MSIM_Single;
+}
+
+bool MicrosoftCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
+  // Null-ness for function memptrs only depends on the first field, which is
+  // the function pointer.  The rest don't matter, so we can zero initialize.
+  if (MPT->isMemberFunctionPointer())
+    return true;
+
+  // The virtual base adjustment field is always -1 for null, so if we have one
+  // we can't zero initialize.  The field offset is sometimes also -1 if 0 is a
+  // valid field offset.
   const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
-  return (MPT->isMemberDataPointer() &&
-          !MPT->getClass()->isIncompleteType() &&
-          RD->getNumVBases() == 0);
+  MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
+  return (!hasVirtualBaseAdjustmentField(Inheritance) &&
+          nullFieldOffsetIsZero(Inheritance));
 }
 
-llvm::Constant *
-MicrosoftCXXABI::getSimpleNullMemberPointer(const MemberPointerType *MPT) {
-  if (isSimpleMemberPointer(MPT)) {
-    const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
-    // A null member data pointer is represented as -1 if the class is not
-    // polymorphic, and 0 otherwise.
-    if (RD->isPolymorphic())
-      return getZeroPtrDiff();
-    return getAllOnesPtrDiff();
+llvm::Type *
+MicrosoftCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
+  const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
+  MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
+  llvm::SmallVector<llvm::Type *, 4> fields;
+  if (MPT->isMemberFunctionPointer())
+    fields.push_back(CGM.VoidPtrTy);  // FunctionPointerOrVirtualThunk
+  else
+    fields.push_back(CGM.IntTy);  // FieldOffset
+
+  if (hasNonVirtualBaseAdjustmentField(MPT->isMemberFunctionPointer(),
+                                       Inheritance))
+    fields.push_back(CGM.IntTy);
+  if (hasVBPtrOffsetField(Inheritance))
+    fields.push_back(CGM.IntTy);
+  if (hasVirtualBaseAdjustmentField(Inheritance))
+    fields.push_back(CGM.IntTy);  // VirtualBaseAdjustmentOffset
+
+  if (fields.size() == 1)
+    return fields[0];
+  return llvm::StructType::get(CGM.getLLVMContext(), fields);
+}
+
+void MicrosoftCXXABI::
+GetNullMemberPointerFields(const MemberPointerType *MPT,
+                           llvm::SmallVectorImpl<llvm::Constant *> &fields) {
+  assert(fields.empty());
+  const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
+  MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
+  if (MPT->isMemberFunctionPointer()) {
+    // FunctionPointerOrVirtualThunk
+    fields.push_back(llvm::Constant::getNullValue(CGM.VoidPtrTy));
+  } else {
+    if (nullFieldOffsetIsZero(Inheritance))
+      fields.push_back(getZeroInt());  // FieldOffset
+    else
+      fields.push_back(getAllOnesInt());  // FieldOffset
   }
-  return GetBogusMemberPointer(QualType(MPT, 0));
+
+  if (hasNonVirtualBaseAdjustmentField(MPT->isMemberFunctionPointer(),
+                                       Inheritance))
+    fields.push_back(getZeroInt());
+  if (hasVBPtrOffsetField(Inheritance))
+    fields.push_back(getZeroInt());
+  if (hasVirtualBaseAdjustmentField(Inheritance))
+    fields.push_back(getAllOnesInt());
 }
 
 llvm::Constant *
 MicrosoftCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
-  if (isSimpleMemberPointer(MPT))
-    return getSimpleNullMemberPointer(MPT);
-  // FIXME: Implement function member pointers.
-  return GetBogusMemberPointer(QualType(MPT, 0));
+  llvm::SmallVector<llvm::Constant *, 4> fields;
+  GetNullMemberPointerFields(MPT, fields);
+  if (fields.size() == 1)
+    return fields[0];
+  llvm::Constant *Res = llvm::ConstantStruct::getAnon(fields);
+  assert(Res->getType() == ConvertMemberPointerType(MPT));
+  return Res;
+}
+
+llvm::Constant *
+MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField,
+                                       bool IsMemberFunction,
+                                       const CXXRecordDecl *RD)
+{
+  MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
+
+  // Single inheritance class member pointer are represented as scalars instead
+  // of aggregates.
+  if (hasOnlyOneField(Inheritance))
+    return FirstField;
+
+  llvm::SmallVector<llvm::Constant *, 4> fields;
+  fields.push_back(FirstField);
+
+  if (hasNonVirtualBaseAdjustmentField(IsMemberFunction, Inheritance))
+    fields.push_back(getZeroInt());
+
+  if (hasVBPtrOffsetField(Inheritance)) {
+    int64_t VBPtrOffset =
+      getContext().getASTRecordLayout(RD).getVBPtrOffset().getQuantity();
+    if (VBPtrOffset == -1)
+      VBPtrOffset = 0;
+    fields.push_back(llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset));
+  }
+
+  // The rest of the fields are adjusted by conversions to a more derived class.
+  if (hasVirtualBaseAdjustmentField(Inheritance))
+    fields.push_back(getZeroInt());
+
+  return llvm::ConstantStruct::getAnon(fields);
 }
 
 llvm::Constant *
 MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
                                        CharUnits offset) {
-  // Member data pointers are plain offsets when no virtual bases are involved.
-  if (isSimpleMemberPointer(MPT))
-    return llvm::ConstantInt::get(CGM.PtrDiffTy, offset.getQuantity());
-  // FIXME: Implement member pointers other inheritance models.
-  return GetBogusMemberPointer(QualType(MPT, 0));
+  const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
+  llvm::Constant *FirstField =
+    llvm::ConstantInt::get(CGM.IntTy, offset.getQuantity());
+  return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/false, RD);
+}
+
+llvm::Constant *
+MicrosoftCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
+  assert(MD->isInstance() && "Member function must not be static!");
+  MD = MD->getCanonicalDecl();
+  const CXXRecordDecl *RD = MD->getParent();
+  CodeGenTypes &Types = CGM.getTypes();
+
+  llvm::Constant *FirstField;
+  if (MD->isVirtual()) {
+    // FIXME: We have to instantiate a thunk that loads the vftable and jumps to
+    // the right offset.
+    FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy);
+  } else {
+    const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
+    llvm::Type *Ty;
+    // Check whether the function has a computable LLVM signature.
+    if (Types.isFuncTypeConvertible(FPT)) {
+      // The function has a computable LLVM signature; use the correct type.
+      Ty = Types.GetFunctionType(Types.arrangeCXXMethodDeclaration(MD));
+    } else {
+      // Use an arbitrary non-function type to tell GetAddrOfFunction that the
+      // function type is incomplete.
+      Ty = CGM.PtrDiffTy;
+    }
+    FirstField = CGM.GetAddrOfFunction(MD, Ty);
+    FirstField = llvm::ConstantExpr::getBitCast(FirstField, CGM.VoidPtrTy);
+  }
+
+  // The rest of the fields are common with data member pointers.
+  return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/true, RD);
+}
+
+llvm::Constant *
+MicrosoftCXXABI::EmitMemberPointer(const APValue &MP, QualType MPT) {
+  // FIXME PR15875: Implement member pointer conversions for Constants.
+  const CXXRecordDecl *RD = MPT->castAs<MemberPointerType>()->getClass()->getAsCXXRecordDecl();
+  return EmitFullMemberPointer(llvm::Constant::getNullValue(CGM.VoidPtrTy),
+                               /*IsMemberFunction=*/true, RD);
+}
+
+/// 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 *
@@ -425,16 +677,90 @@ MicrosoftCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
                                             llvm::Value *MemPtr,
                                             const MemberPointerType *MPT) {
   CGBuilderTy &Builder = CGF.Builder;
+  llvm::SmallVector<llvm::Constant *, 4> fields;
+  // We only need one field for member functions.
+  if (MPT->isMemberFunctionPointer())
+    fields.push_back(llvm::Constant::getNullValue(CGM.VoidPtrTy));
+  else
+    GetNullMemberPointerFields(MPT, fields);
+  assert(!fields.empty());
+  llvm::Value *FirstField = MemPtr;
+  if (MemPtr->getType()->isStructTy())
+    FirstField = Builder.CreateExtractValue(MemPtr, 0);
+  llvm::Value *Res = Builder.CreateICmpNE(FirstField, fields[0], "memptr.cmp0");
+
+  // For function member pointers, we only need to test the function pointer
+  // field.  The other fields if any can be garbage.
+  if (MPT->isMemberFunctionPointer())
+    return Res;
+
+  // Otherwise, emit a series of compares and combine the results.
+  for (int I = 1, E = fields.size(); I < E; ++I) {
+    llvm::Value *Field = Builder.CreateExtractValue(MemPtr, I);
+    llvm::Value *Next = Builder.CreateICmpNE(Field, fields[I], "memptr.cmp");
+    Res = Builder.CreateAnd(Res, Next, "memptr.tobool");
+  }
+  return Res;
+}
 
-  // For member data pointers, this is just a check against -1 or 0.
-  if (isSimpleMemberPointer(MPT)) {
-    llvm::Constant *Val = getSimpleNullMemberPointer(MPT);
-    return Builder.CreateICmpNE(MemPtr, Val, "memptr.tobool");
+// Returns an adjusted base cast to i8*, since we do more address arithmetic on
+// it.
+llvm::Value *
+MicrosoftCXXABI::AdjustVirtualBase(CodeGenFunction &CGF,
+                                   const CXXRecordDecl *RD, llvm::Value *Base,
+                                   llvm::Value *VirtualBaseAdjustmentOffset,
+                                   llvm::Value *VBPtrOffset) {
+  CGBuilderTy &Builder = CGF.Builder;
+  Base = Builder.CreateBitCast(Base, CGM.Int8PtrTy);
+  llvm::BasicBlock *OriginalBB = 0;
+  llvm::BasicBlock *SkipAdjustBB = 0;
+  llvm::BasicBlock *VBaseAdjustBB = 0;
+
+  // In the unspecified inheritance model, there might not be a vbtable at all,
+  // in which case we need to skip the virtual base lookup.  If there is a
+  // vbtable, the first entry is a no-op entry that gives back the original
+  // base, so look for a virtual base adjustment offset of zero.
+  if (VBPtrOffset) {
+    OriginalBB = Builder.GetInsertBlock();
+    VBaseAdjustBB = CGF.createBasicBlock("memptr.vadjust");
+    SkipAdjustBB = CGF.createBasicBlock("memptr.skip_vadjust");
+    llvm::Value *IsVirtual =
+      Builder.CreateICmpNE(VirtualBaseAdjustmentOffset, getZeroInt(),
+                           "memptr.is_vbase");
+    Builder.CreateCondBr(IsVirtual, VBaseAdjustBB, SkipAdjustBB);
+    CGF.EmitBlock(VBaseAdjustBB);
   }
 
-  // FIXME: Implement member pointers other inheritance models.
-  ErrorUnsupportedABI(CGF, "function member pointer tests");
-  return GetBogusMemberPointer(QualType(MPT, 0));
+  // If we weren't given a dynamic vbptr offset, RD should be complete and we'll
+  // know the vbptr offset.
+  if (!VBPtrOffset) {
+    CharUnits offs = getContext().getASTRecordLayout(RD).getVBPtrOffset();
+    VBPtrOffset = llvm::ConstantInt::get(CGM.IntTy, offs.getQuantity());
+  }
+  // Load the vbtable pointer from the vbtable offset in the instance.
+  llvm::Value *VBPtr =
+    Builder.CreateInBoundsGEP(Base, VBPtrOffset, "memptr.vbptr");
+  llvm::Value *VBTable =
+    Builder.CreateBitCast(VBPtr, CGM.Int8PtrTy->getPointerTo(0));
+  VBTable = Builder.CreateLoad(VBTable, "memptr.vbtable");
+  // Load an i32 offset from the vb-table.
+  llvm::Value *VBaseOffs =
+    Builder.CreateInBoundsGEP(VBTable, VirtualBaseAdjustmentOffset);
+  VBaseOffs = Builder.CreateBitCast(VBaseOffs, CGM.Int32Ty->getPointerTo(0));
+  VBaseOffs = Builder.CreateLoad(VBaseOffs, "memptr.vbase_offs");
+  // Add it to VBPtr.  GEP will sign extend the i32 value for us.
+  llvm::Value *AdjustedBase = Builder.CreateInBoundsGEP(VBPtr, VBaseOffs);
+
+  // Merge control flow with the case where we didn't have to adjust.
+  if (VBaseAdjustBB) {
+    Builder.CreateBr(SkipAdjustBB);
+    CGF.EmitBlock(SkipAdjustBB);
+    llvm::PHINode *Phi = Builder.CreatePHI(CGM.Int8PtrTy, 2, "memptr.base");
+    Phi->addIncoming(Base, OriginalBB);
+    Phi->addIncoming(AdjustedBase, VBaseAdjustBB);
+    return Phi;
+  }
+  return AdjustedBase;
 }
 
 llvm::Value *
@@ -442,32 +768,90 @@ MicrosoftCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF,
                                               llvm::Value *Base,
                                               llvm::Value *MemPtr,
                                               const MemberPointerType *MPT) {
+  assert(MPT->isMemberDataPointer());
   unsigned AS = Base->getType()->getPointerAddressSpace();
   llvm::Type *PType =
       CGF.ConvertTypeForMem(MPT->getPointeeType())->getPointerTo(AS);
   CGBuilderTy &Builder = CGF.Builder;
-
-  if (MPT->isMemberFunctionPointer()) {
-    ErrorUnsupportedABI(CGF, "function member pointer address");
-    return llvm::Constant::getNullValue(PType);
+  const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
+  MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
+
+  // Extract the fields we need, regardless of model.  We'll apply them if we
+  // have them.
+  llvm::Value *FieldOffset = MemPtr;
+  llvm::Value *VirtualBaseAdjustmentOffset = 0;
+  llvm::Value *VBPtrOffset = 0;
+  if (MemPtr->getType()->isStructTy()) {
+    // We need to extract values.
+    unsigned I = 0;
+    FieldOffset = Builder.CreateExtractValue(MemPtr, I++);
+    if (hasVBPtrOffsetField(Inheritance))
+      VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++);
+    if (hasVirtualBaseAdjustmentField(Inheritance))
+      VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++);
   }
 
-  llvm::Value *Addr;
-  if (isSimpleMemberPointer(MPT)) {
-    // Add the offset with GEP and i8*.
-    assert(MemPtr->getType() == CGM.PtrDiffTy);
-    Base = Builder.CreateBitCast(Base, Builder.getInt8Ty()->getPointerTo(AS));
-    Addr = Builder.CreateInBoundsGEP(Base, MemPtr, "memptr.offset");
-  } else {
-    ErrorUnsupportedABI(CGF, "non-scalar member pointers");
-    return llvm::Constant::getNullValue(PType);
+  if (VirtualBaseAdjustmentOffset) {
+    Base = AdjustVirtualBase(CGF, RD, Base, VirtualBaseAdjustmentOffset,
+                             VBPtrOffset);
   }
+  llvm::Value *Addr =
+    Builder.CreateInBoundsGEP(Base, FieldOffset, "memptr.offset");
 
   // Cast the address to the appropriate pointer type, adopting the address
   // space of the base pointer.
   return Builder.CreateBitCast(Addr, PType);
 }
 
+llvm::Value *
+MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
+                                                 llvm::Value *&This,
+                                                 llvm::Value *MemPtr,
+                                                 const MemberPointerType *MPT) {
+  assert(MPT->isMemberFunctionPointer());
+  const FunctionProtoType *FPT =
+    MPT->getPointeeType()->castAs<FunctionProtoType>();
+  const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
+  llvm::FunctionType *FTy =
+    CGM.getTypes().GetFunctionType(
+      CGM.getTypes().arrangeCXXMethodType(RD, FPT));
+  CGBuilderTy &Builder = CGF.Builder;
+
+  MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
+
+  // Extract the fields we need, regardless of model.  We'll apply them if we
+  // have them.
+  llvm::Value *FunctionPointer = MemPtr;
+  llvm::Value *NonVirtualBaseAdjustment = NULL;
+  llvm::Value *VirtualBaseAdjustmentOffset = NULL;
+  llvm::Value *VBPtrOffset = NULL;
+  if (MemPtr->getType()->isStructTy()) {
+    // We need to extract values.
+    unsigned I = 0;
+    FunctionPointer = Builder.CreateExtractValue(MemPtr, I++);
+    if (hasNonVirtualBaseAdjustmentField(MPT, Inheritance))
+      NonVirtualBaseAdjustment = Builder.CreateExtractValue(MemPtr, I++);
+    if (hasVBPtrOffsetField(Inheritance))
+      VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++);
+    if (hasVirtualBaseAdjustmentField(Inheritance))
+      VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++);
+  }
+
+  if (VirtualBaseAdjustmentOffset) {
+    This = AdjustVirtualBase(CGF, RD, This, VirtualBaseAdjustmentOffset,
+                             VBPtrOffset);
+  }
+
+  if (NonVirtualBaseAdjustment) {
+    // Apply the adjustment and cast back to the original struct type.
+    llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy());
+    Ptr = Builder.CreateInBoundsGEP(Ptr, NonVirtualBaseAdjustment);
+    This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted");
+  }
+
+  return Builder.CreateBitCast(FunctionPointer, FTy->getPointerTo());
+}
+
 CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {
   return new MicrosoftCXXABI(CGM);
 }
-- 
cgit v1.1