[llvm] [RemoveDIs][DebugInfo][IR] Add parsing for non-intrinsic debug values (PR #79818)

Stephen Tozer via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 7 01:28:33 PST 2024


https://github.com/SLTozer updated https://github.com/llvm/llvm-project/pull/79818

>From df8fa60b3b3c880ebb9c3bbc269d3cb2089cac61 Mon Sep 17 00:00:00 2001
From: Stephen Tozer <Stephen.Tozer at Sony.com>
Date: Mon, 29 Jan 2024 11:04:24 +0000
Subject: [PATCH 01/12] 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 f07f4c61f9d649..086f06e15c8627 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<Metadata *> &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 3c34706ee03e82..c860b17d764ff4 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 cf30b4d0b0aaf0..33fff815d474f8 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 5d8a50eee13068..64bccc3e4bba3d 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<unsigned char>(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 a91e2f690999e0..c91a5520d8a5fd 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -62,6 +62,8 @@ static cl::opt<bool> AllowIncompleteIR(
         "Allow incomplete IR on a best effort basis (references to unknown "
         "metadata will be dropped)"));
 
+extern llvm::cl::opt<bool> 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<std::unique_ptr<DPValue>> 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<DPValue> &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<LocType>(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<DIExpression>(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<DIExpression>(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<DIExpression>(Expression), AssignID,
+      AddressLocation, cast_or_null<DIExpression>(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 a8d64024e1797b..25cd82fb91f8c4 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 00000000000000..f8c0024977bc22
--- /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 <Stephen.Tozer at Sony.com>
Date: Mon, 29 Jan 2024 16:02:50 +0000
Subject: [PATCH 02/12] 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 c91a5520d8a5fd..d202ebaa86cf2a 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<std::unique_ptr<DPValue>> 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<DPValue> &DPV : TrailingDPValues) {
+    for (std::unique_ptr<DPValue> &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<LocType>(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 <Stephen.Tozer at Sony.com>
Date: Mon, 29 Jan 2024 16:22:47 +0000
Subject: [PATCH 03/12] 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 d202ebaa86cf2a..a71f2520059360 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<DIExpression>(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<DIExpression>(Expression))
-      return error(AddressExprLoc, "expected valid DIExpression here");
+    if (!isa<DIExpression>(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<DIExpression>(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 00000000000000..feb513a405f9ec
--- /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 = '<stdin>'
+source_filename = "<stdin>"
+
+define dso_local i32 @f(i32 %a) !dbg !7 {
+entry:
+  ret i32 %a, !dbg !18
+    #dbg_value(!DIArgList(i32 %a), !12, !DIExpression(), !14)
+; CHECK: <stdin>:[[@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 00000000000000..7ab5751777e8cf
--- /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 = '<stdin>'
+source_filename = "<stdin>"
+
+define dso_local i32 @f(i32 %a) !dbg !7 {
+entry:
+    #dbg_value(!DIArgList(i32 %a), !12, !DIExpression(), !14)
+; CHECK: <stdin>:[[@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 00000000000000..72dafcdb97fce4
--- /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 = '<stdin>'
+source_filename = "<stdin>"
+
+define dso_local i32 @f(i32 %a) !dbg !7 {
+entry:
+; CHECK: <stdin>:[[@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 00000000000000..5ea588b87668c4
--- /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 = '<stdin>'
+source_filename = "<stdin>"
+
+define dso_local i32 @f(i32 %a) !dbg !7 {
+entry:
+    #dbg_value(!DIArgList(i32 %a), !12, !DIExpression(), !14)
+; CHECK: <stdin>:[[@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 00000000000000..753a486e896b5a
--- /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 = '<stdin>'
+source_filename = "<stdin>"
+
+define dso_local i32 @f(i32 %a) !dbg !7 {
+entry:
+    #dbg_value(!DIArgList(i32 %a), !12, !DIExpression(), !14)
+  ret i32 %a, !dbg !18
+}
+
+; CHECK: <stdin>:[[@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 00000000000000..e6f072373f54d5
--- /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 = '<stdin>'
+source_filename = "<stdin>"
+
+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: <stdin>:[[@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 00000000000000..f898477603c8e2
--- /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 = '<stdin>'
+source_filename = "<stdin>"
+
+define dso_local i32 @f(i32 %a) !dbg !7 {
+entry:
+; CHECK: <stdin>:[[@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 00000000000000..2b3e3a763221d3
--- /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 = '<stdin>'
+source_filename = "<stdin>"
+
+define dso_local i32 @f(i32 %a) !dbg !7 {
+entry:
+; CHECK: <stdin>:[[@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 00000000000000..9aff3c79d79bb5
--- /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 = '<stdin>'
+source_filename = "<stdin>"
+
+define dso_local i32 @f(i32 %a) !dbg !7 {
+entry:
+; CHECK: <stdin>:[[@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 00000000000000..036a85a2977fc7
--- /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 = '<stdin>'
+source_filename = "<stdin>"
+
+define dso_local i32 @f(i32 %a) !dbg !7 {
+entry:
+; CHECK: <stdin>:[[@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 00000000000000..d0b8f36d7895c5
--- /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 = '<stdin>'
+source_filename = "<stdin>"
+
+define dso_local i32 @f(i32 %a) !dbg !7 {
+entry:
+; CHECK: <stdin>:[[@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 00000000000000..a019f73feab9c5
--- /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 = '<stdin>'
+source_filename = "<stdin>"
+
+define dso_local i32 @f(i32 %a) !dbg !7 {
+entry:
+; CHECK: <stdin>:[[@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 f8c0024977bc22..6efffb431aa687 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 <stephen.tozer at sony.com>
Date: Thu, 22 Feb 2024 15:51:02 +0000
Subject: [PATCH 04/12] 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 c860b17d764ff4..5863a8d6e8ee84 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 64bccc3e4bba3d..632bc404dce0bb 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<unsigned char>(CurPtr[0])))
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index a71f2520059360..1556103e4ba598 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 6efffb431aa687..434864270f660d 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 <stephen.tozer at sony.com>
Date: Wed, 28 Feb 2024 09:18:25 +0000
Subject: [PATCH 05/12] 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 086f06e15c8627..e5e1ade8b38b36 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<Metadata *> &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 33fff815d474f8..4253f549b5697b 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<DILabel> 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 632bc404dce0bb..02f64fcfac4f0c 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 1556103e4ba598..32dd96b78403f2 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<std::unique_ptr<DPValue>> TrailingDPValues;
+  auto DeleteDbgRecord = [](DbgRecord *DR) {
+    DR->deleteRecord();
+  };
+  using DbgRecordPtr = std::unique_ptr<DbgRecord, decltype(DeleteDbgRecord)>;
+  SmallVector<DbgRecordPtr> 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<DPValue> &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<LocType>(Lex.getStrVal())
+  RecordKind RecordType = StringSwitch<RecordKind>(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<LocType>(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<DIExpression>(Expression), AssignID,
+  DR = DPValue::createUnresolvedDPValue(
+      ValueType, ValLocMD, Variable, cast<DIExpression>(Expression), AssignID,
       AddressLocation, cast_or_null<DIExpression>(AddressExpression), DebugLoc);
   return false;
 }
diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp
index 25cd82fb91f8c4..6ac20b03882036 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<DILabel>(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 027c6ccd1ab304..eea98946d6feb4 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<PHINode>(&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 434864270f660d..b15b76d1690c41 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 <stephen.tozer at sony.com>
Date: Wed, 28 Feb 2024 18:09:38 +0000
Subject: [PATCH 06/12] 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 32dd96b78403f2..379c5a42667f37 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<DIExpression>(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<DIExpression>(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<DIExpression>(Expression), AssignID,
-      AddressLocation, cast_or_null<DIExpression>(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 6ac20b03882036..dbeaa674106098 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<DILabel>(Label) || Label->isTemporary() && "Label type must be or resolve to a DILabel");
+  assert((isa<DILabel>(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 <stephen.tozer at sony.com>
Date: Wed, 28 Feb 2024 18:27:52 +0000
Subject: [PATCH 07/12] 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 379c5a42667f37..02c32cff3c53a7 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 <stephen.tozer at sony.com>
Date: Wed, 28 Feb 2024 18:20:43 +0000
Subject: [PATCH 08/12] 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 00000000000000..86321a6ae78e80
--- /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 00000000000000..0832c361c3080e
--- /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
+
+ at 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 00000000000000..14e58883989968
--- /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 00000000000000..881ec4a86fb644
--- /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 00000000000000..db1a9a8ba18945
--- /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 00000000000000..f5526030278eb9
--- /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 00000000000000..f36cee5946e473
--- /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 00000000000000..9d400b892ce8c1
--- /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 00000000000000..b52c15cb3f8816
--- /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 00000000000000..db2b0e0a54e2bd
--- /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 00000000000000..226324036a5bbd
--- /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 00000000000000..cbd93c1ce6a4d6
--- /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 00000000000000..b6fcde250526be
--- /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 00000000000000..0a5fe79453d721
--- /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 00000000000000..d54ba8876c366c
--- /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 <stephen.tozer at sony.com>
Date: Fri, 1 Mar 2024 11:11:06 +0000
Subject: [PATCH 09/12] 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 72dafcdb97fce4..00000000000000
--- 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 = '<stdin>'
-source_filename = "<stdin>"
-
-define dso_local i32 @f(i32 %a) !dbg !7 {
-entry:
-; CHECK: <stdin>:[[@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 5ea588b87668c4..00000000000000
--- 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 = '<stdin>'
-source_filename = "<stdin>"
-
-define dso_local i32 @f(i32 %a) !dbg !7 {
-entry:
-    #dbg_value(!DIArgList(i32 %a), !12, !DIExpression(), !14)
-; CHECK: <stdin>:[[@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 2b3e3a763221d3..5ea588b87668c4 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 = '<stdin>'
 source_filename = "<stdin>"
 
 define dso_local i32 @f(i32 %a) !dbg !7 {
 entry:
-; CHECK: <stdin>:[[@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: <stdin>:[[@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 9aff3c79d79bb5..72dafcdb97fce4 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 = '<stdin>'
 source_filename = "<stdin>"
 
 define dso_local i32 @f(i32 %a) !dbg !7 {
 entry:
-; CHECK: <stdin>:[[@LINE+1]]:63: error: expected valid inline DIExpression here
-    #dbg_assign(i32 %a, !12, !DIExpression(), !15, ptr undef, !20, !14)
+; CHECK: <stdin>:[[@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 <stephen.tozer at sony.com>
Date: Mon, 4 Mar 2024 17:00:33 +0000
Subject: [PATCH 10/12] 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 4253f549b5697b..a8faf415a3ea87 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 02c32cff3c53a7..6079232cd76bf8 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<DbgRecord, decltype(DeleteDbgRecord)>;
   SmallVector<DbgRecordPtr> 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<RecordKind>(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<LocType>(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 dbeaa674106098..5ff1e8c19db68b 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<DILabel>(Label) || Label->isTemporary()) && "Label type must be or resolve to a DILabel");
+  assert((isa<DILabel>(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 eea98946d6feb4..220d028ddc4d60 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<PHINode>(&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 <stephen.tozer at sony.com>
Date: Tue, 5 Mar 2024 15:29:57 +0000
Subject: [PATCH 11/12] 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 6079232cd76bf8..e140c94195205a 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 753a486e896b5a..a019f73feab9c5 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 = '<stdin>'
 source_filename = "<stdin>"
 
 define dso_local i32 @f(i32 %a) !dbg !7 {
 entry:
-    #dbg_value(!DIArgList(i32 %a), !12, !DIExpression(), !14)
+; CHECK: <stdin>:[[@LINE+1]]:24: error: expected '!' here
+    #dbg_value(i32 %a, i32 0, !DIExpression(), !14)
   ret i32 %a, !dbg !18
 }
 
-; CHECK: <stdin>:[[@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 a019f73feab9c5..00000000000000
--- 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 = '<stdin>'
-source_filename = "<stdin>"
-
-define dso_local i32 @f(i32 %a) !dbg !7 {
-entry:
-; CHECK: <stdin>:[[@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 <stephen.tozer at sony.com>
Date: Thu, 7 Mar 2024 09:28:07 +0000
Subject: [PATCH 12/12] 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 220d028ddc4d60..027c6ccd1ab304 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<PHINode>(&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);



More information about the llvm-commits mailing list