[llvm] c37f29c - [Assignment Tracking][4/*] Add llvm.dbg.assign intrinsic boilerplate

via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 7 02:10:33 PST 2022


Author: OCHyams
Date: 2022-11-07T10:09:22Z
New Revision: c37f29c49ea237eaf65dd137bffc1f3316f82951

URL: https://github.com/llvm/llvm-project/commit/c37f29c49ea237eaf65dd137bffc1f3316f82951
DIFF: https://github.com/llvm/llvm-project/commit/c37f29c49ea237eaf65dd137bffc1f3316f82951.diff

LOG: [Assignment Tracking][4/*] Add llvm.dbg.assign intrinsic boilerplate

The Assignment Tracking debug-info feature is outlined in this RFC:

https://discourse.llvm.org/t/
rfc-assignment-tracking-a-better-way-of-specifying-variable-locations-in-ir

Add the llvm.dbg.assign intrinsic boilerplate. This updates the textual-bitcode
roundtrip test to also check that round-tripping with the intrinsic works.

The intrinsic marks the position of a source level assignment.

The llvm.dbg.assign interface looks like this (each parameter is wrapped in
MetadataAsValue, and Value * type parameters are first wrapped in
ValueAsMetadata):

    void @llvm.dbg.assign(Value *Value,
                          DIExpression *ValueExpression,
                          DILocalVariable *Variable,
                          DIAssignID *ID,
                          Value *Address,
                          DIExpression *AddressExpression)

The first three parameters look and behave like an llvm.dbg.value. ID is a
reference to a store. The intrinsic is "linked to" instructions in the same
function that use the same ID as an attachment. That is mostly conceptual at
this point; the two-way link infrastructure will come in another patch. Address
is the destination address of the store and it is modified by
AddressExpression. LLVM currently encodes variable fragment information in
DIExpressions, so as an implementation quirk the FragmentInfo for Variable is
contained within ValueExpression only.

Reviewed By: jmorse

Differential Revision: https://reviews.llvm.org/D132223

Added: 
    llvm/test/DebugInfo/Generic/assignment-tracking/parse-and-verify/verify.ll

Modified: 
    llvm/include/llvm/IR/IntrinsicInst.h
    llvm/include/llvm/IR/Intrinsics.td
    llvm/lib/IR/IntrinsicInst.cpp
    llvm/lib/IR/Verifier.cpp
    llvm/test/DebugInfo/Generic/assignment-tracking/parse-and-verify/roundtrip.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h
index 4ff48c3669d50..f78e45c0e32ee 100644
--- a/llvm/include/llvm/IR/IntrinsicInst.h
+++ b/llvm/include/llvm/IR/IntrinsicInst.h
@@ -91,6 +91,7 @@ class IntrinsicInst : public CallInst {
     case Intrinsic::assume:
     case Intrinsic::sideeffect:
     case Intrinsic::pseudoprobe:
+    case Intrinsic::dbg_assign:
     case Intrinsic::dbg_declare:
     case Intrinsic::dbg_value:
     case Intrinsic::dbg_label:
@@ -129,6 +130,7 @@ static inline bool isDbgInfoIntrinsic(Intrinsic::ID ID) {
   case Intrinsic::dbg_value:
   case Intrinsic::dbg_addr:
   case Intrinsic::dbg_label:
+  case Intrinsic::dbg_assign:
     return true;
   default:
     return false;
@@ -231,10 +233,12 @@ class DbgVariableIntrinsic : public DbgInfoIntrinsic {
 
   bool hasArgList() const { return isa<DIArgList>(getRawLocation()); }
 
-  /// Does this describe the address of a local variable. True for dbg.addr
-  /// and dbg.declare, but not dbg.value, which describes its value.
+  /// Does this describe the address of a local variable. True for dbg.addr and
+  /// dbg.declare, but not dbg.value, which describes its value, or dbg.assign,
+  /// which describes a combination of the variable's value and address.
   bool isAddressOfVariable() const {
-    return getIntrinsicID() != Intrinsic::dbg_value;
+    return getIntrinsicID() != Intrinsic::dbg_value &&
+           getIntrinsicID() != Intrinsic::dbg_assign;
   }
 
   void setUndef() {
@@ -286,6 +290,11 @@ class DbgVariableIntrinsic : public DbgInfoIntrinsic {
   /// is described.
   Optional<uint64_t> getFragmentSizeInBits() const;
 
+  /// Get the FragmentInfo for the variable.
+  Optional<DIExpression::FragmentInfo> getFragment() const {
+    return getExpression()->getFragmentInfo();
+  }
+
   /// \name Casting methods
   /// @{
   static bool classof(const IntrinsicInst *I) {
@@ -293,6 +302,7 @@ class DbgVariableIntrinsic : public DbgInfoIntrinsic {
     case Intrinsic::dbg_declare:
     case Intrinsic::dbg_value:
     case Intrinsic::dbg_addr:
+    case Intrinsic::dbg_assign:
       return true;
     default:
       return false;
@@ -302,7 +312,7 @@ class DbgVariableIntrinsic : public DbgInfoIntrinsic {
     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
   }
   /// @}
-private:
+protected:
   void setArgOperand(unsigned i, Value *v) {
     DbgInfoIntrinsic::setArgOperand(i, v);
   }
@@ -363,7 +373,52 @@ class DbgValueInst : public DbgVariableIntrinsic {
   /// \name Casting methods
   /// @{
   static bool classof(const IntrinsicInst *I) {
-    return I->getIntrinsicID() == Intrinsic::dbg_value;
+    return I->getIntrinsicID() == Intrinsic::dbg_value ||
+           I->getIntrinsicID() == Intrinsic::dbg_assign;
+  }
+  static bool classof(const Value *V) {
+    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
+  }
+  /// @}
+};
+
+/// This represents the llvm.dbg.assign instruction.
+class DbgAssignIntrinsic : public DbgValueInst {
+  enum Operands {
+    OpValue,
+    OpVar,
+    OpExpr,
+    OpAssignID,
+    OpAddress,
+    OpAddressExpr,
+  };
+
+public:
+  Value *getAddress() const;
+  Metadata *getRawAddress() const {
+    return cast<MetadataAsValue>(getArgOperand(OpAddress))->getMetadata();
+  }
+  Metadata *getRawAssignID() const {
+    return cast<MetadataAsValue>(getArgOperand(OpAssignID))->getMetadata();
+  }
+  DIAssignID *getAssignID() const { return cast<DIAssignID>(getRawAssignID()); }
+  Metadata *getRawAddressExpression() const {
+    return cast<MetadataAsValue>(getArgOperand(OpAddressExpr))->getMetadata();
+  }
+  DIExpression *getAddressExpression() const {
+    return cast<DIExpression>(getRawAddressExpression());
+  }
+  void setAddressExpression(DIExpression *NewExpr) {
+    setArgOperand(OpAddressExpr,
+                  MetadataAsValue::get(NewExpr->getContext(), NewExpr));
+  }
+  void setAssignId(DIAssignID *New);
+  void setAddress(Value *V);
+  void setValue(Value *V);
+  /// \name Casting methods
+  /// @{
+  static bool classof(const IntrinsicInst *I) {
+    return I->getIntrinsicID() == Intrinsic::dbg_assign;
   }
   static bool classof(const Value *V) {
     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));

diff  --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index e8fb5c4aef191..3050bd2acec73 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -998,6 +998,13 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in {
                                        [llvm_metadata_ty,
                                         llvm_metadata_ty,
                                         llvm_metadata_ty]>;
+  def int_dbg_assign        : DefaultAttrsIntrinsic<[],
+                                       [llvm_metadata_ty,
+                                        llvm_metadata_ty,
+                                        llvm_metadata_ty,
+                                        llvm_metadata_ty,
+                                        llvm_metadata_ty,
+                                        llvm_metadata_ty]>;
   def int_dbg_label        : DefaultAttrsIntrinsic<[],
                                        [llvm_metadata_ty]>;
 }

diff  --git a/llvm/lib/IR/IntrinsicInst.cpp b/llvm/lib/IR/IntrinsicInst.cpp
index 8ca75f58e4033..b6537b2077ebe 100644
--- a/llvm/lib/IR/IntrinsicInst.cpp
+++ b/llvm/lib/IR/IntrinsicInst.cpp
@@ -112,10 +112,23 @@ static ValueAsMetadata *getAsMetadata(Value *V) {
 
 void DbgVariableIntrinsic::replaceVariableLocationOp(Value *OldValue,
                                                      Value *NewValue) {
+  // If OldValue is used as the address part of a dbg.assign intrinsic replace
+  // it with NewValue and return true.
+  auto ReplaceDbgAssignAddress = [this, OldValue, NewValue]() -> bool {
+    auto *DAI = dyn_cast<DbgAssignIntrinsic>(this);
+    if (!DAI || OldValue != DAI->getAddress())
+      return false;
+    DAI->setAddress(NewValue);
+    return true;
+  };
+  bool DbgAssignAddrReplaced = ReplaceDbgAssignAddress();
+  (void)DbgAssignAddrReplaced;
+
   assert(NewValue && "Values must be non-null");
   auto Locations = location_ops();
   auto OldIt = find(Locations, OldValue);
-  assert(OldIt != Locations.end() && "OldValue must be a current location");
+  assert((OldIt != Locations.end() || DbgAssignAddrReplaced) &&
+         "OldValue must be a current location");
   if (!hasArgList()) {
     Value *NewOperand = isa<MetadataAsValue>(NewValue)
                             ? NewValue
@@ -172,6 +185,32 @@ Optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const {
   return getVariable()->getSizeInBits();
 }
 
+Value *DbgAssignIntrinsic::getAddress() const {
+  auto *MD = getRawAddress();
+  if (auto *V = dyn_cast<ValueAsMetadata>(MD))
+    return V->getValue();
+
+  // When the value goes to null, it gets replaced by an empty MDNode.
+  assert(!cast<MDNode>(MD)->getNumOperands() && "Expected an empty MDNode");
+  return nullptr;
+}
+
+void DbgAssignIntrinsic::setAssignId(DIAssignID *New) {
+  setOperand(OpAssignID, MetadataAsValue::get(getContext(), New));
+}
+
+void DbgAssignIntrinsic::setAddress(Value *V) {
+  assert(V->getType()->isPointerTy() &&
+         "Destination Component must be a pointer type");
+  setOperand(OpAddress,
+             MetadataAsValue::get(getContext(), ValueAsMetadata::get(V)));
+}
+
+void DbgAssignIntrinsic::setValue(Value *V) {
+  setOperand(OpValue,
+             MetadataAsValue::get(getContext(), ValueAsMetadata::get(V)));
+}
+
 int llvm::Intrinsic::lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable,
                                                StringRef Name) {
   assert(Name.startswith("llvm."));

diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index f0097da60c9af..324fa66fb2ea9 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -4541,6 +4541,15 @@ void Verifier::visitDIAssignIDMetadata(Instruction &I, MDNode *MD) {
       isa<AllocaInst>(I) || isa<StoreInst>(I) || isa<MemIntrinsic>(I);
   CheckDI(ExpectedInstTy, "!DIAssignID attached to unexpected instruction kind",
           I, MD);
+  // Iterate over the MetadataAsValue uses of the DIAssignID - these should
+  // only be found as DbgAssignIntrinsic operands.
+  if (auto *AsValue = MetadataAsValue::getIfExists(Context, MD)) {
+    for (auto *User : AsValue->users()) {
+      CheckDI(isa<DbgAssignIntrinsic>(User),
+              "!DIAssignID should only be used by llvm.dbg.assign intrinsics",
+              MD, User);
+    }
+  }
 }
 
 void Verifier::visitCallStackMetadata(MDNode *MD) {
@@ -5023,6 +5032,9 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
   case Intrinsic::dbg_value: // llvm.dbg.value
     visitDbgIntrinsic("value", cast<DbgVariableIntrinsic>(Call));
     break;
+  case Intrinsic::dbg_assign: // llvm.dbg.assign
+    visitDbgIntrinsic("assign", cast<DbgVariableIntrinsic>(Call));
+    break;
   case Intrinsic::dbg_label: // llvm.dbg.label
     visitDbgLabelIntrinsic("label", cast<DbgLabelInst>(Call));
     break;
@@ -5986,6 +5998,18 @@ void Verifier::visitDbgIntrinsic(StringRef Kind, DbgVariableIntrinsic &DII) {
           "invalid llvm.dbg." + Kind + " intrinsic expression", &DII,
           DII.getRawExpression());
 
+  if (auto *DAI = dyn_cast<DbgAssignIntrinsic>(&DII)) {
+    CheckDI(isa<DIAssignID>(DAI->getRawAssignID()),
+            "invalid llvm.dbg.assign intrinsic DIAssignID", &DII,
+            DAI->getRawAssignID());
+    CheckDI(isa<ValueAsMetadata>(DAI->getRawAddress()),
+            "invalid llvm.dbg.assign intrinsic address)", &DII,
+            DAI->getRawAddress());
+    CheckDI(isa<DIExpression>(DAI->getRawAddressExpression()),
+            "invalid llvm.dbg.assign intrinsic address expression", &DII,
+            DAI->getRawAddressExpression());
+  }
+
   // Ignore broken !dbg attachments; they're checked elsewhere.
   if (MDNode *N = DII.getDebugLoc().getAsMDNode())
     if (!isa<DILocation>(N))

diff  --git a/llvm/test/DebugInfo/Generic/assignment-tracking/parse-and-verify/roundtrip.ll b/llvm/test/DebugInfo/Generic/assignment-tracking/parse-and-verify/roundtrip.ll
index 1ddb95b79b0f0..808636a1a0e58 100644
--- a/llvm/test/DebugInfo/Generic/assignment-tracking/parse-and-verify/roundtrip.ll
+++ b/llvm/test/DebugInfo/Generic/assignment-tracking/parse-and-verify/roundtrip.ll
@@ -2,17 +2,81 @@
 ; RUN: | opt -verify -S -experimental-assignment-tracking \
 ; RUN: | FileCheck %s
 
-;; Roundtrip test (text -> bitcode -> text) for DIAssignID attachments.
-
-; CHECK: %local = alloca i32, align 4, !DIAssignID ![[ID:[0-9]+]]
-; CHECK-DAG: ![[ID]] = distinct !DIAssignID()
+;; Roundtrip test (text -> bitcode -> text) for DIAssignID metadata and
+;; llvm.dbg.assign intrinsics.
 
+;; DIAssignID attachment only.
+; CHECK-LABEL: @fun()
+; CHECK: %local = alloca i32, align 4, !DIAssignID ![[ID1:[0-9]+]]
 define dso_local void @fun() !dbg !7 {
 entry:
   %local = alloca i32, align 4, !DIAssignID !14
   ret void, !dbg !13
 }
 
+;; Unlinked llvm.dbg.assign.
+; CHECK-DAG: @fun2()
+; CHECK: llvm.dbg.assign(metadata i32 undef, metadata ![[VAR2:[0-9]+]], metadata !DIExpression(), metadata ![[ID2:[0-9]+]], metadata i32 undef, metadata !DIExpression()), !dbg ![[DBG2:[0-9]+]]
+define dso_local void @fun2() !dbg !15 {
+entry:
+  %local = alloca i32, align 4
+  call void @llvm.dbg.assign(metadata i32 undef, metadata !16, metadata !DIExpression(), metadata !18, metadata i32 undef, metadata !DIExpression()), !dbg !17
+  ret void, !dbg !17
+}
+
+;; An llvm.dbg.assign linked to an alloca.
+; CHECK-LABEL: @fun3()
+; CHECK: %local = alloca i32, align 4, !DIAssignID ![[ID3:[0-9]+]]
+; CHECK-NEXT: llvm.dbg.assign(metadata i32 undef, metadata ![[VAR3:[0-9]+]], metadata !DIExpression(), metadata ![[ID3]], metadata i32 undef, metadata !DIExpression()), !dbg ![[DBG3:[0-9]+]]
+define dso_local void @fun3() !dbg !19 {
+entry:
+  %local = alloca i32, align 4, !DIAssignID !22
+  call void @llvm.dbg.assign(metadata i32 undef, metadata !20, metadata !DIExpression(), metadata !22, metadata i32 undef, metadata !DIExpression()), !dbg !21
+  ret void, !dbg !21
+}
+
+;; Check that using a DIAssignID as an operand before using it as an attachment
+;; works (the order of the alloca and dbg.assign has been swapped).
+; CHECK-LABEL: @fun4()
+; CHECK: llvm.dbg.assign(metadata i32 undef, metadata ![[VAR4:[0-9]+]], metadata !DIExpression(), metadata ![[ID4:[0-9]+]], metadata i32 undef, metadata !DIExpression()), !dbg ![[DBG4:[0-9]+]]
+; CHECK-NEXT: %local = alloca i32, align 4, !DIAssignID ![[ID4]]
+define dso_local void @fun4() !dbg !23 {
+entry:
+  call void @llvm.dbg.assign(metadata i32 undef, metadata !24, metadata !DIExpression(), metadata !26, metadata i32 undef, metadata !DIExpression()), !dbg !25
+  %local = alloca i32, align 4, !DIAssignID !26
+  ret void, !dbg !25
+}
+
+;; Check that the value and address operands print correctly.
+;; There are currently no plans to support DIArgLists for the address component.
+; CHECK-LABEL: @fun5
+; CHECK: %local = alloca i32, align 4, !DIAssignID ![[ID5:[0-9]+]]
+; CHECK-NEXT: llvm.dbg.assign(metadata i32 %v, metadata ![[VAR5:[0-9]+]], metadata !DIExpression(), metadata ![[ID5]], metadata i32* %local, metadata !DIExpression()), !dbg ![[DBG5:[0-9]+]]
+; CHECK-NEXT: llvm.dbg.assign(metadata !DIArgList(i32 %v, i32 1), metadata ![[VAR5]], metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_minus, DW_OP_stack_value), metadata ![[ID5]], metadata i32* %local, metadata !DIExpression()), !dbg ![[DBG5]]
+define dso_local void @fun5(i32 %v) !dbg !27 {
+entry:
+  %local = alloca i32, align 4, !DIAssignID !30
+  call void @llvm.dbg.assign(metadata i32 %v, metadata !28, metadata !DIExpression(), metadata !30, metadata i32* %local, metadata !DIExpression()), !dbg !29
+  call void @llvm.dbg.assign(metadata !DIArgList(i32 %v, i32 1), metadata !28, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_minus, DW_OP_stack_value), metadata !30, metadata i32* %local, metadata !DIExpression()), !dbg !29
+  ret void
+}
+
+; CHECK-DAG: ![[ID1]] = distinct !DIAssignID()
+; CHECK-DAG: ![[ID2]] = distinct !DIAssignID()
+; CHECK-DAG: ![[VAR2]] = !DILocalVariable(name: "local2",
+; CHECK-DAG: ![[DBG2]] = !DILocation(line: 2
+; CHECK-DAG: ![[ID3]] = distinct !DIAssignID()
+; CHECK-DAG: ![[VAR3]] = !DILocalVariable(name: "local3",
+; CHECK-DAG: ![[DBG3]] = !DILocation(line: 3,
+; CHECK-DAG: ![[ID4]] = distinct !DIAssignID()
+; CHECK-DAG: ![[VAR4]] = !DILocalVariable(name: "local4",
+; CHECK-DAG: ![[DBG4]] = !DILocation(line: 4,
+; CHECK-DAG: ![[ID5]] = distinct !DIAssignID()
+; CHECK-DAG: ![[VAR5]] = !DILocalVariable(name: "local5",
+; CHECK-DAG: ![[DBG5]] = !DILocation(line: 5,
+
+declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata)
+
 !llvm.dbg.cu = !{!0}
 !llvm.module.flags = !{!3, !4, !5}
 !llvm.ident = !{!6}
@@ -29,5 +93,23 @@ entry:
 !9 = !{null}
 !10 = !DILocalVariable(name: "local", scope: !7, file: !1, line: 2, type: !11)
 !11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!13 = !DILocation(line: 3, column: 1, scope: !7)
+!13 = !DILocation(line: 1, column: 1, scope: !7)
 !14 = distinct !DIAssignID()
+!15 = distinct !DISubprogram(name: "fun2", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!16 = !DILocalVariable(name: "local2", scope: !15, file: !1, line: 2, type: !11)
+!17 = !DILocation(line: 2, column: 1, scope: !15)
+!18 = distinct !DIAssignID()
+!19 = distinct !DISubprogram(name: "fun3", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!20 = !DILocalVariable(name: "local3", scope: !19, file: !1, line: 2, type: !11)
+!21 = !DILocation(line: 3, column: 1, scope: !19)
+!22 = distinct !DIAssignID()
+!23 = distinct !DISubprogram(name: "fun4", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!24 = !DILocalVariable(name: "local4", scope: !23, file: !1, line: 2, type: !11)
+!25 = !DILocation(line: 4, column: 1, scope: !23)
+!26 = distinct !DIAssignID()
+!27 = distinct !DISubprogram(name: "fun5", scope: !1, file: !1, line: 1, type: !31, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!28 = !DILocalVariable(name: "local5", scope: !27, file: !1, line: 2, type: !11)
+!29 = !DILocation(line: 5, column: 1, scope: !27)
+!30 = distinct !DIAssignID()
+!31 = !DISubroutineType(types: !32)
+!32 = !{null, !11}

diff  --git a/llvm/test/DebugInfo/Generic/assignment-tracking/parse-and-verify/verify.ll b/llvm/test/DebugInfo/Generic/assignment-tracking/parse-and-verify/verify.ll
new file mode 100644
index 0000000000000..577289604d536
--- /dev/null
+++ b/llvm/test/DebugInfo/Generic/assignment-tracking/parse-and-verify/verify.ll
@@ -0,0 +1,52 @@
+; RUN: opt %s -S -verify -experimental-assignment-tracking 2>&1 \
+; RUN: | FileCheck %s
+
+;; Check that badly formed assignment tracking metadata is caught either
+;; while parsing or by the verifier.
+;;
+;; Checks for this one are inline.
+
+define dso_local void @fun() !dbg !7 {
+entry:
+  %a = alloca i32, align 4, !DIAssignID !14
+  ;; Here something other than a dbg.assign intrinsic is using a DIAssignID.
+  ; CHECK: !DIAssignID should only be used by llvm.dbg.assign intrinsics
+  call void @llvm.dbg.value(metadata !14, metadata !10, metadata !DIExpression()), !dbg !13
+
+  ;; Each following dbg.assign has an argument of the incorrect type.
+  ; CHECK: invalid llvm.dbg.assign intrinsic address/value
+  call void @llvm.dbg.assign(metadata !3, metadata !10, metadata !DIExpression(), metadata !14, metadata i32* undef, metadata !DIExpression()), !dbg !13
+  ; CHECK: invalid llvm.dbg.assign intrinsic variable
+  call void @llvm.dbg.assign(metadata i32 0, metadata !2, metadata !DIExpression(), metadata !14, metadata i32* undef, metadata !DIExpression()), !dbg !13
+  ; CHECK: invalid llvm.dbg.assign intrinsic expression
+  call void @llvm.dbg.assign(metadata !14, metadata !10, metadata !2, metadata !14, metadata i32* undef, metadata !DIExpression()), !dbg !13
+  ; CHECK: invalid llvm.dbg.assign intrinsic DIAssignID
+  call void @llvm.dbg.assign(metadata !14, metadata !10, metadata !DIExpression(), metadata !2, metadata i32* undef, metadata !DIExpression()), !dbg !13
+  ; CHECK: invalid llvm.dbg.assign intrinsic address
+  call void @llvm.dbg.assign(metadata !14, metadata !10, metadata !DIExpression(), metadata !14, metadata !3, metadata !DIExpression()), !dbg !13
+  ; CHECK: invalid llvm.dbg.assign intrinsic address expression
+  call void @llvm.dbg.assign(metadata !14, metadata !10, metadata !DIExpression(), metadata !14, metadata i32* undef, metadata !2), !dbg !13
+  ret void
+}
+
+declare void @llvm.dbg.value(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 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/")
+!2 = !{}
+!3 = !{i32 7, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang version 14.0.0"}
+!7 = distinct !DISubprogram(name: "fun", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!8 = !DISubroutineType(types: !9)
+!9 = !{null}
+!10 = !DILocalVariable(name: "local", scope: !7, file: !1, line: 2, type: !11)
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!13 = !DILocation(line: 1, column: 1, scope: !7)
+!14 = distinct !DIAssignID()


        


More information about the llvm-commits mailing list