diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h index f07f4c61f9d64..e5e1ade8b38b3 100644 --- a/llvm/include/llvm/AsmParser/LLParser.h +++ b/llvm/include/llvm/AsmParser/LLParser.h @@ -178,6 +178,9 @@ namespace llvm { /// UpgradeDebuginfo so it can generate broken bitcode. bool UpgradeDebugInfo; + bool SeenNewDbgInfoFormat = false; + bool SeenOldDbgInfoFormat = false; + std::string SourceFileName; public: @@ -573,6 +576,7 @@ namespace llvm { bool parseMDNodeTail(MDNode *&N); bool parseMDNodeVector(SmallVectorImpl &Elts); bool parseMetadataAttachment(unsigned &Kind, MDNode *&MD); + bool parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS); bool parseInstructionMetadata(Instruction &Inst); bool parseGlobalObjectMetadataAttachment(GlobalObject &GO); bool parseOptionalFunctionMetadata(Function &F); diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h index 3c34706ee03e8..5863a8d6e8ee8 100644 --- a/llvm/include/llvm/AsmParser/LLToken.h +++ b/llvm/include/llvm/AsmParser/LLToken.h @@ -36,6 +36,7 @@ enum Kind { exclaim, // ! bar, // | colon, // : + hash, // # kw_vscale, kw_x, @@ -479,6 +480,7 @@ enum Kind { DISPFlag, // DISPFlagFoo DwarfMacinfo, // DW_MACINFO_foo ChecksumKind, // CSK_foo + DbgRecordType, // dbg_foo // Type valued tokens (TyVal). Type, diff --git a/llvm/include/llvm/IR/DebugProgramInstruction.h b/llvm/include/llvm/IR/DebugProgramInstruction.h index cf30b4d0b0aaf..a8faf415a3ea8 100644 --- a/llvm/include/llvm/IR/DebugProgramInstruction.h +++ b/llvm/include/llvm/IR/DebugProgramInstruction.h @@ -223,9 +223,19 @@ inline raw_ostream &operator<<(raw_ostream &OS, const DbgRecord &R) { class DPLabel : public DbgRecord { DbgRecordParamRef Label; + /// This constructor intentionally left private, so that it is only called via + /// "createUnresolvedDPLabel", which clearly expresses that it is for parsing + /// only. + DPLabel(MDNode *Label, MDNode *DL); + public: DPLabel(DILabel *Label, DebugLoc DL); + /// For use during parsing; creates a DPLabel from as-of-yet unresolved + /// MDNodes. Trying to access the resulting DPLabel's fields before they are + /// resolved, or if they resolve to the wrong type, will result in a crash. + static DPLabel *createUnresolvedDPLabel(MDNode *Label, MDNode *DL); + DPLabel *clone() const; void print(raw_ostream &O, bool IsForDebug = false) const; void print(raw_ostream &ROS, ModuleSlotTracker &MST, bool IsForDebug) const; @@ -286,6 +296,29 @@ class DPValue : public DbgRecord, protected DebugValueUser { DIAssignID *AssignID, Metadata *Address, DIExpression *AddressExpression, const DILocation *DI); +private: + /// Private constructor for creating new instances during parsing only. Only + /// called through `createUnresolvedDPValue` below, which makes clear that + /// this is used for parsing only, and will later return a subclass depending + /// on which Type is passed. + DPValue(LocationType Type, Metadata *Val, MDNode *Variable, + MDNode *Expression, MDNode *AssignID, Metadata *Address, + MDNode *AddressExpression, MDNode *DI); + +public: + /// Used to create DPValues during parsing, where some metadata references may + /// still be unresolved. Although for some fields a generic `Metadata*` + /// argument is accepted for forward type-references, the verifier and + /// accessors will reject incorrect types later on. The function is used for + /// all types of DPValues for simplicity while parsing, but asserts if any + /// necessary fields are empty or unused fields are not empty, i.e. if the + /// #dbg_assign fields are used for a non-dbg-assign type. + static DPValue *createUnresolvedDPValue(LocationType Type, Metadata *Val, + MDNode *Variable, MDNode *Expression, + MDNode *AssignID, Metadata *Address, + MDNode *AddressExpression, + MDNode *DI); + static DPValue *createDPVAssign(Value *Val, DILocalVariable *Variable, DIExpression *Expression, DIAssignID *AssignID, Value *Address, diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index 5d8a50eee1306..02f64fcfac4f0 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -438,9 +438,12 @@ lltok::Kind LLLexer::LexCaret() { /// Lex all tokens that start with a # character. /// AttrGrpID ::= #[0-9]+ +/// Hash ::= # lltok::Kind LLLexer::LexHash() { // Handle AttrGrpID: #[0-9]+ - return LexUIntID(lltok::AttrGrpID); + if (isdigit(static_cast(CurPtr[0]))) + return LexUIntID(lltok::AttrGrpID); + return lltok::hash; } /// Lex a label, integer type, keyword, or hexadecimal integer constant. @@ -923,6 +926,21 @@ lltok::Kind LLLexer::LexIdentifier() { #undef DWKEYWORD +// Keywords for debug record types. +#define DBGRECORDTYPEKEYWORD(STR) \ + do { \ + if (Keyword == "dbg_" #STR) { \ + StrVal = #STR; \ + return lltok::DbgRecordType; \ + } \ + } while (false) + + DBGRECORDTYPEKEYWORD(value); + DBGRECORDTYPEKEYWORD(declare); + DBGRECORDTYPEKEYWORD(assign); + DBGRECORDTYPEKEYWORD(label); +#undef DBGRECORDTYPEKEYWORD + if (Keyword.starts_with("DIFlag")) { StrVal.assign(Keyword.begin(), Keyword.end()); return lltok::DIFlag; diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index a91e2f690999e..e140c94195205 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -62,6 +62,8 @@ static cl::opt AllowIncompleteIR( "Allow incomplete IR on a best effort basis (references to unknown " "metadata will be dropped)")); +extern llvm::cl::opt UseNewDbgInfoFormat; + static std::string getTypeString(Type *T) { std::string Result; raw_string_ostream Tmp(Result); @@ -69,6 +71,15 @@ static std::string getTypeString(Type *T) { return Tmp.str(); } +// Currently, we should always process modules in the old debug info format by +// default regardless of the module's format in IR; convert it to the old format +// here. +bool finalizeDebugInfoFormat(Module *M) { + if (M) + M->setIsNewDbgInfoFormat(false); + return false; +} + /// Run: module ::= toplevelentity* bool LLParser::Run(bool UpgradeDebugInfo, DataLayoutCallbackTy DataLayoutCallback) { @@ -86,7 +97,7 @@ bool LLParser::Run(bool UpgradeDebugInfo, } return parseTopLevelEntities() || validateEndOfModule(UpgradeDebugInfo) || - validateEndOfIndex(); + validateEndOfIndex() || finalizeDebugInfoFormat(M); } bool LLParser::parseStandaloneConstantValue(Constant *&C, @@ -6041,6 +6052,17 @@ bool LLParser::parseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc, return false; } +bool isOldDbgFormatIntrinsic(StringRef Name) { + // Exit early for the common (non-debug-intrinsic) case. + // We can make this the only check when we begin supporting all "llvm.dbg" + // intrinsics in the new debug info format. + if (!Name.starts_with("llvm.dbg.")) + return false; + Intrinsic::ID FnID = Function::lookupIntrinsicID(Name); + return FnID == Intrinsic::dbg_declare || FnID == Intrinsic::dbg_value || + FnID == Intrinsic::dbg_assign; +} + /// FunctionHeader /// ::= OptionalLinkage OptionalPreemptionSpecifier OptionalVisibility /// OptionalCallingConv OptRetAttrs OptUnnamedAddr Type GlobalName @@ -6390,9 +6412,31 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) { std::string NameStr; - // parse the instructions in this block until we get a terminator. + // Parse the instructions and debug values in this block until we get a + // terminator. Instruction *Inst; + auto DeleteDbgRecord = [](DbgRecord *DR) { DR->deleteRecord(); }; + using DbgRecordPtr = std::unique_ptr; + SmallVector TrailingDbgRecord; do { + // Handle debug records first - there should always be an instruction + // following the debug records, i.e. they cannot appear after the block + // terminator. + while (Lex.getKind() == lltok::hash) { + if (SeenOldDbgInfoFormat) + return error(Lex.getLoc(), "debug record should not appear in a module " + "containing debug info intrinsics"); + SeenNewDbgInfoFormat = true; + Lex.Lex(); + if (!M->IsNewDbgInfoFormat) + M->convertToNewDbgValues(); + + DbgRecord *DR; + if (parseDebugRecord(DR, PFS)) + return true; + TrailingDbgRecord.emplace_back(DR, DeleteDbgRecord); + } + // This instruction may have three possibilities for a name: a) none // specified, b) name specified "%foo =", c) number specified: "%4 =". LocTy NameLoc = Lex.getLoc(); @@ -6437,11 +6481,121 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) { // Set the name on the instruction. if (PFS.setInstName(NameID, NameStr, NameLoc, Inst)) return true; + + // Attach any preceding debug values to this instruction. + for (DbgRecordPtr &DR : TrailingDbgRecord) + BB->insertDPValueBefore(DR.release(), Inst->getIterator()); + TrailingDbgRecord.clear(); } while (!Inst->isTerminator()); + assert(TrailingDbgRecord.empty() && + "All debug values should have been attached to an instruction."); + return false; } +/// parseDebugRecord +/// ::= #dbg_label '(' MDNode ')' +/// ::= #dbg_type '(' Metadata ',' MDNode ',' Metadata ',' +/// (MDNode ',' Metadata ',' Metadata ',')? MDNode ')' +bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) { + using RecordKind = DbgRecord::Kind; + using LocType = DPValue::LocationType; + LocTy DPVLoc = Lex.getLoc(); + if (Lex.getKind() != lltok::DbgRecordType) + return error(DPVLoc, "expected debug record type here"); + RecordKind RecordType = StringSwitch(Lex.getStrVal()) + .Case("declare", RecordKind::ValueKind) + .Case("value", RecordKind::ValueKind) + .Case("assign", RecordKind::ValueKind) + .Case("label", RecordKind::LabelKind); + + // Parsing labels is trivial; parse here and early exit, otherwise go into the + // full DPValue processing stage. + if (RecordType == RecordKind::LabelKind) { + Lex.Lex(); + if (parseToken(lltok::lparen, "Expected '(' here")) + return true; + MDNode *Label; + if (parseMDNode(Label)) + return true; + if (parseToken(lltok::comma, "Expected ',' here")) + return true; + MDNode *DbgLoc; + if (parseMDNode(DbgLoc)) + return true; + if (parseToken(lltok::rparen, "Expected ')' here")) + return true; + DR = DPLabel::createUnresolvedDPLabel(Label, DbgLoc); + return false; + } + + LocType ValueType = StringSwitch(Lex.getStrVal()) + .Case("declare", LocType::Declare) + .Case("value", LocType::Value) + .Case("assign", LocType::Assign); + + Lex.Lex(); + if (parseToken(lltok::lparen, "Expected '(' here")) + return true; + + // Parse Value field. + Metadata *ValLocMD; + if (parseMetadata(ValLocMD, &PFS)) + return true; + if (parseToken(lltok::comma, "Expected ',' here")) + return true; + + // Parse Variable field. + MDNode *Variable; + if (parseMDNode(Variable)) + return true; + if (parseToken(lltok::comma, "Expected ',' here")) + return true; + + // Parse Expression field. + MDNode *Expression; + if (parseMDNode(Expression)) + return true; + if (parseToken(lltok::comma, "Expected ',' here")) + return true; + + // Parse additional fields for #dbg_assign. + MDNode *AssignID = nullptr; + Metadata *AddressLocation = nullptr; + MDNode *AddressExpression = nullptr; + if (ValueType == LocType::Assign) { + // Parse DIAssignID. + if (parseMDNode(AssignID)) + return true; + if (parseToken(lltok::comma, "Expected ',' here")) + return true; + + // Parse address ValueAsMetadata. + if (parseMetadata(AddressLocation, &PFS)) + return true; + if (parseToken(lltok::comma, "Expected ',' here")) + return true; + + // Parse address DIExpression. + if (parseMDNode(AddressExpression)) + return true; + if (parseToken(lltok::comma, "Expected ',' here")) + return true; + } + + /// Parse DILocation. + MDNode *DebugLoc; + if (parseMDNode(DebugLoc)) + return true; + + if (parseToken(lltok::rparen, "Expected ')' here")) + return true; + DR = DPValue::createUnresolvedDPValue(ValueType, ValLocMD, Variable, + Expression, AssignID, AddressLocation, + AddressExpression, DebugLoc); + return false; +} //===----------------------------------------------------------------------===// // Instruction Parsing. //===----------------------------------------------------------------------===// @@ -7669,6 +7823,16 @@ bool LLParser::parseCall(Instruction *&Inst, PerFunctionState &PFS, } CI->setFastMathFlags(FMF); } + + if (CalleeID.Kind == ValID::t_GlobalName && + isOldDbgFormatIntrinsic(CalleeID.StrVal)) { + if (SeenNewDbgInfoFormat) { + CI->deleteValue(); + return error(CallLoc, "llvm.dbg intrinsic should not appear in a module " + "using non-intrinsic debug info"); + } + SeenOldDbgInfoFormat = true; + } CI->setAttributes(PAL); ForwardRefAttrGroups[CI] = FwdRefAttrGrps; Inst = CI; diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp index a8d64024e1797..5ff1e8c19db68 100644 --- a/llvm/lib/IR/DebugProgramInstruction.cpp +++ b/llvm/lib/IR/DebugProgramInstruction.cpp @@ -138,11 +138,38 @@ DbgRecord::createDebugIntrinsic(Module *M, Instruction *InsertBefore) const { llvm_unreachable("unsupported DbgRecord kind"); } +DPLabel::DPLabel(MDNode *Label, MDNode *DL) + : DbgRecord(LabelKind, DebugLoc(DL)), Label(Label) { + assert(Label && "Unexpected nullptr"); + assert((isa(Label) || Label->isTemporary()) && + "Label type must be or resolve to a DILabel"); +} DPLabel::DPLabel(DILabel *Label, DebugLoc DL) : DbgRecord(LabelKind, DL), Label(Label) { assert(Label && "Unexpected nullptr"); } +DPLabel *DPLabel::createUnresolvedDPLabel(MDNode *Label, MDNode *DL) { + return new DPLabel(Label, DL); +} + +DPValue::DPValue(DPValue::LocationType Type, Metadata *Val, MDNode *Variable, + MDNode *Expression, MDNode *AssignID, Metadata *Address, + MDNode *AddressExpression, MDNode *DI) + : DbgRecord(ValueKind, DebugLoc(DI)), + DebugValueUser({Val, Address, AssignID}), Type(Type), Variable(Variable), + Expression(Expression), AddressExpression(AddressExpression) {} + +DPValue *DPValue::createUnresolvedDPValue(DPValue::LocationType Type, + Metadata *Val, MDNode *Variable, + MDNode *Expression, MDNode *AssignID, + Metadata *Address, + MDNode *AddressExpression, + MDNode *DI) { + return new DPValue(Type, Val, Variable, Expression, AssignID, Address, + AddressExpression, DI); +} + DPValue *DPValue::createDPValue(Value *Location, DILocalVariable *DV, DIExpression *Expr, const DILocation *DI) { return new DPValue(ValueAsMetadata::get(Location), DV, Expr, DI, diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 027c6ccd1ab30..00112dae200a7 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -6291,7 +6291,7 @@ void Verifier::visit(DPValue &DPV) { Var->getRawType()); auto *DLNode = DPV.getDebugLoc().getAsMDNode(); - CheckDI(isa_and_nonnull(DLNode), "invalid #dbg record location", + CheckDI(isa_and_nonnull(DLNode), "invalid #dbg record DILocation", &DPV, DLNode); DILocation *Loc = DPV.getDebugLoc(); diff --git a/llvm/test/Assembler/dbg-record-invalid-0.ll b/llvm/test/Assembler/dbg-record-invalid-0.ll new file mode 100644 index 0000000000000..feb513a405f9e --- /dev/null +++ b/llvm/test/Assembler/dbg-record-invalid-0.ll @@ -0,0 +1,38 @@ +;; Test that we get a parser error when a debug record appears post-terminator. +;; Note: From the parser's perspective, the error is that the debug record is +;; appearing at the start of a new unnamed basic block which contains no actual +;; instructions. +; RUN: not llvm-as < %s 2>&1 | FileCheck %s +; ModuleID = '' +source_filename = "" + +define dso_local i32 @f(i32 %a) !dbg !7 { +entry: + ret i32 %a, !dbg !18 + #dbg_value(!DIArgList(i32 %a), !12, !DIExpression(), !14) +; CHECK: :[[@LINE+1]]:1: error: expected instruction opcode +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 18.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "print.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 5} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 18.0.0"} +!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12, !13} +!12 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !1, line: 3, type: !10) +!13 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 3, type: !10) +!14 = !DILocation(line: 3, column: 15, scope: !7) +!15 = distinct !DIAssignID() +!16 = !DILocation(line: 3, column: 20, scope: !7) +!17 = !DILocation(line: 3, column: 25, scope: !7) +!18 = !DILocation(line: 3, column: 30, scope: !7) diff --git a/llvm/test/Assembler/dbg-record-invalid-1.ll b/llvm/test/Assembler/dbg-record-invalid-1.ll new file mode 100644 index 0000000000000..7ab5751777e8c --- /dev/null +++ b/llvm/test/Assembler/dbg-record-invalid-1.ll @@ -0,0 +1,39 @@ +;; Test that we get a parser error when a debug intrinsic appears in the same +;; module as a debug record. +; RUN: not llvm-as < %s 2>&1 | FileCheck %s +; ModuleID = '' +source_filename = "" + +define dso_local i32 @f(i32 %a) !dbg !7 { +entry: + #dbg_value(!DIArgList(i32 %a), !12, !DIExpression(), !14) +; CHECK: :[[@LINE+1]]:8: error: llvm.dbg intrinsic should not appear in a module using non-intrinsic debug info + call void @llvm.dbg.value(metadata i32 %a, metadata !12, metadata !DIExpression()), !dbg !14 + ret i32 %a, !dbg !18 +} + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 18.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "print.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 5} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 18.0.0"} +!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12, !13} +!12 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !1, line: 3, type: !10) +!13 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 3, type: !10) +!14 = !DILocation(line: 3, column: 15, scope: !7) +!15 = distinct !DIAssignID() +!16 = !DILocation(line: 3, column: 20, scope: !7) +!17 = !DILocation(line: 3, column: 25, scope: !7) +!18 = !DILocation(line: 3, column: 30, scope: !7) diff --git a/llvm/test/Assembler/dbg-record-invalid-2.ll b/llvm/test/Assembler/dbg-record-invalid-2.ll new file mode 100644 index 0000000000000..a019f73feab9c --- /dev/null +++ b/llvm/test/Assembler/dbg-record-invalid-2.ll @@ -0,0 +1,36 @@ +;; Test that we get a parser error when we have a debug record with an +;; incorrect number of arguments. +; RUN: not llvm-as < %s 2>&1 | FileCheck %s +; ModuleID = '' +source_filename = "" + +define dso_local i32 @f(i32 %a) !dbg !7 { +entry: +; CHECK: :[[@LINE+1]]:24: error: expected '!' here + #dbg_value(i32 %a, i32 0, !DIExpression(), !14) + ret i32 %a, !dbg !18 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 18.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "print.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 5} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 18.0.0"} +!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12, !13} +!12 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !1, line: 3, type: !10) +!13 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 3, type: !10) +!14 = !DILocation(line: 3, column: 15, scope: !7) +!15 = distinct !DIAssignID() +!16 = !DILocation(line: 3, column: 20, scope: !7) +!17 = !DILocation(line: 3, column: 25, scope: !7) +!18 = !DILocation(line: 3, column: 30, scope: !7) diff --git a/llvm/test/Assembler/dbg-record-invalid-3.ll b/llvm/test/Assembler/dbg-record-invalid-3.ll new file mode 100644 index 0000000000000..e6f072373f54d --- /dev/null +++ b/llvm/test/Assembler/dbg-record-invalid-3.ll @@ -0,0 +1,39 @@ +;; Test that we get a parser error when a debug record appears in the same +;; module as a debug intrinsic. +; RUN: not llvm-as < %s 2>&1 | FileCheck %s +; ModuleID = '' +source_filename = "" + +define dso_local i32 @f(i32 %a) !dbg !7 { +entry: + call void @llvm.dbg.value(metadata i32 %a, metadata !12, metadata !DIExpression()), !dbg !14 +; CHECK: :[[@LINE+1]]:5: error: debug record should not appear in a module containing debug info intrinsics + #dbg_value(!DIArgList(i32 %a), !12, !DIExpression(), !14) + ret i32 %a, !dbg !18 +} + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 18.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "print.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 5} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 18.0.0"} +!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12, !13} +!12 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !1, line: 3, type: !10) +!13 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 3, type: !10) +!14 = !DILocation(line: 3, column: 15, scope: !7) +!15 = distinct !DIAssignID() +!16 = !DILocation(line: 3, column: 20, scope: !7) +!17 = !DILocation(line: 3, column: 25, scope: !7) +!18 = !DILocation(line: 3, column: 30, scope: !7) diff --git a/llvm/test/Assembler/dbg-record-invalid-4.ll b/llvm/test/Assembler/dbg-record-invalid-4.ll new file mode 100644 index 0000000000000..f898477603c8e --- /dev/null +++ b/llvm/test/Assembler/dbg-record-invalid-4.ll @@ -0,0 +1,36 @@ +;; Test that we get a parser error when we have a debug record with an invalid +;; type. +; RUN: not llvm-as < %s 2>&1 | FileCheck %s +; ModuleID = '' +source_filename = "" + +define dso_local i32 @f(i32 %a) !dbg !7 { +entry: +; CHECK: :[[@LINE+1]]:6: error: expected debug record type here + #dbg_invalid(!DIArgList(i32 %a), !12, !DIExpression(), !14) + ret i32 %a, !dbg !18 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 18.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "print.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 5} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 18.0.0"} +!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12, !13} +!12 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !1, line: 3, type: !10) +!13 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 3, type: !10) +!14 = !DILocation(line: 3, column: 15, scope: !7) +!15 = distinct !DIAssignID() +!16 = !DILocation(line: 3, column: 20, scope: !7) +!17 = !DILocation(line: 3, column: 25, scope: !7) +!18 = !DILocation(line: 3, column: 30, scope: !7) diff --git a/llvm/test/Assembler/dbg-record-invalid-5.ll b/llvm/test/Assembler/dbg-record-invalid-5.ll new file mode 100644 index 0000000000000..5ea588b87668c --- /dev/null +++ b/llvm/test/Assembler/dbg-record-invalid-5.ll @@ -0,0 +1,35 @@ +;; Test that we get a parser error when a basic block contains only a debug +;; record. +; RUN: not llvm-as < %s 2>&1 | FileCheck %s +; ModuleID = '' +source_filename = "" + +define dso_local i32 @f(i32 %a) !dbg !7 { +entry: + #dbg_value(!DIArgList(i32 %a), !12, !DIExpression(), !14) +; CHECK: :[[@LINE+1]]:1: error: expected instruction opcode +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 18.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "print.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 5} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 18.0.0"} +!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12, !13} +!12 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !1, line: 3, type: !10) +!13 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 3, type: !10) +!14 = !DILocation(line: 3, column: 15, scope: !7) +!15 = distinct !DIAssignID() +!16 = !DILocation(line: 3, column: 20, scope: !7) +!17 = !DILocation(line: 3, column: 25, scope: !7) +!18 = !DILocation(line: 3, column: 30, scope: !7) diff --git a/llvm/test/Assembler/dbg-record-invalid-6.ll b/llvm/test/Assembler/dbg-record-invalid-6.ll new file mode 100644 index 0000000000000..72dafcdb97fce --- /dev/null +++ b/llvm/test/Assembler/dbg-record-invalid-6.ll @@ -0,0 +1,36 @@ +;; Test that we get a parser error when we have a debug record with an +;; incorrect number of arguments. +; RUN: not llvm-as < %s 2>&1 | FileCheck %s +; ModuleID = '' +source_filename = "" + +define dso_local i32 @f(i32 %a) !dbg !7 { +entry: +; CHECK: :[[@LINE+1]]:46: error: expected '!' here + #dbg_value(i32 %a, !12, !DIExpression(), i32 0) + ret i32 %a, !dbg !18 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 18.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "print.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 5} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 18.0.0"} +!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12, !13} +!12 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !1, line: 3, type: !10) +!13 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 3, type: !10) +!14 = !DILocation(line: 3, column: 15, scope: !7) +!15 = distinct !DIAssignID() +!16 = !DILocation(line: 3, column: 20, scope: !7) +!17 = !DILocation(line: 3, column: 25, scope: !7) +!18 = !DILocation(line: 3, column: 30, scope: !7) diff --git a/llvm/test/Assembler/dbg-record-invalid-7.ll b/llvm/test/Assembler/dbg-record-invalid-7.ll new file mode 100644 index 0000000000000..036a85a2977fc --- /dev/null +++ b/llvm/test/Assembler/dbg-record-invalid-7.ll @@ -0,0 +1,36 @@ +;; Test that we get a parser error when we have a debug record with an incorrect +;; number of arguments. +; RUN: not llvm-as < %s 2>&1 | FileCheck %s +; ModuleID = '' +source_filename = "" + +define dso_local i32 @f(i32 %a) !dbg !7 { +entry: +; CHECK: :[[@LINE+1]]:44: error: Expected ',' here + #dbg_value(i32 %a, !12, !DIExpression()) + ret i32 %a, !dbg !18 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 18.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "print.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 5} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 18.0.0"} +!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12, !13} +!12 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !1, line: 3, type: !10) +!13 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 3, type: !10) +!14 = !DILocation(line: 3, column: 15, scope: !7) +!15 = distinct !DIAssignID() +!16 = !DILocation(line: 3, column: 20, scope: !7) +!17 = !DILocation(line: 3, column: 25, scope: !7) +!18 = !DILocation(line: 3, column: 30, scope: !7) diff --git a/llvm/test/Assembler/dbg-record-invalid-8.ll b/llvm/test/Assembler/dbg-record-invalid-8.ll new file mode 100644 index 0000000000000..d0b8f36d7895c --- /dev/null +++ b/llvm/test/Assembler/dbg-record-invalid-8.ll @@ -0,0 +1,36 @@ +;; Test that we get a parser error when we have a debug assign record with an +;; incorrect number of arguments. +; RUN: not llvm-as < %s 2>&1 | FileCheck %s +; ModuleID = '' +source_filename = "" + +define dso_local i32 @f(i32 %a) !dbg !7 { +entry: +; CHECK: :[[@LINE+1]]:50: error: Expected ',' here + #dbg_assign(i32 %a, !12, !DIExpression(), !14) + ret i32 %a, !dbg !18 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 18.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "print.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 5} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 18.0.0"} +!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12, !13} +!12 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !1, line: 3, type: !10) +!13 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 3, type: !10) +!14 = !DILocation(line: 3, column: 15, scope: !7) +!15 = distinct !DIAssignID() +!16 = !DILocation(line: 3, column: 20, scope: !7) +!17 = !DILocation(line: 3, column: 25, scope: !7) +!18 = !DILocation(line: 3, column: 30, scope: !7) diff --git a/llvm/test/DebugInfo/roundtrip-non-instruction-debug-info.ll b/llvm/test/DebugInfo/roundtrip-non-instruction-debug-info.ll new file mode 100644 index 0000000000000..b15b76d1690c4 --- /dev/null +++ b/llvm/test/DebugInfo/roundtrip-non-instruction-debug-info.ll @@ -0,0 +1,94 @@ +;; Test that we can write in the old debug info format. +; RUN: opt --passes=verify -S --write-experimental-debuginfo=false < %s \ +; RUN: | FileCheck %s --check-prefixes=CHECK,OLDDBG --implicit-check-not=llvm.dbg --implicit-check-not=#dbg + +;; Test that we can write in the new debug info format... +; RUN: opt --passes=verify -S --write-experimental-debuginfo=true < %s \ +; RUN: | FileCheck %s --check-prefixes=CHECK,NEWDBG --implicit-check-not=llvm.dbg --implicit-check-not=#dbg + +;; ...and then read the new format and write the old format. +; RUN: opt --passes=verify -S --write-experimental-debuginfo=true < %s \ +; RUN: | opt --passes=verify -S --write-experimental-debuginfo=false \ +; RUN: | FileCheck %s --check-prefixes=CHECK,OLDDBG --implicit-check-not=llvm.dbg --implicit-check-not=#dbg + +;; Test also that the new flag is independent of the flag that enables use of +;; these non-instruction debug info during LLVM passes. +; RUN: opt --passes=verify -S --try-experimental-debuginfo-iterators --write-experimental-debuginfo=false < %s \ +; RUN: | FileCheck %s --check-prefixes=CHECK,OLDDBG --implicit-check-not=llvm.dbg --implicit-check-not=#dbg +; RUN: opt --passes=verify -S --try-experimental-debuginfo-iterators --write-experimental-debuginfo=true < %s \ +; RUN: | FileCheck %s --check-prefixes=CHECK,NEWDBG --implicit-check-not=llvm.dbg --implicit-check-not=#dbg + +; CHECK: @f(i32 %[[VAL_A:[0-9a-zA-Z]+]]) +; CHECK-NEXT: entry: +; OLDDBG-NEXT: call void @llvm.dbg.value(metadata i32 %[[VAL_A]], metadata ![[VAR_A:[0-9]+]], metadata !DIExpression()), !dbg ![[LOC_1:[0-9]+]] +; NEWDBG-NEXT: {{^}} #dbg_value(i32 %[[VAL_A]], ![[VAR_A:[0-9]+]], !DIExpression(), ![[LOC_1:[0-9]+]]) +; CHECK-NEXT: {{^}} %[[VAL_B:[0-9a-zA-Z]+]] = alloca +; OLDDBG-NEXT: call void @llvm.dbg.declare(metadata ptr %[[VAL_B]], metadata ![[VAR_B:[0-9]+]], metadata !DIExpression()), !dbg ![[LOC_2:[0-9]+]] +; NEWDBG-NEXT: {{^}} #dbg_declare(ptr %[[VAL_B]], ![[VAR_B:[0-9]+]], !DIExpression(), ![[LOC_2:[0-9]+]]) +; CHECK-NEXT: {{^}} %[[VAL_ADD:[0-9a-zA-Z]+]] = add i32 %[[VAL_A]], 5 +; OLDDBG-NEXT: call void @llvm.dbg.value(metadata !DIArgList(i32 %[[VAL_A]], i32 %[[VAL_ADD]]), metadata ![[VAR_A]], metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus)), !dbg ![[LOC_3:[0-9]+]] +; NEWDBG-NEXT: {{^}} #dbg_value(!DIArgList(i32 %[[VAL_A]], i32 %[[VAL_ADD]]), ![[VAR_A]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus), ![[LOC_3:[0-9]+]]) +; OLDDBG-NEXT: call void @llvm.dbg.label(metadata ![[LABEL_ID:[0-9]+]]), !dbg ![[LOC_3]] +; NEWDBG-NEXT: {{^}} #dbg_label(![[LABEL_ID:[0-9]+]], ![[LOC_3]]) +; CHECK-NEXT: {{^}} store i32 %[[VAL_ADD]]{{.+}}, !DIAssignID ![[ASSIGNID:[0-9]+]] +; OLDDBG-NEXT: call void @llvm.dbg.assign(metadata i32 %[[VAL_ADD]], metadata ![[VAR_B]], metadata !DIExpression(), metadata ![[ASSIGNID]], metadata ptr %[[VAL_B]], metadata !DIExpression()), !dbg ![[LOC_4:[0-9]+]] +; NEWDBG-NEXT: {{^}} #dbg_assign(i32 %[[VAL_ADD]], ![[VAR_B]], !DIExpression(), ![[ASSIGNID]], ptr %[[VAL_B]], !DIExpression(), ![[LOC_4:[0-9]+]]) +; CHECK-NEXT: {{^}} ret i32 + +; OLDDBG-DAG: declare void @llvm.dbg.value +; OLDDBG-DAG: declare void @llvm.dbg.declare +; OLDDBG-DAG: declare void @llvm.dbg.assign +; OLDDBG-DAG: declare void @llvm.dbg.label + +; CHECK-DAG: llvm.dbg.cu +; CHECK-DAG: ![[VAR_A]] = !DILocalVariable(name: "a" +; CHECK-DAG: ![[VAR_B]] = !DILocalVariable(name: "b" +; CHECK-DAG: ![[LOC_1]] = !DILocation(line: 3, column: 15 +; CHECK-DAG: ![[LOC_2]] = !DILocation(line: 3, column: 20 +; CHECK-DAG: ![[LOC_3]] = !DILocation(line: 3, column: 25 +; CHECK-DAG: ![[LOC_4]] = !DILocation(line: 3, column: 30 +; CHECK-DAG: ![[LABEL_ID]] = !DILabel( + +define dso_local i32 @f(i32 %a) !dbg !7 { +entry: + call void @llvm.dbg.value(metadata i32 %a, metadata !20, metadata !DIExpression()), !dbg !30 + %b = alloca i32, !dbg !30, !DIAssignID !40 + call void @llvm.dbg.declare(metadata ptr %b, metadata !21, metadata !DIExpression()), !dbg !31 + %add = add i32 %a, 5, !dbg !31 + call void @llvm.dbg.value(metadata !DIArgList(i32 %a, i32 %add), metadata !20, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus)), !dbg !32 + call void @llvm.dbg.label(metadata !50), !dbg !32 + store i32 %add, ptr %b, !dbg !32, !DIAssignID !40 + call void @llvm.dbg.assign(metadata i32 %add, metadata !21, metadata !DIExpression(), metadata !40, metadata ptr %b, metadata !DIExpression()), !dbg !33 + ret i32 %add, !dbg !33 + +} + +declare void @llvm.dbg.value(metadata, metadata, metadata) +declare void @llvm.dbg.declare(metadata, metadata, metadata) +declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) +declare void @llvm.dbg.label(metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 18.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "print.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 5} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 18.0.0"} +!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !8, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !13) +!8 = !DISubroutineType(types: !9) +!9 = !{!12, !12} +!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!13 = !{!20, !21} +!20 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !1, line: 3, type: !12) +!21 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 3, type: !12) +!30 = !DILocation(line: 3, column: 15, scope: !7) +!31 = !DILocation(line: 3, column: 20, scope: !7) +!32 = !DILocation(line: 3, column: 25, scope: !7) +!33 = !DILocation(line: 3, column: 30, scope: !7) +!40 = distinct !DIAssignID() +!50 = !DILabel(scope: !7, name: "label", file: !1, line: 3) \ No newline at end of file diff --git a/llvm/test/Verifier/RemoveDI/blockbyref.ll b/llvm/test/Verifier/RemoveDI/blockbyref.ll new file mode 100644 index 0000000000000..86321a6ae78e8 --- /dev/null +++ b/llvm/test/Verifier/RemoveDI/blockbyref.ll @@ -0,0 +1,18 @@ +; RUN: llvm-as -disable-output <%s 2>&1| FileCheck %s + +; CHECK: DIBlockByRefStruct on DICompositeType is no longer supported +; CHECK: warning: ignoring invalid debug info + +define void @foo() { +entry: + %s = alloca i32 + #dbg_declare(ptr %s, !2, !DIExpression(), !DILocation(scope: !1)) + ret void +} + + +!llvm.module.flags = !{!0} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DISubprogram() +!2 = !DILocalVariable(scope: !1, type: !3) +!3 = !DICompositeType(tag: DW_TAG_structure_type, flags: DIFlagReservedBit4) diff --git a/llvm/test/Verifier/RemoveDI/dbg-invalid-vector.ll b/llvm/test/Verifier/RemoveDI/dbg-invalid-vector.ll new file mode 100644 index 0000000000000..0832c361c3080 --- /dev/null +++ b/llvm/test/Verifier/RemoveDI/dbg-invalid-vector.ll @@ -0,0 +1,35 @@ +; RUN: opt -passes=verify -disable-output <%s 2>&1 | FileCheck %s +; +; This test creates an invalid vector by defining multiple elements for the +; vector's DICompositeType definition. A vector should only have one element +; in its DICompositeType 'elements' array. +; +; CHECK: invalid vector + +@f.foo = private unnamed_addr constant <6 x float> zeroinitializer, align 32 + +define void @f() { + %1 = alloca <6 x float>, align 32 + #dbg_declare(ptr %1, !10, !DIExpression(), !18) + ret void +} + + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "test.c", directory: "/dbg/info") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !8, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{null} +!10 = !DILocalVariable(name: "foo", scope: !7, file: !1, line: 4, type: !12) +!12 = !DICompositeType(tag: DW_TAG_array_type, baseType: !13, size: 256, flags: DIFlagVector, elements: !14) +!13 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) +!14 = !{!15, !19} +!15 = !DISubrange(count: 6) +!18 = !DILocation(line: 4, column: 48, scope: !7) +!19 = !DISubrange(count: 42) diff --git a/llvm/test/Verifier/RemoveDI/di-subroutine-localvar.ll b/llvm/test/Verifier/RemoveDI/di-subroutine-localvar.ll new file mode 100644 index 0000000000000..14e5888398996 --- /dev/null +++ b/llvm/test/Verifier/RemoveDI/di-subroutine-localvar.ll @@ -0,0 +1,41 @@ +; RUN: opt %s -passes=verify 2>&1 | FileCheck %s +; CHECK: invalid type +; CHECK: !20 = !DILocalVariable(name: "f", scope: !21, file: !13, line: 970, type: !14) +; CHECK: !14 = !DISubroutineType(types: !15) + + +%timespec.0.1.2.3.0.1.2 = type { i64, i64 } +define internal i64 @init_vdso_clock_gettime(i32, ptr nonnull) unnamed_addr !dbg !142 { + #dbg_value(ptr null, !162, !DIExpression(), !167) + ret i64 -38, !dbg !168 +} +!llvm.module.flags = !{!0} +!llvm.dbg.cu = !{!1} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "zig 0.3.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, globals: !76) +!2 = !DIFile(filename: "test", directory: ".") +!3 = !{!4} +!4 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Arch", scope: !5, file: !5, line: 44, baseType: !6, size: 8, align: 8, elements: !7) +!5 = !DIFile(filename: "builtin.zig", directory: "/home/andy/.local/share/zig/stage1/builtin/ugMGxVES9OkDAffv3xhJS3KQVy0Wm1xPM3Bc6x4MBuup5aetdi5pVTrGRG2aDAn0") +!6 = !DIBasicType(name: "u7", size: 8, encoding: DW_ATE_unsigned) +!7 = !{!8} +!8 = !DIEnumerator(name: "armv8_5a", value: 0) +!76 = !{!77} +!77 = !DIGlobalVariableExpression(var: !78, expr: !DIExpression()) +!78 = distinct !DIGlobalVariable(name: "arch", linkageName: "arch", scope: !5, file: !5, line: 437, type: !4, isLocal: true, isDefinition: true) +!81 = !DIFile(filename: "index.zig", directory: "/store/dev/zig/build-llvm8-debug/lib/zig/std/os/linux") +!142 = distinct !DISubprogram(name: "init_vdso_clock_gettime", scope: !81, file: !81, line: 968, type: !143, scopeLine: 968, flags: DIFlagStaticMember, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !1, retainedNodes: !153) +!143 = !DISubroutineType(types: !144) +!144 = !{!145} +!145 = !DIBasicType(name: "usize", size: 64, encoding: DW_ATE_unsigned) +!146 = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed) +!153 = !{!154} +!154 = !DILocalVariable(name: "clk", arg: 1, scope: !142, file: !81, line: 968, type: !146) +!162 = !DILocalVariable(name: "f", scope: !163, file: !81, line: 970, type: !143) +!163 = distinct !DILexicalBlock(scope: !164, file: !81, line: 969, column: 5) +!164 = distinct !DILexicalBlock(scope: !165, file: !81, line: 968, column: 66) +!165 = distinct !DILexicalBlock(scope: !166, file: !81, line: 968, column: 45) +!166 = distinct !DILexicalBlock(scope: !142, file: !81, line: 968, column: 35) +!167 = !DILocation(line: 970, column: 5, scope: !163) +!168 = !DILocation(line: 972, column: 28, scope: !169) +!169 = distinct !DILexicalBlock(scope: !163, file: !81, line: 970, column: 5) diff --git a/llvm/test/Verifier/RemoveDI/diexpression-entry-value-llvm-ir.ll b/llvm/test/Verifier/RemoveDI/diexpression-entry-value-llvm-ir.ll new file mode 100644 index 0000000000000..881ec4a86fb64 --- /dev/null +++ b/llvm/test/Verifier/RemoveDI/diexpression-entry-value-llvm-ir.ll @@ -0,0 +1,34 @@ +; RUN: llvm-as -disable-output <%s 2>&1| FileCheck %s + +; CHECK-NOT: #dbg_value +; CHECK: Entry values are only allowed in MIR unless they target a swiftasync Argument +; CHECK: #dbg_value(i32 %param, !{{.*}}, !DIExpression(DW_OP_LLVM_entry_value, 1) +; CHECK-NOT: #dbg_value +; CHECK-NOT: Entry values are only allowed +; CHECK: warning: ignoring invalid debug info + +define void @foo(i32 %param, ptr swiftasync %ok_param) !dbg !4 { +entry: + #dbg_value(i32 %param, !8, !DIExpression(DW_OP_LLVM_entry_value, 1), !9) + #dbg_value(ptr %ok_param, !8, !DIExpression(DW_OP_LLVM_entry_value, 1), !9) + #dbg_value(ptr poison, !8, !DIExpression(DW_OP_LLVM_entry_value, 1), !9) + #dbg_value(ptr undef, !8, !DIExpression(DW_OP_LLVM_entry_value, 1), !9) + ret void +} + + +attributes #0 = { nounwind readnone speculatable willreturn } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, emissionKind: FullDebug) +!1 = !DIFile(filename: "a.c", directory: "/") +!2 = !{i32 2, !"Dwarf Version", i32 4} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, type: !5, unit: !0) +!5 = !DISubroutineType(types: !6) +!6 = !{null, !7} +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !DILocalVariable(name: "param", arg: 1, scope: !4, file: !1, type: !7) +!9 = !DILocation(line: 0, scope: !4) diff --git a/llvm/test/Verifier/RemoveDI/fnarg-debuginfo.ll b/llvm/test/Verifier/RemoveDI/fnarg-debuginfo.ll new file mode 100644 index 0000000000000..db1a9a8ba1894 --- /dev/null +++ b/llvm/test/Verifier/RemoveDI/fnarg-debuginfo.ll @@ -0,0 +1,26 @@ +; RUN: llvm-as -disable-output < %s -o /dev/null 2>&1 | FileCheck %s + + +define void @foo() !dbg !2 { +entry: + %a = alloca i32 + ; CHECK: conflicting debug info for argument + #dbg_value(i32 0, !3, !DIExpression(), !6) + #dbg_declare(ptr %a, !4, !DIExpression(), !6) + ret void, !dbg !6 +} + +; CHECK: warning: ignoring invalid debug info + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!7, !8} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", emissionKind: FullDebug) +!1 = !DIFile(filename: "x.c", directory: "/") +!2 = distinct !DISubprogram(name: "foo", scope: !0, isDefinition: true, unit: !0) +!3 = !DILocalVariable(name: "a", arg: 1, scope: !2, file: !1, line: 1, type: !5) +!4 = !DILocalVariable(name: "b", arg: 1, scope: !2, file: !1, line: 1, type: !5) +!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!6 = !DILocation(line: 1, scope: !2) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 1, !"Debug Info Version", i32 3} diff --git a/llvm/test/Verifier/RemoveDI/fnarg-nodebug.ll b/llvm/test/Verifier/RemoveDI/fnarg-nodebug.ll new file mode 100644 index 0000000000000..f5526030278eb --- /dev/null +++ b/llvm/test/Verifier/RemoveDI/fnarg-nodebug.ll @@ -0,0 +1,58 @@ +; RUN: llvm-as < %s -o %t +; RUN: llvm-dis < %t -o - | FileCheck %s +; Created at -O1 from: +; int sink(int); +; __attribute__((always_inline)) int f(int i) { return sink(i); } +; __attribute__((always_inline)) int g(int j) { return sink(j); } +; __attribute__((nodebug)) int nodebug(int k) { return f(k)+g(k); } +source_filename = "t.c" +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.12.0" + +declare i32 @sink(i32) local_unnamed_addr + +define i32 @nodebug(i32 %k) local_unnamed_addr #2 { +entry: +; This should not set off the FnArg Verifier. The two variables are in differrent scopes. + #dbg_value(i32 %k, !12, !13, !14) + %call.k = tail call i32 @sink(i32 %k) #4, !dbg !15 + #dbg_value(i32 %k, !19, !13, !20) + %call.k3 = tail call i32 @sink(i32 %k) #4, !dbg !21 + %add = add nsw i32 %call.k3, %call.k + ret i32 %add +} + +; Function Attrs: nounwind readnone + +attributes #2 = { nounwind ssp uwtable } +attributes #3 = { nounwind readnone } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 5.0.0 (trunk 297153) (llvm/trunk 297155)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "t.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"PIC Level", i32 2} +!6 = !{!"clang version 5.0.0 (trunk 297153) (llvm/trunk 297155)"} +!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 2, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12} +; CHECK: !DILocalVariable(name: "i", arg: 1 +!12 = !DILocalVariable(name: "i", arg: 1, scope: !7, file: !1, line: 2, type: !10) +!13 = !DIExpression() +!14 = !DILocation(line: 2, column: 42, scope: !7) +!15 = !DILocation(line: 2, column: 54, scope: !7) +!16 = !DILocation(line: 2, column: 47, scope: !7) +!17 = distinct !DISubprogram(name: "g", scope: !1, file: !1, line: 3, type: !8, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !18) +!18 = !{!19} +; CHECK: !DILocalVariable(name: "j", arg: 1 +!19 = !DILocalVariable(name: "j", arg: 1, scope: !17, file: !1, line: 3, type: !10) +!20 = !DILocation(line: 3, column: 42, scope: !17) +!21 = !DILocation(line: 3, column: 54, scope: !17) +!22 = !DILocation(line: 3, column: 47, scope: !17) diff --git a/llvm/test/Verifier/RemoveDI/invalid-disubrange-count-node.ll b/llvm/test/Verifier/RemoveDI/invalid-disubrange-count-node.ll new file mode 100644 index 0000000000000..f36cee5946e47 --- /dev/null +++ b/llvm/test/Verifier/RemoveDI/invalid-disubrange-count-node.ll @@ -0,0 +1,36 @@ +; RUN: llvm-as < %s -disable-output 2>&1 | FileCheck %s + +define void @foo(i32 %n) { +entry: + %0 = zext i32 %n to i64 + %vla = alloca i32, i64 %0, align 16 + #dbg_declare(ptr %vla, !19, !DIExpression(), !18) + ret void +} + + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 5.0.1", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "vla.c", directory: "/path/to") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 5.0.1"} +!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 20, type: !8, isLocal: false, isDefinition: true, scopeLine: 20, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{null, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!16, !19} +!12 = !DIExpression() +!16 = !DILocalVariable(name: "vla_expr", scope: !7, file: !1, line: 21, type: !17) +!17 = !DIBasicType(name: "long unsigned int", size: 64, encoding: DW_ATE_unsigned) +!18 = !DILocation(line: 21, column: 7, scope: !7) +!19 = !DILocalVariable(name: "vla", scope: !7, file: !1, line: 21, type: !20) +!20 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, align: 32, elements: !21) +!21 = !{!22} +; CHECK: Count must be signed constant or DIVariable or DIExpression +!22 = !DISubrange(count: !17) diff --git a/llvm/test/Verifier/RemoveDI/llvm.dbg.declare-address.ll b/llvm/test/Verifier/RemoveDI/llvm.dbg.declare-address.ll new file mode 100644 index 0000000000000..9d400b892ce8c --- /dev/null +++ b/llvm/test/Verifier/RemoveDI/llvm.dbg.declare-address.ll @@ -0,0 +1,16 @@ +; RUN: llvm-as -disable-output <%s 2>&1 | FileCheck %s +; CHECK: invalid #dbg record address/value +; CHECK-NEXT: #dbg_declare({{.*}}) +; CHECK-NEXT: !"" +; CHECK: warning: ignoring invalid debug info + +define void @foo(i32 %a) { +entry: + %s = alloca i32 + #dbg_declare(!"", !DILocalVariable(scope: !1), !DIExpression(), !DILocation(scope: !1)) + ret void +} + +!llvm.module.flags = !{!0} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DISubprogram() diff --git a/llvm/test/Verifier/RemoveDI/llvm.dbg.declare-expression.ll b/llvm/test/Verifier/RemoveDI/llvm.dbg.declare-expression.ll new file mode 100644 index 0000000000000..b52c15cb3f881 --- /dev/null +++ b/llvm/test/Verifier/RemoveDI/llvm.dbg.declare-expression.ll @@ -0,0 +1,16 @@ +; RUN: llvm-as -disable-output <%s 2>&1 | FileCheck %s +; CHECK: invalid #dbg record expression +; CHECK-NEXT: #dbg_declare({{.*}}) +; CHECK-NEXT: !{} +; CHECK: warning: ignoring invalid debug info + +define void @foo(i32 %a) { +entry: + %s = alloca i32 + #dbg_declare(ptr %s, !DILocalVariable(scope: !1), !{}, !DILocation(scope: !1)) + ret void +} + +!llvm.module.flags = !{!0} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DISubprogram() diff --git a/llvm/test/Verifier/RemoveDI/llvm.dbg.declare-variable.ll b/llvm/test/Verifier/RemoveDI/llvm.dbg.declare-variable.ll new file mode 100644 index 0000000000000..db2b0e0a54e2b --- /dev/null +++ b/llvm/test/Verifier/RemoveDI/llvm.dbg.declare-variable.ll @@ -0,0 +1,17 @@ +; RUN: llvm-as -disable-output <%s 2>&1 | FileCheck %s +; CHECK: invalid #dbg record variable +; CHECK-NEXT: #dbg_declare({{.*}}) +; CHECK-NEXT: !{} +; CHECK: warning: ignoring invalid debug info + +define void @foo(i32 %a) { +entry: + %s = alloca i32 + #dbg_declare(ptr %s, !{}, !DIExpression(), !DILocation(scope: !1)) + ret void +} + + +!llvm.module.flags = !{!0} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DISubprogram() diff --git a/llvm/test/Verifier/RemoveDI/llvm.dbg.intrinsic-dbg-attachment.ll b/llvm/test/Verifier/RemoveDI/llvm.dbg.intrinsic-dbg-attachment.ll new file mode 100644 index 0000000000000..1839821ab1407 --- /dev/null +++ b/llvm/test/Verifier/RemoveDI/llvm.dbg.intrinsic-dbg-attachment.ll @@ -0,0 +1,55 @@ +; RUN: llvm-as -disable-output <%s 2>&1 | FileCheck %s +define void @foo() { +entry: + #dbg_value( + ptr undef, + !DILocalVariable(scope: !1), + !DIExpression(), + !{}) +; CHECK-LABEL: invalid #dbg record DILocation +; CHECK-NEXT: #dbg_value({{.*}}) + + #dbg_declare( + ptr undef, + !DILocalVariable(scope: !1), + !DIExpression(), + !{}) +; CHECK-LABEL: invalid #dbg record DILocation +; CHECK-NEXT: #dbg_declare({{.*}}) + + #dbg_value( + ptr undef, + !DILocalVariable(scope: !1), + !DIExpression(), + !DILocation(scope: !2)) +; CHECK-LABEL: mismatched subprogram between #dbg record variable and DILocation +; CHECK-NEXT: #dbg_value({{[^,]+}}, ![[VAR:[0-9]+]], {{[^,]+}}, ![[LOC:[0-9]+]] +; CHECK-NEXT: label %entry +; CHECK-NEXT: ptr @foo +; CHECK-NEXT: ![[VAR]] = !DILocalVariable({{.*}}scope: ![[VARSP:[0-9]+]] +; CHECK-NEXT: ![[VARSP]] = distinct !DISubprogram( +; CHECK-NEXT: ![[LOC]] = !DILocation({{.*}}scope: ![[LOCSP:[0-9]+]] +; CHECK-NEXT: ![[LOCSP]] = distinct !DISubprogram( + + #dbg_declare( + ptr undef, + !DILocalVariable(scope: !1), + !DIExpression(), + !DILocation(scope: !2)) +; CHECK-LABEL: mismatched subprogram between #dbg record variable and DILocation +; CHECK-NEXT: #dbg_declare({{[^,]+}}, ![[VAR:[0-9]+]], {{.*[^,]+}}, ![[LOC:[0-9]+]] +; CHECK-NEXT: label %entry +; CHECK-NEXT: ptr @foo +; CHECK-NEXT: ![[VAR]] = !DILocalVariable({{.*}}scope: ![[VARSP:[0-9]+]] +; CHECK-NEXT: ![[VARSP]] = distinct !DISubprogram( +; CHECK-NEXT: ![[LOC]] = !DILocation({{.*}}scope: ![[LOCSP:[0-9]+]] +; CHECK-NEXT: ![[LOCSP]] = distinct !DISubprogram( + + ret void +} + + +!llvm.module.flags = !{!0} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DISubprogram(name: "foo") +!2 = distinct !DISubprogram(name: "bar") diff --git a/llvm/test/Verifier/RemoveDI/llvm.dbg.value-expression.ll b/llvm/test/Verifier/RemoveDI/llvm.dbg.value-expression.ll new file mode 100644 index 0000000000000..cbd93c1ce6a4d --- /dev/null +++ b/llvm/test/Verifier/RemoveDI/llvm.dbg.value-expression.ll @@ -0,0 +1,16 @@ +; RUN: llvm-as -disable-output <%s 2>&1 | FileCheck %s +; CHECK: invalid #dbg record expression +; CHECK-NEXT: #dbg_value({{.*}}) +; CHECK-NEXT: !{} +; CHECK: warning: ignoring invalid debug info + +define void @foo(i32 %a) { +entry: + %s = alloca i32 + #dbg_value(ptr %s, !DILocalVariable(scope: !1), !{}, !DILocation(scope: !1)) + ret void +} + +!llvm.module.flags = !{!0} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DISubprogram() diff --git a/llvm/test/Verifier/RemoveDI/llvm.dbg.value-value.ll b/llvm/test/Verifier/RemoveDI/llvm.dbg.value-value.ll new file mode 100644 index 0000000000000..b6fcde250526b --- /dev/null +++ b/llvm/test/Verifier/RemoveDI/llvm.dbg.value-value.ll @@ -0,0 +1,17 @@ +; RUN: llvm-as -disable-output <%s 2>&1 | FileCheck %s +; CHECK: invalid #dbg record address/value +; CHECK-NEXT: #dbg_value({{.*}}) +; CHECK-NEXT: !"" +; CHECK: warning: ignoring invalid debug info + +define void @foo(i32 %a) { +entry: + %s = alloca i32 + #dbg_value(!"", !DILocalVariable(scope: !1), !DIExpression(), !DILocation(scope: !1)) + ret void +} + + +!llvm.module.flags = !{!0} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DISubprogram() diff --git a/llvm/test/Verifier/RemoveDI/llvm.dbg.value-variable.ll b/llvm/test/Verifier/RemoveDI/llvm.dbg.value-variable.ll new file mode 100644 index 0000000000000..0a5fe79453d72 --- /dev/null +++ b/llvm/test/Verifier/RemoveDI/llvm.dbg.value-variable.ll @@ -0,0 +1,17 @@ +; RUN: llvm-as -disable-output <%s 2>&1 | FileCheck %s +; CHECK: invalid #dbg record variable +; CHECK-NEXT: #dbg_value({{.*}}) +; CHECK-NEXT: !{} +; CHECK: warning: ignoring invalid debug info + +define void @foo(i32 %a) { +entry: + %s = alloca i32 + #dbg_value(ptr %s, !{}, !DIExpression(), !DILocation(scope: !1)) + ret void +} + + +!llvm.module.flags = !{!0} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DISubprogram() diff --git a/llvm/test/Verifier/RemoveDI/set1.ll b/llvm/test/Verifier/RemoveDI/set1.ll new file mode 100644 index 0000000000000..d54ba8876c366 --- /dev/null +++ b/llvm/test/Verifier/RemoveDI/set1.ll @@ -0,0 +1,62 @@ +; RUN: llvm-as -disable-output <%s 2>&1 | FileCheck %s + +define void @Main__Test() #0 !dbg !17 { +entry: + %as = alloca i64, align 8 + %bs = alloca i64, align 8 + br label %second, !dbg !21 + +second: ; preds = %entry + #dbg_declare(ptr %as, !22, !DIExpression(), !25) + #dbg_declare(ptr %bs, !26, !DIExpression(), !25) + store i64 36028797018972298, ptr %as, align 8, !dbg !28 + store i64 85, ptr %bs, align 8, !dbg !29 + ret void, !dbg !21 +} + +; Function Attrs: nofree nosync nounwind readnone speculatable willreturn + +!llvm.ident = !{!0} +!llvm.dbg.cu = !{!1} +!llvm.module.flags = !{!14, !15, !16} + +!0 = !{!"versions- cm3: d5.10.0 llvm: 12.0"} +!1 = distinct !DICompileUnit(language: DW_LANG_Modula3, file: !2, producer: "cm3", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3) +!2 = !DIFile(filename: "Main.m3", directory: "/home/peter/cm3/settest/src") +!3 = !{!4} +!4 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Enum", scope: !2, file: !2, line: 11, size: 8, align: 8, elements: !5) +!5 = !{!6, !7, !8, !9, !10, !11, !12, !13} +!6 = !DIEnumerator(name: "alpha", value: 0) +!7 = !DIEnumerator(name: "beta", value: 1) +!8 = !DIEnumerator(name: "gamma", value: 2) +!9 = !DIEnumerator(name: "delta", value: 3) +!10 = !DIEnumerator(name: "epsilon", value: 4) +!11 = !DIEnumerator(name: "theta", value: 5) +!12 = !DIEnumerator(name: "psi", value: 6) +!13 = !DIEnumerator(name: "zeta", value: 7) +!14 = !{i64 2, !"Dwarf Version", i64 4} +!15 = !{i64 2, !"Debug Info Version", i64 3} +!16 = !{i64 2, !"wchar_size", i64 2} +!17 = distinct !DISubprogram(name: "Test", linkageName: "Main__Test", scope: !2, file: !2, line: 11, type: !18, scopeLine: 11, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !20) +!18 = !DISubroutineType(types: !19) +!19 = !{null} +!20 = !{} +!21 = !DILocation(line: 20, scope: !17) +!22 = !DILocalVariable(name: "as", scope: !17, file: !2, line: 11, type: !23) +; CHECK: invalid set base type +!23 = !DIDerivedType(tag: DW_TAG_set_type, name: "SS", scope: !2, file: !2, line: 11, baseType: !24, size: 64, align: 64) +!24 = !DIBasicType(name: "SR", size: 8, encoding: DW_ATE_signed) +!25 = !DILocation(line: 11, scope: !17) +!26 = !DILocalVariable(name: "bs", scope: !17, file: !2, line: 11, type: !27) +!27 = !DIDerivedType(tag: DW_TAG_set_type, name: "ST", scope: !2, file: !2, line: 11, baseType: !23, size: 64, align: 64) +!28 = !DILocation(line: 17, scope: !17) +!29 = !DILocation(line: 18, scope: !17) +!30 = distinct !DISubprogram(name: "Main_M3", linkageName: "Main_M3", scope: !2, file: !2, line: 22, type: !31, scopeLine: 22, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !20) +!31 = !DISubroutineType(types: !32) +!32 = !{!33, !35} +!33 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "ADDR", baseType: !34, size: 64, align: 64) +!34 = !DICompositeType(tag: DW_TAG_class_type, name: "ADDR__HeapObject", scope: !2, file: !2, line: 22, size: 64, align: 64, elements: !19, identifier: "AJWxb1") +!35 = !DIBasicType(name: "INTEGER", size: 64, encoding: DW_ATE_signed) +!36 = !DILocation(line: 23, scope: !30) +!37 = !DILocalVariable(name: "mode", arg: 1, scope: !30, file: !2, line: 22, type: !35) +!38 = !DILocation(line: 22, scope: !30)