2010-06-10 07:25:41 +08:00
|
|
|
//===--- MicrosoftCXXABI.cpp - Emit LLVM Code from ASTs for a Module ------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2011-04-15 13:22:18 +08:00
|
|
|
// This provides C++ code generation targeting the Microsoft Visual C++ ABI.
|
2010-06-10 07:25:41 +08:00
|
|
|
// The class in this file generates structures that follow the Microsoft
|
|
|
|
// Visual C++ ABI, which is actually not very well documented at all outside
|
|
|
|
// of Microsoft.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "CGCXXABI.h"
|
|
|
|
#include "CodeGenModule.h"
|
2013-06-19 23:20:38 +08:00
|
|
|
#include "CGVTables.h"
|
|
|
|
#include "MicrosoftVBTables.h"
|
2010-06-10 07:25:41 +08:00
|
|
|
#include "clang/AST/Decl.h"
|
|
|
|
#include "clang/AST/DeclCXX.h"
|
2013-07-30 17:46:19 +08:00
|
|
|
#include "clang/AST/VTableBuilder.h"
|
2010-06-10 07:25:41 +08:00
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
using namespace CodeGen;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2010-08-16 11:33:14 +08:00
|
|
|
class MicrosoftCXXABI : public CGCXXABI {
|
2010-06-10 07:25:41 +08:00
|
|
|
public:
|
2011-01-14 02:57:25 +08:00
|
|
|
MicrosoftCXXABI(CodeGenModule &CGM) : CGCXXABI(CGM) {}
|
2010-08-31 15:33:07 +08:00
|
|
|
|
2013-07-01 04:40:16 +08:00
|
|
|
bool HasThisReturn(GlobalDecl GD) const;
|
|
|
|
|
2013-04-17 20:54:10 +08:00
|
|
|
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 {
|
2013-06-21 20:45:15 +08:00
|
|
|
if (RD->hasNonTrivialCopyConstructor() || RD->hasNonTrivialDestructor())
|
2013-04-17 20:54:10 +08:00
|
|
|
return RAA_DirectInMemory;
|
|
|
|
return RAA_Default;
|
|
|
|
}
|
|
|
|
|
2012-07-18 01:10:11 +08:00
|
|
|
StringRef GetPureVirtualCallName() { return "_purecall"; }
|
2012-10-17 06:56:05 +08:00
|
|
|
// No known support for deleted functions in MSVC yet, so this choice is
|
|
|
|
// arbitrary.
|
|
|
|
StringRef GetDeletedVirtualCallName() { return "_purecall"; }
|
2012-07-18 01:10:11 +08:00
|
|
|
|
2012-09-25 18:10:39 +08:00
|
|
|
llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *ptr,
|
|
|
|
QualType type);
|
|
|
|
|
2013-05-30 02:02:47 +08:00
|
|
|
llvm::Value *GetVirtualBaseClassOffset(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *This,
|
|
|
|
const CXXRecordDecl *ClassDecl,
|
|
|
|
const CXXRecordDecl *BaseClassDecl);
|
|
|
|
|
2010-08-31 15:33:07 +08:00
|
|
|
void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
|
|
|
|
CXXCtorType Type,
|
|
|
|
CanQualType &ResTy,
|
2012-09-25 16:00:39 +08:00
|
|
|
SmallVectorImpl<CanQualType> &ArgTys);
|
2010-08-31 15:33:07 +08:00
|
|
|
|
2013-06-19 23:20:38 +08:00
|
|
|
llvm::BasicBlock *EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
|
|
|
|
const CXXRecordDecl *RD);
|
2013-02-27 21:46:31 +08:00
|
|
|
|
2013-08-05 01:30:04 +08:00
|
|
|
void EmitCXXConstructors(const CXXConstructorDecl *D);
|
|
|
|
|
[ms-cxxabi] Emit linkonce complete dtors in TUs that need them
Based on Peter Collingbourne's destructor patches.
Prior to this change, clang was considering ?1 to be the complete
destructor and the base destructor, which was wrong. This lead to
crashes when clang tried to emit two LLVM functions with the same name.
In this ABI, TUs with non-inline dtors might not emit a complete
destructor. They are emitted as inline thunks in TUs that need them,
and they always delegate to the base dtors of the complete class and its
virtual bases. This change uses the DeferredDecls machinery to emit
complete dtors as needed.
Currently in clang try body destructors can catch exceptions thrown by
virtual base destructors. In the Microsoft C++ ABI, clang may not have
the destructor definition, in which case clang won't wrap the virtual
virtual base destructor calls in a try-catch. Diagnosing this in user
code is TODO.
Finally, for classes that don't use virtual inheritance, MSVC always
calls the base destructor (?1) directly. This is a useful code size
optimization that avoids emitting lots of extra thunks or aliases.
Implementing it also means our existing tests continue to pass, and is
consistent with MSVC's output.
We can do the same for Itanium by tweaking GetAddrOfCXXDestructor, but
it will require further testing.
Reviewers: rjmccall
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1066
llvm-svn: 186828
2013-07-22 21:51:44 +08:00
|
|
|
// Background on MSVC destructors
|
|
|
|
// ==============================
|
|
|
|
//
|
|
|
|
// Both Itanium and MSVC ABIs have destructor variants. The variant names
|
|
|
|
// roughly correspond in the following way:
|
|
|
|
// Itanium Microsoft
|
|
|
|
// Base -> no name, just ~Class
|
|
|
|
// Complete -> vbase destructor
|
|
|
|
// Deleting -> scalar deleting destructor
|
|
|
|
// vector deleting destructor
|
|
|
|
//
|
|
|
|
// The base and complete destructors are the same as in Itanium, although the
|
|
|
|
// complete destructor does not accept a VTT parameter when there are virtual
|
|
|
|
// bases. A separate mechanism involving vtordisps is used to ensure that
|
|
|
|
// virtual methods of destroyed subobjects are not called.
|
|
|
|
//
|
|
|
|
// The deleting destructors accept an i32 bitfield as a second parameter. Bit
|
|
|
|
// 1 indicates if the memory should be deleted. Bit 2 indicates if the this
|
|
|
|
// pointer points to an array. The scalar deleting destructor assumes that
|
|
|
|
// bit 2 is zero, and therefore does not contain a loop.
|
|
|
|
//
|
|
|
|
// For virtual destructors, only one entry is reserved in the vftable, and it
|
|
|
|
// always points to the vector deleting destructor. The vector deleting
|
|
|
|
// destructor is the most general, so it can be used to destroy objects in
|
|
|
|
// place, delete single heap objects, or delete arrays.
|
|
|
|
//
|
|
|
|
// A TU defining a non-inline destructor is only guaranteed to emit a base
|
|
|
|
// destructor, and all of the other variants are emitted on an as-needed basis
|
|
|
|
// in COMDATs. Because a non-base destructor can be emitted in a TU that
|
|
|
|
// lacks a definition for the destructor, non-base destructors must always
|
|
|
|
// delegate to or alias the base destructor.
|
|
|
|
|
|
|
|
void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
|
2010-08-31 15:33:07 +08:00
|
|
|
CXXDtorType Type,
|
|
|
|
CanQualType &ResTy,
|
2013-02-13 16:37:51 +08:00
|
|
|
SmallVectorImpl<CanQualType> &ArgTys);
|
2010-08-31 15:33:07 +08:00
|
|
|
|
[ms-cxxabi] Emit linkonce complete dtors in TUs that need them
Based on Peter Collingbourne's destructor patches.
Prior to this change, clang was considering ?1 to be the complete
destructor and the base destructor, which was wrong. This lead to
crashes when clang tried to emit two LLVM functions with the same name.
In this ABI, TUs with non-inline dtors might not emit a complete
destructor. They are emitted as inline thunks in TUs that need them,
and they always delegate to the base dtors of the complete class and its
virtual bases. This change uses the DeferredDecls machinery to emit
complete dtors as needed.
Currently in clang try body destructors can catch exceptions thrown by
virtual base destructors. In the Microsoft C++ ABI, clang may not have
the destructor definition, in which case clang won't wrap the virtual
virtual base destructor calls in a try-catch. Diagnosing this in user
code is TODO.
Finally, for classes that don't use virtual inheritance, MSVC always
calls the base destructor (?1) directly. This is a useful code size
optimization that avoids emitting lots of extra thunks or aliases.
Implementing it also means our existing tests continue to pass, and is
consistent with MSVC's output.
We can do the same for Itanium by tweaking GetAddrOfCXXDestructor, but
it will require further testing.
Reviewers: rjmccall
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1066
llvm-svn: 186828
2013-07-22 21:51:44 +08:00
|
|
|
/// Non-base dtors should be emitted as delegating thunks in this ABI.
|
|
|
|
bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,
|
|
|
|
CXXDtorType DT) const {
|
|
|
|
return DT != Dtor_Base;
|
|
|
|
}
|
|
|
|
|
|
|
|
void EmitCXXDestructors(const CXXDestructorDecl *D);
|
|
|
|
|
2013-08-21 14:25:03 +08:00
|
|
|
const CXXRecordDecl *getThisArgumentTypeForMethod(const CXXMethodDecl *MD) {
|
|
|
|
MD = MD->getCanonicalDecl();
|
|
|
|
if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD)) {
|
|
|
|
MicrosoftVFTableContext::MethodVFTableLocation ML =
|
|
|
|
CGM.getVFTableContext().getMethodVFTableLocation(MD);
|
|
|
|
// The vbases might be ordered differently in the final overrider object
|
|
|
|
// and the complete object, so the "this" argument may sometimes point to
|
|
|
|
// memory that has no particular type (e.g. past the complete object).
|
|
|
|
// In this case, we just use a generic pointer type.
|
|
|
|
// FIXME: might want to have a more precise type in the non-virtual
|
|
|
|
// multiple inheritance case.
|
|
|
|
if (ML.VBase || !ML.VFTableOffset.isZero())
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return MD->getParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Value *adjustThisArgumentForVirtualCall(CodeGenFunction &CGF,
|
|
|
|
GlobalDecl GD,
|
|
|
|
llvm::Value *This);
|
|
|
|
|
2010-08-31 15:33:07 +08:00
|
|
|
void BuildInstanceFunctionParams(CodeGenFunction &CGF,
|
|
|
|
QualType &ResTy,
|
2012-09-25 16:00:39 +08:00
|
|
|
FunctionArgList &Params);
|
2010-08-31 15:33:07 +08:00
|
|
|
|
2013-08-21 14:25:03 +08:00
|
|
|
llvm::Value *adjustThisParameterInVirtualFunctionPrologue(
|
|
|
|
CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This);
|
|
|
|
|
2012-09-25 16:00:39 +08:00
|
|
|
void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
|
2011-01-27 10:46:02 +08:00
|
|
|
|
2013-07-01 04:40:16 +08:00
|
|
|
void EmitConstructorCall(CodeGenFunction &CGF,
|
|
|
|
const CXXConstructorDecl *D, CXXCtorType Type,
|
|
|
|
bool ForVirtualBase, bool Delegating,
|
2013-06-20 02:10:35 +08:00
|
|
|
llvm::Value *This,
|
|
|
|
CallExpr::const_arg_iterator ArgBeg,
|
|
|
|
CallExpr::const_arg_iterator ArgEnd);
|
2013-08-21 14:25:03 +08:00
|
|
|
|
|
|
|
llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
|
|
|
|
llvm::Value *This, llvm::Type *Ty);
|
|
|
|
|
2013-07-01 04:40:16 +08:00
|
|
|
void EmitVirtualDestructorCall(CodeGenFunction &CGF,
|
|
|
|
const CXXDestructorDecl *Dtor,
|
|
|
|
CXXDtorType DtorType, SourceLocation CallLoc,
|
|
|
|
llvm::Value *This);
|
2013-02-15 22:45:22 +08:00
|
|
|
|
2013-06-19 23:20:38 +08:00
|
|
|
void EmitVirtualInheritanceTables(llvm::GlobalVariable::LinkageTypes Linkage,
|
|
|
|
const CXXRecordDecl *RD);
|
|
|
|
|
2012-05-01 14:13:13 +08:00
|
|
|
void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
|
|
|
|
llvm::GlobalVariable *DeclPtr,
|
|
|
|
bool PerformInit);
|
|
|
|
|
2011-01-27 10:46:02 +08:00
|
|
|
// ==== Notes on array cookies =========
|
|
|
|
//
|
|
|
|
// MSVC seems to only use cookies when the class has a destructor; a
|
|
|
|
// two-argument usual array deallocation function isn't sufficient.
|
|
|
|
//
|
|
|
|
// For example, this code prints "100" and "1":
|
|
|
|
// struct A {
|
|
|
|
// char x;
|
|
|
|
// void *operator new[](size_t sz) {
|
|
|
|
// printf("%u\n", sz);
|
|
|
|
// return malloc(sz);
|
|
|
|
// }
|
|
|
|
// void operator delete[](void *p, size_t sz) {
|
|
|
|
// printf("%u\n", sz);
|
|
|
|
// free(p);
|
|
|
|
// }
|
|
|
|
// };
|
|
|
|
// int main() {
|
|
|
|
// A *p = new A[100];
|
|
|
|
// delete[] p;
|
|
|
|
// }
|
|
|
|
// Whereas it prints "104" and "104" if you give A a destructor.
|
2012-05-01 13:23:51 +08:00
|
|
|
|
|
|
|
bool requiresArrayCookie(const CXXDeleteExpr *expr, QualType elementType);
|
|
|
|
bool requiresArrayCookie(const CXXNewExpr *expr);
|
|
|
|
CharUnits getArrayCookieSizeImpl(QualType type);
|
|
|
|
llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *NewPtr,
|
|
|
|
llvm::Value *NumElements,
|
|
|
|
const CXXNewExpr *expr,
|
|
|
|
QualType ElementType);
|
|
|
|
llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *allocPtr,
|
|
|
|
CharUnits cookieSize);
|
2013-03-23 03:02:54 +08:00
|
|
|
|
|
|
|
private:
|
2013-04-12 02:13:19 +08:00
|
|
|
llvm::Constant *getZeroInt() {
|
|
|
|
return llvm::ConstantInt::get(CGM.IntTy, 0);
|
2013-03-23 03:02:54 +08:00
|
|
|
}
|
|
|
|
|
2013-04-12 02:13:19 +08:00
|
|
|
llvm::Constant *getAllOnesInt() {
|
|
|
|
return llvm::Constant::getAllOnesValue(CGM.IntTy);
|
2013-03-23 03:02:54 +08:00
|
|
|
}
|
|
|
|
|
2013-05-10 05:01:17 +08:00
|
|
|
llvm::Constant *getConstantOrZeroInt(llvm::Constant *C) {
|
|
|
|
return C ? C : getZeroInt();
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Value *getValueOrZeroInt(llvm::Value *C) {
|
|
|
|
return C ? C : getZeroInt();
|
|
|
|
}
|
|
|
|
|
2013-04-12 02:13:19 +08:00
|
|
|
void
|
|
|
|
GetNullMemberPointerFields(const MemberPointerType *MPT,
|
|
|
|
llvm::SmallVectorImpl<llvm::Constant *> &fields);
|
|
|
|
|
2013-05-30 02:02:47 +08:00
|
|
|
/// \brief Finds the offset from the base of RD to the vbptr it uses, even if
|
|
|
|
/// it is reusing a vbptr from a non-virtual base. RD must have morally
|
|
|
|
/// virtual bases.
|
|
|
|
CharUnits GetVBPtrOffsetFromBases(const CXXRecordDecl *RD);
|
|
|
|
|
|
|
|
/// \brief Shared code for virtual base adjustment. Returns the offset from
|
|
|
|
/// the vbptr to the virtual base. Optionally returns the address of the
|
|
|
|
/// vbptr itself.
|
|
|
|
llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *Base,
|
|
|
|
llvm::Value *VBPtrOffset,
|
|
|
|
llvm::Value *VBTableOffset,
|
|
|
|
llvm::Value **VBPtr = 0);
|
|
|
|
|
|
|
|
/// \brief Performs a full virtual base adjustment. Used to dereference
|
|
|
|
/// pointers to members of virtual bases.
|
2013-04-12 02:13:19 +08:00
|
|
|
llvm::Value *AdjustVirtualBase(CodeGenFunction &CGF, const CXXRecordDecl *RD,
|
|
|
|
llvm::Value *Base,
|
|
|
|
llvm::Value *VirtualBaseAdjustmentOffset,
|
|
|
|
llvm::Value *VBPtrOffset /* optional */);
|
|
|
|
|
2013-05-03 09:15:11 +08:00
|
|
|
/// \brief Emits a full member pointer with the fields common to data and
|
|
|
|
/// function member pointers.
|
|
|
|
llvm::Constant *EmitFullMemberPointer(llvm::Constant *FirstField,
|
|
|
|
bool IsMemberFunction,
|
2013-05-10 05:01:17 +08:00
|
|
|
const CXXRecordDecl *RD,
|
|
|
|
CharUnits NonVirtualBaseAdjustment);
|
|
|
|
|
|
|
|
llvm::Constant *BuildMemberPointer(const CXXRecordDecl *RD,
|
|
|
|
const CXXMethodDecl *MD,
|
|
|
|
CharUnits NonVirtualBaseAdjustment);
|
|
|
|
|
|
|
|
bool MemberPointerConstantIsNull(const MemberPointerType *MPT,
|
|
|
|
llvm::Constant *MP);
|
2013-05-03 09:15:11 +08:00
|
|
|
|
2013-06-19 23:20:38 +08:00
|
|
|
/// \brief - Initialize all vbptrs of 'this' with RD as the complete type.
|
|
|
|
void EmitVBPtrStores(CodeGenFunction &CGF, const CXXRecordDecl *RD);
|
|
|
|
|
|
|
|
/// \brief Caching wrapper around VBTableBuilder::enumerateVBTables().
|
|
|
|
const VBTableVector &EnumerateVBTables(const CXXRecordDecl *RD);
|
|
|
|
|
2013-03-23 03:02:54 +08:00
|
|
|
public:
|
2013-04-12 02:13:19 +08:00
|
|
|
virtual llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT);
|
|
|
|
|
|
|
|
virtual bool isZeroInitializable(const MemberPointerType *MPT);
|
|
|
|
|
2013-03-23 03:02:54 +08:00
|
|
|
virtual llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
|
|
|
|
|
|
|
|
virtual llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
|
|
|
|
CharUnits offset);
|
2013-05-03 09:15:11 +08:00
|
|
|
virtual llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
|
|
|
|
virtual llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT);
|
2013-03-23 03:02:54 +08:00
|
|
|
|
2013-05-01 04:15:14 +08:00
|
|
|
virtual llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *L,
|
|
|
|
llvm::Value *R,
|
|
|
|
const MemberPointerType *MPT,
|
|
|
|
bool Inequality);
|
|
|
|
|
2013-03-23 03:02:54 +08:00
|
|
|
virtual llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *MemPtr,
|
|
|
|
const MemberPointerType *MPT);
|
|
|
|
|
|
|
|
virtual llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *Base,
|
|
|
|
llvm::Value *MemPtr,
|
|
|
|
const MemberPointerType *MPT);
|
|
|
|
|
2013-05-10 05:01:17 +08:00
|
|
|
virtual llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF,
|
|
|
|
const CastExpr *E,
|
|
|
|
llvm::Value *Src);
|
|
|
|
|
|
|
|
virtual llvm::Constant *EmitMemberPointerConversion(const CastExpr *E,
|
|
|
|
llvm::Constant *Src);
|
|
|
|
|
2013-04-12 02:13:19 +08:00
|
|
|
virtual llvm::Value *
|
|
|
|
EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *&This,
|
|
|
|
llvm::Value *MemPtr,
|
|
|
|
const MemberPointerType *MPT);
|
|
|
|
|
2013-06-19 23:20:38 +08:00
|
|
|
private:
|
|
|
|
/// VBTables - All the vbtables which have been referenced.
|
|
|
|
llvm::DenseMap<const CXXRecordDecl *, VBTableVector> VBTablesMap;
|
2010-06-10 07:25:41 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-09-25 18:10:39 +08:00
|
|
|
llvm::Value *MicrosoftCXXABI::adjustToCompleteObject(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *ptr,
|
|
|
|
QualType type) {
|
|
|
|
// FIXME: implement
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
2013-06-05 05:32:29 +08:00
|
|
|
/// \brief Finds the first non-virtual base of RD that has virtual bases. If RD
|
|
|
|
/// doesn't have a vbptr, it will reuse the vbptr of the returned class.
|
|
|
|
static const CXXRecordDecl *FindFirstNVBaseWithVBases(const CXXRecordDecl *RD) {
|
|
|
|
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
|
|
|
|
E = RD->bases_end(); I != E; ++I) {
|
|
|
|
const CXXRecordDecl *Base = I->getType()->getAsCXXRecordDecl();
|
|
|
|
if (!I->isVirtual() && Base->getNumVBases() > 0)
|
|
|
|
return Base;
|
|
|
|
}
|
|
|
|
llvm_unreachable("RD must have an nv base with vbases");
|
|
|
|
}
|
|
|
|
|
2013-05-30 02:02:47 +08:00
|
|
|
CharUnits MicrosoftCXXABI::GetVBPtrOffsetFromBases(const CXXRecordDecl *RD) {
|
|
|
|
assert(RD->getNumVBases());
|
|
|
|
CharUnits Total = CharUnits::Zero();
|
|
|
|
while (RD) {
|
|
|
|
const ASTRecordLayout &RDLayout = getContext().getASTRecordLayout(RD);
|
|
|
|
CharUnits VBPtrOffset = RDLayout.getVBPtrOffset();
|
|
|
|
// -1 is the sentinel for no vbptr.
|
|
|
|
if (VBPtrOffset != CharUnits::fromQuantity(-1)) {
|
|
|
|
Total += VBPtrOffset;
|
|
|
|
break;
|
|
|
|
}
|
2013-06-05 05:32:29 +08:00
|
|
|
RD = FindFirstNVBaseWithVBases(RD);
|
|
|
|
Total += RDLayout.getBaseClassOffset(RD);
|
2013-05-30 02:02:47 +08:00
|
|
|
}
|
|
|
|
return Total;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Value *
|
|
|
|
MicrosoftCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *This,
|
|
|
|
const CXXRecordDecl *ClassDecl,
|
|
|
|
const CXXRecordDecl *BaseClassDecl) {
|
|
|
|
int64_t VBPtrChars = GetVBPtrOffsetFromBases(ClassDecl).getQuantity();
|
|
|
|
llvm::Value *VBPtrOffset = llvm::ConstantInt::get(CGM.PtrDiffTy, VBPtrChars);
|
|
|
|
CharUnits IntSize = getContext().getTypeSizeInChars(getContext().IntTy);
|
2013-06-05 05:32:29 +08:00
|
|
|
CharUnits VBTableChars = IntSize * GetVBTableIndex(ClassDecl, BaseClassDecl);
|
2013-05-30 02:02:47 +08:00
|
|
|
llvm::Value *VBTableOffset =
|
|
|
|
llvm::ConstantInt::get(CGM.IntTy, VBTableChars.getQuantity());
|
|
|
|
|
|
|
|
llvm::Value *VBPtrToNewBase =
|
|
|
|
GetVBaseOffsetFromVBPtr(CGF, This, VBTableOffset, VBPtrOffset);
|
|
|
|
VBPtrToNewBase =
|
|
|
|
CGF.Builder.CreateSExtOrBitCast(VBPtrToNewBase, CGM.PtrDiffTy);
|
|
|
|
return CGF.Builder.CreateNSWAdd(VBPtrOffset, VBPtrToNewBase);
|
|
|
|
}
|
|
|
|
|
2013-07-01 04:40:16 +08:00
|
|
|
bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD) const {
|
|
|
|
return isa<CXXConstructorDecl>(GD.getDecl());
|
2012-09-25 16:00:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void MicrosoftCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
|
|
|
|
CXXCtorType Type,
|
|
|
|
CanQualType &ResTy,
|
|
|
|
SmallVectorImpl<CanQualType> &ArgTys) {
|
2013-07-01 04:40:16 +08:00
|
|
|
// 'this' parameter and 'this' return are already in place
|
2013-02-27 21:46:31 +08:00
|
|
|
|
|
|
|
const CXXRecordDecl *Class = Ctor->getParent();
|
|
|
|
if (Class->getNumVBases()) {
|
|
|
|
// Constructors of classes with virtual bases take an implicit parameter.
|
|
|
|
ArgTys.push_back(CGM.getContext().IntTy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-19 23:20:38 +08:00
|
|
|
llvm::BasicBlock *
|
|
|
|
MicrosoftCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
|
|
|
|
const CXXRecordDecl *RD) {
|
2013-02-27 21:46:31 +08:00
|
|
|
llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF);
|
|
|
|
assert(IsMostDerivedClass &&
|
|
|
|
"ctor for a class with virtual bases must have an implicit parameter");
|
2013-06-19 23:20:38 +08:00
|
|
|
llvm::Value *IsCompleteObject =
|
|
|
|
CGF.Builder.CreateIsNotNull(IsMostDerivedClass, "is_complete_object");
|
2013-02-27 21:46:31 +08:00
|
|
|
|
|
|
|
llvm::BasicBlock *CallVbaseCtorsBB = CGF.createBasicBlock("ctor.init_vbases");
|
|
|
|
llvm::BasicBlock *SkipVbaseCtorsBB = CGF.createBasicBlock("ctor.skip_vbases");
|
|
|
|
CGF.Builder.CreateCondBr(IsCompleteObject,
|
|
|
|
CallVbaseCtorsBB, SkipVbaseCtorsBB);
|
|
|
|
|
|
|
|
CGF.EmitBlock(CallVbaseCtorsBB);
|
2013-06-19 23:20:38 +08:00
|
|
|
|
|
|
|
// Fill in the vbtable pointers here.
|
|
|
|
EmitVBPtrStores(CGF, RD);
|
2013-02-27 21:46:31 +08:00
|
|
|
|
|
|
|
// CGF will put the base ctor calls in this basic block for us later.
|
|
|
|
|
|
|
|
return SkipVbaseCtorsBB;
|
2012-09-25 16:00:39 +08:00
|
|
|
}
|
|
|
|
|
2013-08-05 01:30:04 +08:00
|
|
|
void MicrosoftCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {
|
|
|
|
// There's only one constructor type in this ABI.
|
|
|
|
CGM.EmitGlobal(GlobalDecl(D, Ctor_Complete));
|
|
|
|
}
|
|
|
|
|
2013-06-19 23:20:38 +08:00
|
|
|
void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF,
|
|
|
|
const CXXRecordDecl *RD) {
|
|
|
|
llvm::Value *ThisInt8Ptr =
|
|
|
|
CGF.Builder.CreateBitCast(getThisValue(CGF), CGM.Int8PtrTy, "this.int8");
|
|
|
|
|
|
|
|
const VBTableVector &VBTables = EnumerateVBTables(RD);
|
|
|
|
for (VBTableVector::const_iterator I = VBTables.begin(), E = VBTables.end();
|
|
|
|
I != E; ++I) {
|
|
|
|
const ASTRecordLayout &SubobjectLayout =
|
|
|
|
CGM.getContext().getASTRecordLayout(I->VBPtrSubobject.getBase());
|
|
|
|
uint64_t Offs = (I->VBPtrSubobject.getBaseOffset() +
|
|
|
|
SubobjectLayout.getVBPtrOffset()).getQuantity();
|
|
|
|
llvm::Value *VBPtr =
|
|
|
|
CGF.Builder.CreateConstInBoundsGEP1_64(ThisInt8Ptr, Offs);
|
|
|
|
VBPtr = CGF.Builder.CreateBitCast(VBPtr, I->GV->getType()->getPointerTo(0),
|
|
|
|
"vbptr." + I->ReusingBase->getName());
|
|
|
|
CGF.Builder.CreateStore(I->GV, VBPtr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-13 16:37:51 +08:00
|
|
|
void MicrosoftCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
|
|
|
|
CXXDtorType Type,
|
|
|
|
CanQualType &ResTy,
|
|
|
|
SmallVectorImpl<CanQualType> &ArgTys) {
|
|
|
|
// 'this' is already in place
|
2013-07-01 04:40:16 +08:00
|
|
|
|
2013-02-13 16:37:51 +08:00
|
|
|
// TODO: 'for base' flag
|
|
|
|
|
|
|
|
if (Type == Dtor_Deleting) {
|
2013-08-27 18:38:19 +08:00
|
|
|
// The scalar deleting destructor takes an implicit int parameter.
|
|
|
|
ArgTys.push_back(CGM.getContext().IntTy);
|
2013-02-13 16:37:51 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[ms-cxxabi] Emit linkonce complete dtors in TUs that need them
Based on Peter Collingbourne's destructor patches.
Prior to this change, clang was considering ?1 to be the complete
destructor and the base destructor, which was wrong. This lead to
crashes when clang tried to emit two LLVM functions with the same name.
In this ABI, TUs with non-inline dtors might not emit a complete
destructor. They are emitted as inline thunks in TUs that need them,
and they always delegate to the base dtors of the complete class and its
virtual bases. This change uses the DeferredDecls machinery to emit
complete dtors as needed.
Currently in clang try body destructors can catch exceptions thrown by
virtual base destructors. In the Microsoft C++ ABI, clang may not have
the destructor definition, in which case clang won't wrap the virtual
virtual base destructor calls in a try-catch. Diagnosing this in user
code is TODO.
Finally, for classes that don't use virtual inheritance, MSVC always
calls the base destructor (?1) directly. This is a useful code size
optimization that avoids emitting lots of extra thunks or aliases.
Implementing it also means our existing tests continue to pass, and is
consistent with MSVC's output.
We can do the same for Itanium by tweaking GetAddrOfCXXDestructor, but
it will require further testing.
Reviewers: rjmccall
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1066
llvm-svn: 186828
2013-07-22 21:51:44 +08:00
|
|
|
void MicrosoftCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) {
|
|
|
|
// The TU defining a dtor is only guaranteed to emit a base destructor. All
|
|
|
|
// other destructor variants are delegating thunks.
|
|
|
|
CGM.EmitGlobal(GlobalDecl(D, Dtor_Base));
|
|
|
|
}
|
|
|
|
|
2013-08-21 14:25:03 +08:00
|
|
|
llvm::Value *MicrosoftCXXABI::adjustThisArgumentForVirtualCall(
|
|
|
|
CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This) {
|
|
|
|
GD = GD.getCanonicalDecl();
|
|
|
|
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
|
|
|
|
if (isa<CXXDestructorDecl>(MD))
|
|
|
|
return This;
|
|
|
|
|
|
|
|
MicrosoftVFTableContext::MethodVFTableLocation ML =
|
|
|
|
CGM.getVFTableContext().getMethodVFTableLocation(GD);
|
|
|
|
|
|
|
|
unsigned AS = cast<llvm::PointerType>(This->getType())->getAddressSpace();
|
|
|
|
llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS);
|
|
|
|
if (ML.VBase) {
|
|
|
|
This = CGF.Builder.CreateBitCast(This, charPtrTy);
|
|
|
|
llvm::Value *VBaseOffset = CGM.getCXXABI()
|
|
|
|
.GetVirtualBaseClassOffset(CGF, This, MD->getParent(), ML.VBase);
|
|
|
|
This = CGF.Builder.CreateInBoundsGEP(This, VBaseOffset);
|
|
|
|
}
|
|
|
|
CharUnits StaticOffset = ML.VFTableOffset;
|
|
|
|
if (!StaticOffset.isZero()) {
|
|
|
|
assert(StaticOffset.isPositive());
|
|
|
|
This = CGF.Builder.CreateBitCast(This, charPtrTy);
|
|
|
|
This = CGF.Builder
|
|
|
|
.CreateConstInBoundsGEP1_64(This, StaticOffset.getQuantity());
|
|
|
|
}
|
|
|
|
return This;
|
|
|
|
}
|
|
|
|
|
2013-02-13 16:37:51 +08:00
|
|
|
static bool IsDeletingDtor(GlobalDecl GD) {
|
|
|
|
const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl());
|
|
|
|
if (isa<CXXDestructorDecl>(MD)) {
|
|
|
|
return GD.getDtorType() == Dtor_Deleting;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-09-25 16:00:39 +08:00
|
|
|
void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
|
|
|
|
QualType &ResTy,
|
|
|
|
FunctionArgList &Params) {
|
|
|
|
BuildThisParam(CGF, Params);
|
2013-02-13 16:37:51 +08:00
|
|
|
|
2013-02-27 21:46:31 +08:00
|
|
|
ASTContext &Context = getContext();
|
|
|
|
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
|
|
|
|
if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) {
|
|
|
|
ImplicitParamDecl *IsMostDerived
|
|
|
|
= ImplicitParamDecl::Create(Context, 0,
|
|
|
|
CGF.CurGD.getDecl()->getLocation(),
|
|
|
|
&Context.Idents.get("is_most_derived"),
|
|
|
|
Context.IntTy);
|
|
|
|
Params.push_back(IsMostDerived);
|
|
|
|
getStructorImplicitParamDecl(CGF) = IsMostDerived;
|
|
|
|
} else if (IsDeletingDtor(CGF.CurGD)) {
|
2013-02-13 16:37:51 +08:00
|
|
|
ImplicitParamDecl *ShouldDelete
|
|
|
|
= ImplicitParamDecl::Create(Context, 0,
|
|
|
|
CGF.CurGD.getDecl()->getLocation(),
|
|
|
|
&Context.Idents.get("should_call_delete"),
|
2013-08-27 18:38:19 +08:00
|
|
|
Context.IntTy);
|
2013-02-13 16:37:51 +08:00
|
|
|
Params.push_back(ShouldDelete);
|
|
|
|
getStructorImplicitParamDecl(CGF) = ShouldDelete;
|
|
|
|
}
|
2012-09-25 16:00:39 +08:00
|
|
|
}
|
|
|
|
|
2013-08-21 14:25:03 +08:00
|
|
|
llvm::Value *MicrosoftCXXABI::adjustThisParameterInVirtualFunctionPrologue(
|
|
|
|
CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This) {
|
|
|
|
GD = GD.getCanonicalDecl();
|
|
|
|
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
|
|
|
|
if (isa<CXXDestructorDecl>(MD))
|
|
|
|
return This;
|
|
|
|
|
|
|
|
// In this ABI, every virtual function takes a pointer to one of the
|
|
|
|
// subobjects that first defines it as the 'this' parameter, rather than a
|
|
|
|
// pointer to ther final overrider subobject. Thus, we need to adjust it back
|
|
|
|
// to the final overrider subobject before use.
|
|
|
|
// See comments in the MicrosoftVFTableContext implementation for the details.
|
|
|
|
|
|
|
|
MicrosoftVFTableContext::MethodVFTableLocation ML =
|
|
|
|
CGM.getVFTableContext().getMethodVFTableLocation(GD);
|
|
|
|
CharUnits Adjustment = ML.VFTableOffset;
|
|
|
|
if (ML.VBase) {
|
|
|
|
const ASTRecordLayout &DerivedLayout =
|
|
|
|
CGF.getContext().getASTRecordLayout(MD->getParent());
|
|
|
|
Adjustment += DerivedLayout.getVBaseClassOffset(ML.VBase);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Adjustment.isZero())
|
|
|
|
return This;
|
|
|
|
|
|
|
|
unsigned AS = cast<llvm::PointerType>(This->getType())->getAddressSpace();
|
|
|
|
llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS),
|
|
|
|
*thisTy = This->getType();
|
|
|
|
|
|
|
|
This = CGF.Builder.CreateBitCast(This, charPtrTy);
|
|
|
|
assert(Adjustment.isPositive());
|
|
|
|
This = CGF.Builder.CreateConstGEP1_64(This, -Adjustment.getQuantity());
|
|
|
|
return CGF.Builder.CreateBitCast(This, thisTy);
|
|
|
|
}
|
|
|
|
|
2012-09-25 16:00:39 +08:00
|
|
|
void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
|
|
|
|
EmitThisParam(CGF);
|
2013-07-01 04:40:16 +08:00
|
|
|
|
|
|
|
/// If this is a function that the ABI specifies returns 'this', initialize
|
|
|
|
/// the return slot to 'this' at the start of the function.
|
|
|
|
///
|
|
|
|
/// Unlike the setting of return types, this is done within the ABI
|
|
|
|
/// implementation instead of by clients of CGCXXABI because:
|
|
|
|
/// 1) getThisValue is currently protected
|
|
|
|
/// 2) in theory, an ABI could implement 'this' returns some other way;
|
|
|
|
/// HasThisReturn only specifies a contract, not the implementation
|
|
|
|
if (HasThisReturn(CGF.CurGD))
|
2012-09-25 16:00:39 +08:00
|
|
|
CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
|
2013-02-27 21:46:31 +08:00
|
|
|
|
|
|
|
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
|
|
|
|
if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) {
|
|
|
|
assert(getStructorImplicitParamDecl(CGF) &&
|
|
|
|
"no implicit parameter for a constructor with virtual bases?");
|
|
|
|
getStructorImplicitParamValue(CGF)
|
|
|
|
= CGF.Builder.CreateLoad(
|
|
|
|
CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)),
|
|
|
|
"is_most_derived");
|
|
|
|
}
|
|
|
|
|
2013-02-13 16:37:51 +08:00
|
|
|
if (IsDeletingDtor(CGF.CurGD)) {
|
|
|
|
assert(getStructorImplicitParamDecl(CGF) &&
|
|
|
|
"no implicit parameter for a deleting destructor?");
|
|
|
|
getStructorImplicitParamValue(CGF)
|
|
|
|
= CGF.Builder.CreateLoad(
|
|
|
|
CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)),
|
|
|
|
"should_call_delete");
|
|
|
|
}
|
2012-09-25 16:00:39 +08:00
|
|
|
}
|
|
|
|
|
2013-07-01 04:40:16 +08:00
|
|
|
void MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF,
|
2013-06-20 02:10:35 +08:00
|
|
|
const CXXConstructorDecl *D,
|
2013-07-01 04:40:16 +08:00
|
|
|
CXXCtorType Type,
|
|
|
|
bool ForVirtualBase,
|
2013-06-20 02:10:35 +08:00
|
|
|
bool Delegating,
|
|
|
|
llvm::Value *This,
|
2013-02-27 21:46:31 +08:00
|
|
|
CallExpr::const_arg_iterator ArgBeg,
|
|
|
|
CallExpr::const_arg_iterator ArgEnd) {
|
|
|
|
assert(Type == Ctor_Complete || Type == Ctor_Base);
|
|
|
|
llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Ctor_Complete);
|
|
|
|
|
|
|
|
llvm::Value *ImplicitParam = 0;
|
|
|
|
QualType ImplicitParamTy;
|
|
|
|
if (D->getParent()->getNumVBases()) {
|
|
|
|
ImplicitParam = llvm::ConstantInt::get(CGM.Int32Ty, Type == Ctor_Complete);
|
|
|
|
ImplicitParamTy = getContext().IntTy;
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: Provide a source location here.
|
2013-06-20 02:10:35 +08:00
|
|
|
CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This,
|
2013-07-01 04:40:16 +08:00
|
|
|
ImplicitParam, ImplicitParamTy, ArgBeg, ArgEnd);
|
2013-02-27 21:46:31 +08:00
|
|
|
}
|
|
|
|
|
2013-08-21 14:25:03 +08:00
|
|
|
llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
|
|
|
|
GlobalDecl GD,
|
|
|
|
llvm::Value *This,
|
|
|
|
llvm::Type *Ty) {
|
|
|
|
GD = GD.getCanonicalDecl();
|
|
|
|
CGBuilderTy &Builder = CGF.Builder;
|
|
|
|
|
|
|
|
Ty = Ty->getPointerTo()->getPointerTo();
|
|
|
|
llvm::Value *VPtr = adjustThisArgumentForVirtualCall(CGF, GD, This);
|
|
|
|
llvm::Value *VTable = CGF.GetVTablePtr(VPtr, Ty);
|
|
|
|
|
|
|
|
MicrosoftVFTableContext::MethodVFTableLocation ML =
|
|
|
|
CGM.getVFTableContext().getMethodVFTableLocation(GD);
|
|
|
|
llvm::Value *VFuncPtr =
|
|
|
|
Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn");
|
|
|
|
return Builder.CreateLoad(VFuncPtr);
|
|
|
|
}
|
|
|
|
|
2013-07-01 04:40:16 +08:00
|
|
|
void MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
|
|
|
|
const CXXDestructorDecl *Dtor,
|
|
|
|
CXXDtorType DtorType,
|
|
|
|
SourceLocation CallLoc,
|
|
|
|
llvm::Value *This) {
|
2013-02-15 22:45:22 +08:00
|
|
|
assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
|
|
|
|
|
|
|
|
// We have only one destructor in the vftable but can get both behaviors
|
2013-08-27 18:38:19 +08:00
|
|
|
// by passing an implicit int parameter.
|
2013-08-21 14:25:03 +08:00
|
|
|
const CGFunctionInfo *FInfo =
|
|
|
|
&CGM.getTypes().arrangeCXXDestructor(Dtor, Dtor_Deleting);
|
2013-02-15 22:45:22 +08:00
|
|
|
llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
|
2013-08-21 14:25:03 +08:00
|
|
|
llvm::Value *Callee =
|
|
|
|
getVirtualFunctionPointer(CGF, GlobalDecl(Dtor, Dtor_Deleting), This, Ty);
|
2013-02-15 22:45:22 +08:00
|
|
|
|
|
|
|
ASTContext &Context = CGF.getContext();
|
2013-08-21 14:25:03 +08:00
|
|
|
llvm::Value *ImplicitParam =
|
2013-08-27 18:38:19 +08:00
|
|
|
llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(CGF.getLLVMContext()),
|
2013-02-15 22:45:22 +08:00
|
|
|
DtorType == Dtor_Deleting);
|
|
|
|
|
2013-07-01 04:40:16 +08:00
|
|
|
CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValueSlot(), This,
|
2013-08-27 18:38:19 +08:00
|
|
|
ImplicitParam, Context.IntTy, 0, 0);
|
2013-02-15 22:45:22 +08:00
|
|
|
}
|
|
|
|
|
2013-06-19 23:20:38 +08:00
|
|
|
const VBTableVector &
|
|
|
|
MicrosoftCXXABI::EnumerateVBTables(const CXXRecordDecl *RD) {
|
|
|
|
// At this layer, we can key the cache off of a single class, which is much
|
|
|
|
// easier than caching at the GlobalVariable layer.
|
|
|
|
llvm::DenseMap<const CXXRecordDecl*, VBTableVector>::iterator I;
|
|
|
|
bool added;
|
|
|
|
llvm::tie(I, added) = VBTablesMap.insert(std::make_pair(RD, VBTableVector()));
|
|
|
|
VBTableVector &VBTables = I->second;
|
|
|
|
if (!added)
|
|
|
|
return VBTables;
|
|
|
|
|
|
|
|
VBTableBuilder(CGM, RD).enumerateVBTables(VBTables);
|
|
|
|
|
|
|
|
return VBTables;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MicrosoftCXXABI::EmitVirtualInheritanceTables(
|
|
|
|
llvm::GlobalVariable::LinkageTypes Linkage, const CXXRecordDecl *RD) {
|
|
|
|
const VBTableVector &VBTables = EnumerateVBTables(RD);
|
|
|
|
for (VBTableVector::const_iterator I = VBTables.begin(), E = VBTables.end();
|
|
|
|
I != E; ++I) {
|
|
|
|
I->EmitVBTableDefinition(CGM, RD, Linkage);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-01 13:23:51 +08:00
|
|
|
bool MicrosoftCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
|
|
|
|
QualType elementType) {
|
|
|
|
// Microsoft seems to completely ignore the possibility of a
|
|
|
|
// two-argument usual deallocation function.
|
|
|
|
return elementType.isDestructedType();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MicrosoftCXXABI::requiresArrayCookie(const CXXNewExpr *expr) {
|
|
|
|
// Microsoft seems to completely ignore the possibility of a
|
|
|
|
// two-argument usual deallocation function.
|
|
|
|
return expr->getAllocatedType().isDestructedType();
|
|
|
|
}
|
|
|
|
|
|
|
|
CharUnits MicrosoftCXXABI::getArrayCookieSizeImpl(QualType type) {
|
|
|
|
// The array cookie is always a size_t; we then pad that out to the
|
|
|
|
// alignment of the element type.
|
|
|
|
ASTContext &Ctx = getContext();
|
|
|
|
return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()),
|
|
|
|
Ctx.getTypeAlignInChars(type));
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Value *MicrosoftCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *allocPtr,
|
|
|
|
CharUnits cookieSize) {
|
2012-10-25 23:39:14 +08:00
|
|
|
unsigned AS = allocPtr->getType()->getPointerAddressSpace();
|
2012-05-01 13:23:51 +08:00
|
|
|
llvm::Value *numElementsPtr =
|
|
|
|
CGF.Builder.CreateBitCast(allocPtr, CGF.SizeTy->getPointerTo(AS));
|
|
|
|
return CGF.Builder.CreateLoad(numElementsPtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Value* MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *newPtr,
|
|
|
|
llvm::Value *numElements,
|
|
|
|
const CXXNewExpr *expr,
|
|
|
|
QualType elementType) {
|
|
|
|
assert(requiresArrayCookie(expr));
|
|
|
|
|
|
|
|
// The size of the cookie.
|
|
|
|
CharUnits cookieSize = getArrayCookieSizeImpl(elementType);
|
|
|
|
|
|
|
|
// Compute an offset to the cookie.
|
|
|
|
llvm::Value *cookiePtr = newPtr;
|
|
|
|
|
|
|
|
// Write the number of elements into the appropriate slot.
|
2012-10-25 23:39:14 +08:00
|
|
|
unsigned AS = newPtr->getType()->getPointerAddressSpace();
|
2012-05-01 13:23:51 +08:00
|
|
|
llvm::Value *numElementsPtr
|
|
|
|
= CGF.Builder.CreateBitCast(cookiePtr, CGF.SizeTy->getPointerTo(AS));
|
|
|
|
CGF.Builder.CreateStore(numElements, numElementsPtr);
|
|
|
|
|
|
|
|
// Finally, compute a pointer to the actual data buffer by skipping
|
|
|
|
// over the cookie completely.
|
|
|
|
return CGF.Builder.CreateConstInBoundsGEP1_64(newPtr,
|
|
|
|
cookieSize.getQuantity());
|
|
|
|
}
|
|
|
|
|
2012-05-01 14:13:13 +08:00
|
|
|
void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
|
|
|
|
llvm::GlobalVariable *DeclPtr,
|
|
|
|
bool PerformInit) {
|
|
|
|
// FIXME: this code was only tested for global initialization.
|
|
|
|
// Not sure whether we want thread-safe static local variables as VS
|
|
|
|
// doesn't make them thread-safe.
|
|
|
|
|
2013-04-15 07:01:42 +08:00
|
|
|
if (D.getTLSKind())
|
|
|
|
CGM.ErrorUnsupported(&D, "dynamic TLS initialization");
|
|
|
|
|
2012-05-01 14:13:13 +08:00
|
|
|
// Emit the initializer and add a global destructor if appropriate.
|
|
|
|
CGF.EmitCXXGlobalVarDeclInit(D, DeclPtr, PerformInit);
|
|
|
|
}
|
|
|
|
|
2013-04-12 02:13:19 +08:00
|
|
|
// Member pointer helpers.
|
|
|
|
static bool hasVBPtrOffsetField(MSInheritanceModel Inheritance) {
|
|
|
|
return Inheritance == MSIM_Unspecified;
|
|
|
|
}
|
|
|
|
|
2013-05-10 05:01:17 +08:00
|
|
|
static bool hasOnlyOneField(bool IsMemberFunction,
|
|
|
|
MSInheritanceModel Inheritance) {
|
|
|
|
return Inheritance <= MSIM_SinglePolymorphic ||
|
|
|
|
(!IsMemberFunction && Inheritance <= MSIM_MultiplePolymorphic);
|
2013-05-01 04:15:14 +08:00
|
|
|
}
|
|
|
|
|
2013-04-12 02:13:19 +08:00
|
|
|
// Only member pointers to functions need a this adjustment, since it can be
|
|
|
|
// combined with the field offset for data pointers.
|
2013-05-03 09:15:11 +08:00
|
|
|
static bool hasNonVirtualBaseAdjustmentField(bool IsMemberFunction,
|
2013-04-12 02:13:19 +08:00
|
|
|
MSInheritanceModel Inheritance) {
|
2013-05-03 09:15:11 +08:00
|
|
|
return (IsMemberFunction && Inheritance >= MSIM_Multiple);
|
2013-04-12 02:13:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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.
|
2013-03-23 03:02:54 +08:00
|
|
|
const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
|
2013-04-12 02:13:19 +08:00
|
|
|
MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
|
|
|
|
return (!hasVirtualBaseAdjustmentField(Inheritance) &&
|
|
|
|
nullFieldOffsetIsZero(Inheritance));
|
2013-03-23 03:02:54 +08:00
|
|
|
}
|
|
|
|
|
2013-04-12 02:13:19 +08:00
|
|
|
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
|
|
|
|
|
2013-05-03 09:15:11 +08:00
|
|
|
if (hasNonVirtualBaseAdjustmentField(MPT->isMemberFunctionPointer(),
|
|
|
|
Inheritance))
|
2013-04-12 02:13:19 +08:00
|
|
|
fields.push_back(CGM.IntTy);
|
2013-05-03 09:15:11 +08:00
|
|
|
if (hasVBPtrOffsetField(Inheritance))
|
2013-04-12 02:13:19 +08:00
|
|
|
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
|
2013-03-23 03:02:54 +08:00
|
|
|
}
|
2013-04-12 02:13:19 +08:00
|
|
|
|
2013-05-03 09:15:11 +08:00
|
|
|
if (hasNonVirtualBaseAdjustmentField(MPT->isMemberFunctionPointer(),
|
|
|
|
Inheritance))
|
2013-04-12 02:13:19 +08:00
|
|
|
fields.push_back(getZeroInt());
|
2013-05-03 09:15:11 +08:00
|
|
|
if (hasVBPtrOffsetField(Inheritance))
|
2013-04-12 02:13:19 +08:00
|
|
|
fields.push_back(getZeroInt());
|
|
|
|
if (hasVirtualBaseAdjustmentField(Inheritance))
|
|
|
|
fields.push_back(getAllOnesInt());
|
2013-03-23 03:02:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Constant *
|
|
|
|
MicrosoftCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
|
2013-04-12 02:13:19 +08:00
|
|
|
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;
|
2013-03-23 03:02:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Constant *
|
2013-05-03 09:15:11 +08:00
|
|
|
MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField,
|
|
|
|
bool IsMemberFunction,
|
2013-05-10 05:01:17 +08:00
|
|
|
const CXXRecordDecl *RD,
|
|
|
|
CharUnits NonVirtualBaseAdjustment)
|
2013-05-03 09:15:11 +08:00
|
|
|
{
|
2013-04-12 02:13:19 +08:00
|
|
|
MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
|
2013-05-03 09:15:11 +08:00
|
|
|
|
|
|
|
// Single inheritance class member pointer are represented as scalars instead
|
|
|
|
// of aggregates.
|
2013-05-10 05:01:17 +08:00
|
|
|
if (hasOnlyOneField(IsMemberFunction, Inheritance))
|
2013-05-03 09:15:11 +08:00
|
|
|
return FirstField;
|
|
|
|
|
2013-04-12 02:13:19 +08:00
|
|
|
llvm::SmallVector<llvm::Constant *, 4> fields;
|
2013-05-03 09:15:11 +08:00
|
|
|
fields.push_back(FirstField);
|
|
|
|
|
|
|
|
if (hasNonVirtualBaseAdjustmentField(IsMemberFunction, Inheritance))
|
2013-05-10 05:01:17 +08:00
|
|
|
fields.push_back(llvm::ConstantInt::get(
|
|
|
|
CGM.IntTy, NonVirtualBaseAdjustment.getQuantity()));
|
2013-05-03 09:15:11 +08:00
|
|
|
|
2013-04-12 02:13:19 +08:00
|
|
|
if (hasVBPtrOffsetField(Inheritance)) {
|
2013-06-05 23:58:29 +08:00
|
|
|
fields.push_back(llvm::ConstantInt::get(
|
|
|
|
CGM.IntTy, GetVBPtrOffsetFromBases(RD).getQuantity()));
|
2013-04-12 02:13:19 +08:00
|
|
|
}
|
2013-05-03 09:15:11 +08:00
|
|
|
|
|
|
|
// The rest of the fields are adjusted by conversions to a more derived class.
|
2013-04-12 02:13:19 +08:00
|
|
|
if (hasVirtualBaseAdjustmentField(Inheritance))
|
|
|
|
fields.push_back(getZeroInt());
|
2013-05-03 09:15:11 +08:00
|
|
|
|
2013-04-12 02:13:19 +08:00
|
|
|
return llvm::ConstantStruct::getAnon(fields);
|
2013-03-23 03:02:54 +08:00
|
|
|
}
|
|
|
|
|
2013-05-03 09:15:11 +08:00
|
|
|
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());
|
2013-05-10 05:01:17 +08:00
|
|
|
return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/false, RD,
|
|
|
|
CharUnits::Zero());
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
|
|
|
|
return BuildMemberPointer(MD->getParent(), MD, CharUnits::Zero());
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const APValue &MP,
|
|
|
|
QualType MPType) {
|
|
|
|
const MemberPointerType *MPT = MPType->castAs<MemberPointerType>();
|
|
|
|
const ValueDecl *MPD = MP.getMemberPointerDecl();
|
|
|
|
if (!MPD)
|
|
|
|
return EmitNullMemberPointer(MPT);
|
|
|
|
|
|
|
|
CharUnits ThisAdjustment = getMemberPointerPathAdjustment(MP);
|
|
|
|
|
|
|
|
// FIXME PR15713: Support virtual inheritance paths.
|
|
|
|
|
|
|
|
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD))
|
|
|
|
return BuildMemberPointer(MPT->getClass()->getAsCXXRecordDecl(),
|
|
|
|
MD, ThisAdjustment);
|
|
|
|
|
|
|
|
CharUnits FieldOffset =
|
|
|
|
getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD));
|
|
|
|
return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset);
|
2013-05-03 09:15:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Constant *
|
2013-05-10 05:01:17 +08:00
|
|
|
MicrosoftCXXABI::BuildMemberPointer(const CXXRecordDecl *RD,
|
|
|
|
const CXXMethodDecl *MD,
|
|
|
|
CharUnits NonVirtualBaseAdjustment) {
|
2013-05-03 09:15:11 +08:00
|
|
|
assert(MD->isInstance() && "Member function must not be static!");
|
|
|
|
MD = MD->getCanonicalDecl();
|
|
|
|
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.
|
2013-05-10 05:01:17 +08:00
|
|
|
return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/true, RD,
|
|
|
|
NonVirtualBaseAdjustment);
|
2013-05-03 09:15:11 +08:00
|
|
|
}
|
|
|
|
|
2013-05-01 04:15:14 +08:00
|
|
|
/// 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();
|
2013-05-10 05:01:17 +08:00
|
|
|
if (hasOnlyOneField(MPT->isMemberFunctionPointer(), Inheritance))
|
2013-05-01 04:15:14 +08:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
|
2013-03-23 03:02:54 +08:00
|
|
|
llvm::Value *
|
|
|
|
MicrosoftCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *MemPtr,
|
|
|
|
const MemberPointerType *MPT) {
|
|
|
|
CGBuilderTy &Builder = CGF.Builder;
|
2013-04-12 02:13:19 +08:00
|
|
|
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;
|
|
|
|
}
|
2013-03-23 03:02:54 +08:00
|
|
|
|
2013-05-10 05:01:17 +08:00
|
|
|
bool MicrosoftCXXABI::MemberPointerConstantIsNull(const MemberPointerType *MPT,
|
|
|
|
llvm::Constant *Val) {
|
|
|
|
// Function pointers are null if the pointer in the first field is null.
|
|
|
|
if (MPT->isMemberFunctionPointer()) {
|
|
|
|
llvm::Constant *FirstField = Val->getType()->isStructTy() ?
|
|
|
|
Val->getAggregateElement(0U) : Val;
|
|
|
|
return FirstField->isNullValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
// If it's not a function pointer and it's zero initializable, we can easily
|
|
|
|
// check zero.
|
|
|
|
if (isZeroInitializable(MPT) && Val->isNullValue())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Otherwise, break down all the fields for comparison. Hopefully these
|
|
|
|
// little Constants are reused, while a big null struct might not be.
|
|
|
|
llvm::SmallVector<llvm::Constant *, 4> Fields;
|
|
|
|
GetNullMemberPointerFields(MPT, Fields);
|
|
|
|
if (Fields.size() == 1) {
|
|
|
|
assert(Val->getType()->isIntegerTy());
|
|
|
|
return Val == Fields[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned I, E;
|
|
|
|
for (I = 0, E = Fields.size(); I != E; ++I) {
|
|
|
|
if (Val->getAggregateElement(I) != Fields[I])
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return I == E;
|
|
|
|
}
|
|
|
|
|
2013-05-30 02:02:47 +08:00
|
|
|
llvm::Value *
|
|
|
|
MicrosoftCXXABI::GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *This,
|
|
|
|
llvm::Value *VBTableOffset,
|
|
|
|
llvm::Value *VBPtrOffset,
|
|
|
|
llvm::Value **VBPtrOut) {
|
|
|
|
CGBuilderTy &Builder = CGF.Builder;
|
|
|
|
// Load the vbtable pointer from the vbptr in the instance.
|
|
|
|
This = Builder.CreateBitCast(This, CGM.Int8PtrTy);
|
|
|
|
llvm::Value *VBPtr =
|
|
|
|
Builder.CreateInBoundsGEP(This, VBPtrOffset, "vbptr");
|
|
|
|
if (VBPtrOut) *VBPtrOut = VBPtr;
|
|
|
|
VBPtr = Builder.CreateBitCast(VBPtr, CGM.Int8PtrTy->getPointerTo(0));
|
|
|
|
llvm::Value *VBTable = Builder.CreateLoad(VBPtr, "vbtable");
|
|
|
|
|
|
|
|
// Load an i32 offset from the vb-table.
|
|
|
|
llvm::Value *VBaseOffs = Builder.CreateInBoundsGEP(VBTable, VBTableOffset);
|
|
|
|
VBaseOffs = Builder.CreateBitCast(VBaseOffs, CGM.Int32Ty->getPointerTo(0));
|
|
|
|
return Builder.CreateLoad(VBaseOffs, "vbase_offs");
|
|
|
|
}
|
|
|
|
|
2013-04-12 02:13:19 +08:00
|
|
|
// 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,
|
2013-05-30 02:02:47 +08:00
|
|
|
llvm::Value *VBTableOffset,
|
2013-04-12 02:13:19 +08:00
|
|
|
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 =
|
2013-05-30 02:02:47 +08:00
|
|
|
Builder.CreateICmpNE(VBTableOffset, getZeroInt(),
|
2013-04-12 02:13:19 +08:00
|
|
|
"memptr.is_vbase");
|
|
|
|
Builder.CreateCondBr(IsVirtual, VBaseAdjustBB, SkipAdjustBB);
|
|
|
|
CGF.EmitBlock(VBaseAdjustBB);
|
2013-03-23 03:02:54 +08:00
|
|
|
}
|
|
|
|
|
2013-04-12 02:13:19 +08:00
|
|
|
// If we weren't given a dynamic vbptr offset, RD should be complete and we'll
|
|
|
|
// know the vbptr offset.
|
|
|
|
if (!VBPtrOffset) {
|
2013-05-30 02:02:47 +08:00
|
|
|
CharUnits offs = CharUnits::Zero();
|
|
|
|
if (RD->getNumVBases()) {
|
|
|
|
offs = GetVBPtrOffsetFromBases(RD);
|
|
|
|
}
|
2013-04-12 02:13:19 +08:00
|
|
|
VBPtrOffset = llvm::ConstantInt::get(CGM.IntTy, offs.getQuantity());
|
|
|
|
}
|
2013-05-30 02:02:47 +08:00
|
|
|
llvm::Value *VBPtr = 0;
|
2013-04-12 02:13:19 +08:00
|
|
|
llvm::Value *VBaseOffs =
|
2013-05-30 02:02:47 +08:00
|
|
|
GetVBaseOffsetFromVBPtr(CGF, Base, VBTableOffset, VBPtrOffset, &VBPtr);
|
2013-04-12 02:13:19 +08:00
|
|
|
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;
|
2013-03-23 03:02:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Value *
|
|
|
|
MicrosoftCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *Base,
|
|
|
|
llvm::Value *MemPtr,
|
|
|
|
const MemberPointerType *MPT) {
|
2013-04-12 02:13:19 +08:00
|
|
|
assert(MPT->isMemberDataPointer());
|
2013-03-23 03:02:54 +08:00
|
|
|
unsigned AS = Base->getType()->getPointerAddressSpace();
|
|
|
|
llvm::Type *PType =
|
|
|
|
CGF.ConvertTypeForMem(MPT->getPointeeType())->getPointerTo(AS);
|
|
|
|
CGBuilderTy &Builder = CGF.Builder;
|
2013-04-12 02:13:19 +08:00
|
|
|
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++);
|
2013-03-23 03:02:54 +08:00
|
|
|
}
|
|
|
|
|
2013-04-12 02:13:19 +08:00
|
|
|
if (VirtualBaseAdjustmentOffset) {
|
|
|
|
Base = AdjustVirtualBase(CGF, RD, Base, VirtualBaseAdjustmentOffset,
|
|
|
|
VBPtrOffset);
|
2013-03-23 03:02:54 +08:00
|
|
|
}
|
2013-04-12 02:13:19 +08:00
|
|
|
llvm::Value *Addr =
|
|
|
|
Builder.CreateInBoundsGEP(Base, FieldOffset, "memptr.offset");
|
2013-03-23 03:02:54 +08:00
|
|
|
|
|
|
|
// Cast the address to the appropriate pointer type, adopting the address
|
|
|
|
// space of the base pointer.
|
|
|
|
return Builder.CreateBitCast(Addr, PType);
|
|
|
|
}
|
|
|
|
|
2013-05-10 05:01:17 +08:00
|
|
|
static MSInheritanceModel
|
|
|
|
getInheritanceFromMemptr(const MemberPointerType *MPT) {
|
|
|
|
return MPT->getClass()->getAsCXXRecordDecl()->getMSInheritanceModel();
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Value *
|
|
|
|
MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
|
|
|
|
const CastExpr *E,
|
|
|
|
llvm::Value *Src) {
|
|
|
|
assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
|
|
|
|
E->getCastKind() == CK_BaseToDerivedMemberPointer ||
|
|
|
|
E->getCastKind() == CK_ReinterpretMemberPointer);
|
|
|
|
|
|
|
|
// Use constant emission if we can.
|
|
|
|
if (isa<llvm::Constant>(Src))
|
|
|
|
return EmitMemberPointerConversion(E, cast<llvm::Constant>(Src));
|
|
|
|
|
|
|
|
// We may be adding or dropping fields from the member pointer, so we need
|
|
|
|
// both types and the inheritance models of both records.
|
|
|
|
const MemberPointerType *SrcTy =
|
|
|
|
E->getSubExpr()->getType()->castAs<MemberPointerType>();
|
|
|
|
const MemberPointerType *DstTy = E->getType()->castAs<MemberPointerType>();
|
|
|
|
MSInheritanceModel SrcInheritance = getInheritanceFromMemptr(SrcTy);
|
|
|
|
MSInheritanceModel DstInheritance = getInheritanceFromMemptr(DstTy);
|
|
|
|
bool IsFunc = SrcTy->isMemberFunctionPointer();
|
|
|
|
|
|
|
|
// If the classes use the same null representation, reinterpret_cast is a nop.
|
|
|
|
bool IsReinterpret = E->getCastKind() == CK_ReinterpretMemberPointer;
|
|
|
|
if (IsReinterpret && (IsFunc ||
|
|
|
|
nullFieldOffsetIsZero(SrcInheritance) ==
|
|
|
|
nullFieldOffsetIsZero(DstInheritance)))
|
|
|
|
return Src;
|
|
|
|
|
|
|
|
CGBuilderTy &Builder = CGF.Builder;
|
|
|
|
|
|
|
|
// Branch past the conversion if Src is null.
|
|
|
|
llvm::Value *IsNotNull = EmitMemberPointerIsNotNull(CGF, Src, SrcTy);
|
|
|
|
llvm::Constant *DstNull = EmitNullMemberPointer(DstTy);
|
|
|
|
|
|
|
|
// C++ 5.2.10p9: The null member pointer value is converted to the null member
|
|
|
|
// pointer value of the destination type.
|
|
|
|
if (IsReinterpret) {
|
|
|
|
// For reinterpret casts, sema ensures that src and dst are both functions
|
|
|
|
// or data and have the same size, which means the LLVM types should match.
|
|
|
|
assert(Src->getType() == DstNull->getType());
|
|
|
|
return Builder.CreateSelect(IsNotNull, Src, DstNull);
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::BasicBlock *OriginalBB = Builder.GetInsertBlock();
|
|
|
|
llvm::BasicBlock *ConvertBB = CGF.createBasicBlock("memptr.convert");
|
|
|
|
llvm::BasicBlock *ContinueBB = CGF.createBasicBlock("memptr.converted");
|
|
|
|
Builder.CreateCondBr(IsNotNull, ConvertBB, ContinueBB);
|
|
|
|
CGF.EmitBlock(ConvertBB);
|
|
|
|
|
|
|
|
// Decompose src.
|
|
|
|
llvm::Value *FirstField = Src;
|
|
|
|
llvm::Value *NonVirtualBaseAdjustment = 0;
|
|
|
|
llvm::Value *VirtualBaseAdjustmentOffset = 0;
|
|
|
|
llvm::Value *VBPtrOffset = 0;
|
|
|
|
if (!hasOnlyOneField(IsFunc, SrcInheritance)) {
|
|
|
|
// We need to extract values.
|
|
|
|
unsigned I = 0;
|
|
|
|
FirstField = Builder.CreateExtractValue(Src, I++);
|
|
|
|
if (hasNonVirtualBaseAdjustmentField(IsFunc, SrcInheritance))
|
|
|
|
NonVirtualBaseAdjustment = Builder.CreateExtractValue(Src, I++);
|
|
|
|
if (hasVBPtrOffsetField(SrcInheritance))
|
|
|
|
VBPtrOffset = Builder.CreateExtractValue(Src, I++);
|
|
|
|
if (hasVirtualBaseAdjustmentField(SrcInheritance))
|
|
|
|
VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(Src, I++);
|
|
|
|
}
|
|
|
|
|
|
|
|
// For data pointers, we adjust the field offset directly. For functions, we
|
|
|
|
// have a separate field.
|
|
|
|
llvm::Constant *Adj = getMemberPointerAdjustment(E);
|
|
|
|
if (Adj) {
|
|
|
|
Adj = llvm::ConstantExpr::getTruncOrBitCast(Adj, CGM.IntTy);
|
|
|
|
llvm::Value *&NVAdjustField = IsFunc ? NonVirtualBaseAdjustment : FirstField;
|
|
|
|
bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);
|
|
|
|
if (!NVAdjustField) // If this field didn't exist in src, it's zero.
|
|
|
|
NVAdjustField = getZeroInt();
|
|
|
|
if (isDerivedToBase)
|
|
|
|
NVAdjustField = Builder.CreateNSWSub(NVAdjustField, Adj, "adj");
|
|
|
|
else
|
|
|
|
NVAdjustField = Builder.CreateNSWAdd(NVAdjustField, Adj, "adj");
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME PR15713: Support conversions through virtually derived classes.
|
|
|
|
|
|
|
|
// Recompose dst from the null struct and the adjusted fields from src.
|
|
|
|
llvm::Value *Dst;
|
|
|
|
if (hasOnlyOneField(IsFunc, DstInheritance)) {
|
|
|
|
Dst = FirstField;
|
|
|
|
} else {
|
|
|
|
Dst = llvm::UndefValue::get(DstNull->getType());
|
|
|
|
unsigned Idx = 0;
|
|
|
|
Dst = Builder.CreateInsertValue(Dst, FirstField, Idx++);
|
|
|
|
if (hasNonVirtualBaseAdjustmentField(IsFunc, DstInheritance))
|
|
|
|
Dst = Builder.CreateInsertValue(
|
|
|
|
Dst, getValueOrZeroInt(NonVirtualBaseAdjustment), Idx++);
|
|
|
|
if (hasVBPtrOffsetField(DstInheritance))
|
|
|
|
Dst = Builder.CreateInsertValue(
|
|
|
|
Dst, getValueOrZeroInt(VBPtrOffset), Idx++);
|
|
|
|
if (hasVirtualBaseAdjustmentField(DstInheritance))
|
|
|
|
Dst = Builder.CreateInsertValue(
|
|
|
|
Dst, getValueOrZeroInt(VirtualBaseAdjustmentOffset), Idx++);
|
|
|
|
}
|
|
|
|
Builder.CreateBr(ContinueBB);
|
|
|
|
|
|
|
|
// In the continuation, choose between DstNull and Dst.
|
|
|
|
CGF.EmitBlock(ContinueBB);
|
|
|
|
llvm::PHINode *Phi = Builder.CreatePHI(DstNull->getType(), 2, "memptr.converted");
|
|
|
|
Phi->addIncoming(DstNull, OriginalBB);
|
|
|
|
Phi->addIncoming(Dst, ConvertBB);
|
|
|
|
return Phi;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Constant *
|
|
|
|
MicrosoftCXXABI::EmitMemberPointerConversion(const CastExpr *E,
|
|
|
|
llvm::Constant *Src) {
|
|
|
|
const MemberPointerType *SrcTy =
|
|
|
|
E->getSubExpr()->getType()->castAs<MemberPointerType>();
|
|
|
|
const MemberPointerType *DstTy = E->getType()->castAs<MemberPointerType>();
|
|
|
|
|
|
|
|
// If src is null, emit a new null for dst. We can't return src because dst
|
|
|
|
// might have a new representation.
|
|
|
|
if (MemberPointerConstantIsNull(SrcTy, Src))
|
|
|
|
return EmitNullMemberPointer(DstTy);
|
|
|
|
|
|
|
|
// We don't need to do anything for reinterpret_casts of non-null member
|
|
|
|
// pointers. We should only get here when the two type representations have
|
|
|
|
// the same size.
|
|
|
|
if (E->getCastKind() == CK_ReinterpretMemberPointer)
|
|
|
|
return Src;
|
|
|
|
|
|
|
|
MSInheritanceModel SrcInheritance = getInheritanceFromMemptr(SrcTy);
|
|
|
|
MSInheritanceModel DstInheritance = getInheritanceFromMemptr(DstTy);
|
|
|
|
|
|
|
|
// Decompose src.
|
|
|
|
llvm::Constant *FirstField = Src;
|
|
|
|
llvm::Constant *NonVirtualBaseAdjustment = 0;
|
|
|
|
llvm::Constant *VirtualBaseAdjustmentOffset = 0;
|
|
|
|
llvm::Constant *VBPtrOffset = 0;
|
|
|
|
bool IsFunc = SrcTy->isMemberFunctionPointer();
|
|
|
|
if (!hasOnlyOneField(IsFunc, SrcInheritance)) {
|
|
|
|
// We need to extract values.
|
|
|
|
unsigned I = 0;
|
|
|
|
FirstField = Src->getAggregateElement(I++);
|
|
|
|
if (hasNonVirtualBaseAdjustmentField(IsFunc, SrcInheritance))
|
|
|
|
NonVirtualBaseAdjustment = Src->getAggregateElement(I++);
|
|
|
|
if (hasVBPtrOffsetField(SrcInheritance))
|
|
|
|
VBPtrOffset = Src->getAggregateElement(I++);
|
|
|
|
if (hasVirtualBaseAdjustmentField(SrcInheritance))
|
|
|
|
VirtualBaseAdjustmentOffset = Src->getAggregateElement(I++);
|
|
|
|
}
|
|
|
|
|
|
|
|
// For data pointers, we adjust the field offset directly. For functions, we
|
|
|
|
// have a separate field.
|
|
|
|
llvm::Constant *Adj = getMemberPointerAdjustment(E);
|
|
|
|
if (Adj) {
|
|
|
|
Adj = llvm::ConstantExpr::getTruncOrBitCast(Adj, CGM.IntTy);
|
|
|
|
llvm::Constant *&NVAdjustField =
|
|
|
|
IsFunc ? NonVirtualBaseAdjustment : FirstField;
|
|
|
|
bool IsDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);
|
|
|
|
if (!NVAdjustField) // If this field didn't exist in src, it's zero.
|
|
|
|
NVAdjustField = getZeroInt();
|
|
|
|
if (IsDerivedToBase)
|
|
|
|
NVAdjustField = llvm::ConstantExpr::getNSWSub(NVAdjustField, Adj);
|
|
|
|
else
|
|
|
|
NVAdjustField = llvm::ConstantExpr::getNSWAdd(NVAdjustField, Adj);
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME PR15713: Support conversions through virtually derived classes.
|
|
|
|
|
|
|
|
// Recompose dst from the null struct and the adjusted fields from src.
|
|
|
|
if (hasOnlyOneField(IsFunc, DstInheritance))
|
|
|
|
return FirstField;
|
|
|
|
|
|
|
|
llvm::SmallVector<llvm::Constant *, 4> Fields;
|
|
|
|
Fields.push_back(FirstField);
|
|
|
|
if (hasNonVirtualBaseAdjustmentField(IsFunc, DstInheritance))
|
|
|
|
Fields.push_back(getConstantOrZeroInt(NonVirtualBaseAdjustment));
|
|
|
|
if (hasVBPtrOffsetField(DstInheritance))
|
|
|
|
Fields.push_back(getConstantOrZeroInt(VBPtrOffset));
|
|
|
|
if (hasVirtualBaseAdjustmentField(DstInheritance))
|
|
|
|
Fields.push_back(getConstantOrZeroInt(VirtualBaseAdjustmentOffset));
|
|
|
|
return llvm::ConstantStruct::getAnon(Fields);
|
|
|
|
}
|
|
|
|
|
2013-04-12 02:13:19 +08:00
|
|
|
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++);
|
2013-05-03 09:15:11 +08:00
|
|
|
if (hasVBPtrOffsetField(Inheritance))
|
|
|
|
VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++);
|
2013-04-12 02:13:19 +08:00
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
2010-08-16 11:33:14 +08:00
|
|
|
CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {
|
2010-06-10 07:25:41 +08:00
|
|
|
return new MicrosoftCXXABI(CGM);
|
|
|
|
}
|
|
|
|
|