diff options
author | Shiva Chen <shiva0217@gmail.com> | 2018-05-09 02:40:45 +0000 |
---|---|---|
committer | Shiva Chen <shiva0217@gmail.com> | 2018-05-09 02:40:45 +0000 |
commit | 2c864551df3945f50e1780b2f2c880ec358ae715 (patch) | |
tree | d82705cf2fd8d7508726df36d2034176d901c2f2 /llvm/lib | |
parent | 49914cc807a933f3bafd61b88248e75a90101333 (diff) | |
download | bcm5719-llvm-2c864551df3945f50e1780b2f2c880ec358ae715.tar.gz bcm5719-llvm-2c864551df3945f50e1780b2f2c880ec358ae715.zip |
[DebugInfo] Add DILabel metadata and intrinsic llvm.dbg.label.
In order to set breakpoints on labels and list source code around
labels, we need collect debug information for labels, i.e., label
name, the function label belong, line number in the file, and the
address label located. In order to keep these information in LLVM
IR and to allow backend to generate debug information correctly.
We create a new kind of metadata for labels, DILabel. The format
of DILabel is
!DILabel(scope: !1, name: "foo", file: !2, line: 3)
We hope to keep debug information as much as possible even the
code is optimized. So, we create a new kind of intrinsic for label
metadata to avoid the metadata is eliminated with basic block.
The intrinsic will keep existing if we keep it from optimized out.
The format of the intrinsic is
llvm.dbg.label(metadata !1)
It has only one argument, that is the DILabel metadata. The
intrinsic will follow the label immediately. Backend could get the
label metadata through the intrinsic's parameter.
We also create DIBuilder API for labels to be used by Frontend.
Frontend could use createLabel() to allocate DILabel objects, and use
insertLabel() to insert llvm.dbg.label intrinsic in LLVM IR.
Differential Revision: https://reviews.llvm.org/D45024
Patch by Hsiangkai Wang.
llvm-svn: 331841
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Analysis/ObjCARCInstKind.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLParser.cpp | 22 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 17 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 17 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 28 | ||||
-rw-r--r-- | llvm/lib/CodeGen/IntrinsicLowering.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/IR/AsmWriter.cpp | 14 | ||||
-rw-r--r-- | llvm/lib/IR/DIBuilder.cpp | 67 | ||||
-rw-r--r-- | llvm/lib/IR/DebugInfo.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/IR/DebugInfoMetadata.cpp | 20 | ||||
-rw-r--r-- | llvm/lib/IR/LLVMContextImpl.h | 33 | ||||
-rw-r--r-- | llvm/lib/IR/Verifier.cpp | 61 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/Local.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 1 |
15 files changed, 250 insertions, 40 deletions
diff --git a/llvm/lib/Analysis/ObjCARCInstKind.cpp b/llvm/lib/Analysis/ObjCARCInstKind.cpp index 332c9e894de..f268e2a9abd 100644 --- a/llvm/lib/Analysis/ObjCARCInstKind.cpp +++ b/llvm/lib/Analysis/ObjCARCInstKind.cpp @@ -209,6 +209,7 @@ static bool isInertIntrinsic(unsigned ID) { // Don't let dbg info affect our results. case Intrinsic::dbg_declare: case Intrinsic::dbg_value: + case Intrinsic::dbg_label: // Short cut: Some intrinsics obviously don't use ObjC pointers. return true; default: diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index f757acfade0..60981a1a720 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -501,6 +501,7 @@ bool llvm::isAssumeLikeIntrinsic(const Instruction *I) { case Intrinsic::sideeffect: case Intrinsic::dbg_declare: case Intrinsic::dbg_value: + case Intrinsic::dbg_label: case Intrinsic::invariant_start: case Intrinsic::invariant_end: case Intrinsic::lifetime_start: diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 0f28864534e..a8f634bddce 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -4347,7 +4347,7 @@ bool LLParser::ParseDICompileUnit(MDNode *&Result, bool IsDistinct) { /// virtuality: DW_VIRTUALTIY_pure_virtual, /// virtualIndex: 10, thisAdjustment: 4, flags: 11, /// isOptimized: false, templateParams: !4, declaration: !5, -/// variables: !6, thrownTypes: !7) +/// retainedNodes: !6, thrownTypes: !7) bool LLParser::ParseDISubprogram(MDNode *&Result, bool IsDistinct) { auto Loc = Lex.getLoc(); #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ @@ -4369,7 +4369,7 @@ bool LLParser::ParseDISubprogram(MDNode *&Result, bool IsDistinct) { OPTIONAL(unit, MDField, ); \ OPTIONAL(templateParams, MDField, ); \ OPTIONAL(declaration, MDField, ); \ - OPTIONAL(variables, MDField, ); \ + OPTIONAL(retainedNodes, MDField, ); \ OPTIONAL(thrownTypes, MDField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS @@ -4385,7 +4385,7 @@ bool LLParser::ParseDISubprogram(MDNode *&Result, bool IsDistinct) { type.Val, isLocal.Val, isDefinition.Val, scopeLine.Val, containingType.Val, virtuality.Val, virtualIndex.Val, thisAdjustment.Val, flags.Val, isOptimized.Val, unit.Val, templateParams.Val, - declaration.Val, variables.Val, thrownTypes.Val)); + declaration.Val, retainedNodes.Val, thrownTypes.Val)); return false; } @@ -4568,6 +4568,22 @@ bool LLParser::ParseDILocalVariable(MDNode *&Result, bool IsDistinct) { return false; } +/// ParseDILabel: +/// ::= !DILabel(scope: !0, name: "foo", file: !1, line: 7) +bool LLParser::ParseDILabel(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(scope, MDField, (/* AllowNull */ false)); \ + REQUIRED(name, MDStringField, ); \ + REQUIRED(file, MDField, ); \ + REQUIRED(line, LineField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DILabel, + (Context, scope.Val, name.Val, file.Val, line.Val)); + return false; +} + /// ParseDIExpression: /// ::= !DIExpression(0, 7, -1) bool LLParser::ParseDIExpression(MDNode *&Result, bool IsDistinct) { diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp index efaee21a8d8..011c41e2cec 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -822,6 +822,7 @@ MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() { case bitc::METADATA_TEMPLATE_VALUE: case bitc::METADATA_GLOBAL_VAR: case bitc::METADATA_LOCAL_VAR: + case bitc::METADATA_LABEL: case bitc::METADATA_EXPRESSION: case bitc::METADATA_OBJC_PROPERTY: case bitc::METADATA_IMPORTED_ENTITY: @@ -1438,7 +1439,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( HasUnit ? CUorFn : nullptr, // unit getMDOrNull(Record[15 + Offset]), // templateParams getMDOrNull(Record[16 + Offset]), // declaration - getMDOrNull(Record[17 + Offset]), // variables + getMDOrNull(Record[17 + Offset]), // retainedNodes HasThrownTypes ? getMDOrNull(Record[20]) : nullptr // thrownTypes )); MetadataList.assignValue(SP, NextMetadataNo); @@ -1647,6 +1648,20 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( NextMetadataNo++; break; } + case bitc::METADATA_LABEL: { + if (Record.size() != 5) + return error("Invalid record"); + + IsDistinct = Record[0] & 1; + MetadataList.assignValue( + GET_OR_DISTINCT(DILabel, + (Context, getMDOrNull(Record[1]), + getMDString(Record[2]), + getMDOrNull(Record[3]), Record[4])), + NextMetadataNo); + NextMetadataNo++; + break; + } case bitc::METADATA_EXPRESSION: { if (Record.size() < 1) return error("Invalid record"); diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 90c9392b802..a3bcf6378cb 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -335,6 +335,8 @@ private: unsigned Abbrev); void writeDILocalVariable(const DILocalVariable *N, SmallVectorImpl<uint64_t> &Record, unsigned Abbrev); + void writeDILabel(const DILabel *N, + SmallVectorImpl<uint64_t> &Record, unsigned Abbrev); void writeDIExpression(const DIExpression *N, SmallVectorImpl<uint64_t> &Record, unsigned Abbrev); void writeDIGlobalVariableExpression(const DIGlobalVariableExpression *N, @@ -1628,7 +1630,7 @@ void ModuleBitcodeWriter::writeDISubprogram(const DISubprogram *N, Record.push_back(VE.getMetadataOrNullID(N->getRawUnit())); Record.push_back(VE.getMetadataOrNullID(N->getTemplateParams().get())); Record.push_back(VE.getMetadataOrNullID(N->getDeclaration())); - Record.push_back(VE.getMetadataOrNullID(N->getVariables().get())); + Record.push_back(VE.getMetadataOrNullID(N->getRetainedNodes().get())); Record.push_back(N->getThisAdjustment()); Record.push_back(VE.getMetadataOrNullID(N->getThrownTypes().get())); @@ -1785,6 +1787,19 @@ void ModuleBitcodeWriter::writeDILocalVariable( Record.clear(); } +void ModuleBitcodeWriter::writeDILabel( + const DILabel *N, SmallVectorImpl<uint64_t> &Record, + unsigned Abbrev) { + Record.push_back((uint64_t)N->isDistinct()); + Record.push_back(VE.getMetadataOrNullID(N->getScope())); + Record.push_back(VE.getMetadataOrNullID(N->getRawName())); + Record.push_back(VE.getMetadataOrNullID(N->getFile())); + Record.push_back(N->getLine()); + + Stream.EmitRecord(bitc::METADATA_LABEL, Record, Abbrev); + Record.clear(); +} + void ModuleBitcodeWriter::writeDIExpression(const DIExpression *N, SmallVectorImpl<uint64_t> &Record, unsigned Abbrev) { diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 182fbd6a6ce..b16dc3c1759 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1202,10 +1202,12 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, } // Collect info for variables that were optimized out. - for (const DILocalVariable *DV : SP->getVariables()) { - if (Processed.insert(InlinedVariable(DV, nullptr)).second) - if (LexicalScope *Scope = LScopes.findLexicalScope(DV->getScope())) - createConcreteVariable(TheCU, *Scope, InlinedVariable(DV, nullptr)); + for (const DINode *DN : SP->getRetainedNodes()) { + if (auto *DV = dyn_cast<DILocalVariable>(DN)) { + if (Processed.insert(InlinedVariable(DV, nullptr)).second) + if (LexicalScope *Scope = LScopes.findLexicalScope(DV->getScope())) + createConcreteVariable(TheCU, *Scope, InlinedVariable(DV, nullptr)); + } } } @@ -1386,14 +1388,16 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) { // Construct abstract scopes. for (LexicalScope *AScope : LScopes.getAbstractScopesList()) { auto *SP = cast<DISubprogram>(AScope->getScopeNode()); - // Collect info for variables that were optimized out. - for (const DILocalVariable *DV : SP->getVariables()) { - if (!ProcessedVars.insert(InlinedVariable(DV, nullptr)).second) - continue; - ensureAbstractVariableIsCreated(TheCU, InlinedVariable(DV, nullptr), - DV->getScope()); - assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes - && "ensureAbstractVariableIsCreated inserted abstract scopes"); + for (const DINode *DN : SP->getRetainedNodes()) { + if (auto *DV = dyn_cast<DILocalVariable>(DN)) { + // Collect info for variables that were optimized out. + if (!ProcessedVars.insert(InlinedVariable(DV, nullptr)).second) + continue; + ensureAbstractVariableIsCreated(TheCU, InlinedVariable(DV, nullptr), + DV->getScope()); + assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes + && "ensureAbstractVariableIsCreated inserted abstract scopes"); + } } constructAbstractSubprogramScopeDIE(TheCU, AScope); } diff --git a/llvm/lib/CodeGen/IntrinsicLowering.cpp b/llvm/lib/CodeGen/IntrinsicLowering.cpp index 12777d5ed11..eb409996424 100644 --- a/llvm/lib/CodeGen/IntrinsicLowering.cpp +++ b/llvm/lib/CodeGen/IntrinsicLowering.cpp @@ -456,6 +456,7 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) { } case Intrinsic::dbg_declare: + case Intrinsic::dbg_label: break; // Simply strip out debugging intrinsics case Intrinsic::eh_typeid_for: diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 08a14934b57..624350404ff 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1831,7 +1831,7 @@ static void writeDISubprogram(raw_ostream &Out, const DISubprogram *N, Printer.printMetadata("unit", N->getRawUnit()); Printer.printMetadata("templateParams", N->getRawTemplateParams()); Printer.printMetadata("declaration", N->getRawDeclaration()); - Printer.printMetadata("variables", N->getRawVariables()); + Printer.printMetadata("retainedNodes", N->getRawRetainedNodes()); Printer.printMetadata("thrownTypes", N->getRawThrownTypes()); Out << ")"; } @@ -1971,6 +1971,18 @@ static void writeDILocalVariable(raw_ostream &Out, const DILocalVariable *N, Out << ")"; } +static void writeDILabel(raw_ostream &Out, const DILabel *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, const Module *Context) { + Out << "!DILabel("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); + Printer.printString("name", N->getName()); + Printer.printMetadata("file", N->getRawFile()); + Printer.printInt("line", N->getLine()); + Out << ")"; +} + static void writeDIExpression(raw_ostream &Out, const DIExpression *N, TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context) { diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index 3e5ecdc2091..8596ebd9527 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -33,7 +33,7 @@ cl::opt<bool> DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes, DICompileUnit *CU) : M(m), VMContext(M.getContext()), CUNode(CU), - DeclareFn(nullptr), ValueFn(nullptr), + DeclareFn(nullptr), ValueFn(nullptr), LabelFn(nullptr), AllowUnresolvedNodes(AllowUnresolvedNodes) {} void DIBuilder::trackIfUnresolved(MDNode *N) { @@ -47,18 +47,23 @@ void DIBuilder::trackIfUnresolved(MDNode *N) { } void DIBuilder::finalizeSubprogram(DISubprogram *SP) { - MDTuple *Temp = SP->getVariables().get(); + MDTuple *Temp = SP->getRetainedNodes().get(); if (!Temp || !Temp->isTemporary()) return; - SmallVector<Metadata *, 4> Variables; + SmallVector<Metadata *, 16> RetainedNodes; auto PV = PreservedVariables.find(SP); if (PV != PreservedVariables.end()) - Variables.append(PV->second.begin(), PV->second.end()); + RetainedNodes.append(PV->second.begin(), PV->second.end()); - DINodeArray AV = getOrCreateArray(Variables); - TempMDTuple(Temp)->replaceAllUsesWith(AV.get()); + auto PL = PreservedLabels.find(SP); + if (PL != PreservedLabels.end()) + RetainedNodes.append(PL->second.begin(), PL->second.end()); + + DINodeArray Node = getOrCreateArray(RetainedNodes); + + TempMDTuple(Temp)->replaceAllUsesWith(Node.get()); } void DIBuilder::finalize() { @@ -699,6 +704,26 @@ DILocalVariable *DIBuilder::createParameterVariable( /* AlignInBits */0); } +DILabel *DIBuilder::createLabel( + DIScope *Scope, StringRef Name, DIFile *File, + unsigned LineNo, bool AlwaysPreserve) { + DIScope *Context = getNonCompileUnitScope(Scope); + + auto *Node = + DILabel::get(VMContext, cast_or_null<DILocalScope>(Context), Name, + File, LineNo); + + if (AlwaysPreserve) { + /// The optimizer may remove labels. If there is an interest + /// to preserve label info in such situation then append it to + /// the list of retained nodes of the DISubprogram. + DISubprogram *Fn = getDISubprogram(Scope); + assert(Fn && "Missing subprogram for label"); + PreservedLabels[Fn].emplace_back(Node); + } + return Node; +} + DIExpression *DIBuilder::createExpression(ArrayRef<uint64_t> Addr) { return DIExpression::get(VMContext, Addr); } @@ -821,6 +846,18 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo, return insertDeclare(Storage, VarInfo, Expr, DL, InsertAtEnd, InsertBefore); } +Instruction *DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL, + Instruction *InsertBefore) { + return insertLabel( + LabelInfo, DL, InsertBefore ? InsertBefore->getParent() : nullptr, + InsertBefore); +} + +Instruction *DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL, + BasicBlock *InsertAtEnd) { + return insertLabel(LabelInfo, DL, InsertAtEnd, nullptr); +} + Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, DILocalVariable *VarInfo, DIExpression *Expr, @@ -906,6 +943,24 @@ Instruction *DIBuilder::insertDbgValueIntrinsic( return B.CreateCall(ValueFn, Args); } +Instruction *DIBuilder::insertLabel( + DILabel *LabelInfo, const DILocation *DL, + BasicBlock *InsertBB, Instruction *InsertBefore) { + assert(LabelInfo && "empty or invalid DILabel* passed to dbg.label"); + assert(DL && "Expected debug loc"); + assert(DL->getScope()->getSubprogram() == + LabelInfo->getScope()->getSubprogram() && + "Expected matching subprograms"); + if (!LabelFn) + LabelFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_label); + + trackIfUnresolved(LabelInfo); + Value *Args[] = {MetadataAsValue::get(VMContext, LabelInfo)}; + + IRBuilder<> B = getIRBForDbgInsertion(DL, InsertBB, InsertBefore); + return B.CreateCall(LabelFn, Args); +} + void DIBuilder::replaceVTableHolder(DICompositeType *&T, DIType *VTableHolder) { { diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index 1e771d03028..8cf38e74135 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -568,7 +568,7 @@ void DebugTypeInfoRemoval::traverse(MDNode *N) { // parts of the graph. auto prune = [](MDNode *Parent, MDNode *Child) { if (auto *MDS = dyn_cast<DISubprogram>(Parent)) - return Child == MDS->getVariables().get(); + return Child == MDS->getRetainedNodes().get(); return false; }; diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index bb497e458c0..a9f96e2549d 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -489,7 +489,7 @@ DISubprogram *DISubprogram::getImpl( bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, bool IsOptimized, Metadata *Unit, - Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables, + Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes, Metadata *ThrownTypes, StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); assert(isCanonical(LinkageName) && "Expected canonical MDString"); @@ -497,10 +497,10 @@ DISubprogram *DISubprogram::getImpl( DISubprogram, (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized, Unit, - TemplateParams, Declaration, Variables, ThrownTypes)); + TemplateParams, Declaration, RetainedNodes, ThrownTypes)); SmallVector<Metadata *, 11> Ops = { - File, Scope, Name, LinkageName, Type, Unit, - Declaration, Variables, ContainingType, TemplateParams, ThrownTypes}; + File, Scope, Name, LinkageName, Type, Unit, + Declaration, RetainedNodes, ContainingType, TemplateParams, ThrownTypes}; if (!ThrownTypes) { Ops.pop_back(); if (!TemplateParams) { @@ -653,6 +653,18 @@ Optional<uint64_t> DIVariable::getSizeInBits() const { return None; } +DILabel *DILabel::getImpl(LLVMContext &Context, Metadata *Scope, + MDString *Name, Metadata *File, unsigned Line, + StorageType Storage, + bool ShouldCreate) { + assert(Scope && "Expected scope"); + assert(isCanonical(Name) && "Expected canonical MDString"); + DEFINE_GETIMPL_LOOKUP(DILabel, + (Scope, Name, File, Line)); + Metadata *Ops[] = {Scope, Name, File}; + DEFINE_GETIMPL_STORE(DILabel, (Line), Ops); +} + DIExpression *DIExpression::getImpl(LLVMContext &Context, ArrayRef<uint64_t> Elements, StorageType Storage, bool ShouldCreate) { diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index 13579dcab08..7ceeca6e347 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -619,7 +619,7 @@ template <> struct MDNodeKeyImpl<DISubprogram> { Metadata *Unit; Metadata *TemplateParams; Metadata *Declaration; - Metadata *Variables; + Metadata *RetainedNodes; Metadata *ThrownTypes; MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *LinkageName, @@ -628,7 +628,7 @@ template <> struct MDNodeKeyImpl<DISubprogram> { Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex, int ThisAdjustment, unsigned Flags, bool IsOptimized, Metadata *Unit, Metadata *TemplateParams, - Metadata *Declaration, Metadata *Variables, + Metadata *Declaration, Metadata *RetainedNodes, Metadata *ThrownTypes) : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File), Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit), @@ -637,7 +637,7 @@ template <> struct MDNodeKeyImpl<DISubprogram> { VirtualIndex(VirtualIndex), ThisAdjustment(ThisAdjustment), Flags(Flags), IsOptimized(IsOptimized), Unit(Unit), TemplateParams(TemplateParams), Declaration(Declaration), - Variables(Variables), ThrownTypes(ThrownTypes) {} + RetainedNodes(RetainedNodes), ThrownTypes(ThrownTypes) {} MDNodeKeyImpl(const DISubprogram *N) : Scope(N->getRawScope()), Name(N->getRawName()), LinkageName(N->getRawLinkageName()), File(N->getRawFile()), @@ -648,7 +648,7 @@ template <> struct MDNodeKeyImpl<DISubprogram> { ThisAdjustment(N->getThisAdjustment()), Flags(N->getFlags()), IsOptimized(N->isOptimized()), Unit(N->getRawUnit()), TemplateParams(N->getRawTemplateParams()), - Declaration(N->getRawDeclaration()), Variables(N->getRawVariables()), + Declaration(N->getRawDeclaration()), RetainedNodes(N->getRawRetainedNodes()), ThrownTypes(N->getRawThrownTypes()) {} bool isKeyOf(const DISubprogram *RHS) const { @@ -666,7 +666,7 @@ template <> struct MDNodeKeyImpl<DISubprogram> { Unit == RHS->getUnit() && TemplateParams == RHS->getRawTemplateParams() && Declaration == RHS->getRawDeclaration() && - Variables == RHS->getRawVariables() && + RetainedNodes == RHS->getRawRetainedNodes() && ThrownTypes == RHS->getRawThrownTypes(); } @@ -948,6 +948,29 @@ template <> struct MDNodeKeyImpl<DILocalVariable> { } }; +template <> struct MDNodeKeyImpl<DILabel> { + Metadata *Scope; + MDString *Name; + Metadata *File; + unsigned Line; + + MDNodeKeyImpl(Metadata *Scope, MDString *Name, Metadata *File, unsigned Line) + : Scope(Scope), Name(Name), File(File), Line(Line) {} + MDNodeKeyImpl(const DILabel *N) + : Scope(N->getRawScope()), Name(N->getRawName()), File(N->getRawFile()), + Line(N->getLine()) {} + + bool isKeyOf(const DILabel *RHS) const { + return Scope == RHS->getRawScope() && Name == RHS->getRawName() && + File == RHS->getRawFile() && Line == RHS->getLine(); + } + + /// Using name and line to get hash value. It should already be mostly unique. + unsigned getHashValue() const { + return hash_combine(Scope, Name, Line); + } +}; + template <> struct MDNodeKeyImpl<DIExpression> { ArrayRef<uint64_t> Elements; diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 770d21dfb7b..dca9d9b64ff 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -467,6 +467,7 @@ private: void visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS); void visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI); void visitDbgIntrinsic(StringRef Kind, DbgInfoIntrinsic &DII); + void visitDbgLabelIntrinsic(StringRef Kind, DbgLabelInst &DLI); void visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI); void visitAtomicRMWInst(AtomicRMWInst &RMWI); void visitFenceInst(FenceInst &FI); @@ -1085,12 +1086,13 @@ void Verifier::visitDISubprogram(const DISubprogram &N) { if (auto *S = N.getRawDeclaration()) AssertDI(isa<DISubprogram>(S) && !cast<DISubprogram>(S)->isDefinition(), "invalid subprogram declaration", &N, S); - if (auto *RawVars = N.getRawVariables()) { - auto *Vars = dyn_cast<MDTuple>(RawVars); - AssertDI(Vars, "invalid variable list", &N, RawVars); - for (Metadata *Op : Vars->operands()) { - AssertDI(Op && isa<DILocalVariable>(Op), "invalid local variable", &N, - Vars, Op); + if (auto *RawNode = N.getRawRetainedNodes()) { + auto *Node = dyn_cast<MDTuple>(RawNode); + AssertDI(Node, "invalid retained nodes list", &N, RawNode); + for (Metadata *Op : Node->operands()) { + AssertDI(Op && (isa<DILocalVariable>(Op) || isa<DILabel>(Op)), + "invalid retained nodes, expected DILocalVariable or DILabel", + &N, Node, Op); } } AssertDI(!hasConflictingReferenceFlags(N.getFlags()), @@ -1222,6 +1224,17 @@ void Verifier::visitDILocalVariable(const DILocalVariable &N) { "local variable requires a valid scope", &N, N.getRawScope()); } +void Verifier::visitDILabel(const DILabel &N) { + if (auto *S = N.getRawScope()) + AssertDI(isa<DIScope>(S), "invalid scope", &N, S); + if (auto *F = N.getRawFile()) + AssertDI(isa<DIFile>(F), "invalid file", &N, F); + + AssertDI(N.getTag() == dwarf::DW_TAG_label, "invalid tag", &N); + AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()), + "label requires a valid scope", &N, N.getRawScope()); +} + void Verifier::visitDIExpression(const DIExpression &N) { AssertDI(N.isValid(), "invalid expression", &N); } @@ -4065,6 +4078,9 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) { case Intrinsic::dbg_value: // llvm.dbg.value visitDbgIntrinsic("value", cast<DbgInfoIntrinsic>(*CS.getInstruction())); break; + case Intrinsic::dbg_label: // llvm.dbg.label + visitDbgLabelIntrinsic("label", cast<DbgLabelInst>(*CS.getInstruction())); + break; case Intrinsic::memcpy: case Intrinsic::memmove: case Intrinsic::memset: { @@ -4494,7 +4510,40 @@ void Verifier::visitDbgIntrinsic(StringRef Kind, DbgInfoIntrinsic &DII) { verifyFnArgs(DII); } +void Verifier::visitDbgLabelIntrinsic(StringRef Kind, DbgLabelInst &DLI) { + AssertDI(isa<DILabel>(DLI.getRawVariable()), + "invalid llvm.dbg." + Kind + " intrinsic variable", &DLI, + DLI.getRawVariable()); + + // Ignore broken !dbg attachments; they're checked elsewhere. + if (MDNode *N = DLI.getDebugLoc().getAsMDNode()) + if (!isa<DILocation>(N)) + return; + + BasicBlock *BB = DLI.getParent(); + Function *F = BB ? BB->getParent() : nullptr; + + // The scopes for variables and !dbg attachments must agree. + DILabel *Label = DLI.getLabel(); + DILocation *Loc = DLI.getDebugLoc(); + Assert(Loc, "llvm.dbg." + Kind + " intrinsic requires a !dbg attachment", + &DLI, BB, F); + + DISubprogram *LabelSP = getSubprogram(Label->getRawScope()); + DISubprogram *LocSP = getSubprogram(Loc->getRawScope()); + if (!LabelSP || !LocSP) + return; + + AssertDI(LabelSP == LocSP, "mismatched subprogram between llvm.dbg." + Kind + + " label and !dbg attachment", + &DLI, BB, F, Label, Label->getScope()->getSubprogram(), Loc, + Loc->getScope()->getSubprogram()); +} + void Verifier::verifyFragmentExpression(const DbgInfoIntrinsic &I) { + if (dyn_cast<DbgLabelInst>(&I)) + return; + DILocalVariable *V = dyn_cast_or_null<DILocalVariable>(I.getRawVariable()); DIExpression *E = dyn_cast_or_null<DIExpression>(I.getRawExpression()); diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index d9601556595..0a8375d1d27 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -372,6 +372,11 @@ bool llvm::wouldInstructionBeTriviallyDead(Instruction *I, return false; return true; } + if (DbgLabelInst *DLI = dyn_cast<DbgLabelInst>(I)) { + if (DLI->getLabel()) + return false; + return true; + } if (!I->mayHaveSideEffects()) return true; diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 424a8815954..d900b03ec24 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -3896,6 +3896,7 @@ static bool removeEmptyCleanup(CleanupReturnInst *RI) { switch (IntrinsicID) { case Intrinsic::dbg_declare: case Intrinsic::dbg_value: + case Intrinsic::dbg_label: case Intrinsic::lifetime_end: break; default: |