summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2010-03-03 17:28:16 +0000
committerrdivacky <rdivacky@FreeBSD.org>2010-03-03 17:28:16 +0000
commitdf90325d4c0a65ee64d2dae3ed9b5b34f7418533 (patch)
treee1a885aadfd80632f5bd70d4bd2d37e715e35a79 /lib/CodeGen
parentfd035e6496665b1f1197868e21cb0a4594e8db6e (diff)
downloadFreeBSD-src-df90325d4c0a65ee64d2dae3ed9b5b34f7418533.zip
FreeBSD-src-df90325d4c0a65ee64d2dae3ed9b5b34f7418533.tar.gz
Update clang to 97654.
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGBlocks.cpp144
-rw-r--r--lib/CodeGen/CGBlocks.h8
-rw-r--r--lib/CodeGen/CGBuiltin.cpp75
-rw-r--r--lib/CodeGen/CGCXX.cpp210
-rw-r--r--lib/CodeGen/CGCall.cpp176
-rw-r--r--lib/CodeGen/CGCall.h17
-rw-r--r--lib/CodeGen/CGClass.cpp379
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp34
-rw-r--r--lib/CodeGen/CGDebugInfo.h1
-rw-r--r--lib/CodeGen/CGException.cpp68
-rw-r--r--lib/CodeGen/CGExpr.cpp16
-rw-r--r--lib/CodeGen/CGExprAgg.cpp2
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp25
-rw-r--r--lib/CodeGen/CGObjCMac.cpp23
-rw-r--r--lib/CodeGen/CGVTT.cpp21
-rw-r--r--lib/CodeGen/CGVtable.cpp1549
-rw-r--r--lib/CodeGen/CGVtable.h5
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp119
-rw-r--r--lib/CodeGen/CodeGenFunction.h66
-rw-r--r--lib/CodeGen/CodeGenModule.cpp64
-rw-r--r--lib/CodeGen/CodeGenModule.h27
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp12
-rw-r--r--lib/CodeGen/CodeGenTypes.h19
-rw-r--r--lib/CodeGen/Mangle.cpp78
-rw-r--r--lib/CodeGen/TargetInfo.cpp29
-rw-r--r--lib/CodeGen/TargetInfo.h31
26 files changed, 2276 insertions, 922 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 46b6244..7076067 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -24,7 +24,7 @@ using namespace clang;
using namespace CodeGen;
llvm::Constant *CodeGenFunction::
-BuildDescriptorBlockDecl(bool BlockHasCopyDispose, CharUnits Size,
+BuildDescriptorBlockDecl(const BlockExpr *BE, bool BlockHasCopyDispose, CharUnits Size,
const llvm::StructType* Ty,
std::vector<HelperInfo> *NoteForHelper) {
const llvm::Type *UnsignedLongTy
@@ -43,6 +43,7 @@ BuildDescriptorBlockDecl(bool BlockHasCopyDispose, CharUnits Size,
C = llvm::ConstantInt::get(UnsignedLongTy, Size.getQuantity());
Elts.push_back(C);
+ // optional copy/dispose helpers
if (BlockHasCopyDispose) {
// copy_func_helper_decl
Elts.push_back(BuildCopyHelper(Ty, NoteForHelper));
@@ -51,6 +52,17 @@ BuildDescriptorBlockDecl(bool BlockHasCopyDispose, CharUnits Size,
Elts.push_back(BuildDestroyHelper(Ty, NoteForHelper));
}
+ // Signature. non-optional ObjC-style method descriptor @encode sequence
+ std::string BlockTypeEncoding;
+ CGM.getContext().getObjCEncodingForBlock(BE, BlockTypeEncoding);
+
+ Elts.push_back(llvm::ConstantExpr::getBitCast(
+ CGM.GetAddrOfConstantCString(BlockTypeEncoding), PtrToInt8Ty));
+
+ // Layout.
+ C = llvm::ConstantInt::get(UnsignedLongTy, 0);
+ Elts.push_back(C);
+
C = llvm::ConstantStruct::get(VMContext, Elts, false);
C = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
@@ -110,19 +122,6 @@ static bool CanBlockBeGlobal(const CodeGenFunction::BlockInfo &Info) {
/// invoke function.
static void AllocateAllBlockDeclRefs(const CodeGenFunction::BlockInfo &Info,
CodeGenFunction *CGF) {
- // Always allocate self, as it is often handy in the debugger, even if there
- // is no codegen in the block that uses it. This is also useful to always do
- // this as if we didn't, we'd have to figure out all code that uses a self
- // pointer, including implicit uses.
- if (const ObjCMethodDecl *OMD
- = dyn_cast_or_null<ObjCMethodDecl>(CGF->CurFuncDecl)) {
- ImplicitParamDecl *SelfDecl = OMD->getSelfDecl();
- BlockDeclRefExpr *BDRE = new (CGF->getContext())
- BlockDeclRefExpr(SelfDecl,
- SelfDecl->getType(), SourceLocation(), false);
- CGF->AllocateBlockDecl(BDRE);
- }
-
// FIXME: Also always forward the this pointer in C++ as well.
for (size_t i = 0; i < Info.DeclRefs.size(); ++i)
@@ -148,30 +147,14 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
size_t BlockFields = 5;
- bool hasIntrospection = CGM.getContext().getLangOptions().BlockIntrospection;
-
- if (hasIntrospection) {
- BlockFields++;
- }
std::vector<llvm::Constant*> Elts(BlockFields);
- if (hasIntrospection) {
- std::string BlockTypeEncoding;
- CGM.getContext().getObjCEncodingForBlock(BE, BlockTypeEncoding);
-
- Elts[5] = llvm::ConstantExpr::getBitCast(
- CGM.GetAddrOfConstantCString(BlockTypeEncoding), PtrToInt8Ty);
- }
-
llvm::Constant *C;
llvm::Value *V;
{
// C = BuildBlockStructInitlist();
- unsigned int flags = BLOCK_HAS_DESCRIPTOR;
-
- if (hasIntrospection)
- flags |= BLOCK_HAS_OBJC_TYPE;
+ unsigned int flags = BLOCK_HAS_OBJC_TYPE;
// We run this first so that we set BlockHasCopyDispose from the entire
// block literal.
@@ -212,7 +195,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
if (subBlockDeclRefDecls.size() == 0) {
// __descriptor
- Elts[4] = BuildDescriptorBlockDecl(subBlockHasCopyDispose, subBlockSize,
+ Elts[4] = BuildDescriptorBlockDecl(BE, subBlockHasCopyDispose, subBlockSize,
0, 0);
// Optimize to being a global block.
@@ -234,8 +217,6 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
for (int i=0; i<4; ++i)
Types[i] = Elts[i]->getType();
Types[4] = PtrToInt8Ty;
- if (hasIntrospection)
- Types[5] = PtrToInt8Ty;
for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i) {
const Expr *E = subBlockDeclRefDecls[i];
@@ -258,8 +239,6 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
for (unsigned i=0; i<4; ++i)
Builder.CreateStore(Elts[i], Builder.CreateStructGEP(V, i, "block.tmp"));
- if (hasIntrospection)
- Builder.CreateStore(Elts[5], Builder.CreateStructGEP(V, 5, "block.tmp"));
for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i)
{
@@ -348,7 +327,8 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
NoteForHelper.resize(helpersize);
// __descriptor
- llvm::Value *Descriptor = BuildDescriptorBlockDecl(subBlockHasCopyDispose,
+ llvm::Value *Descriptor = BuildDescriptorBlockDecl(BE,
+ subBlockHasCopyDispose,
subBlockSize, Ty,
&NoteForHelper);
Descriptor = Builder.CreateBitCast(Descriptor, PtrToInt8Ty);
@@ -384,6 +364,16 @@ const llvm::Type *BlockModule::getBlockDescriptorType() {
// struct __block_descriptor {
// unsigned long reserved;
// unsigned long block_size;
+ //
+ // // later, the following will be added
+ //
+ // struct {
+ // void (*copyHelper)();
+ // void (*copyHelper)();
+ // } helpers; // !!! optional
+ //
+ // const char *signature; // the block signature
+ // const char *layout; // reserved
// };
BlockDescriptorType = llvm::StructType::get(UnsignedLongTy->getContext(),
UnsignedLongTy,
@@ -412,20 +402,8 @@ const llvm::Type *BlockModule::getGenericBlockLiteralType() {
// int __reserved;
// void (*__invoke)(void *);
// struct __block_descriptor *__descriptor;
- // // GNU runtime only:
- // const char *types;
// };
- if (CGM.getContext().getLangOptions().BlockIntrospection)
- GenericBlockLiteralType = llvm::StructType::get(IntTy->getContext(),
- PtrToInt8Ty,
- IntTy,
- IntTy,
- PtrToInt8Ty,
- BlockDescPtrTy,
- PtrToInt8Ty,
- NULL);
- else
- GenericBlockLiteralType = llvm::StructType::get(IntTy->getContext(),
+ GenericBlockLiteralType = llvm::StructType::get(IntTy->getContext(),
PtrToInt8Ty,
IntTy,
IntTy,
@@ -439,40 +417,6 @@ const llvm::Type *BlockModule::getGenericBlockLiteralType() {
return GenericBlockLiteralType;
}
-const llvm::Type *BlockModule::getGenericExtendedBlockLiteralType() {
- if (GenericExtendedBlockLiteralType)
- return GenericExtendedBlockLiteralType;
-
- const llvm::Type *BlockDescPtrTy =
- llvm::PointerType::getUnqual(getBlockDescriptorType());
-
- const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
- getTypes().ConvertType(getContext().IntTy));
-
- // struct __block_literal_generic {
- // void *__isa;
- // int __flags;
- // int __reserved;
- // void (*__invoke)(void *);
- // struct __block_descriptor *__descriptor;
- // void *__copy_func_helper_decl;
- // void *__destroy_func_decl;
- // };
- GenericExtendedBlockLiteralType = llvm::StructType::get(IntTy->getContext(),
- PtrToInt8Ty,
- IntTy,
- IntTy,
- PtrToInt8Ty,
- BlockDescPtrTy,
- PtrToInt8Ty,
- PtrToInt8Ty,
- NULL);
-
- getModule().addTypeName("struct.__block_literal_extended_generic",
- GenericExtendedBlockLiteralType);
-
- return GenericExtendedBlockLiteralType;
-}
RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E,
ReturnValueSlot ReturnValue) {
@@ -603,7 +547,7 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
getTypes().ConvertType(getContext().IntTy));
- llvm::Constant *DescriptorFields[2];
+ llvm::Constant *DescriptorFields[4];
// Reserved
DescriptorFields[0] = llvm::Constant::getNullValue(UnsignedLongTy);
@@ -614,9 +558,21 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
CGM.GetTargetTypeStoreSize(getGenericBlockLiteralType());
DescriptorFields[1] =
llvm::ConstantInt::get(UnsignedLongTy,BlockLiteralSize.getQuantity());
+
+ // signature. non-optional ObjC-style method descriptor @encode sequence
+ std::string BlockTypeEncoding;
+ CGM.getContext().getObjCEncodingForBlock(BE, BlockTypeEncoding);
+ DescriptorFields[2] = llvm::ConstantExpr::getBitCast(
+ CGM.GetAddrOfConstantCString(BlockTypeEncoding), PtrToInt8Ty);
+
+ // layout
+ DescriptorFields[3] =
+ llvm::ConstantInt::get(UnsignedLongTy,0);
+
+ // build the structure from the 4 elements
llvm::Constant *DescriptorStruct =
- llvm::ConstantStruct::get(VMContext, &DescriptorFields[0], 2, false);
+ llvm::ConstantStruct::get(VMContext, &DescriptorFields[0], 4, false);
llvm::GlobalVariable *Descriptor =
new llvm::GlobalVariable(getModule(), DescriptorStruct->getType(), true,
@@ -625,8 +581,6 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
int FieldCount = 5;
// Generate the constants for the block literal.
- if (CGM.getContext().getLangOptions().BlockIntrospection)
- FieldCount = 6;
std::vector<llvm::Constant*> LiteralFields(FieldCount);
@@ -649,10 +603,8 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
LiteralFields[0] = getNSConcreteGlobalBlock();
// Flags
- LiteralFields[1] = CGM.getContext().getLangOptions().BlockIntrospection ?
- llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_DESCRIPTOR |
- BLOCK_HAS_OBJC_TYPE) :
- llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_DESCRIPTOR);
+ LiteralFields[1] =
+ llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_OBJC_TYPE);
// Reserved
LiteralFields[2] = llvm::Constant::getNullValue(IntTy);
@@ -663,14 +615,6 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
// Descriptor
LiteralFields[4] = Descriptor;
- // Type encoding
- if (CGM.getContext().getLangOptions().BlockIntrospection) {
- std::string BlockTypeEncoding;
- CGM.getContext().getObjCEncodingForBlock(BE, BlockTypeEncoding);
-
- LiteralFields[5] = CGM.GetAddrOfConstantCString(BlockTypeEncoding);
- }
-
llvm::Constant *BlockLiteralStruct =
llvm::ConstantStruct::get(VMContext, LiteralFields, false);
diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h
index a9f5ae0..39f26f8 100644
--- a/lib/CodeGen/CGBlocks.h
+++ b/lib/CodeGen/CGBlocks.h
@@ -51,12 +51,9 @@ class CodeGenModule;
class BlockBase {
public:
enum {
- BLOCK_NEEDS_FREE = (1 << 24),
BLOCK_HAS_COPY_DISPOSE = (1 << 25),
BLOCK_HAS_CXX_OBJ = (1 << 26),
- BLOCK_IS_GC = (1 << 27),
BLOCK_IS_GLOBAL = (1 << 28),
- BLOCK_HAS_DESCRIPTOR = (1 << 29),
BLOCK_HAS_OBJC_TYPE = (1 << 30)
};
};
@@ -80,7 +77,6 @@ public:
const llvm::Type *getBlockDescriptorType();
const llvm::Type *getGenericBlockLiteralType();
- const llvm::Type *getGenericExtendedBlockLiteralType();
llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, const char *);
@@ -94,7 +90,7 @@ public:
const llvm::Type *BlockDescriptorType;
const llvm::Type *GenericBlockLiteralType;
- const llvm::Type *GenericExtendedBlockLiteralType;
+
struct {
int GlobalUniqueCount;
} Block;
@@ -111,7 +107,7 @@ public:
: Context(C), TheModule(M), TheTargetData(TD), Types(T),
CGM(CodeGen), VMContext(M.getContext()),
NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockDescriptorType(0),
- GenericBlockLiteralType(0), GenericExtendedBlockLiteralType(0),
+ GenericBlockLiteralType(0),
BlockObjectAssign(0), BlockObjectDispose(0) {
Block.GlobalUniqueCount = 0;
PtrToInt8Ty = llvm::Type::getInt8PtrTy(M.getContext());
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index beaf7b8..0f5e90f 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "TargetInfo.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "clang/Basic/TargetInfo.h"
@@ -19,6 +20,7 @@
#include "clang/AST/Decl.h"
#include "clang/Basic/TargetBuiltins.h"
#include "llvm/Intrinsics.h"
+#include "llvm/Target/TargetData.h"
using namespace clang;
using namespace CodeGen;
using namespace llvm;
@@ -57,6 +59,10 @@ static RValue EmitBinaryAtomicPost(CodeGenFunction& CGF,
return RValue::get(CGF.Builder.CreateBinOp(Op, Result, Operand));
}
+static llvm::ConstantInt *getInt32(llvm::LLVMContext &Context, int32_t Value) {
+ return llvm::ConstantInt::get(llvm::Type::getInt32Ty(Context), Value);
+}
+
RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
unsigned BuiltinID, const CallExpr *E) {
// See if we can constant fold this builtin. If so, don't emit it at all.
@@ -341,6 +347,20 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1));
return RValue::get(Address);
}
+ case Builtin::BI__builtin_dwarf_cfa: {
+ // The offset in bytes from the first argument to the CFA.
+ //
+ // Why on earth is this in the frontend? Is there any reason at
+ // all that the backend can't reasonably determine this while
+ // lowering llvm.eh.dwarf.cfa()?
+ //
+ // TODO: If there's a satisfactory reason, add a target hook for
+ // this instead of hard-coding 0, which is correct for most targets.
+ int32_t Offset = 0;
+
+ Value *F = CGM.getIntrinsic(Intrinsic::eh_dwarf_cfa, 0, 0);
+ return RValue::get(Builder.CreateCall(F, getInt32(VMContext, Offset)));
+ }
case Builtin::BI__builtin_return_address: {
Value *Depth = EmitScalarExpr(E->getArg(0));
Depth = Builder.CreateIntCast(Depth,
@@ -358,13 +378,64 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(Builder.CreateCall(F, Depth));
}
case Builtin::BI__builtin_extract_return_addr: {
- // FIXME: There should be a target hook for this
- return RValue::get(EmitScalarExpr(E->getArg(0)));
+ Value *Address = EmitScalarExpr(E->getArg(0));
+ Value *Result = getTargetHooks().decodeReturnAddress(*this, Address);
+ return RValue::get(Result);
+ }
+ case Builtin::BI__builtin_frob_return_addr: {
+ Value *Address = EmitScalarExpr(E->getArg(0));
+ Value *Result = getTargetHooks().encodeReturnAddress(*this, Address);
+ return RValue::get(Result);
+ }
+ case Builtin::BI__builtin_eh_return: {
+ Value *Int = EmitScalarExpr(E->getArg(0));
+ Value *Ptr = EmitScalarExpr(E->getArg(1));
+
+ const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(Int->getType());
+ assert((IntTy->getBitWidth() == 32 || IntTy->getBitWidth() == 64) &&
+ "LLVM's __builtin_eh_return only supports 32- and 64-bit variants");
+ Value *F = CGM.getIntrinsic(IntTy->getBitWidth() == 32
+ ? Intrinsic::eh_return_i32
+ : Intrinsic::eh_return_i64,
+ 0, 0);
+ Builder.CreateCall2(F, Int, Ptr);
+ Value *V = Builder.CreateUnreachable();
+ Builder.ClearInsertionPoint();
+ return RValue::get(V);
}
case Builtin::BI__builtin_unwind_init: {
Value *F = CGM.getIntrinsic(Intrinsic::eh_unwind_init, 0, 0);
return RValue::get(Builder.CreateCall(F));
}
+ case Builtin::BI__builtin_extend_pointer: {
+ // Extends a pointer to the size of an _Unwind_Word, which is
+ // uint64_t on all platforms. Generally this gets poked into a
+ // register and eventually used as an address, so if the
+ // addressing registers are wider than pointers and the platform
+ // doesn't implicitly ignore high-order bits when doing
+ // addressing, we need to make sure we zext / sext based on
+ // the platform's expectations.
+ //
+ // See: http://gcc.gnu.org/ml/gcc-bugs/2002-02/msg00237.html
+
+ LLVMContext &C = CGM.getLLVMContext();
+
+ // Cast the pointer to intptr_t.
+ Value *Ptr = EmitScalarExpr(E->getArg(0));
+ const llvm::IntegerType *IntPtrTy = CGM.getTargetData().getIntPtrType(C);
+ Value *Result = Builder.CreatePtrToInt(Ptr, IntPtrTy, "extend.cast");
+
+ // If that's 64 bits, we're done.
+ if (IntPtrTy->getBitWidth() == 64)
+ return RValue::get(Result);
+
+ // Otherwise, ask the codegen data what to do.
+ const llvm::IntegerType *Int64Ty = llvm::IntegerType::get(C, 64);
+ if (getTargetHooks().extendPointerWithSExt())
+ return RValue::get(Builder.CreateSExt(Result, Int64Ty, "extend.sext"));
+ else
+ return RValue::get(Builder.CreateZExt(Result, Int64Ty, "extend.zext"));
+ }
#if 0
// FIXME: Finish/enable when LLVM backend support stabilizes
case Builtin::BI__builtin_setjmp: {
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 28c4c6b..4889fc0 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -22,33 +22,182 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/CodeGen/CodeGenOptions.h"
#include "llvm/ADT/StringExtras.h"
using namespace clang;
using namespace CodeGen;
+/// Determines whether the given function has a trivial body that does
+/// not require any specific codegen.
+static bool HasTrivialBody(const FunctionDecl *FD) {
+ Stmt *S = FD->getBody();
+ if (!S)
+ return true;
+ if (isa<CompoundStmt>(S) && cast<CompoundStmt>(S)->body_empty())
+ return true;
+ return false;
+}
+
+/// Try to emit a base destructor as an alias to its primary
+/// base-class destructor.
+bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
+ if (!getCodeGenOpts().CXXCtorDtorAliases)
+ return true;
+
+ // If the destructor doesn't have a trivial body, we have to emit it
+ // separately.
+ if (!HasTrivialBody(D))
+ return true;
+
+ const CXXRecordDecl *Class = D->getParent();
+
+ // If we need to manipulate a VTT parameter, give up.
+ if (Class->getNumVBases()) {
+ // Extra Credit: passing extra parameters is perfectly safe
+ // in many calling conventions, so only bail out if the ctor's
+ // calling convention is nonstandard.
+ return true;
+ }
+
+ // If any fields have a non-trivial destructor, we have to emit it
+ // separately.
+ for (CXXRecordDecl::field_iterator I = Class->field_begin(),
+ E = Class->field_end(); I != E; ++I)
+ if (const RecordType *RT = (*I)->getType()->getAs<RecordType>())
+ if (!cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor())
+ return true;
+
+ // Try to find a unique base class with a non-trivial destructor.
+ const CXXRecordDecl *UniqueBase = 0;
+ for (CXXRecordDecl::base_class_const_iterator I = Class->bases_begin(),
+ E = Class->bases_end(); I != E; ++I) {
+
+ // We're in the base destructor, so skip virtual bases.
+ if (I->isVirtual()) continue;
+
+ // Skip base classes with trivial destructors.
+ const CXXRecordDecl *Base
+ = cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+ if (Base->hasTrivialDestructor()) continue;
+
+ // If we've already found a base class with a non-trivial
+ // destructor, give up.
+ if (UniqueBase) return true;
+ UniqueBase = Base;
+ }
+
+ // If we didn't find any bases with a non-trivial destructor, then
+ // the base destructor is actually effectively trivial, which can
+ // happen if it was needlessly user-defined or if there are virtual
+ // bases with non-trivial destructors.
+ if (!UniqueBase)
+ return true;
+
+ /// If we don't have a definition for the destructor yet, don't
+ /// emit. We can't emit aliases to declarations; that's just not
+ /// how aliases work.
+ const CXXDestructorDecl *BaseD = UniqueBase->getDestructor(getContext());
+ if (!BaseD->isImplicit() && !BaseD->getBody())
+ return true;
+
+ // If the base is at a non-zero offset, give up.
+ const ASTRecordLayout &ClassLayout = Context.getASTRecordLayout(Class);
+ if (ClassLayout.getBaseClassOffset(UniqueBase) != 0)
+ return true;
+
+ return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base),
+ GlobalDecl(BaseD, Dtor_Base));
+}
+/// Try to emit a definition as a global alias for another definition.
+bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
+ GlobalDecl TargetDecl) {
+ if (!getCodeGenOpts().CXXCtorDtorAliases)
+ return true;
+
+ // The alias will use the linkage of the referrent. If we can't
+ // support aliases with that linkage, fail.
+ llvm::GlobalValue::LinkageTypes Linkage
+ = getFunctionLinkage(cast<FunctionDecl>(AliasDecl.getDecl()));
+
+ switch (Linkage) {
+ // We can definitely emit aliases to definitions with external linkage.
+ case llvm::GlobalValue::ExternalLinkage:
+ case llvm::GlobalValue::ExternalWeakLinkage:
+ break;
+
+ // Same with local linkage.
+ case llvm::GlobalValue::InternalLinkage:
+ case llvm::GlobalValue::PrivateLinkage:
+ case llvm::GlobalValue::LinkerPrivateLinkage:
+ break;
+
+ // We should try to support linkonce linkages.
+ case llvm::GlobalValue::LinkOnceAnyLinkage:
+ case llvm::GlobalValue::LinkOnceODRLinkage:
+ return true;
+
+ // Other linkages will probably never be supported.
+ default:
+ return true;
+ }
+
+ // Derive the type for the alias.
+ const llvm::PointerType *AliasType
+ = getTypes().GetFunctionType(AliasDecl)->getPointerTo();
+
+ // Find the referrent. Some aliases might require a bitcast, in
+ // which case the caller is responsible for ensuring the soundness
+ // of these semantics.
+ llvm::GlobalValue *Ref = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl));
+ llvm::Constant *Aliasee = Ref;
+ if (Ref->getType() != AliasType)
+ Aliasee = llvm::ConstantExpr::getBitCast(Ref, AliasType);
+
+ // Create the alias with no name.
+ llvm::GlobalAlias *Alias =
+ new llvm::GlobalAlias(AliasType, Linkage, "", Aliasee, &getModule());
+
+ // Switch any previous uses to the alias.
+ const char *MangledName = getMangledName(AliasDecl);
+ llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName];
+ if (Entry) {
+ assert(Entry->isDeclaration() && "definition already exists for alias");
+ assert(Entry->getType() == AliasType &&
+ "declaration exists with different type");
+ Entry->replaceAllUsesWith(Alias);
+ Entry->eraseFromParent();
+ }
+ Entry = Alias;
-llvm::Value *CodeGenFunction::LoadCXXThis() {
- assert(isa<CXXMethodDecl>(CurFuncDecl) &&
- "Must be in a C++ member function decl to load 'this'");
- assert(cast<CXXMethodDecl>(CurFuncDecl)->isInstance() &&
- "Must be in a C++ member function decl to load 'this'");
+ // Finally, set up the alias with its proper name and attributes.
+ Alias->setName(MangledName);
+ SetCommonAttributes(AliasDecl.getDecl(), Alias);
- // FIXME: What if we're inside a block?
- // ans: See how CodeGenFunction::LoadObjCSelf() uses
- // CodeGenFunction::BlockForwardSelf() for how to do this.
- return Builder.CreateLoad(LocalDeclMap[CXXThisDecl], "this");
+ return false;
}
void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) {
+ // The constructor used for constructing this as a complete class;
+ // constucts the virtual bases, then calls the base constructor.
EmitGlobal(GlobalDecl(D, Ctor_Complete));
+
+ // The constructor used for constructing this as a base class;
+ // ignores virtual bases.
EmitGlobal(GlobalDecl(D, Ctor_Base));
}
void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D,
CXXCtorType Type) {
+ // The complete constructor is equivalent to the base constructor
+ // for classes with no virtual bases. Try to emit it as an alias.
+ if (Type == Ctor_Complete &&
+ !D->getParent()->getNumVBases() &&
+ !TryEmitDefinitionAsAlias(GlobalDecl(D, Ctor_Complete),
+ GlobalDecl(D, Ctor_Base)))
+ return;
- llvm::Function *Fn = GetAddrOfCXXConstructor(D, Type);
+ llvm::Function *Fn = cast<llvm::Function>(GetAddrOfCXXConstructor(D, Type));
CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn);
@@ -56,15 +205,17 @@ void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D,
SetLLVMFunctionAttributesForDefinition(D, Fn);
}
-llvm::Function *
+llvm::GlobalValue *
CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D,
CXXCtorType Type) {
+ const char *Name = getMangledCXXCtorName(D, Type);
+ if (llvm::GlobalValue *V = GlobalDeclMap[Name])
+ return V;
+
const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>();
const llvm::FunctionType *FTy =
getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type),
FPT->isVariadic());
-
- const char *Name = getMangledCXXCtorName(D, Type);
return cast<llvm::Function>(
GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type)));
}
@@ -79,15 +230,39 @@ const char *CodeGenModule::getMangledCXXCtorName(const CXXConstructorDecl *D,
}
void CodeGenModule::EmitCXXDestructors(const CXXDestructorDecl *D) {
+ // The destructor in a virtual table is always a 'deleting'
+ // destructor, which calls the complete destructor and then uses the
+ // appropriate operator delete.
if (D->isVirtual())
EmitGlobal(GlobalDecl(D, Dtor_Deleting));
+
+ // The destructor used for destructing this as a most-derived class;
+ // call the base destructor and then destructs any virtual bases.
EmitGlobal(GlobalDecl(D, Dtor_Complete));
+
+ // The destructor used for destructing this as a base class; ignores
+ // virtual bases.
EmitGlobal(GlobalDecl(D, Dtor_Base));
}
void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D,
CXXDtorType Type) {
- llvm::Function *Fn = GetAddrOfCXXDestructor(D, Type);
+ // The complete destructor is equivalent to the base destructor for
+ // classes with no virtual bases, so try to emit it as an alias.
+ if (Type == Dtor_Complete &&
+ !D->getParent()->getNumVBases() &&
+ !TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Complete),
+ GlobalDecl(D, Dtor_Base)))
+ return;
+
+ // The base destructor is equivalent to the base destructor of its
+ // base class if there is exactly one non-virtual base class with a
+ // non-trivial destructor, there are no fields with a non-trivial
+ // destructor, and the body of the destructor is trivial.
+ if (Type == Dtor_Base && !TryEmitBaseDestructorAsAlias(D))
+ return;
+
+ llvm::Function *Fn = cast<llvm::Function>(GetAddrOfCXXDestructor(D, Type));
CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn);
@@ -95,13 +270,16 @@ void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D,
SetLLVMFunctionAttributesForDefinition(D, Fn);
}
-llvm::Function *
+llvm::GlobalValue *
CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
CXXDtorType Type) {
+ const char *Name = getMangledCXXDtorName(D, Type);
+ if (llvm::GlobalValue *V = GlobalDeclMap[Name])
+ return V;
+
const llvm::FunctionType *FTy =
getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type), false);
- const char *Name = getMangledCXXDtorName(D, Type);
return cast<llvm::Function>(
GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type)));
}
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index b064c12..072b1f6 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -41,21 +41,54 @@ static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) {
}
}
-const
-CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionNoProtoType *FTNP) {
- return getFunctionInfo(FTNP->getResultType(),
- llvm::SmallVector<QualType, 16>(),
- FTNP->getCallConv(), FTNP->getNoReturnAttr());
+/// Derives the 'this' type for codegen purposes, i.e. ignoring method
+/// qualification.
+/// FIXME: address space qualification?
+static CanQualType GetThisType(ASTContext &Context, const CXXRecordDecl *RD) {
+ QualType RecTy = Context.getTagDeclType(RD)->getCanonicalTypeInternal();
+ return Context.getPointerType(CanQualType::CreateUnsafe(RecTy));
}
-const
-CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionProtoType *FTP) {
- llvm::SmallVector<QualType, 16> ArgTys;
+/// Returns the canonical formal type of the given C++ method.
+static CanQual<FunctionProtoType> GetFormalType(const CXXMethodDecl *MD) {
+ return MD->getType()->getCanonicalTypeUnqualified()
+ .getAs<FunctionProtoType>();
+}
+
+/// Returns the "extra-canonicalized" return type, which discards
+/// qualifiers on the return type. Codegen doesn't care about them,
+/// and it makes ABI code a little easier to be able to assume that
+/// all parameter and return types are top-level unqualified.
+static CanQualType GetReturnType(QualType RetTy) {
+ return RetTy->getCanonicalTypeUnqualified().getUnqualifiedType();
+}
+
+const CGFunctionInfo &
+CodeGenTypes::getFunctionInfo(CanQual<FunctionNoProtoType> FTNP) {
+ return getFunctionInfo(FTNP->getResultType().getUnqualifiedType(),
+ llvm::SmallVector<CanQualType, 16>(),
+ FTNP->getCallConv(),
+ FTNP->getNoReturnAttr());
+}
+
+/// \param Args - contains any initial parameters besides those
+/// in the formal type
+static const CGFunctionInfo &getFunctionInfo(CodeGenTypes &CGT,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys,
+ CanQual<FunctionProtoType> FTP) {
// FIXME: Kill copy.
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
ArgTys.push_back(FTP->getArgType(i));
- return getFunctionInfo(FTP->getResultType(), ArgTys,
- FTP->getCallConv(), FTP->getNoReturnAttr());
+ CanQualType ResTy = FTP->getResultType().getUnqualifiedType();
+ return CGT.getFunctionInfo(ResTy, ArgTys,
+ FTP->getCallConv(),
+ FTP->getNoReturnAttr());
+}
+
+const CGFunctionInfo &
+CodeGenTypes::getFunctionInfo(CanQual<FunctionProtoType> FTP) {
+ llvm::SmallVector<CanQualType, 16> ArgTys;
+ return ::getFunctionInfo(*this, ArgTys, FTP);
}
static CallingConv getCallingConventionForDecl(const Decl *D) {
@@ -71,67 +104,51 @@ static CallingConv getCallingConventionForDecl(const Decl *D) {
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXRecordDecl *RD,
const FunctionProtoType *FTP) {
- llvm::SmallVector<QualType, 16> ArgTys;
-
+ llvm::SmallVector<CanQualType, 16> ArgTys;
+
// Add the 'this' pointer.
- ArgTys.push_back(Context.getPointerType(Context.getTagDeclType(RD)));
-
- for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
- ArgTys.push_back(FTP->getArgType(i));
-
- // FIXME: Set calling convention correctly, it needs to be associated with the
- // type somehow.
- return getFunctionInfo(FTP->getResultType(), ArgTys,
- FTP->getCallConv(), FTP->getNoReturnAttr());
+ ArgTys.push_back(GetThisType(Context, RD));
+
+ return ::getFunctionInfo(*this, ArgTys,
+ FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>());
}
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXMethodDecl *MD) {
- llvm::SmallVector<QualType, 16> ArgTys;
+ llvm::SmallVector<CanQualType, 16> ArgTys;
+
// Add the 'this' pointer unless this is a static method.
if (MD->isInstance())
- ArgTys.push_back(MD->getThisType(Context));
+ ArgTys.push_back(GetThisType(Context, MD->getParent()));
- const FunctionProtoType *FTP = MD->getType()->getAs<FunctionProtoType>();
- for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
- ArgTys.push_back(FTP->getArgType(i));
- return getFunctionInfo(FTP->getResultType(), ArgTys, FTP->getCallConv(),
- FTP->getNoReturnAttr());
+ return ::getFunctionInfo(*this, ArgTys, GetFormalType(MD));
}
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXConstructorDecl *D,
CXXCtorType Type) {
- llvm::SmallVector<QualType, 16> ArgTys;
+ llvm::SmallVector<CanQualType, 16> ArgTys;
// Add the 'this' pointer.
- ArgTys.push_back(D->getThisType(Context));
+ ArgTys.push_back(GetThisType(Context, D->getParent()));
// Check if we need to add a VTT parameter (which has type void **).
if (Type == Ctor_Base && D->getParent()->getNumVBases() != 0)
ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
-
- const FunctionProtoType *FTP = D->getType()->getAs<FunctionProtoType>();
- for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
- ArgTys.push_back(FTP->getArgType(i));
- return getFunctionInfo(FTP->getResultType(), ArgTys, FTP->getCallConv(),
- FTP->getNoReturnAttr());
+
+ return ::getFunctionInfo(*this, ArgTys, GetFormalType(D));
}
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXDestructorDecl *D,
CXXDtorType Type) {
- llvm::SmallVector<QualType, 16> ArgTys;
+ llvm::SmallVector<CanQualType, 16> ArgTys;
// Add the 'this' pointer.
- ArgTys.push_back(D->getThisType(Context));
+ ArgTys.push_back(GetThisType(Context, D->getParent()));
// Check if we need to add a VTT parameter (which has type void **).
if (Type == Dtor_Base && D->getParent()->getNumVBases() != 0)
ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
-
- const FunctionProtoType *FTP = D->getType()->getAs<FunctionProtoType>();
- for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
- ArgTys.push_back(FTP->getArgType(i));
- return getFunctionInfo(FTP->getResultType(), ArgTys, FTP->getCallConv(),
- FTP->getNoReturnAttr());
+
+ return ::getFunctionInfo(*this, ArgTys, GetFormalType(D));
}
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionDecl *FD) {
@@ -139,30 +156,25 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionDecl *FD) {
if (MD->isInstance())
return getFunctionInfo(MD);
- const FunctionType *FTy = FD->getType()->getAs<FunctionType>();
- if (const FunctionNoProtoType *FNTP = dyn_cast<FunctionNoProtoType>(FTy))
- return getFunctionInfo(FNTP->getResultType(),
- llvm::SmallVector<QualType, 16>(),
- FNTP->getCallConv(), FNTP->getNoReturnAttr());
-
- const FunctionProtoType *FPT = cast<FunctionProtoType>(FTy);
- llvm::SmallVector<QualType, 16> ArgTys;
- // FIXME: Kill copy.
- for (unsigned i = 0, e = FPT->getNumArgs(); i != e; ++i)
- ArgTys.push_back(FPT->getArgType(i));
- return getFunctionInfo(FPT->getResultType(), ArgTys,
- FPT->getCallConv(), FPT->getNoReturnAttr());
+ CanQualType FTy = FD->getType()->getCanonicalTypeUnqualified();
+ assert(isa<FunctionType>(FTy));
+ if (isa<FunctionNoProtoType>(FTy))
+ return getFunctionInfo(FTy.getAs<FunctionNoProtoType>());
+ assert(isa<FunctionProtoType>(FTy));
+ return getFunctionInfo(FTy.getAs<FunctionProtoType>());
}
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const ObjCMethodDecl *MD) {
- llvm::SmallVector<QualType, 16> ArgTys;
- ArgTys.push_back(MD->getSelfDecl()->getType());
- ArgTys.push_back(Context.getObjCSelType());
+ llvm::SmallVector<CanQualType, 16> ArgTys;
+ ArgTys.push_back(Context.getCanonicalParamType(MD->getSelfDecl()->getType()));
+ ArgTys.push_back(Context.getCanonicalParamType(Context.getObjCSelType()));
// FIXME: Kill copy?
for (ObjCMethodDecl::param_iterator i = MD->param_begin(),
- e = MD->param_end(); i != e; ++i)
- ArgTys.push_back((*i)->getType());
- return getFunctionInfo(MD->getResultType(), ArgTys,
+ e = MD->param_end(); i != e; ++i) {
+ ArgTys.push_back(Context.getCanonicalParamType((*i)->getType()));
+ }
+ return getFunctionInfo(GetReturnType(MD->getResultType()),
+ ArgTys,
getCallingConventionForDecl(MD),
/*NoReturn*/ false);
}
@@ -185,11 +197,11 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy,
CallingConv CC,
bool NoReturn) {
// FIXME: Kill copy.
- llvm::SmallVector<QualType, 16> ArgTys;
+ llvm::SmallVector<CanQualType, 16> ArgTys;
for (CallArgList::const_iterator i = Args.begin(), e = Args.end();
i != e; ++i)
- ArgTys.push_back(i->second);
- return getFunctionInfo(ResTy, ArgTys, CC, NoReturn);
+ ArgTys.push_back(Context.getCanonicalParamType(i->second));
+ return getFunctionInfo(GetReturnType(ResTy), ArgTys, CC, NoReturn);
}
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy,
@@ -197,17 +209,23 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy,
CallingConv CC,
bool NoReturn) {
// FIXME: Kill copy.
- llvm::SmallVector<QualType, 16> ArgTys;
+ llvm::SmallVector<CanQualType, 16> ArgTys;
for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end();
i != e; ++i)
- ArgTys.push_back(i->second);
- return getFunctionInfo(ResTy, ArgTys, CC, NoReturn);
+ ArgTys.push_back(Context.getCanonicalParamType(i->second));
+ return getFunctionInfo(GetReturnType(ResTy), ArgTys, CC, NoReturn);
}
-const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy,
- const llvm::SmallVector<QualType, 16> &ArgTys,
+const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy,
+ const llvm::SmallVectorImpl<CanQualType> &ArgTys,
CallingConv CallConv,
bool NoReturn) {
+#ifndef NDEBUG
+ for (llvm::SmallVectorImpl<CanQualType>::const_iterator
+ I = ArgTys.begin(), E = ArgTys.end(); I != E; ++I)
+ assert(I->isCanonicalAsParam());
+#endif
+
unsigned CC = ClangCallConvToLLVMCallConv(CallConv);
// Lookup or create unique function info.
@@ -232,8 +250,8 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy,
CGFunctionInfo::CGFunctionInfo(unsigned _CallingConvention,
bool _NoReturn,
- QualType ResTy,
- const llvm::SmallVector<QualType, 16> &ArgTys)
+ CanQualType ResTy,
+ const llvm::SmallVectorImpl<CanQualType> &ArgTys)
: CallingConvention(_CallingConvention),
EffectiveCallingConvention(_CallingConvention),
NoReturn(_NoReturn)
@@ -416,6 +434,18 @@ bool CodeGenModule::ReturnTypeUsesSret(const CGFunctionInfo &FI) {
return FI.getReturnInfo().isIndirect();
}
+const llvm::FunctionType *CodeGenTypes::GetFunctionType(GlobalDecl GD) {
+ const CGFunctionInfo &FI = getFunctionInfo(GD);
+
+ // For definition purposes, don't consider a K&R function variadic.
+ bool Variadic = false;
+ if (const FunctionProtoType *FPT =
+ cast<FunctionDecl>(GD.getDecl())->getType()->getAs<FunctionProtoType>())
+ Variadic = FPT->isVariadic();
+
+ return GetFunctionType(FI, Variadic);
+}
+
const llvm::FunctionType *
CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic) {
std::vector<const llvm::Type*> ArgTys;
diff --git a/lib/CodeGen/CGCall.h b/lib/CodeGen/CGCall.h
index 9601e9a..3d81165 100644
--- a/lib/CodeGen/CGCall.h
+++ b/lib/CodeGen/CGCall.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Value.h"
#include "clang/AST/Type.h"
+#include "clang/AST/CanonicalType.h"
#include "CGValue.h"
@@ -57,7 +58,7 @@ namespace CodeGen {
/// function definition.
class CGFunctionInfo : public llvm::FoldingSetNode {
struct ArgInfo {
- QualType type;
+ CanQualType type;
ABIArgInfo info;
};
@@ -81,8 +82,8 @@ namespace CodeGen {
CGFunctionInfo(unsigned CallingConvention,
bool NoReturn,
- QualType ResTy,
- const llvm::SmallVector<QualType, 16> &ArgTys);
+ CanQualType ResTy,
+ const llvm::SmallVectorImpl<CanQualType> &ArgTys);
~CGFunctionInfo() { delete[] Args; }
const_arg_iterator arg_begin() const { return Args + 1; }
@@ -107,7 +108,7 @@ namespace CodeGen {
EffectiveCallingConvention = Value;
}
- QualType getReturnType() const { return Args[0].type; }
+ CanQualType getReturnType() const { return Args[0].type; }
ABIArgInfo &getReturnInfo() { return Args[0].info; }
const ABIArgInfo &getReturnInfo() const { return Args[0].info; }
@@ -123,14 +124,16 @@ namespace CodeGen {
static void Profile(llvm::FoldingSetNodeID &ID,
unsigned CallingConvention,
bool NoReturn,
- QualType ResTy,
+ CanQualType ResTy,
Iterator begin,
Iterator end) {
ID.AddInteger(CallingConvention);
ID.AddBoolean(NoReturn);
ResTy.Profile(ID);
- for (; begin != end; ++begin)
- begin->Profile(ID);
+ for (; begin != end; ++begin) {
+ CanQualType T = *begin; // force iterator to be over canonical types
+ T.Profile(ID);
+ }
}
};
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index fa5a47f..99c6dfd 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -14,6 +14,7 @@
#include "CodeGenFunction.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/RecordLayout.h"
+#include "clang/AST/StmtCXX.h"
using namespace clang;
using namespace CodeGen;
@@ -477,12 +478,21 @@ static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD) {
const CXXRecordDecl *RD = cast<CXXMethodDecl>(CGF.CurFuncDecl)->getParent();
const CXXRecordDecl *Base = cast<CXXMethodDecl>(GD.getDecl())->getParent();
-
+
llvm::Value *VTT;
- uint64_t SubVTTIndex =
- CGF.CGM.getVtableInfo().getSubVTTIndex(RD, Base);
- assert(SubVTTIndex != 0 && "Sub-VTT index must be greater than zero!");
+ uint64_t SubVTTIndex;
+
+ // If the record matches the base, this is the complete ctor/dtor
+ // variant calling the base variant in a class with virtual bases.
+ if (RD == Base) {
+ assert(!CGVtableInfo::needsVTTParameter(CGF.CurGD) &&
+ "doing no-op VTT offset in base dtor/ctor?");
+ SubVTTIndex = 0;
+ } else {
+ SubVTTIndex = CGF.CGM.getVtableInfo().getSubVTTIndex(RD, Base);
+ assert(SubVTTIndex != 0 && "Sub-VTT index must be greater than zero!");
+ }
if (CGVtableInfo::needsVTTParameter(CGF.CurGD)) {
// A VTT parameter was passed to the constructor, use it.
@@ -590,19 +600,6 @@ void CodeGenFunction::EmitClassCopyAssignment(
Callee, ReturnValueSlot(), CallArgs, MD);
}
-/// SynthesizeDefaultConstructor - synthesize a default constructor
-void
-CodeGenFunction::SynthesizeDefaultConstructor(const CXXConstructorDecl *Ctor,
- CXXCtorType Type,
- llvm::Function *Fn,
- const FunctionArgList &Args) {
- assert(!Ctor->isTrivial() && "shouldn't need to generate trivial ctor");
- StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args,
- SourceLocation());
- EmitCtorPrologue(Ctor, Type);
- FinishFunction();
-}
-
/// SynthesizeCXXCopyConstructor - This routine implicitly defines body of a
/// copy constructor, in accordance with section 12.8 (p7 and p8) of C++03
/// The implicitly-defined copy constructor for class X performs a memberwise
@@ -619,16 +616,12 @@ CodeGenFunction::SynthesizeDefaultConstructor(const CXXConstructorDecl *Ctor,
/// implicitly-defined copy constructor
void
-CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor,
- CXXCtorType Type,
- llvm::Function *Fn,
- const FunctionArgList &Args) {
+CodeGenFunction::SynthesizeCXXCopyConstructor(const FunctionArgList &Args) {
+ const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(CurGD.getDecl());
const CXXRecordDecl *ClassDecl = Ctor->getParent();
assert(!ClassDecl->hasUserDeclaredCopyConstructor() &&
"SynthesizeCXXCopyConstructor - copy constructor has definition already");
assert(!Ctor->isTrivial() && "shouldn't need to generate trivial ctor");
- StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args,
- SourceLocation());
FunctionArgList::const_iterator i = Args.begin();
const VarDecl *ThisArg = i->first;
@@ -698,7 +691,6 @@ CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor,
}
InitializeVtablePtrs(ClassDecl);
- FinishFunction();
}
/// SynthesizeCXXCopyAssignment - Implicitly define copy assignment operator.
@@ -721,14 +713,11 @@ CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor,
///
/// if the subobject is of scalar type, the built-in assignment operator is
/// used.
-void CodeGenFunction::SynthesizeCXXCopyAssignment(const CXXMethodDecl *CD,
- llvm::Function *Fn,
- const FunctionArgList &Args) {
-
+void CodeGenFunction::SynthesizeCXXCopyAssignment(const FunctionArgList &Args) {
+ const CXXMethodDecl *CD = cast<CXXMethodDecl>(CurGD.getDecl());
const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext());
assert(!ClassDecl->hasUserDeclaredCopyAssignment() &&
"SynthesizeCXXCopyAssignment - copy assignment has user declaration");
- StartFunction(CD, CD->getResultType(), Fn, Args, SourceLocation());
FunctionArgList::const_iterator i = Args.begin();
const VarDecl *ThisArg = i->first;
@@ -796,8 +785,6 @@ void CodeGenFunction::SynthesizeCXXCopyAssignment(const CXXMethodDecl *CD,
// return *this;
Builder.CreateStore(LoadOfThis, ReturnValue);
-
- FinishFunction();
}
static void EmitBaseInitializer(CodeGenFunction &CGF,
@@ -904,6 +891,101 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
}
}
+/// Checks whether the given constructor is a valid subject for the
+/// complete-to-base constructor delegation optimization, i.e.
+/// emitting the complete constructor as a simple call to the base
+/// constructor.
+static bool IsConstructorDelegationValid(const CXXConstructorDecl *Ctor) {
+
+ // Currently we disable the optimization for classes with virtual
+ // bases because (1) the addresses of parameter variables need to be
+ // consistent across all initializers but (2) the delegate function
+ // call necessarily creates a second copy of the parameter variable.
+ //
+ // The limiting example (purely theoretical AFAIK):
+ // struct A { A(int &c) { c++; } };
+ // struct B : virtual A {
+ // B(int count) : A(count) { printf("%d\n", count); }
+ // };
+ // ...although even this example could in principle be emitted as a
+ // delegation since the address of the parameter doesn't escape.
+ if (Ctor->getParent()->getNumVBases()) {
+ // TODO: white-list trivial vbase initializers. This case wouldn't
+ // be subject to the restrictions below.
+
+ // TODO: white-list cases where:
+ // - there are no non-reference parameters to the constructor
+ // - the initializers don't access any non-reference parameters
+ // - the initializers don't take the address of non-reference
+ // parameters
+ // - etc.
+ // If we ever add any of the above cases, remember that:
+ // - function-try-blocks will always blacklist this optimization
+ // - we need to perform the constructor prologue and cleanup in
+ // EmitConstructorBody.
+
+ return false;
+ }
+
+ // We also disable the optimization for variadic functions because
+ // it's impossible to "re-pass" varargs.
+ if (Ctor->getType()->getAs<FunctionProtoType>()->isVariadic())
+ return false;
+
+ return true;
+}
+
+/// EmitConstructorBody - Emits the body of the current constructor.
+void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {
+ const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(CurGD.getDecl());
+ CXXCtorType CtorType = CurGD.getCtorType();
+
+ // Before we go any further, try the complete->base constructor
+ // delegation optimization.
+ if (CtorType == Ctor_Complete && IsConstructorDelegationValid(Ctor)) {
+ EmitDelegateCXXConstructorCall(Ctor, Ctor_Base, Args);
+ return;
+ }
+
+ Stmt *Body = Ctor->getBody();
+
+ // Enter the function-try-block before the constructor prologue if
+ // applicable.
+ CXXTryStmtInfo TryInfo;
+ bool IsTryBody = (Body && isa<CXXTryStmt>(Body));
+
+ if (IsTryBody)
+ TryInfo = EnterCXXTryStmt(*cast<CXXTryStmt>(Body));
+
+ unsigned CleanupStackSize = CleanupEntries.size();
+
+ // Emit the constructor prologue, i.e. the base and member
+ // initializers.
+ EmitCtorPrologue(Ctor, CtorType);
+
+ // Emit the body of the statement.
+ if (IsTryBody)
+ EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock());
+ else if (Body)
+ EmitStmt(Body);
+ else {
+ assert(Ctor->isImplicit() && "bodyless ctor not implicit");
+ if (!Ctor->isDefaultConstructor()) {
+ assert(Ctor->isCopyConstructor());
+ SynthesizeCXXCopyConstructor(Args);
+ }
+ }
+
+ // Emit any cleanup blocks associated with the member or base
+ // initializers, which includes (along the exceptional path) the
+ // destructors for those members and bases that were fully
+ // constructed.
+ EmitCleanupBlocks(CleanupStackSize);
+
+ if (IsTryBody)
+ ExitCXXTryStmt(*cast<CXXTryStmt>(Body), TryInfo);
+}
+
/// EmitCtorPrologue - This routine generates necessary code to initialize
/// base classes and non-static data members belonging to this constructor.
void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
@@ -938,10 +1020,87 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
}
}
+/// EmitDestructorBody - Emits the body of the current destructor.
+void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
+ const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CurGD.getDecl());
+ CXXDtorType DtorType = CurGD.getDtorType();
+
+ Stmt *Body = Dtor->getBody();
+
+ // If the body is a function-try-block, enter the try before
+ // anything else --- unless we're in a deleting destructor, in which
+ // case we're just going to call the complete destructor and then
+ // call operator delete() on the way out.
+ CXXTryStmtInfo TryInfo;
+ bool isTryBody = (DtorType != Dtor_Deleting &&
+ Body && isa<CXXTryStmt>(Body));
+ if (isTryBody)
+ TryInfo = EnterCXXTryStmt(*cast<CXXTryStmt>(Body));
+
+ llvm::BasicBlock *DtorEpilogue = createBasicBlock("dtor.epilogue");
+ PushCleanupBlock(DtorEpilogue);
+
+ bool SkipBody = false; // should get jump-threaded
+
+ // If this is the deleting variant, just invoke the complete
+ // variant, then call the appropriate operator delete() on the way
+ // out.
+ if (DtorType == Dtor_Deleting) {
+ EmitCXXDestructorCall(Dtor, Dtor_Complete, LoadCXXThis());
+ SkipBody = true;
+
+ // If this is the complete variant, just invoke the base variant;
+ // the epilogue will destruct the virtual bases. But we can't do
+ // this optimization if the body is a function-try-block, because
+ // we'd introduce *two* handler blocks.
+ } else if (!isTryBody && DtorType == Dtor_Complete) {
+ EmitCXXDestructorCall(Dtor, Dtor_Base, LoadCXXThis());
+ SkipBody = true;
+
+ // Otherwise, we're in the base variant, so we need to ensure the
+ // vtable ptrs are right before emitting the body.
+ } else {
+ InitializeVtablePtrs(Dtor->getParent());
+ }
+
+ // Emit the body of the statement.
+ if (SkipBody)
+ (void) 0;
+ else if (isTryBody)
+ EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock());
+ else if (Body)
+ EmitStmt(Body);
+ else {
+ assert(Dtor->isImplicit() && "bodyless dtor not implicit");
+ // nothing to do besides what's in the epilogue
+ }
+
+ // Jump to the cleanup block.
+ CleanupBlockInfo Info = PopCleanupBlock();
+ assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!");
+ EmitBlock(DtorEpilogue);
+
+ // Emit the destructor epilogue now. If this is a complete
+ // destructor with a function-try-block, perform the base epilogue
+ // as well.
+ if (isTryBody && DtorType == Dtor_Complete)
+ EmitDtorEpilogue(Dtor, Dtor_Base);
+ EmitDtorEpilogue(Dtor, DtorType);
+
+ // Link up the cleanup information.
+ if (Info.SwitchBlock)
+ EmitBlock(Info.SwitchBlock);
+ if (Info.EndBlock)
+ EmitBlock(Info.EndBlock);
+
+ // Exit the try if applicable.
+ if (isTryBody)
+ ExitCXXTryStmt(*cast<CXXTryStmt>(Body), TryInfo);
+}
+
/// EmitDtorEpilogue - Emit all code that comes at the end of class's
/// destructor. This is to call destructors on members and base classes
/// in reverse order of their construction.
-/// FIXME: This needs to take a CXXDtorType.
void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD,
CXXDtorType DtorType) {
assert(!DD->isTrivial() &&
@@ -949,6 +1108,44 @@ void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD,
const CXXRecordDecl *ClassDecl = DD->getParent();
+ // In a deleting destructor, we've already called the complete
+ // destructor as a subroutine, so we just have to delete the
+ // appropriate value.
+ if (DtorType == Dtor_Deleting) {
+ assert(DD->getOperatorDelete() &&
+ "operator delete missing - EmitDtorEpilogue");
+ EmitDeleteCall(DD->getOperatorDelete(), LoadCXXThis(),
+ getContext().getTagDeclType(ClassDecl));
+ return;
+ }
+
+ // For complete destructors, we've already called the base
+ // destructor (in GenerateBody), so we just need to destruct all the
+ // virtual bases.
+ if (DtorType == Dtor_Complete) {
+ // Handle virtual bases.
+ for (CXXRecordDecl::reverse_base_class_const_iterator I =
+ ClassDecl->vbases_rbegin(), E = ClassDecl->vbases_rend();
+ I != E; ++I) {
+ const CXXBaseSpecifier &Base = *I;
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
+
+ // Ignore trivial destructors.
+ if (BaseClassDecl->hasTrivialDestructor())
+ continue;
+ const CXXDestructorDecl *D = BaseClassDecl->getDestructor(getContext());
+ llvm::Value *V = GetAddressOfBaseOfCompleteClass(LoadCXXThis(),
+ true,
+ ClassDecl,
+ BaseClassDecl);
+ EmitCXXDestructorCall(D, Dtor_Base, V);
+ }
+ return;
+ }
+
+ assert(DtorType == Dtor_Base);
+
// Collect the fields.
llvm::SmallVector<const FieldDecl *, 16> FieldDecls;
for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(),
@@ -1021,51 +1218,6 @@ void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD,
/*NullCheckValue=*/false);
EmitCXXDestructorCall(D, Dtor_Base, V);
}
-
- // If we're emitting a base destructor, we don't want to emit calls to the
- // virtual bases.
- if (DtorType == Dtor_Base)
- return;
-
- // Handle virtual bases.
- for (CXXRecordDecl::reverse_base_class_const_iterator I =
- ClassDecl->vbases_rbegin(), E = ClassDecl->vbases_rend(); I != E; ++I) {
- const CXXBaseSpecifier &Base = *I;
- CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
-
- // Ignore trivial destructors.
- if (BaseClassDecl->hasTrivialDestructor())
- continue;
- const CXXDestructorDecl *D = BaseClassDecl->getDestructor(getContext());
- llvm::Value *V = GetAddressOfBaseOfCompleteClass(LoadCXXThis(),
- true,
- ClassDecl,
- BaseClassDecl);
- EmitCXXDestructorCall(D, Dtor_Base, V);
- }
-
- // If we have a deleting destructor, emit a call to the delete operator.
- if (DtorType == Dtor_Deleting) {
- assert(DD->getOperatorDelete() &&
- "operator delete missing - EmitDtorEpilogue");
- EmitDeleteCall(DD->getOperatorDelete(), LoadCXXThis(),
- getContext().getTagDeclType(ClassDecl));
- }
-}
-
-void CodeGenFunction::SynthesizeDefaultDestructor(const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType,
- llvm::Function *Fn,
- const FunctionArgList &Args) {
- assert(!Dtor->getParent()->hasUserDeclaredDestructor() &&
- "SynthesizeDefaultDestructor - destructor has user declaration");
-
- StartFunction(GlobalDecl(Dtor, DtorType), Dtor->getResultType(), Fn, Args,
- SourceLocation());
- InitializeVtablePtrs(Dtor->getParent());
- EmitDtorEpilogue(Dtor, DtorType);
- FinishFunction();
}
/// EmitCXXAggrConstructorCall - This routine essentially creates a (nested)
@@ -1303,6 +1455,71 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
EmitCXXMemberCall(D, Callee, ReturnValueSlot(), This, VTT, ArgBeg, ArgEnd);
}
+void
+CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
+ CXXCtorType CtorType,
+ const FunctionArgList &Args) {
+ CallArgList DelegateArgs;
+
+ FunctionArgList::const_iterator I = Args.begin(), E = Args.end();
+ assert(I != E && "no parameters to constructor");
+
+ // this
+ DelegateArgs.push_back(std::make_pair(RValue::get(LoadCXXThis()),
+ I->second));
+ ++I;
+
+ // vtt
+ if (llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(Ctor, CtorType))) {
+ QualType VoidPP = getContext().getPointerType(getContext().VoidPtrTy);
+ DelegateArgs.push_back(std::make_pair(RValue::get(VTT), VoidPP));
+
+ if (CGVtableInfo::needsVTTParameter(CurGD)) {
+ assert(I != E && "cannot skip vtt parameter, already done with args");
+ assert(I->second == VoidPP && "skipping parameter not of vtt type");
+ ++I;
+ }
+ }
+
+ // Explicit arguments.
+ for (; I != E; ++I) {
+
+ const VarDecl *Param = I->first;
+ QualType ArgType = Param->getType(); // because we're passing it to itself
+
+ // StartFunction converted the ABI-lowered parameter(s) into a
+ // local alloca. We need to turn that into an r-value suitable
+ // for EmitCall.
+ llvm::Value *Local = GetAddrOfLocalVar(Param);
+ RValue Arg;
+
+ // For the most part, we just need to load the alloca, except:
+ // 1) aggregate r-values are actually pointers to temporaries, and
+ // 2) references to aggregates are pointers directly to the aggregate.
+ // I don't know why references to non-aggregates are different here.
+ if (ArgType->isReferenceType()) {
+ const ReferenceType *RefType = ArgType->getAs<ReferenceType>();
+ if (hasAggregateLLVMType(RefType->getPointeeType()))
+ Arg = RValue::getAggregate(Local);
+ else
+ // Locals which are references to scalars are represented
+ // with allocas holding the pointer.
+ Arg = RValue::get(Builder.CreateLoad(Local));
+ } else {
+ if (hasAggregateLLVMType(ArgType))
+ Arg = RValue::getAggregate(Local);
+ else
+ Arg = RValue::get(EmitLoadOfScalar(Local, false, ArgType));
+ }
+
+ DelegateArgs.push_back(std::make_pair(Arg, ArgType));
+ }
+
+ EmitCall(CGM.getTypes().getFunctionInfo(Ctor, CtorType),
+ CGM.GetAddrOfCXXConstructor(Ctor, CtorType),
+ ReturnValueSlot(), DelegateArgs, Ctor);
+}
+
void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,
CXXDtorType Type,
llvm::Value *This) {
@@ -1405,11 +1622,3 @@ void CodeGenFunction::InitializeVtablePtrsRecursive(
// Store address point
Builder.CreateStore(VtableAddressPoint, VtableField);
}
-
-llvm::Value *CodeGenFunction::LoadCXXVTT() {
- assert((isa<CXXConstructorDecl>(CurFuncDecl) ||
- isa<CXXDestructorDecl>(CurFuncDecl)) &&
- "Must be in a C++ ctor or dtor to load the vtt parameter");
-
- return Builder.CreateLoad(LocalDeclMap[CXXVTTDecl], "vtt");
-}
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 5b9c6b0..0f3502e 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -1034,6 +1034,28 @@ llvm::DIType CGDebugInfo::CreateType(const TagType *Ty,
return llvm::DIType();
}
+llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty,
+ llvm::DICompileUnit Unit) {
+ llvm::DIType ElementTy = getOrCreateType(Ty->getElementType(), Unit);
+ uint64_t NumElems = Ty->getNumElements();
+ if (NumElems > 0)
+ --NumElems;
+ llvm::SmallVector<llvm::DIDescriptor, 8> Subscripts;
+ Subscripts.push_back(DebugFactory.GetOrCreateSubrange(0, NumElems));
+
+ llvm::DIArray SubscriptArray =
+ DebugFactory.GetOrCreateArray(Subscripts.data(), Subscripts.size());
+
+ uint64_t Size = CGM.getContext().getTypeSize(Ty);
+ uint64_t Align = CGM.getContext().getTypeAlign(Ty);
+
+ return
+ DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_vector_type,
+ Unit, "", llvm::DICompileUnit(),
+ 0, Size, Align, 0, 0,
+ ElementTy, SubscriptArray);
+}
+
llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
llvm::DICompileUnit Unit) {
uint64_t Size;
@@ -1214,9 +1236,10 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
// FIXME: Handle these.
case Type::ExtVector:
- case Type::Vector:
return llvm::DIType();
-
+
+ case Type::Vector:
+ return CreateType(cast<VectorType>(Ty), Unit);
case Type::ObjCObjectPointer:
return CreateType(cast<ObjCObjectPointerType>(Ty), Unit);
case Type::ObjCInterface:
@@ -1351,10 +1374,13 @@ void CGDebugInfo::EmitStopPoint(llvm::Function *Fn, CGBuilderTy &Builder) {
/// EmitRegionStart- Constructs the debug code for entering a declarative
/// region - "llvm.dbg.region.start.".
void CGDebugInfo::EmitRegionStart(llvm::Function *Fn, CGBuilderTy &Builder) {
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ PresumedLoc PLoc = SM.getPresumedLoc(CurLoc);
llvm::DIDescriptor D =
DebugFactory.CreateLexicalBlock(RegionStack.empty() ?
llvm::DIDescriptor() :
- llvm::DIDescriptor(RegionStack.back()));
+ llvm::DIDescriptor(RegionStack.back()),
+ PLoc.getLine(), PLoc.getColumn());
RegionStack.push_back(D.getNode());
}
@@ -1666,7 +1692,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
T = CGM.getContext().getConstantArrayType(ET, ConstVal,
ArrayType::Normal, 0);
}
- llvm::StringRef DeclName = D->getName();
+ llvm::StringRef DeclName = Var->getName();
llvm::DIDescriptor DContext =
getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()), Unit);
DebugFactory.CreateGlobalVariable(DContext, DeclName,
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index b2d3a1f..50f5759 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -84,6 +84,7 @@ class CGDebugInfo {
llvm::DIType CreateType(const RecordType *Ty, llvm::DICompileUnit U);
llvm::DIType CreateType(const ObjCInterfaceType *Ty, llvm::DICompileUnit U);
llvm::DIType CreateType(const EnumType *Ty, llvm::DICompileUnit U);
+ llvm::DIType CreateType(const VectorType *Ty, llvm::DICompileUnit Unit);
llvm::DIType CreateType(const ArrayType *Ty, llvm::DICompileUnit U);
llvm::DIType CreateType(const LValueReferenceType *Ty, llvm::DICompileUnit U);
llvm::DIType CreateType(const MemberPointerType *Ty, llvm::DICompileUnit U);
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index d956c1c..142cb81 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -427,6 +427,26 @@ void CodeGenFunction::EmitEndEHSpec(const Decl *D) {
}
void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
+ CXXTryStmtInfo Info = EnterCXXTryStmt(S);
+ EmitStmt(S.getTryBlock());
+ ExitCXXTryStmt(S, Info);
+}
+
+CodeGenFunction::CXXTryStmtInfo
+CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S) {
+ CXXTryStmtInfo Info;
+ Info.SavedLandingPad = getInvokeDest();
+ Info.HandlerBlock = createBasicBlock("try.handler");
+ Info.FinallyBlock = createBasicBlock("finally");
+
+ PushCleanupBlock(Info.FinallyBlock);
+ setInvokeDest(Info.HandlerBlock);
+
+ return Info;
+}
+
+void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S,
+ CXXTryStmtInfo TryInfo) {
// Pointer to the personality function
llvm::Constant *Personality =
CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
@@ -439,54 +459,12 @@ void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
llvm::Value *llvm_eh_selector =
CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
- llvm::BasicBlock *PrevLandingPad = getInvokeDest();
- llvm::BasicBlock *TryHandler = createBasicBlock("try.handler");
- llvm::BasicBlock *FinallyBlock = createBasicBlock("finally");
+ llvm::BasicBlock *PrevLandingPad = TryInfo.SavedLandingPad;
+ llvm::BasicBlock *TryHandler = TryInfo.HandlerBlock;
+ llvm::BasicBlock *FinallyBlock = TryInfo.FinallyBlock;
llvm::BasicBlock *FinallyRethrow = createBasicBlock("finally.throw");
llvm::BasicBlock *FinallyEnd = createBasicBlock("finally.end");
- // Push an EH context entry, used for handling rethrows.
- PushCleanupBlock(FinallyBlock);
-
- // Emit the statements in the try {} block
- setInvokeDest(TryHandler);
-
- // FIXME: We should not have to do this here. The AST should have the member
- // initializers under the CXXTryStmt's TryBlock.
- if (OuterTryBlock == &S) {
- GlobalDecl GD = CurGD;
- const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
-
- if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
- size_t OldCleanupStackSize = CleanupEntries.size();
- EmitCtorPrologue(CD, CurGD.getCtorType());
- EmitStmt(S.getTryBlock());
-
- // If any of the member initializers are temporaries bound to references
- // make sure to emit their destructors.
- EmitCleanupBlocks(OldCleanupStackSize);
- } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) {
- llvm::BasicBlock *DtorEpilogue = createBasicBlock("dtor.epilogue");
- PushCleanupBlock(DtorEpilogue);
-
- InitializeVtablePtrs(DD->getParent());
- EmitStmt(S.getTryBlock());
-
- CleanupBlockInfo Info = PopCleanupBlock();
-
- assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!");
- EmitBlock(DtorEpilogue);
- EmitDtorEpilogue(DD, GD.getDtorType());
-
- if (Info.SwitchBlock)
- EmitBlock(Info.SwitchBlock);
- if (Info.EndBlock)
- EmitBlock(Info.EndBlock);
- } else
- EmitStmt(S.getTryBlock());
- } else
- EmitStmt(S.getTryBlock());
-
// Jump to end if there is no exception
EmitBranchThroughCleanup(FinallyEnd);
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 830954f..030d2c9 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -36,7 +36,17 @@ llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(const llvm::Type *Ty,
return new llvm::AllocaInst(Ty, 0, Name, AllocaInsertPt);
}
-llvm::Value *CodeGenFunction::CreateMemTemp(QualType Ty, const llvm::Twine &Name) {
+llvm::Value *CodeGenFunction::CreateIRTemp(QualType Ty,
+ const llvm::Twine &Name) {
+ llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertType(Ty), Name);
+ // FIXME: Should we prefer the preferred type alignment here?
+ CharUnits Align = getContext().getTypeAlignInChars(Ty);
+ Alloc->setAlignment(Align.getQuantity());
+ return Alloc;
+}
+
+llvm::Value *CodeGenFunction::CreateMemTemp(QualType Ty,
+ const llvm::Twine &Name) {
llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertTypeForMem(Ty), Name);
// FIXME: Should we prefer the preferred type alignment here?
CharUnits Align = getContext().getTypeAlignInChars(Ty);
@@ -1520,9 +1530,7 @@ CodeGenFunction::EmitLValueForFieldInitialization(llvm::Value* BaseValue,
}
LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E){
- llvm::Value *DeclPtr = CreateTempAlloca(ConvertTypeForMem(E->getType()),
- ".compoundliteral");
-
+ llvm::Value *DeclPtr = CreateMemTemp(E->getType(), ".compoundliteral");
const Expr* InitExpr = E->getInitializer();
LValue Result = LValue::MakeAddr(DeclPtr, MakeQualifiers(E->getType()));
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 97455c7..ac189a0 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -189,7 +189,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
CGF.ConvertType(PtrTy));
EmitInitializationToLValue(E->getSubExpr(),
LValue::MakeAddr(CastPtr, Qualifiers()),
- E->getType());
+ E->getSubExpr()->getType());
break;
}
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index 1d38ef9..198e2d1 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -56,7 +56,7 @@ private:
const llvm::FunctionType *IMPTy;
const llvm::PointerType *IdTy;
const llvm::PointerType *PtrToIdTy;
- QualType ASTIdTy;
+ CanQualType ASTIdTy;
const llvm::IntegerType *IntTy;
const llvm::PointerType *PtrTy;
const llvm::IntegerType *LongTy;
@@ -262,7 +262,7 @@ CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm)
PtrTy = PtrToInt8Ty;
// Object type
- ASTIdTy = CGM.getContext().getObjCIdType();
+ ASTIdTy = CGM.getContext().getCanonicalType(CGM.getContext().getObjCIdType());
if (QualType() == ASTIdTy) {
IdTy = PtrToInt8Ty;
} else {
@@ -1192,19 +1192,22 @@ llvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OI
iter != endIter ; iter++) {
std::vector<llvm::Constant*> Fields;
ObjCPropertyDecl *property = (*iter)->getPropertyDecl();
+ ObjCPropertyImplDecl *propertyImpl = *iter;
+ bool isSynthesized = (propertyImpl->getPropertyImplementation() ==
+ ObjCPropertyImplDecl::Synthesize);
Fields.push_back(MakeConstantString(property->getNameAsString()));
Fields.push_back(llvm::ConstantInt::get(Int8Ty,
property->getPropertyAttributes()));
- Fields.push_back(llvm::ConstantInt::get(Int8Ty,
- (*iter)->getPropertyImplementation() ==
- ObjCPropertyImplDecl::Synthesize));
+ Fields.push_back(llvm::ConstantInt::get(Int8Ty, isSynthesized));
if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
- InstanceMethodSels.push_back(getter->getSelector());
std::string TypeStr;
Context.getObjCEncodingForMethodDecl(getter,TypeStr);
llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
- InstanceMethodTypes.push_back(TypeEncoding);
+ if (isSynthesized) {
+ InstanceMethodTypes.push_back(TypeEncoding);
+ InstanceMethodSels.push_back(getter->getSelector());
+ }
Fields.push_back(MakeConstantString(getter->getSelector().getAsString()));
Fields.push_back(TypeEncoding);
} else {
@@ -1212,11 +1215,13 @@ llvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OI
Fields.push_back(NULLPtr);
}
if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) {
- InstanceMethodSels.push_back(setter->getSelector());
std::string TypeStr;
Context.getObjCEncodingForMethodDecl(setter,TypeStr);
llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
- InstanceMethodTypes.push_back(TypeEncoding);
+ if (isSynthesized) {
+ InstanceMethodTypes.push_back(TypeEncoding);
+ InstanceMethodSels.push_back(setter->getSelector());
+ }
Fields.push_back(MakeConstantString(setter->getSelector().getAsString()));
Fields.push_back(TypeEncoding);
} else {
@@ -1685,7 +1690,7 @@ llvm::Constant *CGObjCGNU::EnumerationMutationFunction() {
CodeGen::CodeGenTypes &Types = CGM.getTypes();
ASTContext &Ctx = CGM.getContext();
// void objc_enumerationMutation (id)
- llvm::SmallVector<QualType,16> Params;
+ llvm::SmallVector<CanQualType,1> Params;
Params.push_back(ASTIdTy);
const llvm::FunctionType *FTy =
Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index b16a510..475280b 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -297,9 +297,9 @@ public:
CodeGen::CodeGenTypes &Types = CGM.getTypes();
ASTContext &Ctx = CGM.getContext();
// id objc_getProperty (id, SEL, ptrdiff_t, bool)
- llvm::SmallVector<QualType,16> Params;
- QualType IdType = Ctx.getObjCIdType();
- QualType SelType = Ctx.getObjCSelType();
+ llvm::SmallVector<CanQualType,4> Params;
+ CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
+ CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Params.push_back(IdType);
Params.push_back(SelType);
Params.push_back(Ctx.LongTy);
@@ -314,9 +314,9 @@ public:
CodeGen::CodeGenTypes &Types = CGM.getTypes();
ASTContext &Ctx = CGM.getContext();
// void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
- llvm::SmallVector<QualType,16> Params;
- QualType IdType = Ctx.getObjCIdType();
- QualType SelType = Ctx.getObjCSelType();
+ llvm::SmallVector<CanQualType,6> Params;
+ CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
+ CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Params.push_back(IdType);
Params.push_back(SelType);
Params.push_back(Ctx.LongTy);
@@ -333,8 +333,8 @@ public:
CodeGen::CodeGenTypes &Types = CGM.getTypes();
ASTContext &Ctx = CGM.getContext();
// void objc_enumerationMutation (id)
- llvm::SmallVector<QualType,16> Params;
- Params.push_back(Ctx.getObjCIdType());
+ llvm::SmallVector<CanQualType,1> Params;
+ Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
const llvm::FunctionType *FTy =
Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
CC_Default, false), false);
@@ -3293,7 +3293,7 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
// Add this implementations synthesized ivars.
llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
- CGM.getContext().CollectSynthesizedIvars(OI, Ivars);
+ CGM.getContext().CollectNonClassIvars(OI, Ivars);
for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
RecFields.push_back(cast<FieldDecl>(Ivars[k]));
@@ -5093,9 +5093,8 @@ CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend(
// Find the message function name.
// FIXME. This is too much work to get the ABI-specific result type needed to
// find the message name.
- const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType,
- llvm::SmallVector<QualType, 16>(),
- CC_Default, false);
+ const CGFunctionInfo &FnInfo
+ = Types.getFunctionInfo(ResultType, CallArgList(), CC_Default, false);
llvm::Constant *Fn = 0;
std::string Name("\01l_");
if (CGM.ReturnTypeUsesSret(FnInfo)) {
diff --git a/lib/CodeGen/CGVTT.cpp b/lib/CodeGen/CGVTT.cpp
index 9714bd9..96c104b 100644
--- a/lib/CodeGen/CGVTT.cpp
+++ b/lib/CodeGen/CGVTT.cpp
@@ -46,7 +46,8 @@ class VTTBuilder {
llvm::DenseMap<std::pair<const CXXRecordDecl *, BaseSubobject>, uint64_t>
CtorVtableAddressPoints;
- llvm::Constant *getCtorVtable(const BaseSubobject &Base) {
+ llvm::Constant *getCtorVtable(const BaseSubobject &Base,
+ bool BaseIsVirtual) {
if (!GenerateDefinition)
return 0;
@@ -54,7 +55,7 @@ class VTTBuilder {
if (!CtorVtable) {
// Build the vtable.
CGVtableInfo::CtorVtableInfo Info
- = CGM.getVtableInfo().getCtorVtable(Class, Base);
+ = CGM.getVtableInfo().getCtorVtable(Class, Base, BaseIsVirtual);
CtorVtable = Info.Vtable;
@@ -166,7 +167,7 @@ class VTTBuilder {
if (BaseMorallyVirtual || VtblClass == Class)
init = BuildVtablePtr(vtbl, VtblClass, Base, BaseOffset);
else {
- init = getCtorVtable(BaseSubobject(Base, BaseOffset));
+ init = getCtorVtable(BaseSubobject(Base, BaseOffset), i->isVirtual());
subvtbl = init;
subVtblClass = Base;
@@ -186,7 +187,8 @@ class VTTBuilder {
/// BuiltVTT - Add the VTT to Inits. Offset is the offset in bits to the
/// currnet object we're working on.
- void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset, bool MorallyVirtual) {
+ void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset, bool BaseIsVirtual,
+ bool MorallyVirtual) {
// Itanium C++ ABI 2.6.2:
// An array of virtual table addresses, called the VTT, is declared for
// each class type that has indirect or direct virtual base classes.
@@ -204,7 +206,8 @@ class VTTBuilder {
Vtable = ClassVtbl;
VtableClass = Class;
} else {
- Vtable = getCtorVtable(BaseSubobject(RD, Offset));
+ Vtable = getCtorVtable(BaseSubobject(RD, Offset),
+ /*IsVirtual=*/BaseIsVirtual);
VtableClass = RD;
}
@@ -235,7 +238,7 @@ class VTTBuilder {
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base);
- BuildVTT(Base, BaseOffset, MorallyVirtual);
+ BuildVTT(Base, BaseOffset, /*BaseIsVirtual=*/false, MorallyVirtual);
}
}
@@ -249,7 +252,7 @@ class VTTBuilder {
if (i->isVirtual() && !SeenVBase.count(Base)) {
SeenVBase.insert(Base);
uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
- BuildVTT(Base, BaseOffset, false);
+ BuildVTT(Base, BaseOffset, /*BaseIsVirtual=*/true, false);
}
VirtualVTTs(Base);
}
@@ -335,13 +338,13 @@ CGVtableInfo::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
CGVtableInfo::CtorVtableInfo
CGVtableInfo::getCtorVtable(const CXXRecordDecl *RD,
- const BaseSubobject &Base) {
+ const BaseSubobject &Base, bool BaseIsVirtual) {
CtorVtableInfo Info;
Info.Vtable = GenerateVtable(llvm::GlobalValue::InternalLinkage,
/*GenerateDefinition=*/true,
RD, Base.getBase(), Base.getBaseOffset(),
- Info.AddressPoints);
+ BaseIsVirtual, Info.AddressPoints);
return Info;
}
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp
index 970bbd7..932bd07 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/RecordLayout.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SetVector.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Format.h"
#include <cstdio>
@@ -25,40 +26,44 @@ using namespace CodeGen;
namespace {
+/// BaseOffset - Represents an offset from a derived class to a direct or
+/// indirect base class.
+struct BaseOffset {
+ /// DerivedClass - The derived class.
+ const CXXRecordDecl *DerivedClass;
+
+ /// VirtualBase - If the path from the derived class to the base class
+ /// involves a virtual base class, this holds its declaration.
+ const CXXRecordDecl *VirtualBase;
+
+ /// NonVirtualOffset - The offset from the derived class to the base class.
+ /// (Or the offset from the virtual base class to the base class, if the
+ /// path from the derived class to the base class involves a virtual base
+ /// class.
+ int64_t NonVirtualOffset;
+
+ BaseOffset() : DerivedClass(0), VirtualBase(0), NonVirtualOffset(0) { }
+ BaseOffset(const CXXRecordDecl *DerivedClass,
+ const CXXRecordDecl *VirtualBase, int64_t NonVirtualOffset)
+ : DerivedClass(DerivedClass), VirtualBase(VirtualBase),
+ NonVirtualOffset(NonVirtualOffset) { }
+
+ bool isEmpty() const { return !NonVirtualOffset && !VirtualBase; }
+};
+
/// FinalOverriders - Contains the final overrider member functions for all
/// member functions in the base subobjects of a class.
class FinalOverriders {
public:
- /// BaseOffset - Represents an offset from a derived class to a direct or
- /// indirect base class.
- struct BaseOffset {
- /// DerivedClass - The derived class.
- const CXXRecordDecl *DerivedClass;
-
- /// VirtualBase - If the path from the derived class to the base class
- /// involves a virtual base class, this holds its declaration.
- const CXXRecordDecl *VirtualBase;
-
- /// NonVirtualOffset - The offset from the derived class to the base class.
- /// Or the offset from the virtual base class to the base class, if the path
- /// from the derived class to the base class involves a virtual base class.
- int64_t NonVirtualOffset;
-
- BaseOffset() : DerivedClass(0), VirtualBase(0), NonVirtualOffset(0) { }
- BaseOffset(const CXXRecordDecl *DerivedClass,
- const CXXRecordDecl *VirtualBase, int64_t NonVirtualOffset)
- : DerivedClass(DerivedClass), VirtualBase(VirtualBase),
- NonVirtualOffset(NonVirtualOffset) { }
-
- bool isEmpty() const { return !NonVirtualOffset && !VirtualBase; }
- };
-
/// OverriderInfo - Information about a final overrider.
struct OverriderInfo {
/// Method - The method decl of the overrider.
const CXXMethodDecl *Method;
+
+ /// Offset - the base offset of the overrider relative to the layout class.
+ int64_t Offset;
- OverriderInfo() : Method(0) { }
+ OverriderInfo() : Method(0), Offset(0) { }
};
private:
@@ -93,12 +98,9 @@ private:
/// ReturnAdjustments - Holds return adjustments for all the overriders that
/// need to perform return value adjustments.
AdjustmentOffsetsMapTy ReturnAdjustments;
-
- /// ThisAdjustments - Holds 'this' adjustments for all the overriders that
- /// need them.
- AdjustmentOffsetsMapTy ThisAdjustments;
- typedef llvm::SmallVector<uint64_t, 1> OffsetVectorTy;
+ // FIXME: We might be able to get away with making this a SmallSet.
+ typedef llvm::SmallSetVector<uint64_t, 2> OffsetSetVectorTy;
/// SubobjectOffsetsMapTy - This map is used for keeping track of all the
/// base subobject offsets that a single class declaration might refer to.
@@ -113,12 +115,13 @@ private:
/// when we determine that C::f() overrides A::f(), we need to update the
/// overriders map for both A-in-B1 and A-in-B2 and the subobject offsets map
/// will have the subobject offsets for both A copies.
- typedef llvm::DenseMap<const CXXRecordDecl *, OffsetVectorTy>
+ typedef llvm::DenseMap<const CXXRecordDecl *, OffsetSetVectorTy>
SubobjectOffsetsMapTy;
/// ComputeFinalOverriders - Compute the final overriders for a given base
/// subobject (and all its direct and indirect bases).
void ComputeFinalOverriders(BaseSubobject Base,
+ bool BaseSubobjectIsVisitedVBase,
SubobjectOffsetsMapTy &Offsets);
/// AddOverriders - Add the final overriders for this base subobject to the
@@ -139,17 +142,12 @@ private:
const CXXMethodDecl *NewMD,
SubobjectOffsetsMapTy &Offsets);
- /// ComputeThisAdjustmentBaseOffset - Compute the base offset for adjusting
- /// the 'this' pointer from the base subobject to the derived subobject.
- BaseOffset ComputeThisAdjustmentBaseOffset(BaseSubobject Base,
- BaseSubobject Derived);
-
static void MergeSubobjectOffsets(const SubobjectOffsetsMapTy &NewOffsets,
SubobjectOffsetsMapTy &Offsets);
public:
explicit FinalOverriders(const CXXRecordDecl *MostDerivedClass);
-
+
/// getOverrider - Get the final overrider for the given method declaration in
/// the given base subobject.
OverriderInfo getOverrider(BaseSubobject Base,
@@ -168,14 +166,6 @@ public:
return ReturnAdjustments.lookup(std::make_pair(Base, MD));
}
- /// getThisAdjustmentOffset - Get the 'this' pointer adjustment offset for the
- /// method decl in the given base subobject. Returns an empty base offset if
- /// no adjustment is needed.
- BaseOffset getThisAdjustmentOffset(BaseSubobject Base,
- const CXXMethodDecl *MD) const {
- return ThisAdjustments.lookup(std::make_pair(Base, MD));
- }
-
/// dump - dump the final overriders.
void dump() {
assert(VisitedVirtualBases.empty() &&
@@ -189,6 +179,8 @@ public:
void dump(llvm::raw_ostream &Out, BaseSubobject Base);
};
+#define DUMP_OVERRIDERS 0
+
FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass)
: MostDerivedClass(MostDerivedClass),
Context(MostDerivedClass->getASTContext()),
@@ -196,8 +188,11 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass)
// Compute the final overriders.
SubobjectOffsetsMapTy Offsets;
- ComputeFinalOverriders(BaseSubobject(MostDerivedClass, 0), Offsets);
-
+ ComputeFinalOverriders(BaseSubobject(MostDerivedClass, 0),
+ /*BaseSubobjectIsVisitedVBase=*/false, Offsets);
+ VisitedVirtualBases.clear();
+
+#if DUMP_OVERRIDERS
// And dump them (for now).
dump();
@@ -212,6 +207,7 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass)
for (unsigned I = 0, E = OffsetVector.size(); I != E; ++I)
llvm::errs() << " " << I << " - " << OffsetVector[I] << '\n';
}
+#endif
}
void FinalOverriders::AddOverriders(BaseSubobject Base,
@@ -232,13 +228,14 @@ void FinalOverriders::AddOverriders(BaseSubobject Base,
OverriderInfo& Overrider = OverridersMap[std::make_pair(Base, MD)];
assert(!Overrider.Method && "Overrider should not exist yet!");
+ Overrider.Offset = Base.getBaseOffset();
Overrider.Method = MD;
}
}
-static FinalOverriders::BaseOffset
-ComputeBaseOffset(ASTContext &Context, const CXXRecordDecl *DerivedRD,
- const CXXBasePath &Path) {
+static BaseOffset ComputeBaseOffset(ASTContext &Context,
+ const CXXRecordDecl *DerivedRD,
+ const CXXBasePath &Path) {
int64_t NonVirtualOffset = 0;
unsigned NonVirtualStart = 0;
@@ -264,37 +261,36 @@ ComputeBaseOffset(ASTContext &Context, const CXXRecordDecl *DerivedRD,
// Check the base class offset.
const ASTRecordLayout &Layout = Context.getASTRecordLayout(Element.Class);
-
+
const RecordType *BaseType = Element.Base->getType()->getAs<RecordType>();
const CXXRecordDecl *Base = cast<CXXRecordDecl>(BaseType->getDecl());
-
+
NonVirtualOffset += Layout.getBaseClassOffset(Base);
}
// FIXME: This should probably use CharUnits or something. Maybe we should
// even change the base offsets in ASTRecordLayout to be specified in
// CharUnits.
- return FinalOverriders::BaseOffset(DerivedRD, VirtualBase,
- NonVirtualOffset / 8);
+ return BaseOffset(DerivedRD, VirtualBase, NonVirtualOffset / 8);
}
-static FinalOverriders::BaseOffset
-ComputeBaseOffset(ASTContext &Context, const CXXRecordDecl *BaseRD,
- const CXXRecordDecl *DerivedRD) {
+static BaseOffset ComputeBaseOffset(ASTContext &Context,
+ const CXXRecordDecl *BaseRD,
+ const CXXRecordDecl *DerivedRD) {
CXXBasePaths Paths(/*FindAmbiguities=*/false,
/*RecordPaths=*/true, /*DetectVirtual=*/false);
if (!const_cast<CXXRecordDecl *>(DerivedRD)->
isDerivedFrom(const_cast<CXXRecordDecl *>(BaseRD), Paths)) {
assert(false && "Class must be derived from the passed in base class!");
- return FinalOverriders::BaseOffset();
+ return BaseOffset();
}
return ComputeBaseOffset(Context, DerivedRD, Paths.front());
}
-static FinalOverriders::BaseOffset
+static BaseOffset
ComputeReturnAdjustmentBaseOffset(ASTContext &Context,
const CXXMethodDecl *DerivedMD,
const CXXMethodDecl *BaseMD) {
@@ -313,7 +309,7 @@ ComputeReturnAdjustmentBaseOffset(ASTContext &Context,
if (CanDerivedReturnType == CanBaseReturnType) {
// No adjustment needed.
- return FinalOverriders::BaseOffset();
+ return BaseOffset();
}
if (isa<ReferenceType>(CanDerivedReturnType)) {
@@ -336,7 +332,7 @@ ComputeReturnAdjustmentBaseOffset(ASTContext &Context,
if (CanDerivedReturnType.getUnqualifiedType() ==
CanBaseReturnType.getUnqualifiedType()) {
// No adjustment needed.
- return FinalOverriders::BaseOffset();
+ return BaseOffset();
}
const CXXRecordDecl *DerivedRD =
@@ -348,35 +344,6 @@ ComputeReturnAdjustmentBaseOffset(ASTContext &Context,
return ComputeBaseOffset(Context, BaseRD, DerivedRD);
}
-FinalOverriders::BaseOffset
-FinalOverriders::ComputeThisAdjustmentBaseOffset(BaseSubobject Base,
- BaseSubobject Derived) {
- const CXXRecordDecl *BaseRD = Base.getBase();
- const CXXRecordDecl *DerivedRD = Derived.getBase();
-
- CXXBasePaths Paths(/*FindAmbiguities=*/true,
- /*RecordPaths=*/true, /*DetectVirtual=*/true);
-
- if (!const_cast<CXXRecordDecl *>(DerivedRD)->
- isDerivedFrom(const_cast<CXXRecordDecl *>(BaseRD), Paths)) {
- assert(false && "Class must be derived from the passed in base class!");
- return FinalOverriders::BaseOffset();
- }
-
- assert(!Paths.getDetectedVirtual() && "FIXME: Handle virtual bases!");
-
- BaseOffset Offset;
-
- // FIXME: This is not going to be enough with virtual bases.
- // FIXME: We should not use / 8 here.
- int64_t DerivedToBaseOffset =
- (Base.getBaseOffset() - Derived.getBaseOffset()) / 8;
-
- Offset.NonVirtualOffset = -DerivedToBaseOffset;
-
- return Offset;
-}
-
void FinalOverriders::PropagateOverrider(const CXXMethodDecl *OldMD,
BaseSubobject NewBase,
const CXXMethodDecl *NewMD,
@@ -394,7 +361,7 @@ void FinalOverriders::PropagateOverrider(const CXXMethodDecl *OldMD,
/// struct C : B1, B2 { virtual void f(); };
///
/// When overriding A::f with C::f we need to do so in both A subobjects.
- const OffsetVectorTy &OffsetVector = Offsets[OverriddenRD];
+ const OffsetSetVectorTy &OffsetVector = Offsets[OverriddenRD];
// Go through all the subobjects.
for (unsigned I = 0, E = OffsetVector.size(); I != E; ++I) {
@@ -419,20 +386,10 @@ void FinalOverriders::PropagateOverrider(const CXXMethodDecl *OldMD,
// Store the return adjustment base offset.
ReturnAdjustments[SubobjectAndMethod] = ReturnBaseOffset;
}
-
- // Check if we need a 'this' adjustment base offset as well.
- if (Offset != NewBase.getBaseOffset()) {
- BaseOffset ThisBaseOffset =
- ComputeThisAdjustmentBaseOffset(OverriddenSubobject,
- NewBase);
- assert(!ThisBaseOffset.isEmpty() &&
- "Should not get an empty 'this' adjustment!");
-
- ThisAdjustments[SubobjectAndMethod] = ThisBaseOffset;
- }
}
// Set the new overrider.
+ Overrider.Offset = NewBase.getBaseOffset();
Overrider.Method = NewMD;
// And propagate it further.
@@ -448,45 +405,17 @@ FinalOverriders::MergeSubobjectOffsets(const SubobjectOffsetsMapTy &NewOffsets,
for (SubobjectOffsetsMapTy::const_iterator I = NewOffsets.begin(),
E = NewOffsets.end(); I != E; ++I) {
const CXXRecordDecl *NewRD = I->first;
- const OffsetVectorTy& NewOffsetVector = I->second;
-
- OffsetVectorTy &OffsetVector = Offsets[NewRD];
- if (OffsetVector.empty()) {
- // There were no previous offsets in this vector, just insert all entries
- // from the new offset vector.
- OffsetVector.append(NewOffsetVector.begin(), NewOffsetVector.end());
- continue;
- }
-
- // We need to merge the new offsets vector into the old, but we don't want
- // to have duplicate entries. Do this by inserting the old offsets in a set
- // so they'll be unique. After this, we iterate over the new offset vector
- // and only append elements that aren't in the set.
+ const OffsetSetVectorTy& NewOffsetVector = I->second;
- // First, add the existing offsets to the set.
- llvm::SmallSet<uint64_t, 4> OffsetSet;
- for (unsigned I = 0, E = OffsetVector.size(); I != E; ++I) {
- bool Inserted = OffsetSet.insert(OffsetVector[I]);
- if (!Inserted)
- assert(false && "Set of offsets should be unique!");
- }
+ OffsetSetVectorTy &OffsetVector = Offsets[NewRD];
- // Next, only add the new offsets if they are not already in the set.
- for (unsigned I = 0, E = NewOffsetVector.size(); I != E; ++I) {
- uint64_t Offset = NewOffsetVector[I];
-
- if (OffsetSet.count(Offset)) {
- // Ignore the offset.
- continue;
- }
-
- // Otherwise, add it to the offsets vector.
- OffsetVector.push_back(Offset);
- }
+ // Merge the new offsets set vector into the old.
+ OffsetVector.insert(NewOffsetVector.begin(), NewOffsetVector.end());
}
}
void FinalOverriders::ComputeFinalOverriders(BaseSubobject Base,
+ bool BaseSubobjectIsVisitedVBase,
SubobjectOffsetsMapTy &Offsets) {
const CXXRecordDecl *RD = Base.getBase();
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
@@ -502,25 +431,51 @@ void FinalOverriders::ComputeFinalOverriders(BaseSubobject Base,
if (!BaseDecl->isPolymorphic())
continue;
+ bool IsVisitedVirtualBase = BaseSubobjectIsVisitedVBase;
uint64_t BaseOffset;
if (I->isVirtual()) {
+ if (!VisitedVirtualBases.insert(BaseDecl))
+ IsVisitedVirtualBase = true;
BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
} else {
BaseOffset = Layout.getBaseClassOffset(BaseDecl) + Base.getBaseOffset();
}
// Compute the final overriders for this base.
- ComputeFinalOverriders(BaseSubobject(BaseDecl, BaseOffset), NewOffsets);
+ // We always want to compute the final overriders, even if the base is a
+ // visited virtual base. Consider:
+ //
+ // struct A {
+ // virtual void f();
+ // virtual void g();
+ // };
+ //
+ // struct B : virtual A {
+ // void f();
+ // };
+ //
+ // struct C : virtual A {
+ // void g ();
+ // };
+ //
+ // struct D : B, C { };
+ //
+ // Here, we still want to compute the overriders for A as a base of C,
+ // because otherwise we'll miss that C::g overrides A::f.
+ ComputeFinalOverriders(BaseSubobject(BaseDecl, BaseOffset),
+ IsVisitedVirtualBase, NewOffsets);
}
/// Now add the overriders for this particular subobject.
- AddOverriders(Base, NewOffsets);
+ /// (We don't want to do this more than once for a virtual base).
+ if (!BaseSubobjectIsVisitedVBase)
+ AddOverriders(Base, NewOffsets);
// And merge the newly discovered subobject offsets.
MergeSubobjectOffsets(NewOffsets, Offsets);
/// Finally, add the offset for our own subobject.
- Offsets[RD].push_back(Base.getBaseOffset());
+ Offsets[RD].insert(Base.getBaseOffset());
}
void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base) {
@@ -565,9 +520,10 @@ void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base) {
OverriderInfo Overrider = getOverrider(Base, MD);
- Out << " " << MD->getQualifiedNameAsString() << " - ";
+ Out << " " << MD->getQualifiedNameAsString() << " - (";
Out << Overrider.Method->getQualifiedNameAsString();
-
+ Out << ", " << Overrider.Offset << ')';
+
AdjustmentOffsetsMapTy::const_iterator AI =
ReturnAdjustments.find(std::make_pair(Base, MD));
if (AI != ReturnAdjustments.end()) {
@@ -580,17 +536,6 @@ void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base) {
Out << Offset.NonVirtualOffset << " nv]";
}
- AI = ThisAdjustments.find(std::make_pair(Base, MD));
- if (AI != ThisAdjustments.end()) {
- const BaseOffset &Offset = AI->second;
-
- Out << " [this-adj: ";
- if (Offset.VirtualBase)
- Out << Offset.VirtualBase->getQualifiedNameAsString() << " vbase, ";
-
- Out << Offset.NonVirtualOffset << " nv]";
- }
-
Out << "\n";
}
}
@@ -609,9 +554,18 @@ public:
CK_CompleteDtorPointer,
/// CK_DeletingDtorPointer - A pointer to the deleting destructor.
- CK_DeletingDtorPointer
+ CK_DeletingDtorPointer,
+
+ /// CK_UnusedFunctionPointer - In some cases, a vtable function pointer
+ /// will end up never being called. Such vtable function pointers are
+ /// represented as a CK_UnusedFunctionPointer.
+ CK_UnusedFunctionPointer
};
+ static VtableComponent MakeVCallOffset(int64_t Offset) {
+ return VtableComponent(CK_VCallOffset, Offset);
+ }
+
static VtableComponent MakeVBaseOffset(int64_t Offset) {
return VtableComponent(CK_VBaseOffset, Offset);
}
@@ -642,11 +596,24 @@ public:
reinterpret_cast<uintptr_t>(DD));
}
+ static VtableComponent MakeUnusedFunction(const CXXMethodDecl *MD) {
+ assert(!isa<CXXDestructorDecl>(MD) &&
+ "Don't use MakeUnusedFunction with destructors!");
+ return VtableComponent(CK_UnusedFunctionPointer,
+ reinterpret_cast<uintptr_t>(MD));
+ }
+
/// getKind - Get the kind of this vtable component.
Kind getKind() const {
return (Kind)(Value & 0x7);
}
+ int64_t getVCallOffset() const {
+ assert(getKind() == CK_VCallOffset && "Invalid component kind!");
+
+ return getOffset();
+ }
+
int64_t getVBaseOffset() const {
assert(getKind() == CK_VBaseOffset && "Invalid component kind!");
@@ -678,6 +645,12 @@ public:
return reinterpret_cast<CXXDestructorDecl *>(getPointer());
}
+ const CXXMethodDecl *getUnusedFunctionDecl() const {
+ assert(getKind() == CK_UnusedFunctionPointer);
+
+ return reinterpret_cast<CXXMethodDecl *>(getPointer());
+ }
+
private:
VtableComponent(Kind ComponentKind, int64_t Offset) {
assert((ComponentKind == CK_VCallOffset ||
@@ -692,7 +665,8 @@ private:
assert((ComponentKind == CK_RTTI ||
ComponentKind == CK_FunctionPointer ||
ComponentKind == CK_CompleteDtorPointer ||
- ComponentKind == CK_DeletingDtorPointer) &&
+ ComponentKind == CK_DeletingDtorPointer ||
+ ComponentKind == CK_UnusedFunctionPointer) &&
"Invalid component kind!");
assert((Ptr & 7) == 0 && "Pointer not sufficiently aligned!");
@@ -711,7 +685,8 @@ private:
assert((getKind() == CK_RTTI ||
getKind() == CK_FunctionPointer ||
getKind() == CK_CompleteDtorPointer ||
- getKind() == CK_DeletingDtorPointer) &&
+ getKind() == CK_DeletingDtorPointer ||
+ getKind() == CK_UnusedFunctionPointer) &&
"Invalid component kind!");
return static_cast<uintptr_t>(Value & ~7ULL);
@@ -725,12 +700,334 @@ private:
int64_t Value;
};
+/// VCallOffsetMap - Keeps track of vcall offsets when building a vtable.
+struct VCallOffsetMap {
+
+ typedef std::pair<const CXXMethodDecl *, int64_t> MethodAndOffsetPairTy;
+
+ /// Offsets - Keeps track of methods and their offsets.
+ // FIXME: This should be a real map and not a vector.
+ llvm::SmallVector<MethodAndOffsetPairTy, 16> Offsets;
+
+ /// MethodsCanShareVCallOffset - Returns whether two virtual member functions
+ /// can share the same vcall offset.
+ static bool MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
+ const CXXMethodDecl *RHS);
+
+public:
+ /// AddVCallOffset - Adds a vcall offset to the map. Returns true if the
+ /// add was successful, or false if there was already a member function with
+ /// the same signature in the map.
+ bool AddVCallOffset(const CXXMethodDecl *MD, int64_t OffsetOffset);
+
+ /// getVCallOffsetOffset - Returns the vcall offset offset (relative to the
+ /// vtable address point) for the given virtual member function.
+ int64_t getVCallOffsetOffset(const CXXMethodDecl *MD);
+
+ // empty - Return whether the offset map is empty or not.
+ bool empty() const { return Offsets.empty(); }
+};
+
+static bool HasSameVirtualSignature(const CXXMethodDecl *LHS,
+ const CXXMethodDecl *RHS) {
+ ASTContext &C = LHS->getASTContext(); // TODO: thread this down
+ CanQual<FunctionProtoType>
+ LT = C.getCanonicalType(LHS->getType()).getAs<FunctionProtoType>(),
+ RT = C.getCanonicalType(RHS->getType()).getAs<FunctionProtoType>();
+
+ // Fast-path matches in the canonical types.
+ if (LT == RT) return true;
+
+ // Force the signatures to match. We can't rely on the overrides
+ // list here because there isn't necessarily an inheritance
+ // relationship between the two methods.
+ if (LT.getQualifiers() != RT.getQualifiers() ||
+ LT->getNumArgs() != RT->getNumArgs())
+ return false;
+ for (unsigned I = 0, E = LT->getNumArgs(); I != E; ++I)
+ if (LT->getArgType(I) != RT->getArgType(I))
+ return false;
+ return true;
+}
+
+bool VCallOffsetMap::MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
+ const CXXMethodDecl *RHS) {
+ assert(LHS->isVirtual() && "LHS must be virtual!");
+ assert(RHS->isVirtual() && "LHS must be virtual!");
+
+ // A destructor can share a vcall offset with another destructor.
+ if (isa<CXXDestructorDecl>(LHS))
+ return isa<CXXDestructorDecl>(RHS);
+
+ // FIXME: We need to check more things here.
+
+ // The methods must have the same name.
+ DeclarationName LHSName = LHS->getDeclName();
+ DeclarationName RHSName = RHS->getDeclName();
+ if (LHSName != RHSName)
+ return false;
+
+ // And the same signatures.
+ return HasSameVirtualSignature(LHS, RHS);
+}
+
+bool VCallOffsetMap::AddVCallOffset(const CXXMethodDecl *MD,
+ int64_t OffsetOffset) {
+ // Check if we can reuse an offset.
+ for (unsigned I = 0, E = Offsets.size(); I != E; ++I) {
+ if (MethodsCanShareVCallOffset(Offsets[I].first, MD))
+ return false;
+ }
+
+ // Add the offset.
+ Offsets.push_back(MethodAndOffsetPairTy(MD, OffsetOffset));
+ return true;
+}
+
+int64_t VCallOffsetMap::getVCallOffsetOffset(const CXXMethodDecl *MD) {
+ // Look for an offset.
+ for (unsigned I = 0, E = Offsets.size(); I != E; ++I) {
+ if (MethodsCanShareVCallOffset(Offsets[I].first, MD))
+ return Offsets[I].second;
+ }
+
+ assert(false && "Should always find a vcall offset offset!");
+ return 0;
+}
+
+/// VCallAndVBaseOffsetBuilder - Class for building vcall and vbase offsets.
+class VCallAndVBaseOffsetBuilder {
+ /// MostDerivedClass - The most derived class for which we're building vcall
+ /// and vbase offsets.
+ const CXXRecordDecl *MostDerivedClass;
+
+ /// LayoutClass - The class we're using for layout information. Will be
+ /// different than the most derived class if we're building a construction
+ /// vtable.
+ const CXXRecordDecl *LayoutClass;
+
+ /// Context - The ASTContext which we will use for layout information.
+ ASTContext &Context;
+
+ /// Components - vcall and vbase offset components
+ typedef llvm::SmallVector<VtableComponent, 64> VtableComponentVectorTy;
+ VtableComponentVectorTy Components;
+
+ /// VisitedVirtualBases - Visited virtual bases.
+ llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
+
+ /// VCallOffsets - Keeps track of vcall offsets.
+ VCallOffsetMap VCallOffsets;
+
+ /// FinalOverriders - The final overriders of the most derived class.
+ /// (Can be null when we're not building a vtable of the most derived class).
+ const FinalOverriders *Overriders;
+
+ /// AddVCallAndVBaseOffsets - Add vcall offsets and vbase offsets for the
+ /// given base subobject.
+ void AddVCallAndVBaseOffsets(BaseSubobject Base, bool BaseIsVirtual,
+ uint64_t RealBaseOffset);
+
+ /// AddVCallOffsets - Add vcall offsets for the given base subobject.
+ void AddVCallOffsets(BaseSubobject Base, uint64_t VBaseOffset);
+
+ /// AddVBaseOffsets - Add vbase offsets for the given class.
+ void AddVBaseOffsets(const CXXRecordDecl *Base, uint64_t OffsetInLayoutClass);
+
+public:
+ VCallAndVBaseOffsetBuilder(const CXXRecordDecl *MostDerivedClass,
+ const CXXRecordDecl *LayoutClass,
+ const FinalOverriders *Overriders,
+ BaseSubobject Base, bool BaseIsVirtual,
+ uint64_t OffsetInLayoutClass)
+ : MostDerivedClass(MostDerivedClass), LayoutClass(LayoutClass),
+ Context(MostDerivedClass->getASTContext()), Overriders(Overriders) {
+
+ // Add vcall and vbase offsets.
+ AddVCallAndVBaseOffsets(Base, BaseIsVirtual, OffsetInLayoutClass);
+ }
+
+ /// Methods for iterating over the components.
+ typedef VtableComponentVectorTy::const_reverse_iterator const_iterator;
+ const_iterator components_begin() const { return Components.rbegin(); }
+ const_iterator components_end() const { return Components.rend(); }
+
+ const VCallOffsetMap& getVCallOffsets() const { return VCallOffsets; }
+};
+
+void
+VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base,
+ bool BaseIsVirtual,
+ uint64_t RealBaseOffset) {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base.getBase());
+
+ // Itanium C++ ABI 2.5.2:
+ // ..in classes sharing a virtual table with a primary base class, the vcall
+ // and vbase offsets added by the derived class all come before the vcall
+ // and vbase offsets required by the base class, so that the latter may be
+ // laid out as required by the base class without regard to additions from
+ // the derived class(es).
+
+ // (Since we're emitting the vcall and vbase offsets in reverse order, we'll
+ // emit them for the primary base first).
+ if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
+ bool PrimaryBaseIsVirtual = Layout.getPrimaryBaseWasVirtual();
+
+ uint64_t PrimaryBaseOffset;
+
+ // Get the base offset of the primary base.
+ if (PrimaryBaseIsVirtual) {
+ assert(Layout.getVBaseClassOffset(PrimaryBase) == 0 &&
+ "Primary vbase should have a zero offset!");
+
+ const ASTRecordLayout &MostDerivedClassLayout =
+ Context.getASTRecordLayout(MostDerivedClass);
+
+ PrimaryBaseOffset =
+ MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
+ } else {
+ assert(Layout.getBaseClassOffset(PrimaryBase) == 0 &&
+ "Primary base should have a zero offset!");
+
+ PrimaryBaseOffset = Base.getBaseOffset();
+ }
+
+ AddVCallAndVBaseOffsets(BaseSubobject(PrimaryBase, PrimaryBaseOffset),
+ PrimaryBaseIsVirtual, RealBaseOffset);
+ }
+
+ AddVBaseOffsets(Base.getBase(), RealBaseOffset);
+
+ // We only want to add vcall offsets for virtual bases.
+ if (BaseIsVirtual)
+ AddVCallOffsets(Base, RealBaseOffset);
+}
+
+void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
+ uint64_t VBaseOffset) {
+ const CXXRecordDecl *RD = Base.getBase();
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+
+ // Handle the primary base first.
+ if (PrimaryBase) {
+ uint64_t PrimaryBaseOffset;
+
+ // Get the base offset of the primary base.
+ if (Layout.getPrimaryBaseWasVirtual()) {
+ assert(Layout.getVBaseClassOffset(PrimaryBase) == 0 &&
+ "Primary vbase should have a zero offset!");
+
+ const ASTRecordLayout &MostDerivedClassLayout =
+ Context.getASTRecordLayout(MostDerivedClass);
+
+ PrimaryBaseOffset =
+ MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
+ } else {
+ assert(Layout.getBaseClassOffset(PrimaryBase) == 0 &&
+ "Primary base should have a zero offset!");
+
+ PrimaryBaseOffset = Base.getBaseOffset();
+ }
+
+ AddVCallOffsets(BaseSubobject(PrimaryBase, PrimaryBaseOffset),
+ VBaseOffset);
+ }
+
+ // Add the vcall offsets.
+ for (CXXRecordDecl::method_iterator I = RD->method_begin(),
+ E = RD->method_end(); I != E; ++I) {
+ const CXXMethodDecl *MD = *I;
+
+ if (!MD->isVirtual())
+ continue;
+
+ // OffsetIndex is the index of this vcall offset, relative to the vtable
+ // address point. (We subtract 3 to account for the information just
+ // above the address point, the RTTI info, the offset to top, and the
+ // vcall offset itself).
+ int64_t OffsetIndex = -(int64_t)(3 + Components.size());
+
+ // FIXME: We shouldn't use / 8 here.
+ int64_t OffsetOffset = OffsetIndex *
+ (int64_t)Context.Target.getPointerWidth(0) / 8;
+
+ // Don't add a vcall offset if we already have one for this member function
+ // signature.
+ if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset))
+ continue;
+
+ int64_t Offset = 0;
+
+ if (Overriders) {
+ // Get the final overrider.
+ FinalOverriders::OverriderInfo Overrider =
+ Overriders->getOverrider(Base, MD);
+
+ /// The vcall offset is the offset from the virtual base to the object
+ /// where the function was overridden.
+ // FIXME: We should not use / 8 here.
+ Offset = (int64_t)(Overrider.Offset - VBaseOffset) / 8;
+ }
+
+ Components.push_back(VtableComponent::MakeVCallOffset(Offset));
+ }
+
+ // And iterate over all non-virtual bases (ignoring the primary base).
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+
+ if (I->isVirtual())
+ continue;
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+ if (BaseDecl == PrimaryBase)
+ continue;
+
+ // Get the base offset of this base.
+ uint64_t BaseOffset = Base.getBaseOffset() +
+ Layout.getBaseClassOffset(BaseDecl);
+
+ AddVCallOffsets(BaseSubobject(BaseDecl, BaseOffset), VBaseOffset);
+ }
+}
+
+void VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD,
+ uint64_t OffsetInLayoutClass) {
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+
+ // Add vbase offsets.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Check if this is a virtual base that we haven't visited before.
+ if (I->isVirtual() && VisitedVirtualBases.insert(BaseDecl)) {
+ // FIXME: We shouldn't use / 8 here.
+ int64_t Offset =
+ (int64_t)(LayoutClassLayout.getVBaseClassOffset(BaseDecl) -
+ OffsetInLayoutClass) / 8;
+
+ Components.push_back(VtableComponent::MakeVBaseOffset(Offset));
+ }
+
+ // Check the base class looking for more vbase offsets.
+ AddVBaseOffsets(BaseDecl, OffsetInLayoutClass);
+ }
+}
+
/// VtableBuilder - Class for building vtable layout information.
class VtableBuilder {
public:
- /// PrimaryBasesSetTy - A set of direct and indirect primary bases.
- typedef llvm::SmallPtrSet<const CXXRecordDecl *, 8> PrimaryBasesSetTy;
-
+ /// PrimaryBasesSetVectorTy - A set vector of direct and indirect
+ /// primary bases.
+ typedef llvm::SmallSetVector<const CXXRecordDecl *, 8>
+ PrimaryBasesSetVectorTy;
+
private:
/// VtableInfo - Global vtable information.
CGVtableInfo &VtableInfo;
@@ -739,15 +1036,28 @@ private:
/// vtable.
const CXXRecordDecl *MostDerivedClass;
+ /// MostDerivedClassOffset - If we're building a construction vtable, this
+ /// holds the offset from the layout class to the most derived class.
+ const uint64_t MostDerivedClassOffset;
+
+ /// MostDerivedClassIsVirtual - Whether the most derived class is a virtual
+ /// base. (This only makes sense when building a construction vtable).
+ bool MostDerivedClassIsVirtual;
+
+ /// LayoutClass - The class we're using for layout information. Will be
+ /// different than the most derived class if we're building a construction
+ /// vtable.
+ const CXXRecordDecl *LayoutClass;
+
/// Context - The ASTContext which we will use for layout information.
ASTContext &Context;
/// FinalOverriders - The final overriders of the most derived class.
- FinalOverriders Overriders;
+ const FinalOverriders Overriders;
- /// VCallAndVBaseOffsets - The vcall and vbase offset, of the vtable we're
- // building (in reverse order).
- llvm::SmallVector<VtableComponent, 64> VCallAndVBaseOffsets;
+ /// VCallOffsetsForVBases - Keeps track of vcall offsets for the virtual
+ /// bases in this vtable.
+ llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
/// Components - The components of the vtable being built.
llvm::SmallVector<VtableComponent, 64> Components;
@@ -761,7 +1071,7 @@ private:
/// nearest virtual base.
int64_t NonVirtual;
- /// VBaseOffsetOffset - The offset, in bytes, relative to the address point
+ /// VBaseOffsetOffset - The offset (in bytes), relative to the address point
/// of the virtual base class offset.
int64_t VBaseOffsetOffset;
@@ -774,72 +1084,159 @@ private:
llvm::SmallVector<std::pair<uint64_t, ReturnAdjustment>, 16>
ReturnAdjustments;
+ /// MethodInfo - Contains information about a method in a vtable.
+ /// (Used for computing 'this' pointer adjustment thunks.
+ struct MethodInfo {
+ /// BaseOffset - The base offset of this method.
+ const uint64_t BaseOffset;
+
+ /// VtableIndex - The index in the vtable that this method has.
+ /// (For destructors, this is the index of the complete destructor).
+ const uint64_t VtableIndex;
+
+ MethodInfo(uint64_t BaseOffset, uint64_t VtableIndex)
+ : BaseOffset(BaseOffset), VtableIndex(VtableIndex) { }
+
+ MethodInfo() : BaseOffset(0), VtableIndex(0) { }
+ };
+
+ typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
+
+ /// MethodInfoMap - The information for all methods in the vtable we're
+ /// currently building.
+ MethodInfoMapTy MethodInfoMap;
+
/// ThisAdjustment - A 'this' pointer adjustment thunk.
struct ThisAdjustment {
/// NonVirtual - The non-virtual adjustment from the derived object to its
/// nearest virtual base.
int64_t NonVirtual;
- /// FIXME: Add VCallOffsetOffset here.
+ /// VCallOffsetOffset - The offset (in bytes), relative to the address point,
+ /// of the virtual call offset.
+ int64_t VCallOffsetOffset;
- ThisAdjustment() : NonVirtual(0) { }
+ ThisAdjustment() : NonVirtual(0), VCallOffsetOffset(0) { }
- bool isEmpty() const { return !NonVirtual; }
+ bool isEmpty() const { return !NonVirtual && !VCallOffsetOffset; }
};
/// ThisAdjustments - The 'this' pointer adjustments needed in this vtable.
llvm::SmallVector<std::pair<uint64_t, ThisAdjustment>, 16>
ThisAdjustments;
+
+ /// ComputeThisAdjustments - Compute the 'this' pointer adjustments for the
+ /// part of the vtable we're currently building.
+ void ComputeThisAdjustments();
typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
- /// AddVCallAndVBaseOffsets - Add vcall offsets and vbase offsets for the
- /// given class.
- void AddVCallAndVBaseOffsets(const CXXRecordDecl *RD, int64_t OffsetToTop,
- VisitedVirtualBasesSetTy &VBases);
-
- /// AddVBaseOffsets - Add vbase offsets for the given class.
- void AddVBaseOffsets(const CXXRecordDecl *RD, int64_t OffsetToTop,
- VisitedVirtualBasesSetTy &VBases);
+ /// PrimaryVirtualBases - All known virtual bases who are a primary base of
+ /// some other base.
+ VisitedVirtualBasesSetTy PrimaryVirtualBases;
/// ComputeReturnAdjustment - Compute the return adjustment given a return
/// adjustment base offset.
- ReturnAdjustment ComputeReturnAdjustment(FinalOverriders::BaseOffset Offset);
+ ReturnAdjustment ComputeReturnAdjustment(BaseOffset Offset);
- /// ComputeThisAdjustment - Compute the 'this' pointer adjustment given a
- /// 'this' pointer adjustment base offset.
- ThisAdjustment ComputeThisAdjustment(FinalOverriders::BaseOffset Offset);
+ /// ComputeThisAdjustmentBaseOffset - Compute the base offset for adjusting
+ /// the 'this' pointer from the base subobject to the derived subobject.
+ BaseOffset ComputeThisAdjustmentBaseOffset(BaseSubobject Base,
+ BaseSubobject Derived) const;
+
+ /// ComputeThisAdjustment - Compute the 'this' pointer adjustment for the
+ /// given virtual member function and the 'this' pointer adjustment base
+ /// offset.
+ ThisAdjustment ComputeThisAdjustment(const CXXMethodDecl *MD,
+ BaseOffset Offset);
/// AddMethod - Add a single virtual member function to the vtable
/// components vector.
- void AddMethod(const CXXMethodDecl *MD, ReturnAdjustment ReturnAdjustment,
- ThisAdjustment ThisAdjustment);
+ void AddMethod(const CXXMethodDecl *MD, ReturnAdjustment ReturnAdjustment);
+ /// IsOverriderUsed - Returns whether the overrider will ever be used in this
+ /// part of the vtable.
+ ///
+ /// Itanium C++ ABI 2.5.2:
+ ///
+ /// struct A { virtual void f(); };
+ /// struct B : virtual public A { int i; };
+ /// struct C : virtual public A { int j; };
+ /// struct D : public B, public C {};
+ ///
+ /// When B and C are declared, A is a primary base in each case, so although
+ /// vcall offsets are allocated in the A-in-B and A-in-C vtables, no this
+ /// adjustment is required and no thunk is generated. However, inside D
+ /// objects, A is no longer a primary base of C, so if we allowed calls to
+ /// C::f() to use the copy of A's vtable in the C subobject, we would need
+ /// to adjust this from C* to B::A*, which would require a third-party
+ /// thunk. Since we require that a call to C::f() first convert to A*,
+ /// C-in-D's copy of A's vtable is never referenced, so this is not
+ /// necessary.
+ bool IsOverriderUsed(BaseSubobject Base,
+ BaseSubobject FirstBaseInPrimaryBaseChain,
+ uint64_t OffsetInLayoutClass,
+ FinalOverriders::OverriderInfo Overrider) const;
+
/// AddMethods - Add the methods of this base subobject and all its
/// primary bases to the vtable components vector.
- void AddMethods(BaseSubobject Base, PrimaryBasesSetTy &PrimaryBases);
-
- /// LayoutVtable - Layout a vtable and all its secondary vtables.
- void LayoutVtable(BaseSubobject Base);
+ void AddMethods(BaseSubobject Base, BaseSubobject FirstBaseInPrimaryBaseChain,
+ uint64_t OffsetInLayoutClass,
+ PrimaryBasesSetVectorTy &PrimaryBases);
+
+ // LayoutVtable - Layout the vtable for the given base class, including its
+ // secondary vtables and any vtables for virtual bases.
+ void LayoutVtable();
+
+ /// LayoutPrimaryAndSecondaryVtables - Layout the primary vtable for the
+ /// given base subobject, as well as all its secondary vtables.
+ void LayoutPrimaryAndSecondaryVtables(BaseSubobject Base,
+ bool BaseIsVirtual,
+ uint64_t OffsetInLayoutClass);
+ /// LayoutSecondaryVtables - Layout the secondary vtables for the given base
+ /// subobject.
+ void LayoutSecondaryVtables(BaseSubobject Base, uint64_t OffsetInLayoutClass);
+
+ /// DeterminePrimaryVirtualBases - Determine the primary virtual bases in this
+ /// class hierarchy.
+ void DeterminePrimaryVirtualBases(const CXXRecordDecl *RD,
+ VisitedVirtualBasesSetTy &VBases);
+
+ /// LayoutVtablesForVirtualBases - Layout vtables for all virtual bases of the
+ /// given base (excluding any primary bases).
+ void LayoutVtablesForVirtualBases(const CXXRecordDecl *RD,
+ VisitedVirtualBasesSetTy &VBases);
+
+ /// isBuildingConstructionVtable - Return whether this vtable builder is
+ /// building a construction vtable.
+ bool isBuildingConstructorVtable() const {
+ return MostDerivedClass != LayoutClass;
+ }
+
public:
- VtableBuilder(CGVtableInfo &VtableInfo, const CXXRecordDecl *MostDerivedClass)
- : VtableInfo(VtableInfo), MostDerivedClass(MostDerivedClass),
- Context(MostDerivedClass->getASTContext()), Overriders(MostDerivedClass) {
+ VtableBuilder(CGVtableInfo &VtableInfo, const CXXRecordDecl *MostDerivedClass,
+ uint64_t MostDerivedClassOffset, bool MostDerivedClassIsVirtual,
+ const CXXRecordDecl *LayoutClass)
+ : VtableInfo(VtableInfo), MostDerivedClass(MostDerivedClass),
+ MostDerivedClassOffset(MostDerivedClassOffset),
+ MostDerivedClassIsVirtual(MostDerivedClassIsVirtual),
+ LayoutClass(LayoutClass), Context(MostDerivedClass->getASTContext()),
+ Overriders(MostDerivedClass) {
- LayoutVtable(BaseSubobject(MostDerivedClass, 0));
+ LayoutVtable();
}
/// dumpLayout - Dump the vtable layout.
void dumpLayout(llvm::raw_ostream&);
};
-/// OverridesMethodInPrimaryBase - Checks whether whether this virtual member
-/// function overrides a member function in a direct or indirect primary base.
+/// OverridesMethodInBases - Checks whether whether this virtual member
+/// function overrides a member function in any of the given bases.
/// Returns the overridden member function, or null if none was found.
static const CXXMethodDecl *
-OverridesMethodInPrimaryBase(const CXXMethodDecl *MD,
- VtableBuilder::PrimaryBasesSetTy &PrimaryBases) {
+OverridesMethodInBases(const CXXMethodDecl *MD,
+ VtableBuilder::PrimaryBasesSetVectorTy &Bases) {
for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
E = MD->end_overridden_methods(); I != E; ++I) {
const CXXMethodDecl *OverriddenMD = *I;
@@ -847,15 +1244,77 @@ OverridesMethodInPrimaryBase(const CXXMethodDecl *MD,
assert(OverriddenMD->isCanonicalDecl() &&
"Should have the canonical decl of the overridden RD!");
- if (PrimaryBases.count(OverriddenRD))
+ if (Bases.count(OverriddenRD))
return OverriddenMD;
}
return 0;
}
+void VtableBuilder::ComputeThisAdjustments() {
+ std::map<uint64_t, ThisAdjustment> SortedThisAdjustments;
+
+ // Now go through the method info map and see if any of the methods need
+ // 'this' pointer adjustments.
+ for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(),
+ E = MethodInfoMap.end(); I != E; ++I) {
+ const CXXMethodDecl *MD = I->first;
+ const MethodInfo &MethodInfo = I->second;
+
+ BaseSubobject OverriddenBaseSubobject(MD->getParent(),
+ MethodInfo.BaseOffset);
+
+ // Get the final overrider for this method.
+ FinalOverriders::OverriderInfo Overrider =
+ Overriders.getOverrider(OverriddenBaseSubobject, MD);
+
+ // Check if we need an adjustment.
+ if (Overrider.Offset == (int64_t)MethodInfo.BaseOffset)
+ continue;
+
+ uint64_t VtableIndex = MethodInfo.VtableIndex;
+
+ // Ignore adjustments for pure virtual member functions.
+ if (Overrider.Method->isPure())
+ continue;
+
+ // Ignore adjustments for unused function pointers.
+ if (Components[VtableIndex].getKind() ==
+ VtableComponent::CK_UnusedFunctionPointer)
+ continue;
+
+ BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(),
+ Overrider.Offset);
+
+ // Compute the adjustment offset.
+ BaseOffset ThisAdjustmentOffset =
+ ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
+ OverriderBaseSubobject);
+
+ // Then compute the adjustment itself.
+ ThisAdjustment ThisAdjustment = ComputeThisAdjustment(Overrider.Method,
+ ThisAdjustmentOffset);
+
+ // Add it.
+ SortedThisAdjustments.insert(std::make_pair(VtableIndex, ThisAdjustment));
+
+ if (isa<CXXDestructorDecl>(MD)) {
+ // Add an adjustment for the deleting destructor as well.
+ SortedThisAdjustments.insert(std::make_pair(VtableIndex + 1,
+ ThisAdjustment));
+ }
+ }
+
+ /// Clear the method info map.
+ MethodInfoMap.clear();
+
+ // Add the sorted elements.
+ ThisAdjustments.append(SortedThisAdjustments.begin(),
+ SortedThisAdjustments.end());
+}
+
VtableBuilder::ReturnAdjustment
-VtableBuilder::ComputeReturnAdjustment(FinalOverriders::BaseOffset Offset) {
+VtableBuilder::ComputeReturnAdjustment(BaseOffset Offset) {
ReturnAdjustment Adjustment;
if (!Offset.isEmpty()) {
@@ -876,79 +1335,96 @@ VtableBuilder::ComputeReturnAdjustment(FinalOverriders::BaseOffset Offset) {
return Adjustment;
}
-VtableBuilder::ThisAdjustment
-VtableBuilder::ComputeThisAdjustment(FinalOverriders::BaseOffset Offset) {
- ThisAdjustment Adjustment;
+BaseOffset
+VtableBuilder::ComputeThisAdjustmentBaseOffset(BaseSubobject Base,
+ BaseSubobject Derived) const {
+ const CXXRecordDecl *BaseRD = Base.getBase();
+ const CXXRecordDecl *DerivedRD = Derived.getBase();
- if (!Offset.isEmpty()) {
- assert(!Offset.VirtualBase && "FIXME: Handle virtual bases!");
- Adjustment.NonVirtual = Offset.NonVirtualOffset;
+ CXXBasePaths Paths(/*FindAmbiguities=*/true,
+ /*RecordPaths=*/true, /*DetectVirtual=*/true);
+
+ if (!const_cast<CXXRecordDecl *>(DerivedRD)->
+ isDerivedFrom(const_cast<CXXRecordDecl *>(BaseRD), Paths)) {
+ assert(false && "Class must be derived from the passed in base class!");
+ return BaseOffset();
}
-
- return Adjustment;
-}
-void
-VtableBuilder::AddVCallAndVBaseOffsets(const CXXRecordDecl *RD,
- int64_t OffsetToTop,
- VisitedVirtualBasesSetTy &VBases) {
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ // We have to go through all the paths, and see which one leads us to the
+ // right base subobject.
+ for (CXXBasePaths::const_paths_iterator I = Paths.begin(), E = Paths.end();
+ I != E; ++I) {
+ BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, *I);
+
+ // FIXME: Should not use * 8 here.
+ uint64_t OffsetToBaseSubobject = Offset.NonVirtualOffset * 8;
+
+ if (Offset.VirtualBase) {
+ // If we have a virtual base class, the non-virtual offset is relative
+ // to the virtual base class offset.
+ const ASTRecordLayout &MostDerivedClassLayout =
+ Context.getASTRecordLayout(MostDerivedClass);
+
+ /// Get the virtual base offset, relative to the most derived class
+ /// layout.
+ OffsetToBaseSubobject +=
+ MostDerivedClassLayout.getVBaseClassOffset(Offset.VirtualBase);
+ } else {
+ // Otherwise, the non-virtual offset is relative to the derived class
+ // offset.
+ OffsetToBaseSubobject += Derived.getBaseOffset();
+ }
+
+ // Check if this path gives us the right base subobject.
+ if (OffsetToBaseSubobject == Base.getBaseOffset()) {
+ // Since we're going from the base class _to_ the derived class, we'll
+ // invert the non-virtual offset here.
+ Offset.NonVirtualOffset = -Offset.NonVirtualOffset;
+ return Offset;
+ }
+ }
- // Itanium C++ ABI 2.5.2:
- // ..in classes sharing a virtual table with a primary base class, the vcall
- // and vbase offsets added by the derived class all come before the vcall
- // and vbase offsets required by the base class, so that the latter may be
- // laid out as required by the base class without regard to additions from
- // the derived class(es).
-
- // (Since we're emitting the vcall and vbase offsets in reverse order, we'll
- // emit them for the primary base first).
- if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase())
- AddVCallAndVBaseOffsets(PrimaryBase, OffsetToTop, VBases);
-
- AddVBaseOffsets(RD, OffsetToTop, VBases);
+ return BaseOffset();
}
+
-void VtableBuilder::AddVBaseOffsets(const CXXRecordDecl *RD,
- int64_t OffsetToTop,
- VisitedVirtualBasesSetTy &VBases) {
- const ASTRecordLayout &MostDerivedClassLayout =
- Context.getASTRecordLayout(MostDerivedClass);
-
- // Add vbase offsets.
- for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
- E = RD->bases_end(); I != E; ++I) {
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
-
- // Check if this is a virtual base that we haven't visited before.
- if (I->isVirtual() && VBases.insert(BaseDecl)) {
- // FIXME: We shouldn't use / 8 here.
- uint64_t Offset =
- OffsetToTop + MostDerivedClassLayout.getVBaseClassOffset(BaseDecl) / 8;
-
- VCallAndVBaseOffsets.push_back(VtableComponent::MakeVBaseOffset(Offset));
+VtableBuilder::ThisAdjustment
+VtableBuilder::ComputeThisAdjustment(const CXXMethodDecl *MD,
+ BaseOffset Offset) {
+ ThisAdjustment Adjustment;
+
+ if (!Offset.isEmpty()) {
+ if (Offset.VirtualBase) {
+ // Get the vcall offset map for this virtual base.
+ VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
+
+ if (VCallOffsets.empty()) {
+ // We don't have vcall offsets for this virtual base, go ahead and
+ // build them.
+ VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClass,
+ /*FinalOverriders=*/0,
+ BaseSubobject(Offset.VirtualBase, 0),
+ /*BaseIsVirtual=*/true,
+ /*OffsetInLayoutClass=*/0);
+
+ VCallOffsets = Builder.getVCallOffsets();
+ }
+
+ Adjustment.VCallOffsetOffset = VCallOffsets.getVCallOffsetOffset(MD);
}
-
- // Check the base class looking for more vbase offsets.
- AddVBaseOffsets(BaseDecl, OffsetToTop, VBases);
+
+ Adjustment.NonVirtual = Offset.NonVirtualOffset;
}
+
+ return Adjustment;
}
void
VtableBuilder::AddMethod(const CXXMethodDecl *MD,
- ReturnAdjustment ReturnAdjustment,
- ThisAdjustment ThisAdjustment) {
+ ReturnAdjustment ReturnAdjustment) {
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
assert(ReturnAdjustment.isEmpty() &&
"Destructor can't have return adjustment!");
- // Add the 'this' pointer adjustments if necessary.
- if (!ThisAdjustment.isEmpty()) {
- ThisAdjustments.push_back(std::make_pair(Components.size(),
- ThisAdjustment));
- ThisAdjustments.push_back(std::make_pair(Components.size() + 1,
- ThisAdjustment));
- }
// Add both the complete destructor and the deleting destructor.
Components.push_back(VtableComponent::MakeCompleteDtor(DD));
@@ -959,30 +1435,157 @@ VtableBuilder::AddMethod(const CXXMethodDecl *MD,
ReturnAdjustments.push_back(std::make_pair(Components.size(),
ReturnAdjustment));
- // Add the 'this' pointer adjustment if necessary.
- if (!ThisAdjustment.isEmpty())
- ThisAdjustments.push_back(std::make_pair(Components.size(),
- ThisAdjustment));
-
// Add the function.
Components.push_back(VtableComponent::MakeFunction(MD));
}
}
+/// OverridesIndirectMethodInBase - Return whether the given member function
+/// overrides any methods in the set of given bases.
+/// Unlike OverridesMethodInBase, this checks "overriders of overriders".
+/// For example, if we have:
+///
+/// struct A { virtual void f(); }
+/// struct B : A { virtual void f(); }
+/// struct C : B { virtual void f(); }
+///
+/// OverridesIndirectMethodInBase will return true if given C::f as the method
+/// and { A } as the set of bases.
+static bool
+OverridesIndirectMethodInBases(const CXXMethodDecl *MD,
+ VtableBuilder::PrimaryBasesSetVectorTy &Bases) {
+ for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
+ E = MD->end_overridden_methods(); I != E; ++I) {
+ const CXXMethodDecl *OverriddenMD = *I;
+ const CXXRecordDecl *OverriddenRD = OverriddenMD->getParent();
+ assert(OverriddenMD->isCanonicalDecl() &&
+ "Should have the canonical decl of the overridden RD!");
+
+ if (Bases.count(OverriddenRD))
+ return true;
+
+ // Check "indirect overriders".
+ if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
+ return true;
+ }
+
+ return false;
+}
+
+bool
+VtableBuilder::IsOverriderUsed(BaseSubobject Base,
+ BaseSubobject FirstBaseInPrimaryBaseChain,
+ uint64_t OffsetInLayoutClass,
+ FinalOverriders::OverriderInfo Overrider) const {
+ // If the base and the first base in the primary base chain have the same
+ // offsets, then this overrider will be used.
+ if (Base.getBaseOffset() == OffsetInLayoutClass)
+ return true;
+
+ // We know now that Base (or a direct or indirect base of it) is a primary
+ // base in part of the class hierarchy, but not a primary base in the most
+ // derived class.
+
+ // If the overrider is the first base in the primary base chain, we know
+ // that the overrider will be used.
+ if (Overrider.Method->getParent() == FirstBaseInPrimaryBaseChain.getBase())
+ return true;
+
+ VtableBuilder::PrimaryBasesSetVectorTy PrimaryBases;
+
+ const CXXRecordDecl *RD = FirstBaseInPrimaryBaseChain.getBase();
+ PrimaryBases.insert(RD);
+
+ // Now traverse the base chain, starting with the first base, until we find
+ // the base that is no longer a primary base.
+ while (true) {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+
+ if (!PrimaryBase)
+ break;
+
+ if (Layout.getPrimaryBaseWasVirtual()) {
+ assert(Layout.getVBaseClassOffset(PrimaryBase) == 0 &&
+ "Primary base should always be at offset 0!");
+
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+
+ // Now check if this is the primary base that is not a primary base in the
+ // most derived class.
+ if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) !=
+ OffsetInLayoutClass) {
+ // We found it, stop walking the chain.
+ break;
+ }
+ } else {
+ assert(Layout.getBaseClassOffset(PrimaryBase) == 0 &&
+ "Primary base should always be at offset 0!");
+ }
+
+ if (!PrimaryBases.insert(PrimaryBase))
+ assert(false && "Found a duplicate primary base!");
+
+ RD = PrimaryBase;
+ }
+
+ // If the final overrider is an override of one of the primary bases,
+ // then we know that it will be used.
+ return OverridesIndirectMethodInBases(Overrider.Method, PrimaryBases);
+}
+
+/// FindNearestOverriddenMethod - Given a method, returns the overridden method
+/// from the nearest base. Returns null if no method was found.
+static const CXXMethodDecl *
+FindNearestOverriddenMethod(const CXXMethodDecl *MD,
+ VtableBuilder::PrimaryBasesSetVectorTy &Bases) {
+ for (int I = Bases.size(), E = 0; I != E; --I) {
+ const CXXRecordDecl *PrimaryBase = Bases[I - 1];
+
+ // Now check the overriden methods.
+ for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
+ E = MD->end_overridden_methods(); I != E; ++I) {
+ const CXXMethodDecl *OverriddenMD = *I;
+
+ // We found our overridden method.
+ if (OverriddenMD->getParent() == PrimaryBase)
+ return OverriddenMD;
+ }
+ }
+
+ return 0;
+}
+
void
-VtableBuilder::AddMethods(BaseSubobject Base, PrimaryBasesSetTy &PrimaryBases) {
+VtableBuilder::AddMethods(BaseSubobject Base,
+ BaseSubobject FirstBaseInPrimaryBaseChain,
+ uint64_t OffsetInLayoutClass,
+ PrimaryBasesSetVectorTy &PrimaryBases) {
const CXXRecordDecl *RD = Base.getBase();
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
- if (Layout.getPrimaryBaseWasVirtual())
- assert(false && "FIXME: Handle vbases here.");
- else
+ uint64_t BaseOffset;
+ if (Layout.getPrimaryBaseWasVirtual()) {
+ assert(Layout.getVBaseClassOffset(PrimaryBase) == 0 &&
+ "Primary vbase should have a zero offset!");
+
+ const ASTRecordLayout &MostDerivedClassLayout =
+ Context.getASTRecordLayout(MostDerivedClass);
+
+ BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
+ } else {
assert(Layout.getBaseClassOffset(PrimaryBase) == 0 &&
"Primary base should have a zero offset!");
-
- AddMethods(BaseSubobject(PrimaryBase, Base.getBaseOffset()), PrimaryBases);
+
+ BaseOffset = Base.getBaseOffset();
+ }
+
+ // FIXME: OffsetInLayoutClass is not right here.
+ AddMethods(BaseSubobject(PrimaryBase, BaseOffset),
+ FirstBaseInPrimaryBaseChain, OffsetInLayoutClass, PrimaryBases);
if (!PrimaryBases.insert(PrimaryBase))
assert(false && "Found a duplicate primary base!");
@@ -1004,47 +1607,90 @@ VtableBuilder::AddMethods(BaseSubobject Base, PrimaryBasesSetTy &PrimaryBases) {
// base. If this is the case, and the return type doesn't require adjustment
// then we can just use the member function from the primary base.
if (const CXXMethodDecl *OverriddenMD =
- OverridesMethodInPrimaryBase(MD, PrimaryBases)) {
+ FindNearestOverriddenMethod(MD, PrimaryBases)) {
if (ComputeReturnAdjustmentBaseOffset(Context, MD,
- OverriddenMD).isEmpty())
+ OverriddenMD).isEmpty()) {
+ // Replace the method info of the overridden method with our own
+ // method.
+ assert(MethodInfoMap.count(OverriddenMD) &&
+ "Did not find the overridden method!");
+ MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
+
+ MethodInfo MethodInfo(Base.getBaseOffset(),
+ OverriddenMethodInfo.VtableIndex);
+
+ assert(!MethodInfoMap.count(MD) &&
+ "Should not have method info for this method yet!");
+
+ MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
+ MethodInfoMap.erase(OverriddenMD);
continue;
+ }
}
+ // Insert the method info for this method.
+ MethodInfo MethodInfo(Base.getBaseOffset(), Components.size());
+
+ assert(!MethodInfoMap.count(MD) &&
+ "Should not have method info for this method yet!");
+ MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
+
+ // Check if this overrider is going to be used.
+ if (!IsOverriderUsed(Base, FirstBaseInPrimaryBaseChain, OffsetInLayoutClass,
+ Overrider)) {
+ const CXXMethodDecl *OverriderMD = Overrider.Method;
+ Components.push_back(VtableComponent::MakeUnusedFunction(OverriderMD));
+ continue;
+ }
+
// Check if this overrider needs a return adjustment.
- FinalOverriders::BaseOffset ReturnAdjustmentOffset =
+ BaseOffset ReturnAdjustmentOffset =
Overriders.getReturnAdjustmentOffset(Base, MD);
ReturnAdjustment ReturnAdjustment =
ComputeReturnAdjustment(ReturnAdjustmentOffset);
- // Check if this overrider needs a 'this' pointer adjustment.
- FinalOverriders::BaseOffset ThisAdjustmentOffset =
- Overriders.getThisAdjustmentOffset(Base, MD);
-
- ThisAdjustment ThisAdjustment = ComputeThisAdjustment(ThisAdjustmentOffset);
-
- AddMethod(Overrider.Method, ReturnAdjustment, ThisAdjustment);
+ AddMethod(Overrider.Method, ReturnAdjustment);
}
}
-void VtableBuilder::LayoutVtable(BaseSubobject Base) {
- const CXXRecordDecl *RD = Base.getBase();
- assert(RD->isDynamicClass() && "class does not have a vtable!");
-
- int64_t OffsetToTop = -(int64_t)Base.getBaseOffset() / 8;
-
- // Add vcall and vbase offsets for this vtable.
+void VtableBuilder::LayoutVtable() {
+ LayoutPrimaryAndSecondaryVtables(BaseSubobject(MostDerivedClass, 0),
+ MostDerivedClassIsVirtual,
+ MostDerivedClassOffset);
+
VisitedVirtualBasesSetTy VBases;
- AddVCallAndVBaseOffsets(RD, OffsetToTop, VBases);
+
+ // Determine the primary virtual bases.
+ DeterminePrimaryVirtualBases(MostDerivedClass, VBases);
+ VBases.clear();
+
+ LayoutVtablesForVirtualBases(MostDerivedClass, VBases);
+}
+
+void
+VtableBuilder::LayoutPrimaryAndSecondaryVtables(BaseSubobject Base,
+ bool BaseIsVirtual,
+ uint64_t OffsetInLayoutClass) {
+ assert(Base.getBase()->isDynamicClass() && "class does not have a vtable!");
- // Reverse them and add them to the vtable components.
- std::reverse(VCallAndVBaseOffsets.begin(), VCallAndVBaseOffsets.end());
- Components.append(VCallAndVBaseOffsets.begin(), VCallAndVBaseOffsets.end());
- VCallAndVBaseOffsets.clear();
+ // Add vcall and vbase offsets for this vtable.
+ VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, LayoutClass, &Overriders,
+ Base, BaseIsVirtual, OffsetInLayoutClass);
+ Components.append(Builder.components_begin(), Builder.components_end());
+ // Check if we need to add these vcall offsets.
+ if (BaseIsVirtual && !Builder.getVCallOffsets().empty()) {
+ VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Base.getBase()];
+
+ if (VCallOffsets.empty())
+ VCallOffsets = Builder.getVCallOffsets();
+ }
+
// Add the offset to top.
- // FIXME: This is not going to be right for construction vtables.
// FIXME: We should not use / 8 here.
+ int64_t OffsetToTop = -(int64_t)(OffsetInLayoutClass -
+ MostDerivedClassOffset) / 8;
Components.push_back(VtableComponent::MakeOffsetToTop(OffsetToTop));
// Next, add the RTTI.
@@ -1053,59 +1699,166 @@ void VtableBuilder::LayoutVtable(BaseSubobject Base) {
uint64_t AddressPoint = Components.size();
// Now go through all virtual member functions and add them.
- PrimaryBasesSetTy PrimaryBases;
- AddMethods(Base, PrimaryBases);
+ PrimaryBasesSetVectorTy PrimaryBases;
+ AddMethods(Base, Base, OffsetInLayoutClass, PrimaryBases);
+
+ // Compute 'this' pointer adjustments.
+ ComputeThisAdjustments();
// Record the address point.
- AddressPoints.insert(std::make_pair(Base, AddressPoint));
+ AddressPoints.insert(std::make_pair(BaseSubobject(Base.getBase(),
+ OffsetInLayoutClass),
+ AddressPoint));
// Record the address points for all primary bases.
- for (PrimaryBasesSetTy::const_iterator I = PrimaryBases.begin(),
+ for (PrimaryBasesSetVectorTy::const_iterator I = PrimaryBases.begin(),
E = PrimaryBases.end(); I != E; ++I) {
const CXXRecordDecl *BaseDecl = *I;
// We know that all the primary bases have the same offset as the base
// subobject.
- BaseSubobject PrimaryBase(BaseDecl, Base.getBaseOffset());
+ BaseSubobject PrimaryBase(BaseDecl, OffsetInLayoutClass);
AddressPoints.insert(std::make_pair(PrimaryBase, AddressPoint));
}
+ // Layout secondary vtables.
+ LayoutSecondaryVtables(Base, OffsetInLayoutClass);
+}
+
+void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base,
+ uint64_t OffsetInLayoutClass) {
+ // Itanium C++ ABI 2.5.2:
+ // Following the primary virtual table of a derived class are secondary
+ // virtual tables for each of its proper base classes, except any primary
+ // base(s) with which it shares its primary virtual table.
+
+ const CXXRecordDecl *RD = Base.getBase();
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
-
- // Layout secondary vtables.
+
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
E = RD->bases_end(); I != E; ++I) {
+ // Ignore virtual bases, we'll emit them later.
+ if (I->isVirtual())
+ continue;
+
const CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
// Ignore bases that don't have a vtable.
if (!BaseDecl->isDynamicClass())
continue;
+
+ // Get the base offset of this base.
+ uint64_t RelativeBaseOffset = Layout.getBaseClassOffset(BaseDecl);
+ uint64_t BaseOffset = Base.getBaseOffset() + RelativeBaseOffset;
- // Ignore the primary base.
- if (BaseDecl == PrimaryBase)
+ uint64_t BaseOffsetInLayoutClass = OffsetInLayoutClass + RelativeBaseOffset;
+
+ // Don't emit a secondary vtable for a primary base. We might however want
+ // to emit secondary vtables for other bases of this base.
+ if (BaseDecl == PrimaryBase) {
+ LayoutSecondaryVtables(BaseSubobject(BaseDecl, BaseOffset),
+ BaseOffsetInLayoutClass);
continue;
+ }
- // Ignore virtual bases, we'll emit them later.
- if (I->isVirtual())
+ // Layout the primary vtable (and any secondary vtables) for this base.
+ LayoutPrimaryAndSecondaryVtables(BaseSubobject(BaseDecl, BaseOffset),
+ /*BaseIsVirtual=*/false,
+ BaseOffsetInLayoutClass);
+ }
+}
+
+void
+VtableBuilder::DeterminePrimaryVirtualBases(const CXXRecordDecl *RD,
+ VisitedVirtualBasesSetTy &VBases) {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ // Check if this base has a primary base.
+ if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
+
+ // Check if it's virtual.
+ if (Layout.getPrimaryBaseWasVirtual()) {
+ bool IsPrimaryVirtualBase = true;
+
+ if (isBuildingConstructorVtable()) {
+ // Check if the base is actually a primary base in the class we use for
+ // layout.
+ // FIXME: Is this check enough?
+ if (MostDerivedClassOffset != 0)
+ IsPrimaryVirtualBase = false;
+ }
+
+ if (IsPrimaryVirtualBase)
+ PrimaryVirtualBases.insert(PrimaryBase);
+ }
+ }
+
+ // Traverse bases, looking for more primary virtual bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ if (I->isVirtual() && !VBases.insert(BaseDecl))
continue;
-
- // Get the base offset of this base.
- uint64_t BaseOffset = Base.getBaseOffset() +
- Layout.getBaseClassOffset(BaseDecl);
- // Layout this secondary vtable.
- LayoutVtable(BaseSubobject(BaseDecl, BaseOffset));
+ DeterminePrimaryVirtualBases(BaseDecl, VBases);
+ }
+}
+
+void
+VtableBuilder::LayoutVtablesForVirtualBases(const CXXRecordDecl *RD,
+ VisitedVirtualBasesSetTy &VBases) {
+ // Itanium C++ ABI 2.5.2:
+ // Then come the virtual base virtual tables, also in inheritance graph
+ // order, and again excluding primary bases (which share virtual tables with
+ // the classes for which they are primary).
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Check if this base needs a vtable. (If it's virtual, not a primary base
+ // of some other class, and we haven't visited it before).
+ if (I->isVirtual() && BaseDecl->isDynamicClass() &&
+ !PrimaryVirtualBases.count(BaseDecl) && VBases.insert(BaseDecl)) {
+ const ASTRecordLayout &MostDerivedClassLayout =
+ Context.getASTRecordLayout(MostDerivedClass);
+ uint64_t BaseOffset =
+ MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
+
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+ uint64_t BaseOffsetInLayoutClass =
+ LayoutClassLayout.getVBaseClassOffset(BaseDecl);
+
+ LayoutPrimaryAndSecondaryVtables(BaseSubobject(BaseDecl, BaseOffset),
+ /*BaseIsVirtual=*/true,
+ BaseOffsetInLayoutClass);
+ }
+
+ // We only need to check the base for virtual base vtables if it actually
+ // has virtual bases.
+ if (BaseDecl->getNumVBases())
+ LayoutVtablesForVirtualBases(BaseDecl, VBases);
}
-
- // FIXME: Emit vtables for virtual bases here.
}
/// dumpLayout - Dump the vtable layout.
void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
-
- Out << "Vtable for '" << MostDerivedClass->getQualifiedNameAsString();
+
+ if (MostDerivedClass == LayoutClass) {
+ Out << "Vtable for '";
+ Out << MostDerivedClass->getQualifiedNameAsString();
+ } else {
+ Out << "Construction vtable for ('";
+ Out << MostDerivedClass->getQualifiedNameAsString() << "', ";
+ // FIXME: Don't use / 8 .
+ Out << MostDerivedClassOffset / 8 << ") in '";
+ Out << LayoutClass->getQualifiedNameAsString();
+ }
Out << "' (" << Components.size() << " entries).\n";
// Iterate through the address points and insert them into a new map where
@@ -1125,37 +1878,6 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
unsigned NextThisAdjustmentIndex = 0;
for (unsigned I = 0, E = Components.size(); I != E; ++I) {
uint64_t Index = I;
-
- if (AddressPointsByIndex.count(I)) {
- if (AddressPointsByIndex.count(Index) == 1) {
- const BaseSubobject &Base = AddressPointsByIndex.find(Index)->second;
-
- // FIXME: Instead of dividing by 8, we should be using CharUnits.
- Out << " -- (" << Base.getBase()->getQualifiedNameAsString();
- Out << ", " << Base.getBaseOffset() / 8 << ") vtable address --\n";
- } else {
- uint64_t BaseOffset =
- AddressPointsByIndex.lower_bound(Index)->second.getBaseOffset();
-
- // We store the class names in a set to get a stable order.
- std::set<std::string> ClassNames;
- for (std::multimap<uint64_t, BaseSubobject>::const_iterator I =
- AddressPointsByIndex.lower_bound(Index), E =
- AddressPointsByIndex.upper_bound(Index); I != E; ++I) {
- assert(I->second.getBaseOffset() == BaseOffset &&
- "Invalid base offset!");
- const CXXRecordDecl *RD = I->second.getBase();
- ClassNames.insert(RD->getQualifiedNameAsString());
- }
-
- for (std::set<std::string>::const_iterator I = ClassNames.begin(),
- E = ClassNames.end(); I != E; ++I) {
- // FIXME: Instead of dividing by 8, we should be using CharUnits.
- Out << " -- (" << *I;
- Out << ", " << BaseOffset / 8 << ") vtable address --\n";
- }
- }
- }
Out << llvm::format("%4d | ", I);
@@ -1163,9 +1885,9 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
// Dump the component.
switch (Component.getKind()) {
- // FIXME: Remove this default case.
- default:
- assert(false && "Unhandled component kind!");
+
+ case VtableComponent::CK_VCallOffset:
+ Out << "vcall_offset (" << Component.getVCallOffset() << ")";
break;
case VtableComponent::CK_VBaseOffset:
@@ -1201,6 +1923,7 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
if (Adjustment.VBaseOffsetOffset)
Out << ", " << Adjustment.VBaseOffsetOffset << " vbase offset offset";
+
Out << ']';
NextReturnAdjustmentIndex++;
@@ -1214,7 +1937,10 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
Out << "\n [this adjustment: ";
Out << Adjustment.NonVirtual << " non-virtual";
-
+
+ if (Adjustment.VCallOffsetOffset)
+ Out << ", " << Adjustment.VCallOffsetOffset << " vcall offset offset";
+
Out << ']';
NextThisAdjustmentIndex++;
@@ -1223,31 +1949,94 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
break;
}
- case VtableComponent::CK_CompleteDtorPointer: {
+ case VtableComponent::CK_CompleteDtorPointer:
+ case VtableComponent::CK_DeletingDtorPointer: {
+ bool IsComplete =
+ Component.getKind() == VtableComponent::CK_CompleteDtorPointer;
+
const CXXDestructorDecl *DD = Component.getDestructorDecl();
- Out << DD->getQualifiedNameAsString() << "() [complete]";
+ Out << DD->getQualifiedNameAsString();
+ if (IsComplete)
+ Out << "() [complete]";
+ else
+ Out << "() [deleting]";
+
if (DD->isPure())
Out << " [pure]";
+ // If this destructor has a 'this' pointer adjustment, dump it.
+ if (NextThisAdjustmentIndex < ThisAdjustments.size() &&
+ ThisAdjustments[NextThisAdjustmentIndex].first == I) {
+ const ThisAdjustment Adjustment =
+ ThisAdjustments[NextThisAdjustmentIndex].second;
+
+ Out << "\n [this adjustment: ";
+ Out << Adjustment.NonVirtual << " non-virtual";
+
+ if (Adjustment.VCallOffsetOffset)
+ Out << ", " << Adjustment.VCallOffsetOffset << " vcall offset offset";
+
+ Out << ']';
+
+ NextThisAdjustmentIndex++;
+ }
+
+
break;
}
- case VtableComponent::CK_DeletingDtorPointer: {
- const CXXDestructorDecl *DD = Component.getDestructorDecl();
-
- Out << DD->getQualifiedNameAsString() << "() [deleting]";
- if (DD->isPure())
- Out << " [pure]";
+ case VtableComponent::CK_UnusedFunctionPointer: {
+ const CXXMethodDecl *MD = Component.getUnusedFunctionDecl();
- break;
+ std::string Str =
+ PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
+ MD);
+ Out << "[unused] " << Str;
+ if (MD->isPure())
+ Out << " [pure]";
}
}
Out << '\n';
+
+ // Dump the next address point.
+ uint64_t NextIndex = Index + 1;
+ if (AddressPointsByIndex.count(NextIndex)) {
+ if (AddressPointsByIndex.count(NextIndex) == 1) {
+ const BaseSubobject &Base =
+ AddressPointsByIndex.find(NextIndex)->second;
+
+ // FIXME: Instead of dividing by 8, we should be using CharUnits.
+ Out << " -- (" << Base.getBase()->getQualifiedNameAsString();
+ Out << ", " << Base.getBaseOffset() / 8 << ") vtable address --\n";
+ } else {
+ uint64_t BaseOffset =
+ AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset();
+
+ // We store the class names in a set to get a stable order.
+ std::set<std::string> ClassNames;
+ for (std::multimap<uint64_t, BaseSubobject>::const_iterator I =
+ AddressPointsByIndex.lower_bound(NextIndex), E =
+ AddressPointsByIndex.upper_bound(NextIndex); I != E; ++I) {
+ assert(I->second.getBaseOffset() == BaseOffset &&
+ "Invalid base offset!");
+ const CXXRecordDecl *RD = I->second.getBase();
+ ClassNames.insert(RD->getQualifiedNameAsString());
+ }
+
+ for (std::set<std::string>::const_iterator I = ClassNames.begin(),
+ E = ClassNames.end(); I != E; ++I) {
+ // FIXME: Instead of dividing by 8, we should be using CharUnits.
+ Out << " -- (" << *I;
+ Out << ", " << BaseOffset / 8 << ") vtable address --\n";
+ }
+ }
+ }
}
-
+
+ Out << '\n';
}
}
@@ -1500,10 +2289,10 @@ private:
// If already set, note the two sets as the same
if (0)
printf("%s::%s same as %s::%s\n",
- PrevU->getParent()->getNameAsCString(),
- PrevU->getNameAsCString(),
- U->getParent()->getNameAsCString(),
- U->getNameAsCString());
+ PrevU->getParent()->getNameAsString().c_str(),
+ PrevU->getNameAsString().c_str(),
+ U->getParent()->getNameAsString().c_str(),
+ U->getNameAsString().c_str());
ForwardUnique[PrevU] = U;
return;
}
@@ -1511,11 +2300,11 @@ private:
// Not set, set it now
if (0)
printf("marking %s::%s %p override as %s::%s\n",
- MD->getParent()->getNameAsCString(),
- MD->getNameAsCString(),
+ MD->getParent()->getNameAsString().c_str(),
+ MD->getNameAsString().c_str(),
(void*)MD,
- U->getParent()->getNameAsCString(),
- U->getNameAsCString());
+ U->getParent()->getNameAsString().c_str(),
+ U->getNameAsString().c_str());
UniqueOverrider[MD] = U;
for (CXXMethodDecl::method_iterator mi = MD->begin_overridden_methods(),
@@ -1537,8 +2326,8 @@ private:
BuildUniqueOverrider(MD, MD);
if (0)
printf("top set is %s::%s %p\n",
- MD->getParent()->getNameAsCString(),
- MD->getNameAsCString(),
+ MD->getParent()->getNameAsString().c_str(),
+ MD->getNameAsString().c_str(),
(void*)MD);
ForwardUnique[MD] = MD;
}
@@ -1573,7 +2362,7 @@ private:
A_t::iterator J = I;
while (++J != E && DclCmp(I, J) == 0)
if (DclIsSame(*I, *J)) {
- if (0) printf("connecting %s\n", (*I)->getNameAsCString());
+ if (0) printf("connecting %s\n", (*I)->getNameAsString().c_str());
ForwardUnique[*J] = *I;
}
}
@@ -1657,7 +2446,7 @@ public:
}
//#define D1(x)
-#define D1(X) do { if (getenv("DEBUG")) { X; } } while (0)
+#define D1(X) do { if (getenv("CLANG_VTABLE_DEBUG")) { X; } } while (0)
void GenerateVBaseOffsets(const CXXRecordDecl *RD, uint64_t Offset,
bool updateVBIndex, Index_t current_vbindex) {
@@ -1801,7 +2590,7 @@ public:
return;
D1(printf(" vfn for %s at %d\n",
- dyn_cast<CXXMethodDecl>(GD.getDecl())->getNameAsCString(),
+ dyn_cast<CXXMethodDecl>(GD.getDecl())->getNameAsString().c_str(),
(int)Methods.size()));
// We didn't find an entry in the vtable that we could use, add a new
@@ -1824,7 +2613,7 @@ public:
idx = VCalls.size()+1;
VCalls.push_back(Offset/8 - CurrentVBaseOffset/8);
D1(printf(" vcall for %s at %d with delta %d\n",
- dyn_cast<CXXMethodDecl>(GD.getDecl())->getNameAsCString(),
+ dyn_cast<CXXMethodDecl>(GD.getDecl())->getNameAsString().c_str(),
(int)-VCalls.size()-3, (int)VCalls[idx-1]));
}
}
@@ -2352,7 +3141,7 @@ void CGVtableInfo::ComputeMethodVtableIndices(const CXXRecordDecl *RD) {
// Collect all the primary bases, so we can check whether methods override
// a method from the base.
- VtableBuilder::PrimaryBasesSetTy PrimaryBases;
+ VtableBuilder::PrimaryBasesSetVectorTy PrimaryBases;
for (ASTRecordLayout::primary_base_info_iterator
I = Layout.primary_base_begin(), E = Layout.primary_base_end();
I != E; ++I)
@@ -2370,7 +3159,7 @@ void CGVtableInfo::ComputeMethodVtableIndices(const CXXRecordDecl *RD) {
// Check if this method overrides a method in the primary base.
if (const CXXMethodDecl *OverriddenMD =
- OverridesMethodInPrimaryBase(MD, PrimaryBases)) {
+ OverridesMethodInBases(MD, PrimaryBases)) {
// Check if converting from the return type of the method to the
// return type of the overridden method requires conversion.
if (ComputeReturnAdjustmentBaseOffset(CGM.getContext(), MD,
@@ -2535,12 +3324,25 @@ CGVtableInfo::GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
bool GenerateDefinition,
const CXXRecordDecl *LayoutClass,
const CXXRecordDecl *RD, uint64_t Offset,
+ bool IsVirtual,
AddressPointsMapTy& AddressPoints) {
- if (GenerateDefinition && CGM.getLangOptions().DumpVtableLayouts &&
- LayoutClass == RD) {
- VtableBuilder Builder(*this, RD);
-
- Builder.dumpLayout(llvm::errs());
+ if (GenerateDefinition) {
+ if (LayoutClass == RD) {
+ assert(!IsVirtual &&
+ "Can't only have a virtual base in construction vtables!");
+ VtableBuilder Builder(*this, RD, Offset,
+ /*MostDerivedClassIsVirtual=*/false,
+ LayoutClass);
+
+ if (CGM.getLangOptions().DumpVtableLayouts)
+ Builder.dumpLayout(llvm::errs());
+ } else if (CGM.getLangOptions().DumpVtableLayouts) {
+ // We only build construction vtables when dumping vtable layouts for now.
+ VtableBuilder Builder(*this, RD, Offset,
+ /*MostDerivedClassIsVirtual=*/IsVirtual,
+ LayoutClass);
+ Builder.dumpLayout(llvm::errs());
+ }
}
llvm::SmallString<256> OutName;
@@ -2601,6 +3403,7 @@ void CGVtableInfo::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
AddressPointsMapTy AddressPoints;
Vtable = GenerateVtable(Linkage, /*GenerateDefinition=*/true, RD, RD, 0,
+ /*IsVirtual=*/false,
AddressPoints);
GenerateVTT(Linkage, /*GenerateDefinition=*/true, RD);
}
@@ -2612,7 +3415,7 @@ llvm::GlobalVariable *CGVtableInfo::getVtable(const CXXRecordDecl *RD) {
AddressPointsMapTy AddressPoints;
Vtable = GenerateVtable(llvm::GlobalValue::ExternalLinkage,
/*GenerateDefinition=*/false, RD, RD, 0,
- AddressPoints);
+ /*IsVirtual=*/false, AddressPoints);
}
return Vtable;
diff --git a/lib/CodeGen/CGVtable.h b/lib/CodeGen/CGVtable.h
index 471d638..6ccb011 100644
--- a/lib/CodeGen/CGVtable.h
+++ b/lib/CodeGen/CGVtable.h
@@ -185,7 +185,7 @@ private:
llvm::GlobalVariable *
GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
bool GenerateDefinition, const CXXRecordDecl *LayoutClass,
- const CXXRecordDecl *RD, uint64_t Offset,
+ const CXXRecordDecl *RD, uint64_t Offset, bool IsVirtual,
AddressPointsMapTy& AddressPoints);
llvm::GlobalVariable *GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
@@ -239,7 +239,8 @@ public:
};
CtorVtableInfo getCtorVtable(const CXXRecordDecl *RD,
- const BaseSubobject &Base);
+ const BaseSubobject &Base,
+ bool BaseIsVirtual);
llvm::GlobalVariable *getVTT(const CXXRecordDecl *RD);
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 5a4f94e..f455827 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -30,7 +30,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
Builder(cgm.getModule().getContext()),
DebugInfo(0), IndirectBranch(0),
SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0),
- CXXThisDecl(0), CXXVTTDecl(0),
+ CXXThisDecl(0), CXXThisValue(0), CXXVTTDecl(0), CXXVTTValue(0),
ConditionalBranchLevel(0), TerminateHandler(0), TrapBB(0),
UniqueAggrDestructorCount(0) {
LLVMIntTy = ConvertType(getContext().IntTy);
@@ -197,7 +197,10 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
Builder.SetInsertPoint(EntryBB);
- QualType FnType = getContext().getFunctionType(RetTy, 0, 0, false, 0);
+ QualType FnType = getContext().getFunctionType(RetTy, 0, 0, false, 0,
+ false, false, 0, 0,
+ /*FIXME?*/false,
+ /*FIXME?*/CC_Default);
// Emit subprogram debug descriptor.
if (CGDebugInfo *DI = getDebugInfo()) {
@@ -216,15 +219,20 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
} else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
hasAggregateLLVMType(CurFnInfo->getReturnType())) {
// Indirect aggregate return; emit returned value directly into sret slot.
- // This reduces code size, and is also affects correctness in C++.
+ // This reduces code size, and affects correctness in C++.
ReturnValue = CurFn->arg_begin();
} else {
- ReturnValue = CreateTempAlloca(ConvertType(RetTy), "retval");
+ ReturnValue = CreateIRTemp(RetTy, "retval");
}
EmitStartEHSpec(CurCodeDecl);
EmitFunctionProlog(*CurFnInfo, CurFn, Args);
+ if (CXXThisDecl)
+ CXXThisValue = Builder.CreateLoad(LocalDeclMap[CXXThisDecl], "this");
+ if (CXXVTTDecl)
+ CXXVTTValue = Builder.CreateLoad(LocalDeclMap[CXXVTTDecl], "vtt");
+
// If any of the arguments have a variably modified type, make sure to
// emit the type size.
for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end();
@@ -236,6 +244,19 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
}
}
+void CodeGenFunction::EmitFunctionBody(FunctionArgList &Args) {
+ const FunctionDecl *FD = cast<FunctionDecl>(CurGD.getDecl());
+
+ Stmt *Body = FD->getBody();
+ if (Body)
+ EmitStmt(Body);
+ else {
+ assert(FD->isImplicit() && "non-implicit function def has no body");
+ assert(FD->isCopyAssignment() && "implicit function not copy assignment");
+ SynthesizeCXXCopyAssignment(Args);
+ }
+}
+
void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) {
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
@@ -246,13 +267,13 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) {
FunctionArgList Args;
CurGD = GD;
- OuterTryBlock = 0;
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
if (MD->isInstance()) {
// Create the implicit 'this' decl.
// FIXME: I'm not entirely sure I like using a fake decl just for code
// generation. Maybe we can come up with a better way?
- CXXThisDecl = ImplicitParamDecl::Create(getContext(), 0, SourceLocation(),
+ CXXThisDecl = ImplicitParamDecl::Create(getContext(), 0,
+ FD->getLocation(),
&getContext().Idents.get("this"),
MD->getThisType(getContext()));
Args.push_back(std::make_pair(CXXThisDecl, CXXThisDecl->getType()));
@@ -262,7 +283,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) {
// FIXME: The comment about using a fake decl above applies here too.
QualType T = getContext().getPointerType(getContext().VoidPtrTy);
CXXVTTDecl =
- ImplicitParamDecl::Create(getContext(), 0, SourceLocation(),
+ ImplicitParamDecl::Create(getContext(), 0, FD->getLocation(),
&getContext().Idents.get("vtt"), T);
Args.push_back(std::make_pair(CXXVTTDecl, CXXVTTDecl->getType()));
}
@@ -278,80 +299,22 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) {
FProto->getArgType(i)));
}
- if (const CompoundStmt *S = FD->getCompoundBody()) {
- StartFunction(GD, FD->getResultType(), Fn, Args, S->getLBracLoc());
-
- if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
- EmitCtorPrologue(CD, GD.getCtorType());
- EmitStmt(S);
-
- // If any of the member initializers are temporaries bound to references
- // make sure to emit their destructors.
- EmitCleanupBlocks(0);
-
- } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) {
- llvm::BasicBlock *DtorEpilogue = createBasicBlock("dtor.epilogue");
- PushCleanupBlock(DtorEpilogue);
+ SourceRange BodyRange;
+ if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange();
- InitializeVtablePtrs(DD->getParent());
+ // Emit the standard function prologue.
+ StartFunction(GD, FD->getResultType(), Fn, Args, BodyRange.getBegin());
- EmitStmt(S);
-
- CleanupBlockInfo Info = PopCleanupBlock();
+ // Generate the body of the function.
+ if (isa<CXXDestructorDecl>(FD))
+ EmitDestructorBody(Args);
+ else if (isa<CXXConstructorDecl>(FD))
+ EmitConstructorBody(Args);
+ else
+ EmitFunctionBody(Args);
- assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!");
- EmitBlock(DtorEpilogue);
- EmitDtorEpilogue(DD, GD.getDtorType());
-
- if (Info.SwitchBlock)
- EmitBlock(Info.SwitchBlock);
- if (Info.EndBlock)
- EmitBlock(Info.EndBlock);
- } else {
- // Just a regular function, emit its body.
- EmitStmt(S);
- }
-
- FinishFunction(S->getRBracLoc());
- } else if (FD->isImplicit()) {
- const CXXRecordDecl *ClassDecl =
- cast<CXXRecordDecl>(FD->getDeclContext());
- (void) ClassDecl;
- if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
- // FIXME: For C++0x, we want to look for implicit *definitions* of
- // these special member functions, rather than implicit *declarations*.
- if (CD->isCopyConstructor()) {
- assert(!ClassDecl->hasUserDeclaredCopyConstructor() &&
- "Cannot synthesize a non-implicit copy constructor");
- SynthesizeCXXCopyConstructor(CD, GD.getCtorType(), Fn, Args);
- } else if (CD->isDefaultConstructor()) {
- assert(!ClassDecl->hasUserDeclaredConstructor() &&
- "Cannot synthesize a non-implicit default constructor.");
- SynthesizeDefaultConstructor(CD, GD.getCtorType(), Fn, Args);
- } else {
- assert(false && "Implicit constructor cannot be synthesized");
- }
- } else if (const CXXDestructorDecl *CD = dyn_cast<CXXDestructorDecl>(FD)) {
- assert(!ClassDecl->hasUserDeclaredDestructor() &&
- "Cannot synthesize a non-implicit destructor");
- SynthesizeDefaultDestructor(CD, GD.getDtorType(), Fn, Args);
- } else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
- assert(MD->isCopyAssignment() &&
- !ClassDecl->hasUserDeclaredCopyAssignment() &&
- "Cannot synthesize a method that is not an implicit-defined "
- "copy constructor");
- SynthesizeCXXCopyAssignment(MD, Fn, Args);
- } else {
- assert(false && "Cannot synthesize unknown implicit function");
- }
- } else if (const Stmt *S = FD->getBody()) {
- if (const CXXTryStmt *TS = dyn_cast<CXXTryStmt>(S)) {
- OuterTryBlock = TS;
- StartFunction(GD, FD->getResultType(), Fn, Args, TS->getTryLoc());
- EmitStmt(TS);
- FinishFunction(TS->getEndLoc());
- }
- }
+ // Emit the standard function epilogue.
+ FinishFunction(BodyRange.getEnd());
// Destroy the 'this' declaration.
if (CXXThisDecl)
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index fb2e5fe..d582c0d 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -55,6 +55,7 @@ namespace clang {
class ObjCImplementationDecl;
class ObjCPropertyImplDecl;
class TargetInfo;
+ class TargetCodeGenInfo;
class VarDecl;
class ObjCForCollectionStmt;
class ObjCAtTryStmt;
@@ -62,7 +63,6 @@ namespace clang {
class ObjCAtSynchronizedStmt;
namespace CodeGen {
- class CodeGenModule;
class CodeGenTypes;
class CGDebugInfo;
class CGFunctionInfo;
@@ -91,9 +91,6 @@ public:
/// CurGD - The GlobalDecl for the current function being compiled.
GlobalDecl CurGD;
- /// OuterTryBlock - This is the address of the outter most try block, 0
- /// otherwise.
- const Stmt *OuterTryBlock;
/// ReturnBlock - Unified return block.
llvm::BasicBlock *ReturnBlock;
@@ -382,11 +379,13 @@ private:
/// CXXThisDecl - When generating code for a C++ member function,
/// this will hold the implicit 'this' declaration.
ImplicitParamDecl *CXXThisDecl;
+ llvm::Value *CXXThisValue;
/// CXXVTTDecl - When generating code for a base object constructor or
/// base object destructor with virtual bases, this will hold the implicit
/// VTT parameter.
ImplicitParamDecl *CXXVTTDecl;
+ llvm::Value *CXXVTTValue;
/// CXXLiveTemporaryInfo - Holds information about a live C++ temporary.
struct CXXLiveTemporaryInfo {
@@ -466,7 +465,8 @@ public:
//===--------------------------------------------------------------------===//
llvm::Value *BuildBlockLiteralTmp(const BlockExpr *);
- llvm::Constant *BuildDescriptorBlockDecl(bool BlockHasCopyDispose,
+ llvm::Constant *BuildDescriptorBlockDecl(const BlockExpr *,
+ bool BlockHasCopyDispose,
CharUnits Size,
const llvm::StructType *,
std::vector<HelperInfo> *);
@@ -492,6 +492,10 @@ public:
const FunctionArgList &Args,
SourceLocation StartLoc);
+ void EmitConstructorBody(FunctionArgList &Args);
+ void EmitDestructorBody(FunctionArgList &Args);
+ void EmitFunctionBody(FunctionArgList &Args);
+
/// EmitReturnBlock - Emit the unified return block, trying to avoid its
/// emission when possible.
void EmitReturnBlock();
@@ -525,24 +529,8 @@ public:
llvm::Value *ThisPtr,
uint64_t Offset);
- void SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor,
- CXXCtorType Type,
- llvm::Function *Fn,
- const FunctionArgList &Args);
-
- void SynthesizeCXXCopyAssignment(const CXXMethodDecl *CD,
- llvm::Function *Fn,
- const FunctionArgList &Args);
-
- void SynthesizeDefaultConstructor(const CXXConstructorDecl *Ctor,
- CXXCtorType Type,
- llvm::Function *Fn,
- const FunctionArgList &Args);
-
- void SynthesizeDefaultDestructor(const CXXDestructorDecl *Dtor,
- CXXDtorType Type,
- llvm::Function *Fn,
- const FunctionArgList &Args);
+ void SynthesizeCXXCopyConstructor(const FunctionArgList &Args);
+ void SynthesizeCXXCopyAssignment(const FunctionArgList &Args);
/// EmitDtorEpilogue - Emit all code that comes at the end of class's
/// destructor. This is to call destructors on members and base classes in
@@ -663,6 +651,13 @@ public:
llvm::AllocaInst *CreateTempAlloca(const llvm::Type *Ty,
const llvm::Twine &Name = "tmp");
+ /// CreateIRTemp - Create a temporary IR object of the given type, with
+ /// appropriate alignment. This routine should only be used when an temporary
+ /// value needs to be stored into an alloca (for example, to avoid explicit
+ /// PHI construction), but the type is the IR type, not the type appropriate
+ /// for storing in memory.
+ llvm::Value *CreateIRTemp(QualType T, const llvm::Twine &Name = "tmp");
+
/// CreateMemTemp - Create a temporary memory object of the given type, with
/// appropriate alignment.
llvm::Value *CreateMemTemp(QualType T, const llvm::Twine &Name = "tmp");
@@ -738,11 +733,17 @@ public:
/// LoadCXXThis - Load the value of 'this'. This function is only valid while
/// generating code for an C++ member function.
- llvm::Value *LoadCXXThis();
+ llvm::Value *LoadCXXThis() {
+ assert(CXXThisValue && "no 'this' value for this function");
+ return CXXThisValue;
+ }
/// LoadCXXVTT - Load the VTT parameter to base constructors/destructors have
/// virtual bases.
- llvm::Value *LoadCXXVTT();
+ llvm::Value *LoadCXXVTT() {
+ assert(CXXVTTValue && "no VTT value for this function");
+ return CXXVTTValue;
+ }
/// GetAddressOfBaseOfCompleteClass - Convert the given pointer to a
/// complete class down to one of its virtual bases.
@@ -789,6 +790,9 @@ public:
const CXXRecordDecl *BaseClassDecl,
QualType Ty);
+ void EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
+ CXXCtorType CtorType,
+ const FunctionArgList &Args);
void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type,
llvm::Value *This,
CallExpr::const_arg_iterator ArgBeg,
@@ -916,6 +920,14 @@ public:
void EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S);
void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S);
+ struct CXXTryStmtInfo {
+ llvm::BasicBlock *SavedLandingPad;
+ llvm::BasicBlock *HandlerBlock;
+ llvm::BasicBlock *FinallyBlock;
+ };
+ CXXTryStmtInfo EnterCXXTryStmt(const CXXTryStmt &S);
+ void ExitCXXTryStmt(const CXXTryStmt &S, CXXTryStmtInfo Info);
+
void EmitCXXTryStmt(const CXXTryStmt &S);
//===--------------------------------------------------------------------===//
@@ -1326,6 +1338,10 @@ private:
ArgType));
}
}
+
+ const TargetCodeGenInfo &getTargetHooks() const {
+ return CGM.getTargetCodeGenInfo();
+ }
};
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 5a552c4..91c7322 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -316,24 +316,20 @@ GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
return CodeGenModule::GVA_CXXInline;
}
-/// SetFunctionDefinitionAttributes - Set attributes for a global.
-///
-/// FIXME: This is currently only done for aliases and functions, but not for
-/// variables (these details are set in EmitGlobalVarDefinition for variables).
-void CodeGenModule::SetFunctionDefinitionAttributes(const FunctionDecl *D,
- llvm::GlobalValue *GV) {
+llvm::GlobalValue::LinkageTypes
+CodeGenModule::getFunctionLinkage(const FunctionDecl *D) {
GVALinkage Linkage = GetLinkageForFunction(getContext(), D, Features);
if (Linkage == GVA_Internal) {
- GV->setLinkage(llvm::Function::InternalLinkage);
+ return llvm::Function::InternalLinkage;
} else if (D->hasAttr<DLLExportAttr>()) {
- GV->setLinkage(llvm::Function::DLLExportLinkage);
+ return llvm::Function::DLLExportLinkage;
} else if (D->hasAttr<WeakAttr>()) {
- GV->setLinkage(llvm::Function::WeakAnyLinkage);
+ return llvm::Function::WeakAnyLinkage;
} else if (Linkage == GVA_C99Inline) {
// In C99 mode, 'inline' functions are guaranteed to have a strong
// definition somewhere else, so we can use available_externally linkage.
- GV->setLinkage(llvm::Function::AvailableExternallyLinkage);
+ return llvm::Function::AvailableExternallyLinkage;
} else if (Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation) {
// In C++, the compiler has to emit a definition in every translation unit
// that references the function. We should use linkonce_odr because
@@ -341,13 +337,22 @@ void CodeGenModule::SetFunctionDefinitionAttributes(const FunctionDecl *D,
// don't need to codegen it. b) if the function persists, it needs to be
// merged with other definitions. c) C++ has the ODR, so we know the
// definition is dependable.
- GV->setLinkage(llvm::Function::LinkOnceODRLinkage);
+ return llvm::Function::LinkOnceODRLinkage;
} else {
assert(Linkage == GVA_StrongExternal);
// Otherwise, we have strong external linkage.
- GV->setLinkage(llvm::Function::ExternalLinkage);
+ return llvm::Function::ExternalLinkage;
}
+}
+
+/// SetFunctionDefinitionAttributes - Set attributes for a global.
+///
+/// FIXME: This is currently only done for aliases and functions, but not for
+/// variables (these details are set in EmitGlobalVarDefinition for variables).
+void CodeGenModule::SetFunctionDefinitionAttributes(const FunctionDecl *D,
+ llvm::GlobalValue *GV) {
+ GV->setLinkage(getFunctionLinkage(D));
SetCommonAttributes(D, GV);
}
@@ -747,14 +752,20 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName,
// A called constructor which has no definition or declaration need be
// synthesized.
else if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
- if (CD->isImplicit())
+ if (CD->isImplicit()) {
+ assert (CD->isUsed());
DeferredDeclsToEmit.push_back(D);
+ }
} else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) {
- if (DD->isImplicit())
+ if (DD->isImplicit()) {
+ assert (DD->isUsed());
DeferredDeclsToEmit.push_back(D);
+ }
} else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
- if (MD->isCopyAssignment() && MD->isImplicit())
+ if (MD->isCopyAssignment() && MD->isImplicit()) {
+ assert (MD->isUsed());
DeferredDeclsToEmit.push_back(D);
+ }
}
}
@@ -1190,28 +1201,8 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old,
void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) {
- const llvm::FunctionType *Ty;
const FunctionDecl *D = cast<FunctionDecl>(GD.getDecl());
-
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
- bool isVariadic = D->getType()->getAs<FunctionProtoType>()->isVariadic();
-
- Ty = getTypes().GetFunctionType(getTypes().getFunctionInfo(MD), isVariadic);
- } else {
- Ty = cast<llvm::FunctionType>(getTypes().ConvertType(D->getType()));
-
- // As a special case, make sure that definitions of K&R function
- // "type foo()" aren't declared as varargs (which forces the backend
- // to do unnecessary work).
- if (D->getType()->isFunctionNoProtoType()) {
- assert(Ty->isVarArg() && "Didn't lower type as expected");
- // Due to stret, the lowered function could have arguments.
- // Just create the same type as was lowered by ConvertType
- // but strip off the varargs bit.
- std::vector<const llvm::Type*> Args(Ty->param_begin(), Ty->param_end());
- Ty = llvm::FunctionType::get(Ty->getReturnType(), Args, false);
- }
- }
+ const llvm::FunctionType *Ty = getTypes().GetFunctionType(GD);
// Get or create the prototype for the function.
llvm::Constant *Entry = GetAddrOfFunction(GD, Ty);
@@ -1342,6 +1333,7 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {
GA->setLinkage(llvm::Function::DLLExportLinkage);
}
} else if (D->hasAttr<WeakAttr>() ||
+ D->hasAttr<WeakRefAttr>() ||
D->hasAttr<WeakImportAttr>()) {
GA->setLinkage(llvm::Function::WeakAnyLinkage);
}
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 8280766..ac83326 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -206,6 +206,19 @@ public:
/// GlobalValue.
void setGlobalVisibility(llvm::GlobalValue *GV, const Decl *D) const;
+ llvm::Constant *GetAddrOfGlobal(GlobalDecl GD) {
+ if (isa<CXXConstructorDecl>(GD.getDecl()))
+ return GetAddrOfCXXConstructor(cast<CXXConstructorDecl>(GD.getDecl()),
+ GD.getCtorType());
+ else if (isa<CXXDestructorDecl>(GD.getDecl()))
+ return GetAddrOfCXXDestructor(cast<CXXDestructorDecl>(GD.getDecl()),
+ GD.getDtorType());
+ else if (isa<FunctionDecl>(GD.getDecl()))
+ return GetAddrOfFunction(GD);
+ else
+ return GetAddrOfGlobalVar(cast<VarDecl>(GD.getDecl()));
+ }
+
/// GetAddrOfGlobalVar - Return the llvm::Constant for the address of the
/// given global variable. If Ty is non-null and if the global doesn't exist,
/// then it will be greated with the specified type instead of whatever the
@@ -291,13 +304,13 @@ public:
/// GetAddrOfCXXConstructor - Return the address of the constructor of the
/// given type.
- llvm::Function *GetAddrOfCXXConstructor(const CXXConstructorDecl *D,
- CXXCtorType Type);
+ llvm::GlobalValue *GetAddrOfCXXConstructor(const CXXConstructorDecl *D,
+ CXXCtorType Type);
/// GetAddrOfCXXDestructor - Return the address of the constructor of the
/// given type.
- llvm::Function *GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
- CXXDtorType Type);
+ llvm::GlobalValue *GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
+ CXXDtorType Type);
/// getBuiltinLibFunction - Given a builtin id for a function like
/// "__builtin_fabsf", return a Function* for "fabsf".
@@ -417,6 +430,9 @@ public:
GVA_TemplateInstantiation
};
+ llvm::GlobalVariable::LinkageTypes
+ getFunctionLinkage(const FunctionDecl *FD);
+
/// getVtableLinkage - Return the appropriate linkage for the vtable, VTT,
/// and type information of the given class.
static llvm::GlobalVariable::LinkageTypes
@@ -468,6 +484,9 @@ private:
// C++ related functions.
+ bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target);
+ bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D);
+
void EmitNamespace(const NamespaceDecl *D);
void EmitLinkageSpec(const LinkageSpecDecl *D);
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index 3c20934..4feca4d 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -190,6 +190,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
#define ABSTRACT_TYPE(Class, Base)
#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
#include "clang/AST/TypeNodes.def"
assert(false && "Non-canonical or dependent types aren't possible.");
break;
@@ -313,10 +314,14 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
// The function type can be built; call the appropriate routines to
// build it.
if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(&Ty))
- return GetFunctionType(getFunctionInfo(FPT), FPT->isVariadic());
+ return GetFunctionType(getFunctionInfo(
+ CanQual<FunctionProtoType>::CreateUnsafe(QualType(FPT,0))),
+ FPT->isVariadic());
const FunctionNoProtoType *FNPT = cast<FunctionNoProtoType>(&Ty);
- return GetFunctionType(getFunctionInfo(FNPT), true);
+ return GetFunctionType(getFunctionInfo(
+ CanQual<FunctionNoProtoType>::CreateUnsafe(QualType(FNPT,0))),
+ true);
}
case Type::ObjCInterface: {
@@ -386,9 +391,6 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
NULL);
return PtrDiffTy;
}
-
- case Type::TemplateSpecialization:
- assert(false && "Dependent types can't get here");
}
// FIXME: implement.
diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h
index 87ba0bc..b2912ef 100644
--- a/lib/CodeGen/CodeGenTypes.h
+++ b/lib/CodeGen/CodeGenTypes.h
@@ -35,6 +35,7 @@ namespace llvm {
namespace clang {
class ABIInfo;
class ASTContext;
+ template <typename> class CanQual;
class CXXConstructorDecl;
class CXXDestructorDecl;
class CXXMethodDecl;
@@ -48,6 +49,7 @@ namespace clang {
class TagDecl;
class TargetInfo;
class Type;
+ typedef CanQual<Type> CanQualType;
namespace CodeGen {
class CodeGenTypes;
@@ -168,6 +170,8 @@ public:
const llvm::FunctionType *GetFunctionType(const CGFunctionInfo &Info,
bool IsVariadic);
+ const llvm::FunctionType *GetFunctionType(GlobalDecl GD);
+
/// GetFunctionTypeForVtable - Get the LLVM function type for use in a vtable,
/// given a CXXMethodDecl. If the method to has an incomplete return type,
@@ -184,11 +188,6 @@ public:
/// replace the 'opaque' type we previously made for it if applicable.
void UpdateCompletedType(const TagDecl *TD);
-private:
- const CGFunctionInfo &getFunctionInfo(const FunctionNoProtoType *FTNP);
- const CGFunctionInfo &getFunctionInfo(const FunctionProtoType *FTP);
-
-public:
/// getFunctionInfo - Get the function info for the specified function decl.
const CGFunctionInfo &getFunctionInfo(GlobalDecl GD);
@@ -205,6 +204,8 @@ public:
return getFunctionInfo(Ty->getResultType(), Args,
Ty->getCallConv(), Ty->getNoReturnAttr());
}
+ const CGFunctionInfo &getFunctionInfo(CanQual<FunctionProtoType> Ty);
+ const CGFunctionInfo &getFunctionInfo(CanQual<FunctionNoProtoType> Ty);
// getFunctionInfo - Get the function info for a member function.
const CGFunctionInfo &getFunctionInfo(const CXXRecordDecl *RD,
@@ -221,8 +222,12 @@ public:
const FunctionArgList &Args,
CallingConv CC,
bool NoReturn);
- const CGFunctionInfo &getFunctionInfo(QualType RetTy,
- const llvm::SmallVector<QualType, 16> &ArgTys,
+
+ /// Retrieves the ABI information for the given function signature.
+ ///
+ /// \param ArgTys - must all actually be canonical as params
+ const CGFunctionInfo &getFunctionInfo(CanQualType RetTy,
+ const llvm::SmallVectorImpl<CanQualType> &ArgTys,
CallingConv CC,
bool NoReturn);
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index a302225..64743c7 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -455,7 +455,9 @@ void CXXNameMangler::mangleUnresolvedScope(NestedNameSpecifier *Qualifier) {
mangleType(QualType(Qualifier->getAsType(), 0));
break;
case NestedNameSpecifier::Identifier:
- mangleUnresolvedScope(Qualifier->getPrefix());
+ // Member expressions can have these without prefixes.
+ if (Qualifier->getPrefix())
+ mangleUnresolvedScope(Qualifier->getPrefix());
mangleSourceName(Qualifier->getAsIdentifier());
break;
}
@@ -1123,6 +1125,42 @@ void CXXNameMangler::mangleType(const TypenameType *T) {
Out << 'E';
}
+void CXXNameMangler::mangleType(const TypeOfType *T) {
+ // FIXME: this is pretty unsatisfactory, but there isn't an obvious
+ // "extension with parameters" mangling.
+ Out << "u6typeof";
+}
+
+void CXXNameMangler::mangleType(const TypeOfExprType *T) {
+ // FIXME: this is pretty unsatisfactory, but there isn't an obvious
+ // "extension with parameters" mangling.
+ Out << "u6typeof";
+}
+
+void CXXNameMangler::mangleType(const DecltypeType *T) {
+ Expr *E = T->getUnderlyingExpr();
+
+ // type ::= Dt <expression> E # decltype of an id-expression
+ // # or class member access
+ // ::= DT <expression> E # decltype of an expression
+
+ // This purports to be an exhaustive list of id-expressions and
+ // class member accesses. Note that we do not ignore parentheses;
+ // parentheses change the semantics of decltype for these
+ // expressions (and cause the mangler to use the other form).
+ if (isa<DeclRefExpr>(E) ||
+ isa<MemberExpr>(E) ||
+ isa<UnresolvedLookupExpr>(E) ||
+ isa<DependentScopeDeclRefExpr>(E) ||
+ isa<CXXDependentScopeMemberExpr>(E) ||
+ isa<UnresolvedMemberExpr>(E))
+ Out << "Dt";
+ else
+ Out << "DT";
+ mangleExpression(E);
+ Out << 'E';
+}
+
void CXXNameMangler::mangleIntegerLiteral(QualType T,
const llvm::APSInt &Value) {
// <expr-primary> ::= L <type> <value number> E # integer literal
@@ -1163,20 +1201,14 @@ void CXXNameMangler::mangleCalledExpression(const Expr *E, unsigned Arity) {
/// Mangles a member expression. Implicit accesses are not handled,
/// but that should be okay, because you shouldn't be able to
/// make an implicit access in a function template declaration.
-///
-/// The standard ABI does not describe how member expressions should
-/// be mangled, so this is very unstandardized. We mangle as if it
-/// were a binary operator, except that the RHS is mangled as an
-/// abstract name.
-///
-/// The standard ABI also does not assign a mangling to the dot
-/// operator, so we arbitrarily select 'me'.
void CXXNameMangler::mangleMemberExpr(const Expr *Base,
bool IsArrow,
NestedNameSpecifier *Qualifier,
DeclarationName Member,
unsigned Arity) {
- Out << (IsArrow ? "pt" : "me");
+ // gcc-4.4 uses 'dt' for dot expressions, which is reasonable.
+ // OTOH, gcc also mangles the name as an expression.
+ Out << (IsArrow ? "pt" : "dt");
mangleExpression(Base);
mangleUnresolvedName(Qualifier, Member, Arity);
}
@@ -1346,10 +1378,16 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
break;
case Expr::DeclRefExprClass: {
- const Decl *D = cast<DeclRefExpr>(E)->getDecl();
+ const NamedDecl *D = cast<DeclRefExpr>(E)->getDecl();
switch (D->getKind()) {
- default: assert(false && "Unhandled decl kind!");
+ default:
+ // <expr-primary> ::= L <mangled-name> E # external name
+ Out << 'L';
+ mangle(D, "_Z");
+ Out << 'E';
+ break;
+
case Decl::NonTypeTemplateParm: {
const NonTypeTemplateParmDecl *PD = cast<NonTypeTemplateParmDecl>(D);
mangleTemplateParameter(PD->getIndex());
@@ -1363,7 +1401,18 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
case Expr::DependentScopeDeclRefExprClass: {
const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
- const Type *QTy = DRE->getQualifier()->getAsType();
+ NestedNameSpecifier *NNS = DRE->getQualifier();
+ const Type *QTy = NNS->getAsType();
+
+ // When we're dealing with a nested-name-specifier that has just a
+ // dependent identifier in it, mangle that as a typename. FIXME:
+ // It isn't clear that we ever actually want to have such a
+ // nested-name-specifier; why not just represent it as a typename type?
+ if (!QTy && NNS->getAsIdentifier() && NNS->getPrefix()) {
+ QTy = getASTContext().getTypenameType(NNS->getPrefix(),
+ NNS->getAsIdentifier())
+ .getTypePtr();
+ }
assert(QTy && "Qualifier was not type!");
// ::= sr <type> <unqualified-name> # dependent name
@@ -1648,6 +1697,9 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
if (const ClassTemplateSpecializationDecl *SD =
dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
+ if (!isStdNamespace(SD->getDeclContext()))
+ return false;
+
// <substitution> ::= Ss # ::std::basic_string<char,
// ::std::char_traits<char>,
// ::std::allocator<char> >
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index a7c0caa..f4ec914 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -972,12 +972,11 @@ ABIArgInfo X86_64ABIInfo::getCoerceResult(QualType Ty,
return (Ty->isPromotableIntegerType() ?
ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
} else if (CoerceTo == llvm::Type::getDoubleTy(CoerceTo->getContext())) {
- // FIXME: It would probably be better to make CGFunctionInfo only map using
- // canonical types than to canonize here.
- QualType CTy = Context.getCanonicalType(Ty);
+ assert(Ty.isCanonical() && "should always have a canonical type here");
+ assert(!Ty.hasQualifiers() && "should never have a qualified type here");
// Float and double end up in a single SSE reg.
- if (CTy == Context.FloatTy || CTy == Context.DoubleTy)
+ if (Ty == Context.FloatTy || Ty == Context.DoubleTy)
return ABIArgInfo::getDirect();
}
@@ -1497,9 +1496,29 @@ ABIArgInfo PIC16ABIInfo::classifyArgumentType(QualType Ty,
llvm::Value *PIC16ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
CodeGenFunction &CGF) const {
- return 0;
+ const llvm::Type *BP = llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(CGF.getLLVMContext()));
+ const llvm::Type *BPP = llvm::PointerType::getUnqual(BP);
+
+ CGBuilderTy &Builder = CGF.Builder;
+ llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP,
+ "ap");
+ llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
+ llvm::Type *PTy =
+ llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
+ llvm::Value *AddrTyped = Builder.CreateBitCast(Addr, PTy);
+
+ uint64_t Offset = CGF.getContext().getTypeSize(Ty) / 8;
+
+ llvm::Value *NextAddr =
+ Builder.CreateGEP(Addr, llvm::ConstantInt::get(
+ llvm::Type::getInt32Ty(CGF.getLLVMContext()), Offset),
+ "ap.next");
+ Builder.CreateStore(NextAddr, VAListAddrAsBPP);
+
+ return AddrTyped;
}
+
// ARM ABI Implementation
namespace {
diff --git a/lib/CodeGen/TargetInfo.h b/lib/CodeGen/TargetInfo.h
index 58b7b79..9e80081 100644
--- a/lib/CodeGen/TargetInfo.h
+++ b/lib/CodeGen/TargetInfo.h
@@ -17,6 +17,7 @@
namespace llvm {
class GlobalValue;
+ class Value;
}
namespace clang {
@@ -25,6 +26,7 @@ namespace clang {
namespace CodeGen {
class CodeGenModule;
+ class CodeGenFunction;
}
/// TargetCodeGenInfo - This class organizes various target-specific
@@ -44,6 +46,35 @@ namespace clang {
/// target-specific attributes for the given global.
virtual void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const { }
+
+ /// Controls whether __builtin_extend_pointer should sign-extend
+ /// pointers to uint64_t or zero-extend them (the default). Has
+ /// no effect for targets:
+ /// - that have 64-bit pointers, or
+ /// - that cannot address through registers larger than pointers, or
+ /// - that implicitly ignore/truncate the top bits when addressing
+ /// through such registers.
+ virtual bool extendPointerWithSExt() const { return false; }
+
+ /// Performs the code-generation required to convert a return
+ /// address as stored by the system into the actual address of the
+ /// next instruction that will be executed.
+ ///
+ /// Used by __builtin_extract_return_addr().
+ virtual llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *Address) const {
+ return Address;
+ }
+
+ /// Performs the code-generation required to convert the address
+ /// of an instruction into a return address suitable for storage
+ /// by the system in a return slot.
+ ///
+ /// Used by __builtin_frob_return_addr().
+ virtual llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *Address) const {
+ return Address;
+ }
};
}
OpenPOWER on IntegriCloud