aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/MicrosoftCXXABI.cpp105
1 files changed, 87 insertions, 18 deletions
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index d22a5e9072..f5242eaaa2 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -139,6 +139,12 @@ private:
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);
@@ -148,6 +154,8 @@ public:
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,
@@ -427,10 +435,9 @@ static bool hasOnlyOneField(MSInheritanceModel Inheritance) {
// 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,
+static bool hasNonVirtualBaseAdjustmentField(bool IsMemberFunction,
MSInheritanceModel Inheritance) {
- return (MPT->isMemberFunctionPointer() &&
- Inheritance >= MSIM_Multiple);
+ return (IsMemberFunction && Inheritance >= MSIM_Multiple);
}
static bool hasVirtualBaseAdjustmentField(MSInheritanceModel Inheritance) {
@@ -472,9 +479,10 @@ MicrosoftCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
else
fields.push_back(CGM.IntTy); // FieldOffset
- if (hasVBPtrOffsetField(Inheritance))
+ if (hasNonVirtualBaseAdjustmentField(MPT->isMemberFunctionPointer(),
+ Inheritance))
fields.push_back(CGM.IntTy);
- if (hasNonVirtualBaseAdjustmentField(MPT, Inheritance))
+ if (hasVBPtrOffsetField(Inheritance))
fields.push_back(CGM.IntTy);
if (hasVirtualBaseAdjustmentField(Inheritance))
fields.push_back(CGM.IntTy); // VirtualBaseAdjustmentOffset
@@ -500,9 +508,10 @@ GetNullMemberPointerFields(const MemberPointerType *MPT,
fields.push_back(getAllOnesInt()); // FieldOffset
}
- if (hasVBPtrOffsetField(Inheritance))
+ if (hasNonVirtualBaseAdjustmentField(MPT->isMemberFunctionPointer(),
+ Inheritance))
fields.push_back(getZeroInt());
- if (hasNonVirtualBaseAdjustmentField(MPT, Inheritance))
+ if (hasVBPtrOffsetField(Inheritance))
fields.push_back(getZeroInt());
if (hasVirtualBaseAdjustmentField(Inheritance))
fields.push_back(getAllOnesInt());
@@ -520,27 +529,87 @@ MicrosoftCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
}
llvm::Constant *
-MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
- CharUnits offset) {
- const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
+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(llvm::ConstantInt::get(CGM.IntTy, offset.getQuantity()));
+ 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));
}
- assert(!hasNonVirtualBaseAdjustmentField(MPT, Inheritance));
- // The virtual base field starts out zero. It is adjusted by conversions to
- // member pointer types of a more derived class. See http://llvm.org/PR15713
+
+ // The rest of the fields are adjusted by conversions to a more derived class.
if (hasVirtualBaseAdjustmentField(Inheritance))
fields.push_back(getZeroInt());
- if (fields.size() == 1)
- return fields[0];
+
return llvm::ConstantStruct::getAnon(fields);
}
+llvm::Constant *
+MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
+ CharUnits offset) {
+ 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.
@@ -760,10 +829,10 @@ MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
// We need to extract values.
unsigned I = 0;
FunctionPointer = Builder.CreateExtractValue(MemPtr, I++);
- if (hasVBPtrOffsetField(Inheritance))
- VBPtrOffset = 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++);
}