summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGBlocks.cpp140
-rw-r--r--lib/CodeGen/CGBlocks.h20
-rw-r--r--lib/CodeGen/CGCXX.cpp15
-rw-r--r--lib/CodeGen/CGCall.cpp5
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp99
-rw-r--r--lib/CodeGen/CGDebugInfo.h2
-rw-r--r--lib/CodeGen/CGDecl.cpp5
-rw-r--r--lib/CodeGen/CGExpr.cpp121
-rw-r--r--lib/CodeGen/CGExprAgg.cpp25
-rw-r--r--lib/CodeGen/CGExprConstant.cpp6
-rw-r--r--lib/CodeGen/CGExprScalar.cpp256
-rw-r--r--lib/CodeGen/CGObjCMac.cpp199
-rw-r--r--lib/CodeGen/CGVtable.cpp71
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp6
-rw-r--r--lib/CodeGen/CodeGenFunction.h11
-rw-r--r--lib/CodeGen/CodeGenModule.cpp8
-rw-r--r--lib/CodeGen/Mangle.cpp14
-rw-r--r--lib/CodeGen/TargetABIInfo.cpp20
18 files changed, 693 insertions, 330 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 736425e..682cf5d 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -73,29 +73,60 @@ llvm::Constant *BlockModule::getNSConcreteStackBlock() {
return NSConcreteStackBlock;
}
-static void CollectBlockDeclRefInfo(const Stmt *S,
- CodeGenFunction::BlockInfo &Info) {
+static void CollectBlockDeclRefInfo(
+ const Stmt *S, CodeGenFunction::BlockInfo &Info,
+ llvm::SmallSet<const DeclContext *, 16> &InnerContexts) {
for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
I != E; ++I)
if (*I)
- CollectBlockDeclRefInfo(*I, Info);
+ CollectBlockDeclRefInfo(*I, Info, InnerContexts);
- if (const BlockDeclRefExpr *DE = dyn_cast<BlockDeclRefExpr>(S)) {
+ // We want to ensure we walk down into block literals so we can find
+ // all nested BlockDeclRefExprs.
+ if (const BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
+ InnerContexts.insert(cast<DeclContext>(BE->getBlockDecl()));
+ CollectBlockDeclRefInfo(BE->getBody(), Info, InnerContexts);
+ }
+
+ if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
// FIXME: Handle enums.
- if (isa<FunctionDecl>(DE->getDecl()))
+ if (isa<FunctionDecl>(BDRE->getDecl()))
return;
- if (DE->isByRef())
- Info.ByRefDeclRefs.push_back(DE);
- else
- Info.ByCopyDeclRefs.push_back(DE);
+ // Only Decls that escape are added.
+ if (!InnerContexts.count(BDRE->getDecl()->getDeclContext()))
+ Info.DeclRefs.push_back(BDRE);
}
}
/// CanBlockBeGlobal - Given a BlockInfo struct, determines if a block can be
/// declared as a global variable instead of on the stack.
static bool CanBlockBeGlobal(const CodeGenFunction::BlockInfo &Info) {
- return Info.ByRefDeclRefs.empty() && Info.ByCopyDeclRefs.empty();
+ return Info.DeclRefs.empty();
+}
+
+/// AllocateAllBlockDeclRefs - Preallocate all nested BlockDeclRefExprs to
+/// ensure we can generate the debug information for the parameter for the block
+/// 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)
+ CGF->AllocateBlockDecl(Info.DeclRefs[i]);
}
// FIXME: Push most into CGM, passing down a few bits, like current function
@@ -104,7 +135,9 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
std::string Name = CurFn->getName();
CodeGenFunction::BlockInfo Info(0, Name.c_str());
- CollectBlockDeclRefInfo(BE->getBody(), Info);
+ llvm::SmallSet<const DeclContext *, 16> InnerContexts;
+ InnerContexts.insert(BE->getBlockDecl());
+ CollectBlockDeclRefInfo(BE->getBody(), Info, InnerContexts);
// Check if the block can be global.
// FIXME: This test doesn't work for nested blocks yet. Longer term, I'd like
@@ -159,7 +192,8 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
if (subBlockDeclRefDecls.size() == 0) {
// __descriptor
- Elts[4] = BuildDescriptorBlockDecl(subBlockHasCopyDispose, subBlockSize, 0, 0);
+ Elts[4] = BuildDescriptorBlockDecl(subBlockHasCopyDispose, subBlockSize,
+ 0, 0);
// Optimize to being a global block.
Elts[0] = CGM.getNSConcreteGlobalBlock();
@@ -269,7 +303,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
llvm::Value *BlockLiteral = LoadBlockStruct();
Loc = Builder.CreateGEP(BlockLiteral,
- llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+ llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
offset),
"block.literal");
Ty = llvm::PointerType::get(Ty, 0);
@@ -391,10 +425,6 @@ const llvm::Type *BlockModule::getGenericExtendedBlockLiteralType() {
return GenericExtendedBlockLiteralType;
}
-bool BlockFunction::BlockRequiresCopying(QualType Ty) {
- return CGM.BlockRequiresCopying(Ty);
-}
-
RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) {
const BlockPointerType *BPT =
E->getCallee()->getType()->getAs<BlockPointerType>();
@@ -447,24 +477,34 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) {
return EmitCall(FnInfo, Func, Args);
}
-llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) {
+uint64_t CodeGenFunction::AllocateBlockDecl(const BlockDeclRefExpr *E) {
const ValueDecl *VD = E->getDecl();
-
uint64_t &offset = BlockDecls[VD];
-
// See if we have already allocated an offset for this variable.
- if (offset == 0) {
- // Don't run the expensive check, unless we have to.
- if (!BlockHasCopyDispose && BlockRequiresCopying(E->getType()))
+ if (offset)
+ return offset;
+
+ // Don't run the expensive check, unless we have to.
+ if (!BlockHasCopyDispose)
+ if (E->isByRef()
+ || BlockRequiresCopying(E->getType()))
BlockHasCopyDispose = true;
- // if not, allocate one now.
- offset = getBlockOffset(E);
- }
+
+ // if not, allocate one now.
+ offset = getBlockOffset(E);
+
+ return offset;
+}
+
+llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) {
+ const ValueDecl *VD = E->getDecl();
+ uint64_t offset = AllocateBlockDecl(E);
+
llvm::Value *BlockLiteral = LoadBlockStruct();
llvm::Value *V = Builder.CreateGEP(BlockLiteral,
- llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+ llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
offset),
"block.literal");
if (E->isByRef()) {
@@ -576,7 +616,10 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
}
llvm::Value *CodeGenFunction::LoadBlockStruct() {
- return Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()], "self");
+ llvm::Value *V = Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()],
+ "self");
+ // For now, we codegen based upon byte offsets.
+ return Builder.CreateBitCast(V, PtrToInt8Ty);
}
llvm::Function *
@@ -605,14 +648,8 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
LocalDeclMap[VD] = i->second;
}
- // FIXME: We need to rearrange the code for copy/dispose so we have this
- // sooner, so we can calculate offsets correctly.
- if (!BlockHasCopyDispose)
- BlockOffset = CGM.getTargetData()
- .getTypeStoreSizeInBits(CGM.getGenericBlockLiteralType()) / 8;
- else
- BlockOffset = CGM.getTargetData()
- .getTypeStoreSizeInBits(CGM.getGenericExtendedBlockLiteralType()) / 8;
+ BlockOffset = CGM.getTargetData()
+ .getTypeStoreSizeInBits(CGM.getGenericBlockLiteralType()) / 8;
BlockAlign = getContext().getTypeAlign(getContext().VoidPtrTy) / 8;
const FunctionType *BlockFunctionType = BExpr->getFunctionType();
@@ -630,13 +667,22 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
FunctionArgList Args;
+ CurFuncDecl = OuterFuncDecl;
+
const BlockDecl *BD = BExpr->getBlockDecl();
+ IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
+
+ // Allocate all BlockDeclRefDecls, so we can calculate the right ParmTy below.
+ AllocateAllBlockDeclRefs(Info, this);
+
+ QualType ParmTy = getContext().getBlockParmType(BlockHasCopyDispose,
+ BlockDeclRefDecls);
// FIXME: This leaks
ImplicitParamDecl *SelfDecl =
ImplicitParamDecl::Create(getContext(), 0,
- SourceLocation(), 0,
- getContext().getPointerType(getContext().VoidTy));
+ SourceLocation(), II,
+ ParmTy);
Args.push_back(std::make_pair(SelfDecl, SelfDecl->getType()));
BlockStructDecl = SelfDecl;
@@ -758,11 +804,13 @@ GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T,
FunctionArgList Args;
// FIXME: This leaks
ImplicitParamDecl *Dst =
- ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+ ImplicitParamDecl::Create(getContext(), 0,
+ SourceLocation(), 0,
getContext().getPointerType(getContext().VoidTy));
Args.push_back(std::make_pair(Dst, Dst->getType()));
ImplicitParamDecl *Src =
- ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+ ImplicitParamDecl::Create(getContext(), 0,
+ SourceLocation(), 0,
getContext().getPointerType(getContext().VoidTy));
Args.push_back(std::make_pair(Src, Src->getType()));
@@ -843,7 +891,8 @@ GenerateDestroyHelperFunction(bool BlockHasCopyDispose,
FunctionArgList Args;
// FIXME: This leaks
ImplicitParamDecl *Src =
- ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+ ImplicitParamDecl::Create(getContext(), 0,
+ SourceLocation(), 0,
getContext().getPointerType(getContext().VoidTy));
Args.push_back(std::make_pair(Src, Src->getType()));
@@ -922,13 +971,15 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) {
FunctionArgList Args;
// FIXME: This leaks
ImplicitParamDecl *Dst =
- ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+ ImplicitParamDecl::Create(getContext(), 0,
+ SourceLocation(), 0,
getContext().getPointerType(getContext().VoidTy));
Args.push_back(std::make_pair(Dst, Dst->getType()));
// FIXME: This leaks
ImplicitParamDecl *Src =
- ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+ ImplicitParamDecl::Create(getContext(), 0,
+ SourceLocation(), 0,
getContext().getPointerType(getContext().VoidTy));
Args.push_back(std::make_pair(Src, Src->getType()));
@@ -991,7 +1042,8 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T,
FunctionArgList Args;
// FIXME: This leaks
ImplicitParamDecl *Src =
- ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+ ImplicitParamDecl::Create(getContext(), 0,
+ SourceLocation(), 0,
getContext().getPointerType(getContext().VoidTy));
Args.push_back(std::make_pair(Src, Src->getType()));
diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h
index 3a860c0..3ab4efb 100644
--- a/lib/CodeGen/CGBlocks.h
+++ b/lib/CodeGen/CGBlocks.h
@@ -115,15 +115,8 @@ public:
PtrToInt8Ty = llvm::Type::getInt8PtrTy(M.getContext());
}
- bool BlockRequiresCopying(QualType Ty) {
- if (Ty->isBlockPointerType())
- return true;
- if (getContext().isObjCNSObjectType(Ty))
- return true;
- if (Ty->isObjCObjectPointerType())
- return true;
- return false;
- }
+ bool BlockRequiresCopying(QualType Ty)
+ { return getContext().BlockRequiresCopying(Ty); }
};
class BlockFunction : public BlockBase {
@@ -165,11 +158,7 @@ public:
/// ByCopyDeclRefs - Variables from parent scopes that have been imported
/// into this block.
- llvm::SmallVector<const BlockDeclRefExpr *, 8> ByCopyDeclRefs;
-
- // ByRefDeclRefs - __block variables from parent scopes that have been
- // imported into this block.
- llvm::SmallVector<const BlockDeclRefExpr *, 8> ByRefDeclRefs;
+ llvm::SmallVector<const BlockDeclRefExpr *, 8> DeclRefs;
BlockInfo(const llvm::Type *blt, const char *n)
: BlockLiteralTy(blt), Name(n) {
@@ -228,7 +217,8 @@ public:
llvm::Value *getBlockObjectDispose();
void BuildBlockRelease(llvm::Value *DeclPtr, int flag = BLOCK_FIELD_IS_BYREF);
- bool BlockRequiresCopying(QualType Ty);
+ bool BlockRequiresCopying(QualType Ty)
+ { return getContext().BlockRequiresCopying(Ty); }
};
} // end namespace CodeGen
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 3960cf5..cfa669d 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -590,12 +590,15 @@ void
CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
const CXXConstructExpr *E) {
assert(Dest && "Must have a destination!");
-
- const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl());
- if (RD->hasTrivialConstructor())
+ const CXXConstructorDecl *CD = E->getConstructor();
+ // For a copy constructor, even if it is trivial, must fall thru so
+ // its argument is code-gen'ed.
+ if (!CD->isCopyConstructor(getContext())) {
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl());
+ if (RD->hasTrivialConstructor())
return;
-
+ }
// Code gen optimization to eliminate copy constructor and return
// its first argument instead.
if (getContext().getLangOptions().ElideConstructors && E->isElidable()) {
@@ -604,7 +607,7 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
return;
}
// Call the constructor.
- EmitCXXConstructorCall(E->getConstructor(), Ctor_Complete, Dest,
+ EmitCXXConstructorCall(CD, Ctor_Complete, Dest,
E->arg_begin(), E->arg_end());
}
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index bad166f..7865516 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -639,9 +639,8 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
// If this structure was expanded into multiple arguments then
// we need to create a temporary and reconstruct it from the
// arguments.
- std::string Name = Arg->getNameAsString();
llvm::Value *Temp = CreateTempAlloca(ConvertTypeForMem(Ty),
- (Name + ".addr").c_str());
+ Arg->getName() + ".addr");
// FIXME: What are the right qualifiers here?
llvm::Function::arg_iterator End =
ExpandTypeFromArgs(Ty, LValue::MakeAddr(Temp, Qualifiers()), AI);
@@ -650,7 +649,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
// Name the arguments used in expansion and increment AI.
unsigned Index = 0;
for (; AI != End; ++AI, ++Index)
- AI->setName(Name + "." + llvm::Twine(Index));
+ AI->setName(Arg->getName() + "." + llvm::Twine(Index));
continue;
}
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 4c62420..1b01e15 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -173,10 +173,14 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT,
uint64_t Align = M->getContext().getTypeAlign(BT);
uint64_t Offset = 0;
- return DebugFactory.CreateBasicType(Unit,
- BT->getName(M->getContext().getLangOptions()),
- Unit, 0, Size, Align,
- Offset, /*flags*/ 0, Encoding);
+ llvm::DIType DbgTy =
+ DebugFactory.CreateBasicType(Unit,
+ BT->getName(M->getContext().getLangOptions()),
+ Unit, 0, Size, Align,
+ Offset, /*flags*/ 0, Encoding);
+
+ TypeCache[QualType(BT, 0).getAsOpaquePtr()] = DbgTy.getNode();
+ return DbgTy;
}
llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty,
@@ -190,9 +194,12 @@ llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty,
uint64_t Align = M->getContext().getTypeAlign(Ty);
uint64_t Offset = 0;
- return DebugFactory.CreateBasicType(Unit, "complex",
- Unit, 0, Size, Align,
- Offset, /*flags*/ 0, Encoding);
+ llvm::DIType DbgTy =
+ DebugFactory.CreateBasicType(Unit, "complex",
+ Unit, 0, Size, Align,
+ Offset, /*flags*/ 0, Encoding);
+ TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
+ return DbgTy;
}
/// CreateCVRType - Get the qualified type from the cache or create
@@ -226,8 +233,11 @@ llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DICompileUnit U
// No need to fill in the Name, Line, Size, Alignment, Offset in case of
// CVR derived types.
- return DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DICompileUnit(),
- 0, 0, 0, 0, 0, FromTy);
+ llvm::DIType DbgTy =
+ DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DICompileUnit(),
+ 0, 0, 0, 0, 0, FromTy);
+ TypeCache[Ty.getAsOpaquePtr()] = DbgTy.getNode();
+ return DbgTy;
}
llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
@@ -238,9 +248,12 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
uint64_t Size = M->getContext().getTypeSize(Ty);
uint64_t Align = M->getContext().getTypeAlign(Ty);
- return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
- "", llvm::DICompileUnit(),
- 0, Size, Align, 0, 0, EltTy);
+ llvm::DIType DbgTy =
+ DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
+ "", llvm::DICompileUnit(),
+ 0, Size, Align, 0, 0, EltTy);
+ TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
+ return DbgTy;
}
llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty,
@@ -251,9 +264,10 @@ llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty,
uint64_t Size = M->getContext().getTypeSize(Ty);
uint64_t Align = M->getContext().getTypeAlign(Ty);
- return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
- "", llvm::DICompileUnit(),
- 0, Size, Align, 0, 0, EltTy);
+ return
+ DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
+ "", llvm::DICompileUnit(),
+ 0, Size, Align, 0, 0, EltTy);
}
llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
@@ -401,8 +415,11 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty,
PresumedLoc PLoc = SM.getPresumedLoc(DefLoc);
unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine();
- return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_typedef, Unit,
- TyName, DefUnit, Line, 0, 0, 0, 0, Src);
+ llvm::DIType DbgTy =
+ DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_typedef, Unit,
+ TyName, DefUnit, Line, 0, 0, 0, 0, Src);
+ TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
+ return DbgTy;
}
llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
@@ -424,10 +441,13 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
llvm::DIArray EltTypeArray =
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
- return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type,
- Unit, "", llvm::DICompileUnit(),
- 0, 0, 0, 0, 0,
- llvm::DIType(), EltTypeArray);
+ llvm::DIType DbgTy =
+ DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type,
+ Unit, "", llvm::DICompileUnit(),
+ 0, 0, 0, 0, 0,
+ llvm::DIType(), EltTypeArray);
+ TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
+ return DbgTy;
}
/// CreateType - get structure or union type.
@@ -713,10 +733,14 @@ llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty,
Align = M->getContext().getTypeAlign(Ty);
}
- return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type,
- Unit, EnumName, DefUnit, Line,
- Size, Align, 0, 0,
- llvm::DIType(), EltArray);
+ llvm::DIType DbgTy =
+ DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type,
+ Unit, EnumName, DefUnit, Line,
+ Size, Align, 0, 0,
+ llvm::DIType(), EltArray);
+
+ TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
+ return DbgTy;
}
llvm::DIType CGDebugInfo::CreateType(const TagType *Ty,
@@ -767,11 +791,15 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
llvm::DIArray SubscriptArray =
DebugFactory.GetOrCreateArray(Subscripts.data(), Subscripts.size());
- return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_array_type,
- Unit, "", llvm::DICompileUnit(),
- 0, Size, Align, 0, 0,
- getOrCreateType(EltTy, Unit),
- SubscriptArray);
+ llvm::DIType DbgTy =
+ DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_array_type,
+ Unit, "", llvm::DICompileUnit(),
+ 0, Size, Align, 0, 0,
+ getOrCreateType(EltTy, Unit),
+ SubscriptArray);
+
+ TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
+ return DbgTy;
}
@@ -793,7 +821,6 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty,
// Otherwise create the type.
llvm::DIType Res = CreateTypeNode(Ty, Unit);
- TypeCache.insert(std::make_pair(Ty.getAsOpaquePtr(), Res.getNode()));
return Res;
}
@@ -846,8 +873,6 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
Unit);
case Type::ConstantArray:
- case Type::ConstantArrayWithExpr:
- case Type::ConstantArrayWithoutExpr:
case Type::VariableArray:
case Type::IncompleteArray:
return CreateType(cast<ArrayType>(Ty), Unit);
@@ -863,7 +888,7 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
/// EmitFunctionStart - Constructs the debug code for entering a function -
/// "llvm.dbg.func.start.".
-void CGDebugInfo::EmitFunctionStart(const char *Name, QualType ReturnType,
+void CGDebugInfo::EmitFunctionStart(const char *Name, QualType FnType,
llvm::Function *Fn,
CGBuilderTy &Builder) {
const char *LinkageName = Name;
@@ -881,7 +906,7 @@ void CGDebugInfo::EmitFunctionStart(const char *Name, QualType ReturnType,
llvm::DISubprogram SP =
DebugFactory.CreateSubprogram(Unit, Name, Name, LinkageName, Unit, LineNo,
- getOrCreateType(ReturnType, Unit),
+ getOrCreateType(FnType, Unit),
Fn->hasInternalLinkage(), true/*definition*/);
#ifndef ATTACH_DEBUG_INFO_TO_AN_INSN
@@ -1366,7 +1391,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
}
DebugFactory.CreateGlobalVariable(getContext(Decl, Unit),
- Name, Name, "", Unit, LineNo,
+ Name, Name, Name, Unit, LineNo,
getOrCreateType(T, Unit),
Var->hasInternalLinkage(),
true/*definition*/, Var);
@@ -1396,7 +1421,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
ArrayType::Normal, 0);
}
- DebugFactory.CreateGlobalVariable(Unit, Name, Name, "", Unit, LineNo,
+ DebugFactory.CreateGlobalVariable(Unit, Name, Name, Name, Unit, LineNo,
getOrCreateType(T, Unit),
Var->hasInternalLinkage(),
true/*definition*/, Var);
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index 0a617b9..2e44e09 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -88,7 +88,7 @@ public:
/// EmitFunctionStart - Emit a call to llvm.dbg.function.start to indicate
/// start of a new function.
- void EmitFunctionStart(const char *Name, QualType ReturnType,
+ void EmitFunctionStart(const char *Name, QualType FnType,
llvm::Function *Fn, CGBuilderTy &Builder);
/// EmitRegionStart - Emit a call to llvm.dbg.region.start to indicate start
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 7feff83..1728c67 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -37,6 +37,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
case Decl::Enum: // enum X;
case Decl::EnumConstant: // enum ? { X = ? }
case Decl::CXXRecord: // struct/union/class X; [C++]
+ case Decl::UsingDirective: // using X; [C++]
// None of these decls require codegen support.
return;
@@ -275,8 +276,8 @@ const llvm::Type *CodeGenFunction::BuildByRefType(const ValueDecl *D) {
unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes;
if (NumPaddingBytes > 0) {
const llvm::Type *Ty = llvm::Type::getInt8Ty(VMContext);
- // FIXME: We need a sema error for alignment larger than the minimum of the
- // maximal stack alignmint and the alignment of malloc on the system.
+ // FIXME: We need a sema error for alignment larger than the minimum of
+ // the maximal stack alignmint and the alignment of malloc on the system.
if (NumPaddingBytes > 1)
Ty = llvm::ArrayType::get(Ty, NumPaddingBytes);
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 01a057f..bb487f6 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -28,9 +28,9 @@ using namespace CodeGen;
/// CreateTempAlloca - This creates a alloca and inserts it into the entry
/// block.
llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(const llvm::Type *Ty,
- const char *Name) {
+ const llvm::Twine &Name) {
if (!Builder.isNamePreserving())
- Name = "";
+ return new llvm::AllocaInst(Ty, 0, "", AllocaInsertPt);
return new llvm::AllocaInst(Ty, 0, Name, AllocaInsertPt);
}
@@ -78,24 +78,18 @@ RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E,
RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
QualType DestType,
bool IsInitializer) {
+ bool ShouldDestroyTemporaries = false;
+ unsigned OldNumLiveTemporaries = 0;
+
if (const CXXExprWithTemporaries *TE = dyn_cast<CXXExprWithTemporaries>(E)) {
- // If we shouldn't destroy the temporaries, just emit the
- // child expression.
- if (!TE->shouldDestroyTemporaries())
- return EmitReferenceBindingToExpr(TE->getSubExpr(), DestType,
- IsInitializer);
-
- // Keep track of the current cleanup stack depth.
- unsigned OldNumLiveTemporaries = LiveTemporaries.size();
-
- RValue RV = EmitReferenceBindingToExpr(TE->getSubExpr(), DestType,
- IsInitializer);
-
- // Pop temporaries.
- while (LiveTemporaries.size() > OldNumLiveTemporaries)
- PopCXXTemporary();
+ ShouldDestroyTemporaries = TE->shouldDestroyTemporaries();
+
+ if (ShouldDestroyTemporaries) {
+ // Keep track of the current cleanup stack depth.
+ OldNumLiveTemporaries = LiveTemporaries.size();
+ }
- return RV;
+ E = TE->getSubExpr();
}
RValue Val;
@@ -105,6 +99,12 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
if (LV.isSimple())
return RValue::get(LV.getAddress());
Val = EmitLoadOfLValue(LV, E->getType());
+
+ if (ShouldDestroyTemporaries) {
+ // Pop temporaries.
+ while (LiveTemporaries.size() > OldNumLiveTemporaries)
+ PopCXXTemporary();
+ }
} else {
const CXXRecordDecl *BaseClassDecl = 0;
const CXXRecordDecl *DerivedClassDecl = 0;
@@ -124,6 +124,12 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
Val = EmitAnyExprToTemp(E, /*IsAggLocVolatile=*/false,
IsInitializer);
+ if (ShouldDestroyTemporaries) {
+ // Pop temporaries.
+ while (LiveTemporaries.size() > OldNumLiveTemporaries)
+ PopCXXTemporary();
+ }
+
if (IsInitializer) {
// We might have to destroy the temporary variable.
if (const RecordType *RT = E->getType()->getAs<RecordType>()) {
@@ -297,6 +303,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
case Expr::CXXReinterpretCastExprClass:
case Expr::CXXConstCastExprClass:
return EmitCastLValue(cast<CastExpr>(E));
+ case Expr::CXXZeroInitValueExprClass:
+ return EmitNullInitializationLValue(cast<CXXZeroInitValueExpr>(E));
}
}
@@ -858,6 +866,9 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
llvm::Value *V = LocalDeclMap[IPD];
assert(V && "BlockVarDecl not entered in LocalDeclMap?");
return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
+ } else if (const QualifiedDeclRefExpr *QDRExpr =
+ dyn_cast<QualifiedDeclRefExpr>(E)) {
+ return EmitPointerToDataMemberLValue(QDRExpr);
}
assert(0 && "Unimp declref");
//an invalid LValue, but the assert will
@@ -1307,6 +1318,18 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
}
}
+LValue CodeGenFunction::EmitNullInitializationLValue(
+ const CXXZeroInitValueExpr *E) {
+ QualType Ty = E->getType();
+ const llvm::Type *LTy = ConvertTypeForMem(Ty);
+ llvm::AllocaInst *Alloc = CreateTempAlloca(LTy);
+ unsigned Align = getContext().getTypeAlign(Ty)/8;
+ Alloc->setAlignment(Align);
+ LValue lvalue = LValue::MakeAddr(Alloc, Qualifiers());
+ EmitMemSetToZero(lvalue.getAddress(), Ty);
+ return lvalue;
+}
+
//===--------------------------------------------------------------------===//
// Expression Emission
//===--------------------------------------------------------------------===//
@@ -1356,11 +1379,24 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
return EmitLValue(E->getRHS());
}
+ if (E->getOpcode() == BinaryOperator::PtrMemD)
+ return EmitPointerToDataMemberBinaryExpr(E);
+
// Can only get l-value for binary operator expressions which are a
// simple assignment of aggregate type.
if (E->getOpcode() != BinaryOperator::Assign)
return EmitUnsupportedLValue(E, "binary l-value expression");
+ if (!hasAggregateLLVMType(E->getType())) {
+ // Emit the LHS as an l-value.
+ LValue LV = EmitLValue(E->getLHS());
+
+ llvm::Value *RHS = EmitScalarExpr(E->getRHS());
+ EmitStoreOfScalar(RHS, LV.getAddress(), LV.isVolatileQualified(),
+ E->getType());
+ return LV;
+ }
+
llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType()));
EmitAggExpr(E, Temp, false);
// FIXME: Are these qualifiers correct?
@@ -1483,6 +1519,25 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) {
}
+LValue CodeGenFunction::EmitPointerToDataMemberLValue(
+ const QualifiedDeclRefExpr *E) {
+ const FieldDecl *Field = cast<FieldDecl>(E->getDecl());
+ const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Field->getDeclContext());
+ QualType NNSpecTy =
+ getContext().getCanonicalType(
+ getContext().getTypeDeclType(const_cast<CXXRecordDecl*>(ClassDecl)));
+ NNSpecTy = getContext().getPointerType(NNSpecTy);
+ llvm::Value *V = llvm::Constant::getNullValue(ConvertType(NNSpecTy));
+ LValue MemExpLV = EmitLValueForField(V, const_cast<FieldDecl*>(Field),
+ /*isUnion*/false, /*Qualifiers*/0);
+ const llvm::Type* ResultType = ConvertType(
+ getContext().getPointerDiffType());
+ V = Builder.CreatePtrToInt(MemExpLV.getAddress(), ResultType,
+ "datamember");
+ LValue LV = LValue::MakeAddr(V, MakeQualifiers(E->getType()));
+ return LV;
+}
+
RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd,
@@ -1492,11 +1547,13 @@ RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType,
assert(CalleeType->isFunctionPointerType() &&
"Call must have function pointer type!");
- QualType FnType = CalleeType->getAs<PointerType>()->getPointeeType();
- QualType ResultType = FnType->getAs<FunctionType>()->getResultType();
+ CalleeType = getContext().getCanonicalType(CalleeType);
+
+ QualType FnType = cast<PointerType>(CalleeType)->getPointeeType();
+ QualType ResultType = cast<FunctionType>(FnType)->getResultType();
CallArgList Args;
- EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), ArgBeg, ArgEnd);
+ EmitCallArgs(Args, dyn_cast<FunctionProtoType>(FnType), ArgBeg, ArgEnd);
// FIXME: We should not need to do this, it should be part of the function
// type.
@@ -1508,3 +1565,25 @@ RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType,
CallingConvention),
Callee, Args, TargetDecl);
}
+
+LValue CodeGenFunction::EmitPointerToDataMemberBinaryExpr(
+ const BinaryOperator *E) {
+ llvm::Value *BaseV = EmitLValue(E->getLHS()).getAddress();
+ const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(getLLVMContext());
+ BaseV = Builder.CreateBitCast(BaseV, i8Ty);
+ LValue RHSLV = EmitLValue(E->getRHS());
+ llvm::Value *OffsetV =
+ EmitLoadOfLValue(RHSLV, E->getRHS()->getType()).getScalarVal();
+ const llvm::Type* ResultType = ConvertType(getContext().getPointerDiffType());
+ OffsetV = Builder.CreateBitCast(OffsetV, ResultType);
+ llvm::Value *AddV = Builder.CreateInBoundsGEP(BaseV, OffsetV, "add.ptr");
+ QualType Ty = E->getRHS()->getType();
+ const MemberPointerType *MemPtrType = Ty->getAs<MemberPointerType>();
+ Ty = MemPtrType->getPointeeType();
+ const llvm::Type* PType =
+ ConvertType(getContext().getPointerType(Ty));
+ AddV = Builder.CreateBitCast(AddV, PType);
+ LValue LV = LValue::MakeAddr(AddV, MakeQualifiers(Ty));
+ return LV;
+}
+
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 0866ff8..f47b6ab 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -92,6 +92,7 @@ public:
void VisitCallExpr(const CallExpr *E);
void VisitStmtExpr(const StmtExpr *E);
void VisitBinaryOperator(const BinaryOperator *BO);
+ void VisitPointerToDataMemberBinaryOperator(const BinaryOperator *BO);
void VisitBinAssign(const BinaryOperator *E);
void VisitBinComma(const BinaryOperator *E);
void VisitUnaryAddrOf(const UnaryOperator *E);
@@ -112,6 +113,7 @@ public:
void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
void VisitCXXConstructExpr(const CXXConstructExpr *E);
void VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E);
+ void VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E);
void VisitVAArgExpr(VAArgExpr *E);
@@ -214,6 +216,12 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
break;
}
+ case CastExpr::CK_BitCast: {
+ // This must be a member function pointer cast.
+ Visit(E->getSubExpr());
+ break;
+ }
+
case CastExpr::CK_BaseToDerivedMemberPointer: {
QualType SrcType = E->getSubExpr()->getType();
@@ -285,6 +293,7 @@ void AggExprEmitter::VisitBinComma(const BinaryOperator *E) {
void AggExprEmitter::VisitUnaryAddrOf(const UnaryOperator *E) {
// We have a member function pointer.
const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>();
+ (void) MPT;
assert(MPT->getPointeeType()->isFunctionProtoType() &&
"Unexpected member pointer type!");
@@ -320,7 +329,16 @@ void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) {
}
void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) {
- CGF.ErrorUnsupported(E, "aggregate binary expression");
+ if (E->getOpcode() == BinaryOperator::PtrMemD)
+ VisitPointerToDataMemberBinaryOperator(E);
+ else
+ CGF.ErrorUnsupported(E, "aggregate binary expression");
+}
+
+void AggExprEmitter::VisitPointerToDataMemberBinaryOperator(
+ const BinaryOperator *E) {
+ LValue LV = CGF.EmitPointerToDataMemberBinaryExpr(E);
+ EmitFinalDestCopy(E, LV);
}
void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
@@ -438,6 +456,11 @@ void AggExprEmitter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) {
CGF.EmitCXXExprWithTemporaries(E, DestPtr, VolatileDest, IsInitializer);
}
+void AggExprEmitter::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) {
+ LValue lvalue = LValue::MakeAddr(DestPtr, Qualifiers());
+ EmitNullInitializationToLValue(lvalue, E->getType());
+}
+
void AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV) {
// FIXME: Ignore result?
// FIXME: Are initializers affected by volatile?
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 7f540c3..fc3748c 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -542,7 +542,11 @@ public:
return CS;
}
}
-
+
+ case CastExpr::CK_BitCast:
+ // This must be a member function pointer cast.
+ return Visit(E->getSubExpr());
+
default: {
// FIXME: This should be handled by the CK_NoOp cast kind.
// Explicit and implicit no-op casts
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index cc81256..69604f9 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -106,6 +106,7 @@ public:
return 0;
}
Value *VisitExpr(Expr *S);
+
Value *VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr()); }
// Leaves.
@@ -181,48 +182,7 @@ public:
Value *VisitPredefinedExpr(Expr *E) { return EmitLValue(E).getAddress(); }
- Value *VisitInitListExpr(InitListExpr *E) {
- bool Ignore = TestAndClearIgnoreResultAssign();
- (void)Ignore;
- assert (Ignore == false && "init list ignored");
- unsigned NumInitElements = E->getNumInits();
-
- if (E->hadArrayRangeDesignator()) {
- CGF.ErrorUnsupported(E, "GNU array range designator extension");
- }
-
- const llvm::VectorType *VType =
- dyn_cast<llvm::VectorType>(ConvertType(E->getType()));
-
- // We have a scalar in braces. Just use the first element.
- if (!VType)
- return Visit(E->getInit(0));
-
- unsigned NumVectorElements = VType->getNumElements();
- const llvm::Type *ElementType = VType->getElementType();
-
- // Emit individual vector element stores.
- llvm::Value *V = llvm::UndefValue::get(VType);
-
- // Emit initializers
- unsigned i;
- for (i = 0; i < NumInitElements; ++i) {
- Value *NewV = Visit(E->getInit(i));
- Value *Idx =
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()), i);
- V = Builder.CreateInsertElement(V, NewV, Idx);
- }
-
- // Emit remaining default initializers
- for (/* Do not initialize i*/; i < NumVectorElements; ++i) {
- Value *Idx =
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()), i);
- llvm::Value *NewV = llvm::Constant::getNullValue(ElementType);
- V = Builder.CreateInsertElement(V, NewV, Idx);
- }
-
- return V;
- }
+ Value *VisitInitListExpr(InitListExpr *E);
Value *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
return llvm::Constant::getNullValue(ConvertType(E->getType()));
@@ -404,7 +364,7 @@ public:
/// EmitConversionToBool - Convert the specified expression value to a
/// boolean (i1) truth value. This is equivalent to "Val != 0".
Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) {
- assert(SrcType->isCanonical() && "EmitScalarConversion strips typedefs");
+ assert(SrcType.isCanonical() && "EmitScalarConversion strips typedefs");
if (SrcType->isRealFloatingType()) {
// Compare against 0.0 for fp scalars.
@@ -577,6 +537,13 @@ EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,
//===----------------------------------------------------------------------===//
Value *ScalarExprEmitter::VisitExpr(Expr *E) {
+ if (const BinaryOperator *BExpr = dyn_cast<BinaryOperator>(E))
+ if (BExpr->getOpcode() == BinaryOperator::PtrMemD) {
+ LValue LV = CGF.EmitPointerToDataMemberBinaryExpr(BExpr);
+ Value *InVal = CGF.EmitLoadOfLValue(LV, E->getType()).getScalarVal();
+ return InVal;
+ }
+
CGF.ErrorUnsupported(E, "scalar expression");
if (E->getType()->isVoidType())
return 0;
@@ -616,6 +583,174 @@ Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
return Builder.CreateExtractElement(Base, Idx, "vecext");
}
+static llvm::Constant *getMaskElt(llvm::ShuffleVectorInst *SVI, unsigned Idx,
+ unsigned Off, const llvm::Type *I32Ty) {
+ int MV = SVI->getMaskValue(Idx);
+ if (MV == -1)
+ return llvm::UndefValue::get(I32Ty);
+ return llvm::ConstantInt::get(I32Ty, Off+MV);
+}
+
+Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) {
+ bool Ignore = TestAndClearIgnoreResultAssign();
+ (void)Ignore;
+ assert (Ignore == false && "init list ignored");
+ unsigned NumInitElements = E->getNumInits();
+
+ if (E->hadArrayRangeDesignator())
+ CGF.ErrorUnsupported(E, "GNU array range designator extension");
+
+ const llvm::VectorType *VType =
+ dyn_cast<llvm::VectorType>(ConvertType(E->getType()));
+
+ // We have a scalar in braces. Just use the first element.
+ if (!VType)
+ return Visit(E->getInit(0));
+
+ unsigned ResElts = VType->getNumElements();
+ const llvm::Type *I32Ty = llvm::Type::getInt32Ty(CGF.getLLVMContext());
+
+ // Loop over initializers collecting the Value for each, and remembering
+ // whether the source was swizzle (ExtVectorElementExpr). This will allow
+ // us to fold the shuffle for the swizzle into the shuffle for the vector
+ // initializer, since LLVM optimizers generally do not want to touch
+ // shuffles.
+ unsigned CurIdx = 0;
+ bool VIsUndefShuffle = false;
+ llvm::Value *V = llvm::UndefValue::get(VType);
+ for (unsigned i = 0; i != NumInitElements; ++i) {
+ Expr *IE = E->getInit(i);
+ Value *Init = Visit(IE);
+ llvm::SmallVector<llvm::Constant*, 16> Args;
+
+ const llvm::VectorType *VVT = dyn_cast<llvm::VectorType>(Init->getType());
+
+ // Handle scalar elements. If the scalar initializer is actually one
+ // element of a different vector of the same width, use shuffle instead of
+ // extract+insert.
+ if (!VVT) {
+ if (isa<ExtVectorElementExpr>(IE)) {
+ llvm::ExtractElementInst *EI = cast<llvm::ExtractElementInst>(Init);
+
+ if (EI->getVectorOperandType()->getNumElements() == ResElts) {
+ llvm::ConstantInt *C = cast<llvm::ConstantInt>(EI->getIndexOperand());
+ Value *LHS = 0, *RHS = 0;
+ if (CurIdx == 0) {
+ // insert into undef -> shuffle (src, undef)
+ Args.push_back(C);
+ for (unsigned j = 1; j != ResElts; ++j)
+ Args.push_back(llvm::UndefValue::get(I32Ty));
+
+ LHS = EI->getVectorOperand();
+ RHS = V;
+ VIsUndefShuffle = true;
+ } else if (VIsUndefShuffle) {
+ // insert into undefshuffle && size match -> shuffle (v, src)
+ llvm::ShuffleVectorInst *SVV = cast<llvm::ShuffleVectorInst>(V);
+ for (unsigned j = 0; j != CurIdx; ++j)
+ Args.push_back(getMaskElt(SVV, j, 0, I32Ty));
+ Args.push_back(llvm::ConstantInt::get(I32Ty,
+ ResElts + C->getZExtValue()));
+ for (unsigned j = CurIdx + 1; j != ResElts; ++j)
+ Args.push_back(llvm::UndefValue::get(I32Ty));
+
+ LHS = cast<llvm::ShuffleVectorInst>(V)->getOperand(0);
+ RHS = EI->getVectorOperand();
+ VIsUndefShuffle = false;
+ }
+ if (!Args.empty()) {
+ llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], ResElts);
+ V = Builder.CreateShuffleVector(LHS, RHS, Mask);
+ ++CurIdx;
+ continue;
+ }
+ }
+ }
+ Value *Idx = llvm::ConstantInt::get(I32Ty, CurIdx);
+ V = Builder.CreateInsertElement(V, Init, Idx, "vecinit");
+ VIsUndefShuffle = false;
+ ++CurIdx;
+ continue;
+ }
+
+ unsigned InitElts = VVT->getNumElements();
+
+ // If the initializer is an ExtVecEltExpr (a swizzle), and the swizzle's
+ // input is the same width as the vector being constructed, generate an
+ // optimized shuffle of the swizzle input into the result.
+ if (isa<ExtVectorElementExpr>(IE)) {
+ llvm::ShuffleVectorInst *SVI = cast<llvm::ShuffleVectorInst>(Init);
+ Value *SVOp = SVI->getOperand(0);
+ const llvm::VectorType *OpTy = cast<llvm::VectorType>(SVOp->getType());
+
+ if (OpTy->getNumElements() == ResElts) {
+ unsigned Offset = (CurIdx == 0) ? 0 : ResElts;
+
+ for (unsigned j = 0; j != CurIdx; ++j) {
+ // If the current vector initializer is a shuffle with undef, merge
+ // this shuffle directly into it.
+ if (VIsUndefShuffle) {
+ Args.push_back(getMaskElt(cast<llvm::ShuffleVectorInst>(V), j, 0,
+ I32Ty));
+ } else {
+ Args.push_back(llvm::ConstantInt::get(I32Ty, j));
+ }
+ }
+ for (unsigned j = 0, je = InitElts; j != je; ++j)
+ Args.push_back(getMaskElt(SVI, j, Offset, I32Ty));
+ for (unsigned j = CurIdx + InitElts; j != ResElts; ++j)
+ Args.push_back(llvm::UndefValue::get(I32Ty));
+
+ if (VIsUndefShuffle)
+ V = cast<llvm::ShuffleVectorInst>(V)->getOperand(0);
+
+ Init = SVOp;
+ }
+ }
+
+ // Extend init to result vector length, and then shuffle its contribution
+ // to the vector initializer into V.
+ if (Args.empty()) {
+ for (unsigned j = 0; j != InitElts; ++j)
+ Args.push_back(llvm::ConstantInt::get(I32Ty, j));
+ for (unsigned j = InitElts; j != ResElts; ++j)
+ Args.push_back(llvm::UndefValue::get(I32Ty));
+ llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], ResElts);
+ Init = Builder.CreateShuffleVector(Init, llvm::UndefValue::get(VVT),
+ Mask, "vecext");
+
+ Args.clear();
+ for (unsigned j = 0; j != CurIdx; ++j)
+ Args.push_back(llvm::ConstantInt::get(I32Ty, j));
+ for (unsigned j = 0; j != InitElts; ++j)
+ Args.push_back(llvm::ConstantInt::get(I32Ty, j+ResElts));
+ for (unsigned j = CurIdx + InitElts; j != ResElts; ++j)
+ Args.push_back(llvm::UndefValue::get(I32Ty));
+ }
+
+ // If V is undef, make sure it ends up on the RHS of the shuffle to aid
+ // merging subsequent shuffles into this one.
+ if (CurIdx == 0)
+ std::swap(V, Init);
+ llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], ResElts);
+ V = Builder.CreateShuffleVector(V, Init, Mask, "vecinit");
+ VIsUndefShuffle = isa<llvm::UndefValue>(Init);
+ CurIdx += InitElts;
+ }
+
+ // FIXME: evaluate codegen vs. shuffling against constant null vector.
+ // Emit remaining default initializers.
+ const llvm::Type *EltTy = VType->getElementType();
+
+ // Emit remaining default initializers
+ for (/* Do not initialize i*/; CurIdx < ResElts; ++CurIdx) {
+ Value *Idx = llvm::ConstantInt::get(I32Ty, CurIdx);
+ llvm::Value *Init = llvm::Constant::getNullValue(EltTy);
+ V = Builder.CreateInsertElement(V, Init, Idx, "vecinit");
+ }
+ return V;
+}
+
// VisitCastExpr - Emit code for an explicit or implicit cast. Implicit casts
// have to handle a more broad range of conversions than explicit casts, as they
// handle things like function to ptr-to-function decay etc.
@@ -700,7 +835,16 @@ Value *ScalarExprEmitter::EmitCastExpr(const CastExpr *CE) {
case CastExpr::CK_IntegralToPointer: {
Value *Src = Visit(const_cast<Expr*>(E));
- return Builder.CreateIntToPtr(Src, ConvertType(DestTy));
+
+ // First, convert to the correct width so that we control the kind of
+ // extension.
+ const llvm::Type *MiddleTy =
+ llvm::IntegerType::get(VMContext, CGF.LLVMPointerWidth);
+ bool InputSigned = E->getType()->isSignedIntegerType();
+ llvm::Value* IntResult =
+ Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv");
+
+ return Builder.CreateIntToPtr(IntResult, ConvertType(DestTy));
}
case CastExpr::CK_PointerToIntegral: {
@@ -1379,18 +1523,20 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
}
Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
+ const llvm::Type *ResTy = ConvertType(E->getType());
+
// If we have 0 && RHS, see if we can elide RHS, if so, just return 0.
// If we have 1 && X, just emit X without inserting the control flow.
if (int Cond = CGF.ConstantFoldsToSimpleInteger(E->getLHS())) {
if (Cond == 1) { // If we have 1 && X, just emit X.
Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
- // ZExt result to int.
- return Builder.CreateZExt(RHSCond, CGF.LLVMIntTy, "land.ext");
+ // ZExt result to int or bool.
+ return Builder.CreateZExtOrBitCast(RHSCond, ResTy, "land.ext");
}
- // 0 && RHS: If it is safe, just elide the RHS, and return 0.
+ // 0 && RHS: If it is safe, just elide the RHS, and return 0/false.
if (!CGF.ContainsLabel(E->getRHS()))
- return llvm::Constant::getNullValue(CGF.LLVMIntTy);
+ return llvm::Constant::getNullValue(ResTy);
}
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("land.end");
@@ -1423,22 +1569,24 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
PN->addIncoming(RHSCond, RHSBlock);
// ZExt result to int.
- return Builder.CreateZExt(PN, CGF.LLVMIntTy, "land.ext");
+ return Builder.CreateZExtOrBitCast(PN, ResTy, "land.ext");
}
Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
+ const llvm::Type *ResTy = ConvertType(E->getType());
+
// If we have 1 || RHS, see if we can elide RHS, if so, just return 1.
// If we have 0 || X, just emit X without inserting the control flow.
if (int Cond = CGF.ConstantFoldsToSimpleInteger(E->getLHS())) {
if (Cond == -1) { // If we have 0 || X, just emit X.
Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
- // ZExt result to int.
- return Builder.CreateZExt(RHSCond, CGF.LLVMIntTy, "lor.ext");
+ // ZExt result to int or bool.
+ return Builder.CreateZExtOrBitCast(RHSCond, ResTy, "lor.ext");
}
- // 1 || RHS: If it is safe, just elide the RHS, and return 1.
+ // 1 || RHS: If it is safe, just elide the RHS, and return 1/true.
if (!CGF.ContainsLabel(E->getRHS()))
- return llvm::ConstantInt::get(CGF.LLVMIntTy, 1);
+ return llvm::ConstantInt::get(ResTy, 1);
}
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("lor.end");
@@ -1474,7 +1622,7 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
PN->addIncoming(RHSCond, RHSBlock);
// ZExt result to int.
- return Builder.CreateZExt(PN, CGF.LLVMIntTy, "lor.ext");
+ return Builder.CreateZExtOrBitCast(PN, ResTy, "lor.ext");
}
Value *ScalarExprEmitter::VisitBinComma(const BinaryOperator *E) {
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 4485ed5..9b2f4a1 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -850,7 +850,7 @@ protected:
/// \param[out] NameOut - The return value.
void GetNameForMethod(const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD,
- std::string &NameOut);
+ llvm::SmallVectorImpl<char> &NameOut);
/// GetMethodVarName - Return a unique constant for the given
/// selector's name. The return value has type char *.
@@ -900,7 +900,7 @@ protected:
/// EmitPropertyList - Emit the given property list. The return
/// value has type PropertyListPtrTy.
- llvm::Constant *EmitPropertyList(const std::string &Name,
+ llvm::Constant *EmitPropertyList(llvm::Twine Name,
const Decl *Container,
const ObjCContainerDecl *OCD,
const ObjCCommonTypesHelper &ObjCTypes);
@@ -924,7 +924,7 @@ protected:
/// \param Align - The alignment for the variable, or 0.
/// \param AddToUsed - Whether the variable should be added to
/// "llvm.used".
- llvm::GlobalVariable *CreateMetadataVar(const std::string &Name,
+ llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name,
llvm::Constant *Init,
const char *Section,
unsigned Align,
@@ -1025,7 +1025,7 @@ private:
/// EmitMethodList - Emit the method list for the given
/// implementation. The return value has type MethodListPtrTy.
- llvm::Constant *EmitMethodList(const std::string &Name,
+ llvm::Constant *EmitMethodList(llvm::Twine Name,
const char *Section,
const ConstantVector &Methods);
@@ -1040,7 +1040,7 @@ private:
/// - begin, end: The method list to output.
///
/// The return value has type MethodDescriptionListPtrTy.
- llvm::Constant *EmitMethodDescList(const std::string &Name,
+ llvm::Constant *EmitMethodDescList(llvm::Twine Name,
const char *Section,
const ConstantVector &Methods);
@@ -1066,7 +1066,7 @@ private:
/// EmitProtocolList - Generate the list of referenced
/// protocols. The return value has type ProtocolListPtrTy.
- llvm::Constant *EmitProtocolList(const std::string &Name,
+ llvm::Constant *EmitProtocolList(llvm::Twine Name,
ObjCProtocolDecl::protocol_iterator begin,
ObjCProtocolDecl::protocol_iterator end);
@@ -1197,7 +1197,7 @@ private:
/// EmitMethodList - Emit the method list for the given
/// implementation. The return value has type MethodListnfABITy.
- llvm::Constant *EmitMethodList(const std::string &Name,
+ llvm::Constant *EmitMethodList(llvm::Twine Name,
const char *Section,
const ConstantVector &Methods);
/// EmitIvarList - Emit the ivar list for the given
@@ -1224,7 +1224,7 @@ private:
/// EmitProtocolList - Generate the list of referenced
/// protocols. The return value has type ProtocolListPtrTy.
- llvm::Constant *EmitProtocolList(const std::string &Name,
+ llvm::Constant *EmitProtocolList(llvm::Twine Name,
ObjCProtocolDecl::protocol_iterator begin,
ObjCProtocolDecl::protocol_iterator end);
@@ -1616,8 +1616,6 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
// resolved. Investigate. Its also wasteful to look this up over and over.
LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
- const char *ProtocolName = PD->getNameAsCString();
-
// Construct method lists.
std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
@@ -1647,17 +1645,15 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
Values[1] = GetClassName(PD->getIdentifier());
Values[2] =
- EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getNameAsString(),
+ EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
PD->protocol_begin(),
PD->protocol_end());
Values[3] =
- EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_"
- + PD->getNameAsString(),
+ EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
"__OBJC,__cat_inst_meth,regular,no_dead_strip",
InstanceMethods);
Values[4] =
- EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_"
- + PD->getNameAsString(),
+ EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
"__OBJC,__cat_cls_meth,regular,no_dead_strip",
ClassMethods);
llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
@@ -1672,7 +1668,7 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
llvm::GlobalValue::InternalLinkage,
Init,
- std::string("\01L_OBJC_PROTOCOL_")+ProtocolName);
+ "\01L_OBJC_PROTOCOL_" + PD->getName());
Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Entry->setAlignment(4);
// FIXME: Is this necessary? Why only for protocol?
@@ -1694,7 +1690,7 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
llvm::GlobalValue::ExternalLinkage,
0,
- "\01L_OBJC_PROTOCOL_" + PD->getNameAsString());
+ "\01L_OBJC_PROTOCOL_" + PD->getName());
Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Entry->setAlignment(4);
// FIXME: Is this necessary? Why only for protocol?
@@ -1722,16 +1718,14 @@ CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Values[1] =
EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
- + PD->getNameAsString(),
+ + PD->getName(),
"__OBJC,__cat_inst_meth,regular,no_dead_strip",
OptInstanceMethods);
Values[2] =
- EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_"
- + PD->getNameAsString(),
+ EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
"__OBJC,__cat_cls_meth,regular,no_dead_strip",
OptClassMethods);
- Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" +
- PD->getNameAsString(),
+ Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(),
0, PD, ObjCTypes);
// Return null if no extension bits are used.
@@ -1743,7 +1737,7 @@ CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
// No special section, but goes in llvm.used
- return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getNameAsString(),
+ return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
Init,
0, 0, true);
}
@@ -1756,7 +1750,7 @@ CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
};
*/
llvm::Constant *
-CGObjCMac::EmitProtocolList(const std::string &Name,
+CGObjCMac::EmitProtocolList(llvm::Twine Name,
ObjCProtocolDecl::protocol_iterator begin,
ObjCProtocolDecl::protocol_iterator end) {
std::vector<llvm::Constant*> ProtocolRefs;
@@ -1800,7 +1794,7 @@ CGObjCMac::EmitProtocolList(const std::string &Name,
struct _objc_property[prop_count];
};
*/
-llvm::Constant *CGObjCCommonMac::EmitPropertyList(const std::string &Name,
+llvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,
const Decl *Container,
const ObjCContainerDecl *OCD,
const ObjCCommonTypesHelper &ObjCTypes) {
@@ -1854,7 +1848,7 @@ CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
Desc);
}
-llvm::Constant *CGObjCMac::EmitMethodDescList(const std::string &Name,
+llvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name,
const char *Section,
const ConstantVector &Methods) {
// Return null for empty list.
@@ -1894,8 +1888,10 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
const ObjCCategoryDecl *Category =
Interface->FindCategoryDeclaration(OCD->getIdentifier());
- std::string ExtName(Interface->getNameAsString() + "_" +
- OCD->getNameAsString());
+
+ llvm::SmallString<256> ExtName;
+ llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
+ << OCD->getName();
std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
for (ObjCCategoryImplDecl::instmeth_iterator
@@ -1914,17 +1910,16 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Values[1] = GetClassName(Interface->getIdentifier());
LazySymbols.insert(Interface->getIdentifier());
Values[2] =
- EmitMethodList(std::string("\01L_OBJC_CATEGORY_INSTANCE_METHODS_") +
- ExtName,
+ EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
"__OBJC,__cat_inst_meth,regular,no_dead_strip",
InstanceMethods);
Values[3] =
- EmitMethodList(std::string("\01L_OBJC_CATEGORY_CLASS_METHODS_") + ExtName,
+ EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
"__OBJC,__cat_cls_meth,regular,no_dead_strip",
ClassMethods);
if (Category) {
Values[4] =
- EmitProtocolList(std::string("\01L_OBJC_CATEGORY_PROTOCOLS_") + ExtName,
+ EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
Category->protocol_begin(),
Category->protocol_end());
} else {
@@ -1934,7 +1929,7 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
// If there is no category @interface then there can be no properties.
if (Category) {
- Values[6] = EmitPropertyList(std::string("\01l_OBJC_$_PROP_LIST_")+ExtName,
+ Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
OCD, Category, ObjCTypes);
} else {
Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
@@ -1944,7 +1939,7 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Values);
llvm::GlobalVariable *GV =
- CreateMetadataVar(std::string("\01L_OBJC_CATEGORY_")+ExtName, Init,
+ CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
"__OBJC,__category,regular,no_dead_strip",
4, true);
DefinedCategories.push_back(GV);
@@ -1988,7 +1983,7 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
ObjCInterfaceDecl *Interface =
const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
llvm::Constant *Protocols =
- EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getNameAsString(),
+ EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
Interface->protocol_begin(),
Interface->protocol_end());
unsigned Flags = eClassFlags_Factory;
@@ -2046,7 +2041,7 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Values[ 6] = EmitIvarList(ID, false);
Values[ 7] =
- EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getNameAsString(),
+ EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
"__OBJC,__inst_meth,regular,no_dead_strip",
InstanceMethods);
// cache is always NULL.
@@ -2058,7 +2053,7 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Values);
llvm::GlobalVariable *GV =
- CreateMetadataVar(std::string("\01L_OBJC_CLASS_")+ClassName, Init,
+ CreateMetadataVar("\01L_OBJC_CLASS_" + ClassName, Init,
"__OBJC,__class,regular,no_dead_strip",
4, true);
DefinedClasses.push_back(GV);
@@ -2174,7 +2169,7 @@ CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
std::vector<llvm::Constant*> Values(3);
Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Values[1] = BuildIvarLayout(ID, false);
- Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getNameAsString(),
+ Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
ID, ID->getClassInterface(), ObjCTypes);
// Return null if no extension bits are used.
@@ -2183,7 +2178,7 @@ CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
llvm::Constant *Init =
llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
- return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getNameAsString(),
+ return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
Init, "__OBJC,__class_ext,regular,no_dead_strip",
4, true);
}
@@ -2243,12 +2238,11 @@ llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
llvm::GlobalVariable *GV;
if (ForClass)
- GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getNameAsString(),
+ GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
Init, "__OBJC,__class_vars,regular,no_dead_strip",
4, true);
else
- GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_"
- + ID->getNameAsString(),
+ GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
Init, "__OBJC,__instance_vars,regular,no_dead_strip",
4, true);
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
@@ -2286,7 +2280,7 @@ llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
}
-llvm::Constant *CGObjCMac::EmitMethodList(const std::string &Name,
+llvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name,
const char *Section,
const ConstantVector &Methods) {
// Return null for empty list.
@@ -2308,7 +2302,7 @@ llvm::Constant *CGObjCMac::EmitMethodList(const std::string &Name,
llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD) {
- std::string Name;
+ llvm::SmallString<256> Name;
GetNameForMethod(OMD, CD, Name);
CodeGenTypes &Types = CGM.getTypes();
@@ -2317,7 +2311,7 @@ llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
llvm::Function *Method =
llvm::Function::Create(MethodTy,
llvm::GlobalValue::InternalLinkage,
- Name,
+ Name.str(),
&CGM.getModule());
MethodDefinitions.insert(std::make_pair(OMD, Method));
@@ -2325,7 +2319,7 @@ llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
}
llvm::GlobalVariable *
-CGObjCCommonMac::CreateMetadataVar(const std::string &Name,
+CGObjCCommonMac::CreateMetadataVar(llvm::Twine Name,
llvm::Constant *Init,
const char *Section,
unsigned Align,
@@ -2985,7 +2979,8 @@ llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
if (!Entry)
Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
- llvm::ConstantArray::get(VMContext, Ident->getName()),
+ llvm::ConstantArray::get(VMContext,
+ Ident->getNameStart()),
"__TEXT,__cstring,cstring_literals",
1, true);
@@ -3434,7 +3429,8 @@ llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
if (!Entry)
Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
- llvm::ConstantArray::get(VMContext, Ident->getName()),
+ llvm::ConstantArray::get(VMContext,
+ Ident->getNameStart()),
"__TEXT,__cstring,cstring_literals",
1, true);
@@ -3453,21 +3449,15 @@ CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
const ObjCContainerDecl *CD,
- std::string &NameOut) {
- NameOut = '\01';
- NameOut += (D->isInstanceMethod() ? '-' : '+');
- NameOut += '[';
+ llvm::SmallVectorImpl<char> &Name) {
+ llvm::raw_svector_ostream OS(Name);
assert (CD && "Missing container decl in GetNameForMethod");
- NameOut += CD->getNameAsString();
+ OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
+ << '[' << CD->getName();
if (const ObjCCategoryImplDecl *CID =
- dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext())) {
- NameOut += '(';
- NameOut += CID->getNameAsString();
- NameOut+= ')';
- }
- NameOut += ' ';
- NameOut += D->getSelector().getAsString();
- NameOut += ']';
+ dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
+ OS << '(' << CID->getNameAsString() << ')';
+ OS << ' ' << D->getSelector().getAsString() << ']';
}
void CGObjCMac::FinishModule() {
@@ -4256,7 +4246,7 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
const ObjCInterfaceDecl *OID = ID->getClassInterface();
assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
- + OID->getNameAsString(),
+ + OID->getName(),
OID->protocol_begin(),
OID->protocol_end());
@@ -4269,9 +4259,8 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
if (flags & CLS_META)
Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
else
- Values[ 9] =
- EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getNameAsString(),
- ID, ID->getClassInterface(), ObjCTypes);
+ Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
+ ID, ID->getClassInterface(), ObjCTypes);
llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
Values);
llvm::GlobalVariable *CLASS_RO_GV =
@@ -4532,16 +4521,16 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
const ObjCCategoryDecl *Category =
Interface->FindCategoryDeclaration(OCD->getIdentifier());
if (Category) {
- std::string ExtName(Interface->getNameAsString() + "_$_" +
- OCD->getNameAsString());
+ llvm::SmallString<256> ExtName;
+ llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
+ << OCD->getName();
Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
- + Interface->getNameAsString() + "_$_"
- + Category->getNameAsString(),
+ + Interface->getName() + "_$_"
+ + Category->getName(),
Category->protocol_begin(),
Category->protocol_end());
- Values[5] =
- EmitPropertyList(std::string("\01l_OBJC_$_PROP_LIST_") + ExtName,
- OCD, Category, ObjCTypes);
+ Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
+ OCD, Category, ObjCTypes);
} else {
Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
@@ -4593,10 +4582,9 @@ llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
/// struct _objc_method method_list[method_count];
/// }
///
-llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(
- const std::string &Name,
- const char *Section,
- const ConstantVector &Methods) {
+llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name,
+ const char *Section,
+ const ConstantVector &Methods) {
// Return null for empty list.
if (Methods.empty())
return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
@@ -4742,7 +4730,7 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
llvm::GlobalValue::InternalLinkage,
Init,
- Prefix + OID->getNameAsString());
+ Prefix + OID->getName());
GV->setAlignment(
CGM.getTargetData().getPrefTypeAlignment(Init->getType()));
GV->setSection("__DATA, __objc_const");
@@ -4763,7 +4751,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
llvm::GlobalValue::ExternalLinkage,
0,
- "\01l_OBJC_PROTOCOL_$_" + PD->getNameAsString());
+ "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Entry->setSection("__DATA,__datacoal_nt,coalesced");
}
@@ -4795,8 +4783,6 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
if (Entry && Entry->hasInitializer())
return Entry;
- const char *ProtocolName = PD->getNameAsCString();
-
// Construct method lists.
std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
@@ -4826,28 +4812,27 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
// isa is NULL
Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Values[1] = GetClassName(PD->getIdentifier());
- Values[2] = EmitProtocolList(
- "\01l_OBJC_$_PROTOCOL_REFS_" + PD->getNameAsString(),
- PD->protocol_begin(),
- PD->protocol_end());
+ Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
+ PD->protocol_begin(),
+ PD->protocol_end());
Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
- + PD->getNameAsString(),
+ + PD->getName(),
"__DATA, __objc_const",
InstanceMethods);
Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
- + PD->getNameAsString(),
+ + PD->getName(),
"__DATA, __objc_const",
ClassMethods);
Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
- + PD->getNameAsString(),
+ + PD->getName(),
"__DATA, __objc_const",
OptInstanceMethods);
Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
- + PD->getNameAsString(),
+ + PD->getName(),
"__DATA, __objc_const",
OptClassMethods);
- Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getNameAsString(),
+ Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
0, PD, ObjCTypes);
uint32_t Size =
CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
@@ -4862,10 +4847,9 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Entry->setInitializer(Init);
} else {
Entry =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
- llvm::GlobalValue::WeakAnyLinkage,
- Init,
- std::string("\01l_OBJC_PROTOCOL_$_")+ProtocolName);
+ new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
+ false, llvm::GlobalValue::WeakAnyLinkage, Init,
+ "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Entry->setAlignment(
CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABITy));
Entry->setSection("__DATA,__datacoal_nt,coalesced");
@@ -4875,13 +4859,10 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
// Use this protocol meta-data to build protocol list table in section
// __DATA, __objc_protolist
- llvm::GlobalVariable *PTGV = new llvm::GlobalVariable(
- CGM.getModule(),
- ObjCTypes.ProtocolnfABIPtrTy, false,
- llvm::GlobalValue::WeakAnyLinkage,
- Entry,
- std::string("\01l_OBJC_LABEL_PROTOCOL_$_")
- +ProtocolName);
+ llvm::GlobalVariable *PTGV =
+ new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
+ false, llvm::GlobalValue::WeakAnyLinkage, Entry,
+ "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
PTGV->setAlignment(
CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
@@ -4899,9 +4880,9 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
/// @endcode
///
llvm::Constant *
-CGObjCNonFragileABIMac::EmitProtocolList(const std::string &Name,
- ObjCProtocolDecl::protocol_iterator begin,
- ObjCProtocolDecl::protocol_iterator end) {
+CGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name,
+ ObjCProtocolDecl::protocol_iterator begin,
+ ObjCProtocolDecl::protocol_iterator end) {
std::vector<llvm::Constant*> ProtocolRefs;
// Just return null for empty protocol lists
@@ -4909,10 +4890,12 @@ CGObjCNonFragileABIMac::EmitProtocolList(const std::string &Name,
return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
// FIXME: We shouldn't need to do this lookup here, should we?
- llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
+ llvm::SmallString<256> TmpName;
+ Name.toVector(TmpName);
+ llvm::GlobalVariable *GV =
+ CGM.getModule().getGlobalVariable(TmpName.str(), true);
if (GV)
- return llvm::ConstantExpr::getBitCast(GV,
- ObjCTypes.ProtocolListnfABIPtrTy);
+ return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
for (; begin != end; ++begin)
ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
@@ -5683,7 +5666,7 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
llvm::GlobalValue::ExternalLinkage,
0,
- (std::string("OBJC_EHTYPE_$_") +
+ ("OBJC_EHTYPE_$_" +
ID->getIdentifier()->getName()));
}
@@ -5715,7 +5698,7 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
llvm::GlobalValue::WeakAnyLinkage,
Init,
- (std::string("OBJC_EHTYPE_$_") +
+ ("OBJC_EHTYPE_$_" +
ID->getIdentifier()->getName()));
}
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp
index 6e73db3..9df0e1a 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -119,6 +119,43 @@ public:
Index_t VBlookup(CXXRecordDecl *D, CXXRecordDecl *B);
+ Index_t getNVOffset_1(const CXXRecordDecl *D, const CXXRecordDecl *B,
+ Index_t Offset = 0) {
+
+ if (B == D)
+ return Offset;
+
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(D);
+ for (CXXRecordDecl::base_class_const_iterator i = D->bases_begin(),
+ e = D->bases_end(); i != e; ++i) {
+ const CXXRecordDecl *Base =
+ cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
+ int64_t BaseOffset = 0;
+ if (!i->isVirtual())
+ BaseOffset = Offset + Layout.getBaseClassOffset(Base);
+ int64_t o = getNVOffset_1(Base, B, BaseOffset);
+ if (o >= 0)
+ return o;
+ }
+
+ return -1;
+ }
+
+ /// getNVOffset - Returns the non-virtual offset for the given (B) base of the
+ /// derived class D.
+ Index_t getNVOffset(QualType qB, QualType qD) {
+ qD = qD->getAs<PointerType>()->getPointeeType();
+ qB = qB->getAs<PointerType>()->getPointeeType();
+ CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
+ CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
+ int64_t o = getNVOffset_1(D, B);
+ if (o >= 0)
+ return o;
+
+ assert(false && "FIXME: non-virtual base not found");
+ return 0;
+ }
+
/// getVbaseOffset - Returns the index into the vtable for the virtual base
/// offset for the given (B) virtual base of the derived class D.
Index_t getVbaseOffset(QualType qB, QualType qD) {
@@ -138,8 +175,10 @@ public:
}
bool OverrideMethod(const CXXMethodDecl *MD, llvm::Constant *m,
- bool MorallyVirtual, Index_t Offset) {
+ bool MorallyVirtual, Index_t OverrideOffset,
+ Index_t Offset) {
typedef CXXMethodDecl::method_iterator meth_iter;
+ // FIXME: Should OverrideOffset's be Offset?
// FIXME: Don't like the nested loops. For very large inheritance
// heirarchies we could have a table on the side with the final overridder
@@ -166,11 +205,12 @@ public:
CallOffset ReturnOffset = std::make_pair(0, 0);
if (oret != ret) {
// FIXME: calculate offsets for covariance
- Index_t nv = 0;
if (CovariantThunks.count(OMD)) {
oret = CovariantThunks[OMD].second;
CovariantThunks.erase(OMD);
}
+ // FIXME: Double check oret
+ Index_t nv = getNVOffset(oret, ret)/8;
ReturnOffset = std::make_pair(nv, getVbaseOffset(oret, ret));
}
Index[MD] = i;
@@ -180,17 +220,16 @@ public:
if (MorallyVirtual) {
Index_t &idx = VCall[OMD];
if (idx == 0) {
- VCallOffset[MD] = Offset/8;
+ VCallOffset[MD] = OverrideOffset/8;
idx = VCalls.size()+1;
VCalls.push_back(0);
} else {
VCallOffset[MD] = VCallOffset[OMD];
- VCalls[idx-1] = -VCallOffset[OMD] + Offset/8;
+ VCalls[idx-1] = -VCallOffset[OMD] + OverrideOffset/8;
}
VCall[MD] = idx;
CallOffset ThisOffset;
- // FIXME: calculate non-virtual offset
- ThisOffset = std::make_pair(0 /* -CurrentVBaseOffset/8 + Offset/8 */,
+ ThisOffset = std::make_pair(CurrentVBaseOffset/8 - Offset/8,
-((idx+extra+2)*LLVMPointerWidth/8));
// FIXME: Do we always have to build a covariant thunk to save oret,
// which is the containing virtual base class?
@@ -204,8 +243,8 @@ public:
}
// FIXME: finish off
- int64_t O = VCallOffset[OMD] - Offset/8;
- // int64_t O = CurrentVBaseOffset/8 - Offset/8;
+ int64_t O = VCallOffset[OMD] - OverrideOffset/8;
+ // int64_t O = CurrentVBaseOffset/8 - OverrideOffset/8;
if (O || ReturnOffset.first || ReturnOffset.second) {
CallOffset ThisOffset = std::make_pair(O, 0);
@@ -248,11 +287,11 @@ public:
CovariantThunks.clear();
}
- void OverrideMethods(Path_t *Path, bool MorallyVirtual) {
+ void OverrideMethods(Path_t *Path, bool MorallyVirtual, int64_t Offset) {
for (Path_t::reverse_iterator i = Path->rbegin(),
e = Path->rend(); i != e; ++i) {
const CXXRecordDecl *RD = i->first;
- int64_t Offset = i->second;
+ int64_t OverrideOffset = i->second;
for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
++mi) {
if (!mi->isVirtual())
@@ -272,7 +311,7 @@ public:
m = wrap(CGM.GetAddrOfFunction(MD, Ty));
}
- OverrideMethod(MD, m, MorallyVirtual, Offset);
+ OverrideMethod(MD, m, MorallyVirtual, OverrideOffset, Offset);
}
}
}
@@ -291,7 +330,7 @@ public:
}
// If we can find a previously allocated slot for this, reuse it.
- if (OverrideMethod(MD, m, MorallyVirtual, Offset))
+ if (OverrideMethod(MD, m, MorallyVirtual, Offset, Offset))
return;
// else allocate a new slot.
@@ -344,7 +383,7 @@ public:
llvm::Constant *e = 0;
D(VCalls.insert(VCalls.begin(), 673));
D(VCalls.push_back(672));
- methods.insert(methods.begin() + InsertionPoint, VCalls.size()/*+2*/, e);
+ methods.insert(methods.begin() + InsertionPoint, VCalls.size(), e);
// The vcalls come first...
for (std::vector<Index_t>::reverse_iterator i = VCalls.rbegin(),
e = VCalls.rend();
@@ -380,7 +419,9 @@ public:
int VCallInsertionPoint = methods.size();
if (!DeferVCalls) {
insertVCalls(VCallInsertionPoint);
- }
+ } else
+ // FIXME: just for extra, or for all uses of VCalls.size post this?
+ extra = -VCalls.size();
if (ForVirtualBase) {
D(methods.push_back(wrap(668)));
@@ -463,7 +504,7 @@ public:
AddMethods(RD, MorallyVirtual, Offset);
if (Path)
- OverrideMethods(Path, MorallyVirtual);
+ OverrideMethods(Path, MorallyVirtual, Offset);
return end(RD, offsets, Layout, PrimaryBase, PrimaryBaseWasVirtual,
MorallyVirtual, Offset, ForVirtualBase, Path);
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 5206f44..ba93e5d 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -167,18 +167,20 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
Builder.SetInsertPoint(EntryBB);
+ QualType FnType = getContext().getFunctionType(RetTy, 0, 0, false, 0);
+
// Emit subprogram debug descriptor.
// FIXME: The cast here is a huge hack.
if (CGDebugInfo *DI = getDebugInfo()) {
DI->setLocation(StartLoc);
if (isa<FunctionDecl>(D)) {
- DI->EmitFunctionStart(CGM.getMangledName(GD), RetTy, CurFn, Builder);
+ DI->EmitFunctionStart(CGM.getMangledName(GD), FnType, CurFn, Builder);
} else {
// Just use LLVM function name.
// FIXME: Remove unnecessary conversion to std::string when API settles.
DI->EmitFunctionStart(std::string(Fn->getName()).c_str(),
- RetTy, CurFn, Builder);
+ FnType, CurFn, Builder);
}
}
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 722d002..639e683 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -34,6 +34,7 @@ namespace llvm {
class LLVMContext;
class Module;
class SwitchInst;
+ class Twine;
class Value;
}
@@ -355,6 +356,7 @@ public:
void BlockForwardSelf();
llvm::Value *LoadBlockStruct();
+ uint64_t AllocateBlockDecl(const BlockDeclRefExpr *E);
llvm::Value *GetAddrOfBlockDecl(const BlockDeclRefExpr *E);
const llvm::Type *BuildByRefType(const ValueDecl *D);
@@ -508,7 +510,7 @@ public:
/// CreateTempAlloca - This creates a alloca and inserts it into the entry
/// block.
llvm::AllocaInst *CreateTempAlloca(const llvm::Type *Ty,
- const char *Name = "tmp");
+ const llvm::Twine &Name = "tmp");
/// EvaluateExprAsBool - Perform the usual unary conversions on the specified
/// expression and compare the result against zero, returning an Int1Ty value.
@@ -816,7 +818,9 @@ public:
LValue EmitCompoundLiteralLValue(const CompoundLiteralExpr *E);
LValue EmitConditionalOperatorLValue(const ConditionalOperator *E);
LValue EmitCastLValue(const CastExpr *E);
-
+ LValue EmitNullInitializationLValue(const CXXZeroInitValueExpr *E);
+ LValue EmitPointerToDataMemberLValue(const QualifiedDeclRefExpr *E);
+
llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface,
const ObjCIvarDecl *Ivar);
LValue EmitLValueForField(llvm::Value* Base, FieldDecl* Field,
@@ -841,7 +845,8 @@ public:
LValue EmitObjCKVCRefLValue(const ObjCImplicitSetterGetterRefExpr *E);
LValue EmitObjCSuperExprLValue(const ObjCSuperExpr *E);
LValue EmitStmtExprLValue(const StmtExpr *E);
-
+ LValue EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E);
+
//===--------------------------------------------------------------------===//
// Scalar Expression Emission
//===--------------------------------------------------------------------===//
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 4763b7f..ea84829 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -825,7 +825,7 @@ llvm::Constant *
CodeGenModule::CreateRuntimeFunction(const llvm::FunctionType *FTy,
const char *Name) {
// Convert Name to be a uniqued string from the IdentifierInfo table.
- Name = getContext().Idents.get(Name).getName();
+ Name = getContext().Idents.get(Name).getNameStart();
return GetOrCreateLLVMFunction(Name, FTy, GlobalDecl());
}
@@ -911,7 +911,7 @@ llvm::Constant *
CodeGenModule::CreateRuntimeVariable(const llvm::Type *Ty,
const char *Name) {
// Convert Name to be a uniqued string from the IdentifierInfo table.
- Name = getContext().Idents.get(Name).getName();
+ Name = getContext().Idents.get(Name).getNameStart();
return GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), 0);
}
@@ -1254,7 +1254,7 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {
// Unique the name through the identifier table.
const char *AliaseeName = AA->getAliasee().c_str();
- AliaseeName = getContext().Idents.get(AliaseeName).getName();
+ AliaseeName = getContext().Idents.get(AliaseeName).getNameStart();
// Create a reference to the named value. This ensures that it is emitted
// if a deferred decl.
@@ -1341,7 +1341,7 @@ llvm::Value *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD,
cast<llvm::FunctionType>(getTypes().ConvertType(Type));
// Unique the name through the identifier table.
- Name = getContext().Idents.get(Name).getName();
+ Name = getContext().Idents.get(Name).getNameStart();
return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl(FD));
}
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index fd77274..2e6034b 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -248,7 +248,12 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
FD = PrimaryTemplate->getTemplatedDecl();
}
- mangleBareFunctionType(FD->getType()->getAs<FunctionType>(), MangleReturnType);
+ // Do the canonicalization out here because parameter types can
+ // undergo additional canonicalization (e.g. array decay).
+ FunctionType *FT = cast<FunctionType>(Context.getASTContext()
+ .getCanonicalType(FD->getType()));
+
+ mangleBareFunctionType(FT, MangleReturnType);
}
static bool isStdNamespace(const DeclContext *DC) {
@@ -705,7 +710,7 @@ void CXXNameMangler::mangleType(QualType T) {
// Only operate on the canonical type!
T = Context.getASTContext().getCanonicalType(T);
- bool IsSubstitutable = !isa<BuiltinType>(T);
+ bool IsSubstitutable = T.hasQualifiers() || !isa<BuiltinType>(T);
if (IsSubstitutable && mangleSubstitution(T))
return;
@@ -1236,10 +1241,7 @@ static bool isCharSpecialization(QualType T, const char *Name) {
if (!isCharType(TemplateArgs[0].getAsType()))
return false;
- if (strcmp(SD->getIdentifier()->getName(), Name) != 0)
- return false;
-
- return true;
+ return SD->getIdentifier()->getName() == Name;
}
bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
diff --git a/lib/CodeGen/TargetABIInfo.cpp b/lib/CodeGen/TargetABIInfo.cpp
index 59f579f..852bba4 100644
--- a/lib/CodeGen/TargetABIInfo.cpp
+++ b/lib/CodeGen/TargetABIInfo.cpp
@@ -353,11 +353,17 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
return ABIArgInfo::getDirect();
} else if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
- // Structures with flexible arrays are always indirect.
- if (const RecordType *RT = RetTy->getAsStructureType())
+ if (const RecordType *RT = RetTy->getAsStructureType()) {
+ // Structures with either a non-trivial destructor or a non-trivial
+ // copy constructor are always indirect.
+ if (hasNonTrivialDestructorOrCopyConstructor(RT))
+ return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+
+ // Structures with flexible arrays are always indirect.
if (RT->getDecl()->hasFlexibleArrayMember())
return ABIArgInfo::getIndirect(0);
-
+ }
+
// If specified, structs and unions are always indirect.
if (!IsSmallStructInRegABI && !RetTy->isAnyComplexType())
return ABIArgInfo::getIndirect(0);
@@ -1744,14 +1750,14 @@ const ABIInfo &CodeGenTypes::getABIInfo() const {
return *(TheABIInfo = new SystemZABIInfo());
case llvm::Triple::x86:
- if (Triple.getOS() == llvm::Triple::Darwin)
- return *(TheABIInfo = new X86_32ABIInfo(Context, true, true));
-
switch (Triple.getOS()) {
+ case llvm::Triple::Darwin:
+ return *(TheABIInfo = new X86_32ABIInfo(Context, true, true));
case llvm::Triple::Cygwin:
- case llvm::Triple::DragonFly:
case llvm::Triple::MinGW32:
case llvm::Triple::MinGW64:
+ case llvm::Triple::AuroraUX:
+ case llvm::Triple::DragonFly:
case llvm::Triple::FreeBSD:
case llvm::Triple::OpenBSD:
return *(TheABIInfo = new X86_32ABIInfo(Context, false, true));
OpenPOWER on IntegriCloud