diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-05-27 15:17:06 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-05-27 15:17:06 +0000 |
commit | 53992adde3eda3ccf9da63bc7e45673f043de18f (patch) | |
tree | 3558f327a6f9ab59c5d7a06528d84e1560445247 /lib/CodeGen | |
parent | 7e411337c0ed226dace6e07f1420486768161308 (diff) | |
download | FreeBSD-src-53992adde3eda3ccf9da63bc7e45673f043de18f.zip FreeBSD-src-53992adde3eda3ccf9da63bc7e45673f043de18f.tar.gz |
Update clang to r104832.
Diffstat (limited to 'lib/CodeGen')
39 files changed, 2154 insertions, 1139 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 8082b33..de58597 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -24,6 +24,45 @@ using namespace clang; using namespace CodeGen; +/// CGBlockInfo - Information to generate a block literal. +class clang::CodeGen::CGBlockInfo { +public: + /// Name - The name of the block, kindof. + const char *Name; + + /// DeclRefs - Variables from parent scopes that have been + /// imported into this block. + llvm::SmallVector<const BlockDeclRefExpr *, 8> DeclRefs; + + /// InnerBlocks - This block and the blocks it encloses. + llvm::SmallPtrSet<const DeclContext *, 4> InnerBlocks; + + /// CXXThisRef - Non-null if 'this' was required somewhere, in + /// which case this is that expression. + const CXXThisExpr *CXXThisRef; + + /// NeedsObjCSelf - True if something in this block has an implicit + /// reference to 'self'. + bool NeedsObjCSelf; + + /// These are initialized by GenerateBlockFunction. + bool BlockHasCopyDispose; + CharUnits BlockSize; + CharUnits BlockAlign; + llvm::SmallVector<const Expr*, 8> BlockLayout; + + CGBlockInfo(const char *Name); +}; + +CGBlockInfo::CGBlockInfo(const char *N) + : Name(N), CXXThisRef(0), NeedsObjCSelf(false) { + + // Skip asm prefix, if any. + if (Name && Name[0] == '\01') + ++Name; +} + + llvm::Constant *CodeGenFunction:: BuildDescriptorBlockDecl(const BlockExpr *BE, bool BlockHasCopyDispose, CharUnits Size, const llvm::StructType* Ty, @@ -86,58 +125,86 @@ llvm::Constant *BlockModule::getNSConcreteStackBlock() { return NSConcreteStackBlock; } -static void CollectBlockDeclRefInfo( - const Stmt *S, CodeGenFunction::BlockInfo &Info, - llvm::SmallSet<const DeclContext *, 16> &InnerContexts) { +static void CollectBlockDeclRefInfo(const Stmt *S, CGBlockInfo &Info) { for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end(); I != E; ++I) if (*I) - CollectBlockDeclRefInfo(*I, Info, InnerContexts); + CollectBlockDeclRefInfo(*I, Info); // 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); + Info.InnerBlocks.insert(BE->getBlockDecl()); + CollectBlockDeclRefInfo(BE->getBody(), Info); } - if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) { + else if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) { + const ValueDecl *D = BDRE->getDecl(); // FIXME: Handle enums. - if (isa<FunctionDecl>(BDRE->getDecl())) + if (isa<FunctionDecl>(D)) return; + if (isa<ImplicitParamDecl>(D) && + isa<ObjCMethodDecl>(D->getDeclContext()) && + cast<ObjCMethodDecl>(D->getDeclContext())->getSelfDecl() == D) { + Info.NeedsObjCSelf = true; + return; + } + // Only Decls that escape are added. - if (!InnerContexts.count(BDRE->getDecl()->getDeclContext())) + if (!Info.InnerBlocks.count(D->getDeclContext())) Info.DeclRefs.push_back(BDRE); } + + // Make sure to capture implicit 'self' references due to super calls. + else if (const ObjCMessageExpr *E = dyn_cast<ObjCMessageExpr>(S)) { + if (E->getReceiverKind() == ObjCMessageExpr::SuperClass || + E->getReceiverKind() == ObjCMessageExpr::SuperInstance) + Info.NeedsObjCSelf = true; + } + + // Getter/setter uses may also cause implicit super references, + // which we can check for with: + else if (isa<ObjCSuperExpr>(S)) + Info.NeedsObjCSelf = true; + + else if (isa<CXXThisExpr>(S)) + Info.CXXThisRef = cast<CXXThisExpr>(S); } -/// CanBlockBeGlobal - Given a BlockInfo struct, determines if a block can be +/// CanBlockBeGlobal - Given a CGBlockInfo struct, determines if a block can be /// declared as a global variable instead of on the stack. -static bool CanBlockBeGlobal(const CodeGenFunction::BlockInfo &Info) { +static bool CanBlockBeGlobal(const CGBlockInfo &Info) { 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) { - // FIXME: Also always forward the this pointer in C++ as well. +static void AllocateAllBlockDeclRefs(CodeGenFunction &CGF, CGBlockInfo &Info) { + if (Info.CXXThisRef) + CGF.AllocateBlockCXXThisPointer(Info.CXXThisRef); for (size_t i = 0; i < Info.DeclRefs.size(); ++i) - CGF->AllocateBlockDecl(Info.DeclRefs[i]); + CGF.AllocateBlockDecl(Info.DeclRefs[i]); + + if (Info.NeedsObjCSelf) { + ValueDecl *Self = cast<ObjCMethodDecl>(CGF.CurFuncDecl)->getSelfDecl(); + BlockDeclRefExpr *BDRE = + new (CGF.getContext()) BlockDeclRefExpr(Self, Self->getType(), + SourceLocation(), false); + Info.DeclRefs.push_back(BDRE); + CGF.AllocateBlockDecl(BDRE); + } } // FIXME: Push most into CGM, passing down a few bits, like current function // name. llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { - std::string Name = CurFn->getName(); - CodeGenFunction::BlockInfo Info(0, Name.c_str()); - llvm::SmallSet<const DeclContext *, 16> InnerContexts; - InnerContexts.insert(BE->getBlockDecl()); - CollectBlockDeclRefInfo(BE->getBody(), Info, InnerContexts); + CGBlockInfo Info(Name.c_str()); + Info.InnerBlocks.insert(BE->getBlockDecl()); + CollectBlockDeclRefInfo(BE->getBody(), Info); // Check if the block can be global. // FIXME: This test doesn't work for nested blocks yet. Longer term, I'd like @@ -160,23 +227,15 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { // We run this first so that we set BlockHasCopyDispose from the entire // block literal. // __invoke - CharUnits subBlockSize; - CharUnits subBlockAlign; - llvm::SmallVector<const Expr *, 8> subBlockDeclRefDecls; - bool subBlockHasCopyDispose = false; llvm::Function *Fn = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, CurFuncDecl, - LocalDeclMap, - subBlockSize, - subBlockAlign, - subBlockDeclRefDecls, - subBlockHasCopyDispose); - BlockHasCopyDispose |= subBlockHasCopyDispose; + LocalDeclMap); + BlockHasCopyDispose |= Info.BlockHasCopyDispose; Elts[3] = Fn; // FIXME: Don't use BlockHasCopyDispose, it is set more often then // necessary, for example: { ^{ __block int i; ^{ i = 1; }(); }(); } - if (subBlockHasCopyDispose) + if (Info.BlockHasCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE; // __isa @@ -206,10 +265,10 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { C = llvm::ConstantInt::get(IntTy, 0); Elts[2] = C; - if (subBlockDeclRefDecls.size() == 0) { + if (Info.BlockLayout.empty()) { // __descriptor - Elts[4] = BuildDescriptorBlockDecl(BE, subBlockHasCopyDispose, subBlockSize, - 0, 0); + Elts[4] = BuildDescriptorBlockDecl(BE, Info.BlockHasCopyDispose, + Info.BlockSize, 0, 0); // Optimize to being a global block. Elts[0] = CGM.getNSConcreteGlobalBlock(); @@ -227,13 +286,13 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { return C; } - std::vector<const llvm::Type *> Types(BlockFields+subBlockDeclRefDecls.size()); + std::vector<const llvm::Type *> Types(BlockFields+Info.BlockLayout.size()); for (int i=0; i<4; ++i) Types[i] = Elts[i]->getType(); Types[4] = PtrToInt8Ty; - for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i) { - const Expr *E = subBlockDeclRefDecls[i]; + for (unsigned i = 0, n = Info.BlockLayout.size(); i != n; ++i) { + const Expr *E = Info.BlockLayout[i]; const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E); QualType Ty = E->getType(); if (BDRE && BDRE->isByRef()) { @@ -245,105 +304,113 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { llvm::StructType *Ty = llvm::StructType::get(VMContext, Types, true); llvm::AllocaInst *A = CreateTempAlloca(Ty); - A->setAlignment(subBlockAlign.getQuantity()); + A->setAlignment(Info.BlockAlign.getQuantity()); V = A; - std::vector<HelperInfo> NoteForHelper(subBlockDeclRefDecls.size()); - int helpersize = 0; + // Build layout / cleanup information for all the data entries in the + // layout, and write the enclosing fields into the type. + std::vector<HelperInfo> NoteForHelper(Info.BlockLayout.size()); + unsigned NumHelpers = 0; for (unsigned i=0; i<4; ++i) Builder.CreateStore(Elts[i], Builder.CreateStructGEP(V, i, "block.tmp")); - for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i) - { - // FIXME: Push const down. - Expr *E = const_cast<Expr*>(subBlockDeclRefDecls[i]); - DeclRefExpr *DR; - ValueDecl *VD; - - DR = dyn_cast<DeclRefExpr>(E); - // Skip padding. - if (DR) continue; - - BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E); - VD = BDRE->getDecl(); - - llvm::Value* Addr = Builder.CreateStructGEP(V, i+BlockFields, "tmp"); - NoteForHelper[helpersize].index = i+5; - NoteForHelper[helpersize].RequiresCopying - = BlockRequiresCopying(VD->getType()); - NoteForHelper[helpersize].flag - = (VD->getType()->isBlockPointerType() - ? BLOCK_FIELD_IS_BLOCK - : BLOCK_FIELD_IS_OBJECT); - - if (LocalDeclMap[VD]) { - if (BDRE->isByRef()) { - NoteForHelper[helpersize].flag = BLOCK_FIELD_IS_BYREF | - // FIXME: Someone double check this. - (VD->getType().isObjCGCWeak() ? BLOCK_FIELD_IS_WEAK : 0); - llvm::Value *Loc = LocalDeclMap[VD]; - Loc = Builder.CreateStructGEP(Loc, 1, "forwarding"); - Loc = Builder.CreateLoad(Loc); - Builder.CreateStore(Loc, Addr); - ++helpersize; - continue; - } else - E = new (getContext()) DeclRefExpr (VD, - VD->getType(), - SourceLocation()); - } + for (unsigned i=0; i < Info.BlockLayout.size(); ++i) { + const Expr *E = Info.BlockLayout[i]; + + // Skip padding. + if (isa<DeclRefExpr>(E)) continue; + + llvm::Value* Addr = Builder.CreateStructGEP(V, i+BlockFields, "tmp"); + HelperInfo &Note = NoteForHelper[NumHelpers++]; + + Note.index = i+5; + + if (isa<CXXThisExpr>(E)) { + Note.RequiresCopying = false; + Note.flag = BLOCK_FIELD_IS_OBJECT; + + Builder.CreateStore(LoadCXXThis(), Addr); + continue; + } + + const BlockDeclRefExpr *BDRE = cast<BlockDeclRefExpr>(E); + const ValueDecl *VD = BDRE->getDecl(); + QualType T = VD->getType(); + + Note.RequiresCopying = BlockRequiresCopying(T); + + if (BDRE->isByRef()) { + Note.flag = BLOCK_FIELD_IS_BYREF; + if (T.isObjCGCWeak()) + Note.flag |= BLOCK_FIELD_IS_WEAK; + } else if (T->isBlockPointerType()) { + Note.flag = BLOCK_FIELD_IS_BLOCK; + } else { + Note.flag = BLOCK_FIELD_IS_OBJECT; + } + + if (LocalDeclMap[VD]) { if (BDRE->isByRef()) { - NoteForHelper[helpersize].flag = BLOCK_FIELD_IS_BYREF | - // FIXME: Someone double check this. - (VD->getType().isObjCGCWeak() ? BLOCK_FIELD_IS_WEAK : 0); - E = new (getContext()) - UnaryOperator(E, UnaryOperator::AddrOf, - getContext().getPointerType(E->getType()), - SourceLocation()); - } - ++helpersize; - - RValue r = EmitAnyExpr(E, Addr, false); - if (r.isScalar()) { - llvm::Value *Loc = r.getScalarVal(); - const llvm::Type *Ty = Types[i+BlockFields]; - if (BDRE->isByRef()) { - // E is now the address of the value field, instead, we want the - // address of the actual ByRef struct. We optimize this slightly - // compared to gcc by not grabbing the forwarding slot as this must - // be done during Block_copy for us, and we can postpone the work - // until then. - CharUnits offset = BlockDecls[BDRE->getDecl()]; - - llvm::Value *BlockLiteral = LoadBlockStruct(); - - Loc = Builder.CreateGEP(BlockLiteral, - llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), - offset.getQuantity()), - "block.literal"); - Ty = llvm::PointerType::get(Ty, 0); - Loc = Builder.CreateBitCast(Loc, Ty); - Loc = Builder.CreateLoad(Loc); - // Loc = Builder.CreateBitCast(Loc, Ty); - } + llvm::Value *Loc = LocalDeclMap[VD]; + Loc = Builder.CreateStructGEP(Loc, 1, "forwarding"); + Loc = Builder.CreateLoad(Loc); Builder.CreateStore(Loc, Addr); - } else if (r.isComplex()) - // FIXME: implement - ErrorUnsupported(BE, "complex in block literal"); - else if (r.isAggregate()) - ; // Already created into the destination - else - assert (0 && "bad block variable"); - // FIXME: Ensure that the offset created by the backend for - // the struct matches the previously computed offset in BlockDecls. + continue; + } else { + E = new (getContext()) DeclRefExpr(const_cast<ValueDecl*>(VD), + VD->getType(), + SourceLocation()); + } } - NoteForHelper.resize(helpersize); + + if (BDRE->isByRef()) { + E = new (getContext()) + UnaryOperator(const_cast<Expr*>(E), UnaryOperator::AddrOf, + getContext().getPointerType(E->getType()), + SourceLocation()); + } + + RValue r = EmitAnyExpr(E, Addr, false); + if (r.isScalar()) { + llvm::Value *Loc = r.getScalarVal(); + const llvm::Type *Ty = Types[i+BlockFields]; + if (BDRE->isByRef()) { + // E is now the address of the value field, instead, we want the + // address of the actual ByRef struct. We optimize this slightly + // compared to gcc by not grabbing the forwarding slot as this must + // be done during Block_copy for us, and we can postpone the work + // until then. + CharUnits offset = BlockDecls[BDRE->getDecl()]; + + llvm::Value *BlockLiteral = LoadBlockStruct(); + + Loc = Builder.CreateGEP(BlockLiteral, + llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), + offset.getQuantity()), + "block.literal"); + Ty = llvm::PointerType::get(Ty, 0); + Loc = Builder.CreateBitCast(Loc, Ty); + Loc = Builder.CreateLoad(Loc); + // Loc = Builder.CreateBitCast(Loc, Ty); + } + Builder.CreateStore(Loc, Addr); + } else if (r.isComplex()) + // FIXME: implement + ErrorUnsupported(BE, "complex in block literal"); + else if (r.isAggregate()) + ; // Already created into the destination + else + assert (0 && "bad block variable"); + // FIXME: Ensure that the offset created by the backend for + // the struct matches the previously computed offset in BlockDecls. + } + NoteForHelper.resize(NumHelpers); // __descriptor llvm::Value *Descriptor = BuildDescriptorBlockDecl(BE, - subBlockHasCopyDispose, - subBlockSize, Ty, + Info.BlockHasCopyDispose, + Info.BlockSize, Ty, &NoteForHelper); Descriptor = Builder.CreateBitCast(Descriptor, PtrToInt8Ty); Builder.CreateStore(Descriptor, Builder.CreateStructGEP(V, 4, "block.tmp")); @@ -487,13 +554,25 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E, return EmitCall(FnInfo, Func, ReturnValue, Args); } -CharUnits CodeGenFunction::AllocateBlockDecl(const BlockDeclRefExpr *E) { +void CodeGenFunction::AllocateBlockCXXThisPointer(const CXXThisExpr *E) { + assert(BlockCXXThisOffset.isZero() && "already computed 'this' pointer"); + + // Figure out what the offset is. + QualType T = E->getType(); + std::pair<CharUnits,CharUnits> TypeInfo = getContext().getTypeInfoInChars(T); + CharUnits Offset = getBlockOffset(TypeInfo.first, TypeInfo.second); + + BlockCXXThisOffset = Offset; + BlockLayout.push_back(E); +} + +void CodeGenFunction::AllocateBlockDecl(const BlockDeclRefExpr *E) { const ValueDecl *VD = E->getDecl(); - CharUnits &offset = BlockDecls[VD]; + CharUnits &Offset = BlockDecls[VD]; // See if we have already allocated an offset for this variable. - if (offset.isPositive()) - return offset; + if (!Offset.isZero()) + return; // Don't run the expensive check, unless we have to. if (!BlockHasCopyDispose) @@ -501,23 +580,34 @@ CharUnits CodeGenFunction::AllocateBlockDecl(const BlockDeclRefExpr *E) { || BlockRequiresCopying(E->getType())) BlockHasCopyDispose = true; - // if not, allocate one now. - offset = getBlockOffset(E); + const ValueDecl *D = cast<ValueDecl>(E->getDecl()); - return offset; + CharUnits Size; + CharUnits Align; + + if (E->isByRef()) { + llvm::tie(Size,Align) = + getContext().getTypeInfoInChars(getContext().VoidPtrTy); + } else { + Size = getContext().getTypeSizeInChars(D->getType()); + Align = getContext().getDeclAlign(D); + } + + Offset = getBlockOffset(Size, Align); + BlockLayout.push_back(E); } -llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) { - const ValueDecl *VD = E->getDecl(); - CharUnits offset = AllocateBlockDecl(E); - +llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const ValueDecl *VD, + bool IsByRef) { + CharUnits offset = BlockDecls[VD]; + assert(!offset.isZero() && "getting address of unallocated decl"); llvm::Value *BlockLiteral = LoadBlockStruct(); llvm::Value *V = Builder.CreateGEP(BlockLiteral, llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), offset.getQuantity()), "block.literal"); - if (E->isByRef()) { + if (IsByRef) { const llvm::Type *PtrStructTy = llvm::PointerType::get(BuildByRefType(VD), 0); // The block literal will need a copy/destroy helper. @@ -543,19 +633,6 @@ llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) { return V; } -void CodeGenFunction::BlockForwardSelf() { - const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); - ImplicitParamDecl *SelfDecl = OMD->getSelfDecl(); - llvm::Value *&DMEntry = LocalDeclMap[SelfDecl]; - if (DMEntry) - return; - // FIXME - Eliminate BlockDeclRefExprs, clients don't need/want to care - BlockDeclRefExpr *BDRE = new (getContext()) - BlockDeclRefExpr(SelfDecl, - SelfDecl->getType(), SourceLocation(), false); - DMEntry = GetAddrOfBlockDecl(BDRE); -} - llvm::Constant * BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) { // Generate the block descriptor. @@ -600,19 +677,11 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) { std::vector<llvm::Constant*> LiteralFields(FieldCount); - CodeGenFunction::BlockInfo Info(0, n); - CharUnits subBlockSize; - CharUnits subBlockAlign; - llvm::SmallVector<const Expr *, 8> subBlockDeclRefDecls; - bool subBlockHasCopyDispose = false; + CGBlockInfo Info(n); llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap; llvm::Function *Fn - = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, 0, LocalDeclMap, - subBlockSize, - subBlockAlign, - subBlockDeclRefDecls, - subBlockHasCopyDispose); - assert(subBlockSize == BlockLiteralSize + = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, 0, LocalDeclMap); + assert(Info.BlockSize == BlockLiteralSize && "no imports allowed for global block"); // isa @@ -651,13 +720,9 @@ llvm::Value *CodeGenFunction::LoadBlockStruct() { llvm::Function * CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr, - const BlockInfo& Info, + CGBlockInfo &Info, const Decl *OuterFuncDecl, - llvm::DenseMap<const Decl*, llvm::Value*> ldm, - CharUnits &Size, - CharUnits &Align, - llvm::SmallVector<const Expr *, 8> &subBlockDeclRefDecls, - bool &subBlockHasCopyDispose) { + llvm::DenseMap<const Decl*, llvm::Value*> ldm) { // Check if we should generate debug info for this block. if (CGM.getDebugInfo()) @@ -701,11 +766,12 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr, IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor"); - // Allocate all BlockDeclRefDecls, so we can calculate the right ParmTy below. - AllocateAllBlockDeclRefs(Info, this); + // Build the block struct now. + AllocateAllBlockDeclRefs(*this, Info); QualType ParmTy = getContext().getBlockParmType(BlockHasCopyDispose, - BlockDeclRefDecls); + BlockLayout); + // FIXME: This leaks ImplicitParamDecl *SelfDecl = ImplicitParamDecl::Create(getContext(), const_cast<BlockDecl*>(BD), @@ -725,10 +791,11 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr, CodeGenTypes &Types = CGM.getTypes(); const llvm::FunctionType *LTy = Types.GetFunctionType(FI, IsVariadic); + MangleBuffer Name; + CGM.getMangledName(Name, BD); llvm::Function *Fn = - llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, - llvm::Twine("__") + Info.Name + "_block_invoke_", - &CGM.getModule()); + llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, + Name.getString(), &CGM.getModule()); CGM.SetInternalFunctionAttributes(BD, Fn, FI); @@ -738,6 +805,34 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr, CurFuncDecl = OuterFuncDecl; CurCodeDecl = BD; + // If we have a C++ 'this' reference, go ahead and force it into + // existence now. + if (Info.CXXThisRef) { + assert(!BlockCXXThisOffset.isZero() && + "haven't yet allocated 'this' reference"); + + // TODO: I have a dream that one day this will be typed. + llvm::Value *BlockLiteral = LoadBlockStruct(); + llvm::Value *ThisPtrRaw = + Builder.CreateConstInBoundsGEP1_64(BlockLiteral, + BlockCXXThisOffset.getQuantity(), + "this.ptr.raw"); + + const llvm::Type *Ty = + CGM.getTypes().ConvertType(Info.CXXThisRef->getType()); + Ty = llvm::PointerType::get(Ty, 0); + llvm::Value *ThisPtr = Builder.CreateBitCast(ThisPtrRaw, Ty, "this.ptr"); + + CXXThisValue = Builder.CreateLoad(ThisPtr, "this"); + } + + // If we have an Objective C 'self' reference, go ahead and force it + // into existence now. + if (Info.NeedsObjCSelf) { + ValueDecl *Self = cast<ObjCMethodDecl>(CurFuncDecl)->getSelfDecl(); + LocalDeclMap[Self] = GetAddrOfBlockDecl(Self, false); + } + // Save a spot to insert the debug information for all the BlockDeclRefDecls. llvm::BasicBlock *entry = Builder.GetInsertBlock(); llvm::BasicBlock::iterator entry_ptr = Builder.GetInsertPoint(); @@ -754,9 +849,10 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr, if (CGDebugInfo *DI = getDebugInfo()) { // Emit debug information for all the BlockDeclRefDecls. - for (unsigned i = 0, e = BlockDeclRefDecls.size(); i != e; ++i) { - if (const BlockDeclRefExpr *BDRE = - dyn_cast<BlockDeclRefExpr>(BlockDeclRefDecls[i])) { + // FIXME: also for 'this' + for (unsigned i = 0, e = BlockLayout.size(); i != e; ++i) { + if (const BlockDeclRefExpr *BDRE = + dyn_cast<BlockDeclRefExpr>(BlockLayout[i])) { const ValueDecl *D = BDRE->getDecl(); DI->setLocation(D->getLocation()); DI->EmitDeclareOfBlockDeclRefVariable(BDRE, @@ -779,25 +875,15 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr, llvm::RoundUpToAlignment(BlockOffset.getQuantity(), MinAlign.getQuantity())); - Size = BlockOffset; - Align = BlockAlign; - subBlockDeclRefDecls = BlockDeclRefDecls; - subBlockHasCopyDispose |= BlockHasCopyDispose; + Info.BlockSize = BlockOffset; + Info.BlockAlign = BlockAlign; + Info.BlockLayout = BlockLayout; + Info.BlockHasCopyDispose = BlockHasCopyDispose; return Fn; } -CharUnits BlockFunction::getBlockOffset(const BlockDeclRefExpr *BDRE) { - const ValueDecl *D = dyn_cast<ValueDecl>(BDRE->getDecl()); - - CharUnits Size = getContext().getTypeSizeInChars(D->getType()); - CharUnits Align = getContext().getDeclAlign(D); - - if (BDRE->isByRef()) { - Size = getContext().getTypeSizeInChars(getContext().VoidPtrTy); - Align = getContext().getTypeAlignInChars(getContext().VoidPtrTy); - } - - assert ((Align.isPositive()) && "alignment must be 1 byte or more"); +CharUnits BlockFunction::getBlockOffset(CharUnits Size, CharUnits Align) { + assert((Align.isPositive()) && "alignment must be 1 byte or more"); CharUnits OldOffset = BlockOffset; @@ -808,23 +894,22 @@ CharUnits BlockFunction::getBlockOffset(const BlockDeclRefExpr *BDRE) { CharUnits Pad = BlockOffset - OldOffset; if (Pad.isPositive()) { - llvm::ArrayType::get(llvm::Type::getInt8Ty(VMContext), Pad.getQuantity()); QualType PadTy = getContext().getConstantArrayType(getContext().CharTy, llvm::APInt(32, Pad.getQuantity()), ArrayType::Normal, 0); - ValueDecl *PadDecl = VarDecl::Create(getContext(), 0, SourceLocation(), + ValueDecl *PadDecl = VarDecl::Create(getContext(), + getContext().getTranslationUnitDecl(), + SourceLocation(), 0, QualType(PadTy), 0, VarDecl::None, VarDecl::None); - Expr *E; - E = new (getContext()) DeclRefExpr(PadDecl, PadDecl->getType(), - SourceLocation()); - BlockDeclRefDecls.push_back(E); + Expr *E = new (getContext()) DeclRefExpr(PadDecl, PadDecl->getType(), + SourceLocation()); + BlockLayout.push_back(E); } - BlockDeclRefDecls.push_back(BDRE); BlockOffset += Size; - return BlockOffset-Size; + return BlockOffset - Size; } llvm::Constant *BlockFunction:: diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h index 5646d00..e9b2bd5 100644 --- a/lib/CodeGen/CGBlocks.h +++ b/lib/CodeGen/CGBlocks.h @@ -148,26 +148,6 @@ public: BLOCK_BYREF_CURRENT_MAX = 256 }; - /// BlockInfo - Information to generate a block literal. - struct BlockInfo { - /// BlockLiteralTy - The type of the block literal. - const llvm::Type *BlockLiteralTy; - - /// Name - the name of the function this block was created for, if any. - const char *Name; - - /// ByCopyDeclRefs - Variables from parent scopes that have been imported - /// into this block. - llvm::SmallVector<const BlockDeclRefExpr *, 8> DeclRefs; - - BlockInfo(const llvm::Type *blt, const char *n) - : BlockLiteralTy(blt), Name(n) { - // Skip asm prefix, if any. - if (Name && Name[0] == '\01') - ++Name; - } - }; - CGBuilderTy &Builder; BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf, CGBuilderTy &B); @@ -179,19 +159,31 @@ public: /// characters. CharUnits BlockAlign; - /// getBlockOffset - Allocate an offset for the ValueDecl from a - /// BlockDeclRefExpr in a block literal (BlockExpr). - CharUnits getBlockOffset(const BlockDeclRefExpr *E); + /// getBlockOffset - Allocate a location within the block's storage + /// for a value with the given size and alignment requirements. + CharUnits getBlockOffset(CharUnits Size, CharUnits Align); /// BlockHasCopyDispose - True iff the block uses copy/dispose. bool BlockHasCopyDispose; - /// BlockDeclRefDecls - Decls from BlockDeclRefExprs in apperance order - /// in a block literal. Decls without names are used for padding. - llvm::SmallVector<const Expr *, 8> BlockDeclRefDecls; + /// BlockLayout - The layout of the block's storage, represented as + /// a sequence of expressions which require such storage. The + /// expressions can be: + /// - a BlockDeclRefExpr, indicating that the given declaration + /// from an enclosing scope is needed by the block; + /// - a DeclRefExpr, which always wraps an anonymous VarDecl with + /// array type, used to insert padding into the block; or + /// - a CXXThisExpr, indicating that the C++ 'this' value should + /// propagate from the parent to the block. + /// This is a really silly representation. + llvm::SmallVector<const Expr *, 8> BlockLayout; /// BlockDecls - Offsets for all Decls in BlockDeclRefExprs. - std::map<const Decl*, CharUnits> BlockDecls; + llvm::DenseMap<const Decl*, CharUnits> BlockDecls; + + /// BlockCXXThisOffset - The offset of the C++ 'this' value within + /// the block structure. + CharUnits BlockCXXThisOffset; ImplicitParamDecl *BlockStructDecl; ImplicitParamDecl *getBlockStructDecl() { return BlockStructDecl; } diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 95c41db..dd505c2 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -71,7 +71,7 @@ static RValue EmitBinaryAtomic(CodeGenFunction &CGF, /// Utility to insert an atomic instruction based Instrinsic::ID and // the expression node, where the return value is the result of the // operation. -static RValue EmitBinaryAtomicPost(CodeGenFunction& CGF, +static RValue EmitBinaryAtomicPost(CodeGenFunction &CGF, Intrinsic::ID Id, const CallExpr *E, Instruction::BinaryOps Op) { const llvm::Type *ResType[2]; @@ -88,6 +88,30 @@ static llvm::ConstantInt *getInt32(llvm::LLVMContext &Context, int32_t Value) { return llvm::ConstantInt::get(llvm::Type::getInt32Ty(Context), Value); } + +/// EmitFAbs - Emit a call to fabs/fabsf/fabsl, depending on the type of ValTy, +/// which must be a scalar floating point type. +static Value *EmitFAbs(CodeGenFunction &CGF, Value *V, QualType ValTy) { + const BuiltinType *ValTyP = ValTy->getAs<BuiltinType>(); + assert(ValTyP && "isn't scalar fp type!"); + + StringRef FnName; + switch (ValTyP->getKind()) { + default: assert(0 && "Isn't a scalar fp type!"); + case BuiltinType::Float: FnName = "fabsf"; break; + case BuiltinType::Double: FnName = "fabs"; break; + case BuiltinType::LongDouble: FnName = "fabsl"; break; + } + + // The prototype is something that takes and returns whatever V's type is. + std::vector<const llvm::Type*> Args; + Args.push_back(V->getType()); + llvm::FunctionType *FT = llvm::FunctionType::get(V->getType(), Args, false); + llvm::Value *Fn = CGF.CGM.CreateRuntimeFunction(FT, FnName); + + return CGF.Builder.CreateCall(Fn, V, "abs"); +} + RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, unsigned BuiltinID, const CallExpr *E) { // See if we can constant fold this builtin. If so, don't emit it at all. @@ -328,6 +352,50 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, V = Builder.CreateFCmpUNO(V, V, "cmp"); return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType()), "tmp")); } + + case Builtin::BI__builtin_isinf: { + // isinf(x) --> fabs(x) == infinity + Value *V = EmitScalarExpr(E->getArg(0)); + V = EmitFAbs(*this, V, E->getArg(0)->getType()); + + V = Builder.CreateFCmpOEQ(V, ConstantFP::getInfinity(V->getType()),"isinf"); + return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType()), "tmp")); + } + + // TODO: BI__builtin_isinf_sign + // isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 + + case Builtin::BI__builtin_isnormal: { + // isnormal(x) --> x == x && fabsf(x) < infinity && fabsf(x) >= float_min + Value *V = EmitScalarExpr(E->getArg(0)); + Value *Eq = Builder.CreateFCmpOEQ(V, V, "iseq"); + + Value *Abs = EmitFAbs(*this, V, E->getArg(0)->getType()); + Value *IsLessThanInf = + Builder.CreateFCmpULT(Abs, ConstantFP::getInfinity(V->getType()),"isinf"); + APFloat Smallest = APFloat::getSmallestNormalized( + getContext().getFloatTypeSemantics(E->getArg(0)->getType())); + Value *IsNormal = + Builder.CreateFCmpUGE(Abs, ConstantFP::get(V->getContext(), Smallest), + "isnormal"); + V = Builder.CreateAnd(Eq, IsLessThanInf, "and"); + V = Builder.CreateAnd(V, IsNormal, "and"); + return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType()))); + } + + case Builtin::BI__builtin_isfinite: { + // isfinite(x) --> x == x && fabs(x) != infinity; } + Value *V = EmitScalarExpr(E->getArg(0)); + Value *Eq = Builder.CreateFCmpOEQ(V, V, "iseq"); + + Value *Abs = EmitFAbs(*this, V, E->getArg(0)->getType()); + Value *IsNotInf = + Builder.CreateFCmpUNE(Abs, ConstantFP::getInfinity(V->getType()),"isinf"); + + V = Builder.CreateAnd(Eq, IsNotInf, "and"); + return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType()))); + } + case Builtin::BIalloca: case Builtin::BI__builtin_alloca: { // FIXME: LLVM IR Should allow alloca with an i64 size! diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 74cf113..5258779 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -13,6 +13,7 @@ // We might split this into multiple files if it gets too unwieldy +#include "CGCXXABI.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" #include "Mangle.h" @@ -206,6 +207,7 @@ void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D, return; llvm::Function *Fn = cast<llvm::Function>(GetAddrOfCXXConstructor(D, Type)); + setFunctionLinkage(D, Fn); CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn); @@ -229,6 +231,10 @@ CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D, GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type))); } +void CodeGenModule::getMangledName(MangleBuffer &Buffer, const BlockDecl *BD) { + getMangleContext().mangleBlock(BD, Buffer.getBuffer()); +} + void CodeGenModule::getMangledCXXCtorName(MangleBuffer &Name, const CXXConstructorDecl *D, CXXCtorType Type) { @@ -269,6 +275,7 @@ void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D, return; llvm::Function *Fn = cast<llvm::Function>(GetAddrOfCXXDestructor(D, Type)); + setFunctionLinkage(D, Fn); CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn); @@ -327,3 +334,5 @@ CodeGenFunction::BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type, return ::BuildVirtualCall(*this, VTableIndex, This, Ty); } + +CXXABI::~CXXABI() {} diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h new file mode 100644 index 0000000..a7e1871 --- /dev/null +++ b/lib/CodeGen/CGCXXABI.h @@ -0,0 +1,37 @@ +//===----- CGCXXABI.h - Interface to C++ ABIs -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This provides an abstract class for C++ code generation. Concrete subclasses +// of this implement code generation for specific C++ ABIs. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_CODEGEN_CXXABI_H +#define CLANG_CODEGEN_CXXABI_H + +namespace clang { +namespace CodeGen { + class CodeGenModule; + class MangleContext; + +/// Implements C++ ABI-specific code generation functions. +class CXXABI { +public: + virtual ~CXXABI(); + + /// Gets the mangle context. + virtual MangleContext &getMangleContext() = 0; +}; + +/// Creates an instance of a C++ ABI class. +CXXABI *CreateItaniumCXXABI(CodeGenModule &CGM); +} +} + +#endif diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 92d15d9..73cee3c 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -38,6 +38,7 @@ static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) { default: return llvm::CallingConv::C; case CC_X86StdCall: return llvm::CallingConv::X86_StdCall; case CC_X86FastCall: return llvm::CallingConv::X86_FastCall; + case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall; } } @@ -97,6 +98,9 @@ static CallingConv getCallingConventionForDecl(const Decl *D) { if (D->hasAttr<FastCallAttr>()) return CC_X86FastCall; + if (D->hasAttr<ThisCallAttr>()) + return CC_X86ThisCall; + return CC_C; } @@ -858,6 +862,36 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, } } +RValue CodeGenFunction::EmitDelegateCallArg(const VarDecl *Param) { + // StartFunction converted the ABI-lowered parameter(s) into a + // local alloca. We need to turn that into an r-value suitable + // for EmitCall. + llvm::Value *Local = GetAddrOfLocalVar(Param); + + QualType ArgType = Param->getType(); + + // For the most part, we just need to load the alloca, except: + // 1) aggregate r-values are actually pointers to temporaries, and + // 2) references to aggregates are pointers directly to the aggregate. + // I don't know why references to non-aggregates are different here. + if (const ReferenceType *RefType = ArgType->getAs<ReferenceType>()) { + if (hasAggregateLLVMType(RefType->getPointeeType())) + return RValue::getAggregate(Local); + + // Locals which are references to scalars are represented + // with allocas holding the pointer. + return RValue::get(Builder.CreateLoad(Local)); + } + + if (ArgType->isAnyComplexType()) + return RValue::getComplex(LoadComplexFromAddr(Local, /*volatile*/ false)); + + if (hasAggregateLLVMType(ArgType)) + return RValue::getAggregate(Local); + + return RValue::get(EmitLoadOfScalar(Local, false, ArgType)); +} + RValue CodeGenFunction::EmitCallArg(const Expr *E, QualType ArgType) { if (ArgType->isReferenceType()) return EmitReferenceBindingToExpr(E); diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index a604eef..bebea54 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -262,102 +262,7 @@ CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value, return Value; } - -/// EmitCopyCtorCall - Emit a call to a copy constructor. -static void -EmitCopyCtorCall(CodeGenFunction &CGF, const CXXConstructorDecl *CopyCtor, - llvm::Value *ThisPtr, llvm::Value *Src) { - llvm::Value *Callee = CGF.CGM.GetAddrOfCXXConstructor(CopyCtor, Ctor_Complete); - - CallArgList CallArgs; - - // Push the this ptr. - CallArgs.push_back(std::make_pair(RValue::get(ThisPtr), - CopyCtor->getThisType(CGF.getContext()))); - - // Push the Src ptr. - CallArgs.push_back(std::make_pair(RValue::get(Src), - CopyCtor->getParamDecl(0)->getType())); - - - { - CodeGenFunction::CXXTemporariesCleanupScope Scope(CGF); - - // If the copy constructor has default arguments, emit them. - for (unsigned I = 1, E = CopyCtor->getNumParams(); I < E; ++I) { - const ParmVarDecl *Param = CopyCtor->getParamDecl(I); - const Expr *DefaultArgExpr = Param->getDefaultArg(); - - assert(DefaultArgExpr && "Ctor parameter must have default arg!"); - - QualType ArgType = Param->getType(); - CallArgs.push_back(std::make_pair(CGF.EmitCallArg(DefaultArgExpr, - ArgType), - ArgType)); - } - - const FunctionProtoType *FPT = - CopyCtor->getType()->getAs<FunctionProtoType>(); - CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(CallArgs, FPT), - Callee, ReturnValueSlot(), CallArgs, CopyCtor); - } -} -/// EmitClassAggrMemberwiseCopy - This routine generates code to copy a class -/// array of objects from SrcValue to DestValue. Copying can be either a bitwise -/// copy or via a copy constructor call. -// FIXME. Consolidate this with EmitCXXAggrConstructorCall. -void CodeGenFunction::EmitClassAggrMemberwiseCopy(llvm::Value *Dest, - llvm::Value *Src, - const ConstantArrayType *Array, - const CXXRecordDecl *ClassDecl) { - // Create a temporary for the loop index and initialize it with 0. - llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext), - "loop.index"); - llvm::Value* zeroConstant = - llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)); - Builder.CreateStore(zeroConstant, IndexPtr); - // Start the loop with a block that tests the condition. - llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); - llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); - - EmitBlock(CondBlock); - - llvm::BasicBlock *ForBody = createBasicBlock("for.body"); - // Generate: if (loop-index < number-of-elements fall to the loop body, - // otherwise, go to the block after the for-loop. - uint64_t NumElements = getContext().getConstantArrayElementCount(Array); - llvm::Value * NumElementsPtr = - llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), NumElements); - llvm::Value *Counter = Builder.CreateLoad(IndexPtr); - llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElementsPtr, - "isless"); - // If the condition is true, execute the body. - Builder.CreateCondBr(IsLess, ForBody, AfterFor); - - EmitBlock(ForBody); - llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); - // Inside the loop body, emit the constructor call on the array element. - Counter = Builder.CreateLoad(IndexPtr); - Src = Builder.CreateInBoundsGEP(Src, Counter, "srcaddress"); - Dest = Builder.CreateInBoundsGEP(Dest, Counter, "destaddress"); - EmitClassMemberwiseCopy(Dest, Src, ClassDecl); - - EmitBlock(ContinueBlock); - - // Emit the increment of the loop counter. - llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1); - Counter = Builder.CreateLoad(IndexPtr); - NextVal = Builder.CreateAdd(Counter, NextVal, "inc"); - Builder.CreateStore(NextVal, IndexPtr); - - // Finally, branch back up to the condition for the next iteration. - EmitBranch(CondBlock); - - // Emit the fall-through block. - EmitBlock(AfterFor, true); -} - /// GetVTTParameter - Return the VTT parameter that should be passed to a /// base constructor/destructor with virtual bases. static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD, @@ -405,111 +310,6 @@ static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD, return VTT; } - -/// EmitClassMemberwiseCopy - This routine generates code to copy a class -/// object from SrcValue to DestValue. Copying can be either a bitwise copy -/// or via a copy constructor call. -void CodeGenFunction::EmitClassMemberwiseCopy( - llvm::Value *Dest, llvm::Value *Src, - const CXXRecordDecl *ClassDecl) { - if (ClassDecl->hasTrivialCopyConstructor()) { - EmitAggregateCopy(Dest, Src, getContext().getTagDeclType(ClassDecl)); - return; - } - - CXXConstructorDecl *CopyCtor = ClassDecl->getCopyConstructor(getContext(), 0); - assert(CopyCtor && "Did not have copy ctor!"); - - EmitCopyCtorCall(*this, CopyCtor, Dest, Src); -} - -/// SynthesizeCXXCopyConstructor - This routine implicitly defines body of a -/// copy constructor, in accordance with section 12.8 (p7 and p8) of C++03 -/// The implicitly-defined copy constructor for class X performs a memberwise -/// copy of its subobjects. The order of copying is the same as the order of -/// initialization of bases and members in a user-defined constructor -/// Each subobject is copied in the manner appropriate to its type: -/// if the subobject is of class type, the copy constructor for the class is -/// used; -/// if the subobject is an array, each element is copied, in the manner -/// appropriate to the element type; -/// if the subobject is of scalar type, the built-in assignment operator is -/// used. -/// Virtual base class subobjects shall be copied only once by the -/// implicitly-defined copy constructor - -void -CodeGenFunction::SynthesizeCXXCopyConstructor(const FunctionArgList &Args) { - const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(CurGD.getDecl()); - CXXCtorType CtorType = CurGD.getCtorType(); - (void) CtorType; - - const CXXRecordDecl *ClassDecl = Ctor->getParent(); - assert(!ClassDecl->hasUserDeclaredCopyConstructor() && - "SynthesizeCXXCopyConstructor - copy constructor has definition already"); - assert(!Ctor->isTrivial() && "shouldn't need to generate trivial ctor"); - - llvm::Value *ThisPtr = LoadCXXThis(); - - // Find the source pointer. - unsigned SrcArgIndex = Args.size() - 1; - assert(CtorType == Ctor_Base || SrcArgIndex == 1); - assert(CtorType != Ctor_Base || - (ClassDecl->getNumVBases() != 0 && SrcArgIndex == 2) || - SrcArgIndex == 1); - - llvm::Value *SrcPtr = - Builder.CreateLoad(GetAddrOfLocalVar(Args[SrcArgIndex].first)); - - for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(), - E = ClassDecl->field_end(); I != E; ++I) { - const FieldDecl *Field = *I; - - QualType FieldType = getContext().getCanonicalType(Field->getType()); - const ConstantArrayType *Array = - getContext().getAsConstantArrayType(FieldType); - if (Array) - FieldType = getContext().getBaseElementType(FieldType); - - if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { - CXXRecordDecl *FieldClassDecl - = cast<CXXRecordDecl>(FieldClassType->getDecl()); - LValue LHS = EmitLValueForField(ThisPtr, Field, 0); - LValue RHS = EmitLValueForField(SrcPtr, Field, 0); - if (Array) { - const llvm::Type *BasePtr = ConvertType(FieldType)->getPointerTo(); - llvm::Value *DestBaseAddrPtr = - Builder.CreateBitCast(LHS.getAddress(), BasePtr); - llvm::Value *SrcBaseAddrPtr = - Builder.CreateBitCast(RHS.getAddress(), BasePtr); - EmitClassAggrMemberwiseCopy(DestBaseAddrPtr, SrcBaseAddrPtr, Array, - FieldClassDecl); - } - else - EmitClassMemberwiseCopy(LHS.getAddress(), RHS.getAddress(), - FieldClassDecl); - continue; - } - - // Do a built-in assignment of scalar data members. - LValue LHS = EmitLValueForFieldInitialization(ThisPtr, Field, 0); - LValue RHS = EmitLValueForFieldInitialization(SrcPtr, Field, 0); - - if (!hasAggregateLLVMType(Field->getType())) { - RValue RVRHS = EmitLoadOfLValue(RHS, Field->getType()); - EmitStoreThroughLValue(RVRHS, LHS, Field->getType()); - } else if (Field->getType()->isAnyComplexType()) { - ComplexPairTy Pair = LoadComplexFromAddr(RHS.getAddress(), - RHS.isVolatileQualified()); - StoreComplexToAddr(Pair, LHS.getAddress(), LHS.isVolatileQualified()); - } else { - EmitAggregateCopy(LHS.getAddress(), RHS.getAddress(), Field->getType()); - } - } - - InitializeVTablePointers(ClassDecl); -} - static void EmitBaseInitializer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl, CXXBaseOrMemberInitializer *BaseInit, @@ -547,9 +347,97 @@ static void EmitBaseInitializer(CodeGenFunction &CGF, } } +static void EmitAggMemberInitializer(CodeGenFunction &CGF, + LValue LHS, + llvm::Value *ArrayIndexVar, + CXXBaseOrMemberInitializer *MemberInit, + QualType T, + unsigned Index) { + if (Index == MemberInit->getNumArrayIndices()) { + CodeGenFunction::CleanupScope Cleanups(CGF); + + llvm::Value *Dest = LHS.getAddress(); + if (ArrayIndexVar) { + // If we have an array index variable, load it and use it as an offset. + // Then, increment the value. + llvm::Value *ArrayIndex = CGF.Builder.CreateLoad(ArrayIndexVar); + Dest = CGF.Builder.CreateInBoundsGEP(Dest, ArrayIndex, "destaddress"); + llvm::Value *Next = llvm::ConstantInt::get(ArrayIndex->getType(), 1); + Next = CGF.Builder.CreateAdd(ArrayIndex, Next, "inc"); + CGF.Builder.CreateStore(Next, ArrayIndexVar); + } + + CGF.EmitAggExpr(MemberInit->getInit(), Dest, + LHS.isVolatileQualified(), + /*IgnoreResult*/ false, + /*IsInitializer*/ true); + + return; + } + + const ConstantArrayType *Array = CGF.getContext().getAsConstantArrayType(T); + assert(Array && "Array initialization without the array type?"); + llvm::Value *IndexVar + = CGF.GetAddrOfLocalVar(MemberInit->getArrayIndex(Index)); + assert(IndexVar && "Array index variable not loaded"); + + // Initialize this index variable to zero. + llvm::Value* Zero + = llvm::Constant::getNullValue( + CGF.ConvertType(CGF.getContext().getSizeType())); + CGF.Builder.CreateStore(Zero, IndexVar); + + // Start the loop with a block that tests the condition. + llvm::BasicBlock *CondBlock = CGF.createBasicBlock("for.cond"); + llvm::BasicBlock *AfterFor = CGF.createBasicBlock("for.end"); + + CGF.EmitBlock(CondBlock); + + llvm::BasicBlock *ForBody = CGF.createBasicBlock("for.body"); + // Generate: if (loop-index < number-of-elements) fall to the loop body, + // otherwise, go to the block after the for-loop. + uint64_t NumElements = Array->getSize().getZExtValue(); + llvm::Value *Counter = CGF.Builder.CreateLoad(IndexVar); + llvm::Value *NumElementsPtr = + llvm::ConstantInt::get(Counter->getType(), NumElements); + llvm::Value *IsLess = CGF.Builder.CreateICmpULT(Counter, NumElementsPtr, + "isless"); + + // If the condition is true, execute the body. + CGF.Builder.CreateCondBr(IsLess, ForBody, AfterFor); + + CGF.EmitBlock(ForBody); + llvm::BasicBlock *ContinueBlock = CGF.createBasicBlock("for.inc"); + + { + CodeGenFunction::CleanupScope Cleanups(CGF); + + // Inside the loop body recurse to emit the inner loop or, eventually, the + // constructor call. + EmitAggMemberInitializer(CGF, LHS, ArrayIndexVar, MemberInit, + Array->getElementType(), Index + 1); + } + + CGF.EmitBlock(ContinueBlock); + + // Emit the increment of the loop counter. + llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1); + Counter = CGF.Builder.CreateLoad(IndexVar); + NextVal = CGF.Builder.CreateAdd(Counter, NextVal, "inc"); + CGF.Builder.CreateStore(NextVal, IndexVar); + + // Finally, branch back up to the condition for the next iteration. + CGF.EmitBranch(CondBlock); + + // Emit the fall-through block. + CGF.EmitBlock(AfterFor, true); +} + static void EmitMemberInitializer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl, - CXXBaseOrMemberInitializer *MemberInit) { + CXXBaseOrMemberInitializer *MemberInit, + const CXXConstructorDecl *Constructor, + FunctionArgList &Args) { assert(MemberInit->isMemberInitializer() && "Must have member initializer!"); @@ -558,13 +446,15 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, QualType FieldType = CGF.getContext().getCanonicalType(Field->getType()); llvm::Value *ThisPtr = CGF.LoadCXXThis(); - LValue LHS = CGF.EmitLValueForFieldInitialization(ThisPtr, Field, 0); + LValue LHS; // If we are initializing an anonymous union field, drill down to the field. if (MemberInit->getAnonUnionMember()) { Field = MemberInit->getAnonUnionMember(); - LHS = CGF.EmitLValueForField(LHS.getAddress(), Field, 0); + LHS = CGF.EmitLValueForAnonRecordField(ThisPtr, Field, 0); FieldType = Field->getType(); + } else { + LHS = CGF.EmitLValueForFieldInitialization(ThisPtr, Field, 0); } // FIXME: If there's no initializer and the CXXBaseOrMemberInitializer @@ -575,7 +465,7 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, /*IsInitializer=*/true); CGF.EmitStoreThroughLValue(RHS, LHS, FieldType); } else if (FieldType->isArrayType() && !MemberInit->getInit()) { - CGF.EmitMemSetToZero(LHS.getAddress(), Field->getType()); + CGF.EmitNullInitialization(LHS.getAddress(), Field->getType()); } else if (!CGF.hasAggregateLLVMType(Field->getType())) { RHS = RValue::get(CGF.EmitScalarExpr(MemberInit->getInit(), true)); CGF.EmitStoreThroughLValue(RHS, LHS, FieldType); @@ -583,14 +473,61 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, CGF.EmitComplexExprIntoAddr(MemberInit->getInit(), LHS.getAddress(), LHS.isVolatileQualified()); } else { - CGF.EmitAggExpr(MemberInit->getInit(), LHS.getAddress(), - LHS.isVolatileQualified(), - /*IgnoreResult*/ false, - /*IsInitializer*/ true); + llvm::Value *ArrayIndexVar = 0; + const ConstantArrayType *Array + = CGF.getContext().getAsConstantArrayType(FieldType); + if (Array && Constructor->isImplicit() && + Constructor->isCopyConstructor()) { + const llvm::Type *SizeTy + = CGF.ConvertType(CGF.getContext().getSizeType()); + + // The LHS is a pointer to the first object we'll be constructing, as + // a flat array. + QualType BaseElementTy = CGF.getContext().getBaseElementType(Array); + const llvm::Type *BasePtr = CGF.ConvertType(BaseElementTy); + BasePtr = llvm::PointerType::getUnqual(BasePtr); + llvm::Value *BaseAddrPtr = CGF.Builder.CreateBitCast(LHS.getAddress(), + BasePtr); + LHS = LValue::MakeAddr(BaseAddrPtr, CGF.MakeQualifiers(BaseElementTy)); + + // Create an array index that will be used to walk over all of the + // objects we're constructing. + ArrayIndexVar = CGF.CreateTempAlloca(SizeTy, "object.index"); + llvm::Value *Zero = llvm::Constant::getNullValue(SizeTy); + CGF.Builder.CreateStore(Zero, ArrayIndexVar); + + // If we are copying an array of scalars or classes with trivial copy + // constructors, perform a single aggregate copy. + const RecordType *Record = BaseElementTy->getAs<RecordType>(); + if (!Record || + cast<CXXRecordDecl>(Record->getDecl())->hasTrivialCopyConstructor()) { + // Find the source pointer. We knows it's the last argument because + // we know we're in a copy constructor. + unsigned SrcArgIndex = Args.size() - 1; + llvm::Value *SrcPtr + = CGF.Builder.CreateLoad( + CGF.GetAddrOfLocalVar(Args[SrcArgIndex].first)); + LValue Src = CGF.EmitLValueForFieldInitialization(SrcPtr, Field, 0); + + // Copy the aggregate. + CGF.EmitAggregateCopy(LHS.getAddress(), Src.getAddress(), FieldType, + LHS.isVolatileQualified()); + return; + } + + // Emit the block variables for the array indices, if any. + for (unsigned I = 0, N = MemberInit->getNumArrayIndices(); I != N; ++I) + CGF.EmitLocalBlockVarDecl(*MemberInit->getArrayIndex(I)); + } + + EmitAggMemberInitializer(CGF, LHS, ArrayIndexVar, MemberInit, FieldType, 0); if (!CGF.Exceptions) return; + // FIXME: If we have an array of classes w/ non-trivial destructors, + // we need to destroy in reverse order of construction along the exception + // path. const RecordType *RT = FieldType->getAs<RecordType>(); if (!RT) return; @@ -680,20 +617,13 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) { // Emit the constructor prologue, i.e. the base and member // initializers. - EmitCtorPrologue(Ctor, CtorType); + EmitCtorPrologue(Ctor, CtorType, Args); // Emit the body of the statement. if (IsTryBody) EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock()); else if (Body) EmitStmt(Body); - else { - assert(Ctor->isImplicit() && "bodyless ctor not implicit"); - if (!Ctor->isDefaultConstructor()) { - assert(Ctor->isCopyConstructor()); - SynthesizeCXXCopyConstructor(Args); - } - } // Emit any cleanup blocks associated with the member or base // initializers, which includes (along the exceptional path) the @@ -708,7 +638,8 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) { /// EmitCtorPrologue - This routine generates necessary code to initialize /// base classes and non-static data members belonging to this constructor. void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, - CXXCtorType CtorType) { + CXXCtorType CtorType, + FunctionArgList &Args) { const CXXRecordDecl *ClassDecl = CD->getParent(); llvm::SmallVector<CXXBaseOrMemberInitializer *, 8> MemberInitializers; @@ -733,7 +664,7 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, assert(LiveTemporaries.empty() && "Should not have any live temporaries at initializer start!"); - EmitMemberInitializer(*this, ClassDecl, MemberInitializers[I]); + EmitMemberInitializer(*this, ClassDecl, MemberInitializers[I], CD, Args); } } @@ -1206,34 +1137,9 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, // Explicit arguments. for (; I != E; ++I) { - const VarDecl *Param = I->first; QualType ArgType = Param->getType(); // because we're passing it to itself - - // StartFunction converted the ABI-lowered parameter(s) into a - // local alloca. We need to turn that into an r-value suitable - // for EmitCall. - llvm::Value *Local = GetAddrOfLocalVar(Param); - RValue Arg; - - // For the most part, we just need to load the alloca, except: - // 1) aggregate r-values are actually pointers to temporaries, and - // 2) references to aggregates are pointers directly to the aggregate. - // I don't know why references to non-aggregates are different here. - if (ArgType->isReferenceType()) { - const ReferenceType *RefType = ArgType->getAs<ReferenceType>(); - if (hasAggregateLLVMType(RefType->getPointeeType())) - Arg = RValue::getAggregate(Local); - else - // Locals which are references to scalars are represented - // with allocas holding the pointer. - Arg = RValue::get(Builder.CreateLoad(Local)); - } else { - if (hasAggregateLLVMType(ArgType)) - Arg = RValue::getAggregate(Local); - else - Arg = RValue::get(EmitLoadOfScalar(Local, false, ArgType)); - } + RValue Arg = EmitDelegateCallArg(Param); DelegateArgs.push_back(std::make_pair(Arg, ArgType)); } diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 48ae511..c9bcb1b 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -64,7 +64,14 @@ llvm::DIDescriptor CGDebugInfo::getContextDescriptor(const Decl *Context, // Check namespace. if (const NamespaceDecl *NSDecl = dyn_cast<NamespaceDecl>(Context)) return llvm::DIDescriptor(getOrCreateNameSpace(NSDecl, CompileUnit)); - + + if (const RecordDecl *RDecl = dyn_cast<RecordDecl>(Context)) { + if (!RDecl->isDependentType()) { + llvm::DIType Ty = getOrCreateType(CGM.getContext().getTypeDeclType(RDecl), + llvm::DIFile(CompileUnit)); + return llvm::DIDescriptor(Ty); + } + } return CompileUnit; } @@ -114,10 +121,29 @@ llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) { llvm::DIFile F = DebugFactory.CreateFile(AbsFileName.getLast(), AbsFileName.getDirname(), TheCU); - DIFileCache[fname] = F.getNode(); + DIFileCache[fname] = F; return F; } + +/// getLineNumber - Get line number for the location. If location is invalid +/// then use current location. +unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) { + assert (CurLoc.isValid() && "Invalid current location!"); + SourceManager &SM = CGM.getContext().getSourceManager(); + PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc); + return PLoc.getLine(); +} + +/// getColumnNumber - Get column number for the location. If location is +/// invalid then use current location. +unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc) { + assert (CurLoc.isValid() && "Invalid current location!"); + SourceManager &SM = CGM.getContext().getSourceManager(); + PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc); + return PLoc.getColumn(); +} + /// CreateCompileUnit - Create new compile unit. void CGDebugInfo::CreateCompileUnit() { @@ -327,10 +353,11 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, EltTys.clear(); unsigned Flags = llvm::DIType::FlagAppleBlock; + unsigned LineNo = getLineNumber(CurLoc); EltTy = DebugFactory.CreateCompositeType(Tag, Unit, "__block_descriptor", - Unit, 0, FieldOffset, 0, 0, Flags, - llvm::DIType(), Elements); + Unit, LineNo, FieldOffset, 0, 0, + Flags, llvm::DIType(), Elements); // Bit size, align and offset of the type. uint64_t Size = CGM.getContext().getTypeSize(Ty); @@ -338,7 +365,7 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, DescTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit, "", Unit, - 0, Size, Align, 0, 0, EltTy); + LineNo, Size, Align, 0, 0, EltTy); FieldOffset = 0; FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); @@ -355,7 +382,7 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, FieldAlign = CGM.getContext().getTypeAlign(Ty); FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, "__descriptor", Unit, - 0, FieldSize, FieldAlign, + LineNo, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); @@ -363,14 +390,14 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, Elements = DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size()); EltTy = DebugFactory.CreateCompositeType(Tag, Unit, "__block_literal_generic", - Unit, 0, FieldOffset, 0, 0, Flags, - llvm::DIType(), Elements); + Unit, LineNo, FieldOffset, 0, 0, + Flags, llvm::DIType(), Elements); BlockLiteralGenericSet = true; BlockLiteralGeneric = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit, "", Unit, - 0, Size, Align, 0, 0, EltTy); + LineNo, Size, Align, 0, 0, EltTy); return BlockLiteralGeneric; } @@ -382,9 +409,7 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, // We don't set size information, but do specify where the typedef was // declared. - SourceManager &SM = CGM.getContext().getSourceManager(); - PresumedLoc PLoc = SM.getPresumedLoc(Ty->getDecl()->getLocation()); - unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine(); + unsigned Line = getLineNumber(Ty->getDecl()->getLocation()); llvm::DIDescriptor TyContext = getContextDescriptor(dyn_cast<Decl>(Ty->getDecl()->getDeclContext()), @@ -430,7 +455,6 @@ void CGDebugInfo:: CollectRecordFields(const RecordDecl *RD, llvm::DIFile Unit, llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys) { unsigned FieldNo = 0; - SourceManager &SM = CGM.getContext().getSourceManager(); const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); @@ -445,16 +469,8 @@ CollectRecordFields(const RecordDecl *RD, llvm::DIFile Unit, continue; // Get the location for the field. - SourceLocation FieldDefLoc = Field->getLocation(); - PresumedLoc PLoc = SM.getPresumedLoc(FieldDefLoc); - llvm::DIFile FieldDefUnit; - unsigned FieldLine = 0; - - if (!PLoc.isInvalid()) { - FieldDefUnit = getOrCreateFile(FieldDefLoc); - FieldLine = PLoc.getLine(); - } - + llvm::DIFile FieldDefUnit = getOrCreateFile(Field->getLocation()); + unsigned FieldLine = getLineNumber(Field->getLocation()); QualType FType = Field->getType(); uint64_t FieldSize = 0; unsigned FieldAlign = 0; @@ -506,7 +522,7 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, // Add "this" pointer. - llvm::DIArray Args = llvm::DICompositeType(FnTy.getNode()).getTypeArray(); + llvm::DIArray Args = llvm::DICompositeType(FnTy).getTypeArray(); assert (Args.getNumElements() && "Invalid number of arguments!"); llvm::SmallVector<llvm::DIDescriptor, 16> Elts; @@ -520,7 +536,7 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, Context.getPointerType(Context.getTagDeclType(Method->getParent())); llvm::DIType ThisPtrType = DebugFactory.CreateArtificialType(getOrCreateType(ThisPtr, Unit)); - TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType.getNode(); + TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType; Elts.push_back(ThisPtrType); // Copy rest of the arguments. @@ -555,18 +571,9 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method, if (!IsCtorOrDtor) CGM.getMangledName(MethodLinkageName, Method); - SourceManager &SM = CGM.getContext().getSourceManager(); - // Get the location for the method. - SourceLocation MethodDefLoc = Method->getLocation(); - PresumedLoc PLoc = SM.getPresumedLoc(MethodDefLoc); - llvm::DIFile MethodDefUnit; - unsigned MethodLine = 0; - - if (!PLoc.isInvalid()) { - MethodDefUnit = getOrCreateFile(MethodDefLoc); - MethodLine = PLoc.getLine(); - } + llvm::DIFile MethodDefUnit = getOrCreateFile(Method->getLocation()); + unsigned MethodLine = getLineNumber(Method->getLocation()); // Collect virtual method info. llvm::DIType ContainingType; @@ -597,7 +604,7 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method, // Don't cache ctors or dtors since we have to emit multiple functions for // a single ctor or dtor. if (!IsCtorOrDtor && Method->isThisDeclarationADefinition()) - SPCache[Method] = llvm::WeakVH(SP.getNode()); + SPCache[Method] = llvm::WeakVH(SP); return SP; } @@ -741,16 +748,9 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, Tag = llvm::dwarf::DW_TAG_class_type; } - SourceManager &SM = CGM.getContext().getSourceManager(); - // Get overall information about the record type for the debug info. - PresumedLoc PLoc = SM.getPresumedLoc(RD->getLocation()); - llvm::DIFile DefUnit; - unsigned Line = 0; - if (!PLoc.isInvalid()) { - DefUnit = getOrCreateFile(RD->getLocation()); - Line = PLoc.getLine(); - } + llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation()); + unsigned Line = getLineNumber(RD->getLocation()); // Records and classes and unions can all be recursive. To handle them, we // first generate a debug descriptor for the struct as a forward declaration. @@ -774,13 +774,14 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, if (!RD->getDefinition()) return FwdDecl; - llvm::TrackingVH<llvm::MDNode> FwdDeclNode = FwdDecl.getNode(); + llvm::MDNode *MN = FwdDecl; + llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN; // Otherwise, insert it into the TypeCache so that recursive uses will find // it. - TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl.getNode(); + TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl; // Push the struct on region stack. - RegionStack.push_back(FwdDecl.getNode()); - RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl.getNode()); + RegionStack.push_back(FwdDeclNode); + RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl); // Convert all the elements. llvm::SmallVector<llvm::DIDescriptor, 16> EltTys; @@ -799,9 +800,9 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) ContainingType = - getOrCreateType(QualType(PBase->getTypeForDecl(), 0), Unit).getNode(); + getOrCreateType(QualType(PBase->getTypeForDecl(), 0), Unit); else if (CXXDecl->isDynamicClass()) - ContainingType = FwdDecl.getNode(); + ContainingType = FwdDecl; } llvm::DIArray Elements = @@ -829,24 +830,26 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, // Now that we have a real decl for the struct, replace anything using the // old decl with the new one. This will recursively update the debug info. llvm::DIDerivedType(FwdDeclNode).replaceAllUsesWith(RealDecl); - RegionMap[RD] = llvm::WeakVH(RealDecl.getNode()); + RegionMap[RD] = llvm::WeakVH(RealDecl); return RealDecl; } +/// CreateType - get objective-c object type. +llvm::DIType CGDebugInfo::CreateType(const ObjCObjectType *Ty, + llvm::DIFile Unit) { + // Ignore protocols. + return getOrCreateType(Ty->getBaseType(), Unit); +} + /// CreateType - get objective-c interface type. llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, llvm::DIFile Unit) { ObjCInterfaceDecl *ID = Ty->getDecl(); - unsigned Tag = llvm::dwarf::DW_TAG_structure_type; - SourceManager &SM = CGM.getContext().getSourceManager(); // Get overall information about the record type for the debug info. llvm::DIFile DefUnit = getOrCreateFile(ID->getLocation()); - PresumedLoc PLoc = SM.getPresumedLoc(ID->getLocation()); - unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine(); - - + unsigned Line = getLineNumber(ID->getLocation()); unsigned RuntimeLang = TheCU.getLanguage(); // To handle recursive interface, we @@ -865,13 +868,14 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, if (ID->isForwardDecl()) return FwdDecl; - llvm::TrackingVH<llvm::MDNode> FwdDeclNode = FwdDecl.getNode(); + llvm::MDNode *MN = FwdDecl; + llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN; // Otherwise, insert it into the TypeCache so that recursive uses will find // it. - TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl.getNode(); + TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl; // Push the struct on region stack. - RegionStack.push_back(FwdDecl.getNode()); - RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl.getNode()); + RegionStack.push_back(FwdDeclNode); + RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl); // Convert all the elements. llvm::SmallVector<llvm::DIDescriptor, 16> EltTys; @@ -902,12 +906,8 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, continue; // Get the location for the field. - SourceLocation FieldDefLoc = Field->getLocation(); - llvm::DIFile FieldDefUnit = getOrCreateFile(FieldDefLoc); - PresumedLoc PLoc = SM.getPresumedLoc(FieldDefLoc); - unsigned FieldLine = PLoc.isInvalid() ? 0 : PLoc.getLine(); - - + llvm::DIFile FieldDefUnit = getOrCreateFile(Field->getLocation()); + unsigned FieldLine = getLineNumber(Field->getLocation()); QualType FType = Field->getType(); uint64_t FieldSize = 0; unsigned FieldAlign = 0; @@ -962,7 +962,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, // Now that we have a real decl for the struct, replace anything using the // old decl with the new one. This will recursively update the debug info. llvm::DIDerivedType(FwdDeclNode).replaceAllUsesWith(RealDecl); - RegionMap[ID] = llvm::WeakVH(RealDecl.getNode()); + RegionMap[ID] = llvm::WeakVH(RealDecl); return RealDecl; } @@ -985,12 +985,8 @@ llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty, llvm::DIArray EltArray = DebugFactory.GetOrCreateArray(Enumerators.data(), Enumerators.size()); - SourceLocation DefLoc = ED->getLocation(); - llvm::DIFile DefUnit = getOrCreateFile(DefLoc); - SourceManager &SM = CGM.getContext().getSourceManager(); - PresumedLoc PLoc = SM.getPresumedLoc(DefLoc); - unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine(); - + llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation()); + unsigned Line = getLineNumber(ED->getLocation()); // Size and align of the type. uint64_t Size = 0; @@ -1152,15 +1148,12 @@ static QualType UnwrapTypeForDebugInfo(QualType T) { case Type::Decltype: T = cast<DecltypeType>(T)->getUnderlyingType(); break; - case Type::QualifiedName: - T = cast<QualifiedNameType>(T)->getNamedType(); + case Type::Elaborated: + T = cast<ElaboratedType>(T)->getNamedType(); break; case Type::SubstTemplateTypeParm: T = cast<SubstTemplateTypeParmType>(T)->getReplacementType(); break; - case Type::Elaborated: - T = cast<ElaboratedType>(T)->getUnderlyingType(); - break; } assert(T != LastT && "Type unwrapping failed to unwrap!"); @@ -1194,7 +1187,7 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIType Res = CreateTypeNode(Ty, Unit); // And update the type cache. - TypeCache[Ty.getAsOpaquePtr()] = Res.getNode(); + TypeCache[Ty.getAsOpaquePtr()] = Res; return Res; } @@ -1224,6 +1217,8 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, return CreateType(cast<VectorType>(Ty), Unit); case Type::ObjCObjectPointer: return CreateType(cast<ObjCObjectPointerType>(Ty), Unit); + case Type::ObjCObject: + return CreateType(cast<ObjCObjectType>(Ty), Unit); case Type::ObjCInterface: return CreateType(cast<ObjCInterfaceType>(Ty), Unit); case Type::Builtin: return CreateType(cast<BuiltinType>(Ty), Unit); @@ -1251,7 +1246,6 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, case Type::TemplateSpecialization: case Type::Elaborated: - case Type::QualifiedName: case Type::SubstTemplateTypeParm: case Type::TypeOfExpr: case Type::TypeOf: @@ -1304,9 +1298,10 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, FI = SPCache.find(FD); if (FI != SPCache.end()) { llvm::DIDescriptor SP(dyn_cast_or_null<llvm::MDNode>(FI->second)); - if (SP.isSubprogram() && llvm::DISubprogram(SP.getNode()).isDefinition()) { - RegionStack.push_back(SP.getNode()); - RegionMap[D] = llvm::WeakVH(SP.getNode()); + if (SP.isSubprogram() && llvm::DISubprogram(SP).isDefinition()) { + llvm::MDNode *SPN = SP; + RegionStack.push_back(SPN); + RegionMap[D] = llvm::WeakVH(SP); return; } } @@ -1325,8 +1320,7 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, // Usually, CurLoc points to the left bracket location of compound // statement representing function body. llvm::DIFile Unit = getOrCreateFile(CurLoc); - SourceManager &SM = CGM.getContext().getSourceManager(); - unsigned LineNo = SM.getPresumedLoc(CurLoc).getLine(); + unsigned LineNo = getLineNumber(CurLoc); llvm::DISubprogram SP = DebugFactory.CreateSubprogram(Unit, Name, Name, LinkageName, Unit, LineNo, @@ -1334,8 +1328,9 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, Fn->hasInternalLinkage(), true/*definition*/); // Push function on region stack. - RegionStack.push_back(SP.getNode()); - RegionMap[D] = llvm::WeakVH(SP.getNode()); + llvm::MDNode *SPN = SP; + RegionStack.push_back(SPN); + RegionMap[D] = llvm::WeakVH(SP); } @@ -1355,27 +1350,23 @@ void CGDebugInfo::EmitStopPoint(llvm::Function *Fn, CGBuilderTy &Builder) { // Update last state. PrevLoc = CurLoc; - // Get the appropriate compile unit. - llvm::DIFile Unit = getOrCreateFile(CurLoc); - PresumedLoc PLoc = SM.getPresumedLoc(CurLoc); - llvm::MDNode *Scope = RegionStack.back(); - Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(PLoc.getLine(), - PLoc.getColumn(), + Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(getLineNumber(CurLoc), + getColumnNumber(CurLoc), Scope)); } /// EmitRegionStart- Constructs the debug code for entering a declarative /// region - "llvm.dbg.region.start.". void CGDebugInfo::EmitRegionStart(llvm::Function *Fn, CGBuilderTy &Builder) { - SourceManager &SM = CGM.getContext().getSourceManager(); - PresumedLoc PLoc = SM.getPresumedLoc(CurLoc); llvm::DIDescriptor D = DebugFactory.CreateLexicalBlock(RegionStack.empty() ? llvm::DIDescriptor() : llvm::DIDescriptor(RegionStack.back()), - PLoc.getLine(), PLoc.getColumn()); - RegionStack.push_back(D.getNode()); + getLineNumber(CurLoc), + getColumnNumber(CurLoc)); + llvm::MDNode *DN = D; + RegionStack.push_back(DN); } /// EmitRegionEnd - Constructs the debug code for exiting a declarative @@ -1473,20 +1464,14 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, else Ty = getOrCreateType(VD->getType(), Unit); + // If there is not any debug info for type then do not emit debug info + // for this variable. + if (!Ty) + return; + // Get location information. - SourceManager &SM = CGM.getContext().getSourceManager(); - PresumedLoc PLoc = SM.getPresumedLoc(VD->getLocation()); - unsigned Line = 0; - unsigned Column = 0; - if (PLoc.isInvalid()) - PLoc = SM.getPresumedLoc(CurLoc); - if (PLoc.isValid()) { - Line = PLoc.getLine(); - Column = PLoc.getColumn(); - Unit = getOrCreateFile(CurLoc); - } else { - Unit = llvm::DIFile(); - } + unsigned Line = getLineNumber(VD->getLocation()); + unsigned Column = getColumnNumber(VD->getLocation()); // Create the descriptor for the variable. llvm::DIVariable D = @@ -1520,13 +1505,8 @@ void CGDebugInfo::EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag, Ty = getOrCreateType(VD->getType(), Unit); // Get location information. - SourceManager &SM = CGM.getContext().getSourceManager(); - PresumedLoc PLoc = SM.getPresumedLoc(VD->getLocation()); - unsigned Line = 0; - if (!PLoc.isInvalid()) - Line = PLoc.getLine(); - else - Unit = llvm::DIFile(); + unsigned Line = getLineNumber(VD->getLocation()); + unsigned Column = getColumnNumber(VD->getLocation()); CharUnits offset = CGF->BlockDecls[VD]; llvm::SmallVector<llvm::Value *, 9> addr; @@ -1558,7 +1538,7 @@ void CGDebugInfo::EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag, DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertBlock()); llvm::MDNode *Scope = RegionStack.back(); - Call->setDebugLoc(llvm::DebugLoc::get(Line, PLoc.getColumn(), Scope)); + Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope)); } void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, @@ -1588,9 +1568,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, // Create global variable debug descriptor. llvm::DIFile Unit = getOrCreateFile(D->getLocation()); - SourceManager &SM = CGM.getContext().getSourceManager(); - PresumedLoc PLoc = SM.getPresumedLoc(D->getLocation()); - unsigned LineNo = PLoc.isInvalid() ? 0 : PLoc.getLine(); + unsigned LineNo = getLineNumber(D->getLocation()); QualType T = D->getType(); if (T->isIncompleteArrayType()) { @@ -1605,11 +1583,13 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, ArrayType::Normal, 0); } llvm::StringRef DeclName = D->getName(); + llvm::StringRef LinkageName; + if (D->getDeclContext() && !isa<FunctionDecl>(D->getDeclContext())) + LinkageName = Var->getName(); llvm::DIDescriptor DContext = getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()), Unit); - DebugFactory.CreateGlobalVariable(DContext, DeclName, - DeclName, llvm::StringRef(), Unit, LineNo, - getOrCreateType(T, Unit), + DebugFactory.CreateGlobalVariable(DContext, DeclName, DeclName, LinkageName, + Unit, LineNo, getOrCreateType(T, Unit), Var->hasInternalLinkage(), true/*definition*/, Var); } @@ -1619,9 +1599,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, ObjCInterfaceDecl *ID) { // Create global variable debug descriptor. llvm::DIFile Unit = getOrCreateFile(ID->getLocation()); - SourceManager &SM = CGM.getContext().getSourceManager(); - PresumedLoc PLoc = SM.getPresumedLoc(ID->getLocation()); - unsigned LineNo = PLoc.isInvalid() ? 0 : PLoc.getLine(); + unsigned LineNo = getLineNumber(ID->getLocation()); llvm::StringRef Name = ID->getName(); @@ -1654,15 +1632,13 @@ CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl, if (I != NameSpaceCache.end()) return llvm::DINameSpace(cast<llvm::MDNode>(I->second)); - SourceManager &SM = CGM.getContext().getSourceManager(); - PresumedLoc PLoc = SM.getPresumedLoc(NSDecl->getLocation()); - unsigned LineNo = PLoc.isInvalid() ? 0 : PLoc.getLine(); + unsigned LineNo = getLineNumber(NSDecl->getLocation()); llvm::DIDescriptor Context = getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()), Unit); llvm::DINameSpace NS = DebugFactory.CreateNameSpace(Context, NSDecl->getName(), - llvm::DIFile(Unit.getNode()), LineNo); - NameSpaceCache[NSDecl] = llvm::WeakVH(NS.getNode()); + llvm::DIFile(Unit), LineNo); + NameSpaceCache[NSDecl] = llvm::WeakVH(NS); return NS; } diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index c16379a..620a5f2 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -80,6 +80,7 @@ class CGDebugInfo { llvm::DIType CreateType(const TagType *Ty, llvm::DIFile F); llvm::DIType CreateType(const RecordType *Ty, llvm::DIFile F); llvm::DIType CreateType(const ObjCInterfaceType *Ty, llvm::DIFile F); + llvm::DIType CreateType(const ObjCObjectType *Ty, llvm::DIFile F); llvm::DIType CreateType(const EnumType *Ty, llvm::DIFile F); llvm::DIType CreateType(const VectorType *Ty, llvm::DIFile F); llvm::DIType CreateType(const ArrayType *Ty, llvm::DIFile F); @@ -208,6 +209,13 @@ private: /// getVTableName - Get vtable name for the given Class. llvm::StringRef getVTableName(const CXXRecordDecl *Decl); + /// getLineNumber - Get line number for the location. If location is invalid + /// then use current location. + unsigned getLineNumber(SourceLocation Loc); + + /// getColumnNumber - Get column number for the location. If location is + /// invalid then use current location. + unsigned getColumnNumber(SourceLocation Loc); }; } // namespace CodeGen } // namespace clang diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 48198ff..07edca0 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -114,14 +114,14 @@ void CodeGenFunction::EmitBlockVarDecl(const VarDecl &D) { llvm::GlobalValue::LinkageTypes Linkage = llvm::GlobalValue::InternalLinkage; - // If this is a static declaration inside an inline function, it must have - // weak linkage so that the linker will merge multiple definitions of it. - if (getContext().getLangOptions().CPlusPlus) { - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurFuncDecl)) { - if (FD->isInlined()) - Linkage = llvm::GlobalValue::WeakAnyLinkage; - } - } + // If the function definition has some sort of weak linkage, its + // static variables should also be weak so that they get properly + // uniqued. We can't do this in C, though, because there's no + // standard way to agree on which variables are the same (i.e. + // there's no mangling). + if (getContext().getLangOptions().CPlusPlus) + if (llvm::GlobalValue::isWeakForLinker(CurFn->getLinkage())) + Linkage = CurFn->getLinkage(); return EmitStaticBlockVarDecl(D, Linkage); } @@ -239,8 +239,6 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D, // Store into LocalDeclMap before generating initializer to handle // circular references. DMEntry = GV; - if (getContext().getLangOptions().CPlusPlus) - CGM.setStaticLocalDeclAddress(&D, GV); // We can't have a VLA here, but we can have a pointer to a VLA, // even though that doesn't really make any sense. @@ -269,6 +267,9 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D, if (D.hasAttr<UsedAttr>()) CGM.AddUsedGlobal(GV); + if (getContext().getLangOptions().CPlusPlus) + CGM.setStaticLocalDeclAddress(&D, GV); + // We may have to cast the constant because of the initializer // mismatch above. // @@ -398,16 +399,20 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { CharUnits Align = CharUnits::Zero(); bool IsSimpleConstantInitializer = false; + bool NRVO = false; + llvm::Value *NRVOFlag = 0; llvm::Value *DeclPtr; if (Ty->isConstantSizeType()) { if (!Target.useGlobalsForAutomaticVariables()) { - + NRVO = getContext().getLangOptions().ElideConstructors && + D.isNRVOVariable(); // If this value is an array or struct, is POD, and if the initializer is - // a staticly determinable constant, try to optimize it. + // a staticly determinable constant, try to optimize it (unless the NRVO + // is already optimizing this). if (D.getInit() && !isByRef && (Ty->isArrayType() || Ty->isRecordType()) && Ty->isPODType() && - D.getInit()->isConstantInitializer(getContext())) { + D.getInit()->isConstantInitializer(getContext()) && !NRVO) { // If this variable is marked 'const', emit the value as a global. if (CGM.getCodeGenOpts().MergeAllConstants && Ty.isConstant(getContext())) { @@ -418,19 +423,44 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { IsSimpleConstantInitializer = true; } - // A normal fixed sized variable becomes an alloca in the entry block. + // A normal fixed sized variable becomes an alloca in the entry block, + // unless it's an NRVO variable. const llvm::Type *LTy = ConvertTypeForMem(Ty); - if (isByRef) - LTy = BuildByRefType(&D); - llvm::AllocaInst *Alloc = CreateTempAlloca(LTy); - Alloc->setName(D.getNameAsString()); - - Align = getContext().getDeclAlign(&D); - if (isByRef) - Align = std::max(Align, - CharUnits::fromQuantity(Target.getPointerAlign(0) / 8)); - Alloc->setAlignment(Align.getQuantity()); - DeclPtr = Alloc; + + if (NRVO) { + // The named return value optimization: allocate this variable in the + // return slot, so that we can elide the copy when returning this + // variable (C++0x [class.copy]p34). + DeclPtr = ReturnValue; + + if (const RecordType *RecordTy = Ty->getAs<RecordType>()) { + if (!cast<CXXRecordDecl>(RecordTy->getDecl())->hasTrivialDestructor()) { + // Create a flag that is used to indicate when the NRVO was applied + // to this variable. Set it to zero to indicate that NRVO was not + // applied. + const llvm::Type *BoolTy = llvm::Type::getInt1Ty(VMContext); + llvm::Value *Zero = llvm::ConstantInt::get(BoolTy, 0); + NRVOFlag = CreateTempAlloca(BoolTy, "nrvo"); + Builder.CreateStore(Zero, NRVOFlag); + + // Record the NRVO flag for this variable. + NRVOFlags[&D] = NRVOFlag; + } + } + } else { + if (isByRef) + LTy = BuildByRefType(&D); + + llvm::AllocaInst *Alloc = CreateTempAlloca(LTy); + Alloc->setName(D.getNameAsString()); + + Align = getContext().getDeclAlign(&D); + if (isByRef) + Align = std::max(Align, + CharUnits::fromQuantity(Target.getPointerAlign(0) / 8)); + Alloc->setAlignment(Align.getQuantity()); + DeclPtr = Alloc; + } } else { // Targets that don't support recursion emit locals as globals. const char *Class = @@ -645,13 +675,15 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { while (const ArrayType *Array = getContext().getAsArrayType(DtorTy)) DtorTy = getContext().getBaseElementType(Array); if (const RecordType *RT = DtorTy->getAs<RecordType>()) - if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) { - llvm::Value *Loc = DeclPtr; - if (isByRef) - Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D), - D.getNameAsString()); - + if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) { if (!ClassDecl->hasTrivialDestructor()) { + // Note: We suppress the destructor call when the corresponding NRVO + // flag has been set. + llvm::Value *Loc = DeclPtr; + if (isByRef) + Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D), + D.getNameAsString()); + const CXXDestructorDecl *D = ClassDecl->getDestructor(getContext()); assert(D && "EmitLocalBlockVarDecl - destructor is nul"); @@ -680,13 +712,27 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { } } else { { + // Normal destruction. DelayedCleanupBlock Scope(*this); + + if (NRVO) { + // If we exited via NRVO, we skip the destructor call. + llvm::BasicBlock *NoNRVO = createBasicBlock("nrvo.unused"); + Builder.CreateCondBr(Builder.CreateLoad(NRVOFlag, "nrvo.val"), + Scope.getCleanupExitBlock(), + NoNRVO); + EmitBlock(NoNRVO); + } + + // We don't call the destructor along the normal edge if we're + // applying the NRVO. EmitCXXDestructorCall(D, Dtor_Complete, /*ForVirtualBase=*/false, Loc); // Make sure to jump to the exit block. EmitBranch(Scope.getCleanupExitBlock()); } + if (Exceptions) { EHCleanupBlock Cleanup(*this); EmitCXXDestructorCall(D, Dtor_Complete, /*ForVirtualBase=*/false, diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index 6afa538..f94ddd9 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -13,6 +13,8 @@ #include "CodeGenFunction.h" #include "clang/CodeGen/CodeGenOptions.h" +#include "llvm/Intrinsics.h" + using namespace clang; using namespace CodeGen; @@ -22,7 +24,6 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D, assert(!D.getType()->isReferenceType() && "Should not call EmitDeclInit on a reference!"); - CodeGenModule &CGM = CGF.CGM; ASTContext &Context = CGF.getContext(); const Expr *Init = D.getInit(); @@ -36,41 +37,52 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D, CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile); } else { CGF.EmitAggExpr(Init, DeclPtr, isVolatile); - - // Avoid generating destructor(s) for initialized objects. - if (!isa<CXXConstructExpr>(Init)) - return; - - const ConstantArrayType *Array = Context.getAsConstantArrayType(T); - if (Array) - T = Context.getBaseElementType(Array); - - const RecordType *RT = T->getAs<RecordType>(); - if (!RT) - return; - - CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - if (RD->hasTrivialDestructor()) - return; - - CXXDestructorDecl *Dtor = RD->getDestructor(Context); - - llvm::Constant *DtorFn; - if (Array) { - DtorFn = - CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(Dtor, - Array, - DeclPtr); - const llvm::Type *Int8PtrTy = - llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); - DeclPtr = llvm::Constant::getNullValue(Int8PtrTy); - } else - DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete); - - CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr); } } +static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D, + llvm::Constant *DeclPtr) { + CodeGenModule &CGM = CGF.CGM; + ASTContext &Context = CGF.getContext(); + + const Expr *Init = D.getInit(); + QualType T = D.getType(); + if (!CGF.hasAggregateLLVMType(T) || T->isAnyComplexType()) + return; + + // Avoid generating destructor(s) for initialized objects. + if (!isa<CXXConstructExpr>(Init)) + return; + + const ConstantArrayType *Array = Context.getAsConstantArrayType(T); + if (Array) + T = Context.getBaseElementType(Array); + + const RecordType *RT = T->getAs<RecordType>(); + if (!RT) + return; + + CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + if (RD->hasTrivialDestructor()) + return; + + CXXDestructorDecl *Dtor = RD->getDestructor(Context); + + llvm::Constant *DtorFn; + if (Array) { + DtorFn = + CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(Dtor, + Array, + DeclPtr); + const llvm::Type *Int8PtrTy = + llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); + DeclPtr = llvm::Constant::getNullValue(Int8PtrTy); + } else + DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete); + + CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr); +} + void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::Constant *DeclPtr) { @@ -79,6 +91,7 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, if (!T->isReferenceType()) { EmitDeclInit(*this, D, DeclPtr); + EmitDeclDestroy(*this, D, DeclPtr); return; } if (Init->isLvalue(getContext()) == Expr::LV_Valid) { @@ -310,7 +323,10 @@ CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D, EmitBlock(InitCheckBlock); - if (ThreadsafeStatics) { + // Variables used when coping with thread-safe statics and exceptions. + llvm::BasicBlock *SavedLandingPad = 0; + llvm::BasicBlock *LandingPad = 0; + if (ThreadsafeStatics) { // Call __cxa_guard_acquire. V = Builder.CreateCall(getGuardAcquireFn(*this), GuardVariable); @@ -319,14 +335,13 @@ CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D, Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"), InitBlock, EndBlock); - EmitBlock(InitBlock); - if (Exceptions) { - EHCleanupBlock Cleanup(*this); - - // Call __cxa_guard_abort. - Builder.CreateCall(getGuardAbortFn(*this), GuardVariable); + SavedLandingPad = getInvokeDest(); + LandingPad = createBasicBlock("guard.lpad"); + setInvokeDest(LandingPad); } + + EmitBlock(InitBlock); } if (D.getType()->isReferenceType()) { @@ -342,12 +357,68 @@ CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D, if (ThreadsafeStatics) { // Call __cxa_guard_release. - Builder.CreateCall(getGuardReleaseFn(*this), GuardVariable); + Builder.CreateCall(getGuardReleaseFn(*this), GuardVariable); } else { llvm::Value *One = llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1); Builder.CreateStore(One, Builder.CreateBitCast(GuardVariable, PtrTy)); } + // Register the call to the destructor. + if (!D.getType()->isReferenceType()) + EmitDeclDestroy(*this, D, GV); + + if (ThreadsafeStatics && Exceptions) { + // If an exception is thrown during initialization, call __cxa_guard_abort + // along the exceptional edge. + EmitBranch(EndBlock); + + // Construct the landing pad. + EmitBlock(LandingPad); + + // Personality function and LLVM intrinsics. + llvm::Constant *Personality = + CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty + (VMContext), + true), + "__gxx_personality_v0"); + Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty); + llvm::Value *llvm_eh_exception = + CGM.getIntrinsic(llvm::Intrinsic::eh_exception); + llvm::Value *llvm_eh_selector = + CGM.getIntrinsic(llvm::Intrinsic::eh_selector); + + // Exception object + llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc"); + llvm::Value *RethrowPtr = CreateTempAlloca(Exc->getType(), "_rethrow"); + + // Call the selector function. + const llvm::PointerType *PtrToInt8Ty + = llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(VMContext)); + llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty); + llvm::Value* SelectorArgs[3] = { Exc, Personality, Null }; + Builder.CreateCall(llvm_eh_selector, SelectorArgs, SelectorArgs + 3, + "selector"); + Builder.CreateStore(Exc, RethrowPtr); + + // Call __cxa_guard_abort along the exceptional edge. + Builder.CreateCall(getGuardAbortFn(*this), GuardVariable); + + setInvokeDest(SavedLandingPad); + + // Rethrow the current exception. + if (getInvokeDest()) { + llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); + Builder.CreateInvoke(getUnwindResumeOrRethrowFn(), Cont, + getInvokeDest(), + Builder.CreateLoad(RethrowPtr)); + EmitBlock(Cont); + } else + Builder.CreateCall(getUnwindResumeOrRethrowFn(), + Builder.CreateLoad(RethrowPtr)); + + Builder.CreateUnreachable(); + } + EmitBlock(EndBlock); } diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index c1d05bf..ddc1c77 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -100,17 +100,17 @@ static llvm::Constant *getUnexpectedFn(CodeGenFunction &CGF) { return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected"); } -static llvm::Constant *getUnwindResumeOrRethrowFn(CodeGenFunction &CGF) { - const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); +llvm::Constant *CodeGenFunction::getUnwindResumeOrRethrowFn() { + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext()); std::vector<const llvm::Type*> Args(1, Int8PtrTy); const llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), Args, + llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()), Args, false); - if (CGF.CGM.getLangOptions().SjLjExceptions) - return CGF.CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume"); - return CGF.CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume_or_Rethrow"); + if (CGM.getLangOptions().SjLjExceptions) + return CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume"); + return CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume_or_Rethrow"); } static llvm::Constant *getTerminateFn(CodeGenFunction &CGF) { @@ -119,7 +119,29 @@ static llvm::Constant *getTerminateFn(CodeGenFunction &CGF) { const llvm::FunctionType *FTy = llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false); - return CGF.CGM.CreateRuntimeFunction(FTy, "_ZSt9terminatev"); + return CGF.CGM.CreateRuntimeFunction(FTy, + CGF.CGM.getLangOptions().CPlusPlus ? "_ZSt9terminatev" : "abort"); +} + +static llvm::Constant *getPersonalityFn(CodeGenModule &CGM) { + const char *PersonalityFnName = "__gcc_personality_v0"; + LangOptions Opts = CGM.getLangOptions(); + if (Opts.CPlusPlus) + PersonalityFnName = "__gxx_personality_v0"; + else if (Opts.ObjC1) { + if (Opts.NeXTRuntime) { + if (Opts.ObjCNonFragileABI) + PersonalityFnName = "__gcc_personality_v0"; + } else + PersonalityFnName = "__gnu_objc_personality_v0"; + } + + llvm::Constant *Personality = + CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty( + CGM.getLLVMContext()), + true), + PersonalityFnName); + return llvm::ConstantExpr::getBitCast(Personality, CGM.PtrToInt8Ty); } // Emits an exception expression into the given location. This @@ -324,12 +346,7 @@ void CodeGenFunction::EmitStartEHSpec(const Decl *D) { if (!Proto->hasExceptionSpec()) return; - llvm::Constant *Personality = - CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty - (VMContext), - true), - "__gxx_personality_v0"); - Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty); + llvm::Constant *Personality = getPersonalityFn(CGM); llvm::Value *llvm_eh_exception = CGM.getIntrinsic(llvm::Intrinsic::eh_exception); llvm::Value *llvm_eh_selector = @@ -397,7 +414,7 @@ void CodeGenFunction::EmitStartEHSpec(const Decl *D) { if (Proto->getNumExceptions()) { EmitBlock(Unwind); - Builder.CreateCall(getUnwindResumeOrRethrowFn(*this), + Builder.CreateCall(getUnwindResumeOrRethrowFn(), Builder.CreateLoad(RethrowPtr)); Builder.CreateUnreachable(); } @@ -444,12 +461,7 @@ CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S) { void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, CXXTryStmtInfo TryInfo) { // Pointer to the personality function - llvm::Constant *Personality = - CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty - (VMContext), - true), - "__gxx_personality_v0"); - Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty); + llvm::Constant *Personality = getPersonalityFn(CGM); llvm::Value *llvm_eh_exception = CGM.getIntrinsic(llvm::Intrinsic::eh_exception); llvm::Value *llvm_eh_selector = @@ -631,12 +643,12 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, // here. if (getInvokeDest()) { llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); - Builder.CreateInvoke(getUnwindResumeOrRethrowFn(*this), Cont, + Builder.CreateInvoke(getUnwindResumeOrRethrowFn(), Cont, getInvokeDest(), Builder.CreateLoad(RethrowPtr)); EmitBlock(Cont); } else - Builder.CreateCall(getUnwindResumeOrRethrowFn(*this), + Builder.CreateCall(getUnwindResumeOrRethrowFn(), Builder.CreateLoad(RethrowPtr)); Builder.CreateUnreachable(); @@ -654,12 +666,7 @@ CodeGenFunction::EHCleanupBlock::~EHCleanupBlock() { // The libstdc++ personality function. // TODO: generalize to work with other libraries. - llvm::Constant *Personality = - CGF.CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty - (CGF.VMContext), - true), - "__gxx_personality_v0"); - Personality = llvm::ConstantExpr::getBitCast(Personality, CGF.PtrToInt8Ty); + llvm::Constant *Personality = getPersonalityFn(CGF.CGM); // %exception = call i8* @llvm.eh.exception() // Magic intrinsic which tells gives us a handle to the caught @@ -687,11 +694,11 @@ CodeGenFunction::EHCleanupBlock::~EHCleanupBlock() { // Rethrow the exception. if (CGF.getInvokeDest()) { llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont"); - CGF.Builder.CreateInvoke(getUnwindResumeOrRethrowFn(CGF), Cont, + CGF.Builder.CreateInvoke(CGF.getUnwindResumeOrRethrowFn(), Cont, CGF.getInvokeDest(), Exc); CGF.EmitBlock(Cont); } else - CGF.Builder.CreateCall(getUnwindResumeOrRethrowFn(CGF), Exc); + CGF.Builder.CreateCall(CGF.getUnwindResumeOrRethrowFn(), Exc); CGF.Builder.CreateUnreachable(); // Resume inserting where we started, but put the new cleanup @@ -715,12 +722,7 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() { llvm::BasicBlock::iterator SavedInsertPoint = Builder.GetInsertPoint(); Builder.ClearInsertionPoint(); - llvm::Constant *Personality = - CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty - (VMContext), - true), - "__gxx_personality_v0"); - Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty); + llvm::Constant *Personality = getPersonalityFn(CGM); llvm::Value *llvm_eh_exception = CGM.getIntrinsic(llvm::Intrinsic::eh_exception); llvm::Value *llvm_eh_selector = diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 9ade916..d67618b 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -135,6 +135,39 @@ void CodeGenFunction::EmitAnyExprToMem(const Expr *E, } } +/// \brief An adjustment to be made to the temporary created when emitting a +/// reference binding, which accesses a particular subobject of that temporary. +struct SubobjectAdjustment { + enum { DerivedToBaseAdjustment, FieldAdjustment } Kind; + + union { + struct { + const CXXBaseSpecifierArray *BasePath; + const CXXRecordDecl *DerivedClass; + } DerivedToBase; + + struct { + FieldDecl *Field; + unsigned CVRQualifiers; + } Field; + }; + + SubobjectAdjustment(const CXXBaseSpecifierArray *BasePath, + const CXXRecordDecl *DerivedClass) + : Kind(DerivedToBaseAdjustment) + { + DerivedToBase.BasePath = BasePath; + DerivedToBase.DerivedClass = DerivedClass; + } + + SubobjectAdjustment(FieldDecl *Field, unsigned CVRQualifiers) + : Kind(FieldAdjustment) + { + this->Field.Field = Field; + this->Field.CVRQualifiers = CVRQualifiers; + } +}; + RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, bool IsInitializer) { bool ShouldDestroyTemporaries = false; @@ -174,19 +207,46 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, PopCXXTemporary(); } } else { - const CXXBaseSpecifierArray *BasePath = 0; - const CXXRecordDecl *DerivedClassDecl = 0; + QualType ResultTy = E->getType(); - if (const CastExpr *CE = - dyn_cast<CastExpr>(E->IgnoreParenNoopCasts(getContext()))) { - if (CE->getCastKind() == CastExpr::CK_DerivedToBase) { - E = CE->getSubExpr(); - - BasePath = &CE->getBasePath(); - DerivedClassDecl = - cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl()); + llvm::SmallVector<SubobjectAdjustment, 2> Adjustments; + do { + if (const ParenExpr *PE = dyn_cast<ParenExpr>(E)) { + E = PE->getSubExpr(); + continue; + } + + if (const CastExpr *CE = dyn_cast<CastExpr>(E)) { + if ((CE->getCastKind() == CastExpr::CK_DerivedToBase || + CE->getCastKind() == CastExpr::CK_UncheckedDerivedToBase) && + E->getType()->isRecordType()) { + E = CE->getSubExpr(); + CXXRecordDecl *Derived + = cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl()); + Adjustments.push_back(SubobjectAdjustment(&CE->getBasePath(), + Derived)); + continue; + } + + if (CE->getCastKind() == CastExpr::CK_NoOp) { + E = CE->getSubExpr(); + continue; + } + } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) { + if (ME->getBase()->isLvalue(getContext()) != Expr::LV_Valid && + ME->getBase()->getType()->isRecordType()) { + if (FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl())) { + E = ME->getBase(); + Adjustments.push_back(SubobjectAdjustment(Field, + E->getType().getCVRQualifiers())); + continue; + } + } } - } + + // Nothing changed. + break; + } while (true); Val = EmitAnyExprToTemp(E, /*IsAggLocVolatile=*/false, IsInitializer); @@ -225,13 +285,47 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, } } - // Check if need to perform the derived-to-base cast. - if (BasePath) { - llvm::Value *Derived = Val.getAggregateAddr(); - llvm::Value *Base = - GetAddressOfBaseClass(Derived, DerivedClassDecl, *BasePath, - /*NullCheckValue=*/false); - return RValue::get(Base); + // Check if need to perform derived-to-base casts and/or field accesses, to + // get from the temporary object we created (and, potentially, for which we + // extended the lifetime) to the subobject we're binding the reference to. + if (!Adjustments.empty()) { + llvm::Value *Object = Val.getAggregateAddr(); + for (unsigned I = Adjustments.size(); I != 0; --I) { + SubobjectAdjustment &Adjustment = Adjustments[I-1]; + switch (Adjustment.Kind) { + case SubobjectAdjustment::DerivedToBaseAdjustment: + Object = GetAddressOfBaseClass(Object, + Adjustment.DerivedToBase.DerivedClass, + *Adjustment.DerivedToBase.BasePath, + /*NullCheckValue=*/false); + break; + + case SubobjectAdjustment::FieldAdjustment: { + unsigned CVR = Adjustment.Field.CVRQualifiers; + LValue LV = EmitLValueForField(Object, Adjustment.Field.Field, CVR); + if (LV.isSimple()) { + Object = LV.getAddress(); + break; + } + + // For non-simple lvalues, we actually have to create a copy of + // the object we're binding to. + QualType T = Adjustment.Field.Field->getType().getNonReferenceType() + .getUnqualifiedType(); + Object = CreateTempAlloca(ConvertType(T), "lv"); + EmitStoreThroughLValue(EmitLoadOfLValue(LV, T), + LValue::MakeAddr(Object, + Qualifiers::fromCVRMask(CVR)), + T); + break; + } + } + } + + const llvm::Type *ResultPtrTy + = llvm::PointerType::get(ConvertType(ResultTy), 0); + Object = Builder.CreateBitCast(Object, ResultPtrTy, "temp"); + return RValue::get(Object); } } @@ -309,8 +403,7 @@ EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), AmountVal); if (!isa<llvm::FunctionType>(PT->getElementType())) { QualType PTEE = ValTy->getPointeeType(); - if (const ObjCInterfaceType *OIT = - dyn_cast<ObjCInterfaceType>(PTEE)) { + if (const ObjCObjectType *OIT = PTEE->getAs<ObjCObjectType>()) { // Handle interface types, which are not represented with a concrete // type. int size = getContext().getTypeSize(OIT) / 8; @@ -1371,8 +1464,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { llvm::ConstantInt::get(Idx->getType(), BaseTypeSize.getQuantity())); Address = Builder.CreateInBoundsGEP(Base, Idx, "arrayidx"); - } else if (const ObjCInterfaceType *OIT = - dyn_cast<ObjCInterfaceType>(E->getType())) { + } else if (const ObjCObjectType *OIT = + E->getType()->getAs<ObjCObjectType>()) { llvm::Value *InterfaceSize = llvm::ConstantInt::get(Idx->getType(), getContext().getTypeSizeInChars(OIT).getQuantity()); @@ -1530,6 +1623,35 @@ LValue CodeGenFunction::EmitLValueForBitfield(llvm::Value* BaseValue, Field->getType().getCVRQualifiers()|CVRQualifiers); } +/// EmitLValueForAnonRecordField - Given that the field is a member of +/// an anonymous struct or union buried inside a record, and given +/// that the base value is a pointer to the enclosing record, derive +/// an lvalue for the ultimate field. +LValue CodeGenFunction::EmitLValueForAnonRecordField(llvm::Value *BaseValue, + const FieldDecl *Field, + unsigned CVRQualifiers) { + llvm::SmallVector<const FieldDecl *, 8> Path; + Path.push_back(Field); + + while (Field->getParent()->isAnonymousStructOrUnion()) { + const ValueDecl *VD = Field->getParent()->getAnonymousStructOrUnionObject(); + if (!isa<FieldDecl>(VD)) break; + Field = cast<FieldDecl>(VD); + Path.push_back(Field); + } + + llvm::SmallVectorImpl<const FieldDecl*>::reverse_iterator + I = Path.rbegin(), E = Path.rend(); + while (true) { + LValue LV = EmitLValueForField(BaseValue, *I, CVRQualifiers); + if (++I == E) return LV; + + assert(LV.isSimple()); + BaseValue = LV.getAddress(); + CVRQualifiers |= LV.getVRQualifiers(); + } +} + LValue CodeGenFunction::EmitLValueForField(llvm::Value* BaseValue, const FieldDecl* Field, unsigned CVRQualifiers) { @@ -1670,7 +1792,17 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { MakeQualifiers(E->getType())); } - case CastExpr::CK_NoOp: + case CastExpr::CK_NoOp: { + LValue LV = EmitLValue(E->getSubExpr()); + if (LV.isPropertyRef()) { + QualType QT = E->getSubExpr()->getType(); + RValue RV = EmitLoadOfPropertyRefLValue(LV, QT); + assert(!RV.isScalar() && "EmitCastLValue - scalar cast of property ref"); + llvm::Value *V = RV.getAggregateAddr(); + return LValue::MakeAddr(V, MakeQualifiers(QT)); + } + return LV; + } case CastExpr::CK_ConstructorConversion: case CastExpr::CK_UserDefinedConversion: case CastExpr::CK_AnyPointerToObjCPointerCast: @@ -1724,7 +1856,7 @@ LValue CodeGenFunction::EmitNullInitializationLValue( const CXXZeroInitValueExpr *E) { QualType Ty = E->getType(); LValue LV = LValue::MakeAddr(CreateMemTemp(Ty), MakeQualifiers(Ty)); - EmitMemSetToZero(LV.getAddress(), Ty); + EmitNullInitialization(LV.getAddress(), Ty); return LV; } diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index d1b0dff..a4e64fb 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -37,6 +37,16 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> { bool IgnoreResult; bool IsInitializer; bool RequiresGCollection; + + ReturnValueSlot getReturnValueSlot() const { + // If the destination slot requires garbage collection, we can't + // use the real return value slot, because we have to use the GC + // API. + if (RequiresGCollection) return ReturnValueSlot(); + + return ReturnValueSlot(DestPtr, VolatileDest); + } + public: AggExprEmitter(CodeGenFunction &cgf, llvm::Value *destPtr, bool v, bool ignore, bool isinit, bool requiresGCollection) @@ -58,6 +68,10 @@ public: void EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore = false); void EmitFinalDestCopy(const Expr *E, RValue Src, bool Ignore = false); + void EmitGCMove(const Expr *E, RValue Src); + + bool TypeRequiresGCollection(QualType T); + //===--------------------------------------------------------------------===// // Visitor Methods //===--------------------------------------------------------------------===// @@ -137,6 +151,39 @@ void AggExprEmitter::EmitAggLoadOfLValue(const Expr *E) { EmitFinalDestCopy(E, LV); } +/// \brief True if the given aggregate type requires special GC API calls. +bool AggExprEmitter::TypeRequiresGCollection(QualType T) { + // Only record types have members that might require garbage collection. + const RecordType *RecordTy = T->getAs<RecordType>(); + if (!RecordTy) return false; + + // Don't mess with non-trivial C++ types. + RecordDecl *Record = RecordTy->getDecl(); + if (isa<CXXRecordDecl>(Record) && + (!cast<CXXRecordDecl>(Record)->hasTrivialCopyConstructor() || + !cast<CXXRecordDecl>(Record)->hasTrivialDestructor())) + return false; + + // Check whether the type has an object member. + return Record->hasObjectMember(); +} + +/// \brief Perform the final move to DestPtr if RequiresGCollection is set. +/// +/// The idea is that you do something like this: +/// RValue Result = EmitSomething(..., getReturnValueSlot()); +/// EmitGCMove(E, Result); +/// If GC doesn't interfere, this will cause the result to be emitted +/// directly into the return value slot. If GC does interfere, a final +/// move will be performed. +void AggExprEmitter::EmitGCMove(const Expr *E, RValue Src) { + if (!RequiresGCollection) return; + + CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF, DestPtr, + Src.getAggregateAddr(), + E->getType()); +} + /// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired. void AggExprEmitter::EmitFinalDestCopy(const Expr *E, RValue Src, bool Ignore) { assert(Src.isAggregate() && "value must be aggregate value!"); @@ -178,7 +225,7 @@ void AggExprEmitter::EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore) { //===----------------------------------------------------------------------===// void AggExprEmitter::VisitCastExpr(CastExpr *E) { - if (!DestPtr) { + if (!DestPtr && E->getCastKind() != CastExpr::CK_Dynamic) { Visit(E->getSubExpr()); return; } @@ -186,6 +233,20 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { switch (E->getCastKind()) { default: assert(0 && "Unhandled cast kind!"); + case CastExpr::CK_Dynamic: { + assert(isa<CXXDynamicCastExpr>(E) && "CK_Dynamic without a dynamic_cast?"); + LValue LV = CGF.EmitCheckedLValue(E->getSubExpr()); + // FIXME: Do we also need to handle property references here? + if (LV.isSimple()) + CGF.EmitDynamicCast(LV.getAddress(), cast<CXXDynamicCastExpr>(E)); + else + CGF.CGM.ErrorUnsupported(E, "non-simple lvalue dynamic_cast"); + + if (DestPtr) + CGF.CGM.ErrorUnsupported(E, "lvalue dynamic_cast with a destination"); + break; + } + case CastExpr::CK_ToUnion: { // GCC union extension QualType PtrTy = @@ -198,6 +259,14 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { break; } + case CastExpr::CK_DerivedToBase: + case CastExpr::CK_BaseToDerived: + case CastExpr::CK_UncheckedDerivedToBase: { + assert(0 && "cannot perform hierarchy conversion in EmitAggExpr: " + "should have been unpacked before we got here"); + break; + } + // FIXME: Remove the CK_Unknown check here. case CastExpr::CK_Unknown: case CastExpr::CK_NoOp: @@ -282,31 +351,24 @@ void AggExprEmitter::VisitCallExpr(const CallExpr *E) { return; } - // If the struct doesn't require GC, we can just pass the destination - // directly to EmitCall. - if (!RequiresGCollection) { - CGF.EmitCallExpr(E, ReturnValueSlot(DestPtr, VolatileDest)); - return; - } - - RValue RV = CGF.EmitCallExpr(E); - EmitFinalDestCopy(E, RV); + RValue RV = CGF.EmitCallExpr(E, getReturnValueSlot()); + EmitGCMove(E, RV); } void AggExprEmitter::VisitObjCMessageExpr(ObjCMessageExpr *E) { - RValue RV = CGF.EmitObjCMessageExpr(E); - EmitFinalDestCopy(E, RV); + RValue RV = CGF.EmitObjCMessageExpr(E, getReturnValueSlot()); + EmitGCMove(E, RV); } void AggExprEmitter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { - RValue RV = CGF.EmitObjCPropertyGet(E); - EmitFinalDestCopy(E, RV); + RValue RV = CGF.EmitObjCPropertyGet(E, getReturnValueSlot()); + EmitGCMove(E, RV); } void AggExprEmitter::VisitObjCImplicitSetterGetterRefExpr( ObjCImplicitSetterGetterRefExpr *E) { - RValue RV = CGF.EmitObjCPropertyGet(E); - EmitFinalDestCopy(E, RV); + RValue RV = CGF.EmitObjCPropertyGet(E, getReturnValueSlot()); + EmitGCMove(E, RV); } void AggExprEmitter::VisitBinComma(const BinaryOperator *E) { @@ -412,11 +474,9 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { RValue::getAggregate(AggLoc, VolatileDest)); } else { bool RequiresGCollection = false; - if (CGF.getContext().getLangOptions().NeXTRuntime) { - QualType LHSTy = E->getLHS()->getType(); - if (const RecordType *FDTTy = LHSTy.getTypePtr()->getAs<RecordType>()) - RequiresGCollection = FDTTy->getDecl()->hasObjectMember(); - } + if (CGF.getContext().getLangOptions().getGCMode()) + RequiresGCollection = TypeRequiresGCollection(E->getLHS()->getType()); + // Codegen the RHS so that it stores directly into the LHS. CGF.EmitAggExpr(E->getRHS(), LHS.getAddress(), LHS.isVolatileQualified(), false, false, RequiresGCollection); @@ -559,14 +619,10 @@ void AggExprEmitter::EmitNullInitializationToLValue(LValue LV, QualType T) { llvm::Value *Null = llvm::Constant::getNullValue(CGF.ConvertType(T)); CGF.EmitStoreThroughLValue(RValue::get(Null), LV, T); } else { - // Otherwise, just memset the whole thing to zero. This is legal - // because in LLVM, all default initializers are guaranteed to have a - // bit pattern of all zeros. - // FIXME: That isn't true for member pointers! // There's a potential optimization opportunity in combining // memsets; that would be easy for arrays, but relatively // difficult for structures with the current code. - CGF.EmitMemSetToZero(LV.getAddress(), T); + CGF.EmitNullInitialization(LV.getAddress(), T); } } @@ -738,21 +794,20 @@ LValue CodeGenFunction::EmitAggExprToLValue(const Expr *E) { return LValue::MakeAddr(Temp, Q); } -void CodeGenFunction::EmitAggregateClear(llvm::Value *DestPtr, QualType Ty) { - assert(!Ty->isAnyComplexType() && "Shouldn't happen for complex"); - - EmitMemSetToZero(DestPtr, Ty); -} - void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr, llvm::Value *SrcPtr, QualType Ty, bool isVolatile) { assert(!Ty->isAnyComplexType() && "Shouldn't happen for complex"); - // Ignore empty classes in C++. if (getContext().getLangOptions().CPlusPlus) { if (const RecordType *RT = Ty->getAs<RecordType>()) { - if (cast<CXXRecordDecl>(RT->getDecl())->isEmpty()) + CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl()); + assert((Record->hasTrivialCopyConstructor() || + Record->hasTrivialCopyAssignment()) && + "Trying to aggregate-copy a type without a trivial copy " + "constructor or assignment operator"); + // Ignore empty classes in C++. + if (Record->isEmpty()) return; } } diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index b57cdc9..f93c79c 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "CodeGenFunction.h" +#include "CGObjCRuntime.h" using namespace clang; using namespace CodeGen; @@ -255,16 +256,29 @@ CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, ReturnValueSlot ReturnValue) { assert(MD->isInstance() && "Trying to emit a member call expr on a static method!"); - if (MD->isCopyAssignment()) { const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(MD->getDeclContext()); if (ClassDecl->hasTrivialCopyAssignment()) { assert(!ClassDecl->hasUserDeclaredCopyAssignment() && "EmitCXXOperatorMemberCallExpr - user declared copy assignment"); - llvm::Value *This = EmitLValue(E->getArg(0)).getAddress(); + LValue LV = EmitLValue(E->getArg(0)); + llvm::Value *This; + if (LV.isPropertyRef()) { + llvm::Value *AggLoc = CreateMemTemp(E->getArg(1)->getType()); + EmitAggExpr(E->getArg(1), AggLoc, false /*VolatileDest*/); + EmitObjCPropertySet(LV.getPropertyRefExpr(), + RValue::getAggregate(AggLoc, false /*VolatileDest*/)); + return RValue::getAggregate(0, false); + } + else + This = LV.getAddress(); + llvm::Value *Src = EmitLValue(E->getArg(1)).getAddress(); QualType Ty = E->getType(); - EmitAggregateCopy(This, Src, Ty); + if (ClassDecl->hasObjectMember()) + CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, This, Src, Ty); + else + EmitAggregateCopy(This, Src, Ty); return RValue::get(This); } } @@ -273,8 +287,15 @@ CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, const llvm::Type *Ty = CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), FPT->isVariadic()); - - llvm::Value *This = EmitLValue(E->getArg(0)).getAddress(); + LValue LV = EmitLValue(E->getArg(0)); + llvm::Value *This; + if (LV.isPropertyRef()) { + RValue RV = EmitLoadOfPropertyRefLValue(LV, E->getArg(0)->getType()); + assert (!RV.isScalar() && "EmitCXXOperatorMemberCallExpr"); + This = RV.getAggregateAddr(); + } + else + This = LV.getAddress(); llvm::Value *Callee; if (MD->isVirtual() && !canDevirtualizeMemberFunctionCalls(E->getArg(0))) @@ -305,11 +326,13 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest, return; } // Code gen optimization to eliminate copy constructor and return - // its first argument instead. + // its first argument instead, if in fact that argument is a temporary + // object. if (getContext().getLangOptions().ElideConstructors && E->isElidable()) { - const Expr *Arg = E->getArg(0)->getTemporaryObject(); - EmitAggExpr(Arg, Dest, false); - return; + if (const Expr *Arg = E->getArg(0)->getTemporaryObject()) { + EmitAggExpr(Arg, Dest, false); + return; + } } if (Array) { QualType BaseElementTy = getContext().getBaseElementType(Array); @@ -851,6 +874,8 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V, ToVoid = true; } else { LTy = LTy->getPointerTo(); + + // FIXME: What if exceptions are disabled? ThrowOnBad = true; } @@ -917,15 +942,21 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V, if (ThrowOnBad) { BadCastBlock = createBasicBlock(); - Builder.CreateCondBr(Builder.CreateIsNotNull(V), ContBlock, BadCastBlock); EmitBlock(BadCastBlock); - /// Call __cxa_bad_cast + /// Invoke __cxa_bad_cast ResultType = llvm::Type::getVoidTy(VMContext); const llvm::FunctionType *FBadTy; FBadTy = llvm::FunctionType::get(ResultType, false); llvm::Value *F = CGM.CreateRuntimeFunction(FBadTy, "__cxa_bad_cast"); - Builder.CreateCall(F)->setDoesNotReturn(); + if (llvm::BasicBlock *InvokeDest = getInvokeDest()) { + llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); + Builder.CreateInvoke(F, Cont, InvokeDest)->setDoesNotReturn(); + EmitBlock(Cont); + } else { + // FIXME: Does this ever make sense? + Builder.CreateCall(F)->setDoesNotReturn(); + } Builder.CreateUnreachable(); } } diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 2595ff0..551a47a 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -984,32 +984,81 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, return C; } -static bool containsPointerToDataMember(CodeGenTypes &Types, QualType T) { - // No need to check for member pointers when not compiling C++. - if (!Types.getContext().getLangOptions().CPlusPlus) - return false; - - T = Types.getContext().getBaseElementType(T); - - if (const RecordType *RT = T->getAs<RecordType>()) { - const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - - // FIXME: It would be better if there was a way to explicitly compute the - // record layout instead of converting to a type. - Types.ConvertTagDeclType(RD); +static void +FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T, + std::vector<llvm::Constant *> &Elements, + uint64_t StartOffset) { + assert(StartOffset % 8 == 0 && "StartOffset not byte aligned!"); + + if (!CGM.getTypes().ContainsPointerToDataMember(T)) + return; + + if (const ConstantArrayType *CAT = + CGM.getContext().getAsConstantArrayType(T)) { + QualType ElementTy = CAT->getElementType(); + uint64_t ElementSize = CGM.getContext().getTypeSize(ElementTy); - const CGRecordLayout &Layout = Types.getCGRecordLayout(RD); - return Layout.containsPointerToDataMember(); - } + for (uint64_t I = 0, E = CAT->getSize().getZExtValue(); I != E; ++I) { + FillInNullDataMemberPointers(CGM, ElementTy, Elements, + StartOffset + I * ElementSize); + } + } else if (const RecordType *RT = T->getAs<RecordType>()) { + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); + + // Go through all bases and fill in any null pointer to data members. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + assert(!I->isVirtual() && "Should not see virtual bases here!"); + + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + // Ignore empty bases. + if (BaseDecl->isEmpty()) + continue; + + // Ignore bases that don't have any pointer to data members. + if (!CGM.getTypes().ContainsPointerToDataMember(BaseDecl)) + continue; + + uint64_t BaseOffset = Layout.getBaseClassOffset(BaseDecl); + FillInNullDataMemberPointers(CGM, I->getType(), + Elements, StartOffset + BaseOffset); + } - if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) - return !MPT->getPointeeType()->isFunctionType(); + // Visit all fields. + unsigned FieldNo = 0; + for (RecordDecl::field_iterator I = RD->field_begin(), + E = RD->field_end(); I != E; ++I, ++FieldNo) { + QualType FieldType = I->getType(); + + if (!CGM.getTypes().ContainsPointerToDataMember(FieldType)) + continue; + + uint64_t FieldOffset = StartOffset + Layout.getFieldOffset(FieldNo); + FillInNullDataMemberPointers(CGM, FieldType, Elements, FieldOffset); + } + } else { + assert(T->isMemberPointerType() && "Should only see member pointers here!"); + assert(!T->getAs<MemberPointerType>()->getPointeeType()->isFunctionType() && + "Should only see pointers to data members here!"); - return false; + uint64_t StartIndex = StartOffset / 8; + uint64_t EndIndex = StartIndex + CGM.getContext().getTypeSize(T) / 8; + + llvm::Constant *NegativeOne = + llvm::ConstantInt::get(llvm::Type::getInt8Ty(CGM.getLLVMContext()), + -1ULL, /*isSigned=*/true); + + // Fill in the null data member pointer. + for (uint64_t I = StartIndex; I != EndIndex; ++I) + Elements[I] = NegativeOne; + } } llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { - if (!containsPointerToDataMember(getTypes(), T)) + if (!getTypes().ContainsPointerToDataMember(T)) return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T)); if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(T)) { @@ -1029,21 +1078,60 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { if (const RecordType *RT = T->getAs<RecordType>()) { const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - assert(!RD->getNumBases() && - "FIXME: Handle zero-initializing structs with bases and " - "pointers to data members."); const llvm::StructType *STy = cast<llvm::StructType>(getTypes().ConvertTypeForMem(T)); unsigned NumElements = STy->getNumElements(); std::vector<llvm::Constant *> Elements(NumElements); + const CGRecordLayout &Layout = getTypes().getCGRecordLayout(RD); + + // Go through all bases and fill in any null pointer to data members. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + assert(!I->isVirtual() && "Should not see virtual bases here!"); + + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + // Ignore empty bases. + if (BaseDecl->isEmpty()) + continue; + + // Ignore bases that don't have any pointer to data members. + if (!getTypes().ContainsPointerToDataMember(BaseDecl)) + continue; + + // Currently, all bases are arrays of i8. Figure out how many elements + // this base array has. + unsigned BaseFieldNo = Layout.getNonVirtualBaseLLVMFieldNo(BaseDecl); + const llvm::ArrayType *BaseArrayTy = + cast<llvm::ArrayType>(STy->getElementType(BaseFieldNo)); + + unsigned NumBaseElements = BaseArrayTy->getNumElements(); + std::vector<llvm::Constant *> BaseElements(NumBaseElements); + + // Now fill in null data member pointers. + FillInNullDataMemberPointers(*this, I->getType(), BaseElements, 0); + + // Now go through all other elements and zero them out. + if (NumBaseElements) { + llvm::Constant *Zero = + llvm::ConstantInt::get(llvm::Type::getInt8Ty(getLLVMContext()), 0); + + for (unsigned I = 0; I != NumBaseElements; ++I) { + if (!BaseElements[I]) + BaseElements[I] = Zero; + } + } + + Elements[BaseFieldNo] = llvm::ConstantArray::get(BaseArrayTy, + BaseElements); + } + for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); I != E; ++I) { const FieldDecl *FD = *I; - - const CGRecordLayout &RL = - getTypes().getCGRecordLayout(FD->getParent()); - unsigned FieldNo = RL.getLLVMFieldNo(FD); + unsigned FieldNo = Layout.getLLVMFieldNo(FD); Elements[FieldNo] = EmitNullConstant(FD->getType()); } @@ -1056,6 +1144,7 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { return llvm::ConstantStruct::get(STy, Elements); } + assert(T->isMemberPointerType() && "Should only see member pointers here!"); assert(!T->getAs<MemberPointerType>()->getPointeeType()->isFunctionType() && "Should only see pointers to data members here!"); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 9849688..2108414 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -96,6 +96,9 @@ public: Value *EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src, QualType SrcTy, QualType DstTy); + /// EmitNullValue - Emit a value that corresponds to null for the given type. + Value *EmitNullValue(QualType Ty); + //===--------------------------------------------------------------------===// // Visitor Methods //===--------------------------------------------------------------------===// @@ -123,10 +126,10 @@ public: return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue()); } Value *VisitCXXZeroInitValueExpr(const CXXZeroInitValueExpr *E) { - return llvm::Constant::getNullValue(ConvertType(E->getType())); + return EmitNullValue(E->getType()); } Value *VisitGNUNullExpr(const GNUNullExpr *E) { - return llvm::Constant::getNullValue(ConvertType(E->getType())); + return EmitNullValue(E->getType()); } Value *VisitTypesCompatibleExpr(const TypesCompatibleExpr *E) { return llvm::ConstantInt::get(ConvertType(E->getType()), @@ -186,7 +189,7 @@ public: Value *VisitInitListExpr(InitListExpr *E); Value *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { - return llvm::Constant::getNullValue(ConvertType(E->getType())); + return CGF.CGM.EmitNullConstant(E->getType()); } Value *VisitCastExpr(CastExpr *E) { // Make sure to evaluate VLA bounds now so that we have them for later. @@ -278,7 +281,7 @@ public: } Value *VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) { - return llvm::Constant::getNullValue(ConvertType(E->getType())); + return EmitNullValue(E->getType()); } Value *VisitCXXThrowExpr(const CXXThrowExpr *E) { @@ -549,6 +552,19 @@ EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src, return EmitScalarConversion(Src.first, SrcTy, DstTy); } +Value *ScalarExprEmitter::EmitNullValue(QualType Ty) { + const llvm::Type *LTy = ConvertType(Ty); + + if (!Ty->isMemberPointerType()) + return llvm::Constant::getNullValue(LTy); + + assert(!Ty->isMemberFunctionPointerType() && + "member function pointers are not scalar!"); + + // Itanium C++ ABI 2.3: + // A NULL pointer is represented as -1. + return llvm::ConstantInt::get(LTy, -1ULL, /*isSigned=*/true); +} //===----------------------------------------------------------------------===// // Visitor Methods @@ -1334,7 +1350,7 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) { } const QualType ElementType = PT ? PT->getPointeeType() : OPT->getPointeeType(); // Handle interface types, which are not represented with a concrete type. - if (const ObjCInterfaceType *OIT = dyn_cast<ObjCInterfaceType>(ElementType)) { + if (const ObjCObjectType *OIT = ElementType->getAs<ObjCObjectType>()) { llvm::Value *InterfaceSize = llvm::ConstantInt::get(Idx->getType(), CGF.getContext().getTypeSizeInChars(OIT).getQuantity()); @@ -1402,8 +1418,7 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) { Idx = Builder.CreateNeg(Idx, "sub.ptr.neg"); // Handle interface types, which are not represented with a concrete type. - if (const ObjCInterfaceType *OIT = - dyn_cast<ObjCInterfaceType>(LHSElementType)) { + if (const ObjCObjectType *OIT = LHSElementType->getAs<ObjCObjectType>()) { llvm::Value *InterfaceSize = llvm::ConstantInt::get(Idx->getType(), CGF.getContext(). diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 8426f71..7c842a9 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -47,7 +47,8 @@ llvm::Value *CodeGenFunction::EmitObjCProtocolExpr(const ObjCProtocolExpr *E) { } -RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { +RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E, + ReturnValueSlot Return) { // Only the lookup mechanism and first two arguments of the method // implementation vary between runtimes. We can get the receiver and // arguments in generic code. @@ -64,10 +65,11 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { break; case ObjCMessageExpr::Class: { - const ObjCInterfaceType *IFace - = E->getClassReceiver()->getAs<ObjCInterfaceType>(); - OID = IFace->getDecl(); - assert(IFace && "Invalid Objective-C class message send"); + const ObjCObjectType *ObjTy + = E->getClassReceiver()->getAs<ObjCObjectType>(); + assert(ObjTy && "Invalid Objective-C class message send"); + OID = ObjTy->getInterface(); + assert(OID && "Invalid Objective-C class message send"); Receiver = Runtime.GetClass(Builder, OID); isClassMessage = true; break; @@ -92,7 +94,7 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { // super is only valid in an Objective-C method const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); - return Runtime.GenerateMessageSendSuper(*this, E->getType(), + return Runtime.GenerateMessageSendSuper(*this, Return, E->getType(), E->getSelector(), OMD->getClassInterface(), isCategoryImpl, @@ -102,7 +104,8 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { E->getMethodDecl()); } - return Runtime.GenerateMessageSend(*this, E->getType(), E->getSelector(), + return Runtime.GenerateMessageSend(*this, Return, E->getType(), + E->getSelector(), Receiver, Args, OID, E->getMethodDecl()); } @@ -157,9 +160,6 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic); ObjCMethodDecl *OMD = PD->getGetterMethodDecl(); assert(OMD && "Invalid call to generate getter (empty method)"); - // FIXME: This is rather murky, we create this here since they will not have - // been created by Sema for us. - OMD->createImplicitParams(getContext(), IMP->getClassInterface()); StartObjCMethod(OMD, IMP->getClassInterface()); // Determine if we should use an objc_getProperty call for @@ -208,8 +208,9 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, Types.ConvertType(PD->getType()))); EmitReturnOfRValue(RV, PD->getType()); } else { - LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0); if (Ivar->getType()->isAnyComplexType()) { + LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), + Ivar, 0); ComplexPairTy Pair = LoadComplexFromAddr(LV.getAddress(), LV.isVolatileQualified()); StoreComplexToAddr(Pair, ReturnValue, LV.isVolatileQualified()); @@ -219,6 +220,8 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, if ((IsAtomic || (IsStrong = IvarTypeWithAggrGCObjects(Ivar->getType()))) && CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect && CGM.getObjCRuntime().GetCopyStructFunction()) { + LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), + Ivar, 0); llvm::Value *GetCopyStructFn = CGM.getObjCRuntime().GetCopyStructFunction(); CodeGenTypes &Types = CGM.getTypes(); @@ -251,9 +254,23 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, FunctionType::ExtInfo()), GetCopyStructFn, ReturnValueSlot(), Args); } - else - EmitAggregateCopy(ReturnValue, LV.getAddress(), Ivar->getType()); + else { + if (PID->getGetterCXXConstructor()) { + ReturnStmt *Stmt = + new (getContext()) ReturnStmt(SourceLocation(), + PID->getGetterCXXConstructor(), + 0); + EmitReturnStmt(*Stmt); + } + else { + LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), + Ivar, 0); + EmitAggregateCopy(ReturnValue, LV.getAddress(), Ivar->getType()); + } + } } else { + LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), + Ivar, 0); CodeGenTypes &Types = CGM.getTypes(); RValue RV = EmitLoadOfLValue(LV, Ivar->getType()); RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), @@ -274,9 +291,6 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, const ObjCPropertyDecl *PD = PID->getPropertyDecl(); ObjCMethodDecl *OMD = PD->getSetterMethodDecl(); assert(OMD && "Invalid call to generate setter (empty method)"); - // FIXME: This is rather murky, we create this here since they will not have - // been created by Sema for us. - OMD->createImplicitParams(getContext(), IMP->getClassInterface()); StartObjCMethod(OMD, IMP->getClassInterface()); bool IsCopy = PD->getSetterKind() == ObjCPropertyDecl::Copy; @@ -368,6 +382,10 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args, FunctionType::ExtInfo()), GetCopyStructFn, ReturnValueSlot(), Args); + } else if (PID->getSetterCXXAssignment()) { + EmitAnyExpr(PID->getSetterCXXAssignment(), (llvm::Value *)0, false, true, + false); + } else { // FIXME: Find a clean way to avoid AST node creation. SourceLocation Loc = PD->getLocation(); @@ -425,8 +443,7 @@ void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP, llvm::Value *SelfAsId = Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); EmitReturnOfRValue(RValue::get(SelfAsId), IdTy); - } - else { + } else { // dtor for (size_t i = IvarInitializers.size(); i > 0; --i) { FieldDecl *Field = IvarInitializers[i - 1]->getMember(); @@ -442,7 +459,7 @@ void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP, const RecordType *RT = FieldType->getAs<RecordType>(); CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); CXXDestructorDecl *Dtor = FieldClassDecl->getDestructor(getContext()); - if (!Dtor->isTrivial()) + if (!Dtor->isTrivial()) { if (Array) { const llvm::Type *BasePtr = ConvertType(FieldType); BasePtr = llvm::PointerType::getUnqual(BasePtr); @@ -450,12 +467,13 @@ void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP, Builder.CreateBitCast(LV.getAddress(), BasePtr); EmitCXXAggrDestructorCall(Dtor, Array, BaseAddrPtr); - } - else + } else { EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, LV.getAddress()); - } + } + } + } } FinishFunction(); } @@ -478,8 +496,6 @@ bool CodeGenFunction::IvarTypeWithAggrGCObjects(QualType Ty) { llvm::Value *CodeGenFunction::LoadObjCSelf() { const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); - // See if we need to lazily forward self inside a block literal. - BlockForwardSelf(); return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self"); } @@ -492,12 +508,14 @@ QualType CodeGenFunction::TypeOfSelfObject() { } RValue CodeGenFunction::EmitObjCSuperPropertyGet(const Expr *Exp, - const Selector &S) { + const Selector &S, + ReturnValueSlot Return) { llvm::Value *Receiver = LoadObjCSelf(); const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); bool isClassMessage = OMD->isClassMethod(); bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); return CGM.getObjCRuntime().GenerateMessageSendSuper(*this, + Return, Exp->getType(), S, OMD->getClassInterface(), @@ -508,15 +526,16 @@ RValue CodeGenFunction::EmitObjCSuperPropertyGet(const Expr *Exp, } -RValue CodeGenFunction::EmitObjCPropertyGet(const Expr *Exp) { +RValue CodeGenFunction::EmitObjCPropertyGet(const Expr *Exp, + ReturnValueSlot Return) { Exp = Exp->IgnoreParens(); // FIXME: Split it into two separate routines. if (const ObjCPropertyRefExpr *E = dyn_cast<ObjCPropertyRefExpr>(Exp)) { Selector S = E->getProperty()->getGetterName(); if (isa<ObjCSuperExpr>(E->getBase())) - return EmitObjCSuperPropertyGet(E, S); + return EmitObjCSuperPropertyGet(E, S, Return); return CGM.getObjCRuntime(). - GenerateMessageSend(*this, Exp->getType(), S, + GenerateMessageSend(*this, Return, Exp->getType(), S, EmitScalarExpr(E->getBase()), CallArgList()); } else { @@ -528,11 +547,11 @@ RValue CodeGenFunction::EmitObjCPropertyGet(const Expr *Exp) { const ObjCInterfaceDecl *OID = KE->getInterfaceDecl(); Receiver = CGM.getObjCRuntime().GetClass(Builder, OID); } else if (isa<ObjCSuperExpr>(KE->getBase())) - return EmitObjCSuperPropertyGet(KE, S); + return EmitObjCSuperPropertyGet(KE, S, Return); else Receiver = EmitScalarExpr(KE->getBase()); return CGM.getObjCRuntime(). - GenerateMessageSend(*this, Exp->getType(), S, + GenerateMessageSend(*this, Return, Exp->getType(), S, Receiver, CallArgList(), KE->getInterfaceDecl()); } @@ -548,6 +567,7 @@ void CodeGenFunction::EmitObjCSuperPropertySet(const Expr *Exp, bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); Args.push_back(std::make_pair(Src, Exp->getType())); CGM.getObjCRuntime().GenerateMessageSendSuper(*this, + ReturnValueSlot(), Exp->getType(), S, OMD->getClassInterface(), @@ -569,7 +589,8 @@ void CodeGenFunction::EmitObjCPropertySet(const Expr *Exp, } CallArgList Args; Args.push_back(std::make_pair(Src, E->getType())); - CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S, + CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(), + getContext().VoidTy, S, EmitScalarExpr(E->getBase()), Args); } else if (const ObjCImplicitSetterGetterRefExpr *E = @@ -586,7 +607,8 @@ void CodeGenFunction::EmitObjCPropertySet(const Expr *Exp, } else Receiver = EmitScalarExpr(E->getBase()); Args.push_back(std::make_pair(Src, E->getType())); - CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S, + CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(), + getContext().VoidTy, S, Receiver, Args, E->getInterfaceDecl()); } else @@ -618,7 +640,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ // Fast enumeration state. QualType StateTy = getContext().getObjCFastEnumerationStateType(); llvm::Value *StatePtr = CreateMemTemp(StateTy, "state.ptr"); - EmitMemSetToZero(StatePtr, StateTy); + EmitNullInitialization(StatePtr, StateTy); // Number of elements in the items array. static const unsigned NumItems = 16; @@ -653,7 +675,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ getContext().UnsignedLongTy)); RValue CountRV = - CGM.getObjCRuntime().GenerateMessageSend(*this, + CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(), getContext().UnsignedLongTy, FastEnumSel, Collection, Args); @@ -778,7 +800,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ EmitBlock(FetchMore); CountRV = - CGM.getObjCRuntime().GenerateMessageSend(*this, + CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(), getContext().UnsignedLongTy, FastEnumSel, Collection, Args); diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 3c51b7e..6c25afe 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -142,6 +142,7 @@ public: virtual llvm::Constant *GenerateConstantString(const StringLiteral *); virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, + ReturnValueSlot Return, QualType ResultType, Selector Sel, llvm::Value *Receiver, @@ -150,6 +151,7 @@ public: const ObjCMethodDecl *Method); virtual CodeGen::RValue GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, + ReturnValueSlot Return, QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class, @@ -235,6 +237,21 @@ static std::string SymbolNameForMethod(const std::string &ClassName, const return std::string(isClassMethod ? "_c_" : "_i_") + ClassName + "_" + CategoryName + "_" + MethodNameColonStripped; } +static std::string MangleSelectorTypes(const std::string &TypeString) { + std::string Mangled = TypeString; + // Simple mangling to avoid breaking when we mix JIT / static code. + // Not part of the ABI, subject to change without notice. + std::replace(Mangled.begin(), Mangled.end(), '@', '_'); + std::replace(Mangled.begin(), Mangled.end(), ':', 'J'); + std::replace(Mangled.begin(), Mangled.end(), '*', 'e'); + std::replace(Mangled.begin(), Mangled.end(), '#', 'E'); + std::replace(Mangled.begin(), Mangled.end(), ':', 'j'); + std::replace(Mangled.begin(), Mangled.end(), '(', 'g'); + std::replace(Mangled.begin(), Mangled.end(), ')', 'G'); + std::replace(Mangled.begin(), Mangled.end(), '[', 'h'); + std::replace(Mangled.begin(), Mangled.end(), ']', 'H'); + return Mangled; +} CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm) : CGM(cgm), TheModule(CGM.getModule()), ClassPtrAlias(0), @@ -440,6 +457,7 @@ llvm::Constant *CGObjCGNU::GenerateConstantString(const StringLiteral *SL) { ///should be called. CodeGen::RValue CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, + ReturnValueSlot Return, QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class, @@ -567,7 +585,7 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD, 3); llvm::Instruction *call; - RValue msgRet = CGF.EmitCall(FnInfo, imp, ReturnValueSlot(), ActualArgs, + RValue msgRet = CGF.EmitCall(FnInfo, imp, Return, ActualArgs, 0, &call); call->setMetadata(msgSendMDKind, node); return msgRet; @@ -576,6 +594,7 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, /// Generate code for a message send expression. CodeGen::RValue CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, + ReturnValueSlot Return, QualType ResultType, Selector Sel, llvm::Value *Receiver, @@ -611,16 +630,16 @@ CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, llvm::BasicBlock *startBB = 0; llvm::BasicBlock *messageBB = 0; - llvm::BasicBlock *contiueBB = 0; + llvm::BasicBlock *continueBB = 0; if (!isPointerSizedReturn) { startBB = Builder.GetInsertBlock(); messageBB = CGF.createBasicBlock("msgSend"); - contiueBB = CGF.createBasicBlock("continue"); + continueBB = CGF.createBasicBlock("continue"); llvm::Value *isNil = Builder.CreateICmpEQ(Receiver, llvm::Constant::getNullValue(Receiver->getType())); - Builder.CreateCondBr(isNil, contiueBB, messageBB); + Builder.CreateCondBr(isNil, continueBB, messageBB); CGF.EmitBlock(messageBB); } @@ -711,12 +730,15 @@ CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, cast<llvm::CallInst>(imp)->setMetadata(msgSendMDKind, node); } llvm::Instruction *call; - RValue msgRet = CGF.EmitCall(FnInfo, imp, ReturnValueSlot(), ActualArgs, + RValue msgRet = CGF.EmitCall(FnInfo, imp, Return, ActualArgs, 0, &call); call->setMetadata(msgSendMDKind, node); + if (!isPointerSizedReturn) { - CGF.EmitBlock(contiueBB); + messageBB = CGF.Builder.GetInsertBlock(); + CGF.Builder.CreateBr(continueBB); + CGF.EmitBlock(continueBB); if (msgRet.isScalar()) { llvm::Value *v = msgRet.getScalarVal(); llvm::PHINode *phi = Builder.CreatePHI(v->getType()); @@ -1665,34 +1687,36 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { llvm::Constant *Idxs[] = {Zeros[0], llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), index++), Zeros[0]}; llvm::Constant *SelPtr = new llvm::GlobalVariable(TheModule, SelStructPtrTy, - true, llvm::GlobalValue::InternalLinkage, - llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2), - ".objc_sel_ptr"); + true, llvm::GlobalValue::LinkOnceODRLinkage, + llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2), + MangleSelectorTypes(".objc_sel_ptr"+iter->first.first+"."+ + iter->first.second)); // If selectors are defined as an opaque type, cast the pointer to this // type. if (isSelOpaque) { SelPtr = llvm::ConstantExpr::getBitCast(SelPtr, llvm::PointerType::getUnqual(SelectorTy)); } - (*iter).second->setAliasee(SelPtr); + (*iter).second->replaceAllUsesWith(SelPtr); + (*iter).second->eraseFromParent(); } for (llvm::StringMap<llvm::GlobalAlias*>::iterator iter=UntypedSelectors.begin(), iterEnd = UntypedSelectors.end(); iter != iterEnd; iter++) { llvm::Constant *Idxs[] = {Zeros[0], llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), index++), Zeros[0]}; - llvm::Constant *SelPtr = new llvm::GlobalVariable - (TheModule, SelStructPtrTy, - true, llvm::GlobalValue::InternalLinkage, - llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2), - ".objc_sel_ptr"); + llvm::Constant *SelPtr = new llvm::GlobalVariable(TheModule, SelStructPtrTy, + true, llvm::GlobalValue::LinkOnceODRLinkage, + llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2), + MangleSelectorTypes(std::string(".objc_sel_ptr")+iter->getKey().str())); // If selectors are defined as an opaque type, cast the pointer to this // type. if (isSelOpaque) { SelPtr = llvm::ConstantExpr::getBitCast(SelPtr, llvm::PointerType::getUnqual(SelectorTy)); } - (*iter).second->setAliasee(SelPtr); + (*iter).second->replaceAllUsesWith(SelPtr); + (*iter).second->eraseFromParent(); } // Number of classes defined. Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext), @@ -1922,11 +1946,11 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const ObjCObjectPointerType *OPT = CatchDecl->getType()->getAs<ObjCObjectPointerType>(); assert(OPT && "Invalid @catch type."); - const ObjCInterfaceType *IT = - OPT->getPointeeType()->getAs<ObjCInterfaceType>(); - assert(IT && "Invalid @catch type."); + const ObjCInterfaceDecl *IDecl = + OPT->getObjectType()->getInterface(); + assert(IDecl && "Invalid @catch type."); llvm::Value *EHType = - MakeConstantString(IT->getDecl()->getNameAsString()); + MakeConstantString(IDecl->getNameAsString()); ESelArgs.push_back(EHType); } } @@ -2208,7 +2232,8 @@ LValue CGObjCGNU::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, unsigned CVRQualifiers) { - const ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCInterfaceType>()->getDecl(); + const ObjCInterfaceDecl *ID = + ObjectTy->getAs<ObjCObjectType>()->getInterface(); return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, EmitIvarOffset(CGF, ID, Ivar)); } diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 77eabbf..d3bafd7 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -973,6 +973,7 @@ protected: bool AddToUsed); CodeGen::RValue EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF, + ReturnValueSlot Return, QualType ResultType, llvm::Value *Sel, llvm::Value *Arg0, @@ -1039,6 +1040,7 @@ private: llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID); CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF, + ReturnValueSlot Return, QualType ResultType, Selector Sel, llvm::Value *Arg0, @@ -1126,6 +1128,7 @@ public: virtual llvm::Function *ModuleInitFunction(); virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, + ReturnValueSlot Return, QualType ResultType, Selector Sel, llvm::Value *Receiver, @@ -1135,6 +1138,7 @@ public: virtual CodeGen::RValue GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, + ReturnValueSlot Return, QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class, @@ -1279,6 +1283,7 @@ private: ObjCProtocolDecl::protocol_iterator end); CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF, + ReturnValueSlot Return, QualType ResultType, Selector Sel, llvm::Value *Receiver, @@ -1354,6 +1359,7 @@ public: virtual llvm::Function *ModuleInitFunction(); virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, + ReturnValueSlot Return, QualType ResultType, Selector Sel, llvm::Value *Receiver, @@ -1363,6 +1369,7 @@ public: virtual CodeGen::RValue GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, + ReturnValueSlot Return, QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class, @@ -1515,6 +1522,7 @@ llvm::Constant *CGObjCCommonMac::GenerateConstantString( /// which class's method should be called. CodeGen::RValue CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, + ReturnValueSlot Return, QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class, @@ -1566,7 +1574,7 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, Target = CGF.Builder.CreateBitCast(Target, ClassTy); CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1)); - return EmitLegacyMessageSend(CGF, ResultType, + return EmitLegacyMessageSend(CGF, Return, ResultType, EmitSelector(CGF.Builder, Sel), ObjCSuper, ObjCTypes.SuperPtrCTy, true, CallArgs, Method, ObjCTypes); @@ -1574,13 +1582,14 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, /// Generate code for a message send expression. CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, + ReturnValueSlot Return, QualType ResultType, Selector Sel, llvm::Value *Receiver, const CallArgList &CallArgs, const ObjCInterfaceDecl *Class, const ObjCMethodDecl *Method) { - return EmitLegacyMessageSend(CGF, ResultType, + return EmitLegacyMessageSend(CGF, Return, ResultType, EmitSelector(CGF.Builder, Sel), Receiver, CGF.getContext().getObjCIdType(), false, CallArgs, Method, ObjCTypes); @@ -1588,6 +1597,7 @@ CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, CodeGen::RValue CGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF, + ReturnValueSlot Return, QualType ResultType, llvm::Value *Sel, llvm::Value *Arg0, @@ -1634,7 +1644,7 @@ CGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF, assert(Fn && "EmitLegacyMessageSend - unknown API"); Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy)); - return CGF.EmitCall(FnInfo, Fn, ReturnValueSlot(), ActualArgs); + return CGF.EmitCall(FnInfo, Fn, Return, ActualArgs); } llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder, @@ -2701,12 +2711,12 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, } assert(OPT && "Unexpected non-object pointer type in @catch"); - QualType T = OPT->getPointeeType(); - const ObjCInterfaceType *ObjCType = T->getAs<ObjCInterfaceType>(); - assert(ObjCType && "Catch parameter must have Objective-C type!"); + const ObjCObjectType *ObjTy = OPT->getObjectType(); + ObjCInterfaceDecl *IDecl = ObjTy->getInterface(); + assert(IDecl && "Catch parameter must have Objective-C type!"); // Check if the @catch block matches the exception object. - llvm::Value *Class = EmitClassRef(CGF.Builder, ObjCType->getDecl()); + llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl); llvm::Value *Match = CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(), @@ -2938,7 +2948,8 @@ LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, unsigned CVRQualifiers) { - const ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCInterfaceType>()->getDecl(); + const ObjCInterfaceDecl *ID = + ObjectTy->getAs<ObjCObjectType>()->getInterface(); return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, EmitIvarOffset(CGF, ID, Ivar)); } @@ -3669,7 +3680,7 @@ ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm) // id self; // Class cls; // } - RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, + RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct, Ctx.getTranslationUnitDecl(), SourceLocation(), &Ctx.Idents.get("_objc_super")); @@ -4131,7 +4142,7 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul // }; // First the clang type for struct _message_ref_t - RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, + RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct, Ctx.getTranslationUnitDecl(), SourceLocation(), &Ctx.Idents.get("_message_ref_t")); @@ -5095,12 +5106,12 @@ CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) { /// @encode /// LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar( - CodeGen::CodeGenFunction &CGF, - QualType ObjectTy, - llvm::Value *BaseValue, - const ObjCIvarDecl *Ivar, - unsigned CVRQualifiers) { - const ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCInterfaceType>()->getDecl(); + CodeGen::CodeGenFunction &CGF, + QualType ObjectTy, + llvm::Value *BaseValue, + const ObjCIvarDecl *Ivar, + unsigned CVRQualifiers) { + ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface(); return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, EmitIvarOffset(CGF, ID, Ivar)); } @@ -5114,6 +5125,7 @@ llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset( CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend( CodeGen::CodeGenFunction &CGF, + ReturnValueSlot Return, QualType ResultType, Selector Sel, llvm::Value *Receiver, @@ -5213,12 +5225,13 @@ CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend( const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo1, true); Callee = CGF.Builder.CreateBitCast(Callee, llvm::PointerType::getUnqual(FTy)); - return CGF.EmitCall(FnInfo1, Callee, ReturnValueSlot(), ActualArgs); + return CGF.EmitCall(FnInfo1, Callee, Return, ActualArgs); } /// Generate code for a message send expression in the nonfragile abi. CodeGen::RValue CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, + ReturnValueSlot Return, QualType ResultType, Selector Sel, llvm::Value *Receiver, @@ -5226,10 +5239,11 @@ CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, const ObjCInterfaceDecl *Class, const ObjCMethodDecl *Method) { return LegacyDispatchedSelector(Sel) - ? EmitLegacyMessageSend(CGF, ResultType, EmitSelector(CGF.Builder, Sel), + ? EmitLegacyMessageSend(CGF, Return, ResultType, + EmitSelector(CGF.Builder, Sel), Receiver, CGF.getContext().getObjCIdType(), false, CallArgs, Method, ObjCTypes) - : EmitMessageSend(CGF, ResultType, Sel, + : EmitMessageSend(CGF, Return, ResultType, Sel, Receiver, CGF.getContext().getObjCIdType(), false, CallArgs); } @@ -5336,6 +5350,7 @@ llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder, /// which class's method should be called. CodeGen::RValue CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, + ReturnValueSlot Return, QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class, @@ -5378,10 +5393,11 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, CGF.Builder.CreateStructGEP(ObjCSuper, 1)); return (LegacyDispatchedSelector(Sel)) - ? EmitLegacyMessageSend(CGF, ResultType,EmitSelector(CGF.Builder, Sel), + ? EmitLegacyMessageSend(CGF, Return, ResultType, + EmitSelector(CGF.Builder, Sel), ObjCSuper, ObjCTypes.SuperPtrCTy, true, CallArgs, Method, ObjCTypes) - : EmitMessageSend(CGF, ResultType, Sel, + : EmitMessageSend(CGF, Return, ResultType, Sel, ObjCSuper, ObjCTypes.SuperPtrCTy, true, CallArgs); } diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h index 654ad0a..8de7f10 100644 --- a/lib/CodeGen/CGObjCRuntime.h +++ b/lib/CodeGen/CGObjCRuntime.h @@ -119,6 +119,7 @@ public: /// a property setter or getter. virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, + ReturnValueSlot ReturnSlot, QualType ResultType, Selector Sel, llvm::Value *Receiver, @@ -134,6 +135,7 @@ public: /// a property setter or getter. virtual CodeGen::RValue GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, + ReturnValueSlot ReturnSlot, QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class, diff --git a/lib/CodeGen/CGRecordLayout.h b/lib/CodeGen/CGRecordLayout.h index 9f966fb..e95591e 100644 --- a/lib/CodeGen/CGRecordLayout.h +++ b/lib/CodeGen/CGRecordLayout.h @@ -168,6 +168,10 @@ private: /// field no. This info is populated by record builder. llvm::DenseMap<const FieldDecl *, CGBitFieldInfo> BitFields; + // FIXME: Maybe we could use a CXXBaseSpecifier as the key and use a single + // map for both virtual and non virtual bases. + llvm::DenseMap<const CXXRecordDecl *, unsigned> NonVirtualBaseFields; + /// Whether one of the fields in this record layout is a pointer to data /// member, or a struct that contains pointer to data member. bool ContainsPointerToDataMember : 1; @@ -194,6 +198,11 @@ public: return FieldInfo.lookup(FD); } + unsigned getNonVirtualBaseLLVMFieldNo(const CXXRecordDecl *RD) const { + assert(NonVirtualBaseFields.count(RD) && "Invalid non-virtual base!"); + return NonVirtualBaseFields.lookup(RD); + } + /// \brief Return the BitFieldInfo that corresponds to the field FD. const CGBitFieldInfo &getBitFieldInfo(const FieldDecl *FD) const { assert(FD->isBitField() && "Invalid call for non bit-field decl!"); diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp index 6302cf8..9f16875 100644 --- a/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -42,6 +42,9 @@ public: typedef std::pair<const FieldDecl *, CGBitFieldInfo> LLVMBitFieldInfo; llvm::SmallVector<LLVMBitFieldInfo, 16> LLVMBitFields; + typedef std::pair<const CXXRecordDecl *, unsigned> LLVMBaseInfo; + llvm::SmallVector<LLVMBaseInfo, 16> LLVMNonVirtualBases; + /// ContainsPointerToDataMember - Whether one of the fields in this record /// layout is a pointer to data member, or a struct that contains pointer to /// data member. @@ -81,8 +84,13 @@ private: /// Returns false if the operation failed because the struct is not packed. bool LayoutFields(const RecordDecl *D); - /// LayoutBases - layout the bases and vtable pointer of a record decl. - void LayoutBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout); + /// LayoutNonVirtualBase - layout a single non-virtual base. + void LayoutNonVirtualBase(const CXXRecordDecl *BaseDecl, + uint64_t BaseOffset); + + /// LayoutNonVirtualBases - layout the non-virtual bases of a record decl. + void LayoutNonVirtualBases(const CXXRecordDecl *RD, + const ASTRecordLayout &Layout); /// LayoutField - layout a single field. Returns false if the operation failed /// because the current struct is not packed. @@ -110,6 +118,7 @@ private: /// CheckForPointerToDataMember - Check if the given type contains a pointer /// to data member. void CheckForPointerToDataMember(QualType T); + void CheckForPointerToDataMember(const CXXRecordDecl *RD); public: CGRecordLayoutBuilder(CodeGenTypes &Types) @@ -143,6 +152,7 @@ void CGRecordLayoutBuilder::Layout(const RecordDecl *D) { FieldTypes.clear(); LLVMFields.clear(); LLVMBitFields.clear(); + LLVMNonVirtualBases.clear(); LayoutFields(D); } @@ -319,8 +329,9 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D, if (const RecordType *RT = D->getType()->getAs<RecordType>()) { const RecordDecl *RD = cast<RecordDecl>(RT->getDecl()); - if (const PragmaPackAttr *PPA = RD->getAttr<PragmaPackAttr>()) { - if (PPA->getAlignment() != TypeAlignment * 8 && !Packed) + if (const MaxFieldAlignmentAttr *MFAA = + RD->getAttr<MaxFieldAlignmentAttr>()) { + if (MFAA->getAlignment() != TypeAlignment * 8 && !Packed) return false; } } @@ -435,16 +446,66 @@ void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) { AppendPadding(Layout.getSize() / 8, Align); } -void CGRecordLayoutBuilder::LayoutBases(const CXXRecordDecl *RD, - const ASTRecordLayout &Layout) { +void CGRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *BaseDecl, + uint64_t BaseOffset) { + const ASTRecordLayout &Layout = + Types.getContext().getASTRecordLayout(BaseDecl); + + uint64_t NonVirtualSize = Layout.getNonVirtualSize(); + + if (BaseDecl->isEmpty()) { + // FIXME: Lay out empty bases. + return; + } + + CheckForPointerToDataMember(BaseDecl); + + // FIXME: Actually use a better type than [sizeof(BaseDecl) x i8] when we can. + AppendPadding(BaseOffset / 8, 1); + + // Append the base field. + LLVMNonVirtualBases.push_back(LLVMBaseInfo(BaseDecl, FieldTypes.size())); + + AppendBytes(NonVirtualSize / 8); +} + +void +CGRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD, + const ASTRecordLayout &Layout) { + const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); + // Check if we need to add a vtable pointer. - if (RD->isDynamicClass() && !Layout.getPrimaryBase()) { - const llvm::Type *Int8PtrTy = - llvm::Type::getInt8PtrTy(Types.getLLVMContext()); + if (RD->isDynamicClass()) { + if (!PrimaryBase) { + const llvm::Type *FunctionType = + llvm::FunctionType::get(llvm::Type::getInt32Ty(Types.getLLVMContext()), + /*isVarArg=*/true); + const llvm::Type *VTableTy = FunctionType->getPointerTo(); + + assert(NextFieldOffsetInBytes == 0 && + "VTable pointer must come first!"); + AppendField(NextFieldOffsetInBytes, VTableTy->getPointerTo()); + } else { + // FIXME: Handle a virtual primary base. + if (!Layout.getPrimaryBaseWasVirtual()) + LayoutNonVirtualBase(PrimaryBase, 0); + } + } - assert(NextFieldOffsetInBytes == 0 && - "VTable pointer must come first!"); - AppendField(NextFieldOffsetInBytes, Int8PtrTy->getPointerTo()); + // Layout the non-virtual bases. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + if (I->isVirtual()) + continue; + + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + // We've already laid out the primary base. + if (BaseDecl == PrimaryBase && !Layout.getPrimaryBaseWasVirtual()) + continue; + + LayoutNonVirtualBase(BaseDecl, Layout.getBaseClassOffset(BaseDecl)); } } @@ -455,7 +516,7 @@ bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(D); if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) - LayoutBases(RD, Layout); + LayoutNonVirtualBases(RD, Layout); unsigned FieldNo = 0; @@ -561,15 +622,24 @@ void CGRecordLayoutBuilder::CheckForPointerToDataMember(QualType T) { } else if (const RecordType *RT = T->getAs<RecordType>()) { const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - // FIXME: It would be better if there was a way to explicitly compute the - // record layout instead of converting to a type. - Types.ConvertTagDeclType(RD); + return CheckForPointerToDataMember(RD); + } +} - const CGRecordLayout &Layout = Types.getCGRecordLayout(RD); +void +CGRecordLayoutBuilder::CheckForPointerToDataMember(const CXXRecordDecl *RD) { + // This record already contains a member pointer. + if (ContainsPointerToDataMember) + return; - if (Layout.containsPointerToDataMember()) - ContainsPointerToDataMember = true; - } + // FIXME: It would be better if there was a way to explicitly compute the + // record layout instead of converting to a type. + Types.ConvertTagDeclType(RD); + + const CGRecordLayout &Layout = Types.getCGRecordLayout(RD); + + if (Layout.containsPointerToDataMember()) + ContainsPointerToDataMember = true; } CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) { @@ -584,13 +654,17 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) { CGRecordLayout *RL = new CGRecordLayout(Ty, Builder.ContainsPointerToDataMember); + // Add all the non-virtual base field numbers. + RL->NonVirtualBaseFields.insert(Builder.LLVMNonVirtualBases.begin(), + Builder.LLVMNonVirtualBases.end()); + // Add all the field numbers. - for (unsigned i = 0, e = Builder.LLVMFields.size(); i != e; ++i) - RL->FieldInfo.insert(Builder.LLVMFields[i]); + RL->FieldInfo.insert(Builder.LLVMFields.begin(), + Builder.LLVMFields.end()); // Add bitfield info. - for (unsigned i = 0, e = Builder.LLVMBitFields.size(); i != e; ++i) - RL->BitFields.insert(Builder.LLVMBitFields[i]); + RL->BitFields.insert(Builder.LLVMBitFields.begin(), + Builder.LLVMBitFields.end()); // Dump the layout, if requested. if (getContext().getLangOptions().DumpRecordLayouts) { diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index a914c80d..efde380 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -30,7 +30,10 @@ using namespace CodeGen; void CodeGenFunction::EmitStopPoint(const Stmt *S) { if (CGDebugInfo *DI = getDebugInfo()) { - DI->setLocation(S->getLocStart()); + if (isa<DeclStmt>(S)) + DI->setLocation(S->getLocEnd()); + else + DI->setLocation(S->getLocStart()); DI->EmitStopPoint(CurFn, Builder); } } @@ -76,8 +79,11 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { // Expression emitters don't handle unreachable blocks yet, so look for one // explicitly here. This handles the common case of a call to a noreturn // function. + // We can't erase blocks with an associated cleanup size here since the + // memory might be reused, leaving the old cleanup info pointing at a new + // block. if (llvm::BasicBlock *CurBB = Builder.GetInsertBlock()) { - if (CurBB->empty() && CurBB->use_empty()) { + if (CurBB->empty() && CurBB->use_empty() && !BlockScopes.count(CurBB)) { CurBB->eraseFromParent(); Builder.ClearInsertionPoint(); } @@ -484,8 +490,6 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S) { } void CodeGenFunction::EmitForStmt(const ForStmt &S) { - // FIXME: What do we do if the increment (f.e.) contains a stmt expression, - // which contains a continue/break? CleanupScope ForScope(*this); // Evaluate the first part before the loop. @@ -555,14 +559,14 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) { EmitStmt(S.getBody()); } - BreakContinueStack.pop_back(); - // If there is an increment, emit it next. if (S.getInc()) { EmitBlock(IncBlock); EmitStmt(S.getInc()); } + BreakContinueStack.pop_back(); + // Finally, branch back up to the condition for the next iteration. if (CondCleanup) { // Branch to the cleanup block. @@ -604,7 +608,20 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { // FIXME: Clean this up by using an LValue for ReturnTemp, // EmitStoreThroughLValue, and EmitAnyExpr. - if (!ReturnValue) { + if (S.getNRVOCandidate() && S.getNRVOCandidate()->isNRVOVariable() && + !Target.useGlobalsForAutomaticVariables()) { + // Apply the named return value optimization for this return statement, + // which means doing nothing: the appropriate result has already been + // constructed into the NRVO variable. + + // If there is an NRVO flag for this variable, set it to 1 into indicate + // that the cleanup code should not destroy the variable. + if (llvm::Value *NRVOFlag = NRVOFlags[S.getNRVOCandidate()]) { + const llvm::Type *BoolTy = llvm::Type::getInt1Ty(VMContext); + llvm::Value *One = llvm::ConstantInt::get(BoolTy, 1); + Builder.CreateStore(One, NRVOFlag); + } + } else if (!ReturnValue) { // Make sure not to return anything, but evaluate the expression // for side effects. if (RV) diff --git a/lib/CodeGen/CGVTT.cpp b/lib/CodeGen/CGVTT.cpp index 15e5648..61c7423 100644 --- a/lib/CodeGen/CGVTT.cpp +++ b/lib/CodeGen/CGVTT.cpp @@ -378,7 +378,7 @@ CodeGenVTables::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage, D1(printf("vtt %s\n", RD->getNameAsCString())); - llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); + llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true); if (GV == 0 || GV->isDeclaration()) { const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index 159753a..0f023e6 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -2548,7 +2548,7 @@ llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD, getMangleContext().mangleThunk(MD, Thunk, Name); const llvm::Type *Ty = getTypes().GetFunctionTypeForVTable(MD); - return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl()); + return GetOrCreateLLVMFunction(Name, Ty, GD); } static llvm::Value *PerformTypeAdjustment(CodeGenFunction &CGF, @@ -2641,10 +2641,9 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD, E = MD->param_end(); I != E; ++I) { ParmVarDecl *Param = *I; QualType ArgType = Param->getType(); + RValue Arg = EmitDelegateCallArg(Param); - // FIXME: Declaring a DeclRefExpr on the stack is kinda icky. - DeclRefExpr ArgExpr(Param, ArgType.getNonReferenceType(), SourceLocation()); - CallArgs.push_back(std::make_pair(EmitCallArg(&ArgExpr, ArgType), ArgType)); + CallArgs.push_back(std::make_pair(Arg, ArgType)); } // Get our callee. @@ -2657,8 +2656,15 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD, CGM.getTypes().getFunctionInfo(ResultType, CallArgs, FPT->getExtInfo()); + // Determine whether we have a return value slot to use. + ReturnValueSlot Slot; + if (!ResultType->isVoidType() && + FnInfo.getReturnInfo().getKind() == ABIArgInfo::Indirect && + hasAggregateLLVMType(CurFnInfo->getReturnType())) + Slot = ReturnValueSlot(ReturnValue, ResultType.isVolatileQualified()); + // Now emit our call. - RValue RV = EmitCall(FnInfo, Callee, ReturnValueSlot(), CallArgs, MD); + RValue RV = EmitCall(FnInfo, Callee, Slot, CallArgs, MD); if (!Thunk.Return.isEmpty()) { // Emit the return adjustment. @@ -2701,7 +2707,7 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD, RV = RValue::get(ReturnValue); } - if (!ResultType->isVoidType()) + if (!ResultType->isVoidType() && Slot.isNull()) EmitReturnOfRValue(RV, ResultType); FinishFunction(); @@ -2710,7 +2716,7 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD, CXXThisDecl->Destroy(getContext()); // Set the right linkage. - Fn->setLinkage(CGM.getFunctionLinkage(MD)); + CGM.setFunctionLinkage(MD, Fn); // Set the right visibility. CGM.setGlobalVisibility(Fn, MD); @@ -2788,7 +2794,13 @@ void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) { // Check if we've computed this information before. if (LayoutData) return; - + + // We may need to generate a definition for this vtable. + if (!isKeyFunctionInAnotherTU(CGM.getContext(), RD) && + RD->getTemplateSpecializationKind() + != TSK_ExplicitInstantiationDeclaration) + CGM.DeferredVTables.push_back(RD); + VTableBuilder Builder(*this, RD, 0, /*MostDerivedClassIsVirtual=*/0, RD); // Add the VTable layout. @@ -3119,49 +3131,3 @@ CodeGenVTables::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage, DC->getParent()->isTranslationUnit()) CGM.EmitFundamentalRTTIDescriptors(); } - -void CodeGenVTables::EmitVTableRelatedData(GlobalDecl GD) { - const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); - const CXXRecordDecl *RD = MD->getParent(); - - // If the class doesn't have a vtable we don't need to emit one. - if (!RD->isDynamicClass()) - return; - - // Check if we need to emit thunks for this function. - if (MD->isVirtual()) - EmitThunks(GD); - - // Get the key function. - const CXXMethodDecl *KeyFunction = CGM.getContext().getKeyFunction(RD); - - TemplateSpecializationKind RDKind = RD->getTemplateSpecializationKind(); - TemplateSpecializationKind MDKind = MD->getTemplateSpecializationKind(); - - if (KeyFunction) { - // We don't have the right key function. - if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl()) - return; - } else { - // If we have no key funcion and this is a explicit instantiation declaration, - // we will produce a vtable at the explicit instantiation. We don't need one - // here. - if (RDKind == clang::TSK_ExplicitInstantiationDeclaration) - return; - - // If this is an explicit instantiation of a method, we don't need a vtable. - // Since we have no key function, we will emit the vtable when we see - // a use, and just defining a function is not an use. - if (RDKind == TSK_ImplicitInstantiation && - MDKind == TSK_ExplicitInstantiationDefinition) - return; - } - - if (VTables.count(RD)) - return; - - if (RDKind == TSK_ImplicitInstantiation) - CGM.DeferredVTables.push_back(RD); - else - GenerateClassData(CGM.getVTableLinkage(RD), RD); -} diff --git a/lib/CodeGen/CGVTables.h b/lib/CodeGen/CGVTables.h index 6c18ca8..e55377f 100644 --- a/lib/CodeGen/CGVTables.h +++ b/lib/CodeGen/CGVTables.h @@ -272,9 +272,6 @@ class CodeGenVTables { /// EmitThunk - Emit a single thunk. void EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk); - /// EmitThunks - Emit the associated thunks for the given global decl. - void EmitThunks(GlobalDecl GD); - /// ComputeVTableRelatedInformation - Compute and store all vtable related /// information (vtable layout, vbase offset offsets, thunks etc) for the /// given record decl. @@ -349,11 +346,10 @@ public: VTableAddressPointsMapTy& AddressPoints); llvm::GlobalVariable *getVTT(const CXXRecordDecl *RD); - - // EmitVTableRelatedData - Will emit any thunks that the global decl might - // have, as well as the vtable itself if the global decl is the key function. - void EmitVTableRelatedData(GlobalDecl GD); + /// EmitThunks - Emit the associated thunks for the given global decl. + void EmitThunks(GlobalDecl GD); + /// GenerateClassData - Generate all the class data required to be generated /// upon definition of a KeyFunction. This includes the vtable, the /// rtti data structure and the VTT. diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt index dfd2a39..a226400 100644 --- a/lib/CodeGen/CMakeLists.txt +++ b/lib/CodeGen/CMakeLists.txt @@ -28,7 +28,10 @@ add_clang_library(clangCodeGen CodeGenFunction.cpp CodeGenModule.cpp CodeGenTypes.cpp + ItaniumCXXABI.cpp Mangle.cpp ModuleBuilder.cpp TargetInfo.cpp ) + +add_dependencies(clangCodeGen ClangStmtNodes) diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index d3bf164..73de0fd 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -37,6 +37,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) LLVMPointerWidth = Target.getPointerWidth(0); Exceptions = getContext().getLangOptions().Exceptions; CatchUndefined = getContext().getLangOptions().CatchUndefined; + CGM.getMangleContext().startNewFunction(); } ASTContext &CodeGenFunction::getContext() const { @@ -472,7 +473,23 @@ void CodeGenFunction::ErrorUnsupported(const Stmt *S, const char *Type, CGM.ErrorUnsupported(S, Type, OmitOnError); } -void CodeGenFunction::EmitMemSetToZero(llvm::Value *DestPtr, QualType Ty) { +void +CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) { + // If the type contains a pointer to data member we can't memset it to zero. + // Instead, create a null constant and copy it to the destination. + if (CGM.getTypes().ContainsPointerToDataMember(Ty)) { + llvm::Constant *NullConstant = CGM.EmitNullConstant(Ty); + + llvm::GlobalVariable *NullVariable = + new llvm::GlobalVariable(CGM.getModule(), NullConstant->getType(), + /*isConstant=*/true, + llvm::GlobalVariable::PrivateLinkage, + NullConstant, llvm::Twine()); + EmitAggregateCopy(DestPtr, NullVariable, Ty, /*isVolatile=*/false); + return; + } + + // Ignore empty classes in C++. if (getContext().getLangOptions().CPlusPlus) { if (const RecordType *RT = Ty->getAs<RecordType>()) { @@ -481,6 +498,9 @@ void CodeGenFunction::EmitMemSetToZero(llvm::Value *DestPtr, QualType Ty) { } } + // Otherwise, just memset the whole thing to zero. This is legal + // because in LLVM, all default initializers (other than the ones we just + // handled above) are guaranteed to have a bit pattern of all zeros. const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext); if (DestPtr->getType() != BP) DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp"); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 90a3ec4..ece275e 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -67,6 +67,7 @@ namespace CodeGen { class CGDebugInfo; class CGFunctionInfo; class CGRecordLayout; + class CGBlockInfo; /// CodeGenFunction - This class organizes the per-function state that is used /// while generating LLVM code. @@ -107,6 +108,11 @@ public: bool Exceptions; bool CatchUndefined; + + /// \brief A mapping from NRVO variables to the flags used to indicate + /// when the NRVO has been applied to this variable. + llvm::DenseMap<const VarDecl *, llvm::Value *> NRVOFlags; + public: /// ObjCEHValueStack - Stack of Objective-C exception values, used for /// rethrows. @@ -496,18 +502,18 @@ public: std::vector<HelperInfo> *); llvm::Function *GenerateBlockFunction(const BlockExpr *BExpr, - const BlockInfo& Info, + CGBlockInfo &Info, const Decl *OuterFuncDecl, - llvm::DenseMap<const Decl*, llvm::Value*> ldm, - CharUnits &Size, CharUnits &Align, - llvm::SmallVector<const Expr *, 8> &subBlockDeclRefDecls, - bool &subBlockHasCopyDispose); + llvm::DenseMap<const Decl*, llvm::Value*> ldm); - void BlockForwardSelf(); llvm::Value *LoadBlockStruct(); - CharUnits AllocateBlockDecl(const BlockDeclRefExpr *E); - llvm::Value *GetAddrOfBlockDecl(const BlockDeclRefExpr *E); + void AllocateBlockCXXThisPointer(const CXXThisExpr *E); + void AllocateBlockDecl(const BlockDeclRefExpr *E); + llvm::Value *GetAddrOfBlockDecl(const BlockDeclRefExpr *E) { + return GetAddrOfBlockDecl(E->getDecl(), E->isByRef()); + } + llvm::Value *GetAddrOfBlockDecl(const ValueDecl *D, bool ByRef); const llvm::Type *BuildByRefType(const ValueDecl *D); void GenerateCode(GlobalDecl GD, llvm::Function *Fn); @@ -531,7 +537,8 @@ public: /// GenerateThunk - Generate a thunk for the given method. void GenerateThunk(llvm::Function *Fn, GlobalDecl GD, const ThunkInfo &Thunk); - void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type); + void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type, + FunctionArgList &Args); /// InitializeVTablePointer - Initialize the vtable pointer of the given /// subobject. @@ -554,8 +561,6 @@ public: void InitializeVTablePointers(const CXXRecordDecl *ClassDecl); - void SynthesizeCXXCopyConstructor(const FunctionArgList &Args); - /// EmitDtorEpilogue - Emit all code that comes at the end of class's /// destructor. This is to call destructors on members and base classes in /// reverse order of their construction. @@ -725,8 +730,6 @@ public: void EmitAggregateCopy(llvm::Value *DestPtr, llvm::Value *SrcPtr, QualType EltTy, bool isVolatile=false); - void EmitAggregateClear(llvm::Value *DestPtr, QualType Ty); - /// StartBlock - Start new block named N. If insert block is a dummy block /// then reuse it. void StartBlock(const char *N); @@ -744,8 +747,10 @@ public: llvm::BlockAddress *GetAddrOfLabel(const LabelStmt *L); llvm::BasicBlock *GetIndirectGotoBlock(); - /// EmitMemSetToZero - Generate code to memset a value of the given type to 0. - void EmitMemSetToZero(llvm::Value *DestPtr, QualType Ty); + /// EmitNullInitialization - Generate code to set a value of the given type to + /// null, If the type contains data member pointers, they will be initialized + /// to -1 in accordance with the Itanium C++ ABI. + void EmitNullInitialization(llvm::Value *DestPtr, QualType Ty); // EmitVAArg - Generate code to get an argument from the passed in pointer // and update it accordingly. The return value is a pointer to the argument. @@ -802,14 +807,6 @@ public: const CXXRecordDecl *ClassDecl, const CXXRecordDecl *BaseClassDecl); - void EmitClassAggrMemberwiseCopy(llvm::Value *DestValue, - llvm::Value *SrcValue, - const ConstantArrayType *Array, - const CXXRecordDecl *ClassDecl); - - void EmitClassMemberwiseCopy(llvm::Value *DestValue, llvm::Value *SrcValue, - const CXXRecordDecl *ClassDecl); - void EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, CXXCtorType CtorType, const FunctionArgList &Args); @@ -940,6 +937,7 @@ public: void EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S); void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S); + llvm::Constant *getUnwindResumeOrRethrowFn(); struct CXXTryStmtInfo { llvm::BasicBlock *SavedLandingPad; llvm::BasicBlock *HandlerBlock; @@ -1056,6 +1054,9 @@ public: llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar); + LValue EmitLValueForAnonRecordField(llvm::Value* Base, + const FieldDecl* Field, + unsigned CVRQualifiers); LValue EmitLValueForField(llvm::Value* Base, const FieldDecl* Field, unsigned CVRQualifiers); @@ -1151,9 +1152,12 @@ public: llvm::Value *EmitObjCProtocolExpr(const ObjCProtocolExpr *E); llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E); llvm::Value *EmitObjCSelectorExpr(const ObjCSelectorExpr *E); - RValue EmitObjCMessageExpr(const ObjCMessageExpr *E); - RValue EmitObjCPropertyGet(const Expr *E); - RValue EmitObjCSuperPropertyGet(const Expr *Exp, const Selector &S); + RValue EmitObjCMessageExpr(const ObjCMessageExpr *E, + ReturnValueSlot Return = ReturnValueSlot()); + RValue EmitObjCPropertyGet(const Expr *E, + ReturnValueSlot Return = ReturnValueSlot()); + RValue EmitObjCSuperPropertyGet(const Expr *Exp, const Selector &S, + ReturnValueSlot Return = ReturnValueSlot()); void EmitObjCPropertySet(const Expr *E, RValue Src); void EmitObjCSuperPropertySet(const Expr *E, const Selector &S, RValue Src); @@ -1298,6 +1302,11 @@ public: /// EmitCallArg - Emit a single call argument. RValue EmitCallArg(const Expr *E, QualType ArgType); + /// EmitDelegateCallArg - We are performing a delegate call; that + /// is, the current function is delegating to another one. Produce + /// a r-value suitable for passing the given parameter. + RValue EmitDelegateCallArg(const VarDecl *Param); + private: void EmitReturnOfRValue(RValue RV, QualType Ty); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index cc90a28..103024c 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -48,7 +48,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, Features(C.getLangOptions()), CodeGenOpts(CGO), TheModule(M), TheTargetData(TD), TheTargetCodeGenInfo(0), Diags(diags), Types(C, M, TD, getTargetCodeGenInfo().getABIInfo()), - MangleCtx(C, diags), VTables(*this), Runtime(0), + VTables(*this), Runtime(0), ABI(0), CFConstantStringClassRef(0), NSConstantStringClassRef(0), VMContext(M.getContext()) { @@ -62,12 +62,17 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, else Runtime = CreateMacObjCRuntime(*this); + if (!Features.CPlusPlus) + ABI = 0; + else createCXXABI(); + // If debug info generation is enabled, create the CGDebugInfo object. DebugInfo = CodeGenOpts.DebugInfo ? new CGDebugInfo(*this) : 0; } CodeGenModule::~CodeGenModule() { delete Runtime; + delete ABI; delete DebugInfo; } @@ -80,6 +85,11 @@ void CodeGenModule::createObjCRuntime() { Runtime = CreateMacObjCRuntime(*this); } +void CodeGenModule::createCXXABI() { + // For now, just create an Itanium ABI. + ABI = CreateItaniumCXXABI(*this); +} + void CodeGenModule::Release() { EmitDeferred(); EmitCXXGlobalInitFunc(); @@ -316,17 +326,6 @@ GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD, == TSK_ExplicitInstantiationDeclaration) return CodeGenModule::GVA_C99Inline; - // If this is a virtual method and its class has a key method in another - // translation unit, we know that this method will be present in that - // translation unit. In this translation unit we will use this method - // only for inlining and analysis. This is the semantics of c99 inline. - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { - const CXXRecordDecl *RD = MD->getParent(); - if (MD->isVirtual() && - CodeGenVTables::isKeyFunctionInAnotherTU(Context, RD)) - return CodeGenModule::GVA_C99Inline; - } - return CodeGenModule::GVA_CXXInline; } @@ -372,7 +371,6 @@ CodeGenModule::getFunctionLinkage(const FunctionDecl *D) { /// variables (these details are set in EmitGlobalVarDefinition for variables). void CodeGenModule::SetFunctionDefinitionAttributes(const FunctionDecl *D, llvm::GlobalValue *GV) { - GV->setLinkage(getFunctionLinkage(D)); SetCommonAttributes(D, GV); } @@ -515,9 +513,14 @@ void CodeGenModule::EmitDeferred() { GlobalDecl D = DeferredDeclsToEmit.back(); DeferredDeclsToEmit.pop_back(); - // Look it up to see if it was defined with a stronger definition (e.g. an - // extern inline function with a strong function redefinition). If so, - // just ignore the deferred decl. + // Check to see if we've already emitted this. This is necessary + // for a couple of reasons: first, decls can end up in the + // deferred-decls queue multiple times, and second, decls can end + // up with definitions in unusual ways (e.g. by an extern inline + // function acquiring a strong function redefinition). Just + // ignore these cases. + // + // TODO: That said, looking this up multiple times is very wasteful. MangleBuffer Name; getMangledName(Name, D); llvm::GlobalValue *CGRef = GetGlobalValue(Name); @@ -526,6 +529,11 @@ void CodeGenModule::EmitDeferred() { if (!CGRef->isDeclaration()) continue; + // GlobalAlias::isDeclaration() defers to the aliasee, but for our + // purposes an alias counts as a definition. + if (isa<llvm::GlobalAlias>(CGRef)) + continue; + // Otherwise, emit the definition and move on to the next one. EmitGlobalDefinition(D); } @@ -727,8 +735,9 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) { Context.getSourceManager(), "Generating code for declaration"); - if (isa<CXXMethodDecl>(D)) - getVTables().EmitVTableRelatedData(GD); + if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) + if (Method->isVirtual()) + getVTables().EmitThunks(GD); if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D)) return EmitCXXConstructor(CD, GD.getCtorType()); @@ -984,6 +993,11 @@ void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) { EmitGlobalVarDefinition(D); } +void CodeGenModule::EmitVTable(CXXRecordDecl *Class, bool DefinitionRequired) { + if (DefinitionRequired) + getVTables().GenerateClassData(getVTableLinkage(Class), Class); +} + llvm::GlobalVariable::LinkageTypes CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) { if (RD->isInAnonymousNamespace() || !RD->hasLinkage()) @@ -1101,10 +1115,12 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { assert(!ASTTy->isIncompleteType() && "Unexpected incomplete type"); Init = EmitNullConstant(D->getType()); } else { - Init = EmitConstantExpr(InitExpr, D->getType()); - + Init = EmitConstantExpr(InitExpr, D->getType()); if (!Init) { QualType T = InitExpr->getType(); + if (D->getType()->isReferenceType()) + T = D->getType(); + if (getLangOptions().CPlusPlus) { EmitCXXGlobalVarDeclInitFunc(D); Init = EmitNullConstant(T); @@ -1333,6 +1349,7 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) { } llvm::Function *Fn = cast<llvm::Function>(Entry); + setFunctionLinkage(D, Fn); CodeGenFunction(*this).GenerateCode(D, Fn); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 93d8ddf..319744c4 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -22,6 +22,7 @@ #include "CGCall.h" #include "CGCXX.h" #include "CGVTables.h" +#include "CGCXXABI.h" #include "CodeGenTypes.h" #include "GlobalDecl.h" #include "Mangle.h" @@ -90,13 +91,13 @@ class CodeGenModule : public BlockModule { mutable const TargetCodeGenInfo *TheTargetCodeGenInfo; Diagnostic &Diags; CodeGenTypes Types; - MangleContext MangleCtx; /// VTables - Holds information about C++ vtables. CodeGenVTables VTables; friend class CodeGenVTables; CGObjCRuntime* Runtime; + CXXABI* ABI; CGDebugInfo* DebugInfo; // WeakRefReferences - A set of references that have only been seen via @@ -153,6 +154,8 @@ class CodeGenModule : public BlockModule { /// Lazily create the Objective-C runtime void createObjCRuntime(); + /// Lazily create the C++ ABI + void createCXXABI(); llvm::LLVMContext &VMContext; public: @@ -175,6 +178,16 @@ public: /// been configured. bool hasObjCRuntime() { return !!Runtime; } + /// getCXXABI() - Return a reference to the configured + /// C++ ABI. + CXXABI &getCXXABI() { + if (!ABI) createCXXABI(); + return *ABI; + } + + /// hasCXXABI() - Return true iff a C++ ABI has been configured. + bool hasCXXABI() { return !!ABI; } + llvm::Value *getStaticLocalDeclAddress(const VarDecl *VD) { return StaticLocalDeclMap[VD]; } @@ -189,7 +202,10 @@ public: const LangOptions &getLangOptions() const { return Features; } llvm::Module &getModule() const { return TheModule; } CodeGenTypes &getTypes() { return Types; } - MangleContext &getMangleContext() { return MangleCtx; } + MangleContext &getMangleContext() { + if (!ABI) createCXXABI(); + return ABI->getMangleContext(); + } CodeGenVTables &getVTables() { return VTables; } Diagnostic &getDiags() const { return Diags; } const llvm::TargetData &getTargetData() const { return TheTargetData; } @@ -413,6 +429,7 @@ public: void getMangledName(MangleBuffer &Buffer, GlobalDecl D); void getMangledName(MangleBuffer &Buffer, const NamedDecl *ND); + void getMangledName(MangleBuffer &Buffer, const BlockDecl *BD); void getMangledCXXCtorName(MangleBuffer &Buffer, const CXXConstructorDecl *D, CXXCtorType Type); @@ -422,6 +439,8 @@ public: void EmitTentativeDefinition(const VarDecl *D); + void EmitVTable(CXXRecordDecl *Class, bool DefinitionRequired); + enum GVALinkage { GVA_Internal, GVA_C99Inline, @@ -434,6 +453,10 @@ public: llvm::GlobalVariable::LinkageTypes getFunctionLinkage(const FunctionDecl *FD); + void setFunctionLinkage(const FunctionDecl *FD, llvm::GlobalValue *V) { + V->setLinkage(getFunctionLinkage(FD)); + } + /// getVTableLinkage - Return the appropriate linkage for the vtable, VTT, /// and type information of the given class. static llvm::GlobalVariable::LinkageTypes diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index f53dd83..a46dc72 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -322,6 +322,9 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { true); } + case Type::ObjCObject: + return ConvertTypeRecursive(cast<ObjCObjectType>(Ty).getBaseType()); + case Type::ObjCInterface: { // Objective-C interfaces are always opaque (outside of the // runtime, which can do whatever it likes); we never refine @@ -467,3 +470,32 @@ CodeGenTypes::getCGRecordLayout(const RecordDecl *TD) const { assert(Layout && "Unable to find record layout information for type"); return *Layout; } + +bool CodeGenTypes::ContainsPointerToDataMember(QualType T) { + // No need to check for member pointers when not compiling C++. + if (!Context.getLangOptions().CPlusPlus) + return false; + + T = Context.getBaseElementType(T); + + if (const RecordType *RT = T->getAs<RecordType>()) { + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + + return ContainsPointerToDataMember(RD); + } + + if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) + return !MPT->getPointeeType()->isFunctionType(); + + return false; +} + +bool CodeGenTypes::ContainsPointerToDataMember(const CXXRecordDecl *RD) { + + // FIXME: It would be better if there was a way to explicitly compute the + // record layout instead of converting to a type. + ConvertTagDeclType(RD); + + const CGRecordLayout &Layout = getCGRecordLayout(RD); + return Layout.containsPointerToDataMember(); +} diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h index 10e71e2..fc28c3a 100644 --- a/lib/CodeGen/CodeGenTypes.h +++ b/lib/CodeGen/CodeGenTypes.h @@ -186,6 +186,14 @@ public: // These are internal details of CGT that shouldn't be used externally. /// argument types it would be passed as on the provided vector \arg /// ArgTys. See ABIArgInfo::Expand. void GetExpandedTypes(QualType Ty, std::vector<const llvm::Type*> &ArgTys); + + /// ContainsPointerToDataMember - Return whether the given type contains a + /// pointer to a data member. + bool ContainsPointerToDataMember(QualType T); + + /// ContainsPointerToDataMember - Return whether the record decl contains a + /// pointer to a data member. + bool ContainsPointerToDataMember(const CXXRecordDecl *RD); }; } // end namespace CodeGen diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp new file mode 100644 index 0000000..98db75e --- /dev/null +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -0,0 +1,39 @@ +//===------- ItaniumCXXABI.cpp - Emit LLVM Code from ASTs for a Module ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This provides C++ code generation targetting the Itanium C++ ABI. The class +// in this file generates structures that follow the Itanium C++ ABI, which is +// documented at: +// http://www.codesourcery.com/public/cxx-abi/abi.html +// http://www.codesourcery.com/public/cxx-abi/abi-eh.html +//===----------------------------------------------------------------------===// + +#include "CGCXXABI.h" +#include "CodeGenModule.h" +#include "Mangle.h" + +using namespace clang; + +namespace { +class ItaniumCXXABI : public CodeGen::CXXABI { + CodeGen::MangleContext MangleCtx; +public: + ItaniumCXXABI(CodeGen::CodeGenModule &CGM) : + MangleCtx(CGM.getContext(), CGM.getDiags()) { } + + CodeGen::MangleContext &getMangleContext() { + return MangleCtx; + } +}; +} + +CodeGen::CXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) { + return new ItaniumCXXABI(CGM); +} + diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 8658cfb..6c2a648 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -36,6 +36,57 @@ using namespace clang; using namespace CodeGen; +MiscNameMangler::MiscNameMangler(MangleContext &C, + llvm::SmallVectorImpl<char> &Res) + : Context(C), Out(Res) { } + +void MiscNameMangler::mangleBlock(const BlockDecl *BD) { + // Mangle the context of the block. + // FIXME: We currently mimic GCC's mangling scheme, which leaves much to be + // desired. Come up with a better mangling scheme. + const DeclContext *DC = BD->getDeclContext(); + while (isa<BlockDecl>(DC) || isa<EnumDecl>(DC)) + DC = DC->getParent(); + if (DC->isFunctionOrMethod()) { + Out << "__"; + if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) + mangleObjCMethodName(Method); + else { + const NamedDecl *ND = cast<NamedDecl>(DC); + if (IdentifierInfo *II = ND->getIdentifier()) + Out << II->getName(); + else { + // FIXME: We were doing a mangleUnqualifiedName() before, but that's + // a private member of a class that will soon itself be private to the + // Itanium C++ ABI object. What should we do now? Right now, I'm just + // calling the mangleName() method on the MangleContext; is there a + // better way? + llvm::SmallString<64> Buffer; + Context.mangleName(ND, Buffer); + Out << Buffer; + } + } + Out << "_block_invoke_" << Context.getBlockId(BD, true); + } else { + Out << "__block_global_" << Context.getBlockId(BD, false); + } +} + +void MiscNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) { + llvm::SmallString<64> Name; + llvm::raw_svector_ostream OS(Name); + + const ObjCContainerDecl *CD = + dyn_cast<ObjCContainerDecl>(MD->getDeclContext()); + assert (CD && "Missing container decl in GetNameForMethod"); + OS << (MD->isInstanceMethod() ? '-' : '+') << '[' << CD->getName(); + if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(CD)) + OS << '(' << CID << ')'; + OS << ' ' << MD->getSelector().getAsString() << ']'; + + Out << OS.str().size() << OS.str(); +} + namespace { static const DeclContext *GetLocalClassFunctionDeclContext( @@ -107,7 +158,8 @@ public: void mangleFunctionEncoding(const FunctionDecl *FD); void mangleName(const NamedDecl *ND); void mangleType(QualType T); - + void mangleNameOrStandardSubstitution(const NamedDecl *ND); + private: bool mangleSubstitution(const NamedDecl *ND); bool mangleSubstitution(QualType T); @@ -714,8 +766,9 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { const DeclContext *DC = ND->getDeclContext(); Out << 'Z'; - if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) - mangleObjCMethodName(MD); + if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) { + mangleObjCMethodName(MD); + } else if (const DeclContext *CDC = GetLocalClassFunctionDeclContext(DC)) { mangleFunctionEncoding(cast<FunctionDecl>(CDC)); Out << 'E'; @@ -752,6 +805,14 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { if (DC->isTranslationUnit()) return; + if (const BlockDecl *Block = dyn_cast<BlockDecl>(DC)) { + manglePrefix(DC->getParent(), NoFunction); + llvm::SmallString<64> Name; + Context.mangleBlock(Block, Name); + Out << Name.size() << Name; + return; + } + if (mangleSubstitution(cast<NamedDecl>(DC))) return; @@ -762,8 +823,10 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { TemplateParameterList *TemplateParameters = TD->getTemplateParameters(); mangleTemplateArgs(*TemplateParameters, *TemplateArgs); } - else if(NoFunction && isa<FunctionDecl>(DC)) + else if(NoFunction && (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC))) return; + else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) + mangleObjCMethodName(Method); else { manglePrefix(DC->getParent(), NoFunction); mangleUnqualifiedName(cast<NamedDecl>(DC)); @@ -942,18 +1005,9 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { } void CXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) { - llvm::SmallString<64> Name; - llvm::raw_svector_ostream OS(Name); - - const ObjCContainerDecl *CD = - dyn_cast<ObjCContainerDecl>(MD->getDeclContext()); - assert (CD && "Missing container decl in GetNameForMethod"); - OS << (MD->isInstanceMethod() ? '-' : '+') << '[' << CD->getName(); - if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(CD)) - OS << '(' << CID << ')'; - OS << ' ' << MD->getSelector().getAsString() << ']'; - - Out << OS.str().size() << OS.str(); + llvm::SmallString<64> Buffer; + MiscNameMangler(Context, Buffer).mangleObjCMethodName(MD); + Out << Buffer; } void CXXNameMangler::mangleType(QualType T) { @@ -989,6 +1043,11 @@ void CXXNameMangler::mangleType(QualType T) { addSubstitution(T); } +void CXXNameMangler::mangleNameOrStandardSubstitution(const NamedDecl *ND) { + if (!mangleStandardSubstitution(ND)) + mangleName(ND); +} + void CXXNameMangler::mangleType(const BuiltinType *T) { // <type> ::= <builtin-type> // <builtin-type> ::= v # void @@ -1206,6 +1265,12 @@ void CXXNameMangler::mangleType(const ObjCInterfaceType *T) { mangleSourceName(T->getDecl()->getIdentifier()); } +void CXXNameMangler::mangleType(const ObjCObjectType *T) { + // We don't allow overloading by different protocol qualification, + // so mangling them isn't necessary. + mangleType(T->getBaseType()); +} + void CXXNameMangler::mangleType(const BlockPointerType *T) { Out << "U13block_pointer"; mangleType(T->getPointeeType()); @@ -1369,7 +1434,7 @@ void CXXNameMangler::mangleExpression(const Expr *E) { #define EXPR(Type, Base) #define STMT(Type, Base) \ case Expr::Type##Class: -#include "clang/AST/StmtNodes.def" +#include "clang/AST/StmtNodes.inc" llvm_unreachable("unexpected statement kind"); break; @@ -2027,6 +2092,12 @@ void MangleContext::mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, Mangler.mangle(D); } +void MangleContext::mangleBlock(const BlockDecl *BD, + llvm::SmallVectorImpl<char> &Res) { + MiscNameMangler Mangler(*this, Res); + Mangler.mangleBlock(BD); +} + void MangleContext::mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, llvm::SmallVectorImpl<char> &Res) { @@ -2089,7 +2160,7 @@ void MangleContext::mangleCXXVTable(const CXXRecordDecl *RD, // <special-name> ::= TV <type> # virtual table CXXNameMangler Mangler(*this, Res); Mangler.getStream() << "_ZTV"; - Mangler.mangleName(RD); + Mangler.mangleNameOrStandardSubstitution(RD); } void MangleContext::mangleCXXVTT(const CXXRecordDecl *RD, @@ -2097,7 +2168,7 @@ void MangleContext::mangleCXXVTT(const CXXRecordDecl *RD, // <special-name> ::= TT <type> # VTT structure CXXNameMangler Mangler(*this, Res); Mangler.getStream() << "_ZTT"; - Mangler.mangleName(RD); + Mangler.mangleNameOrStandardSubstitution(RD); } void MangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, @@ -2106,10 +2177,10 @@ void MangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, // <special-name> ::= TC <type> <offset number> _ <base type> CXXNameMangler Mangler(*this, Res); Mangler.getStream() << "_ZTC"; - Mangler.mangleName(RD); + Mangler.mangleNameOrStandardSubstitution(RD); Mangler.getStream() << Offset; Mangler.getStream() << '_'; - Mangler.mangleName(Type); + Mangler.mangleNameOrStandardSubstitution(Type); } void MangleContext::mangleCXXRTTI(QualType Ty, diff --git a/lib/CodeGen/Mangle.h b/lib/CodeGen/Mangle.h index da3626f..f1c5358 100644 --- a/lib/CodeGen/Mangle.h +++ b/lib/CodeGen/Mangle.h @@ -23,14 +23,17 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" namespace clang { class ASTContext; + class BlockDecl; class CXXConstructorDecl; class CXXDestructorDecl; class CXXMethodDecl; class FunctionDecl; class NamedDecl; + class ObjCMethodDecl; class VarDecl; namespace CodeGen { @@ -63,7 +66,7 @@ private: llvm::StringRef String; llvm::SmallString<256> Buffer; }; - + /// MangleContext - Context for tracking state which persists across multiple /// calls to the C++ name mangler. class MangleContext { @@ -73,6 +76,8 @@ class MangleContext { llvm::DenseMap<const TagDecl *, uint64_t> AnonStructIds; unsigned Discriminator; llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier; + llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds; + llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds; public: explicit MangleContext(ASTContext &Context, @@ -83,6 +88,8 @@ public: Diagnostic &getDiags() const { return Diags; } + void startNewFunction() { LocalBlockIds.clear(); } + uint64_t getAnonymousStructId(const TagDecl *TD) { std::pair<llvm::DenseMap<const TagDecl *, uint64_t>::iterator, bool> Result = @@ -90,31 +97,42 @@ public: return Result.first->second; } + unsigned getBlockId(const BlockDecl *BD, bool Local) { + llvm::DenseMap<const BlockDecl *, unsigned> &BlockIds + = Local? LocalBlockIds : GlobalBlockIds; + std::pair<llvm::DenseMap<const BlockDecl *, unsigned>::iterator, bool> + Result = BlockIds.insert(std::make_pair(BD, BlockIds.size())); + return Result.first->second; + } + /// @name Mangler Entry Points /// @{ bool shouldMangleDeclName(const NamedDecl *D); - - void mangleName(const NamedDecl *D, llvm::SmallVectorImpl<char> &); - void mangleThunk(const CXXMethodDecl *MD, - const ThunkInfo &Thunk, - llvm::SmallVectorImpl<char> &); - void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, - const ThisAdjustment &ThisAdjustment, + virtual void mangleName(const NamedDecl *D, llvm::SmallVectorImpl<char> &); + virtual void mangleThunk(const CXXMethodDecl *MD, + const ThunkInfo &Thunk, llvm::SmallVectorImpl<char> &); - void mangleGuardVariable(const VarDecl *D, llvm::SmallVectorImpl<char> &); - void mangleCXXVTable(const CXXRecordDecl *RD, llvm::SmallVectorImpl<char> &); - void mangleCXXVTT(const CXXRecordDecl *RD, llvm::SmallVectorImpl<char> &); - void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, - const CXXRecordDecl *Type, - llvm::SmallVectorImpl<char> &); - void mangleCXXRTTI(QualType T, llvm::SmallVectorImpl<char> &); - void mangleCXXRTTIName(QualType T, llvm::SmallVectorImpl<char> &); - void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, - llvm::SmallVectorImpl<char> &); - void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, - llvm::SmallVectorImpl<char> &); - + virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, + const ThisAdjustment &ThisAdjustment, + llvm::SmallVectorImpl<char> &); + virtual void mangleGuardVariable(const VarDecl *D, + llvm::SmallVectorImpl<char> &); + virtual void mangleCXXVTable(const CXXRecordDecl *RD, + llvm::SmallVectorImpl<char> &); + virtual void mangleCXXVTT(const CXXRecordDecl *RD, + llvm::SmallVectorImpl<char> &); + virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, + const CXXRecordDecl *Type, + llvm::SmallVectorImpl<char> &); + virtual void mangleCXXRTTI(QualType T, llvm::SmallVectorImpl<char> &); + virtual void mangleCXXRTTIName(QualType T, llvm::SmallVectorImpl<char> &); + virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, + llvm::SmallVectorImpl<char> &); + virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, + llvm::SmallVectorImpl<char> &); + void mangleBlock(const BlockDecl *BD, llvm::SmallVectorImpl<char> &); + void mangleInitDiscriminator() { Discriminator = 0; } @@ -130,7 +148,23 @@ public: } /// @} }; + +/// MiscNameMangler - Mangles Objective-C method names and blocks. +class MiscNameMangler { + MangleContext &Context; + llvm::raw_svector_ostream Out; + ASTContext &getASTContext() const { return Context.getASTContext(); } + +public: + MiscNameMangler(MangleContext &C, llvm::SmallVectorImpl<char> &Res); + + llvm::raw_svector_ostream &getStream() { return Out; } + + void mangleBlock(const BlockDecl *BD); + void mangleObjCMethodName(const ObjCMethodDecl *MD); +}; + } } diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp index 1e1edc1..9905ca6 100644 --- a/lib/CodeGen/ModuleBuilder.cpp +++ b/lib/CodeGen/ModuleBuilder.cpp @@ -89,6 +89,13 @@ namespace { Builder->EmitTentativeDefinition(D); } + + virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) { + if (Diags.hasErrorOccurred()) + return; + + Builder->EmitVTable(RD, DefinitionRequired); + } }; } diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index e1fdf86..b29d3cb 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -23,6 +23,18 @@ using namespace clang; using namespace CodeGen; +static void AssignToArrayRange(CodeGen::CGBuilderTy &Builder, + llvm::Value *Array, + llvm::Value *Value, + unsigned FirstIndex, + unsigned LastIndex) { + // Alternatively, we could emit this as a loop in the source. + for (unsigned I = FirstIndex; I <= LastIndex; ++I) { + llvm::Value *Cell = Builder.CreateConstInBoundsGEP1_32(Array, I); + Builder.CreateStore(Value, Cell); + } +} + ABIInfo::~ABIInfo() {} void ABIArgInfo::dump() const { @@ -71,6 +83,17 @@ static bool isEmptyField(ASTContext &Context, const FieldDecl *FD, while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) FT = AT->getElementType(); + const RecordType *RT = FT->getAs<RecordType>(); + if (!RT) + return false; + + // C++ record fields are never empty, at least in the Itanium ABI. + // + // FIXME: We should use a predicate for whether this behavior is true in the + // current ABI. + if (isa<CXXRecordDecl>(RT->getDecl())) + return false; + return isEmptyRecord(Context, FT, AllowArrays); } @@ -84,6 +107,14 @@ static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays) { const RecordDecl *RD = RT->getDecl(); if (RD->hasFlexibleArrayMember()) return false; + + // If this is a C++ record, check the bases first. + if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) + for (CXXRecordDecl::base_class_const_iterator i = CXXRD->bases_begin(), + e = CXXRD->bases_end(); i != e; ++i) + if (!isEmptyRecord(Context, i->getType(), true)) + return false; + for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); i != e; ++i) if (!isEmptyField(Context, *i, AllowArrays)) @@ -130,6 +161,28 @@ static const Type *isSingleElementStruct(QualType T, ASTContext &Context) { return 0; const Type *Found = 0; + + // If this is a C++ record, check the bases first. + if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) { + for (CXXRecordDecl::base_class_const_iterator i = CXXRD->bases_begin(), + e = CXXRD->bases_end(); i != e; ++i) { + // Ignore empty records. + if (isEmptyRecord(Context, i->getType(), true)) + continue; + + // If we already found an element then this isn't a single-element struct. + if (Found) + return 0; + + // If this is non-empty and not a single element struct, the composite + // cannot be a single element struct. + Found = isSingleElementStruct(i->getType(), Context); + if (!Found) + return 0; + } + } + + // Check for single element. for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); i != e; ++i) { const FieldDecl *FD = *i; @@ -164,7 +217,7 @@ static const Type *isSingleElementStruct(QualType T, ASTContext &Context) { } static bool is32Or64BitBasicType(QualType Ty, ASTContext &Context) { - if (!Ty->getAs<BuiltinType>() && !Ty->isAnyPointerType() && + if (!Ty->getAs<BuiltinType>() && !Ty->hasPointerRepresentation() && !Ty->isAnyComplexType() && !Ty->isEnumeralType() && !Ty->isBlockPointerType()) return false; @@ -212,23 +265,6 @@ static bool canExpandIndirectArgument(QualType Ty, ASTContext &Context) { return true; } -static bool typeContainsSSEVector(const RecordDecl *RD, ASTContext &Context) { - for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); - i != e; ++i) { - const FieldDecl *FD = *i; - - if (FD->getType()->isVectorType() && - Context.getTypeSize(FD->getType()) >= 128) - return true; - - if (const RecordType* RT = FD->getType()->getAs<RecordType>()) - if (typeContainsSSEVector(RT->getDecl(), Context)) - return true; - } - - return false; -} - namespace { /// DefaultABIInfo - The default implementation for ABI specific /// details. This implementation provides information which results in @@ -363,10 +399,11 @@ bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty, return true; } - // If this is a builtin, pointer, enum, or complex type, it is ok. - if (Ty->getAs<BuiltinType>() || Ty->isAnyPointerType() || + // If this is a builtin, pointer, enum, complex type, member pointer, or + // member function pointer it is ok. + if (Ty->getAs<BuiltinType>() || Ty->hasPointerRepresentation() || Ty->isAnyComplexType() || Ty->isEnumeralType() || - Ty->isBlockPointerType()) + Ty->isBlockPointerType() || Ty->isMemberPointerType()) return true; // Arrays are treated like records. @@ -596,20 +633,14 @@ bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable( // 0-7 are the eight integer registers; the order is different // on Darwin (for EH), but the range is the same. // 8 is %eip. - for (unsigned I = 0, E = 9; I != E; ++I) { - llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); - Builder.CreateStore(Four8, Slot); - } + AssignToArrayRange(Builder, Address, Four8, 0, 8); if (CGF.CGM.isTargetDarwin()) { // 12-16 are st(0..4). Not sure why we stop at 4. // These have size 16, which is sizeof(long double) on // platforms with 8-byte alignment for that type. llvm::Value *Sixteen8 = llvm::ConstantInt::get(i8, 16); - for (unsigned I = 12, E = 17; I != E; ++I) { - llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); - Builder.CreateStore(Sixteen8, Slot); - } + AssignToArrayRange(Builder, Address, Sixteen8, 12, 16); } else { // 9 is %eflags, which doesn't get a size on Darwin for some @@ -620,11 +651,8 @@ bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable( // These have size 12, which is sizeof(long double) on // platforms with 4-byte alignment for that type. llvm::Value *Twelve8 = llvm::ConstantInt::get(i8, 12); - for (unsigned I = 11, E = 17; I != E; ++I) { - llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); - Builder.CreateStore(Twelve8, Slot); - } - } + AssignToArrayRange(Builder, Address, Twelve8, 11, 16); + } return false; } @@ -733,12 +761,9 @@ public: const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8); - // 0-16 are the 16 integer registers. - // 17 is %rip. - for (unsigned I = 0, E = 17; I != E; ++I) { - llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); - Builder.CreateStore(Eight8, Slot); - } + // 0-15 are the 16 integer registers. + // 16 is %rip. + AssignToArrayRange(Builder, Address, Eight8, 0, 16); return false; } @@ -828,6 +853,11 @@ void X86_64ABIInfo::classify(QualType Ty, classify(ET->getDecl()->getIntegerType(), Context, OffsetBase, Lo, Hi); } else if (Ty->hasPointerRepresentation()) { Current = Integer; + } else if (Ty->isMemberPointerType()) { + if (Ty->isMemberFunctionPointerType()) + Lo = Hi = Integer; + else + Current = Integer; } else if (const VectorType *VT = Ty->getAs<VectorType>()) { uint64_t Size = Context.getTypeSize(VT); if (Size == 32) { @@ -1661,16 +1691,10 @@ PPC32TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, llvm::Value *Sixteen8 = llvm::ConstantInt::get(i8, 16); // 0-31: r0-31, the 4-byte general-purpose registers - for (unsigned I = 0, E = 32; I != E; ++I) { - llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); - Builder.CreateStore(Four8, Slot); - } + AssignToArrayRange(Builder, Address, Four8, 0, 31); // 32-63: fp0-31, the 8-byte floating-point registers - for (unsigned I = 32, E = 64; I != E; ++I) { - llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); - Builder.CreateStore(Eight8, Slot); - } + AssignToArrayRange(Builder, Address, Eight8, 32, 63); // 64-76 are various 4-byte special-purpose registers: // 64: mq @@ -1679,26 +1703,17 @@ PPC32TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, // 67: ap // 68-75 cr0-7 // 76: xer - for (unsigned I = 64, E = 77; I != E; ++I) { - llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); - Builder.CreateStore(Four8, Slot); - } + AssignToArrayRange(Builder, Address, Four8, 64, 76); // 77-108: v0-31, the 16-byte vector registers - for (unsigned I = 77, E = 109; I != E; ++I) { - llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); - Builder.CreateStore(Sixteen8, Slot); - } + AssignToArrayRange(Builder, Address, Sixteen8, 77, 108); // 109: vrsave // 110: vscr // 111: spe_acc // 112: spefscr // 113: sfp - for (unsigned I = 109, E = 114; I != E; ++I) { - llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); - Builder.CreateStore(Four8, Slot); - } + AssignToArrayRange(Builder, Address, Four8, 109, 113); return false; } @@ -2123,6 +2138,56 @@ void MSP430TargetCodeGenInfo::SetTargetAttributes(const Decl *D, } } +// MIPS ABI Implementation. This works for both little-endian and +// big-endian variants. +namespace { +class MIPSTargetCodeGenInfo : public TargetCodeGenInfo { +public: + MIPSTargetCodeGenInfo(): TargetCodeGenInfo(new DefaultABIInfo()) {} + + int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const { + return 29; + } + + bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const; +}; +} + +bool +MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const { + // This information comes from gcc's implementation, which seems to + // as canonical as it gets. + + CodeGen::CGBuilderTy &Builder = CGF.Builder; + llvm::LLVMContext &Context = CGF.getLLVMContext(); + + // Everything on MIPS is 4 bytes. Double-precision FP registers + // are aliased to pairs of single-precision FP registers. + const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); + llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4); + + // 0-31 are the general purpose registers, $0 - $31. + // 32-63 are the floating-point registers, $f0 - $f31. + // 64 and 65 are the multiply/divide registers, $hi and $lo. + // 66 is the (notional, I think) register for signal-handler return. + AssignToArrayRange(Builder, Address, Four8, 0, 65); + + // 67-74 are the floating-point status registers, $fcc0 - $fcc7. + // They are one bit wide and ignored here. + + // 80-111 are the coprocessor 0 registers, $c0r0 - $c0r31. + // (coprocessor 1 is the FP unit) + // 112-143 are the coprocessor 2 registers, $c2r0 - $c2r31. + // 144-175 are the coprocessor 3 registers, $c3r0 - $c3r31. + // 176-181 are the DSP accumulator registers. + AssignToArrayRange(Builder, Address, Four8, 80, 181); + + return false; +} + + const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() const { if (TheTargetCodeGenInfo) return *TheTargetCodeGenInfo; @@ -2135,6 +2200,10 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() const { default: return *(TheTargetCodeGenInfo = new DefaultTargetCodeGenInfo); + case llvm::Triple::mips: + case llvm::Triple::mipsel: + return *(TheTargetCodeGenInfo = new MIPSTargetCodeGenInfo()); + case llvm::Triple::arm: case llvm::Triple::thumb: // FIXME: We want to know the float calling convention as well. |