From: John McCall Date: Tue, 22 Feb 2011 22:38:33 +0000 (+0000) Subject: Emit the structure layout of the block literal parameter to a block X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8178df3b39ab923ff5d24538812628abee33df79;p=clang Emit the structure layout of the block literal parameter to a block invocation function into the debug info. Rather than faking up a class, which is tricky because of the custom layout we do, we just emit a struct directly from the layout information we've already got. Also, don't emit an unnecessarily parameter alloca for this "variable". git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126255 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 43a53d9bcd..c0eeb5af38 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -552,11 +552,6 @@ public: return cudaConfigureCallDecl; } - /// This gets the struct used to keep track of pointer to blocks, complete - /// with captured variables. - QualType getBlockParmType(bool BlockHasCopyDispose, - llvm::SmallVectorImpl &Layout) const; - /// This builds the struct used for __block variables. QualType BuildByRefType(llvm::StringRef DeclName, QualType Ty) const; @@ -1526,7 +1521,6 @@ private: /// \brief A counter used to uniquely identify "blocks". mutable unsigned int UniqueBlockByRefTypeID; - mutable unsigned int UniqueBlockParmTypeID; friend class DeclContext; friend class DeclarationNameTable; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 6d0b6d7ce2..0b3febd0bd 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -205,7 +205,7 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, DeclarationNames(*this), ExternalSource(0), Listener(0), PrintingPolicy(LOpts), LastSDM(0, 0), - UniqueBlockByRefTypeID(0), UniqueBlockParmTypeID(0) { + UniqueBlockByRefTypeID(0) { ObjCIdRedefinitionType = QualType(); ObjCClassRedefinitionType = QualType(); ObjCSelRedefinitionType = QualType(); @@ -3619,78 +3619,6 @@ ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) const { return getPointerType(getTagDeclType(T)); } - -QualType ASTContext::getBlockParmType( - bool BlockHasCopyDispose, - llvm::SmallVectorImpl &Layout) const { - - // FIXME: Move up - llvm::SmallString<36> Name; - llvm::raw_svector_ostream(Name) << "__block_literal_" - << ++UniqueBlockParmTypeID; - RecordDecl *T; - T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(), - &Idents.get(Name.str())); - T->startDefinition(); - QualType FieldTypes[] = { - getPointerType(VoidPtrTy), - IntTy, - IntTy, - getPointerType(VoidPtrTy), - (BlockHasCopyDispose ? - getPointerType(getBlockDescriptorExtendedType()) : - getPointerType(getBlockDescriptorType())) - }; - - const char *FieldNames[] = { - "__isa", - "__flags", - "__reserved", - "__FuncPtr", - "__descriptor" - }; - - for (size_t i = 0; i < 5; ++i) { - FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), - &Idents.get(FieldNames[i]), - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, /*Mutable=*/false); - Field->setAccess(AS_public); - T->addDecl(Field); - } - - for (unsigned i = 0; i < Layout.size(); ++i) { - const Expr *E = Layout[i]; - - QualType FieldType = E->getType(); - IdentifierInfo *FieldName = 0; - if (isa(E)) { - FieldName = &Idents.get("this"); - } else if (const BlockDeclRefExpr *BDRE = dyn_cast(E)) { - const ValueDecl *D = BDRE->getDecl(); - FieldName = D->getIdentifier(); - if (BDRE->isByRef()) - FieldType = BuildByRefType(D->getName(), FieldType); - } else { - // Padding. - assert(isa(FieldType) && - isa(E) && - !cast(E)->getDecl()->getDeclName() && - "doesn't match characteristics of padding decl"); - } - - FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), - FieldName, FieldType, /*TInfo=*/0, - /*BitWidth=*/0, /*Mutable=*/false); - Field->setAccess(AS_public); - T->addDecl(Field); - } - - T->completeDefinition(); - - return getPointerType(getTagDeclType(T)); -} - void ASTContext::setObjCFastEnumerationStateType(QualType T) { const RecordType *Rec = T->getAs(); assert(Rec && "Invalid ObjCFAstEnumerationStateType"); diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 83cca931ce..9587de223a 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -895,12 +895,9 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, QualType selfTy = getContext().VoidPtrTy; IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor"); - // FIXME: this leaks, and we only need it very temporarily. - ImplicitParamDecl *selfDecl = - ImplicitParamDecl::Create(getContext(), - const_cast(blockDecl), - SourceLocation(), II, selfTy); - args.push_back(std::make_pair(selfDecl, selfTy)); + ImplicitParamDecl selfDecl(const_cast(blockDecl), + SourceLocation(), II, selfTy); + args.push_back(std::make_pair(&selfDecl, selfTy)); // Now add the rest of the parameters. for (BlockDecl::param_const_iterator i = blockDecl->param_begin(), @@ -928,12 +925,11 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, blockInfo.getBlockExpr()->getBody()->getLocEnd()); CurFuncDecl = outerFnDecl; // StartFunction sets this to blockDecl - // Okay. Undo some of what StartFunction did. We really don't need - // an alloca for the block address; in theory we could remove it, - // but that might do unpleasant things to debug info. - llvm::AllocaInst *blockAddrAlloca - = cast(LocalDeclMap[selfDecl]); - llvm::Value *blockAddr = Builder.CreateLoad(blockAddrAlloca); + // Okay. Undo some of what StartFunction did. + + // Pull the 'self' reference out of the local decl map. + llvm::Value *blockAddr = LocalDeclMap[&selfDecl]; + LocalDeclMap.erase(&selfDecl); BlockPointer = Builder.CreateBitCast(blockAddr, blockInfo.StructureType->getPointerTo(), "block"); @@ -1010,7 +1006,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, continue; } - DI->EmitDeclareOfBlockDeclRefVariable(variable, blockAddrAlloca, + DI->EmitDeclareOfBlockDeclRefVariable(variable, BlockPointer, Builder, blockInfo); } } diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h index bee729dcce..0bc8bcaa14 100644 --- a/lib/CodeGen/CGBlocks.h +++ b/lib/CodeGen/CGBlocks.h @@ -177,7 +177,6 @@ public: const BlockExpr *Block; CharUnits BlockSize; CharUnits BlockAlign; - llvm::SmallVector BlockLayout; const Capture &getCapture(const VarDecl *var) const { llvm::DenseMap::const_iterator diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 36d37d2d52..dfd9f56b12 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -430,7 +430,7 @@ llvm::DIType CGDebugInfo::CreatePointeeType(QualType PointeeTy, llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation()); unsigned Line = getLineNumber(RD->getLocation()); llvm::DIDescriptor FDContext = - getContextDescriptor(dyn_cast(RD->getDeclContext())); + getContextDescriptor(cast(RD->getDeclContext())); if (RD->isStruct()) return DBuilder.createStructType(FDContext, RD->getName(), DefUnit, @@ -571,53 +571,63 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, return DbgTy; } +llvm::DIType CGDebugInfo::createFieldType(llvm::StringRef name, + QualType type, + Expr *bitWidth, + SourceLocation loc, + AccessSpecifier AS, + uint64_t offsetInBits, + llvm::DIFile tunit) { + llvm::DIType debugType = getOrCreateType(type, tunit); + + // Get the location for the field. + llvm::DIFile file = getOrCreateFile(loc); + unsigned line = getLineNumber(loc); + + uint64_t sizeInBits = 0; + unsigned alignInBits = 0; + if (!type->isIncompleteArrayType()) { + llvm::tie(sizeInBits, alignInBits) = CGM.getContext().getTypeInfo(type); + + if (bitWidth) + sizeInBits = bitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue(); + } + + unsigned flags = 0; + if (AS == clang::AS_private) + flags |= llvm::DIDescriptor::FlagPrivate; + else if (AS == clang::AS_protected) + flags |= llvm::DIDescriptor::FlagProtected; + + return DBuilder.createMemberType(name, file, line, sizeInBits, alignInBits, + offsetInBits, flags, debugType); +} + /// CollectRecordFields - A helper function to collect debug info for /// record fields. This is used while creating debug info entry for a Record. void CGDebugInfo:: -CollectRecordFields(const RecordDecl *RD, llvm::DIFile Unit, - llvm::SmallVectorImpl &EltTys) { - unsigned FieldNo = 0; - const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); - for (RecordDecl::field_iterator I = RD->field_begin(), - E = RD->field_end(); - I != E; ++I, ++FieldNo) { - FieldDecl *Field = *I; - llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit); - llvm::StringRef FieldName = Field->getName(); - - // Ignore unnamed fields. Do not ignore unnamed records. - if (FieldName.empty() && !isa(Field->getType())) +CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit, + llvm::SmallVectorImpl &elements) { + unsigned fieldNo = 0; + const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record); + for (RecordDecl::field_iterator I = record->field_begin(), + E = record->field_end(); + I != E; ++I, ++fieldNo) { + FieldDecl *field = *I; + + llvm::StringRef name = field->getName(); + QualType type = field->getType(); + + // Ignore unnamed fields unless they're anonymous structs/unions. + if (name.empty() && !type->isRecordType()) continue; - // Get the location for the field. - llvm::DIFile FieldDefUnit = getOrCreateFile(Field->getLocation()); - unsigned FieldLine = getLineNumber(Field->getLocation()); - QualType FType = Field->getType(); - uint64_t FieldSize = 0; - unsigned FieldAlign = 0; - if (!FType->isIncompleteArrayType()) { - - // Bit size, align and offset of the type. - FieldSize = CGM.getContext().getTypeSize(FType); - Expr *BitWidth = Field->getBitWidth(); - if (BitWidth) - FieldSize = BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue(); - FieldAlign = CGM.getContext().getTypeAlign(FType); - } - - uint64_t FieldOffset = RL.getFieldOffset(FieldNo); - - unsigned Flags = 0; - AccessSpecifier Access = I->getAccess(); - if (Access == clang::AS_private) - Flags |= llvm::DIDescriptor::FlagPrivate; - else if (Access == clang::AS_protected) - Flags |= llvm::DIDescriptor::FlagProtected; + llvm::DIType fieldType + = createFieldType(name, type, field->getBitWidth(), + field->getLocation(), field->getAccess(), + layout.getFieldOffset(fieldNo), tunit); - FieldTy = DBuilder.createMemberType(FieldName, FieldDefUnit, - FieldLine, FieldSize, FieldAlign, - FieldOffset, Flags, FieldTy); - EltTys.push_back(FieldTy); + elements.push_back(fieldType); } } @@ -902,7 +912,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { // may refer to the forward decl if the struct is recursive) and replace all // uses of the forward declaration with the final definition. llvm::DIDescriptor FDContext = - getContextDescriptor(dyn_cast(RD->getDeclContext())); + getContextDescriptor(cast(RD->getDeclContext())); // If this is just a forward declaration, construct an appropriately // marked node and just return it. @@ -994,7 +1004,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { RegionMap.erase(RI); llvm::DIDescriptor RDContext = - getContextDescriptor(dyn_cast(RD->getDeclContext())); + getContextDescriptor(cast(RD->getDeclContext())); llvm::StringRef RDName = RD->getName(); uint64_t Size = CGM.getContext().getTypeSize(Ty); uint64_t Align = CGM.getContext().getTypeAlign(Ty); @@ -1329,7 +1339,7 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) { Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl()); } llvm::DIDescriptor EnumContext = - getContextDescriptor(dyn_cast(ED->getDeclContext())); + getContextDescriptor(cast(ED->getDeclContext())); llvm::DIType DbgTy = DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit, Line, Size, Align, EltArray); @@ -1827,33 +1837,34 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, // If VD is an anonymous union then Storage represents value for // all union fields. - if (const RecordType *RT = dyn_cast(VD->getType())) - if (const RecordDecl *RD = dyn_cast(RT->getDecl())) - if (RD->isUnion()) { - for (RecordDecl::field_iterator I = RD->field_begin(), - E = RD->field_end(); - I != E; ++I) { - FieldDecl *Field = *I; - llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit); - llvm::StringRef FieldName = Field->getName(); + if (const RecordType *RT = dyn_cast(VD->getType())) { + const RecordDecl *RD = cast(RT->getDecl()); + if (RD->isUnion()) { + for (RecordDecl::field_iterator I = RD->field_begin(), + E = RD->field_end(); + I != E; ++I) { + FieldDecl *Field = *I; + llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit); + llvm::StringRef FieldName = Field->getName(); - // Ignore unnamed fields. Do not ignore unnamed records. - if (FieldName.empty() && !isa(Field->getType())) - continue; + // Ignore unnamed fields. Do not ignore unnamed records. + if (FieldName.empty() && !isa(Field->getType())) + continue; - // Use VarDecl's Tag, Scope and Line number. - llvm::DIVariable D = - DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope), - FieldName, Unit, Line, FieldTy, - CGM.getLangOptions().Optimize, Flags); + // Use VarDecl's Tag, Scope and Line number. + llvm::DIVariable D = + DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope), + FieldName, Unit, Line, FieldTy, + CGM.getLangOptions().Optimize, Flags); - // Insert an llvm.dbg.declare into the current block. - llvm::Instruction *Call = - DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock()); + // Insert an llvm.dbg.declare into the current block. + llvm::Instruction *Call = + DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock()); - Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope)); - } + Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope)); } + } + } } /// EmitDeclare - Emit local variable declaration debug info. @@ -1887,7 +1898,6 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, llvm::SmallVector addr; const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(CGM.getLLVMContext()); - addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref)); addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity())); if (isByRef) { @@ -1936,7 +1946,146 @@ void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI, EmitDeclare(VD, llvm::dwarf::DW_TAG_arg_variable, AI, Builder); } +namespace { + struct BlockLayoutChunk { + uint64_t OffsetInBits; + const BlockDecl::Capture *Capture; + }; + bool operator<(const BlockLayoutChunk &l, const BlockLayoutChunk &r) { + return l.OffsetInBits < r.OffsetInBits; + } +} + +void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, + llvm::Value *addr, + CGBuilderTy &Builder) { + ASTContext &C = CGM.getContext(); + const BlockDecl *blockDecl = block.getBlockDecl(); + + // Collect some general information about the block's location. + SourceLocation loc = blockDecl->getCaretLocation(); + llvm::DIFile tunit = getOrCreateFile(loc); + unsigned line = getLineNumber(loc); + unsigned column = getColumnNumber(loc); + + // Build the debug-info type for the block literal. + llvm::DIDescriptor enclosingContext = + getContextDescriptor(cast(blockDecl->getDeclContext())); + + const llvm::StructLayout *blockLayout = + CGM.getTargetData().getStructLayout(block.StructureType); + + llvm::SmallVector fields; + fields.push_back(createFieldType("__isa", C.VoidPtrTy, 0, loc, AS_public, + blockLayout->getElementOffsetInBits(0), + tunit)); + fields.push_back(createFieldType("__flags", C.IntTy, 0, loc, AS_public, + blockLayout->getElementOffsetInBits(1), + tunit)); + fields.push_back(createFieldType("__reserved", C.IntTy, 0, loc, AS_public, + blockLayout->getElementOffsetInBits(2), + tunit)); + fields.push_back(createFieldType("__FuncPtr", C.VoidPtrTy, 0, loc, AS_public, + blockLayout->getElementOffsetInBits(3), + tunit)); + fields.push_back(createFieldType("__descriptor", + C.getPointerType(block.NeedsCopyDispose ? + C.getBlockDescriptorExtendedType() : + C.getBlockDescriptorType()), + 0, loc, AS_public, + blockLayout->getElementOffsetInBits(4), + tunit)); + + // We want to sort the captures by offset, not because DWARF + // requires this, but because we're paranoid about debuggers. + llvm::SmallVector chunks; + + // 'this' capture. + if (blockDecl->capturesCXXThis()) { + BlockLayoutChunk chunk; + chunk.OffsetInBits = + blockLayout->getElementOffsetInBits(block.CXXThisIndex); + chunk.Capture = 0; + chunks.push_back(chunk); + } + + // Variable captures. + for (BlockDecl::capture_const_iterator + i = blockDecl->capture_begin(), e = blockDecl->capture_end(); + i != e; ++i) { + const BlockDecl::Capture &capture = *i; + const VarDecl *variable = capture.getVariable(); + const CGBlockInfo::Capture &captureInfo = block.getCapture(variable); + // Ignore constant captures. + if (captureInfo.isConstant()) + continue; + + BlockLayoutChunk chunk; + chunk.OffsetInBits = + blockLayout->getElementOffsetInBits(captureInfo.getIndex()); + chunk.Capture = &capture; + chunks.push_back(chunk); + } + + // Sort by offset. + llvm::array_pod_sort(chunks.begin(), chunks.end()); + + for (llvm::SmallVectorImpl::iterator + i = chunks.begin(), e = chunks.end(); i != e; ++i) { + uint64_t offsetInBits = i->OffsetInBits; + const BlockDecl::Capture *capture = i->Capture; + + // If we have a null capture, this must be the C++ 'this' capture. + if (!capture) { + const CXXMethodDecl *method = + cast(blockDecl->getNonClosureContext()); + QualType type = method->getThisType(C); + + fields.push_back(createFieldType("this", type, 0, loc, AS_public, + offsetInBits, tunit)); + continue; + } + + const VarDecl *variable = capture->getVariable(); + QualType type = (capture->isByRef() ? C.VoidPtrTy : variable->getType()); + llvm::StringRef name = variable->getName(); + fields.push_back(createFieldType(name, type, 0, loc, AS_public, + offsetInBits, tunit)); + } + + llvm::SmallString<36> typeName; + llvm::raw_svector_ostream(typeName) + << "__block_literal_" << CGM.getUniqueBlockCount(); + + llvm::DIArray fieldsArray = + DBuilder.getOrCreateArray(fields.data(), fields.size()); + + llvm::DIType type = + DBuilder.createStructType(tunit, typeName.str(), tunit, line, + CGM.getContext().toBits(block.BlockSize), + CGM.getContext().toBits(block.BlockAlign), + 0, fieldsArray); + type = DBuilder.createPointerType(type, CGM.PointerWidthInBits); + + // Get overall information about the block. + unsigned flags = llvm::DIDescriptor::FlagArtificial; + llvm::MDNode *scope = RegionStack.back(); + llvm::StringRef name = ".block_descriptor"; + + // Create the descriptor for the parameter. + llvm::DIVariable debugVar = + DBuilder.createLocalVariable(llvm::dwarf::DW_TAG_arg_variable, + llvm::DIDescriptor(scope), + name, tunit, line, type, + CGM.getLangOptions().Optimize, flags); + + // Insert an llvm.dbg.value into the current block. + llvm::Instruction *declare = + DBuilder.insertDbgValueIntrinsic(addr, 0, debugVar, + Builder.GetInsertBlock()); + declare->setDebugLoc(llvm::DebugLoc::get(line, column, scope)); +} /// EmitGlobalVariable - Emit information about a global variable. void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index 6a9ab9c58b..a39078860f 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -123,7 +123,10 @@ class CGDebugInfo { llvm::SmallVectorImpl &EltTys, llvm::DIType RecordTy); - + llvm::DIType createFieldType(llvm::StringRef name, QualType type, + Expr *bitWidth, SourceLocation loc, + AccessSpecifier AS, uint64_t offsetInBits, + llvm::DIFile tunit); void CollectRecordFields(const RecordDecl *Decl, llvm::DIFile F, llvm::SmallVectorImpl &E); @@ -180,6 +183,13 @@ public: void EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI, CGBuilderTy &Builder); + /// EmitDeclareOfBlockLiteralArgVariable - Emit call to + /// llvm.dbg.declare for the block-literal argument to a block + /// invocation function. + void EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, + llvm::Value *addr, + CGBuilderTy &Builder); + /// EmitGlobalVariable - Emit information about a global variable. void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl); diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index d44d2aabd2..844b1e37b0 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -1004,6 +1004,24 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) { // FIXME: Why isn't ImplicitParamDecl a ParmVarDecl? assert((isa(D) || isa(D)) && "Invalid argument to EmitParmDecl"); + + Arg->setName(D.getName()); + + // Use better IR generation for certain implicit parameters. + if (isa(D)) { + // The only implicit argument a block has is its literal. + if (BlockInfo) { + LocalDeclMap[&D] = Arg; + + if (CGDebugInfo *DI = getDebugInfo()) { + DI->setLocation(D.getLocation()); + DI->EmitDeclareOfBlockLiteralArgVariable(*BlockInfo, Arg, Builder); + } + + return; + } + } + QualType Ty = D.getType(); llvm::Value *DeclPtr; @@ -1020,7 +1038,6 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) { getContext().getDeclAlign(&D).getQuantity(), Ty, CGM.getTBAAInfo(Ty)); } - Arg->setName(D.getName()); llvm::Value *&DMEntry = LocalDeclMap[&D]; assert(DMEntry == 0 && "Decl already exists in localdeclmap!"); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index f1206a71f0..1528e4b4a8 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -389,8 +389,8 @@ public: unsigned Align, const VarDecl *variable); - /// getGlobalUniqueCount - Fetches the global unique block count. - int getGlobalUniqueCount() { return ++Block.GlobalUniqueCount; } + /// getUniqueBlockCount - Fetches the global unique block count. + int getUniqueBlockCount() { return ++Block.GlobalUniqueCount; } /// getBlockDescriptorType - Fetches the type of a generic block /// descriptor.