[Mlir-commits] [mlir] [MLIR][LLVM] Add DILocAttr for debug locations (PR #186146)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Thu Mar 12 08:24:19 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-llvm

Author: Alexander Yermolovich (ayermolo)

<details>
<summary>Changes</summary>

Introduces DILocAttr, a new MLIR location attribute that pairs a FileLineColLoc with a DIScopeAttr to carry debug scope information directly on locations instead of encoding it as FusedLoc metadata. Replaces FusedLoc-with-metadata patterns across the LLVM dialect transforms.

---

Patch is 27.00 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/186146.diff


13 Files Affected:

- (modified) mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td (+27) 
- (modified) mlir/include/mlir/Dialect/LLVMIR/LLVMDialectBytecode.td (+10) 
- (modified) mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp (+2) 
- (modified) mlir/lib/Dialect/LLVMIR/Transforms/DIScopeForLLVMFuncOp.cpp (+37-36) 
- (modified) mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp (+6-7) 
- (modified) mlir/lib/Target/LLVMIR/DebugImporter.cpp (+22-15) 
- (modified) mlir/lib/Target/LLVMIR/DebugTranslation.cpp (+22-5) 
- (modified) mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp (+4) 
- (modified) mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp (+18-2) 
- (modified) mlir/test/Dialect/LLVMIR/add-debuginfo-func-scope.mlir (+3-3) 
- (added) mlir/test/Dialect/LLVMIR/diloc-attr.mlir (+17) 
- (modified) mlir/test/Dialect/LLVMIR/invalid-call-location.mlir (+33) 
- (modified) mlir/test/Target/LLVMIR/Import/debug-info.ll (+14-14) 


``````````diff
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index 36acf244865eb..ccf7bef462786 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -642,6 +642,33 @@ def LLVM_DILexicalBlockFile : LLVM_Attr<"DILexicalBlockFile", "di_lexical_block_
   let genMnemonicAlias = 1;
 }
 
+//===----------------------------------------------------------------------===//
+// DILocAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_DILocAttr : LocationAttrDef<LLVM_Dialect, "DILoc"> {
+  let description = [{
+    Represents a debug location combining a source position and a debug info
+    scope. Replaces the convention-based FusedLoc encoding for instruction-level
+    and function-level debug locations.
+  }];
+  let mnemonic = "di_loc";
+
+  let parameters = (ins
+    "FileLineColLoc":$sourceLoc,
+    "DILocalScopeAttr":$scope
+  );
+  let assemblyFormat = "`<` $sourceLoc `in` $scope `>`";
+
+  let builders = [
+    AttrBuilderWithInferredContext<(ins
+      "FileLineColLoc":$sourceLoc, "DILocalScopeAttr":$scope
+    ), [{
+      return $_get(sourceLoc.getContext(), sourceLoc, scope);
+    }]>,
+  ];
+}
+
 //===----------------------------------------------------------------------===//
 // DILocalVariableAttr
 //===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialectBytecode.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialectBytecode.td
index 659c535c1b671..3da283778d1ff 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialectBytecode.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialectBytecode.td
@@ -275,6 +275,15 @@ def DILexicalBlockFileAttr : DialectAttribute<(attr
   VarInt:$discriminator
 )>;
 
+//===----------------------------------------------------------------------===//
+// DILocAttr
+//===----------------------------------------------------------------------===//
+
+def DILocAttr : DialectAttribute<(attr
+  Attr<"FileLineColLoc">:$sourceLoc,
+  Attr<"DILocalScopeAttr">:$scope
+)>;
+
 //===----------------------------------------------------------------------===//
 // DINamespaceAttr
 //===----------------------------------------------------------------------===//
