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"
|
2013-06-19 23:20:38 +08:00
|
|
|
#include "CGVTables.h"
|
2014-01-07 19:51:46 +08:00
|
|
|
#include "CodeGenModule.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"
|
2013-09-27 22:48:01 +08:00
|
|
|
#include "llvm/ADT/StringSet.h"
|
2010-06-10 07:25:41 +08:00
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
using namespace CodeGen;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2014-01-03 08:14:35 +08:00
|
|
|
/// Holds all the vbtable globals for a given class.
|
|
|
|
struct VBTableGlobals {
|
2014-02-28 03:40:09 +08:00
|
|
|
const VPtrInfoVector *VBTables;
|
2014-01-03 08:14:35 +08:00
|
|
|
SmallVector<llvm::GlobalVariable *, 2> Globals;
|
|
|
|
};
|
|
|
|
|
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 {
|
2014-02-01 08:04:45 +08:00
|
|
|
if (RD->hasNonTrivialCopyConstructor() || RD->hasNonTrivialDestructor()) {
|
|
|
|
llvm::Triple::ArchType Arch = CGM.getTarget().getTriple().getArch();
|
|
|
|
if (Arch == llvm::Triple::x86)
|
|
|
|
return RAA_DirectInMemory;
|
|
|
|
// On x64, pass non-trivial records indirectly.
|
|
|
|
// FIXME: Test other Windows architectures.
|
|
|
|
return RAA_Indirect;
|
|
|
|
}
|
2013-04-17 20:54:10 +08:00
|
|
|
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
|
|
|
|
2013-11-21 08:15:56 +08:00
|
|
|
bool isInlineInitializedStaticDataMemberLinkOnce() { return true; }
|
|
|
|
|
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-10-10 02:16:58 +08:00
|
|
|
void initializeHiddenVirtualInheritanceMembers(CodeGenFunction &CGF,
|
|
|
|
const CXXRecordDecl *RD);
|
|
|
|
|
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)) {
|
2013-11-05 23:54:58 +08:00
|
|
|
MicrosoftVTableContext::MethodVFTableLocation ML =
|
|
|
|
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(MD);
|
2013-08-21 14:25:03 +08:00
|
|
|
// 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.
|
2013-11-07 21:34:02 +08:00
|
|
|
if (ML.VBase || !ML.VFPtrOffset.isZero())
|
2013-08-21 14:25:03 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return MD->getParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Value *adjustThisArgumentForVirtualCall(CodeGenFunction &CGF,
|
|
|
|
GlobalDecl GD,
|
|
|
|
llvm::Value *This);
|
|
|
|
|
2013-12-18 03:46:40 +08:00
|
|
|
void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy,
|
|
|
|
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-12-18 03:46:40 +08:00
|
|
|
unsigned addImplicitConstructorArgs(CodeGenFunction &CGF,
|
|
|
|
const CXXConstructorDecl *D,
|
|
|
|
CXXCtorType Type, bool ForVirtualBase,
|
|
|
|
bool Delegating, CallArgList &Args);
|
2013-08-21 14:25:03 +08:00
|
|
|
|
2013-12-13 08:53:54 +08:00
|
|
|
void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD,
|
|
|
|
CXXDtorType Type, bool ForVirtualBase,
|
|
|
|
bool Delegating, llvm::Value *This);
|
|
|
|
|
2013-09-27 22:48:01 +08:00
|
|
|
void emitVTableDefinitions(CodeGenVTables &CGVT, const CXXRecordDecl *RD);
|
|
|
|
|
|
|
|
llvm::Value *getVTableAddressPointInStructor(
|
|
|
|
CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
|
|
|
|
BaseSubobject Base, const CXXRecordDecl *NearestVBase,
|
|
|
|
bool &NeedsVirtualOffset);
|
|
|
|
|
|
|
|
llvm::Constant *
|
|
|
|
getVTableAddressPointForConstExpr(BaseSubobject Base,
|
|
|
|
const CXXRecordDecl *VTableClass);
|
|
|
|
|
|
|
|
llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,
|
|
|
|
CharUnits VPtrOffset);
|
|
|
|
|
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-10-09 17:23:58 +08:00
|
|
|
void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD,
|
|
|
|
CallArgList &CallArgs) {
|
|
|
|
assert(GD.getDtorType() == Dtor_Deleting &&
|
|
|
|
"Only deleting destructor thunks are available in this ABI");
|
|
|
|
CallArgs.add(RValue::get(getStructorImplicitParamValue(CGF)),
|
|
|
|
CGM.getContext().IntTy);
|
|
|
|
}
|
|
|
|
|
2013-09-27 22:48:01 +08:00
|
|
|
void emitVirtualInheritanceTables(const CXXRecordDecl *RD);
|
2013-06-19 23:20:38 +08:00
|
|
|
|
2014-01-03 08:14:35 +08:00
|
|
|
llvm::GlobalVariable *
|
2014-02-28 03:40:09 +08:00
|
|
|
getAddrOfVBTable(const VPtrInfo &VBT, const CXXRecordDecl *RD,
|
2014-01-03 08:14:35 +08:00
|
|
|
llvm::GlobalVariable::LinkageTypes Linkage);
|
|
|
|
|
2014-02-28 03:40:09 +08:00
|
|
|
void emitVBTableDefinition(const VPtrInfo &VBT, const CXXRecordDecl *RD,
|
2014-01-03 08:14:35 +08:00
|
|
|
llvm::GlobalVariable *GV) const;
|
|
|
|
|
2013-10-09 17:23:58 +08:00
|
|
|
void setThunkLinkage(llvm::Function *Thunk, bool ForVTable) {
|
|
|
|
Thunk->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
|
|
|
|
}
|
|
|
|
|
2013-10-30 19:55:43 +08:00
|
|
|
llvm::Value *performThisAdjustment(CodeGenFunction &CGF, llvm::Value *This,
|
|
|
|
const ThisAdjustment &TA);
|
|
|
|
|
|
|
|
llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, llvm::Value *Ret,
|
|
|
|
const ReturnAdjustment &RA);
|
|
|
|
|
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-10-03 14:26:13 +08:00
|
|
|
MicrosoftMangleContext &getMangleContext() {
|
|
|
|
return cast<MicrosoftMangleContext>(CodeGen::CGCXXABI::getMangleContext());
|
|
|
|
}
|
|
|
|
|
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 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);
|
|
|
|
|
2013-10-30 19:55:43 +08:00
|
|
|
llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *Base,
|
|
|
|
int32_t VBPtrOffset,
|
|
|
|
int32_t VBTableOffset,
|
|
|
|
llvm::Value **VBPtr = 0) {
|
|
|
|
llvm::Value *VBPOffset = llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset),
|
|
|
|
*VBTOffset = llvm::ConstantInt::get(CGM.IntTy, VBTableOffset);
|
|
|
|
return GetVBaseOffsetFromVBPtr(CGF, Base, VBPOffset, VBTOffset, VBPtr);
|
|
|
|
}
|
|
|
|
|
2013-05-30 02:02:47 +08:00
|
|
|
/// \brief Performs a full virtual base adjustment. Used to dereference
|
|
|
|
/// pointers to members of virtual bases.
|
2014-02-21 07:22:07 +08:00
|
|
|
llvm::Value *AdjustVirtualBase(CodeGenFunction &CGF, const Expr *E,
|
|
|
|
const CXXRecordDecl *RD, llvm::Value *Base,
|
2013-04-12 02:13:19 +08:00
|
|
|
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().
|
2014-01-03 08:14:35 +08:00
|
|
|
const VBTableGlobals &enumerateVBTables(const CXXRecordDecl *RD);
|
2013-06-19 23:20:38 +08:00
|
|
|
|
2013-11-16 01:24:45 +08:00
|
|
|
/// \brief Generate a thunk for calling a virtual member function MD.
|
2014-02-21 10:27:32 +08:00
|
|
|
llvm::Function *EmitVirtualMemPtrThunk(
|
|
|
|
const CXXMethodDecl *MD,
|
|
|
|
const MicrosoftVTableContext::MethodVFTableLocation &ML);
|
2013-11-16 01:24:45 +08:00
|
|
|
|
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);
|
|
|
|
|
2014-02-21 07:22:07 +08:00
|
|
|
virtual llvm::Value *
|
|
|
|
EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,
|
|
|
|
llvm::Value *Base, llvm::Value *MemPtr,
|
|
|
|
const MemberPointerType *MPT);
|
2013-03-23 03:02:54 +08:00
|
|
|
|
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 *
|
2014-02-21 07:22:07 +08:00
|
|
|
EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E,
|
|
|
|
llvm::Value *&This, llvm::Value *MemPtr,
|
2013-04-12 02:13:19 +08:00
|
|
|
const MemberPointerType *MPT);
|
|
|
|
|
2013-06-19 23:20:38 +08:00
|
|
|
private:
|
2013-09-27 22:48:01 +08:00
|
|
|
typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;
|
|
|
|
typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *> VFTablesMapTy;
|
|
|
|
/// \brief All the vftables that have been referenced.
|
|
|
|
VFTablesMapTy VFTablesMap;
|
|
|
|
|
|
|
|
/// \brief This set holds the record decls we've deferred vtable emission for.
|
|
|
|
llvm::SmallPtrSet<const CXXRecordDecl *, 4> DeferredVFTables;
|
|
|
|
|
|
|
|
|
|
|
|
/// \brief All the vbtables which have been referenced.
|
2014-01-03 08:14:35 +08:00
|
|
|
llvm::DenseMap<const CXXRecordDecl *, VBTableGlobals> VBTablesMap;
|
2013-09-11 04:14:30 +08:00
|
|
|
|
|
|
|
/// Info on the global variable used to guard initialization of static locals.
|
|
|
|
/// The BitIndex field is only used for externally invisible declarations.
|
|
|
|
struct GuardInfo {
|
|
|
|
GuardInfo() : Guard(0), BitIndex(0) {}
|
|
|
|
llvm::GlobalVariable *Guard;
|
|
|
|
unsigned BitIndex;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Map from DeclContext to the current guard variable. We assume that the
|
|
|
|
/// AST is visited in source code order.
|
|
|
|
llvm::DenseMap<const DeclContext *, GuardInfo> GuardVariableMap;
|
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-05-30 02:02:47 +08:00
|
|
|
llvm::Value *
|
|
|
|
MicrosoftCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *This,
|
|
|
|
const CXXRecordDecl *ClassDecl,
|
|
|
|
const CXXRecordDecl *BaseClassDecl) {
|
2014-01-14 08:50:39 +08:00
|
|
|
int64_t VBPtrChars =
|
|
|
|
getContext().getASTRecordLayout(ClassDecl).getVBPtrOffset().getQuantity();
|
2013-05-30 02:02:47 +08:00
|
|
|
llvm::Value *VBPtrOffset = llvm::ConstantInt::get(CGM.PtrDiffTy, VBPtrChars);
|
|
|
|
CharUnits IntSize = getContext().getTypeSizeInChars(getContext().IntTy);
|
2013-11-05 23:54:58 +08:00
|
|
|
CharUnits VBTableChars =
|
|
|
|
IntSize *
|
|
|
|
CGM.getMicrosoftVTableContext().getVBTableIndex(ClassDecl, BaseClassDecl);
|
2013-05-30 02:02:47 +08:00
|
|
|
llvm::Value *VBTableOffset =
|
|
|
|
llvm::ConstantInt::get(CGM.IntTy, VBTableChars.getQuantity());
|
|
|
|
|
|
|
|
llvm::Value *VBPtrToNewBase =
|
2013-10-28 01:10:27 +08:00
|
|
|
GetVBaseOffsetFromVBPtr(CGF, This, VBPtrOffset, VBTableOffset);
|
2013-05-30 02:02:47 +08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2013-12-18 03:46:40 +08:00
|
|
|
void MicrosoftCXXABI::BuildConstructorSignature(
|
|
|
|
const CXXConstructorDecl *Ctor, CXXCtorType Type, CanQualType &ResTy,
|
|
|
|
SmallVectorImpl<CanQualType> &ArgTys) {
|
|
|
|
|
|
|
|
// All parameters are already in place except is_most_derived, which goes
|
|
|
|
// after 'this' if it's variadic and last if it's not.
|
2013-02-27 21:46:31 +08:00
|
|
|
|
|
|
|
const CXXRecordDecl *Class = Ctor->getParent();
|
2013-12-18 03:46:40 +08:00
|
|
|
const FunctionProtoType *FPT = Ctor->getType()->castAs<FunctionProtoType>();
|
2013-02-27 21:46:31 +08:00
|
|
|
if (Class->getNumVBases()) {
|
2013-12-18 03:46:40 +08:00
|
|
|
if (FPT->isVariadic())
|
|
|
|
ArgTys.insert(ArgTys.begin() + 1, CGM.getContext().IntTy);
|
|
|
|
else
|
|
|
|
ArgTys.push_back(CGM.getContext().IntTy);
|
2013-02-27 21:46:31 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-10-10 02:16:58 +08:00
|
|
|
void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers(
|
|
|
|
CodeGenFunction &CGF, const CXXRecordDecl *RD) {
|
|
|
|
// In most cases, an override for a vbase virtual method can adjust
|
|
|
|
// the "this" parameter by applying a constant offset.
|
|
|
|
// However, this is not enough while a constructor or a destructor of some
|
|
|
|
// class X is being executed if all the following conditions are met:
|
|
|
|
// - X has virtual bases, (1)
|
|
|
|
// - X overrides a virtual method M of a vbase Y, (2)
|
|
|
|
// - X itself is a vbase of the most derived class.
|
|
|
|
//
|
|
|
|
// If (1) and (2) are true, the vtorDisp for vbase Y is a hidden member of X
|
|
|
|
// which holds the extra amount of "this" adjustment we must do when we use
|
|
|
|
// the X vftables (i.e. during X ctor or dtor).
|
|
|
|
// Outside the ctors and dtors, the values of vtorDisps are zero.
|
|
|
|
|
|
|
|
const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
|
|
|
|
typedef ASTRecordLayout::VBaseOffsetsMapTy VBOffsets;
|
|
|
|
const VBOffsets &VBaseMap = Layout.getVBaseOffsetsMap();
|
|
|
|
CGBuilderTy &Builder = CGF.Builder;
|
|
|
|
|
|
|
|
unsigned AS =
|
|
|
|
cast<llvm::PointerType>(getThisValue(CGF)->getType())->getAddressSpace();
|
|
|
|
llvm::Value *Int8This = 0; // Initialize lazily.
|
|
|
|
|
|
|
|
for (VBOffsets::const_iterator I = VBaseMap.begin(), E = VBaseMap.end();
|
|
|
|
I != E; ++I) {
|
|
|
|
if (!I->second.hasVtorDisp())
|
|
|
|
continue;
|
|
|
|
|
2013-11-14 00:03:43 +08:00
|
|
|
llvm::Value *VBaseOffset =
|
|
|
|
GetVirtualBaseClassOffset(CGF, getThisValue(CGF), RD, I->first);
|
2013-10-10 02:16:58 +08:00
|
|
|
// FIXME: it doesn't look right that we SExt in GetVirtualBaseClassOffset()
|
|
|
|
// just to Trunc back immediately.
|
|
|
|
VBaseOffset = Builder.CreateTruncOrBitCast(VBaseOffset, CGF.Int32Ty);
|
|
|
|
uint64_t ConstantVBaseOffset =
|
|
|
|
Layout.getVBaseClassOffset(I->first).getQuantity();
|
|
|
|
|
|
|
|
// vtorDisp_for_vbase = vbptr[vbase_idx] - offsetof(RD, vbase).
|
|
|
|
llvm::Value *VtorDispValue = Builder.CreateSub(
|
|
|
|
VBaseOffset, llvm::ConstantInt::get(CGM.Int32Ty, ConstantVBaseOffset),
|
|
|
|
"vtordisp.value");
|
|
|
|
|
|
|
|
if (!Int8This)
|
|
|
|
Int8This = Builder.CreateBitCast(getThisValue(CGF),
|
|
|
|
CGF.Int8Ty->getPointerTo(AS));
|
|
|
|
llvm::Value *VtorDispPtr = Builder.CreateInBoundsGEP(Int8This, VBaseOffset);
|
|
|
|
// vtorDisp is always the 32-bits before the vbase in the class layout.
|
|
|
|
VtorDispPtr = Builder.CreateConstGEP1_32(VtorDispPtr, -4);
|
|
|
|
VtorDispPtr = Builder.CreateBitCast(
|
|
|
|
VtorDispPtr, CGF.Int32Ty->getPointerTo(AS), "vtordisp.ptr");
|
|
|
|
|
|
|
|
Builder.CreateStore(VtorDispValue, VtorDispPtr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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");
|
2014-01-04 07:42:00 +08:00
|
|
|
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
|
2013-06-19 23:20:38 +08:00
|
|
|
|
2014-01-03 08:14:35 +08:00
|
|
|
const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
|
|
|
|
for (unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) {
|
2014-02-28 03:40:09 +08:00
|
|
|
const VPtrInfo *VBT = (*VBGlobals.VBTables)[I];
|
2014-01-03 08:14:35 +08:00
|
|
|
llvm::GlobalVariable *GV = VBGlobals.Globals[I];
|
2013-06-19 23:20:38 +08:00
|
|
|
const ASTRecordLayout &SubobjectLayout =
|
2014-02-28 03:40:09 +08:00
|
|
|
CGM.getContext().getASTRecordLayout(VBT->BaseWithVPtr);
|
2014-01-04 07:42:00 +08:00
|
|
|
CharUnits Offs = VBT->NonVirtualOffset;
|
|
|
|
Offs += SubobjectLayout.getVBPtrOffset();
|
2014-02-28 03:40:09 +08:00
|
|
|
if (VBT->getVBaseWithVPtr())
|
|
|
|
Offs += Layout.getVBaseClassOffset(VBT->getVBaseWithVPtr());
|
2013-06-19 23:20:38 +08:00
|
|
|
llvm::Value *VBPtr =
|
2014-01-04 07:42:00 +08:00
|
|
|
CGF.Builder.CreateConstInBoundsGEP1_64(ThisInt8Ptr, Offs.getQuantity());
|
2014-01-03 08:14:35 +08:00
|
|
|
VBPtr = CGF.Builder.CreateBitCast(VBPtr, GV->getType()->getPointerTo(0),
|
2014-01-04 07:42:00 +08:00
|
|
|
"vbptr." + VBT->ReusingBase->getName());
|
2014-01-03 08:14:35 +08:00
|
|
|
CGF.Builder.CreateStore(GV, VBPtr);
|
2013-06-19 23:20:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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());
|
2013-10-17 02:24:06 +08:00
|
|
|
// FIXME: consider splitting the vdtor vs regular method code into two
|
|
|
|
// functions.
|
|
|
|
|
|
|
|
GlobalDecl LookupGD = GD;
|
|
|
|
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
|
|
|
|
// Complete dtors take a pointer to the complete object,
|
|
|
|
// thus don't need adjustment.
|
|
|
|
if (GD.getDtorType() == Dtor_Complete)
|
|
|
|
return This;
|
|
|
|
|
|
|
|
// There's only Dtor_Deleting in vftable but it shares the this adjustment
|
|
|
|
// with the base one, so look up the deleting one instead.
|
|
|
|
LookupGD = GlobalDecl(DD, Dtor_Deleting);
|
|
|
|
}
|
2013-11-05 23:54:58 +08:00
|
|
|
MicrosoftVTableContext::MethodVFTableLocation ML =
|
|
|
|
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD);
|
2013-08-21 14:25:03 +08:00
|
|
|
|
|
|
|
unsigned AS = cast<llvm::PointerType>(This->getType())->getAddressSpace();
|
|
|
|
llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS);
|
2013-11-07 21:34:02 +08:00
|
|
|
CharUnits StaticOffset = ML.VFPtrOffset;
|
2014-02-19 06:51:52 +08:00
|
|
|
|
|
|
|
// Base destructors expect 'this' to point to the beginning of the base
|
|
|
|
// subobject, not the first vfptr that happens to contain the virtual dtor.
|
|
|
|
// However, we still need to apply the virtual base adjustment.
|
|
|
|
if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
|
|
|
|
StaticOffset = CharUnits::Zero();
|
|
|
|
|
2013-08-21 14:25:03 +08:00
|
|
|
if (ML.VBase) {
|
2013-10-17 02:24:06 +08:00
|
|
|
bool AvoidVirtualOffset = false;
|
|
|
|
if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base) {
|
|
|
|
// A base destructor can only be called from a complete destructor of the
|
2013-10-17 17:11:45 +08:00
|
|
|
// same record type or another destructor of a more derived type;
|
|
|
|
// or a constructor of the same record type if an exception is thrown.
|
|
|
|
assert(isa<CXXDestructorDecl>(CGF.CurGD.getDecl()) ||
|
|
|
|
isa<CXXConstructorDecl>(CGF.CurGD.getDecl()));
|
2013-10-17 02:24:06 +08:00
|
|
|
const CXXRecordDecl *CurRD =
|
2013-10-17 17:11:45 +08:00
|
|
|
cast<CXXMethodDecl>(CGF.CurGD.getDecl())->getParent();
|
2013-10-17 02:24:06 +08:00
|
|
|
|
|
|
|
if (MD->getParent() == CurRD) {
|
2013-10-17 17:11:45 +08:00
|
|
|
if (isa<CXXDestructorDecl>(CGF.CurGD.getDecl()))
|
|
|
|
assert(CGF.CurGD.getDtorType() == Dtor_Complete);
|
|
|
|
if (isa<CXXConstructorDecl>(CGF.CurGD.getDecl()))
|
|
|
|
assert(CGF.CurGD.getCtorType() == Ctor_Complete);
|
|
|
|
// We're calling the main base dtor from a complete structor,
|
|
|
|
// so we know the "this" offset statically.
|
2013-10-17 02:24:06 +08:00
|
|
|
AvoidVirtualOffset = true;
|
|
|
|
} else {
|
|
|
|
// Let's see if we try to call a destructor of a non-virtual base.
|
|
|
|
for (CXXRecordDecl::base_class_const_iterator I = CurRD->bases_begin(),
|
|
|
|
E = CurRD->bases_end(); I != E; ++I) {
|
|
|
|
if (I->getType()->getAsCXXRecordDecl() != MD->getParent())
|
|
|
|
continue;
|
|
|
|
// If we call a base destructor for a non-virtual base, we statically
|
|
|
|
// know where it expects the vfptr and "this" to be.
|
2013-10-17 17:11:45 +08:00
|
|
|
// The total offset should reflect the adjustment done by
|
|
|
|
// adjustThisParameterInVirtualFunctionPrologue().
|
2013-10-17 02:24:06 +08:00
|
|
|
AvoidVirtualOffset = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (AvoidVirtualOffset) {
|
|
|
|
const ASTRecordLayout &Layout =
|
|
|
|
CGF.getContext().getASTRecordLayout(MD->getParent());
|
|
|
|
StaticOffset += Layout.getVBaseClassOffset(ML.VBase);
|
|
|
|
} else {
|
|
|
|
This = CGF.Builder.CreateBitCast(This, charPtrTy);
|
2013-11-14 00:03:43 +08:00
|
|
|
llvm::Value *VBaseOffset =
|
|
|
|
GetVirtualBaseClassOffset(CGF, This, MD->getParent(), ML.VBase);
|
2013-10-17 02:24:06 +08:00
|
|
|
This = CGF.Builder.CreateInBoundsGEP(This, VBaseOffset);
|
|
|
|
}
|
2013-08-21 14:25:03 +08:00
|
|
|
}
|
|
|
|
if (!StaticOffset.isZero()) {
|
|
|
|
assert(StaticOffset.isPositive());
|
|
|
|
This = CGF.Builder.CreateBitCast(This, charPtrTy);
|
2013-10-23 02:15:24 +08:00
|
|
|
if (ML.VBase) {
|
|
|
|
// Non-virtual adjustment might result in a pointer outside the allocated
|
|
|
|
// object, e.g. if the final overrider class is laid out after the virtual
|
|
|
|
// base that declares a method in the most derived class.
|
|
|
|
// FIXME: Update the code that emits this adjustment in thunks prologues.
|
|
|
|
This = CGF.Builder.CreateConstGEP1_32(This, StaticOffset.getQuantity());
|
|
|
|
} else {
|
|
|
|
This = CGF.Builder.CreateConstInBoundsGEP1_32(This,
|
|
|
|
StaticOffset.getQuantity());
|
|
|
|
}
|
2013-08-21 14:25:03 +08:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-12-18 03:46:40 +08:00
|
|
|
void MicrosoftCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,
|
|
|
|
QualType &ResTy,
|
|
|
|
FunctionArgList &Params) {
|
2013-02-27 21:46:31 +08:00
|
|
|
ASTContext &Context = getContext();
|
|
|
|
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
|
2013-12-18 03:46:40 +08:00
|
|
|
assert(isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD));
|
2013-02-27 21:46:31 +08:00
|
|
|
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);
|
2013-12-18 03:46:40 +08:00
|
|
|
// The 'most_derived' parameter goes second if the ctor is variadic and last
|
|
|
|
// if it's not. Dtors can't be variadic.
|
|
|
|
const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
|
|
|
|
if (FPT->isVariadic())
|
|
|
|
Params.insert(Params.begin() + 1, IsMostDerived);
|
|
|
|
else
|
|
|
|
Params.push_back(IsMostDerived);
|
2013-02-27 21:46:31 +08:00
|
|
|
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());
|
2013-10-17 02:24:06 +08:00
|
|
|
|
|
|
|
GlobalDecl LookupGD = GD;
|
|
|
|
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
|
|
|
|
// Complete destructors take a pointer to the complete object as a
|
|
|
|
// parameter, thus don't need this adjustment.
|
|
|
|
if (GD.getDtorType() == Dtor_Complete)
|
|
|
|
return This;
|
|
|
|
|
|
|
|
// There's no Dtor_Base in vftable but it shares the this adjustment with
|
|
|
|
// the deleting one, so look it up instead.
|
|
|
|
LookupGD = GlobalDecl(DD, Dtor_Deleting);
|
|
|
|
}
|
2013-08-21 14:25:03 +08:00
|
|
|
|
|
|
|
// 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
|
2013-12-06 00:25:25 +08:00
|
|
|
// pointer to the final overrider subobject. Thus, we need to adjust it back
|
2013-08-21 14:25:03 +08:00
|
|
|
// to the final overrider subobject before use.
|
|
|
|
// See comments in the MicrosoftVFTableContext implementation for the details.
|
|
|
|
|
2013-11-05 23:54:58 +08:00
|
|
|
MicrosoftVTableContext::MethodVFTableLocation ML =
|
|
|
|
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD);
|
2013-11-07 21:34:02 +08:00
|
|
|
CharUnits Adjustment = ML.VFPtrOffset;
|
2014-02-19 06:51:52 +08:00
|
|
|
|
|
|
|
// Normal virtual instance methods need to adjust from the vfptr that first
|
|
|
|
// defined the virtual method to the virtual base subobject, but destructors
|
|
|
|
// do not. The vector deleting destructor thunk applies this adjustment for
|
|
|
|
// us if necessary.
|
|
|
|
if (isa<CXXDestructorDecl>(MD))
|
|
|
|
Adjustment = CharUnits::Zero();
|
|
|
|
|
2013-08-21 14:25:03 +08:00
|
|
|
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());
|
2013-10-23 02:15:24 +08:00
|
|
|
This =
|
|
|
|
CGF.Builder.CreateConstInBoundsGEP1_32(This, -Adjustment.getQuantity());
|
2013-08-21 14:25:03 +08:00
|
|
|
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-12-18 03:46:40 +08:00
|
|
|
unsigned MicrosoftCXXABI::addImplicitConstructorArgs(
|
|
|
|
CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type,
|
|
|
|
bool ForVirtualBase, bool Delegating, CallArgList &Args) {
|
2013-02-27 21:46:31 +08:00
|
|
|
assert(Type == Ctor_Complete || Type == Ctor_Base);
|
|
|
|
|
2013-12-18 03:46:40 +08:00
|
|
|
// Check if we need a 'most_derived' parameter.
|
|
|
|
if (!D->getParent()->getNumVBases())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Add the 'most_derived' argument second if we are variadic or last if not.
|
|
|
|
const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>();
|
|
|
|
llvm::Value *MostDerivedArg =
|
|
|
|
llvm::ConstantInt::get(CGM.Int32Ty, Type == Ctor_Complete);
|
|
|
|
RValue RV = RValue::get(MostDerivedArg);
|
|
|
|
if (MostDerivedArg) {
|
|
|
|
if (FPT->isVariadic())
|
|
|
|
Args.insert(Args.begin() + 1,
|
|
|
|
CallArg(RV, getContext().IntTy, /*needscopy=*/false));
|
|
|
|
else
|
|
|
|
Args.add(RV, getContext().IntTy);
|
2013-02-27 21:46:31 +08:00
|
|
|
}
|
|
|
|
|
2013-12-18 03:46:40 +08:00
|
|
|
return 1; // Added one arg.
|
2013-02-27 21:46:31 +08:00
|
|
|
}
|
|
|
|
|
2013-12-13 08:53:54 +08:00
|
|
|
void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
|
|
|
|
const CXXDestructorDecl *DD,
|
|
|
|
CXXDtorType Type, bool ForVirtualBase,
|
|
|
|
bool Delegating, llvm::Value *This) {
|
|
|
|
llvm::Value *Callee = CGM.GetAddrOfCXXDestructor(DD, Type);
|
|
|
|
|
|
|
|
if (DD->isVirtual())
|
|
|
|
This = adjustThisArgumentForVirtualCall(CGF, GlobalDecl(DD, Type), This);
|
|
|
|
|
|
|
|
// FIXME: Provide a source location here.
|
|
|
|
CGF.EmitCXXMemberCall(DD, SourceLocation(), Callee, ReturnValueSlot(), This,
|
|
|
|
/*ImplicitParam=*/0, /*ImplicitParamTy=*/QualType(), 0, 0);
|
|
|
|
}
|
|
|
|
|
2013-09-27 22:48:01 +08:00
|
|
|
void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
|
|
|
|
const CXXRecordDecl *RD) {
|
2013-11-05 23:54:58 +08:00
|
|
|
MicrosoftVTableContext &VFTContext = CGM.getMicrosoftVTableContext();
|
2014-02-28 03:40:09 +08:00
|
|
|
VPtrInfoVector VFPtrs = VFTContext.getVFPtrOffsets(RD);
|
2013-09-27 22:48:01 +08:00
|
|
|
llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
|
|
|
|
|
2014-02-28 03:40:09 +08:00
|
|
|
for (VPtrInfoVector::iterator I = VFPtrs.begin(), E = VFPtrs.end(); I != E;
|
|
|
|
++I) {
|
|
|
|
llvm::GlobalVariable *VTable = getAddrOfVTable(RD, (*I)->FullOffsetInMDC);
|
2013-09-27 22:48:01 +08:00
|
|
|
if (VTable->hasInitializer())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
const VTableLayout &VTLayout =
|
2014-02-28 03:40:09 +08:00
|
|
|
VFTContext.getVFTableLayout(RD, (*I)->FullOffsetInMDC);
|
2013-09-27 22:48:01 +08:00
|
|
|
llvm::Constant *Init = CGVT.CreateVTableInitializer(
|
|
|
|
RD, VTLayout.vtable_component_begin(),
|
|
|
|
VTLayout.getNumVTableComponents(), VTLayout.vtable_thunk_begin(),
|
|
|
|
VTLayout.getNumVTableThunks());
|
|
|
|
VTable->setInitializer(Init);
|
|
|
|
|
|
|
|
VTable->setLinkage(Linkage);
|
2014-02-08 08:41:16 +08:00
|
|
|
CGM.setGlobalVisibility(VTable, RD);
|
2013-09-27 22:48:01 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Value *MicrosoftCXXABI::getVTableAddressPointInStructor(
|
|
|
|
CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base,
|
|
|
|
const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) {
|
|
|
|
NeedsVirtualOffset = (NearestVBase != 0);
|
|
|
|
|
|
|
|
llvm::Value *VTableAddressPoint =
|
|
|
|
getAddrOfVTable(VTableClass, Base.getBaseOffset());
|
|
|
|
if (!VTableAddressPoint) {
|
|
|
|
assert(Base.getBase()->getNumVBases() &&
|
|
|
|
!CGM.getContext().getASTRecordLayout(Base.getBase()).hasOwnVFPtr());
|
|
|
|
}
|
|
|
|
return VTableAddressPoint;
|
|
|
|
}
|
|
|
|
|
2013-10-03 14:26:13 +08:00
|
|
|
static void mangleVFTableName(MicrosoftMangleContext &MangleContext,
|
2014-02-28 03:40:09 +08:00
|
|
|
const CXXRecordDecl *RD, const VPtrInfo *VFPtr,
|
2013-10-03 14:26:13 +08:00
|
|
|
SmallString<256> &Name) {
|
2013-09-27 22:48:01 +08:00
|
|
|
llvm::raw_svector_ostream Out(Name);
|
2014-02-28 03:40:09 +08:00
|
|
|
MangleContext.mangleCXXVFTable(RD, VFPtr->MangledPath, Out);
|
2013-09-27 22:48:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr(
|
|
|
|
BaseSubobject Base, const CXXRecordDecl *VTableClass) {
|
|
|
|
llvm::Constant *VTable = getAddrOfVTable(VTableClass, Base.getBaseOffset());
|
|
|
|
assert(VTable && "Couldn't find a vftable for the given base?");
|
|
|
|
return VTable;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
|
|
|
|
CharUnits VPtrOffset) {
|
|
|
|
// getAddrOfVTable may return 0 if asked to get an address of a vtable which
|
|
|
|
// shouldn't be used in the given record type. We want to cache this result in
|
|
|
|
// VFTablesMap, thus a simple zero check is not sufficient.
|
|
|
|
VFTableIdTy ID(RD, VPtrOffset);
|
|
|
|
VFTablesMapTy::iterator I;
|
|
|
|
bool Inserted;
|
2014-03-02 21:01:17 +08:00
|
|
|
std::tie(I, Inserted) = VFTablesMap.insert(
|
2013-09-27 22:48:01 +08:00
|
|
|
std::make_pair(ID, static_cast<llvm::GlobalVariable *>(0)));
|
|
|
|
if (!Inserted)
|
|
|
|
return I->second;
|
|
|
|
|
|
|
|
llvm::GlobalVariable *&VTable = I->second;
|
|
|
|
|
2013-11-05 23:54:58 +08:00
|
|
|
MicrosoftVTableContext &VTContext = CGM.getMicrosoftVTableContext();
|
2014-02-28 03:40:09 +08:00
|
|
|
const VPtrInfoVector &VFPtrs = VTContext.getVFPtrOffsets(RD);
|
2013-09-27 22:48:01 +08:00
|
|
|
|
|
|
|
if (DeferredVFTables.insert(RD)) {
|
|
|
|
// We haven't processed this record type before.
|
|
|
|
// Queue up this v-table for possible deferred emission.
|
|
|
|
CGM.addDeferredVTable(RD);
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
// Create all the vftables at once in order to make sure each vftable has
|
|
|
|
// a unique mangled name.
|
|
|
|
llvm::StringSet<> ObservedMangledNames;
|
|
|
|
for (size_t J = 0, F = VFPtrs.size(); J != F; ++J) {
|
|
|
|
SmallString<256> Name;
|
2013-10-03 14:26:13 +08:00
|
|
|
mangleVFTableName(getMangleContext(), RD, VFPtrs[J], Name);
|
2013-09-27 22:48:01 +08:00
|
|
|
if (!ObservedMangledNames.insert(Name.str()))
|
|
|
|
llvm_unreachable("Already saw this mangling before?");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t J = 0, F = VFPtrs.size(); J != F; ++J) {
|
2014-02-28 03:40:09 +08:00
|
|
|
if (VFPtrs[J]->FullOffsetInMDC != VPtrOffset)
|
2013-09-27 22:48:01 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
llvm::ArrayType *ArrayType = llvm::ArrayType::get(
|
|
|
|
CGM.Int8PtrTy,
|
2014-02-28 03:40:09 +08:00
|
|
|
VTContext.getVFTableLayout(RD, VFPtrs[J]->FullOffsetInMDC)
|
2013-09-27 22:48:01 +08:00
|
|
|
.getNumVTableComponents());
|
|
|
|
|
|
|
|
SmallString<256> Name;
|
2013-10-03 14:26:13 +08:00
|
|
|
mangleVFTableName(getMangleContext(), RD, VFPtrs[J], Name);
|
2013-09-27 22:48:01 +08:00
|
|
|
VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
|
|
|
|
Name.str(), ArrayType, llvm::GlobalValue::ExternalLinkage);
|
|
|
|
VTable->setUnnamedAddr(true);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return VTable;
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
2013-11-05 23:54:58 +08:00
|
|
|
MicrosoftVTableContext::MethodVFTableLocation ML =
|
|
|
|
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD);
|
2013-08-21 14:25:03 +08:00
|
|
|
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-10-17 02:24:06 +08:00
|
|
|
GlobalDecl GD(Dtor, Dtor_Deleting);
|
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-10-17 02:24:06 +08:00
|
|
|
llvm::Value *Callee = getVirtualFunctionPointer(CGF, GD, 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-10-17 02:24:06 +08:00
|
|
|
This = adjustThisArgumentForVirtualCall(CGF, GD, This);
|
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
|
|
|
}
|
|
|
|
|
2014-01-03 08:14:35 +08:00
|
|
|
const VBTableGlobals &
|
|
|
|
MicrosoftCXXABI::enumerateVBTables(const CXXRecordDecl *RD) {
|
2013-06-19 23:20:38 +08:00
|
|
|
// At this layer, we can key the cache off of a single class, which is much
|
2014-01-03 08:14:35 +08:00
|
|
|
// easier than caching each vbtable individually.
|
|
|
|
llvm::DenseMap<const CXXRecordDecl*, VBTableGlobals>::iterator Entry;
|
|
|
|
bool Added;
|
2014-03-02 21:01:17 +08:00
|
|
|
std::tie(Entry, Added) =
|
|
|
|
VBTablesMap.insert(std::make_pair(RD, VBTableGlobals()));
|
2014-01-03 08:14:35 +08:00
|
|
|
VBTableGlobals &VBGlobals = Entry->second;
|
|
|
|
if (!Added)
|
|
|
|
return VBGlobals;
|
|
|
|
|
|
|
|
MicrosoftVTableContext &Context = CGM.getMicrosoftVTableContext();
|
|
|
|
VBGlobals.VBTables = &Context.enumerateVBTables(RD);
|
|
|
|
|
|
|
|
// Cache the globals for all vbtables so we don't have to recompute the
|
|
|
|
// mangled names.
|
|
|
|
llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
|
2014-02-28 03:40:09 +08:00
|
|
|
for (VPtrInfoVector::const_iterator I = VBGlobals.VBTables->begin(),
|
|
|
|
E = VBGlobals.VBTables->end();
|
2014-01-03 08:14:35 +08:00
|
|
|
I != E; ++I) {
|
2014-01-04 07:42:00 +08:00
|
|
|
VBGlobals.Globals.push_back(getAddrOfVBTable(**I, RD, Linkage));
|
2014-01-03 08:14:35 +08:00
|
|
|
}
|
2013-06-19 23:20:38 +08:00
|
|
|
|
2014-01-03 08:14:35 +08:00
|
|
|
return VBGlobals;
|
2013-06-19 23:20:38 +08:00
|
|
|
}
|
|
|
|
|
2014-02-21 10:27:32 +08:00
|
|
|
llvm::Function *MicrosoftCXXABI::EmitVirtualMemPtrThunk(
|
|
|
|
const CXXMethodDecl *MD,
|
|
|
|
const MicrosoftVTableContext::MethodVFTableLocation &ML) {
|
|
|
|
// Calculate the mangled name.
|
|
|
|
SmallString<256> ThunkName;
|
|
|
|
llvm::raw_svector_ostream Out(ThunkName);
|
|
|
|
getMangleContext().mangleVirtualMemPtrThunk(MD, Out);
|
|
|
|
Out.flush();
|
|
|
|
|
2013-11-16 01:24:45 +08:00
|
|
|
// If the thunk has been generated previously, just return it.
|
|
|
|
if (llvm::GlobalValue *GV = CGM.getModule().getNamedValue(ThunkName))
|
|
|
|
return cast<llvm::Function>(GV);
|
|
|
|
|
|
|
|
// Create the llvm::Function.
|
|
|
|
const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeGlobalDeclaration(MD);
|
|
|
|
llvm::FunctionType *ThunkTy = CGM.getTypes().GetFunctionType(FnInfo);
|
|
|
|
llvm::Function *ThunkFn =
|
|
|
|
llvm::Function::Create(ThunkTy, llvm::Function::ExternalLinkage,
|
|
|
|
ThunkName.str(), &CGM.getModule());
|
|
|
|
assert(ThunkFn->getName() == ThunkName && "name was uniqued!");
|
|
|
|
|
|
|
|
ThunkFn->setLinkage(MD->isExternallyVisible()
|
|
|
|
? llvm::GlobalValue::LinkOnceODRLinkage
|
|
|
|
: llvm::GlobalValue::InternalLinkage);
|
|
|
|
|
|
|
|
CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn);
|
|
|
|
CGM.SetLLVMFunctionAttributesForDefinition(MD, ThunkFn);
|
|
|
|
|
|
|
|
// Start codegen.
|
|
|
|
CodeGenFunction CGF(CGM);
|
|
|
|
CGF.StartThunk(ThunkFn, MD, FnInfo);
|
|
|
|
|
2014-02-21 10:27:32 +08:00
|
|
|
// Load the vfptr and then callee from the vftable. The callee should have
|
|
|
|
// adjusted 'this' so that the vfptr is at offset zero.
|
2013-11-16 01:24:45 +08:00
|
|
|
llvm::Value *This = CGF.LoadCXXThis();
|
2014-02-21 10:27:32 +08:00
|
|
|
llvm::Value *VTable =
|
|
|
|
CGF.GetVTablePtr(This, ThunkTy->getPointerTo()->getPointerTo());
|
|
|
|
llvm::Value *VFuncPtr =
|
|
|
|
CGF.Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn");
|
|
|
|
llvm::Value *Callee = CGF.Builder.CreateLoad(VFuncPtr);
|
2013-11-16 01:24:45 +08:00
|
|
|
|
|
|
|
// Make the call and return the result.
|
|
|
|
CGF.EmitCallAndReturnForThunk(MD, Callee, 0);
|
|
|
|
|
|
|
|
return ThunkFn;
|
|
|
|
}
|
|
|
|
|
2013-09-27 22:48:01 +08:00
|
|
|
void MicrosoftCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) {
|
2014-01-03 08:14:35 +08:00
|
|
|
const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
|
|
|
|
for (unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) {
|
2014-02-28 03:40:09 +08:00
|
|
|
const VPtrInfo *VBT = (*VBGlobals.VBTables)[I];
|
2014-01-03 08:14:35 +08:00
|
|
|
llvm::GlobalVariable *GV = VBGlobals.Globals[I];
|
2014-01-04 07:42:00 +08:00
|
|
|
emitVBTableDefinition(*VBT, RD, GV);
|
2014-01-03 08:14:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::GlobalVariable *
|
2014-02-28 03:40:09 +08:00
|
|
|
MicrosoftCXXABI::getAddrOfVBTable(const VPtrInfo &VBT, const CXXRecordDecl *RD,
|
2014-01-03 08:14:35 +08:00
|
|
|
llvm::GlobalVariable::LinkageTypes Linkage) {
|
|
|
|
SmallString<256> OutName;
|
|
|
|
llvm::raw_svector_ostream Out(OutName);
|
|
|
|
MicrosoftMangleContext &Mangler =
|
|
|
|
cast<MicrosoftMangleContext>(CGM.getCXXABI().getMangleContext());
|
|
|
|
Mangler.mangleCXXVBTable(RD, VBT.MangledPath, Out);
|
|
|
|
Out.flush();
|
|
|
|
StringRef Name = OutName.str();
|
|
|
|
|
|
|
|
llvm::ArrayType *VBTableType =
|
|
|
|
llvm::ArrayType::get(CGM.IntTy, 1 + VBT.ReusingBase->getNumVBases());
|
|
|
|
|
|
|
|
assert(!CGM.getModule().getNamedGlobal(Name) &&
|
|
|
|
"vbtable with this name already exists: mangling bug?");
|
|
|
|
llvm::GlobalVariable *GV =
|
|
|
|
CGM.CreateOrReplaceCXXRuntimeVariable(Name, VBTableType, Linkage);
|
|
|
|
GV->setUnnamedAddr(true);
|
|
|
|
return GV;
|
|
|
|
}
|
|
|
|
|
2014-02-28 03:40:09 +08:00
|
|
|
void MicrosoftCXXABI::emitVBTableDefinition(const VPtrInfo &VBT,
|
2014-01-03 08:14:35 +08:00
|
|
|
const CXXRecordDecl *RD,
|
|
|
|
llvm::GlobalVariable *GV) const {
|
|
|
|
const CXXRecordDecl *ReusingBase = VBT.ReusingBase;
|
|
|
|
|
|
|
|
assert(RD->getNumVBases() && ReusingBase->getNumVBases() &&
|
|
|
|
"should only emit vbtables for classes with vbtables");
|
2013-09-27 22:48:01 +08:00
|
|
|
|
2014-01-03 08:14:35 +08:00
|
|
|
const ASTRecordLayout &BaseLayout =
|
2014-02-28 03:40:09 +08:00
|
|
|
CGM.getContext().getASTRecordLayout(VBT.BaseWithVPtr);
|
2014-01-03 08:14:35 +08:00
|
|
|
const ASTRecordLayout &DerivedLayout =
|
|
|
|
CGM.getContext().getASTRecordLayout(RD);
|
|
|
|
|
|
|
|
SmallVector<llvm::Constant *, 4> Offsets(1 + ReusingBase->getNumVBases(), 0);
|
|
|
|
|
|
|
|
// The offset from ReusingBase's vbptr to itself always leads.
|
|
|
|
CharUnits VBPtrOffset = BaseLayout.getVBPtrOffset();
|
|
|
|
Offsets[0] = llvm::ConstantInt::get(CGM.IntTy, -VBPtrOffset.getQuantity());
|
|
|
|
|
|
|
|
MicrosoftVTableContext &Context = CGM.getMicrosoftVTableContext();
|
|
|
|
for (CXXRecordDecl::base_class_const_iterator I = ReusingBase->vbases_begin(),
|
|
|
|
E = ReusingBase->vbases_end();
|
2013-06-19 23:20:38 +08:00
|
|
|
I != E; ++I) {
|
2014-01-03 08:14:35 +08:00
|
|
|
const CXXRecordDecl *VBase = I->getType()->getAsCXXRecordDecl();
|
|
|
|
CharUnits Offset = DerivedLayout.getVBaseClassOffset(VBase);
|
|
|
|
assert(!Offset.isNegative());
|
2014-01-04 07:42:00 +08:00
|
|
|
|
2014-01-03 08:14:35 +08:00
|
|
|
// Make it relative to the subobject vbptr.
|
2014-01-04 07:42:00 +08:00
|
|
|
CharUnits CompleteVBPtrOffset = VBT.NonVirtualOffset + VBPtrOffset;
|
2014-02-28 03:40:09 +08:00
|
|
|
if (VBT.getVBaseWithVPtr())
|
2014-01-04 07:42:00 +08:00
|
|
|
CompleteVBPtrOffset +=
|
2014-02-28 03:40:09 +08:00
|
|
|
DerivedLayout.getVBaseClassOffset(VBT.getVBaseWithVPtr());
|
2014-01-04 07:42:00 +08:00
|
|
|
Offset -= CompleteVBPtrOffset;
|
|
|
|
|
2014-01-03 08:14:35 +08:00
|
|
|
unsigned VBIndex = Context.getVBTableIndex(ReusingBase, VBase);
|
|
|
|
assert(Offsets[VBIndex] == 0 && "The same vbindex seen twice?");
|
|
|
|
Offsets[VBIndex] = llvm::ConstantInt::get(CGM.IntTy, Offset.getQuantity());
|
2013-06-19 23:20:38 +08:00
|
|
|
}
|
2014-01-03 08:14:35 +08:00
|
|
|
|
|
|
|
assert(Offsets.size() ==
|
|
|
|
cast<llvm::ArrayType>(cast<llvm::PointerType>(GV->getType())
|
|
|
|
->getElementType())->getNumElements());
|
|
|
|
llvm::ArrayType *VBTableType =
|
|
|
|
llvm::ArrayType::get(CGM.IntTy, Offsets.size());
|
|
|
|
llvm::Constant *Init = llvm::ConstantArray::get(VBTableType, Offsets);
|
|
|
|
GV->setInitializer(Init);
|
|
|
|
|
|
|
|
// Set the right visibility.
|
2014-02-08 08:41:16 +08:00
|
|
|
CGM.setGlobalVisibility(GV, RD);
|
2013-06-19 23:20:38 +08:00
|
|
|
}
|
|
|
|
|
2013-10-30 19:55:43 +08:00
|
|
|
llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *This,
|
|
|
|
const ThisAdjustment &TA) {
|
|
|
|
if (TA.isEmpty())
|
|
|
|
return This;
|
|
|
|
|
|
|
|
llvm::Value *V = CGF.Builder.CreateBitCast(This, CGF.Int8PtrTy);
|
|
|
|
|
2013-11-06 14:24:31 +08:00
|
|
|
if (!TA.Virtual.isEmpty()) {
|
|
|
|
assert(TA.Virtual.Microsoft.VtordispOffset < 0);
|
|
|
|
// Adjust the this argument based on the vtordisp value.
|
|
|
|
llvm::Value *VtorDispPtr =
|
|
|
|
CGF.Builder.CreateConstGEP1_32(V, TA.Virtual.Microsoft.VtordispOffset);
|
|
|
|
VtorDispPtr =
|
|
|
|
CGF.Builder.CreateBitCast(VtorDispPtr, CGF.Int32Ty->getPointerTo());
|
|
|
|
llvm::Value *VtorDisp = CGF.Builder.CreateLoad(VtorDispPtr, "vtordisp");
|
|
|
|
V = CGF.Builder.CreateGEP(V, CGF.Builder.CreateNeg(VtorDisp));
|
|
|
|
|
|
|
|
if (TA.Virtual.Microsoft.VBPtrOffset) {
|
|
|
|
// If the final overrider is defined in a virtual base other than the one
|
|
|
|
// that holds the vfptr, we have to use a vtordispex thunk which looks up
|
|
|
|
// the vbtable of the derived class.
|
|
|
|
assert(TA.Virtual.Microsoft.VBPtrOffset > 0);
|
|
|
|
assert(TA.Virtual.Microsoft.VBOffsetOffset >= 0);
|
|
|
|
llvm::Value *VBPtr;
|
|
|
|
llvm::Value *VBaseOffset =
|
|
|
|
GetVBaseOffsetFromVBPtr(CGF, V, -TA.Virtual.Microsoft.VBPtrOffset,
|
|
|
|
TA.Virtual.Microsoft.VBOffsetOffset, &VBPtr);
|
|
|
|
V = CGF.Builder.CreateInBoundsGEP(VBPtr, VBaseOffset);
|
|
|
|
}
|
|
|
|
}
|
2013-10-30 19:55:43 +08:00
|
|
|
|
|
|
|
if (TA.NonVirtual) {
|
|
|
|
// Non-virtual adjustment might result in a pointer outside the allocated
|
|
|
|
// object, e.g. if the final overrider class is laid out after the virtual
|
|
|
|
// base that declares a method in the most derived class.
|
|
|
|
V = CGF.Builder.CreateConstGEP1_32(V, TA.NonVirtual);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't need to bitcast back, the call CodeGen will handle this.
|
|
|
|
return V;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Value *
|
|
|
|
MicrosoftCXXABI::performReturnAdjustment(CodeGenFunction &CGF, llvm::Value *Ret,
|
|
|
|
const ReturnAdjustment &RA) {
|
|
|
|
if (RA.isEmpty())
|
|
|
|
return Ret;
|
|
|
|
|
|
|
|
llvm::Value *V = CGF.Builder.CreateBitCast(Ret, CGF.Int8PtrTy);
|
|
|
|
|
|
|
|
if (RA.Virtual.Microsoft.VBIndex) {
|
|
|
|
assert(RA.Virtual.Microsoft.VBIndex > 0);
|
|
|
|
int32_t IntSize =
|
|
|
|
getContext().getTypeSizeInChars(getContext().IntTy).getQuantity();
|
|
|
|
llvm::Value *VBPtr;
|
|
|
|
llvm::Value *VBaseOffset =
|
|
|
|
GetVBaseOffsetFromVBPtr(CGF, V, RA.Virtual.Microsoft.VBPtrOffset,
|
|
|
|
IntSize * RA.Virtual.Microsoft.VBIndex, &VBPtr);
|
|
|
|
V = CGF.Builder.CreateInBoundsGEP(VBPtr, VBaseOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (RA.NonVirtual)
|
|
|
|
V = CGF.Builder.CreateConstInBoundsGEP1_32(V, RA.NonVirtual);
|
|
|
|
|
|
|
|
// Cast back to the original type.
|
|
|
|
return CGF.Builder.CreateBitCast(V, Ret->getType());
|
|
|
|
}
|
|
|
|
|
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,
|
2013-09-11 04:14:30 +08:00
|
|
|
llvm::GlobalVariable *GV,
|
2012-05-01 14:13:13 +08:00
|
|
|
bool PerformInit) {
|
2013-09-11 04:14:30 +08:00
|
|
|
// MSVC always uses an i32 bitfield to guard initialization, which is *not*
|
|
|
|
// threadsafe. Since the user may be linking in inline functions compiled by
|
|
|
|
// cl.exe, there's no reason to provide a false sense of security by using
|
|
|
|
// critical sections here.
|
2012-05-01 14:13:13 +08:00
|
|
|
|
2013-04-15 07:01:42 +08:00
|
|
|
if (D.getTLSKind())
|
|
|
|
CGM.ErrorUnsupported(&D, "dynamic TLS initialization");
|
|
|
|
|
2013-09-11 04:14:30 +08:00
|
|
|
CGBuilderTy &Builder = CGF.Builder;
|
|
|
|
llvm::IntegerType *GuardTy = CGF.Int32Ty;
|
|
|
|
llvm::ConstantInt *Zero = llvm::ConstantInt::get(GuardTy, 0);
|
|
|
|
|
|
|
|
// Get the guard variable for this function if we have one already.
|
|
|
|
GuardInfo &GI = GuardVariableMap[D.getDeclContext()];
|
|
|
|
|
|
|
|
unsigned BitIndex;
|
|
|
|
if (D.isExternallyVisible()) {
|
|
|
|
// Externally visible variables have to be numbered in Sema to properly
|
|
|
|
// handle unreachable VarDecls.
|
2014-03-05 16:57:59 +08:00
|
|
|
BitIndex = getContext().getStaticLocalNumber(&D);
|
2013-09-11 04:14:30 +08:00
|
|
|
assert(BitIndex > 0);
|
|
|
|
BitIndex--;
|
|
|
|
} else {
|
|
|
|
// Non-externally visible variables are numbered here in CodeGen.
|
|
|
|
BitIndex = GI.BitIndex++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (BitIndex >= 32) {
|
|
|
|
if (D.isExternallyVisible())
|
|
|
|
ErrorUnsupportedABI(CGF, "more than 32 guarded initializations");
|
|
|
|
BitIndex %= 32;
|
|
|
|
GI.Guard = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Lazily create the i32 bitfield for this function.
|
|
|
|
if (!GI.Guard) {
|
|
|
|
// Mangle the name for the guard.
|
|
|
|
SmallString<256> GuardName;
|
|
|
|
{
|
|
|
|
llvm::raw_svector_ostream Out(GuardName);
|
|
|
|
getMangleContext().mangleStaticGuardVariable(&D, Out);
|
|
|
|
Out.flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the guard variable with a zero-initializer. Just absorb linkage
|
|
|
|
// and visibility from the guarded variable.
|
|
|
|
GI.Guard = new llvm::GlobalVariable(CGM.getModule(), GuardTy, false,
|
|
|
|
GV->getLinkage(), Zero, GuardName.str());
|
|
|
|
GI.Guard->setVisibility(GV->getVisibility());
|
|
|
|
} else {
|
|
|
|
assert(GI.Guard->getLinkage() == GV->getLinkage() &&
|
|
|
|
"static local from the same function had different linkage");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pseudo code for the test:
|
|
|
|
// if (!(GuardVar & MyGuardBit)) {
|
|
|
|
// GuardVar |= MyGuardBit;
|
|
|
|
// ... initialize the object ...;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// Test our bit from the guard variable.
|
|
|
|
llvm::ConstantInt *Bit = llvm::ConstantInt::get(GuardTy, 1U << BitIndex);
|
|
|
|
llvm::LoadInst *LI = Builder.CreateLoad(GI.Guard);
|
|
|
|
llvm::Value *IsInitialized =
|
|
|
|
Builder.CreateICmpNE(Builder.CreateAnd(LI, Bit), Zero);
|
|
|
|
llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
|
|
|
|
llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
|
|
|
|
Builder.CreateCondBr(IsInitialized, EndBlock, InitBlock);
|
|
|
|
|
|
|
|
// Set our bit in the guard variable and emit the initializer and add a global
|
|
|
|
// destructor if appropriate.
|
|
|
|
CGF.EmitBlock(InitBlock);
|
|
|
|
Builder.CreateStore(Builder.CreateOr(LI, Bit), GI.Guard);
|
|
|
|
CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit);
|
|
|
|
Builder.CreateBr(EndBlock);
|
|
|
|
|
|
|
|
// Continue.
|
|
|
|
CGF.EmitBlock(EndBlock);
|
2012-05-01 14:13:13 +08:00
|
|
|
}
|
|
|
|
|
2013-04-12 02:13:19 +08:00
|
|
|
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.
|
2014-01-17 17:01:00 +08:00
|
|
|
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
|
|
|
|
MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
|
2014-02-06 01:27:08 +08:00
|
|
|
return (!MSInheritanceAttr::hasVBTableOffsetField(Inheritance) &&
|
|
|
|
RD->nullFieldOffsetIsZero());
|
2013-03-23 03:02:54 +08:00
|
|
|
}
|
|
|
|
|
2013-04-12 02:13:19 +08:00
|
|
|
llvm::Type *
|
|
|
|
MicrosoftCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
|
2014-01-17 17:01:00 +08:00
|
|
|
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
|
|
|
|
MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
|
2013-04-12 02:13:19 +08:00
|
|
|
llvm::SmallVector<llvm::Type *, 4> fields;
|
|
|
|
if (MPT->isMemberFunctionPointer())
|
|
|
|
fields.push_back(CGM.VoidPtrTy); // FunctionPointerOrVirtualThunk
|
|
|
|
else
|
|
|
|
fields.push_back(CGM.IntTy); // FieldOffset
|
|
|
|
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasNVOffsetField(MPT->isMemberFunctionPointer(),
|
|
|
|
Inheritance))
|
2013-04-12 02:13:19 +08:00
|
|
|
fields.push_back(CGM.IntTy);
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance))
|
2013-04-12 02:13:19 +08:00
|
|
|
fields.push_back(CGM.IntTy);
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance))
|
2013-04-12 02:13:19 +08:00
|
|
|
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());
|
2014-01-17 17:01:00 +08:00
|
|
|
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
|
|
|
|
MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
|
2013-04-12 02:13:19 +08:00
|
|
|
if (MPT->isMemberFunctionPointer()) {
|
|
|
|
// FunctionPointerOrVirtualThunk
|
|
|
|
fields.push_back(llvm::Constant::getNullValue(CGM.VoidPtrTy));
|
|
|
|
} else {
|
2014-02-06 01:27:08 +08:00
|
|
|
if (RD->nullFieldOffsetIsZero())
|
2013-04-12 02:13:19 +08:00
|
|
|
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
|
|
|
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasNVOffsetField(MPT->isMemberFunctionPointer(),
|
|
|
|
Inheritance))
|
2013-04-12 02:13:19 +08:00
|
|
|
fields.push_back(getZeroInt());
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance))
|
2013-04-12 02:13:19 +08:00
|
|
|
fields.push_back(getZeroInt());
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance))
|
2013-04-12 02:13:19 +08:00
|
|
|
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
|
|
|
{
|
2014-01-17 17:01:00 +08:00
|
|
|
MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
|
2013-05-03 09:15:11 +08:00
|
|
|
|
|
|
|
// Single inheritance class member pointer are represented as scalars instead
|
|
|
|
// of aggregates.
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::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);
|
|
|
|
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasNVOffsetField(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
|
|
|
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) {
|
2013-10-15 09:18:02 +08:00
|
|
|
CharUnits Offs = CharUnits::Zero();
|
|
|
|
if (RD->getNumVBases())
|
2014-01-14 08:50:39 +08:00
|
|
|
Offs = getContext().getASTRecordLayout(RD).getVBPtrOffset();
|
2013-10-15 09:18:02 +08:00
|
|
|
fields.push_back(llvm::ConstantInt::get(CGM.IntTy, Offs.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.
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance))
|
2013-04-12 02:13:19 +08:00
|
|
|
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) {
|
2014-01-17 17:01:00 +08:00
|
|
|
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
|
2013-05-03 09:15:11 +08:00
|
|
|
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))
|
2014-01-17 17:01:00 +08:00
|
|
|
return BuildMemberPointer(MPT->getMostRecentCXXRecordDecl(), MD,
|
|
|
|
ThisAdjustment);
|
2013-05-10 05:01:17 +08:00
|
|
|
|
|
|
|
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();
|
2014-01-17 17:01:00 +08:00
|
|
|
RD = RD->getMostRecentDecl();
|
2013-05-03 09:15:11 +08:00
|
|
|
CodeGenTypes &Types = CGM.getTypes();
|
|
|
|
|
|
|
|
llvm::Constant *FirstField;
|
2013-11-16 01:24:45 +08:00
|
|
|
if (!MD->isVirtual()) {
|
2013-05-03 09:15:11 +08:00
|
|
|
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);
|
2013-11-16 01:24:45 +08:00
|
|
|
} else {
|
|
|
|
MicrosoftVTableContext::MethodVFTableLocation ML =
|
|
|
|
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(MD);
|
|
|
|
if (MD->isVariadic()) {
|
|
|
|
CGM.ErrorUnsupported(MD, "pointer to variadic virtual member function");
|
|
|
|
FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy);
|
|
|
|
} else if (!CGM.getTypes().isFuncTypeConvertible(
|
|
|
|
MD->getType()->castAs<FunctionType>())) {
|
|
|
|
CGM.ErrorUnsupported(MD, "pointer to virtual member function with "
|
|
|
|
"incomplete return or parameter type");
|
|
|
|
FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy);
|
|
|
|
} else if (ML.VBase) {
|
|
|
|
CGM.ErrorUnsupported(MD, "pointer to virtual member function overriding "
|
|
|
|
"member function in virtual base class");
|
|
|
|
FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy);
|
|
|
|
} else {
|
2014-02-21 10:27:32 +08:00
|
|
|
llvm::Function *Thunk = EmitVirtualMemPtrThunk(MD, ML);
|
2013-11-16 01:24:45 +08:00
|
|
|
FirstField = llvm::ConstantExpr::getBitCast(Thunk, CGM.VoidPtrTy);
|
2014-02-21 10:27:32 +08:00
|
|
|
// Include the vfptr adjustment if the method is in a non-primary vftable.
|
|
|
|
NonVirtualBaseAdjustment += ML.VFPtrOffset;
|
2013-11-16 01:24:45 +08:00
|
|
|
}
|
2013-05-03 09:15:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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.
|
2014-01-17 17:01:00 +08:00
|
|
|
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
|
|
|
|
MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::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 *VBPtrOffset,
|
2013-10-28 01:10:27 +08:00
|
|
|
llvm::Value *VBTableOffset,
|
2013-05-30 02:02:47 +08:00
|
|
|
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.
|
2014-02-21 07:22:07 +08:00
|
|
|
llvm::Value *MicrosoftCXXABI::AdjustVirtualBase(
|
|
|
|
CodeGenFunction &CGF, const Expr *E, const CXXRecordDecl *RD,
|
|
|
|
llvm::Value *Base, llvm::Value *VBTableOffset, llvm::Value *VBPtrOffset) {
|
2013-04-12 02:13:19 +08:00
|
|
|
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();
|
2014-02-21 07:22:07 +08:00
|
|
|
if (!RD->hasDefinition()) {
|
|
|
|
DiagnosticsEngine &Diags = CGF.CGM.getDiags();
|
|
|
|
unsigned DiagID = Diags.getCustomDiagID(
|
|
|
|
DiagnosticsEngine::Error,
|
|
|
|
"member pointer representation requires a "
|
|
|
|
"complete class type for %0 to perform this expression");
|
|
|
|
Diags.Report(E->getExprLoc(), DiagID) << RD << E->getSourceRange();
|
|
|
|
} else if (RD->getNumVBases())
|
2014-01-14 08:50:39 +08:00
|
|
|
offs = getContext().getASTRecordLayout(RD).getVBPtrOffset();
|
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-10-28 01:10:27 +08:00
|
|
|
GetVBaseOffsetFromVBPtr(CGF, Base, VBPtrOffset, VBTableOffset, &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
|
|
|
}
|
|
|
|
|
2014-02-21 07:22:07 +08:00
|
|
|
llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress(
|
|
|
|
CodeGenFunction &CGF, const Expr *E, 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;
|
2014-01-17 17:01:00 +08:00
|
|
|
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
|
|
|
|
MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
|
2013-04-12 02:13:19 +08:00
|
|
|
|
|
|
|
// 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++);
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance))
|
2013-04-12 02:13:19 +08:00
|
|
|
VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++);
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance))
|
2013-04-12 02:13:19 +08:00
|
|
|
VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++);
|
2013-03-23 03:02:54 +08:00
|
|
|
}
|
|
|
|
|
2013-04-12 02:13:19 +08:00
|
|
|
if (VirtualBaseAdjustmentOffset) {
|
2014-02-21 07:22:07 +08:00
|
|
|
Base = AdjustVirtualBase(CGF, E, RD, Base, VirtualBaseAdjustmentOffset,
|
2013-04-12 02:13:19 +08:00
|
|
|
VBPtrOffset);
|
2013-03-23 03:02:54 +08:00
|
|
|
}
|
2013-12-06 06:44:07 +08:00
|
|
|
|
|
|
|
// Cast to char*.
|
|
|
|
Base = Builder.CreateBitCast(Base, Builder.getInt8Ty()->getPointerTo(AS));
|
|
|
|
|
|
|
|
// Apply the offset, which we assume is non-null.
|
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);
|
|
|
|
}
|
|
|
|
|
2014-01-17 17:01:00 +08:00
|
|
|
static MSInheritanceAttr::Spelling
|
2013-05-10 05:01:17 +08:00
|
|
|
getInheritanceFromMemptr(const MemberPointerType *MPT) {
|
2014-01-17 17:01:00 +08:00
|
|
|
return MPT->getMostRecentCXXRecordDecl()->getMSInheritanceModel();
|
2013-05-10 05:01:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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>();
|
|
|
|
bool IsFunc = SrcTy->isMemberFunctionPointer();
|
|
|
|
|
|
|
|
// If the classes use the same null representation, reinterpret_cast is a nop.
|
|
|
|
bool IsReinterpret = E->getCastKind() == CK_ReinterpretMemberPointer;
|
2014-01-17 17:01:00 +08:00
|
|
|
if (IsReinterpret && IsFunc)
|
|
|
|
return Src;
|
|
|
|
|
|
|
|
CXXRecordDecl *SrcRD = SrcTy->getMostRecentCXXRecordDecl();
|
|
|
|
CXXRecordDecl *DstRD = DstTy->getMostRecentCXXRecordDecl();
|
|
|
|
if (IsReinterpret &&
|
2014-02-06 01:27:08 +08:00
|
|
|
SrcRD->nullFieldOffsetIsZero() == DstRD->nullFieldOffsetIsZero())
|
2013-05-10 05:01:17 +08:00
|
|
|
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;
|
2014-01-17 17:01:00 +08:00
|
|
|
MSInheritanceAttr::Spelling SrcInheritance = SrcRD->getMSInheritanceModel();
|
2014-02-06 01:27:08 +08:00
|
|
|
if (!MSInheritanceAttr::hasOnlyOneField(IsFunc, SrcInheritance)) {
|
2013-05-10 05:01:17 +08:00
|
|
|
// We need to extract values.
|
|
|
|
unsigned I = 0;
|
|
|
|
FirstField = Builder.CreateExtractValue(Src, I++);
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasNVOffsetField(IsFunc, SrcInheritance))
|
2013-05-10 05:01:17 +08:00
|
|
|
NonVirtualBaseAdjustment = Builder.CreateExtractValue(Src, I++);
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasVBPtrOffsetField(SrcInheritance))
|
2013-05-10 05:01:17 +08:00
|
|
|
VBPtrOffset = Builder.CreateExtractValue(Src, I++);
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasVBTableOffsetField(SrcInheritance))
|
2013-05-10 05:01:17 +08:00
|
|
|
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.
|
2014-01-17 17:01:00 +08:00
|
|
|
MSInheritanceAttr::Spelling DstInheritance = DstRD->getMSInheritanceModel();
|
2013-05-10 05:01:17 +08:00
|
|
|
llvm::Value *Dst;
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasOnlyOneField(IsFunc, DstInheritance)) {
|
2013-05-10 05:01:17 +08:00
|
|
|
Dst = FirstField;
|
|
|
|
} else {
|
|
|
|
Dst = llvm::UndefValue::get(DstNull->getType());
|
|
|
|
unsigned Idx = 0;
|
|
|
|
Dst = Builder.CreateInsertValue(Dst, FirstField, Idx++);
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasNVOffsetField(IsFunc, DstInheritance))
|
2013-05-10 05:01:17 +08:00
|
|
|
Dst = Builder.CreateInsertValue(
|
|
|
|
Dst, getValueOrZeroInt(NonVirtualBaseAdjustment), Idx++);
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasVBPtrOffsetField(DstInheritance))
|
2013-05-10 05:01:17 +08:00
|
|
|
Dst = Builder.CreateInsertValue(
|
|
|
|
Dst, getValueOrZeroInt(VBPtrOffset), Idx++);
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasVBTableOffsetField(DstInheritance))
|
2013-05-10 05:01:17 +08:00
|
|
|
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;
|
|
|
|
|
2014-01-17 17:01:00 +08:00
|
|
|
MSInheritanceAttr::Spelling SrcInheritance = getInheritanceFromMemptr(SrcTy);
|
|
|
|
MSInheritanceAttr::Spelling DstInheritance = getInheritanceFromMemptr(DstTy);
|
2013-05-10 05:01:17 +08:00
|
|
|
|
|
|
|
// Decompose src.
|
|
|
|
llvm::Constant *FirstField = Src;
|
|
|
|
llvm::Constant *NonVirtualBaseAdjustment = 0;
|
|
|
|
llvm::Constant *VirtualBaseAdjustmentOffset = 0;
|
|
|
|
llvm::Constant *VBPtrOffset = 0;
|
|
|
|
bool IsFunc = SrcTy->isMemberFunctionPointer();
|
2014-02-06 01:27:08 +08:00
|
|
|
if (!MSInheritanceAttr::hasOnlyOneField(IsFunc, SrcInheritance)) {
|
2013-05-10 05:01:17 +08:00
|
|
|
// We need to extract values.
|
|
|
|
unsigned I = 0;
|
|
|
|
FirstField = Src->getAggregateElement(I++);
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasNVOffsetField(IsFunc, SrcInheritance))
|
2013-05-10 05:01:17 +08:00
|
|
|
NonVirtualBaseAdjustment = Src->getAggregateElement(I++);
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasVBPtrOffsetField(SrcInheritance))
|
2013-05-10 05:01:17 +08:00
|
|
|
VBPtrOffset = Src->getAggregateElement(I++);
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasVBTableOffsetField(SrcInheritance))
|
2013-05-10 05:01:17 +08:00
|
|
|
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.
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasOnlyOneField(IsFunc, DstInheritance))
|
2013-05-10 05:01:17 +08:00
|
|
|
return FirstField;
|
|
|
|
|
|
|
|
llvm::SmallVector<llvm::Constant *, 4> Fields;
|
|
|
|
Fields.push_back(FirstField);
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasNVOffsetField(IsFunc, DstInheritance))
|
2013-05-10 05:01:17 +08:00
|
|
|
Fields.push_back(getConstantOrZeroInt(NonVirtualBaseAdjustment));
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasVBPtrOffsetField(DstInheritance))
|
2013-05-10 05:01:17 +08:00
|
|
|
Fields.push_back(getConstantOrZeroInt(VBPtrOffset));
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasVBTableOffsetField(DstInheritance))
|
2013-05-10 05:01:17 +08:00
|
|
|
Fields.push_back(getConstantOrZeroInt(VirtualBaseAdjustmentOffset));
|
|
|
|
return llvm::ConstantStruct::getAnon(Fields);
|
|
|
|
}
|
|
|
|
|
2014-02-21 07:22:07 +08:00
|
|
|
llvm::Value *MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(
|
|
|
|
CodeGenFunction &CGF, const Expr *E, llvm::Value *&This,
|
|
|
|
llvm::Value *MemPtr, const MemberPointerType *MPT) {
|
2013-04-12 02:13:19 +08:00
|
|
|
assert(MPT->isMemberFunctionPointer());
|
|
|
|
const FunctionProtoType *FPT =
|
|
|
|
MPT->getPointeeType()->castAs<FunctionProtoType>();
|
2014-01-17 17:01:00 +08:00
|
|
|
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
|
2013-04-12 02:13:19 +08:00
|
|
|
llvm::FunctionType *FTy =
|
|
|
|
CGM.getTypes().GetFunctionType(
|
|
|
|
CGM.getTypes().arrangeCXXMethodType(RD, FPT));
|
|
|
|
CGBuilderTy &Builder = CGF.Builder;
|
|
|
|
|
2014-01-17 17:01:00 +08:00
|
|
|
MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
|
2013-04-12 02:13:19 +08:00
|
|
|
|
|
|
|
// 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++);
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasNVOffsetField(MPT, Inheritance))
|
2013-04-12 02:13:19 +08:00
|
|
|
NonVirtualBaseAdjustment = Builder.CreateExtractValue(MemPtr, I++);
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance))
|
2013-05-03 09:15:11 +08:00
|
|
|
VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++);
|
2014-02-06 01:27:08 +08:00
|
|
|
if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance))
|
2013-04-12 02:13:19 +08:00
|
|
|
VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VirtualBaseAdjustmentOffset) {
|
2014-02-21 07:22:07 +08:00
|
|
|
This = AdjustVirtualBase(CGF, E, RD, This, VirtualBaseAdjustmentOffset,
|
2013-04-12 02:13:19 +08:00
|
|
|
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);
|
|
|
|
}
|