From df8fa60b3b3c880ebb9c3bbc269d3cb2089cac61 Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Mon, 29 Jan 2024 11:04:24 +0000 Subject: [PATCH 01/13] Add parsing for non-intrinsic debug values --- llvm/include/llvm/AsmParser/LLParser.h | 4 + llvm/include/llvm/AsmParser/LLToken.h | 3 + .../include/llvm/IR/DebugProgramInstruction.h | 24 +++ llvm/lib/AsmParser/LLLexer.cpp | 18 ++- llvm/lib/AsmParser/LLParser.cpp | 144 +++++++++++++++++- llvm/lib/IR/DebugProgramInstruction.cpp | 17 +++ .../roundtrip-non-instruction-debug-info.ll | 87 +++++++++++ 7 files changed, 295 insertions(+), 2 deletions(-) create mode 100644 llvm/test/DebugInfo/roundtrip-non-instruction-debug-info.ll diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h index f07f4c61f9d64..086f06e15c862 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 parseDebugProgramValue(DPValue *&DPV, 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..c860b17d764ff 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, @@ -483,6 +484,8 @@ enum Kind { // Type valued tokens (TyVal). Type, + DbgRecordType, + APFloat, // APFloatVal APSInt // APSInt }; diff --git a/llvm/include/llvm/IR/DebugProgramInstruction.h b/llvm/include/llvm/IR/DebugProgramInstruction.h index cf30b4d0b0aaf..33fff815d474f 100644 --- a/llvm/include/llvm/IR/DebugProgramInstruction.h +++ b/llvm/include/llvm/IR/DebugProgramInstruction.h @@ -286,6 +286,30 @@ 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..64bccc3e4bba3 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -440,7 +440,9 @@ lltok::Kind LLLexer::LexCaret() { /// AttrGrpID ::= #[0-9]+ 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 +925,20 @@ 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); +#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..c91a5520d8a5f 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); @@ -6041,6 +6043,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 @@ -6228,6 +6241,13 @@ bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine, } } + if (isOldDbgFormatIntrinsic(FunctionName)) { + if (SeenNewDbgInfoFormat) + return error(NameLoc, "llvm.dbg intrinsic should not appear in a module " + "using non-intrinsic debug info"); + SeenOldDbgInfoFormat = true; + } + Fn = Function::Create(FT, GlobalValue::ExternalLinkage, AddrSpace, FunctionName, M); @@ -6390,9 +6410,29 @@ 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; + DPValue *DPV; + SmallVector> TrailingDPValues; 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 (!BB->getModule()->IsNewDbgInfoFormat) + BB->getModule()->convertToNewDbgValues(); + + if (parseDebugProgramValue(DPV, PFS)) + return true; + TrailingDPValues.emplace_back(DPV); + } + // 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 +6477,103 @@ 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 (std::unique_ptr &DPV : TrailingDPValues) { + BB->insertDPValueBefore(DPV.release(), Inst->getIterator()); + } + TrailingDPValues.clear(); } while (!Inst->isTerminator()); + assert(TrailingDPValues.empty() && + "All debug values should have been attached to an instruction."); + return false; } +/// parseDebugProgramValue +/// ::= #dbg_Type { (ValueAsMetadata|DIArgList|MDNode), MetadataID, +/// DIExpression, DILocation } +bool LLParser::parseDebugProgramValue(DPValue *&DPV, PerFunctionState &PFS) { + using LocType = DPValue::LocationType; + LocTy DPVLoc = Lex.getLoc(); + if (Lex.getKind() != lltok::DbgRecordType) { + return error(DPVLoc, "expected debug record type here"); + } + auto Type = StringSwitch(Lex.getStrVal()) + .Case("declare", LocType::Declare) + .Case("value", LocType::Value) + .Case("assign", LocType::Assign) + .Default(LocType::End); + if (Type == LocType::End) + return error(DPVLoc, "expected valid #dbg record here"); + Lex.Lex(); + if (parseToken(lltok::lbrace, "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... + LocTy ExprLoc = Lex.getLoc(); + Metadata *Expression; + if (parseMetadata(Expression, &PFS)) + return true; + if (!isa(Expression)) + return error(ExprLoc, "expected valid DIExpression here"); + if (parseToken(lltok::comma, "Expected ',' here")) + return true; + + // Parse additional fields for #dbg_assign. + MDNode *AssignID = nullptr; + Metadata *AddressLocation = nullptr; + Metadata *AddressExpression = nullptr; + if (Type == 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... + LocTy AddressExprLoc = Lex.getLoc(); + if (parseMetadata(AddressExpression, &PFS)) + return true; + if (!isa(Expression)) + return error(AddressExprLoc, "expected valid DIExpression here"); + if (parseToken(lltok::comma, "Expected ',' here")) + return true; + } + + /// Parse DILocation... + MDNode *DebugLoc; + if (parseMDNode(DebugLoc)) + return true; + + if (parseToken(lltok::rbrace, "Expected '}' here")) + return true; + DPV = DPValue::createUnresolvedDPValue( + Type, ValLocMD, Variable, cast(Expression), AssignID, + AddressLocation, cast_or_null(AddressExpression), DebugLoc); + return false; +} //===----------------------------------------------------------------------===// // Instruction Parsing. //===----------------------------------------------------------------------===// @@ -7669,6 +7801,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..25cd82fb91f8c 100644 --- a/llvm/lib/IR/DebugProgramInstruction.cpp +++ b/llvm/lib/IR/DebugProgramInstruction.cpp @@ -143,6 +143,23 @@ DPLabel::DPLabel(DILabel *Label, DebugLoc DL) assert(Label && "Unexpected nullptr"); } +DPValue::DPValue(DPValue::LocationType Type, Metadata *Val, MDNode *Variable, + MDNode *Expression, MDNode *AssignID, Metadata *Address, + MDNode *AddressExpression, MDNode *DI) + : DebugValueUser({Val, Address, AssignID}), Variable(Variable), + Expression(Expression), DbgLoc(DI), AddressExpression(AddressExpression), + Type(Type) {} + +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/test/DebugInfo/roundtrip-non-instruction-debug-info.ll b/llvm/test/DebugInfo/roundtrip-non-instruction-debug-info.ll new file mode 100644 index 0000000000000..f8c0024977bc2 --- /dev/null +++ b/llvm/test/DebugInfo/roundtrip-non-instruction-debug-info.ll @@ -0,0 +1,87 @@ +;; 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 + +;; 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 + +;; ...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 + +;; 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 +; 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 + +; 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]+]] } +; 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 + +; 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 + +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 + 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) + +!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() \ No newline at end of file From 617b5298f74bf7434c98848e58bea6eeff83713c Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Mon, 29 Jan 2024 16:02:50 +0000 Subject: [PATCH 02/13] Address review nits --- llvm/lib/AsmParser/LLParser.cpp | 45 ++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index c91a5520d8a5f..d202ebaa86cf2 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -71,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) { @@ -88,7 +97,7 @@ bool LLParser::Run(bool UpgradeDebugInfo, } return parseTopLevelEntities() || validateEndOfModule(UpgradeDebugInfo) || - validateEndOfIndex(); + validateEndOfIndex() || finalizeDebugInfoFormat(M); } bool LLParser::parseStandaloneConstantValue(Constant *&C, @@ -6410,10 +6419,9 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) { std::string NameStr; - // parse the instructions and debug values in this block until we get a + // Parse the instructions and debug values in this block until we get a // terminator. Instruction *Inst; - DPValue *DPV; SmallVector> TrailingDPValues; do { // Handle debug records first - there should always be an instruction @@ -6425,9 +6433,10 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) { "containing debug info intrinsics"); SeenNewDbgInfoFormat = true; Lex.Lex(); - if (!BB->getModule()->IsNewDbgInfoFormat) - BB->getModule()->convertToNewDbgValues(); + if (!M->IsNewDbgInfoFormat) + M->convertToNewDbgValues(); + DPValue *DPV; if (parseDebugProgramValue(DPV, PFS)) return true; TrailingDPValues.emplace_back(DPV); @@ -6479,9 +6488,8 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) { return true; // Attach any preceding debug values to this instruction. - for (std::unique_ptr &DPV : TrailingDPValues) { + for (std::unique_ptr &DPV : TrailingDPValues) BB->insertDPValueBefore(DPV.release(), Inst->getIterator()); - } TrailingDPValues.clear(); } while (!Inst->isTerminator()); @@ -6492,14 +6500,15 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) { } /// parseDebugProgramValue -/// ::= #dbg_Type { (ValueAsMetadata|DIArgList|MDNode), MetadataID, -/// DIExpression, DILocation } +/// ::= #dbg_Type '{' (ValueAsMetadata|DIArgList|MDNode) ',' MetadataID ',' +/// DIExpression ',' +/// (DIAssignID',' (ValueAsMetadata|MDNode)',' DIExpression] ',')? +/// DILocation '}' bool LLParser::parseDebugProgramValue(DPValue *&DPV, PerFunctionState &PFS) { using LocType = DPValue::LocationType; LocTy DPVLoc = Lex.getLoc(); - if (Lex.getKind() != lltok::DbgRecordType) { + if (Lex.getKind() != lltok::DbgRecordType) return error(DPVLoc, "expected debug record type here"); - } auto Type = StringSwitch(Lex.getStrVal()) .Case("declare", LocType::Declare) .Case("value", LocType::Value) @@ -6511,21 +6520,21 @@ bool LLParser::parseDebugProgramValue(DPValue *&DPV, PerFunctionState &PFS) { if (parseToken(lltok::lbrace, "Expected '{' here")) return true; - // Parse Value field... + // Parse Value field. Metadata *ValLocMD; if (parseMetadata(ValLocMD, &PFS)) return true; if (parseToken(lltok::comma, "Expected ',' here")) return true; - // Parse Variable field... + // Parse Variable field. MDNode *Variable; if (parseMDNode(Variable)) return true; if (parseToken(lltok::comma, "Expected ',' here")) return true; - // Parse Expression field... + // Parse Expression field. LocTy ExprLoc = Lex.getLoc(); Metadata *Expression; if (parseMetadata(Expression, &PFS)) @@ -6540,19 +6549,19 @@ bool LLParser::parseDebugProgramValue(DPValue *&DPV, PerFunctionState &PFS) { Metadata *AddressLocation = nullptr; Metadata *AddressExpression = nullptr; if (Type == LocType::Assign) { - // Parse DIAssignID... + // Parse DIAssignID. if (parseMDNode(AssignID)) return true; if (parseToken(lltok::comma, "Expected ',' here")) return true; - // Parse address ValueAsMetadata... + // Parse address ValueAsMetadata. if (parseMetadata(AddressLocation, &PFS)) return true; if (parseToken(lltok::comma, "Expected ',' here")) return true; - // Parse address DIExpression... + // Parse address DIExpression. LocTy AddressExprLoc = Lex.getLoc(); if (parseMetadata(AddressExpression, &PFS)) return true; @@ -6562,7 +6571,7 @@ bool LLParser::parseDebugProgramValue(DPValue *&DPV, PerFunctionState &PFS) { return true; } - /// Parse DILocation... + /// Parse DILocation. MDNode *DebugLoc; if (parseMDNode(DebugLoc)) return true; From c6e5affd09e3e2d4ca984326bb449717afad176b Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Mon, 29 Jan 2024 16:22:47 +0000 Subject: [PATCH 03/13] Add tests, use brackets, minor fixes --- llvm/lib/AsmParser/LLParser.cpp | 17 ++++---- llvm/test/Assembler/dbg-removedi-invalid-0.ll | 38 ++++++++++++++++++ llvm/test/Assembler/dbg-removedi-invalid-1.ll | 39 +++++++++++++++++++ .../test/Assembler/dbg-removedi-invalid-10.ll | 36 +++++++++++++++++ .../test/Assembler/dbg-removedi-invalid-11.ll | 35 +++++++++++++++++ llvm/test/Assembler/dbg-removedi-invalid-2.ll | 38 ++++++++++++++++++ llvm/test/Assembler/dbg-removedi-invalid-3.ll | 39 +++++++++++++++++++ llvm/test/Assembler/dbg-removedi-invalid-4.ll | 36 +++++++++++++++++ llvm/test/Assembler/dbg-removedi-invalid-5.ll | 37 ++++++++++++++++++ llvm/test/Assembler/dbg-removedi-invalid-6.ll | 37 ++++++++++++++++++ llvm/test/Assembler/dbg-removedi-invalid-7.ll | 36 +++++++++++++++++ llvm/test/Assembler/dbg-removedi-invalid-8.ll | 36 +++++++++++++++++ llvm/test/Assembler/dbg-removedi-invalid-9.ll | 36 +++++++++++++++++ .../roundtrip-non-instruction-debug-info.ll | 8 ++-- 14 files changed, 457 insertions(+), 11 deletions(-) create mode 100644 llvm/test/Assembler/dbg-removedi-invalid-0.ll create mode 100644 llvm/test/Assembler/dbg-removedi-invalid-1.ll create mode 100644 llvm/test/Assembler/dbg-removedi-invalid-10.ll create mode 100644 llvm/test/Assembler/dbg-removedi-invalid-11.ll create mode 100644 llvm/test/Assembler/dbg-removedi-invalid-2.ll create mode 100644 llvm/test/Assembler/dbg-removedi-invalid-3.ll create mode 100644 llvm/test/Assembler/dbg-removedi-invalid-4.ll create mode 100644 llvm/test/Assembler/dbg-removedi-invalid-5.ll create mode 100644 llvm/test/Assembler/dbg-removedi-invalid-6.ll create mode 100644 llvm/test/Assembler/dbg-removedi-invalid-7.ll create mode 100644 llvm/test/Assembler/dbg-removedi-invalid-8.ll create mode 100644 llvm/test/Assembler/dbg-removedi-invalid-9.ll diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index d202ebaa86cf2..a71f252005936 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -6514,10 +6514,13 @@ bool LLParser::parseDebugProgramValue(DPValue *&DPV, PerFunctionState &PFS) { .Case("value", LocType::Value) .Case("assign", LocType::Assign) .Default(LocType::End); - if (Type == LocType::End) - return error(DPVLoc, "expected valid #dbg record here"); + // If the file contained an invalid debug record type then parsing should fail + // above; the assert here should only fire if the Lexer gives us an invalid + // value. + assert(Type != LocType::End && + "Lexer returned an invalid DbgRecordType string."); Lex.Lex(); - if (parseToken(lltok::lbrace, "Expected '{' here")) + if (parseToken(lltok::lparen, "Expected '(' here")) return true; // Parse Value field. @@ -6540,7 +6543,7 @@ bool LLParser::parseDebugProgramValue(DPValue *&DPV, PerFunctionState &PFS) { if (parseMetadata(Expression, &PFS)) return true; if (!isa(Expression)) - return error(ExprLoc, "expected valid DIExpression here"); + return error(ExprLoc, "expected valid inline DIExpression here"); if (parseToken(lltok::comma, "Expected ',' here")) return true; @@ -6565,8 +6568,8 @@ bool LLParser::parseDebugProgramValue(DPValue *&DPV, PerFunctionState &PFS) { LocTy AddressExprLoc = Lex.getLoc(); if (parseMetadata(AddressExpression, &PFS)) return true; - if (!isa(Expression)) - return error(AddressExprLoc, "expected valid DIExpression here"); + if (!isa(AddressExpression)) + return error(AddressExprLoc, "expected valid inline DIExpression here"); if (parseToken(lltok::comma, "Expected ',' here")) return true; } @@ -6576,7 +6579,7 @@ bool LLParser::parseDebugProgramValue(DPValue *&DPV, PerFunctionState &PFS) { if (parseMDNode(DebugLoc)) return true; - if (parseToken(lltok::rbrace, "Expected '}' here")) + if (parseToken(lltok::rparen, "Expected ')' here")) return true; DPV = DPValue::createUnresolvedDPValue( Type, ValLocMD, Variable, cast(Expression), AssignID, diff --git a/llvm/test/Assembler/dbg-removedi-invalid-0.ll b/llvm/test/Assembler/dbg-removedi-invalid-0.ll new file mode 100644 index 0000000000000..feb513a405f9e --- /dev/null +++ b/llvm/test/Assembler/dbg-removedi-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-removedi-invalid-1.ll b/llvm/test/Assembler/dbg-removedi-invalid-1.ll new file mode 100644 index 0000000000000..7ab5751777e8c --- /dev/null +++ b/llvm/test/Assembler/dbg-removedi-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-removedi-invalid-10.ll b/llvm/test/Assembler/dbg-removedi-invalid-10.ll new file mode 100644 index 0000000000000..72dafcdb97fce --- /dev/null +++ b/llvm/test/Assembler/dbg-removedi-invalid-10.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-removedi-invalid-11.ll b/llvm/test/Assembler/dbg-removedi-invalid-11.ll new file mode 100644 index 0000000000000..5ea588b87668c --- /dev/null +++ b/llvm/test/Assembler/dbg-removedi-invalid-11.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-removedi-invalid-2.ll b/llvm/test/Assembler/dbg-removedi-invalid-2.ll new file mode 100644 index 0000000000000..753a486e896b5 --- /dev/null +++ b/llvm/test/Assembler/dbg-removedi-invalid-2.ll @@ -0,0 +1,38 @@ +;; Test that we get a parser error when a debug intrinsic declaration appears in +;; the same module as a debug intrinsic declaration. +; 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) + ret i32 %a, !dbg !18 +} + +; CHECK: :[[@LINE+1]]:14: error: llvm.dbg intrinsic should not appear in a module using non-intrinsic debug info +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-removedi-invalid-3.ll b/llvm/test/Assembler/dbg-removedi-invalid-3.ll new file mode 100644 index 0000000000000..e6f072373f54d --- /dev/null +++ b/llvm/test/Assembler/dbg-removedi-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-removedi-invalid-4.ll b/llvm/test/Assembler/dbg-removedi-invalid-4.ll new file mode 100644 index 0000000000000..f898477603c8e --- /dev/null +++ b/llvm/test/Assembler/dbg-removedi-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-removedi-invalid-5.ll b/llvm/test/Assembler/dbg-removedi-invalid-5.ll new file mode 100644 index 0000000000000..2b3e3a763221d --- /dev/null +++ b/llvm/test/Assembler/dbg-removedi-invalid-5.ll @@ -0,0 +1,37 @@ +;; Test that we get a parser error when we have a debug record that does not use +;; an inline DIExpression. +; 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]]:29: error: expected valid inline DIExpression here + #dbg_value(i32 %a, !12, !20, !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) +!20 = !DIExpression() diff --git a/llvm/test/Assembler/dbg-removedi-invalid-6.ll b/llvm/test/Assembler/dbg-removedi-invalid-6.ll new file mode 100644 index 0000000000000..9aff3c79d79bb --- /dev/null +++ b/llvm/test/Assembler/dbg-removedi-invalid-6.ll @@ -0,0 +1,37 @@ +;; Test that we get a parser error when we have a debug assign record that does +;; not use an inline DIExpression for its address expression. +; 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]]:63: error: expected valid inline DIExpression here + #dbg_assign(i32 %a, !12, !DIExpression(), !15, ptr undef, !20, !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) +!20 = !DIExpression() diff --git a/llvm/test/Assembler/dbg-removedi-invalid-7.ll b/llvm/test/Assembler/dbg-removedi-invalid-7.ll new file mode 100644 index 0000000000000..036a85a2977fc --- /dev/null +++ b/llvm/test/Assembler/dbg-removedi-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-removedi-invalid-8.ll b/llvm/test/Assembler/dbg-removedi-invalid-8.ll new file mode 100644 index 0000000000000..d0b8f36d7895c --- /dev/null +++ b/llvm/test/Assembler/dbg-removedi-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/Assembler/dbg-removedi-invalid-9.ll b/llvm/test/Assembler/dbg-removedi-invalid-9.ll new file mode 100644 index 0000000000000..a019f73feab9c --- /dev/null +++ b/llvm/test/Assembler/dbg-removedi-invalid-9.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/DebugInfo/roundtrip-non-instruction-debug-info.ll b/llvm/test/DebugInfo/roundtrip-non-instruction-debug-info.ll index f8c0024977bc2..6efffb431aa68 100644 --- a/llvm/test/DebugInfo/roundtrip-non-instruction-debug-info.ll +++ b/llvm/test/DebugInfo/roundtrip-non-instruction-debug-info.ll @@ -21,16 +21,16 @@ ; 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]+]] } +; 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]+]] } +; 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]+]] } +; 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]+]]) ; 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]+]] } +; 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 From ac969d371896da256701e16baf7a1f7a9632a551 Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Thu, 22 Feb 2024 15:51:02 +0000 Subject: [PATCH 04/13] Rename tests, adjust lexer/token descriptions --- llvm/include/llvm/AsmParser/LLToken.h | 3 +-- llvm/lib/AsmParser/LLLexer.cpp | 1 + llvm/lib/AsmParser/LLParser.cpp | 6 ++---- ...g-removedi-invalid-0.ll => dbg-record-invalid-0.ll} | 0 ...g-removedi-invalid-1.ll => dbg-record-invalid-1.ll} | 0 ...removedi-invalid-10.ll => dbg-record-invalid-10.ll} | 0 ...removedi-invalid-11.ll => dbg-record-invalid-11.ll} | 0 ...g-removedi-invalid-2.ll => dbg-record-invalid-2.ll} | 0 ...g-removedi-invalid-3.ll => dbg-record-invalid-3.ll} | 0 ...g-removedi-invalid-4.ll => dbg-record-invalid-4.ll} | 0 ...g-removedi-invalid-5.ll => dbg-record-invalid-5.ll} | 0 ...g-removedi-invalid-6.ll => dbg-record-invalid-6.ll} | 0 ...g-removedi-invalid-7.ll => dbg-record-invalid-7.ll} | 0 ...g-removedi-invalid-8.ll => dbg-record-invalid-8.ll} | 0 ...g-removedi-invalid-9.ll => dbg-record-invalid-9.ll} | 0 .../DebugInfo/roundtrip-non-instruction-debug-info.ll | 10 +++++----- 16 files changed, 9 insertions(+), 11 deletions(-) rename llvm/test/Assembler/{dbg-removedi-invalid-0.ll => dbg-record-invalid-0.ll} (100%) rename llvm/test/Assembler/{dbg-removedi-invalid-1.ll => dbg-record-invalid-1.ll} (100%) rename llvm/test/Assembler/{dbg-removedi-invalid-10.ll => dbg-record-invalid-10.ll} (100%) rename llvm/test/Assembler/{dbg-removedi-invalid-11.ll => dbg-record-invalid-11.ll} (100%) rename llvm/test/Assembler/{dbg-removedi-invalid-2.ll => dbg-record-invalid-2.ll} (100%) rename llvm/test/Assembler/{dbg-removedi-invalid-3.ll => dbg-record-invalid-3.ll} (100%) rename llvm/test/Assembler/{dbg-removedi-invalid-4.ll => dbg-record-invalid-4.ll} (100%) rename llvm/test/Assembler/{dbg-removedi-invalid-5.ll => dbg-record-invalid-5.ll} (100%) rename llvm/test/Assembler/{dbg-removedi-invalid-6.ll => dbg-record-invalid-6.ll} (100%) rename llvm/test/Assembler/{dbg-removedi-invalid-7.ll => dbg-record-invalid-7.ll} (100%) rename llvm/test/Assembler/{dbg-removedi-invalid-8.ll => dbg-record-invalid-8.ll} (100%) rename llvm/test/Assembler/{dbg-removedi-invalid-9.ll => dbg-record-invalid-9.ll} (100%) diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h index c860b17d764ff..5863a8d6e8ee8 100644 --- a/llvm/include/llvm/AsmParser/LLToken.h +++ b/llvm/include/llvm/AsmParser/LLToken.h @@ -480,12 +480,11 @@ enum Kind { DISPFlag, // DISPFlagFoo DwarfMacinfo, // DW_MACINFO_foo ChecksumKind, // CSK_foo + DbgRecordType, // dbg_foo // Type valued tokens (TyVal). Type, - DbgRecordType, - APFloat, // APFloatVal APSInt // APSInt }; diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index 64bccc3e4bba3..632bc404dce0b 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -438,6 +438,7 @@ lltok::Kind LLLexer::LexCaret() { /// Lex all tokens that start with a # character. /// AttrGrpID ::= #[0-9]+ +/// Hash ::= # lltok::Kind LLLexer::LexHash() { // Handle AttrGrpID: #[0-9]+ if (isdigit(static_cast(CurPtr[0]))) diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index a71f252005936..1556103e4ba59 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -6500,10 +6500,8 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) { } /// parseDebugProgramValue -/// ::= #dbg_Type '{' (ValueAsMetadata|DIArgList|MDNode) ',' MetadataID ',' -/// DIExpression ',' -/// (DIAssignID',' (ValueAsMetadata|MDNode)',' DIExpression] ',')? -/// DILocation '}' +/// ::= #dbg_type '(' Metadata ',' MDNode ',' Metadata ',' +/// (MDNode ',' Metadata ',' Metadata ',')? MDNode ')' bool LLParser::parseDebugProgramValue(DPValue *&DPV, PerFunctionState &PFS) { using LocType = DPValue::LocationType; LocTy DPVLoc = Lex.getLoc(); diff --git a/llvm/test/Assembler/dbg-removedi-invalid-0.ll b/llvm/test/Assembler/dbg-record-invalid-0.ll similarity index 100% rename from llvm/test/Assembler/dbg-removedi-invalid-0.ll rename to llvm/test/Assembler/dbg-record-invalid-0.ll diff --git a/llvm/test/Assembler/dbg-removedi-invalid-1.ll b/llvm/test/Assembler/dbg-record-invalid-1.ll similarity index 100% rename from llvm/test/Assembler/dbg-removedi-invalid-1.ll rename to llvm/test/Assembler/dbg-record-invalid-1.ll diff --git a/llvm/test/Assembler/dbg-removedi-invalid-10.ll b/llvm/test/Assembler/dbg-record-invalid-10.ll similarity index 100% rename from llvm/test/Assembler/dbg-removedi-invalid-10.ll rename to llvm/test/Assembler/dbg-record-invalid-10.ll diff --git a/llvm/test/Assembler/dbg-removedi-invalid-11.ll b/llvm/test/Assembler/dbg-record-invalid-11.ll similarity index 100% rename from llvm/test/Assembler/dbg-removedi-invalid-11.ll rename to llvm/test/Assembler/dbg-record-invalid-11.ll diff --git a/llvm/test/Assembler/dbg-removedi-invalid-2.ll b/llvm/test/Assembler/dbg-record-invalid-2.ll similarity index 100% rename from llvm/test/Assembler/dbg-removedi-invalid-2.ll rename to llvm/test/Assembler/dbg-record-invalid-2.ll diff --git a/llvm/test/Assembler/dbg-removedi-invalid-3.ll b/llvm/test/Assembler/dbg-record-invalid-3.ll similarity index 100% rename from llvm/test/Assembler/dbg-removedi-invalid-3.ll rename to llvm/test/Assembler/dbg-record-invalid-3.ll diff --git a/llvm/test/Assembler/dbg-removedi-invalid-4.ll b/llvm/test/Assembler/dbg-record-invalid-4.ll similarity index 100% rename from llvm/test/Assembler/dbg-removedi-invalid-4.ll rename to llvm/test/Assembler/dbg-record-invalid-4.ll diff --git a/llvm/test/Assembler/dbg-removedi-invalid-5.ll b/llvm/test/Assembler/dbg-record-invalid-5.ll similarity index 100% rename from llvm/test/Assembler/dbg-removedi-invalid-5.ll rename to llvm/test/Assembler/dbg-record-invalid-5.ll diff --git a/llvm/test/Assembler/dbg-removedi-invalid-6.ll b/llvm/test/Assembler/dbg-record-invalid-6.ll similarity index 100% rename from llvm/test/Assembler/dbg-removedi-invalid-6.ll rename to llvm/test/Assembler/dbg-record-invalid-6.ll diff --git a/llvm/test/Assembler/dbg-removedi-invalid-7.ll b/llvm/test/Assembler/dbg-record-invalid-7.ll similarity index 100% rename from llvm/test/Assembler/dbg-removedi-invalid-7.ll rename to llvm/test/Assembler/dbg-record-invalid-7.ll diff --git a/llvm/test/Assembler/dbg-removedi-invalid-8.ll b/llvm/test/Assembler/dbg-record-invalid-8.ll similarity index 100% rename from llvm/test/Assembler/dbg-removedi-invalid-8.ll rename to llvm/test/Assembler/dbg-record-invalid-8.ll diff --git a/llvm/test/Assembler/dbg-removedi-invalid-9.ll b/llvm/test/Assembler/dbg-record-invalid-9.ll similarity index 100% rename from llvm/test/Assembler/dbg-removedi-invalid-9.ll rename to llvm/test/Assembler/dbg-record-invalid-9.ll diff --git a/llvm/test/DebugInfo/roundtrip-non-instruction-debug-info.ll b/llvm/test/DebugInfo/roundtrip-non-instruction-debug-info.ll index 6efffb431aa68..434864270f660 100644 --- a/llvm/test/DebugInfo/roundtrip-non-instruction-debug-info.ll +++ b/llvm/test/DebugInfo/roundtrip-non-instruction-debug-info.ll @@ -1,22 +1,22 @@ ;; 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 +; 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 +; 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 +; 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 +; 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 +; 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: From 2e929cba70f5ea1ec2d7baac2790924771f3643a Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Wed, 28 Feb 2024 09:18:25 +0000 Subject: [PATCH 05/13] Parser fixes for DPLabel --- llvm/include/llvm/AsmParser/LLParser.h | 2 +- .../include/llvm/IR/DebugProgramInstruction.h | 9 +++ llvm/lib/AsmParser/LLLexer.cpp | 1 + llvm/lib/AsmParser/LLParser.cpp | 69 +++++++++++++------ llvm/lib/IR/DebugProgramInstruction.cpp | 14 +++- llvm/lib/IR/Verifier.cpp | 1 + .../roundtrip-non-instruction-debug-info.ll | 9 ++- 7 files changed, 80 insertions(+), 25 deletions(-) diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h index 086f06e15c862..e5e1ade8b38b3 100644 --- a/llvm/include/llvm/AsmParser/LLParser.h +++ b/llvm/include/llvm/AsmParser/LLParser.h @@ -576,7 +576,7 @@ namespace llvm { bool parseMDNodeTail(MDNode *&N); bool parseMDNodeVector(SmallVectorImpl &Elts); bool parseMetadataAttachment(unsigned &Kind, MDNode *&MD); - bool parseDebugProgramValue(DPValue *&DPV, PerFunctionState &PFS); + bool parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS); bool parseInstructionMetadata(Instruction &Inst); bool parseGlobalObjectMetadataAttachment(GlobalObject &GO); bool parseOptionalFunctionMetadata(Function &F); diff --git a/llvm/include/llvm/IR/DebugProgramInstruction.h b/llvm/include/llvm/IR/DebugProgramInstruction.h index 33fff815d474f..4253f549b5697 100644 --- a/llvm/include/llvm/IR/DebugProgramInstruction.h +++ b/llvm/include/llvm/IR/DebugProgramInstruction.h @@ -223,9 +223,18 @@ 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; diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index 632bc404dce0b..02f64fcfac4f0 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -938,6 +938,7 @@ lltok::Kind LLLexer::LexIdentifier() { DBGRECORDTYPEKEYWORD(value); DBGRECORDTYPEKEYWORD(declare); DBGRECORDTYPEKEYWORD(assign); + DBGRECORDTYPEKEYWORD(label); #undef DBGRECORDTYPEKEYWORD if (Keyword.starts_with("DIFlag")) { diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 1556103e4ba59..32dd96b78403f 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -6422,7 +6422,11 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) { // Parse the instructions and debug values in this block until we get a // terminator. Instruction *Inst; - SmallVector> TrailingDPValues; + 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 @@ -6436,10 +6440,10 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) { if (!M->IsNewDbgInfoFormat) M->convertToNewDbgValues(); - DPValue *DPV; - if (parseDebugProgramValue(DPV, PFS)) + DbgRecord *DR; + if (parseDebugRecord(DR, PFS)) return true; - TrailingDPValues.emplace_back(DPV); + TrailingDbgRecord.emplace_back(DR, DeleteDbgRecord); } // This instruction may have three possibilities for a name: a) none @@ -6488,35 +6492,58 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) { return true; // Attach any preceding debug values to this instruction. - for (std::unique_ptr &DPV : TrailingDPValues) - BB->insertDPValueBefore(DPV.release(), Inst->getIterator()); - TrailingDPValues.clear(); + for (DbgRecordPtr &DR : TrailingDbgRecord) + BB->insertDPValueBefore(DR.release(), Inst->getIterator()); + TrailingDbgRecord.clear(); } while (!Inst->isTerminator()); - assert(TrailingDPValues.empty() && + assert(TrailingDbgRecord.empty() && "All debug values should have been attached to an instruction."); return false; } -/// parseDebugProgramValue +/// parseDebugRecord +/// ::= #dbg_label '(' MDNode ')' /// ::= #dbg_type '(' Metadata ',' MDNode ',' Metadata ',' /// (MDNode ',' Metadata ',' Metadata ',')? MDNode ')' -bool LLParser::parseDebugProgramValue(DPValue *&DPV, PerFunctionState &PFS) { +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"); - auto Type = StringSwitch(Lex.getStrVal()) + 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) - .Default(LocType::End); - // If the file contained an invalid debug record type then parsing should fail - // above; the assert here should only fire if the Lexer gives us an invalid - // value. - assert(Type != LocType::End && - "Lexer returned an invalid DbgRecordType string."); + .Case("assign", LocType::Assign); + Lex.Lex(); if (parseToken(lltok::lparen, "Expected '(' here")) return true; @@ -6549,7 +6576,7 @@ bool LLParser::parseDebugProgramValue(DPValue *&DPV, PerFunctionState &PFS) { MDNode *AssignID = nullptr; Metadata *AddressLocation = nullptr; Metadata *AddressExpression = nullptr; - if (Type == LocType::Assign) { + if (ValueType == LocType::Assign) { // Parse DIAssignID. if (parseMDNode(AssignID)) return true; @@ -6579,8 +6606,8 @@ bool LLParser::parseDebugProgramValue(DPValue *&DPV, PerFunctionState &PFS) { if (parseToken(lltok::rparen, "Expected ')' here")) return true; - DPV = DPValue::createUnresolvedDPValue( - Type, ValLocMD, Variable, cast(Expression), AssignID, + DR = DPValue::createUnresolvedDPValue( + ValueType, ValLocMD, Variable, cast(Expression), AssignID, AddressLocation, cast_or_null(AddressExpression), DebugLoc); return false; } diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp index 25cd82fb91f8c..6ac20b0388203 100644 --- a/llvm/lib/IR/DebugProgramInstruction.cpp +++ b/llvm/lib/IR/DebugProgramInstruction.cpp @@ -138,16 +138,26 @@ 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) - : DebugValueUser({Val, Address, AssignID}), Variable(Variable), - Expression(Expression), DbgLoc(DI), AddressExpression(AddressExpression), + : DbgRecord(ValueKind, DebugLoc(DI)), DebugValueUser({Val, Address, AssignID}), Variable(Variable), + Expression(Expression), AddressExpression(AddressExpression), Type(Type) {} DPValue *DPValue::createUnresolvedDPValue(DPValue::LocationType Type, diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 027c6ccd1ab30..eea98946d6feb 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -684,6 +684,7 @@ void Verifier::visitDbgRecords(Instruction &I) { &I); CheckDI(!isa(&I) || !I.hasDbgValues(), "PHI Node must not have any attached DbgRecords", &I); + //for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) { for (DbgRecord &DR : I.getDbgValueRange()) { CheckDI(DR.getMarker() == I.DbgMarker, "DbgRecord had invalid DbgMarker", &I, &DR); diff --git a/llvm/test/DebugInfo/roundtrip-non-instruction-debug-info.ll b/llvm/test/DebugInfo/roundtrip-non-instruction-debug-info.ll index 434864270f660..b15b76d1690c4 100644 --- a/llvm/test/DebugInfo/roundtrip-non-instruction-debug-info.ll +++ b/llvm/test/DebugInfo/roundtrip-non-instruction-debug-info.ll @@ -28,6 +28,8 @@ ; 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]+]]) @@ -36,6 +38,7 @@ ; 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" @@ -44,6 +47,7 @@ ; 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: @@ -52,6 +56,7 @@ entry: 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 @@ -61,6 +66,7 @@ entry: 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} @@ -84,4 +90,5 @@ declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, !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() \ No newline at end of file +!40 = distinct !DIAssignID() +!50 = !DILabel(scope: !7, name: "label", file: !1, line: 3) \ No newline at end of file From f1903e0b302cd208dee9e94389b321b9c6ad6667 Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Wed, 28 Feb 2024 18:09:38 +0000 Subject: [PATCH 06/13] Parser fixes --- llvm/lib/AsmParser/LLParser.cpp | 16 ++++++---------- llvm/lib/IR/DebugProgramInstruction.cpp | 7 +++---- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 32dd96b78403f..379c5a42667f3 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -6564,18 +6564,16 @@ bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) { // Parse Expression field. LocTy ExprLoc = Lex.getLoc(); - Metadata *Expression; - if (parseMetadata(Expression, &PFS)) + MDNode *Expression; + if (parseMDNode(Expression)) return true; - if (!isa(Expression)) - return error(ExprLoc, "expected valid inline DIExpression here"); if (parseToken(lltok::comma, "Expected ',' here")) return true; // Parse additional fields for #dbg_assign. MDNode *AssignID = nullptr; Metadata *AddressLocation = nullptr; - Metadata *AddressExpression = nullptr; + MDNode *AddressExpression = nullptr; if (ValueType == LocType::Assign) { // Parse DIAssignID. if (parseMDNode(AssignID)) @@ -6591,10 +6589,8 @@ bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) { // Parse address DIExpression. LocTy AddressExprLoc = Lex.getLoc(); - if (parseMetadata(AddressExpression, &PFS)) + if (parseMDNode(AddressExpression)) return true; - if (!isa(AddressExpression)) - return error(AddressExprLoc, "expected valid inline DIExpression here"); if (parseToken(lltok::comma, "Expected ',' here")) return true; } @@ -6607,8 +6603,8 @@ bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) { if (parseToken(lltok::rparen, "Expected ')' here")) return true; DR = DPValue::createUnresolvedDPValue( - ValueType, ValLocMD, Variable, cast(Expression), AssignID, - AddressLocation, cast_or_null(AddressExpression), DebugLoc); + ValueType, ValLocMD, Variable, Expression, AssignID, + AddressLocation, AddressExpression, DebugLoc); return false; } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp index 6ac20b0388203..dbeaa67410609 100644 --- a/llvm/lib/IR/DebugProgramInstruction.cpp +++ b/llvm/lib/IR/DebugProgramInstruction.cpp @@ -142,7 +142,7 @@ DbgRecord::createDebugIntrinsic(Module *M, Instruction *InsertBefore) const { 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"); + 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) { @@ -156,9 +156,8 @@ DPLabel *DPLabel::createUnresolvedDPLabel(MDNode *Label, MDNode *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}), Variable(Variable), - Expression(Expression), AddressExpression(AddressExpression), - Type(Type) {} + : 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, From 3bee3661f0d95673bd026e698c34b41bf9cb877d Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Wed, 28 Feb 2024 18:27:52 +0000 Subject: [PATCH 07/13] Unused variables --- llvm/lib/AsmParser/LLParser.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 379c5a42667f3..02c32cff3c53a 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -6563,7 +6563,6 @@ bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) { return true; // Parse Expression field. - LocTy ExprLoc = Lex.getLoc(); MDNode *Expression; if (parseMDNode(Expression)) return true; @@ -6588,7 +6587,6 @@ bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) { return true; // Parse address DIExpression. - LocTy AddressExprLoc = Lex.getLoc(); if (parseMDNode(AddressExpression)) return true; if (parseToken(lltok::comma, "Expected ',' here")) From ea2a9245ef94dd5b14fbb3237888c1875a7aa3fb Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Wed, 28 Feb 2024 18:20:43 +0000 Subject: [PATCH 08/13] Add tests (requires parsing) --- llvm/test/Verifier/RemoveDI/blockbyref.ll | 18 ++++++ .../Verifier/RemoveDI/dbg-invalid-vector.ll | 35 +++++++++++ .../RemoveDI/di-subroutine-localvar.ll | 41 ++++++++++++ .../diexpression-entry-value-llvm-ir.ll | 34 ++++++++++ .../test/Verifier/RemoveDI/fnarg-debuginfo.ll | 26 ++++++++ llvm/test/Verifier/RemoveDI/fnarg-nodebug.ll | 58 +++++++++++++++++ .../RemoveDI/invalid-disubrange-count-node.ll | 36 +++++++++++ .../RemoveDI/llvm.dbg.declare-address.ll | 16 +++++ .../RemoveDI/llvm.dbg.declare-expression.ll | 16 +++++ .../RemoveDI/llvm.dbg.declare-variable.ll | 17 +++++ .../llvm.dbg.intrinsic-dbg-attachment.ll | 55 ++++++++++++++++ .../RemoveDI/llvm.dbg.value-expression.ll | 16 +++++ .../Verifier/RemoveDI/llvm.dbg.value-value.ll | 17 +++++ .../RemoveDI/llvm.dbg.value-variable.ll | 17 +++++ llvm/test/Verifier/RemoveDI/set1.ll | 62 +++++++++++++++++++ 15 files changed, 464 insertions(+) create mode 100644 llvm/test/Verifier/RemoveDI/blockbyref.ll create mode 100644 llvm/test/Verifier/RemoveDI/dbg-invalid-vector.ll create mode 100644 llvm/test/Verifier/RemoveDI/di-subroutine-localvar.ll create mode 100644 llvm/test/Verifier/RemoveDI/diexpression-entry-value-llvm-ir.ll create mode 100644 llvm/test/Verifier/RemoveDI/fnarg-debuginfo.ll create mode 100644 llvm/test/Verifier/RemoveDI/fnarg-nodebug.ll create mode 100644 llvm/test/Verifier/RemoveDI/invalid-disubrange-count-node.ll create mode 100644 llvm/test/Verifier/RemoveDI/llvm.dbg.declare-address.ll create mode 100644 llvm/test/Verifier/RemoveDI/llvm.dbg.declare-expression.ll create mode 100644 llvm/test/Verifier/RemoveDI/llvm.dbg.declare-variable.ll create mode 100644 llvm/test/Verifier/RemoveDI/llvm.dbg.intrinsic-dbg-attachment.ll create mode 100644 llvm/test/Verifier/RemoveDI/llvm.dbg.value-expression.ll create mode 100644 llvm/test/Verifier/RemoveDI/llvm.dbg.value-value.ll create mode 100644 llvm/test/Verifier/RemoveDI/llvm.dbg.value-variable.ll create mode 100644 llvm/test/Verifier/RemoveDI/set1.ll 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..226324036a5bb --- /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 location +; CHECK-NEXT: #dbg_value({{.*}}) + + #dbg_declare( + ptr undef, + !DILocalVariable(scope: !1), + !DIExpression(), + !{}) +; CHECK-LABEL: invalid #dbg record location +; 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) From b56190db4d35efb9bea180a58d5f95707240c03a Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Fri, 1 Mar 2024 11:11:06 +0000 Subject: [PATCH 09/13] Delete tests for DIExpression validity --- llvm/test/Assembler/dbg-record-invalid-10.ll | 36 -------------------- llvm/test/Assembler/dbg-record-invalid-11.ll | 35 ------------------- llvm/test/Assembler/dbg-record-invalid-5.ll | 10 +++--- llvm/test/Assembler/dbg-record-invalid-6.ll | 9 +++-- 4 files changed, 8 insertions(+), 82 deletions(-) delete mode 100644 llvm/test/Assembler/dbg-record-invalid-10.ll delete mode 100644 llvm/test/Assembler/dbg-record-invalid-11.ll diff --git a/llvm/test/Assembler/dbg-record-invalid-10.ll b/llvm/test/Assembler/dbg-record-invalid-10.ll deleted file mode 100644 index 72dafcdb97fce..0000000000000 --- a/llvm/test/Assembler/dbg-record-invalid-10.ll +++ /dev/null @@ -1,36 +0,0 @@ -;; 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-11.ll b/llvm/test/Assembler/dbg-record-invalid-11.ll deleted file mode 100644 index 5ea588b87668c..0000000000000 --- a/llvm/test/Assembler/dbg-record-invalid-11.ll +++ /dev/null @@ -1,35 +0,0 @@ -;; 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-5.ll b/llvm/test/Assembler/dbg-record-invalid-5.ll index 2b3e3a763221d..5ea588b87668c 100644 --- a/llvm/test/Assembler/dbg-record-invalid-5.ll +++ b/llvm/test/Assembler/dbg-record-invalid-5.ll @@ -1,14 +1,13 @@ -;; Test that we get a parser error when we have a debug record that does not use -;; an inline DIExpression. +;; 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: -; CHECK: :[[@LINE+1]]:29: error: expected valid inline DIExpression here - #dbg_value(i32 %a, !12, !20, !14) - 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} @@ -34,4 +33,3 @@ entry: !16 = !DILocation(line: 3, column: 20, scope: !7) !17 = !DILocation(line: 3, column: 25, scope: !7) !18 = !DILocation(line: 3, column: 30, scope: !7) -!20 = !DIExpression() diff --git a/llvm/test/Assembler/dbg-record-invalid-6.ll b/llvm/test/Assembler/dbg-record-invalid-6.ll index 9aff3c79d79bb..72dafcdb97fce 100644 --- a/llvm/test/Assembler/dbg-record-invalid-6.ll +++ b/llvm/test/Assembler/dbg-record-invalid-6.ll @@ -1,13 +1,13 @@ -;; Test that we get a parser error when we have a debug assign record that does -;; not use an inline DIExpression for its address expression. +;; 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]]:63: error: expected valid inline DIExpression here - #dbg_assign(i32 %a, !12, !DIExpression(), !15, ptr undef, !20, !14) +; CHECK: :[[@LINE+1]]:46: error: expected '!' here + #dbg_value(i32 %a, !12, !DIExpression(), i32 0) ret i32 %a, !dbg !18 } @@ -34,4 +34,3 @@ entry: !16 = !DILocation(line: 3, column: 20, scope: !7) !17 = !DILocation(line: 3, column: 25, scope: !7) !18 = !DILocation(line: 3, column: 30, scope: !7) -!20 = !DIExpression() From 5702fea17e487ca97073a7eb0f2e157026ffa412 Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Mon, 4 Mar 2024 17:00:33 +0000 Subject: [PATCH 10/13] clang-format --- .../include/llvm/IR/DebugProgramInstruction.h | 4 ++-- llvm/lib/AsmParser/LLParser.cpp | 24 +++++++++---------- llvm/lib/IR/DebugProgramInstruction.cpp | 11 +++++---- llvm/lib/IR/Verifier.cpp | 2 +- 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/llvm/include/llvm/IR/DebugProgramInstruction.h b/llvm/include/llvm/IR/DebugProgramInstruction.h index 4253f549b5697..a8faf415a3ea8 100644 --- a/llvm/include/llvm/IR/DebugProgramInstruction.h +++ b/llvm/include/llvm/IR/DebugProgramInstruction.h @@ -227,6 +227,7 @@ class DPLabel : public DbgRecord { /// "createUnresolvedDPLabel", which clearly expresses that it is for parsing /// only. DPLabel(MDNode *Label, MDNode *DL); + public: DPLabel(DILabel *Label, DebugLoc DL); @@ -313,8 +314,7 @@ class DPValue : public DbgRecord, protected DebugValueUser { /// 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 *Variable, MDNode *Expression, MDNode *AssignID, Metadata *Address, MDNode *AddressExpression, MDNode *DI); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 02c32cff3c53a..6079232cd76bf 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -6422,9 +6422,7 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) { // Parse the instructions and debug values in this block until we get a // terminator. Instruction *Inst; - auto DeleteDbgRecord = [](DbgRecord *DR) { - DR->deleteRecord(); - }; + auto DeleteDbgRecord = [](DbgRecord *DR) { DR->deleteRecord(); }; using DbgRecordPtr = std::unique_ptr; SmallVector TrailingDbgRecord; do { @@ -6514,10 +6512,10 @@ bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) { 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); + .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. @@ -6540,9 +6538,9 @@ bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) { } LocType ValueType = StringSwitch(Lex.getStrVal()) - .Case("declare", LocType::Declare) - .Case("value", LocType::Value) - .Case("assign", LocType::Assign); + .Case("declare", LocType::Declare) + .Case("value", LocType::Value) + .Case("assign", LocType::Assign); Lex.Lex(); if (parseToken(lltok::lparen, "Expected '(' here")) @@ -6600,9 +6598,9 @@ bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) { if (parseToken(lltok::rparen, "Expected ')' here")) return true; - DR = DPValue::createUnresolvedDPValue( - ValueType, ValLocMD, Variable, Expression, AssignID, - AddressLocation, AddressExpression, DebugLoc); + DR = DPValue::createUnresolvedDPValue(ValueType, ValLocMD, Variable, + Expression, AssignID, AddressLocation, + AddressExpression, DebugLoc); return false; } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp index dbeaa67410609..5ff1e8c19db68 100644 --- a/llvm/lib/IR/DebugProgramInstruction.cpp +++ b/llvm/lib/IR/DebugProgramInstruction.cpp @@ -138,11 +138,11 @@ 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"); + 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) { @@ -156,13 +156,14 @@ DPLabel *DPLabel::createUnresolvedDPLabel(MDNode *Label, MDNode *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), + : 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 *Expression, MDNode *AssignID, + Metadata *Address, MDNode *AddressExpression, MDNode *DI) { return new DPValue(Type, Val, Variable, Expression, AssignID, Address, diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index eea98946d6feb..220d028ddc4d6 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -684,7 +684,7 @@ void Verifier::visitDbgRecords(Instruction &I) { &I); CheckDI(!isa(&I) || !I.hasDbgValues(), "PHI Node must not have any attached DbgRecords", &I); - //for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) { + // for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) { for (DbgRecord &DR : I.getDbgValueRange()) { CheckDI(DR.getMarker() == I.DbgMarker, "DbgRecord had invalid DbgMarker", &I, &DR); From 758ef7c18809c807efd59fc47570fe43972db28f Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Tue, 5 Mar 2024 15:29:57 +0000 Subject: [PATCH 11/13] Don't error-out when we see an intrinsic decl --- llvm/lib/AsmParser/LLParser.cpp | 7 ---- llvm/test/Assembler/dbg-record-invalid-2.ll | 10 +++--- llvm/test/Assembler/dbg-record-invalid-9.ll | 36 --------------------- 3 files changed, 4 insertions(+), 49 deletions(-) delete mode 100644 llvm/test/Assembler/dbg-record-invalid-9.ll diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 6079232cd76bf..e140c94195205 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -6250,13 +6250,6 @@ bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine, } } - if (isOldDbgFormatIntrinsic(FunctionName)) { - if (SeenNewDbgInfoFormat) - return error(NameLoc, "llvm.dbg intrinsic should not appear in a module " - "using non-intrinsic debug info"); - SeenOldDbgInfoFormat = true; - } - Fn = Function::Create(FT, GlobalValue::ExternalLinkage, AddrSpace, FunctionName, M); diff --git a/llvm/test/Assembler/dbg-record-invalid-2.ll b/llvm/test/Assembler/dbg-record-invalid-2.ll index 753a486e896b5..a019f73feab9c 100644 --- a/llvm/test/Assembler/dbg-record-invalid-2.ll +++ b/llvm/test/Assembler/dbg-record-invalid-2.ll @@ -1,18 +1,16 @@ -;; Test that we get a parser error when a debug intrinsic declaration appears in -;; the same module as a debug intrinsic declaration. +;; 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: - #dbg_value(!DIArgList(i32 %a), !12, !DIExpression(), !14) +; CHECK: :[[@LINE+1]]:24: error: expected '!' here + #dbg_value(i32 %a, i32 0, !DIExpression(), !14) ret i32 %a, !dbg !18 } -; CHECK: :[[@LINE+1]]:14: error: llvm.dbg intrinsic should not appear in a module using non-intrinsic debug info -declare void @llvm.dbg.value(metadata, metadata, metadata) - !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4, !5} !llvm.ident = !{!6} diff --git a/llvm/test/Assembler/dbg-record-invalid-9.ll b/llvm/test/Assembler/dbg-record-invalid-9.ll deleted file mode 100644 index a019f73feab9c..0000000000000 --- a/llvm/test/Assembler/dbg-record-invalid-9.ll +++ /dev/null @@ -1,36 +0,0 @@ -;; 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) From d87a9aafc4eb96e1cb80d1c69cfd7e7b08b6940e Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Thu, 7 Mar 2024 09:28:07 +0000 Subject: [PATCH 12/13] Remove hanging comment --- llvm/lib/IR/Verifier.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 220d028ddc4d6..027c6ccd1ab30 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -684,7 +684,6 @@ void Verifier::visitDbgRecords(Instruction &I) { &I); CheckDI(!isa(&I) || !I.hasDbgValues(), "PHI Node must not have any attached DbgRecords", &I); - // for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) { for (DbgRecord &DR : I.getDbgValueRange()) { CheckDI(DR.getMarker() == I.DbgMarker, "DbgRecord had invalid DbgMarker", &I, &DR); From 6e90f7aa71fc97967610c87c83d9bc5d1b509415 Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Thu, 7 Mar 2024 11:15:57 +0000 Subject: [PATCH 13/13] Update 'bad location' check to be more specific --- llvm/lib/IR/Verifier.cpp | 2 +- .../Verifier/RemoveDI/llvm.dbg.intrinsic-dbg-attachment.ll | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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/Verifier/RemoveDI/llvm.dbg.intrinsic-dbg-attachment.ll b/llvm/test/Verifier/RemoveDI/llvm.dbg.intrinsic-dbg-attachment.ll index 226324036a5bb..1839821ab1407 100644 --- a/llvm/test/Verifier/RemoveDI/llvm.dbg.intrinsic-dbg-attachment.ll +++ b/llvm/test/Verifier/RemoveDI/llvm.dbg.intrinsic-dbg-attachment.ll @@ -6,7 +6,7 @@ entry: !DILocalVariable(scope: !1), !DIExpression(), !{}) -; CHECK-LABEL: invalid #dbg record location +; CHECK-LABEL: invalid #dbg record DILocation ; CHECK-NEXT: #dbg_value({{.*}}) #dbg_declare( @@ -14,7 +14,7 @@ entry: !DILocalVariable(scope: !1), !DIExpression(), !{}) -; CHECK-LABEL: invalid #dbg record location +; CHECK-LABEL: invalid #dbg record DILocation ; CHECK-NEXT: #dbg_declare({{.*}}) #dbg_value(