@@ -338,6 +347,7 @@ def LLVMDialectAttributes : DialectAttributes<"LLVM"> {
     DILabelAttr,
     DILexicalBlockAttr,
     DILexicalBlockFileAttr,
+    DILocAttr,
     DILocalVariableAttr,
     DINamespaceAttr,
     DISubprogramAttr,
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index e5bafea345700..70709ea2f477c 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -1142,6 +1142,8 @@ static LogicalResult verifyCallOpDebugInfo(CallOp callOp, LLVMFuncOp callee) {
     return success();
 
   auto hasSubprogram = [](Operation *op) {
+    if (auto diLoc = op->getLoc()->findInstanceOf<LLVM::DILocAttr>())
+      return isa<LLVM::DISubprogramAttr>(diLoc.getScope());
     return op->getLoc()
                ->findInstanceOf<FusedLocWith<LLVM::DISubprogramAttr>>() !=
            nullptr;
diff --git a/mlir/lib/Dialect/LLVMIR/Transforms/DIScopeForLLVMFuncOp.cpp b/mlir/lib/Dialect/LLVMIR/Transforms/DIScopeForLLVMFuncOp.cpp
index 36b31ffc3970e..cb4cb7cab52a4 100644
--- a/mlir/lib/Dialect/LLVMIR/Transforms/DIScopeForLLVMFuncOp.cpp
+++ b/mlir/lib/Dialect/LLVMIR/Transforms/DIScopeForLLVMFuncOp.cpp
@@ -25,6 +25,8 @@ using namespace mlir;
 static FileLineColLoc extractFileLoc(Location loc) {
   if (auto fileLoc = dyn_cast<FileLineColLoc>(loc))
     return fileLoc;
+  if (auto diLoc = dyn_cast<LLVM::DILocAttr>(loc))
+    return diLoc.getSourceLoc();
   if (auto nameLoc = dyn_cast<NameLoc>(loc))
     return extractFileLoc(nameLoc.getChildLoc());
   if (auto opaqueLoc = dyn_cast<OpaqueLoc>(loc))
@@ -47,6 +49,9 @@ static void addScopeToFunction(LLVM::LLVMFuncOp llvmFunc,
                                LLVM::DICompileUnitAttr compileUnitAttr) {
 
   Location loc = llvmFunc.getLoc();
+  if (auto diLoc = loc->findInstanceOf<LLVM::DILocAttr>())
+    if (isa<LLVM::DISubprogramAttr>(diLoc.getScope()))
+      return;
   if (loc->findInstanceOf<FusedLocWith<LLVM::DISubprogramAttr>>())
     return;
 
@@ -87,26 +92,30 @@ static void addScopeToFunction(LLVM::LLVMFuncOp llvmFunc,
       fileAttr,
       /*line=*/line, /*scopeLine=*/line, subprogramFlags, subroutineTypeAttr,
       /*retainedNodes=*/{}, /*annotations=*/{});
-  llvmFunc->setLoc(FusedLoc::get(context, {loc}, subprogramAttr));
+  FileLineColLoc fileLoc = extractFileLoc(loc);
+  if (!fileLoc)
+    fileLoc = FileLineColLoc::get(context, "<unknown>", line, /*column=*/0);
+  llvmFunc->setLoc(LLVM::DILocAttr::get(fileLoc, subprogramAttr));
 }
 
-// Get a nested loc for inlined functions.
+// Build a DILocAttr for an inlined callee. Each recursion level creates a
+// DILexicalBlockFileAttr whose scope chains back through the caller scopes
+// to the enclosing subprogram. The scope nesting is carried by the
+// DILexicalBlockFileAttr hierarchy, not by nesting locations.
 static Location getNestedLoc(Operation *op, LLVM::DIScopeAttr scopeAttr,
                              Location calleeLoc) {
-  auto calleeFileName = extractFileLoc(calleeLoc).getFilename();
+  FileLineColLoc calleeFileLoc = extractFileLoc(calleeLoc);
   auto *context = op->getContext();
+  StringAttr calleeFileName = calleeFileLoc.getFilename();
   LLVM::DIFileAttr calleeFileAttr =
       LLVM::DIFileAttr::get(context, llvm::sys::path::filename(calleeFileName),
                             llvm::sys::path::parent_path(calleeFileName));
   auto lexicalBlockFileAttr = LLVM::DILexicalBlockFileAttr::get(
       context, scopeAttr, calleeFileAttr, /*discriminator=*/0);
-  Location loc = calleeLoc;
   // Recurse if the callee location is again a call site.
-  if (auto callSiteLoc = dyn_cast<CallSiteLoc>(calleeLoc)) {
-    auto nestedLoc = callSiteLoc.getCallee();
-    loc = getNestedLoc(op, lexicalBlockFileAttr, nestedLoc);
-  }
-  return FusedLoc::get(context, {loc}, lexicalBlockFileAttr);
+  if (auto callSiteLoc = dyn_cast<CallSiteLoc>(calleeLoc))
+    return getNestedLoc(op, lexicalBlockFileAttr, callSiteLoc.getCallee());
+  return LLVM::DILocAttr::get(calleeFileLoc, lexicalBlockFileAttr);
 }
 
 /// Adds DILexicalBlockFileAttr for operations with CallSiteLoc and operations
@@ -114,27 +123,27 @@ static Location getNestedLoc(Operation *op, LLVM::DIScopeAttr scopeAttr,
 static void setLexicalBlockFileAttr(Operation *op) {
   Location opLoc = op->getLoc();
 
-  if (auto callSiteLoc = dyn_cast<CallSiteLoc>(opLoc)) {
-    auto callerLoc = callSiteLoc.getCaller();
-    auto calleeLoc = callSiteLoc.getCallee();
-    LLVM::DIScopeAttr scopeAttr;
-    // We assemble the full inline stack so the parent of this loc must be a
-    // function
-    if (auto funcOp = op->getParentOfType<LLVM::LLVMFuncOp>()) {
-      if (auto funcOpLoc =
-              llvm::dyn_cast_if_present<FusedLoc>(funcOp.getLoc())) {
-        scopeAttr = cast<LLVM::DISubprogramAttr>(funcOpLoc.getMetadata());
-        op->setLoc(CallSiteLoc::get(getNestedLoc(op, scopeAttr, calleeLoc),
-                                    callerLoc));
-      }
-    }
-
+  auto funcOp = op->getParentOfType<LLVM::LLVMFuncOp>();
+  if (!funcOp)
     return;
+
+  // Extract the subprogram scope from the function's location.
+  LLVM::DISubprogramAttr scopeAttr;
+  if (auto diLoc = funcOp.getLoc()->findInstanceOf<LLVM::DILocAttr>()) {
+    scopeAttr = dyn_cast<LLVM::DISubprogramAttr>(diLoc.getScope());
+  } else if (auto funcOpLoc =
+                 llvm::dyn_cast_if_present<FusedLoc>(funcOp.getLoc())) {
+    scopeAttr = dyn_cast<LLVM::DISubprogramAttr>(funcOpLoc.getMetadata());
   }
+  if (!scopeAttr)
+    return;
 
-  auto funcOp = op->getParentOfType<LLVM::LLVMFuncOp>();
-  if (!funcOp)
+  if (auto callSiteLoc = dyn_cast<CallSiteLoc>(opLoc)) {
+    op->setLoc(CallSiteLoc::get(
+        getNestedLoc(op, scopeAttr, callSiteLoc.getCallee()),
+        callSiteLoc.getCaller()));
     return;
+  }
 
   FileLineColLoc opFileLoc = extractFileLoc(opLoc);
   if (!opFileLoc)
@@ -150,23 +159,15 @@ static void setLexicalBlockFileAttr(Operation *op) {
   // Handle cross-file operations: add DILexicalBlockFileAttr when the
   // operation's source file differs from its containing function.
   if (opFile != funcFile) {
-    auto funcOpLoc = llvm::dyn_cast_if_present<FusedLoc>(funcOp.getLoc());
-    if (!funcOpLoc)
-      return;
-    auto scopeAttr = dyn_cast<LLVM::DISubprogramAttr>(funcOpLoc.getMetadata());
-    if (!scopeAttr)
-      return;
-
     auto *context = op->getContext();
     LLVM::DIFileAttr opFileAttr =
         LLVM::DIFileAttr::get(context, llvm::sys::path::filename(opFile),
                               llvm::sys::path::parent_path(opFile));
 
-    LLVM::DILexicalBlockFileAttr lexicalBlockFileAttr =
+    auto lexicalBlockFileAttr =
         LLVM::DILexicalBlockFileAttr::get(context, scopeAttr, opFileAttr, 0);
 
-    Location newLoc = FusedLoc::get(context, {opLoc}, lexicalBlockFileAttr);
-    op->setLoc(newLoc);
+    op->setLoc(LLVM::DILocAttr::get(opFileLoc, lexicalBlockFileAttr));
   }
 }
 
diff --git a/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp b/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp
index 680fafcc099f2..0b2dbc3a707f7 100644
--- a/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp
@@ -487,16 +487,15 @@ static void handleAccessGroups(Operation *call,
 static void
 handleLoopAnnotations(Operation *call,
                       iterator_range<Region::iterator> inlinedBlocks) {
-  // Attempt to extract a DISubprogram from the callee.
+  // Attempt to extract a DISubprogram from the caller.
   auto func = call->getParentOfType<FunctionOpInterface>();
   if (!func)
     return;
-  LocationAttr funcLoc = func->getLoc();
-  auto fusedLoc = dyn_cast_if_present<FusedLoc>(funcLoc);
-  if (!fusedLoc)
-    return;
-  auto scope =
-      dyn_cast_if_present<LLVM::DISubprogramAttr>(fusedLoc.getMetadata());
+  LLVM::DISubprogramAttr scope;
+  if (auto diLoc = func->getLoc()->findInstanceOf<LLVM::DILocAttr>())
+    scope = dyn_cast<LLVM::DISubprogramAttr>(diLoc.getScope());
+  else if (auto fusedLoc = dyn_cast_if_present<FusedLoc>(func->getLoc()))
+    scope = dyn_cast_if_present<LLVM::DISubprogramAttr>(fusedLoc.getMetadata());
   if (!scope)
     return;
 
diff --git a/mlir/lib/Target/LLVMIR/DebugImporter.cpp b/mlir/lib/Target/LLVMIR/DebugImporter.cpp
index 37140e3a949c7..2fe5f8a0a2b5b 100644
--- a/mlir/lib/Target/LLVMIR/DebugImporter.cpp
+++ b/mlir/lib/Target/LLVMIR/DebugImporter.cpp
@@ -33,11 +33,20 @@ Location DebugImporter::translateFuncLocation(llvm::Function *func) {
   if (!subprogram)
     return UnknownLoc::get(context);
 
-  // Add a fused location to link the subprogram information.
   StringAttr fileName = StringAttr::get(context, subprogram->getFilename());
-  return FusedLocWith<DISubprogramAttr>::get(
-      {FileLineColLoc::get(fileName, subprogram->getLine(), /*column=*/0)},
-      translate(subprogram), context);
+  auto fileLoc =
+      FileLineColLoc::get(fileName, subprogram->getLine(), /*column=*/0);
+  auto scope =
+      dyn_cast_or_null<DILocalScopeAttr>(translate(subprogram));
+  // DILocAttr requires a non-null DILocalScopeAttr, but
+  // translateImpl(DISubprogram*) can return null when the subprogram's parent
+  // scope or subroutine type cannot be translated. Preserve the file location
+  // so diagnostics still have source info. This also matches the original
+  // FusedLocWith<DISubprogramAttr> behavior, where a null metadata caused the
+  // location to fail FusedLocWith<DISubprogramAttr> classof checks anyway.
+  if (!scope)
+    return fileLoc;
+  return DILocAttr::get(fileLoc, scope);
 }
 
 //===----------------------------------------------------------------------===//
@@ -465,19 +474,17 @@ Location DebugImporter::translateLoc(llvm::DILocation *loc) {
   if (!loc)
     return UnknownLoc::get(context);
 
-  // Get the file location of the instruction.
-  Location result = FileLineColLoc::get(context, loc->getFilename(),
-                                        loc->getLine(), loc->getColumn());
-
-  // Add scope information.
-  assert(loc->getScope() && "expected non-null scope");
-  result = FusedLocWith<DIScopeAttr>::get({result}, translate(loc->getScope()),
-                                          context);
-
-  // Add call site information, if available.
+  auto fileLoc = FileLineColLoc::get(context, loc->getFilename(),
+                                    loc->getLine(), loc->getColumn());
+  auto scope =
+      dyn_cast_or_null<DILocalScopeAttr>(translate(loc->getScope()));
+  // DILocAttr requires a non-null DILocalScopeAttr. When the scope cannot
+  // be translated, preserve the file location for diagnostics.
+  Location result = scope
+      ? Location(DILocAttr::get(fileLoc, scope))
+      : Location(fileLoc);
   if (llvm::DILocation *inlinedAt = loc->getInlinedAt())
     result = CallSiteLoc::get(result, translateLoc(inlinedAt));
-
   return result;
 }
 
diff --git a/mlir/lib/Target/LLVMIR/DebugTranslation.cpp b/mlir/lib/Target/LLVMIR/DebugTranslation.cpp
index 08eee68c195db..52e322f2bf9e6 100644
--- a/mlir/lib/Target/LLVMIR/DebugTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/DebugTranslation.cpp
@@ -61,12 +61,18 @@ void DebugTranslation::translate(LLVMFuncOp func, llvm::Function &llvmFunc) {
   if (!debugEmissionIsEnabled)
     return;
 
-  // Look for a sub program attached to the function.
-  auto spLoc =
-      func.getLoc()->findInstanceOf<FusedLocWith<LLVM::DISubprogramAttr>>();
-  if (!spLoc)
+  // Look for a subprogram: check DILocAttr first, fall back to FusedLoc.
+  LLVM::DISubprogramAttr sp;
+  if (auto diLoc = func.getLoc()->findInstanceOf<LLVM::DILocAttr>()) {
+    sp = dyn_cast<LLVM::DISubprogramAttr>(diLoc.getScope());
+  } else if (auto spLoc =
+                 func.getLoc()
+                     ->findInstanceOf<FusedLocWith<LLVM::DISubprogramAttr>>()) {
+    sp = spLoc.getMetadata();
+  }
+  if (!sp)
     return;
-  llvmFunc.setSubprogram(translate(spLoc.getMetadata()));
+  llvmFunc.setSubprogram(translate(sp));
 }
 
 //===----------------------------------------------------------------------===//
@@ -543,6 +549,17 @@ llvm::DILocation *DebugTranslation::translateLoc(Location loc,
     if (!llvmLoc)
       llvmLoc = callerLoc;
 
+  } else if (auto diLoc = dyn_cast<LLVM::DILocAttr>(loc)) {
+    // Translate the scope from the DILocAttr.
+    llvm::DILocalScope *diScope = translate(diLoc.getScope());
+    if (!diScope)
+      return nullptr;
+
+    auto sourceLoc = diLoc.getSourceLoc();
+    llvmLoc = llvm::DILocation::get(
+        llvmCtx, sourceLoc.getLine(), sourceLoc.getColumn(), diScope,
+        const_cast<llvm::DILocation *>(inlinedAt));
+
   } else if (auto fileLoc = dyn_cast<FileLineColLoc>(loc)) {
     // A scope of a DILocation cannot be null.
     if (!scope)
diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index 21f7954fd338a..10d611dfee3a9 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -364,6 +364,10 @@ static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder,
 static llvm::DILocalScope *
 getLocalScopeFromLoc(llvm::IRBuilderBase &builder, Location loc,
                      LLVM::ModuleTranslation &moduleTranslation) {
+  if (auto diLoc = loc->findInstanceOf<LLVM::DILocAttr>())
+    if (auto *localScope = llvm::dyn_cast<llvm::DILocalScope>(
+            moduleTranslation.translateDebugInfo(diLoc.getScope())))
+      return localScope;
   if (auto scopeLoc =
           loc->findInstanceOf<FusedLocWith<LLVM::DILocalScopeAttr>>())
     if (auto *localScope = llvm::dyn_cast<llvm::DILocalScope>(
diff --git a/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp b/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp
index e4905423347a2..7546bb09d1348 100644
--- a/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp
+++ b/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp
@@ -410,10 +410,26 @@ LoopMetadataConversion::convertParallelAccesses() {
   return refs;
 }
 
+/// Convert a translated location to a FusedLoc for loop annotation storage.
+/// translateLoc produces DILocAttr, but LoopAnnotationAttr stores locations as
+/// FusedLoc<scope>[raw_loc]. Extract the source location and scope from the
+/// DILocAttr to build the FusedLoc directly, matching the format expected by
+/// LoopAnnotationTranslation on the export side.
+static FusedLoc toFusedLoc(Location loc) {
+  if (auto fused = dyn_cast<FusedLoc>(loc))
+    return fused;
+  if (isa<UnknownLoc>(loc))
+    return {};
+  if (auto diLoc = dyn_cast<LLVM::DILocAttr>(loc))
+    return dyn_cast<FusedLoc>(FusedLoc::get(
+        {diLoc.getSourceLoc()}, diLoc.getScope(), loc.getContext()));
+  return {};
+}
+
 FusedLoc LoopMetadataConversion::convertStartLoc() {
   if (locations.empty())
     return {};
-  return dyn_cast<FusedLoc>(
+  return toFusedLoc(
       loopAnnotationImporter.moduleImport.translateLoc(locations[0]));
 }
 
@@ -423,7 +439,7 @@ FailureOr<FusedLoc> LoopMetadataConversion::convertEndLoc() {
   if (locations.size() > 2)
     return emitError(loc)
            << "expected loop metadata to have at most two DILocations";
-  return dyn_cast<FusedLoc>(
+  return toFusedLoc(
       loopAnnotationImporter.moduleImport.translateLoc(locations[1]));
 }
 
diff --git a/mlir/test/Dialect/LLVMIR/add-debuginfo-func-scope.mlir b/mlir/test/Dialect/LLVMIR/add-debuginfo-func-scope.mlir
index 895c3fcb7fb23..30fc670846851 100644
--- a/mlir/test/Dialect/LLVMIR/add-debuginfo-func-scope.mlir
+++ b/mlir/test/Dialect/LLVMIR/add-debuginfo-func-scope.mlir
@@ -6,7 +6,7 @@
 // CHECK: loc(#loc[[LOC:[0-9]+]])
 // CHECK: #di_file = #llvm.di_file<"<unknown>" in "">
 // CHECK: #di_subprogram = #llvm.di_subprogram<id = distinct[{{.*}}]<>, compileUnit = #di_compile_unit, scope = #di_file, name = "func_no_debug", linkageName = "func_no_debug", file = #di_file, line = 1, scopeLine = 1, subprogramFlags = "Definition|Optimized", type = #di_subroutine_type>
-// CHECK: #loc[[LOC]] = loc(fused<#di_subprogram>
+// CHECK: #loc[[LOC]] = #llvm.di_loc<{{.*}} in #di_subprogram>
 module {
   llvm.func @func_no_debug() {
     llvm.return loc(unknown)
@@ -31,7 +31,7 @@ module {
 // CHECK: loc(#loc[[LOC:[0-9]+]])
 // CHECK: #di_file = #llvm.di_file<"<unknown>" in "">
 // CHECK: #di_subprogram = #llvm.di_subprogram<id = distinct[{{.*}}]<>, compileUnit = #di_compile_unit, scope = #di_file, name = "func_with_debug", linkageName = "func_with_debug", file = #di_file, line = 42, scopeLine = 42, subprogramFlags = "Definition|Optimized", type = #di_subroutine_type>
-// CHECK: #loc[[LOC]] = loc(fused<#di_subprogram>
+// CHECK: #loc[[LOC]] = loc(fused<#di_subprogram>[
 // CHECK_OTHER_KIND: emissionKind = DebugDirectivesOnly
 module {
   llvm.func @func_with_debug() {
@@ -59,7 +59,7 @@ module {
 // CHECK-DAG: #di_compile_unit = #llvm.di_compile_unit<id = distinct[{{.*}}]<>, sourceLanguage = DW_LANG_C, file = #[[DI_FILE_MODULE]], producer = "MLIR", isOptimized = true, emissionKind = LineTablesOnly>
 // CHECK-DAG: #di_subprogram = #llvm.di_subprogram<id = distinct[{{.*}}]<>, compileUnit = #di_compile_unit, scope = #[[DI_FILE_FUNC]], name = "propagate_compile_unit", linkageName = "propagate_compile_unit", file = #[[DI_FILE_FUNC]], line = 9, scopeLine = 9, subprogramFlags = "Definition|Optimized", type = #di_subroutine_type>
 // CHECK-DAG: #loc[[MODULELOC]] = loc(fused<#di_compile_unit>[#loc])
-// CHECK-DAG: #loc[[FUNCLOC]] = loc(fused<#di_subprogram>[#loc[[FUNCFILELOC]]
+// CHECK-DAG: #loc[[FUNCLOC]] = #llvm.di_loc<#loc[[FUNCFILELOC]] in #di_subprogram>
 module {
   llvm.func @propagate_compile_unit() {
     llvm.return loc(unknown)
diff --git a/mlir/test/Dialect/LLVMIR/diloc-attr.mlir b/mlir/test/Dialect/LLVMIR/diloc-attr.mlir
new file mode 100644
index 0000000000000..85abbb7783efb
--- /dev/null
+++ b/mlir/test/Dialect/LLVMIR/diloc-attr.mlir
@@ -0,0 +1,17 @@
+// RUN: mlir-opt %s --mlir-print-debuginfo | FileCheck %s
+//
+// Basic parse/print test for DILocAt...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/186146


More information about the Mlir-commits mailing list