Index: include/llvm/Analysis/TargetTransformInfoImpl.h =================================================================== --- include/llvm/Analysis/TargetTransformInfoImpl.h +++ include/llvm/Analysis/TargetTransformInfoImpl.h @@ -155,6 +155,7 @@ 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: Index: include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- include/llvm/Bitcode/LLVMBitCodes.h +++ include/llvm/Bitcode/LLVMBitCodes.h @@ -310,6 +310,7 @@ METADATA_GLOBAL_VAR_EXPR = 37, // [distinct, var, expr] METADATA_INDEX_OFFSET = 38, // [offset] METADATA_INDEX = 39, // [bitpos] + METADATA_LABEL = 40, // [distinct, scope, name, file, line] }; // The constants block (CONSTANTS_BLOCK_ID) describes emission for each Index: include/llvm/IR/DIBuilder.h =================================================================== --- include/llvm/IR/DIBuilder.h +++ include/llvm/IR/DIBuilder.h @@ -46,6 +46,7 @@ DICompileUnit *CUNode; ///< The one compile unit created by this DIBuiler. Function *DeclareFn; ///< llvm.dbg.declare Function *ValueFn; ///< llvm.dbg.value + Function *LabelFn; ///< llvm.dbg.label SmallVector AllEnumTypes; /// Track the RetainTypes, since they can be updated later on. @@ -69,6 +70,9 @@ /// copy. DenseMap> PreservedVariables; + /// Each subprogram's preserved labels. + DenseMap> PreservedLabels; + /// Create a temporary. /// /// Create an \a temporary node and track it in \a UnresolvedNodes. @@ -79,6 +83,10 @@ DIExpression *Expr, const DILocation *DL, BasicBlock *InsertBB, Instruction *InsertBefore); + /// Internal helper for insertLabel. + Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL, + BasicBlock *InsertBB, Instruction *InsertBefore); + /// Internal helper for insertDbgValueIntrinsic. Instruction * insertDbgValueIntrinsic(llvm::Value *Val, DILocalVariable *VarInfo, @@ -591,6 +599,14 @@ DINode::DIFlags Flags = DINode::FlagZero, uint32_t AlignInBits = 0); + /// Create a new descriptor for an label. + /// + /// \c Scope must be a \a DILocalScope, and thus its scope chain eventually + /// leads to a \a DISubprogram. + DILabel * + createLabel(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo, + bool AlwaysPreserve = false); + /// Create a new descriptor for a parameter variable. /// /// \c Scope must be a \a DILocalScope, and thus its scope chain eventually @@ -782,6 +798,20 @@ DIExpression *Expr, const DILocation *DL, Instruction *InsertBefore); + /// Insert a new llvm.dbg.label intrinsic call. + /// \param LabelInfo Label's debug info descriptor. + /// \param DL Debug info location. + /// \param InsertBefore Location for the new intrinsic. + Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL, + Instruction *InsertBefore); + + /// Insert a new llvm.dbg.label intrinsic call. + /// \param LabelInfo Label's debug info descriptor. + /// \param DL Debug info location. + /// \param InsertAtEnd Location for the new intrinsic. + Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL, + BasicBlock *InsertAtEnd); + /// Insert a new llvm.dbg.value intrinsic call. /// \param Val llvm::Value of the variable /// \param VarInfo Variable's debug info descriptor. Index: include/llvm/IR/DebugInfoMetadata.h =================================================================== --- include/llvm/IR/DebugInfoMetadata.h +++ include/llvm/IR/DebugInfoMetadata.h @@ -232,6 +232,7 @@ case DITemplateValueParameterKind: case DIGlobalVariableKind: case DILocalVariableKind: + case DILabelKind: case DIObjCPropertyKind: case DIImportedEntityKind: case DIModuleKind: @@ -1610,14 +1611,14 @@ unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, bool IsOptimized, DICompileUnit *Unit, DITemplateParameterArray TemplateParams, DISubprogram *Declaration, - DILocalVariableArray Variables, DITypeArray ThrownTypes, - StorageType Storage, bool ShouldCreate = true) { + DILocalVariableArray Variables, DILabelArray Labels, + DITypeArray ThrownTypes, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, LinkageName), File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized, Unit, TemplateParams.get(), Declaration, Variables.get(), - ThrownTypes.get(), Storage, ShouldCreate); + Labels.get(), ThrownTypes.get(), Storage, ShouldCreate); } static DISubprogram * getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, @@ -1626,7 +1627,8 @@ Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, bool IsOptimized, Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables, - Metadata *ThrownTypes, StorageType Storage, bool ShouldCreate = true); + Metadata *Labels, Metadata *ThrownTypes, StorageType Storage, + bool ShouldCreate = true); TempDISubprogram cloneImpl() const { return getTemporary(getContext(), getScope(), getName(), getLinkageName(), @@ -1635,7 +1637,7 @@ getVirtuality(), getVirtualIndex(), getThisAdjustment(), getFlags(), isOptimized(), getUnit(), getTemplateParams(), getDeclaration(), getVariables(), - getThrownTypes()); + getLabels(), getThrownTypes()); } public: @@ -1649,11 +1651,13 @@ DITemplateParameterArray TemplateParams = nullptr, DISubprogram *Declaration = nullptr, DILocalVariableArray Variables = nullptr, + DILabelArray Labels = nullptr, DITypeArray ThrownTypes = nullptr), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized, Unit, - TemplateParams, Declaration, Variables, ThrownTypes)) + TemplateParams, Declaration, Variables, Labels, + ThrownTypes)) DEFINE_MDNODE_GET( DISubprogram, (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, @@ -1662,11 +1666,11 @@ unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, bool IsOptimized, Metadata *Unit, Metadata *TemplateParams = nullptr, Metadata *Declaration = nullptr, Metadata *Variables = nullptr, - Metadata *ThrownTypes = nullptr), + Metadata *Labels = nullptr, Metadata *ThrownTypes = nullptr), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized, Unit, TemplateParams, Declaration, Variables, - ThrownTypes)) + Labels, ThrownTypes)) TempDISubprogram clone() const { return cloneImpl(); } @@ -1740,6 +1744,9 @@ DITypeArray getThrownTypes() const { return cast_or_null(getRawThrownTypes()); } + DILabelArray getLabels() const { + return cast_or_null(getRawLabels()); + } Metadata *getRawScope() const { return getOperand(1); } MDString *getRawName() const { return getOperandAs(2); } @@ -1748,15 +1755,18 @@ Metadata *getRawUnit() const { return getOperand(5); } Metadata *getRawDeclaration() const { return getOperand(6); } Metadata *getRawVariables() const { return getOperand(7); } - Metadata *getRawContainingType() const { + Metadata *getRawLabels() const { return getNumOperands() > 8 ? getOperandAs(8) : nullptr; } - Metadata *getRawTemplateParams() const { + Metadata *getRawContainingType() const { return getNumOperands() > 9 ? getOperandAs(9) : nullptr; } - Metadata *getRawThrownTypes() const { + Metadata *getRawTemplateParams() const { return getNumOperands() > 10 ? getOperandAs(10) : nullptr; } + Metadata *getRawThrownTypes() const { + return getNumOperands() > 11 ? getOperandAs(11) : nullptr; + } /// Check if this subprogram describes the given function. /// @@ -2603,6 +2613,76 @@ } }; +/// Label. +/// +class DILabel : public DINode { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + + DILabel(LLVMContext &C, StorageType Storage, unsigned Line, + ArrayRef Ops) + : DINode(C, DILabelKind, Storage, dwarf::DW_TAG_label, Ops), Line(Line) {} + ~DILabel() = default; + + static DILabel *getImpl(LLVMContext &Context, DIScope *Scope, + StringRef Name, DIFile *File, unsigned Line, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File, + Line, Storage, ShouldCreate); + } + static DILabel *getImpl(LLVMContext &Context, Metadata *Scope, + MDString *Name, Metadata *File, unsigned Line, + StorageType Storage, + bool ShouldCreate = true); + + TempDILabel cloneImpl() const { + return getTemporary(getContext(), getScope(), getName(), getFile(), + getLine()); + } + +public: + DEFINE_MDNODE_GET(DILabel, + (DILocalScope * Scope, StringRef Name, DIFile *File, + unsigned Line), + (Scope, Name, File, Line)) + DEFINE_MDNODE_GET(DILabel, + (Metadata * Scope, MDString *Name, Metadata *File, + unsigned Line), + (Scope, Name, File, Line)) + + TempDILabel clone() const { return cloneImpl(); } + + /// Get the local scope for this label. + /// + /// Labels must be defined in a local scope. + DILocalScope *getScope() const { + return cast_or_null(getRawScope()); + } + unsigned getLine() const { return Line; } + StringRef getName() const { return getStringOperand(1); } + DIFile *getFile() const { return cast_or_null(getRawFile()); } + + Metadata *getRawScope() const { return getOperand(0); } + MDString *getRawName() const { return getOperandAs(1); } + Metadata *getRawFile() const { return getOperand(2); } + + /// Check that a location is valid for this label. + /// + /// Check that \c DL exists, is in the same subprogram, and has the same + /// inlined-at location as \c this. (Otherwise, it's not a valid attachment + /// to a \a DbgInfoIntrinsic.) + bool isValidLocationForIntrinsic(const DILocation *DL) const { + return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DILabelKind; + } +}; + class DIObjCProperty : public DINode { friend class LLVMContextImpl; friend class MDNode; Index: include/llvm/IR/InstVisitor.h =================================================================== --- include/llvm/IR/InstVisitor.h +++ include/llvm/IR/InstVisitor.h @@ -213,6 +213,7 @@ // Handle the special instrinsic instruction classes. RetTy visitDbgDeclareInst(DbgDeclareInst &I) { DELEGATE(DbgInfoIntrinsic);} RetTy visitDbgValueInst(DbgValueInst &I) { DELEGATE(DbgInfoIntrinsic);} + RetTy visitDbgLabelInst(DbgLabelInst &I) { DELEGATE(DbgInfoIntrinsic);} RetTy visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) { DELEGATE(IntrinsicInst); } RetTy visitMemSetInst(MemSetInst &I) { DELEGATE(MemIntrinsic); } RetTy visitMemCpyInst(MemCpyInst &I) { DELEGATE(MemTransferInst); } @@ -272,6 +273,7 @@ default: DELEGATE(IntrinsicInst); case Intrinsic::dbg_declare: DELEGATE(DbgDeclareInst); case Intrinsic::dbg_value: DELEGATE(DbgValueInst); + case Intrinsic::dbg_label: DELEGATE(DbgLabelInst); case Intrinsic::memcpy: DELEGATE(MemCpyInst); case Intrinsic::memmove: DELEGATE(MemMoveInst); case Intrinsic::memset: DELEGATE(MemSetInst); Index: include/llvm/IR/IntrinsicInst.h =================================================================== --- include/llvm/IR/IntrinsicInst.h +++ include/llvm/IR/IntrinsicInst.h @@ -100,6 +100,7 @@ case Intrinsic::dbg_declare: case Intrinsic::dbg_value: case Intrinsic::dbg_addr: + case Intrinsic::dbg_label: return true; default: return false; } @@ -159,6 +160,30 @@ /// @} }; + /// This represents the llvm.dbg.label instruction. + class DbgLabelInst : public DbgInfoIntrinsic { + public: + DILabel *getLabel() const { + return cast(getRawVariable()); + } + + Metadata *getRawVariable() const { + return cast(getArgOperand(0))->getMetadata(); + } + + Metadata *getRawExpression() const { + return nullptr; + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::dbg_label; + } + static bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + /// This is the common base class for constrained floating point intrinsics. class ConstrainedFPIntrinsic : public IntrinsicInst { public: Index: include/llvm/IR/Intrinsics.td =================================================================== --- include/llvm/IR/Intrinsics.td +++ include/llvm/IR/Intrinsics.td @@ -595,6 +595,8 @@ [llvm_metadata_ty, llvm_metadata_ty, llvm_metadata_ty]>; + def int_dbg_label : Intrinsic<[], + [llvm_metadata_ty]>; } //===------------------ Exception Handling Intrinsics----------------------===// Index: include/llvm/IR/Metadata.def =================================================================== --- include/llvm/IR/Metadata.def +++ include/llvm/IR/Metadata.def @@ -108,6 +108,7 @@ HANDLE_SPECIALIZED_MDNODE_BRANCH(DIVariable) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGlobalVariable) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocalVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILabel) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIObjCProperty) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIImportedEntity) HANDLE_SPECIALIZED_MDNODE_BRANCH(DIMacroNode) Index: lib/Analysis/ObjCARCInstKind.cpp =================================================================== --- lib/Analysis/ObjCARCInstKind.cpp +++ lib/Analysis/ObjCARCInstKind.cpp @@ -209,6 +209,7 @@ // 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: Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -493,6 +493,7 @@ 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: Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -4343,7 +4343,7 @@ /// virtuality: DW_VIRTUALTIY_pure_virtual, /// virtualIndex: 10, thisAdjustment: 4, flags: 11, /// isOptimized: false, templateParams: !4, declaration: !5, -/// variables: !6, thrownTypes: !7) +/// variables: !6, labels: !7, thrownTypes: !8) bool LLParser::ParseDISubprogram(MDNode *&Result, bool IsDistinct) { auto Loc = Lex.getLoc(); #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ @@ -4366,6 +4366,7 @@ OPTIONAL(templateParams, MDField, ); \ OPTIONAL(declaration, MDField, ); \ OPTIONAL(variables, MDField, ); \ + OPTIONAL(labels, MDField, ); \ OPTIONAL(thrownTypes, MDField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS @@ -4381,7 +4382,7 @@ 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, variables.Val, labels.Val, thrownTypes.Val)); return false; } @@ -4564,6 +4565,22 @@ 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) { Index: lib/Bitcode/Reader/MetadataLoader.cpp =================================================================== --- lib/Bitcode/Reader/MetadataLoader.cpp +++ lib/Bitcode/Reader/MetadataLoader.cpp @@ -822,6 +822,7 @@ 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: @@ -1400,7 +1401,7 @@ break; } case bitc::METADATA_SUBPROGRAM: { - if (Record.size() < 18 || Record.size() > 21) + if (Record.size() < 18 || Record.size() > 22) return error("Invalid record"); IsDistinct = @@ -1439,7 +1440,8 @@ getMDOrNull(Record[15 + Offset]), // templateParams getMDOrNull(Record[16 + Offset]), // declaration getMDOrNull(Record[17 + Offset]), // variables - HasThrownTypes ? getMDOrNull(Record[20]) : nullptr // thrownTypes + getMDOrNull(Record[18 + Offset]), // labels + HasThrownTypes ? getMDOrNull(Record[21]) : nullptr // thrownTypes )); MetadataList.assignValue(SP, NextMetadataNo); NextMetadataNo++; @@ -1647,6 +1649,20 @@ 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"); Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -331,6 +331,8 @@ unsigned Abbrev); void writeDILocalVariable(const DILocalVariable *N, SmallVectorImpl &Record, unsigned Abbrev); + void writeDILabel(const DILabel *N, + SmallVectorImpl &Record, unsigned Abbrev); void writeDIExpression(const DIExpression *N, SmallVectorImpl &Record, unsigned Abbrev); void writeDIGlobalVariableExpression(const DIGlobalVariableExpression *N, @@ -1623,6 +1625,7 @@ 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->getLabels().get())); Record.push_back(N->getThisAdjustment()); Record.push_back(VE.getMetadataOrNullID(N->getThrownTypes().get())); @@ -1779,6 +1782,19 @@ Record.clear(); } +void ModuleBitcodeWriter::writeDILabel( + const DILabel *N, SmallVectorImpl &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 &Record, unsigned Abbrev) { Index: lib/CodeGen/IntrinsicLowering.cpp =================================================================== --- lib/CodeGen/IntrinsicLowering.cpp +++ lib/CodeGen/IntrinsicLowering.cpp @@ -456,6 +456,7 @@ } case Intrinsic::dbg_declare: + case Intrinsic::dbg_label: break; // Simply strip out debugging intrinsics case Intrinsic::eh_typeid_for: Index: lib/IR/AsmWriter.cpp =================================================================== --- lib/IR/AsmWriter.cpp +++ lib/IR/AsmWriter.cpp @@ -1829,6 +1829,7 @@ Printer.printMetadata("templateParams", N->getRawTemplateParams()); Printer.printMetadata("declaration", N->getRawDeclaration()); Printer.printMetadata("variables", N->getRawVariables()); + Printer.printMetadata("labels", N->getRawLabels()); Printer.printMetadata("thrownTypes", N->getRawThrownTypes()); Out << ")"; } @@ -1968,6 +1969,18 @@ 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) { Index: lib/IR/DIBuilder.cpp =================================================================== --- lib/IR/DIBuilder.cpp +++ lib/IR/DIBuilder.cpp @@ -33,7 +33,7 @@ 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) { @@ -59,6 +59,20 @@ DINodeArray AV = getOrCreateArray(Variables); TempMDTuple(Temp)->replaceAllUsesWith(AV.get()); + + // processing labels. + Temp = SP->getLabels().get(); + if (!Temp || !Temp->isTemporary()) + return; + + SmallVector Labels; + + auto PL = PreservedLabels.find(SP); + if (PL != PreservedLabels.end()) + Labels.append(PL->second.begin(), PL->second.end()); + + DINodeArray AL = getOrCreateArray(Labels); + TempMDTuple(Temp)->replaceAllUsesWith(AL.get()); } void DIBuilder::finalize() { @@ -699,6 +713,26 @@ /* 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(Context), Name, + File, LineNo); + + if (AlwaysPreserve) { + // The optimizer may remove labels. If there is an interest + // to preserve label info in such situation then stash it in a + // named mdnode. + DISubprogram *Fn = getDISubprogram(Scope); + assert(Fn && "Missing subprogram for label"); + PreservedLabels[Fn].emplace_back(Node); + } + return Node; +} + DIExpression *DIBuilder::createExpression(ArrayRef Addr) { return DIExpression::get(VMContext, Addr); } @@ -727,6 +761,7 @@ getNonCompileUnitScope(Context), Name, LinkageName, File, LineNo, Ty, isLocalToUnit, isDefinition, ScopeLine, nullptr, 0, 0, 0, Flags, isOptimized, isDefinition ? CUNode : nullptr, TParams, Decl, + MDTuple::getTemporary(VMContext, None).release(), MDTuple::getTemporary(VMContext, None).release(), ThrownTypes); if (isDefinition) @@ -745,7 +780,7 @@ VMContext, getNonCompileUnitScope(Context), Name, LinkageName, File, LineNo, Ty, isLocalToUnit, isDefinition, ScopeLine, nullptr, 0, 0, 0, Flags, isOptimized, isDefinition ? CUNode : nullptr, - TParams, Decl, nullptr, ThrownTypes) + TParams, Decl, nullptr, nullptr, ThrownTypes) .release(); } @@ -763,7 +798,8 @@ /* IsDistinct = */ isDefinition, VMContext, cast(Context), Name, LinkageName, F, LineNo, Ty, isLocalToUnit, isDefinition, LineNo, VTableHolder, VK, VIndex, ThisAdjustment, Flags, isOptimized, - isDefinition ? CUNode : nullptr, TParams, nullptr, nullptr, ThrownTypes); + isDefinition ? CUNode : nullptr, TParams, nullptr, nullptr, nullptr, + ThrownTypes); if (isDefinition) AllSubprograms.push_back(SP); @@ -821,6 +857,18 @@ 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 +954,24 @@ 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) { { Index: lib/IR/DebugInfoMetadata.cpp =================================================================== --- lib/IR/DebugInfoMetadata.cpp +++ lib/IR/DebugInfoMetadata.cpp @@ -490,17 +490,19 @@ Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, bool IsOptimized, Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables, - Metadata *ThrownTypes, StorageType Storage, bool ShouldCreate) { + Metadata *Labels, Metadata *ThrownTypes, StorageType Storage, + bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); assert(isCanonical(LinkageName) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP( DISubprogram, (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized, Unit, - TemplateParams, Declaration, Variables, ThrownTypes)); - SmallVector Ops = { - File, Scope, Name, LinkageName, Type, Unit, - Declaration, Variables, ContainingType, TemplateParams, ThrownTypes}; + TemplateParams, Declaration, Variables, Labels, + ThrownTypes)); + SmallVector Ops = { + File, Scope, Name, LinkageName, Type, Unit, + Declaration, Variables, Labels, ContainingType, TemplateParams, ThrownTypes}; if (!ThrownTypes) { Ops.pop_back(); if (!TemplateParams) { @@ -653,6 +655,18 @@ 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 Elements, StorageType Storage, bool ShouldCreate) { Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ lib/IR/LLVMContextImpl.h @@ -620,6 +620,7 @@ Metadata *TemplateParams; Metadata *Declaration; Metadata *Variables; + Metadata *Labels; Metadata *ThrownTypes; MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *LinkageName, @@ -629,7 +630,7 @@ unsigned VirtualIndex, int ThisAdjustment, unsigned Flags, bool IsOptimized, Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables, - Metadata *ThrownTypes) + Metadata *Labels, Metadata *ThrownTypes) : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File), Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition), ScopeLine(ScopeLine), @@ -637,7 +638,7 @@ VirtualIndex(VirtualIndex), ThisAdjustment(ThisAdjustment), Flags(Flags), IsOptimized(IsOptimized), Unit(Unit), TemplateParams(TemplateParams), Declaration(Declaration), - Variables(Variables), ThrownTypes(ThrownTypes) {} + Variables(Variables), Labels(Labels), ThrownTypes(ThrownTypes) {} MDNodeKeyImpl(const DISubprogram *N) : Scope(N->getRawScope()), Name(N->getRawName()), LinkageName(N->getRawLinkageName()), File(N->getRawFile()), @@ -649,7 +650,7 @@ IsOptimized(N->isOptimized()), Unit(N->getRawUnit()), TemplateParams(N->getRawTemplateParams()), Declaration(N->getRawDeclaration()), Variables(N->getRawVariables()), - ThrownTypes(N->getRawThrownTypes()) {} + Labels(N->getRawLabels()), ThrownTypes(N->getRawThrownTypes()) {} bool isKeyOf(const DISubprogram *RHS) const { return Scope == RHS->getRawScope() && Name == RHS->getRawName() && @@ -667,6 +668,7 @@ TemplateParams == RHS->getRawTemplateParams() && Declaration == RHS->getRawDeclaration() && Variables == RHS->getRawVariables() && + Labels == RHS->getRawLabels() && ThrownTypes == RHS->getRawThrownTypes(); } @@ -948,6 +950,28 @@ } }; +template <> struct MDNodeKeyImpl { + 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(); + } + + unsigned getHashValue() const { + return hash_combine(Scope, Name, File, Line); + } +}; + template <> struct MDNodeKeyImpl { ArrayRef Elements; Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -467,6 +467,7 @@ 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); @@ -1222,6 +1223,17 @@ "local variable requires a valid scope", &N, N.getRawScope()); } +void Verifier::visitDILabel(const DILabel &N) { + if (auto *S = N.getRawScope()) + AssertDI(isa(S), "invalid scope", &N, S); + if (auto *F = N.getRawFile()) + AssertDI(isa(F), "invalid file", &N, F); + + AssertDI(N.getTag() == dwarf::DW_TAG_label, "invalid tag", &N); + AssertDI(N.getRawScope() && isa(N.getRawScope()), + "label requires a valid scope", &N, N.getRawScope()); +} + void Verifier::visitDIExpression(const DIExpression &N) { AssertDI(N.isValid(), "invalid expression", &N); } @@ -4064,6 +4076,9 @@ case Intrinsic::dbg_value: // llvm.dbg.value visitDbgIntrinsic("value", cast(*CS.getInstruction())); break; + case Intrinsic::dbg_label: // llvm.dbg.label + visitDbgLabelIntrinsic("label", cast(*CS.getInstruction())); + break; case Intrinsic::memcpy: case Intrinsic::memmove: case Intrinsic::memset: { @@ -4556,7 +4571,40 @@ verifyFnArgs(DII); } +void Verifier::visitDbgLabelIntrinsic(StringRef Kind, DbgLabelInst &DLI) { + AssertDI(isa(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(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; // Broken scope chains are checked elsewhere. + + AssertDI(LabelSP == LocSP, "mismatched subprogram between llvm.dbg." + Kind + + " variable and !dbg attachment", + &DLI, BB, F, Label, Label->getScope()->getSubprogram(), Loc, + Loc->getScope()->getSubprogram()); +} + void Verifier::verifyFragmentExpression(const DbgInfoIntrinsic &I) { + if (dyn_cast(&I)) + return; + DILocalVariable *V = dyn_cast_or_null(I.getRawVariable()); DIExpression *E = dyn_cast_or_null(I.getRawExpression()); Index: lib/Transforms/Utils/Local.cpp =================================================================== --- lib/Transforms/Utils/Local.cpp +++ lib/Transforms/Utils/Local.cpp @@ -372,6 +372,11 @@ return false; return true; } + if (DbgLabelInst *DLI = dyn_cast(I)) { + if (DLI->getLabel()) + return false; + return true; + } if (!I->mayHaveSideEffects()) return true; Index: lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- lib/Transforms/Utils/SimplifyCFG.cpp +++ lib/Transforms/Utils/SimplifyCFG.cpp @@ -3890,6 +3890,7 @@ switch (IntrinsicID) { case Intrinsic::dbg_declare: case Intrinsic::dbg_value: + case Intrinsic::dbg_label: case Intrinsic::lifetime_end: break; default: Index: test/DebugInfo/Generic/debug-label-bitcode.ll =================================================================== --- /dev/null +++ test/DebugInfo/Generic/debug-label-bitcode.ll @@ -0,0 +1,67 @@ +; Test bitcode writer/reader for DILabel metadata. +; RUN: llvm-as -o - %s | llvm-dis | FileCheck %s +; +; CHECK: top: +; CHECK: call void @llvm.dbg.label(metadata [[LABEL_METADATA:!.*]]) +; CHECK: [[LABEL_METADATA]] = !DILabel({{.*}}, name: "top", {{.*}}, line: 4) + +source_filename = "debug-label-bitcode.c" + +; Function Attrs: noinline nounwind optnone +define i32 @foo(i32 signext %a, i32 signext %b) !dbg !7 { +entry: + %a.addr = alloca i32, align 4 + %b.addr = alloca i32, align 4 + %sum = alloca i32, align 4 + store i32 %a, i32* %a.addr, align 4 + store i32 %b, i32* %b.addr, align 4 + br label %top, !dbg !17 + +top: ; preds = %entry + call void @llvm.dbg.label(metadata !18), !dbg !19 + %0 = load i32, i32* %a.addr, align 4, !dbg !20 + %1 = load i32, i32* %b.addr, align 4, !dbg !21 + %add = add nsw i32 %0, %1, !dbg !22 + store i32 %add, i32* %sum, align 4, !dbg !23 + br label %done, !dbg !24 + +done: ; preds = %top + call void @llvm.dbg.label(metadata !25), !dbg !26 + %2 = load i32, i32* %sum, align 4, !dbg !27 + ret i32 %2, !dbg !28 +} + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.label(metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "debug-label-bitcode.c", directory: "./") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !1, line: 1, type: !10) +!12 = !DILocation(line: 1, column: 13, scope: !7) +!13 = !DILocalVariable(name: "b", arg: 2, scope: !7, file: !1, line: 1, type: !10) +!14 = !DILocation(line: 1, column: 20, scope: !7) +!15 = !DILocalVariable(name: "sum", scope: !7, file: !1, line: 3, type: !10) +!16 = !DILocation(line: 3, column: 7, scope: !7) +!17 = !DILocation(line: 3, column: 3, scope: !7) +!18 = !DILabel(scope: !7, name: "top", file: !1, line: 4) +!19 = !DILocation(line: 4, column: 1, scope: !7) +!20 = !DILocation(line: 5, column: 9, scope: !7) +!21 = !DILocation(line: 5, column: 13, scope: !7) +!22 = !DILocation(line: 5, column: 11, scope: !7) +!23 = !DILocation(line: 5, column: 7, scope: !7) +!24 = !DILocation(line: 5, column: 3, scope: !7) +!25 = !DILabel(scope: !7, name: "done", file: !1, line: 7) +!26 = !DILocation(line: 7, column: 1, scope: !7) +!27 = !DILocation(line: 8, column: 10, scope: !7) +!28 = !DILocation(line: 8, column: 3, scope: !7)