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. @@ -79,6 +80,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 +596,13 @@ 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); + /// Create a new descriptor for a parameter variable. /// /// \c Scope must be a \a DILocalScope, and thus its scope chain eventually @@ -782,6 +794,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: @@ -2603,6 +2604,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 @@ -4564,6 +4564,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: @@ -1647,6 +1648,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, @@ -1779,6 +1781,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 @@ -1968,6 +1968,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) { @@ -699,6 +699,16 @@ /* AlignInBits */0); } +DILabel *DIBuilder::createLabel(DIScope *Scope, StringRef Name, DIFile *File, + unsigned LineNo) { + DIScope *Context = getNonCompileUnitScope(Scope); + + auto *Node = + DILabel::get(VMContext, cast_or_null(Context), Name, + File, LineNo); + return Node; +} + DIExpression *DIBuilder::createExpression(ArrayRef Addr) { return DIExpression::get(VMContext, Addr); } @@ -821,6 +831,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 +928,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 @@ -653,6 +653,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 @@ -948,6 +948,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)