diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGBlocks.cpp | 140 | ||||
-rw-r--r-- | lib/CodeGen/CGBlocks.h | 20 | ||||
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 15 | ||||
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 5 | ||||
-rw-r--r-- | lib/CodeGen/CGDebugInfo.cpp | 99 | ||||
-rw-r--r-- | lib/CodeGen/CGDebugInfo.h | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 5 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 121 | ||||
-rw-r--r-- | lib/CodeGen/CGExprAgg.cpp | 25 | ||||
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 256 | ||||
-rw-r--r-- | lib/CodeGen/CGObjCMac.cpp | 199 | ||||
-rw-r--r-- | lib/CodeGen/CGVtable.cpp | 71 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 11 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 8 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 14 | ||||
-rw-r--r-- | lib/CodeGen/TargetABIInfo.cpp | 20 |
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)); |