From 360744eb7447800952b548bdf8048a8f13b77735 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Wed, 12 Nov 2025 16:33:20 -0800 Subject: [PATCH 1/6] [MLIR][LLVM] Debug info: support importing debug records directly --- .../include/mlir/Target/LLVMIR/ModuleImport.h | 28 ++- mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp | 10 +- mlir/lib/Target/LLVMIR/ModuleImport.cpp | 236 ++++++++++++++---- .../LLVMIR/Import/debug-info-records.ll | 94 +++++++ 4 files changed, 311 insertions(+), 57 deletions(-) create mode 100644 mlir/test/Target/LLVMIR/Import/debug-info-records.ll diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h index 09d819a05618b..78b18c54a5a2a 100644 --- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h @@ -163,9 +163,10 @@ class ModuleImport { /// Converts `value` to a float attribute. Asserts if the matching fails. FloatAttr matchFloatAttr(llvm::Value *value); - /// Converts `value` to a local variable attribute. Asserts if the matching - /// fails. - DILocalVariableAttr matchLocalVariableAttr(llvm::Value *value); + /// Converts `valOrVariable` to a local variable attribute. Asserts if the + /// matching fails. + DILocalVariableAttr matchLocalVariableAttr( + llvm::PointerUnion valOrVariable); /// Converts `value` to a label attribute. Asserts if the matching fails. DILabelAttr matchLabelAttr(llvm::Value *value); @@ -281,6 +282,10 @@ class ModuleImport { /// after the function conversion has finished. void addDebugIntrinsic(llvm::CallInst *intrinsic); + /// Adds a debug intrinsics to the list of intrinsics that should be converted + /// after the function conversion has finished. + void addDebugRecord(llvm::DbgRecord *dr); + /// Converts the LLVM values for an intrinsic to mixed MLIR values and /// attributes for LLVM_IntrOpBase. Attributes correspond to LLVM immargs. The /// list `immArgPositions` contains the positions of immargs on the LLVM @@ -339,9 +344,23 @@ class ModuleImport { /// Converts all debug intrinsics in `debugIntrinsics`. Assumes that the /// function containing the intrinsics has been fully converted to MLIR. LogicalResult processDebugIntrinsics(); + /// Converts all debug intrinsics in `debugIntrinsics`. Assumes that the + /// function containing the intrinsics has been fully converted to MLIR. + LogicalResult processDebugRecords(); /// Converts a single debug intrinsic. LogicalResult processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr, DominanceInfo &domInfo); + /// Converts a single debug intrinsic. + LogicalResult processDebugRecord(llvm::DbgRecord &dr, DominanceInfo &domInfo); + /// YYY + void processDebugVariableAndExpression( + Location loc, DILocalVariableAttr &localVarAttr, + DIExpressionAttr &localExprAttr, Value &locVal, bool hasArgList, + bool isKillLocation, + llvm::function_ref()> convertArgOperandToValue, + llvm::Value *llvmLocation, + llvm::PointerUnion llvmLocalVar, + llvm::DIExpression *expression, DominanceInfo &domInfo); /// Converts LLMV IR asm inline call operand's attributes into an array of /// MLIR attributes to be utilized in `llvm.inline_asm`. ArrayAttr convertAsmInlineOperandAttrs(const llvm::CallBase &llvmCall); @@ -485,6 +504,9 @@ class ModuleImport { /// Function-local list of debug intrinsics that need to be imported after the /// function conversion has finished. SetVector debugIntrinsics; + /// Function-local list of debug intrinsics that need to be imported after the + /// function conversion has finished. + SetVector debugRecords; /// Mapping between LLVM alias scope and domain metadata nodes and /// attributes in the LLVM dialect corresponding to these nodes. DenseMap aliasScopeMapping; diff --git a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp index 2dd0640f794e5..f8064b2d55205 100644 --- a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp +++ b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp @@ -30,6 +30,11 @@ void registerFromLLVMIRTranslation() { llvm::cl::desc("Emit expensive warnings during LLVM IR import " "(discouraged: testing only!)"), llvm::cl::init(false)); + static llvm::cl::opt disableNewDbgConversion( + "disable-newdbg-conversion", + llvm::cl::desc("Disable conversion from new debug info format during " + "LLVM IR import (discouraged: WIP!)"), + llvm::cl::init(false)); static llvm::cl::opt dropDICompositeTypeElements( "drop-di-composite-type-elements", llvm::cl::desc( @@ -69,8 +74,9 @@ void registerFromLLVMIRTranslation() { if (llvm::verifyModule(*llvmModule, &llvm::errs())) return nullptr; - // Debug records are not currently supported in the LLVM IR translator. - llvmModule->convertFromNewDbgValues(); + // Debug records are WIP in the LLVM IR translator. + if (!disableNewDbgConversion) + llvmModule->convertFromNewDbgValues(); return translateLLVMIRToModule( std::move(llvmModule), context, emitExpensiveWarnings, diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp index d9891e3168820..7ffb04e9608ab 100644 --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -34,12 +34,14 @@ #include "llvm/ADT/TypeSwitch.h" #include "llvm/IR/Comdat.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DebugProgramInstruction.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Operator.h" +#include "llvm/Support/LogicalResult.h" #include "llvm/Support/ModRef.h" #include @@ -522,6 +524,11 @@ void ModuleImport::addDebugIntrinsic(llvm::CallInst *intrinsic) { debugIntrinsics.insert(intrinsic); } +void ModuleImport::addDebugRecord(llvm::DbgRecord *dr) { + if (!debugRecords.contains(dr)) + debugRecords.insert(dr); +} + static Attribute convertCGProfileModuleFlagValue(ModuleOp mlirModule, llvm::MDTuple *mdTuple) { auto getLLVMFunction = @@ -2003,9 +2010,15 @@ FloatAttr ModuleImport::matchFloatAttr(llvm::Value *value) { return floatAttr; } -DILocalVariableAttr ModuleImport::matchLocalVariableAttr(llvm::Value *value) { - auto *nodeAsVal = cast(value); - auto *node = cast(nodeAsVal->getMetadata()); +DILocalVariableAttr ModuleImport::matchLocalVariableAttr( + llvm::PointerUnion valOrVariable) { + llvm::DILocalVariable *node = nullptr; + if (auto *value = dyn_cast(valOrVariable)) { + auto *nodeAsVal = cast(value); + node = cast(nodeAsVal->getMetadata()); + } else { + node = cast(valOrVariable); + } return debugImporter->translate(node); } @@ -2544,6 +2557,12 @@ LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) { if (auto *intrinsic = dyn_cast(inst)) return convertIntrinsic(intrinsic); + // Capture instruction with attached debug markers for later processing. + if (inst->DebugMarker) { + for (llvm::DbgRecord &dr : inst->DebugMarker->getDbgRecordRange()) + addDebugRecord(&dr); + } + // Convert all remaining LLVM instructions to MLIR operations. return convertInstruction(inst); } @@ -3007,76 +3026,50 @@ LogicalResult ModuleImport::processFunction(llvm::Function *func) { if (failed(processDebugIntrinsics())) return failure(); + // Process the debug r that require a delayed conversion after + // everything else was converted. + if (failed(processDebugRecords())) + return failure(); + return success(); } -/// Checks if `dbgIntr` is a kill location that holds metadata instead of an SSA -/// value. -static bool isMetadataKillLocation(llvm::DbgVariableIntrinsic *dbgIntr) { - if (!dbgIntr->isKillLocation()) +/// Checks if a kill location holds metadata instead of an SSA value. +static bool isMetadataKillLocation(bool isKillLocation, llvm::Value *value) { + if (!isKillLocation) return false; - llvm::Value *value = dbgIntr->getArgOperand(0); auto *nodeAsVal = dyn_cast(value); if (!nodeAsVal) return false; return !isa(nodeAsVal->getMetadata()); } -LogicalResult -ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr, - DominanceInfo &domInfo) { - Location loc = translateLoc(dbgIntr->getDebugLoc()); - auto emitUnsupportedWarning = [&]() { - if (emitExpensiveWarnings) - emitWarning(loc) << "dropped intrinsic: " << diag(*dbgIntr); - return success(); - }; - // Drop debug intrinsics with arg lists. - // TODO: Support debug intrinsics that have arg lists. - if (dbgIntr->hasArgList()) - return emitUnsupportedWarning(); - // Kill locations can have metadata nodes as location operand. This - // cannot be converted to poison as the type cannot be reconstructed. - // TODO: find a way to support this case. - if (isMetadataKillLocation(dbgIntr)) - return emitUnsupportedWarning(); - // Drop debug intrinsics if the associated variable information cannot be - // translated due to cyclic debug metadata. - // TODO: Support cyclic debug metadata. - DILocalVariableAttr localVariableAttr = - matchLocalVariableAttr(dbgIntr->getArgOperand(1)); - if (!localVariableAttr) - return emitUnsupportedWarning(); - FailureOr argOperand = convertMetadataValue(dbgIntr->getArgOperand(0)); - if (failed(argOperand)) - return emitError(loc) << "failed to convert a debug intrinsic operand: " - << diag(*dbgIntr); - - // Ensure that the debug intrinsic is inserted right after its operand is - // defined. Otherwise, the operand might not necessarily dominate the - // intrinsic. If the defining operation is a terminator, insert the intrinsic - // into a dominated block. - OpBuilder::InsertionGuard guard(builder); - if (Operation *op = argOperand->getDefiningOp(); +/// Ensure that the debug intrinsic is inserted right after its operand is +/// defined. Otherwise, the operand might not necessarily dominate the +/// intrinsic. If the defining operation is a terminator, insert the intrinsic +/// into a dominated block. +static LogicalResult setDebugIntrinsicBuilderInsertionPoint( + mlir::OpBuilder &builder, DominanceInfo &domInfo, Value argOperand) { + if (Operation *op = argOperand.getDefiningOp(); op && op->hasTrait()) { // Find a dominated block that can hold the debug intrinsic. auto dominatedBlocks = domInfo.getNode(op->getBlock())->children(); // If no block is dominated by the terminator, this intrinisc cannot be // converted. if (dominatedBlocks.empty()) - return emitUnsupportedWarning(); + return failure(); // Set insertion point before the terminator, to avoid inserting something // before landingpads. Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock(); builder.setInsertionPoint(dominatedBlock->getTerminator()); } else { - Value insertPt = *argOperand; - if (auto blockArg = dyn_cast(*argOperand)) { + Value insertPt = argOperand; + if (auto blockArg = dyn_cast(argOperand)) { // The value might be coming from a phi node and is now a block argument, // which means the insertion point is set to the start of the block. If // this block is a target destination of an invoke, the insertion point // must happen after the landing pad operation. - Block *insertionBlock = argOperand->getParentBlock(); + Block *insertionBlock = argOperand.getParentBlock(); if (!insertionBlock->empty() && isa(insertionBlock->front())) insertPt = cast(insertionBlock->front()).getRes(); @@ -3084,23 +3077,152 @@ ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr, builder.setInsertionPointAfterValue(insertPt); } - auto locationExprAttr = - debugImporter->translateExpression(dbgIntr->getExpression()); + return success(); +} + +void ModuleImport::processDebugVariableAndExpression( + Location loc, DILocalVariableAttr &localVarAttr, + DIExpressionAttr &localExprAttr, Value &locVal, bool hasArgList, + bool isKillLocation, + llvm::function_ref()> convertArgOperandToValue, + llvm::Value *llvmLocation, + llvm::PointerUnion llvmLocalVar, + llvm::DIExpression *expression, DominanceInfo &domInfo) { + // Drop debug intrinsics with arg lists. + // TODO: Support debug intrinsics that have arg lists. + if (hasArgList) + return; + // Kill locations can have metadata nodes as location operand. This + // cannot be converted to poison as the type cannot be reconstructed. + // TODO: find a way to support this case. + if (isMetadataKillLocation(isKillLocation, llvmLocation)) + return; + // Drop debug intrinsics if the associated variable information cannot be + // translated due to cyclic debug metadata. + // TODO: Support cyclic debug metadata. + localVarAttr = matchLocalVariableAttr(llvmLocalVar); + if (!localVarAttr) + return; + FailureOr argOperand = convertArgOperandToValue(); + if (failed(argOperand)) { + emitError(loc) << "failed to convert a debug operand: " + << diag(*llvmLocation); + return; + } + + if (setDebugIntrinsicBuilderInsertionPoint(builder, domInfo, *argOperand) + .failed()) + return; + + localExprAttr = debugImporter->translateExpression(expression); + locVal = *argOperand; +} + +LogicalResult +ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr, + DominanceInfo &domInfo) { + Location loc = translateLoc(dbgIntr->getDebugLoc()); + auto emitUnsupportedWarning = [&]() { + if (emitExpensiveWarnings) + emitWarning(loc) << "dropped intrinsic: " << diag(*dbgIntr); + return success(); + }; + + DILocalVariableAttr localVariableAttr; + DIExpressionAttr locationExprAttr; + Value locVal; + OpBuilder::InsertionGuard guard(builder); + auto convertArgOperandToValue = [&]() { + return convertMetadataValue(dbgIntr->getArgOperand(0)); + }; + + processDebugVariableAndExpression( + loc, localVariableAttr, locationExprAttr, locVal, dbgIntr->hasArgList(), + dbgIntr->isKillLocation(), convertArgOperandToValue, + dbgIntr->getArgOperand(0), dbgIntr->getArgOperand(1), + dbgIntr->getExpression(), domInfo); + + if (!localVariableAttr) + return emitUnsupportedWarning(); + + if (!locVal) // Expected if localVariableAttr is present. + return failure(); + Operation *op = llvm::TypeSwitch(dbgIntr) .Case([&](llvm::DbgDeclareInst *) { return LLVM::DbgDeclareOp::create( - builder, loc, *argOperand, localVariableAttr, locationExprAttr); + builder, loc, locVal, localVariableAttr, locationExprAttr); }) .Case([&](llvm::DbgValueInst *) { return LLVM::DbgValueOp::create( - builder, loc, *argOperand, localVariableAttr, locationExprAttr); + builder, loc, locVal, localVariableAttr, locationExprAttr); }); mapNoResultOp(dbgIntr, op); setNonDebugMetadataAttrs(dbgIntr, op); return success(); } +LogicalResult ModuleImport::processDebugRecord(llvm::DbgRecord &dr, + DominanceInfo &domInfo) { + Location loc = translateLoc(dr.getDebugLoc()); + auto emitUnsupportedWarning = [&]() { + if (!emitExpensiveWarnings) + return success(); + std::string options; + llvm::raw_string_ostream optionsStream(options); + dr.print(optionsStream); + emitWarning(loc) << "unhandled debug record " << optionsStream.str(); + return success(); + }; + + OpBuilder::InsertionGuard guard(builder); + if (auto *dbgVar = dyn_cast(&dr)) { + DILocalVariableAttr localVariableAttr; + DIExpressionAttr locationExprAttr; + Value locVal; + auto convertArgOperandToValue = [&]() -> FailureOr { + llvm::Value *value = dbgVar->getAddress(); + + // Return the mapped value if it has been converted before. + auto it = valueMapping.find(value); + if (it != valueMapping.end()) + return it->getSecond(); + + // Convert constants such as immediate values that have no mapping yet. + if (auto *constant = dyn_cast(value)) + return convertConstantExpr(constant); + return failure(); + }; + + processDebugVariableAndExpression( + loc, localVariableAttr, locationExprAttr, locVal, dbgVar->hasArgList(), + dbgVar->isKillLocation(), convertArgOperandToValue, + dbgVar->getAddress(), dbgVar->getVariable(), dbgVar->getExpression(), + domInfo); + + if (!localVariableAttr) + return emitUnsupportedWarning(); + + if (!locVal) // Expected if localVariableAttr is present. + return failure(); + + if (dbgVar->isDbgDeclare()) + LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr, + locationExprAttr); + else if (dbgVar->isDbgValue()) + LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr, + locationExprAttr); + else // isDbgAssign + return emitUnsupportedWarning(); + + // FIXME: Nothing to map given the source is an LLVM attribute? + return success(); + } + + return emitUnsupportedWarning(); +} + LogicalResult ModuleImport::processDebugIntrinsics() { DominanceInfo domInfo; for (llvm::Instruction *inst : debugIntrinsics) { @@ -3111,6 +3233,16 @@ LogicalResult ModuleImport::processDebugIntrinsics() { return success(); } +LogicalResult ModuleImport::processDebugRecords() { + DominanceInfo domInfo; + for (llvm::DbgRecord *dr : debugRecords) { + if (failed(processDebugRecord(*dr, domInfo))) + return failure(); + } + debugRecords.clear(); + return success(); +} + LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb, Block *block) { builder.setInsertionPointToStart(block); diff --git a/mlir/test/Target/LLVMIR/Import/debug-info-records.ll b/mlir/test/Target/LLVMIR/Import/debug-info-records.ll new file mode 100644 index 0000000000000..eb87c838b60e4 --- /dev/null +++ b/mlir/test/Target/LLVMIR/Import/debug-info-records.ll @@ -0,0 +1,94 @@ +; RUN: mlir-translate -import-llvm -mlir-print-debuginfo -disable-newdbg-conversion -emit-expensive-warnings -split-input-file %s 2>&1 | FileCheck %s +; RUN: mlir-translate -import-llvm -mlir-print-debuginfo -emit-expensive-warnings -split-input-file %s 2>&1 | FileCheck %s + +; CHECK: @callee() +define void @callee() { + ret void +} + +define void @func_with_empty_named_info() { + call void @callee() + ret void +} + +define void @func_no_debug() { + ret void +} + +; CHECK: llvm.func @func_with_debug(%[[ARG0:.*]]: i64 +define void @func_with_debug(i64 %0) !dbg !3 { + + ; CHECK: llvm.intr.dbg.value #di_local_variable = %[[ARG0]] : i64 + ; CHECK: llvm.intr.dbg.value #di_local_variable1 #llvm.di_expression<[DW_OP_LLVM_fragment(0, 1)]> = %[[ARG0]] : i64 + ; CHECK: %[[CST:.*]] = llvm.mlir.constant(1 : i32) : i32 + ; CHECK: %[[ADDR:.*]] = llvm.alloca %[[CST]] x i64 + ; CHECK: llvm.intr.dbg.declare #di_local_variable2 #llvm.di_expression<[DW_OP_deref, DW_OP_LLVM_convert(4, DW_ATE_signed)]> = %[[ADDR]] : !llvm.ptr + %2 = alloca i64, align 8, !dbg !19 + #dbg_value(i64 %0, !20, !DIExpression(DW_OP_LLVM_fragment, 0, 1), !22) + #dbg_declare(ptr %2, !23, !DIExpression(DW_OP_deref, DW_OP_LLVM_convert, 4, DW_ATE_signed), !25) + #dbg_value(i64 %0, !26, !DIExpression(), !27) + call void @func_no_debug(), !dbg !28 + call void @func_no_debug(), !dbg !28 + call void @func_no_debug(), !dbg !29 + call void @func_no_debug(), !dbg !30 + call void @func_no_debug(), !dbg !30 + call void @func_no_debug(), !dbg !31 + call void @func_no_debug(), !dbg !32 + %3 = add i64 %0, %0, !dbg !32 + ret void, !dbg !37 +} + +define void @empty_types() !dbg !38 { + ret void, !dbg !44 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2} + +!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "MLIR", isOptimized: true, runtimeVersion: 0, splitDebugFilename: "test.dwo", emissionKind: FullDebug, nameTableKind: None) +!1 = !DIFile(filename: "foo.mlir", directory: "/test/") +!2 = !{i32 2, !"Debug Info Version", i32 3} +!3 = distinct !DISubprogram(name: "func_with_debug", linkageName: "func_with_debug", scope: !4, file: !1, line: 3, type: !6, scopeLine: 3, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!4 = !DINamespace(name: "nested", scope: !5) +!5 = !DINamespace(name: "toplevel", scope: null, exportSymbols: true) +!6 = !DISubroutineType(cc: DW_CC_normal, types: !7) +!7 = !{null, !8, !9, !11, !12, !13, !16} +!8 = !DIBasicType(name: "si64") +!9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64, align: 32, offset: 8, extraData: !10) +!10 = !DIBasicType(name: "si32", size: 32, encoding: DW_ATE_signed) +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "named", baseType: !10) +!12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64, align: 32, offset: 8, dwarfAddressSpace: 3) +!13 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "composite", file: !1, line: 42, size: 64, align: 32, elements: !14) +!14 = !{!15} +!15 = !DISubrange(count: 4) +!16 = !DICompositeType(tag: DW_TAG_array_type, name: "array", file: !1, baseType: !8, flags: DIFlagVector, elements: !17) +!17 = !{!18} +!18 = !DISubrange(lowerBound: 0, upperBound: 4, stride: 1) +!19 = !DILocation(line: 100, column: 12, scope: !3) +!20 = !DILocalVariable(name: "arg", arg: 1, scope: !21, file: !1, line: 6, type: !8, align: 32) +!21 = distinct !DILexicalBlockFile(scope: !3, file: !1, discriminator: 0) +!22 = !DILocation(line: 103, column: 3, scope: !3) +!23 = !DILocalVariable(name: "alloc", scope: !24) +!24 = distinct !DILexicalBlock(scope: !3) +!25 = !DILocation(line: 106, column: 3, scope: !3) +!26 = !DILocalVariable(scope: !24) +!27 = !DILocation(line: 109, column: 3, scope: !3) +!28 = !DILocation(line: 1, column: 2, scope: !3) +!29 = !DILocation(line: 10, column: 10, scope: !3) +!30 = !DILocation(line: 5, column: 6, scope: !3) +!31 = !DILocation(line: 1, column: 1, scope: !3) +!32 = !DILocation(line: 2, column: 4, scope: !33, inlinedAt: !36) +!33 = distinct !DISubprogram(name: "callee", scope: !13, file: !1, type: !34, spFlags: DISPFlagDefinition, unit: !0) +!34 = !DISubroutineType(types: !35) +!35 = !{!8, !8} +!36 = !DILocation(line: 28, column: 5, scope: !3) +!37 = !DILocation(line: 135, column: 3, scope: !3) +!38 = distinct !DISubprogram(name: "empty_types", scope: !39, file: !1, type: !40, spFlags: DISPFlagDefinition, unit: !0, annotations: !42) +!39 = !DIModule(scope: !1, name: "module", configMacros: "bar", includePath: "/", apinotes: "/", file: !1, line: 42, isDecl: true) +!40 = !DISubroutineType(cc: DW_CC_normal, types: !41) +!41 = !{} +!42 = !{!43} +!43 = !{!"foo", !"bar"} +!44 = !DILocation(line: 140, column: 3, scope: !38) + +; ///// ----- From 4b26a799bd6969bd5af5385f30b3e5c2bc49eb72 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Wed, 12 Nov 2025 19:03:47 -0800 Subject: [PATCH 2/6] update a bunch --- .../include/mlir/Target/LLVMIR/ModuleImport.h | 22 ++++++++++--------- mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp | 13 ++++++----- mlir/lib/Target/LLVMIR/ModuleImport.cpp | 17 +++++++------- .../LLVMIR/Import/debug-info-records.ll | 2 +- 4 files changed, 29 insertions(+), 25 deletions(-) diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h index 78b18c54a5a2a..50cca5d9f48da 100644 --- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h @@ -282,8 +282,7 @@ class ModuleImport { /// after the function conversion has finished. void addDebugIntrinsic(llvm::CallInst *intrinsic); - /// Adds a debug intrinsics to the list of intrinsics that should be converted - /// after the function conversion has finished. + /// Similar to `addDebugIntrinsic`, but for debug records. void addDebugRecord(llvm::DbgRecord *dr); /// Converts the LLVM values for an intrinsic to mixed MLIR values and @@ -344,22 +343,25 @@ class ModuleImport { /// Converts all debug intrinsics in `debugIntrinsics`. Assumes that the /// function containing the intrinsics has been fully converted to MLIR. LogicalResult processDebugIntrinsics(); - /// Converts all debug intrinsics in `debugIntrinsics`. Assumes that the - /// function containing the intrinsics has been fully converted to MLIR. + /// Converts all debug records in `debugRecords`. Assumes that the + /// function containing the record has been fully converted to MLIR. LogicalResult processDebugRecords(); /// Converts a single debug intrinsic. LogicalResult processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr, DominanceInfo &domInfo); - /// Converts a single debug intrinsic. + /// Converts a single debug record. LogicalResult processDebugRecord(llvm::DbgRecord &dr, DominanceInfo &domInfo); - /// YYY - void processDebugVariableAndExpression( + /// Process arguments for declare/value operation insertion. `localVarAttr` + /// and `localExprAttr` are the attained attributes after importing the debug + /// variable and expressions. This also sets the builder insertion point to be + /// used by these operations. + void processDebugOpArgumentsAndInsertionPt( Location loc, DILocalVariableAttr &localVarAttr, DIExpressionAttr &localExprAttr, Value &locVal, bool hasArgList, bool isKillLocation, llvm::function_ref()> convertArgOperandToValue, - llvm::Value *llvmLocation, - llvm::PointerUnion llvmLocalVar, + llvm::Value *address, + llvm::PointerUnion variable, llvm::DIExpression *expression, DominanceInfo &domInfo); /// Converts LLMV IR asm inline call operand's attributes into an array of /// MLIR attributes to be utilized in `llvm.inline_asm`. @@ -504,7 +506,7 @@ class ModuleImport { /// Function-local list of debug intrinsics that need to be imported after the /// function conversion has finished. SetVector debugIntrinsics; - /// Function-local list of debug intrinsics that need to be imported after the + /// Function-local list of debug records that need to be imported after the /// function conversion has finished. SetVector debugRecords; /// Mapping between LLVM alias scope and domain metadata nodes and diff --git a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp index f8064b2d55205..c22d029fcf878 100644 --- a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp +++ b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp @@ -30,10 +30,13 @@ void registerFromLLVMIRTranslation() { llvm::cl::desc("Emit expensive warnings during LLVM IR import " "(discouraged: testing only!)"), llvm::cl::init(false)); - static llvm::cl::opt disableNewDbgConversion( - "disable-newdbg-conversion", - llvm::cl::desc("Disable conversion from new debug info format during " - "LLVM IR import (discouraged: WIP!)"), + static llvm::cl::opt convertDebugRecToIntrinsics( + "convert-debug-rec-to-intrinsics", + llvm::cl::desc("Change the input LLVM module to use old debug intrinsics " + "instead of records " + "via convertFromNewDbgValues, this happens " + "before importing the debug information" + "(discouraged: to be removed soon!)"), llvm::cl::init(false)); static llvm::cl::opt dropDICompositeTypeElements( "drop-di-composite-type-elements", @@ -75,7 +78,7 @@ void registerFromLLVMIRTranslation() { return nullptr; // Debug records are WIP in the LLVM IR translator. - if (!disableNewDbgConversion) + if (!convertDebugRecToIntrinsics) llvmModule->convertFromNewDbgValues(); return translateLLVMIRToModule( diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp index 7ffb04e9608ab..5503dec2887ac 100644 --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -3080,13 +3080,13 @@ static LogicalResult setDebugIntrinsicBuilderInsertionPoint( return success(); } -void ModuleImport::processDebugVariableAndExpression( +void ModuleImport::processDebugOpArgumentsAndInsertionPt( Location loc, DILocalVariableAttr &localVarAttr, DIExpressionAttr &localExprAttr, Value &locVal, bool hasArgList, bool isKillLocation, llvm::function_ref()> convertArgOperandToValue, - llvm::Value *llvmLocation, - llvm::PointerUnion llvmLocalVar, + llvm::Value *address, + llvm::PointerUnion variable, llvm::DIExpression *expression, DominanceInfo &domInfo) { // Drop debug intrinsics with arg lists. // TODO: Support debug intrinsics that have arg lists. @@ -3095,18 +3095,17 @@ void ModuleImport::processDebugVariableAndExpression( // Kill locations can have metadata nodes as location operand. This // cannot be converted to poison as the type cannot be reconstructed. // TODO: find a way to support this case. - if (isMetadataKillLocation(isKillLocation, llvmLocation)) + if (isMetadataKillLocation(isKillLocation, address)) return; // Drop debug intrinsics if the associated variable information cannot be // translated due to cyclic debug metadata. // TODO: Support cyclic debug metadata. - localVarAttr = matchLocalVariableAttr(llvmLocalVar); + localVarAttr = matchLocalVariableAttr(variable); if (!localVarAttr) return; FailureOr argOperand = convertArgOperandToValue(); if (failed(argOperand)) { - emitError(loc) << "failed to convert a debug operand: " - << diag(*llvmLocation); + emitError(loc) << "failed to convert a debug operand: " << diag(*address); return; } @@ -3136,7 +3135,7 @@ ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr, return convertMetadataValue(dbgIntr->getArgOperand(0)); }; - processDebugVariableAndExpression( + processDebugOpArgumentsAndInsertionPt( loc, localVariableAttr, locationExprAttr, locVal, dbgIntr->hasArgList(), dbgIntr->isKillLocation(), convertArgOperandToValue, dbgIntr->getArgOperand(0), dbgIntr->getArgOperand(1), @@ -3195,7 +3194,7 @@ LogicalResult ModuleImport::processDebugRecord(llvm::DbgRecord &dr, return failure(); }; - processDebugVariableAndExpression( + processDebugOpArgumentsAndInsertionPt( loc, localVariableAttr, locationExprAttr, locVal, dbgVar->hasArgList(), dbgVar->isKillLocation(), convertArgOperandToValue, dbgVar->getAddress(), dbgVar->getVariable(), dbgVar->getExpression(), diff --git a/mlir/test/Target/LLVMIR/Import/debug-info-records.ll b/mlir/test/Target/LLVMIR/Import/debug-info-records.ll index eb87c838b60e4..142356dc0a1e2 100644 --- a/mlir/test/Target/LLVMIR/Import/debug-info-records.ll +++ b/mlir/test/Target/LLVMIR/Import/debug-info-records.ll @@ -1,4 +1,4 @@ -; RUN: mlir-translate -import-llvm -mlir-print-debuginfo -disable-newdbg-conversion -emit-expensive-warnings -split-input-file %s 2>&1 | FileCheck %s +; RUN: mlir-translate -import-llvm -mlir-print-debuginfo -convert-debug-rec-to-intrinsics -emit-expensive-warnings -split-input-file %s 2>&1 | FileCheck %s ; RUN: mlir-translate -import-llvm -mlir-print-debuginfo -emit-expensive-warnings -split-input-file %s 2>&1 | FileCheck %s ; CHECK: @callee() From a57ebdb48cf36af580e379f48befa47956fdc52b Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Wed, 12 Nov 2025 19:07:15 -0800 Subject: [PATCH 3/6] fix comment --- mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp index c22d029fcf878..ba80f6294bd9b 100644 --- a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp +++ b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp @@ -77,7 +77,8 @@ void registerFromLLVMIRTranslation() { if (llvm::verifyModule(*llvmModule, &llvm::errs())) return nullptr; - // Debug records are WIP in the LLVM IR translator. + // Now that the translation supports importing debug records directly, + // make it the default, but allow the user to override to old behavior. if (!convertDebugRecToIntrinsics) llvmModule->convertFromNewDbgValues(); From 1c7df13de2b63aeda075ece935ee25ed5a4b6f33 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Wed, 12 Nov 2025 19:10:34 -0800 Subject: [PATCH 4/6] Remove extra empty input --- mlir/test/Target/LLVMIR/Import/debug-info-records.ll | 2 -- 1 file changed, 2 deletions(-) diff --git a/mlir/test/Target/LLVMIR/Import/debug-info-records.ll b/mlir/test/Target/LLVMIR/Import/debug-info-records.ll index 142356dc0a1e2..a7a33397cdf37 100644 --- a/mlir/test/Target/LLVMIR/Import/debug-info-records.ll +++ b/mlir/test/Target/LLVMIR/Import/debug-info-records.ll @@ -90,5 +90,3 @@ define void @empty_types() !dbg !38 { !42 = !{!43} !43 = !{!"foo", !"bar"} !44 = !DILocation(line: 140, column: 3, scope: !38) - -; ///// ----- From 860a3b5861594195f2f935693419b982b8a4ac2a Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Thu, 13 Nov 2025 14:10:31 -0800 Subject: [PATCH 5/6] Address feedback --- .../include/mlir/Target/LLVMIR/ModuleImport.h | 12 +- mlir/lib/Target/LLVMIR/ModuleImport.cpp | 157 +++++++++--------- .../LLVMIR/Import/debug-info-records.ll | 15 +- 3 files changed, 83 insertions(+), 101 deletions(-) diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h index 50cca5d9f48da..a4a7df985b681 100644 --- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h @@ -283,7 +283,7 @@ class ModuleImport { void addDebugIntrinsic(llvm::CallInst *intrinsic); /// Similar to `addDebugIntrinsic`, but for debug records. - void addDebugRecord(llvm::DbgRecord *dr); + void addDebugRecord(llvm::DbgRecord *debugRecord); /// Converts the LLVM values for an intrinsic to mixed MLIR values and /// attributes for LLVM_IntrOpBase. Attributes correspond to LLVM immargs. The @@ -350,15 +350,15 @@ class ModuleImport { LogicalResult processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr, DominanceInfo &domInfo); /// Converts a single debug record. - LogicalResult processDebugRecord(llvm::DbgRecord &dr, DominanceInfo &domInfo); + LogicalResult processDebugRecord(llvm::DbgRecord &debugRecord, + DominanceInfo &domInfo); /// Process arguments for declare/value operation insertion. `localVarAttr` /// and `localExprAttr` are the attained attributes after importing the debug /// variable and expressions. This also sets the builder insertion point to be /// used by these operations. - void processDebugOpArgumentsAndInsertionPt( - Location loc, DILocalVariableAttr &localVarAttr, - DIExpressionAttr &localExprAttr, Value &locVal, bool hasArgList, - bool isKillLocation, + std::tuple + processDebugOpArgumentsAndInsertionPt( + Location loc, bool hasArgList, bool isKillLocation, llvm::function_ref()> convertArgOperandToValue, llvm::Value *address, llvm::PointerUnion variable, diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp index 5503dec2887ac..b8106101692b8 100644 --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -524,9 +524,9 @@ void ModuleImport::addDebugIntrinsic(llvm::CallInst *intrinsic) { debugIntrinsics.insert(intrinsic); } -void ModuleImport::addDebugRecord(llvm::DbgRecord *dr) { - if (!debugRecords.contains(dr)) - debugRecords.insert(dr); +void ModuleImport::addDebugRecord(llvm::DbgRecord *debugRecord) { + if (!debugRecords.contains(debugRecord)) + debugRecords.insert(debugRecord); } static Attribute convertCGProfileModuleFlagValue(ModuleOp mlirModule, @@ -2558,10 +2558,9 @@ LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) { return convertIntrinsic(intrinsic); // Capture instruction with attached debug markers for later processing. - if (inst->DebugMarker) { - for (llvm::DbgRecord &dr : inst->DebugMarker->getDbgRecordRange()) - addDebugRecord(&dr); - } + if (inst->DebugMarker) + for (llvm::DbgRecord &debugRecord : inst->DebugMarker->getDbgRecordRange()) + addDebugRecord(&debugRecord); // Convert all remaining LLVM instructions to MLIR operations. return convertInstruction(inst); @@ -3026,7 +3025,7 @@ LogicalResult ModuleImport::processFunction(llvm::Function *func) { if (failed(processDebugIntrinsics())) return failure(); - // Process the debug r that require a delayed conversion after + // Process the debug records that require a delayed conversion after // everything else was converted. if (failed(processDebugRecords())) return failure(); @@ -3044,8 +3043,8 @@ static bool isMetadataKillLocation(bool isKillLocation, llvm::Value *value) { return !isa(nodeAsVal->getMetadata()); } -/// Ensure that the debug intrinsic is inserted right after its operand is -/// defined. Otherwise, the operand might not necessarily dominate the +/// Ensure that the debug intrinsic is inserted right after the operand +/// definition. Otherwise, the operand might not necessarily dominate the /// intrinsic. If the defining operation is a terminator, insert the intrinsic /// into a dominated block. static LogicalResult setDebugIntrinsicBuilderInsertionPoint( @@ -3080,10 +3079,9 @@ static LogicalResult setDebugIntrinsicBuilderInsertionPoint( return success(); } -void ModuleImport::processDebugOpArgumentsAndInsertionPt( - Location loc, DILocalVariableAttr &localVarAttr, - DIExpressionAttr &localExprAttr, Value &locVal, bool hasArgList, - bool isKillLocation, +std::tuple +ModuleImport::processDebugOpArgumentsAndInsertionPt( + Location loc, bool hasArgList, bool isKillLocation, llvm::function_ref()> convertArgOperandToValue, llvm::Value *address, llvm::PointerUnion variable, @@ -3091,30 +3089,30 @@ void ModuleImport::processDebugOpArgumentsAndInsertionPt( // Drop debug intrinsics with arg lists. // TODO: Support debug intrinsics that have arg lists. if (hasArgList) - return; + return {}; // Kill locations can have metadata nodes as location operand. This // cannot be converted to poison as the type cannot be reconstructed. // TODO: find a way to support this case. if (isMetadataKillLocation(isKillLocation, address)) - return; + return {}; // Drop debug intrinsics if the associated variable information cannot be // translated due to cyclic debug metadata. // TODO: Support cyclic debug metadata. - localVarAttr = matchLocalVariableAttr(variable); + DILocalVariableAttr localVarAttr = matchLocalVariableAttr(variable); if (!localVarAttr) - return; + return {}; FailureOr argOperand = convertArgOperandToValue(); if (failed(argOperand)) { emitError(loc) << "failed to convert a debug operand: " << diag(*address); - return; + return {}; } if (setDebugIntrinsicBuilderInsertionPoint(builder, domInfo, *argOperand) .failed()) - return; + return {}; - localExprAttr = debugImporter->translateExpression(expression); - locVal = *argOperand; + return {localVarAttr, debugImporter->translateExpression(expression), + *argOperand}; } LogicalResult @@ -3127,19 +3125,16 @@ ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr, return success(); }; - DILocalVariableAttr localVariableAttr; - DIExpressionAttr locationExprAttr; - Value locVal; OpBuilder::InsertionGuard guard(builder); auto convertArgOperandToValue = [&]() { return convertMetadataValue(dbgIntr->getArgOperand(0)); }; - processDebugOpArgumentsAndInsertionPt( - loc, localVariableAttr, locationExprAttr, locVal, dbgIntr->hasArgList(), - dbgIntr->isKillLocation(), convertArgOperandToValue, - dbgIntr->getArgOperand(0), dbgIntr->getArgOperand(1), - dbgIntr->getExpression(), domInfo); + auto [localVariableAttr, locationExprAttr, locVal] = + processDebugOpArgumentsAndInsertionPt( + loc, dbgIntr->hasArgList(), dbgIntr->isKillLocation(), + convertArgOperandToValue, dbgIntr->getArgOperand(0), + dbgIntr->getArgOperand(1), dbgIntr->getExpression(), domInfo); if (!localVariableAttr) return emitUnsupportedWarning(); @@ -3147,79 +3142,75 @@ ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr, if (!locVal) // Expected if localVariableAttr is present. return failure(); - Operation *op = - llvm::TypeSwitch(dbgIntr) - .Case([&](llvm::DbgDeclareInst *) { - return LLVM::DbgDeclareOp::create( - builder, loc, locVal, localVariableAttr, locationExprAttr); - }) - .Case([&](llvm::DbgValueInst *) { - return LLVM::DbgValueOp::create( - builder, loc, locVal, localVariableAttr, locationExprAttr); - }); + Operation *op = nullptr; + if (isa(dbgIntr)) + op = LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr, + locationExprAttr); + else if (isa(dbgIntr)) + op = LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr, + locationExprAttr); + else + return emitUnsupportedWarning(); + mapNoResultOp(dbgIntr, op); setNonDebugMetadataAttrs(dbgIntr, op); return success(); } -LogicalResult ModuleImport::processDebugRecord(llvm::DbgRecord &dr, +LogicalResult ModuleImport::processDebugRecord(llvm::DbgRecord &debugRecord, DominanceInfo &domInfo) { - Location loc = translateLoc(dr.getDebugLoc()); + Location loc = translateLoc(debugRecord.getDebugLoc()); auto emitUnsupportedWarning = [&]() { if (!emitExpensiveWarnings) return success(); std::string options; llvm::raw_string_ostream optionsStream(options); - dr.print(optionsStream); + debugRecord.print(optionsStream); emitWarning(loc) << "unhandled debug record " << optionsStream.str(); return success(); }; OpBuilder::InsertionGuard guard(builder); - if (auto *dbgVar = dyn_cast(&dr)) { - DILocalVariableAttr localVariableAttr; - DIExpressionAttr locationExprAttr; - Value locVal; - auto convertArgOperandToValue = [&]() -> FailureOr { - llvm::Value *value = dbgVar->getAddress(); - - // Return the mapped value if it has been converted before. - auto it = valueMapping.find(value); - if (it != valueMapping.end()) - return it->getSecond(); - - // Convert constants such as immediate values that have no mapping yet. - if (auto *constant = dyn_cast(value)) - return convertConstantExpr(constant); - return failure(); - }; + auto *dbgVar = dyn_cast(&debugRecord); + if (!dbgVar) + return emitUnsupportedWarning(); - processDebugOpArgumentsAndInsertionPt( - loc, localVariableAttr, locationExprAttr, locVal, dbgVar->hasArgList(), - dbgVar->isKillLocation(), convertArgOperandToValue, - dbgVar->getAddress(), dbgVar->getVariable(), dbgVar->getExpression(), - domInfo); + auto convertArgOperandToValue = [&]() -> FailureOr { + llvm::Value *value = dbgVar->getAddress(); - if (!localVariableAttr) - return emitUnsupportedWarning(); + // Return the mapped value if it has been converted before. + auto it = valueMapping.find(value); + if (it != valueMapping.end()) + return it->getSecond(); - if (!locVal) // Expected if localVariableAttr is present. - return failure(); + // Convert constants such as immediate values that have no mapping yet. + if (auto *constant = dyn_cast(value)) + return convertConstantExpr(constant); + return failure(); + }; - if (dbgVar->isDbgDeclare()) - LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr, - locationExprAttr); - else if (dbgVar->isDbgValue()) - LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr, - locationExprAttr); - else // isDbgAssign - return emitUnsupportedWarning(); + auto [localVariableAttr, locationExprAttr, locVal] = + processDebugOpArgumentsAndInsertionPt( + loc, dbgVar->hasArgList(), dbgVar->isKillLocation(), + convertArgOperandToValue, dbgVar->getAddress(), dbgVar->getVariable(), + dbgVar->getExpression(), domInfo); - // FIXME: Nothing to map given the source is an LLVM attribute? - return success(); - } + if (!localVariableAttr) + return emitUnsupportedWarning(); - return emitUnsupportedWarning(); + if (!locVal) // Expected if localVariableAttr is present. + return failure(); + + if (dbgVar->isDbgDeclare()) + LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr, + locationExprAttr); + else if (dbgVar->isDbgValue()) + LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr, + locationExprAttr); + else // isDbgAssign + return emitUnsupportedWarning(); + + return success(); } LogicalResult ModuleImport::processDebugIntrinsics() { @@ -3234,8 +3225,8 @@ LogicalResult ModuleImport::processDebugIntrinsics() { LogicalResult ModuleImport::processDebugRecords() { DominanceInfo domInfo; - for (llvm::DbgRecord *dr : debugRecords) { - if (failed(processDebugRecord(*dr, domInfo))) + for (llvm::DbgRecord *debugRecord : debugRecords) { + if (failed(processDebugRecord(*debugRecord, domInfo))) return failure(); } debugRecords.clear(); diff --git a/mlir/test/Target/LLVMIR/Import/debug-info-records.ll b/mlir/test/Target/LLVMIR/Import/debug-info-records.ll index a7a33397cdf37..a951b0bfb98a9 100644 --- a/mlir/test/Target/LLVMIR/Import/debug-info-records.ll +++ b/mlir/test/Target/LLVMIR/Import/debug-info-records.ll @@ -18,22 +18,16 @@ define void @func_no_debug() { ; CHECK: llvm.func @func_with_debug(%[[ARG0:.*]]: i64 define void @func_with_debug(i64 %0) !dbg !3 { - ; CHECK: llvm.intr.dbg.value #di_local_variable = %[[ARG0]] : i64 - ; CHECK: llvm.intr.dbg.value #di_local_variable1 #llvm.di_expression<[DW_OP_LLVM_fragment(0, 1)]> = %[[ARG0]] : i64 + ; CHECK: llvm.intr.dbg.value #di_local_variable{{.*}} = %[[ARG0]] : i64 + ; CHECK: llvm.intr.dbg.value #di_local_variable{{.*}} #llvm.di_expression<[DW_OP_LLVM_fragment(0, 1)]> = %[[ARG0]] : i64 ; CHECK: %[[CST:.*]] = llvm.mlir.constant(1 : i32) : i32 ; CHECK: %[[ADDR:.*]] = llvm.alloca %[[CST]] x i64 - ; CHECK: llvm.intr.dbg.declare #di_local_variable2 #llvm.di_expression<[DW_OP_deref, DW_OP_LLVM_convert(4, DW_ATE_signed)]> = %[[ADDR]] : !llvm.ptr + ; CHECK: llvm.intr.dbg.declare #di_local_variable{{.*}} #llvm.di_expression<[DW_OP_deref, DW_OP_LLVM_convert(4, DW_ATE_signed)]> = %[[ADDR]] : !llvm.ptr %2 = alloca i64, align 8, !dbg !19 #dbg_value(i64 %0, !20, !DIExpression(DW_OP_LLVM_fragment, 0, 1), !22) #dbg_declare(ptr %2, !23, !DIExpression(DW_OP_deref, DW_OP_LLVM_convert, 4, DW_ATE_signed), !25) #dbg_value(i64 %0, !26, !DIExpression(), !27) call void @func_no_debug(), !dbg !28 - call void @func_no_debug(), !dbg !28 - call void @func_no_debug(), !dbg !29 - call void @func_no_debug(), !dbg !30 - call void @func_no_debug(), !dbg !30 - call void @func_no_debug(), !dbg !31 - call void @func_no_debug(), !dbg !32 %3 = add i64 %0, %0, !dbg !32 ret void, !dbg !37 } @@ -74,9 +68,6 @@ define void @empty_types() !dbg !38 { !26 = !DILocalVariable(scope: !24) !27 = !DILocation(line: 109, column: 3, scope: !3) !28 = !DILocation(line: 1, column: 2, scope: !3) -!29 = !DILocation(line: 10, column: 10, scope: !3) -!30 = !DILocation(line: 5, column: 6, scope: !3) -!31 = !DILocation(line: 1, column: 1, scope: !3) !32 = !DILocation(line: 2, column: 4, scope: !33, inlinedAt: !36) !33 = distinct !DISubprogram(name: "callee", scope: !13, file: !1, type: !34, spFlags: DISPFlagDefinition, unit: !0) !34 = !DISubroutineType(types: !35) From b7878230d5847acd7cd9675e56f23f05af0e11b0 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Thu, 13 Nov 2025 14:22:55 -0800 Subject: [PATCH 6/6] match local_variable in check --- mlir/test/Target/LLVMIR/Import/debug-info-records.ll | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/mlir/test/Target/LLVMIR/Import/debug-info-records.ll b/mlir/test/Target/LLVMIR/Import/debug-info-records.ll index a951b0bfb98a9..077871e356774 100644 --- a/mlir/test/Target/LLVMIR/Import/debug-info-records.ll +++ b/mlir/test/Target/LLVMIR/Import/debug-info-records.ll @@ -1,6 +1,10 @@ ; RUN: mlir-translate -import-llvm -mlir-print-debuginfo -convert-debug-rec-to-intrinsics -emit-expensive-warnings -split-input-file %s 2>&1 | FileCheck %s ; RUN: mlir-translate -import-llvm -mlir-print-debuginfo -emit-expensive-warnings -split-input-file %s 2>&1 | FileCheck %s +; CHECK: #[[LOCAL_VAR0:.*]] = #llvm.di_local_variable +; CHECK: #[[LOCAL_VAR1:.*]] = #llvm.di_local_variable = %[[ARG0]] : i64 + ; CHECK: llvm.intr.dbg.value #[[LOCAL_VAR0]] = %[[ARG0]] : i64 + ; CHECK: llvm.intr.dbg.value #[[LOCAL_VAR1]] #llvm.di_expression<[DW_OP_LLVM_fragment(0, 1)]> = %[[ARG0]] : i64 ; CHECK: %[[CST:.*]] = llvm.mlir.constant(1 : i32) : i32 ; CHECK: %[[ADDR:.*]] = llvm.alloca %[[CST]] x i64 - ; CHECK: llvm.intr.dbg.declare #di_local_variable{{.*}} #llvm.di_expression<[DW_OP_deref, DW_OP_LLVM_convert(4, DW_ATE_signed)]> = %[[ADDR]] : !llvm.ptr + ; CHECK: llvm.intr.dbg.declare #[[LOCAL_VAR2]] #llvm.di_expression<[DW_OP_deref, DW_OP_LLVM_convert(4, DW_ATE_signed)]> = %[[ADDR]] : !llvm.ptr %2 = alloca i64, align 8, !dbg !19 #dbg_value(i64 %0, !20, !DIExpression(DW_OP_LLVM_fragment, 0, 1), !22) #dbg_declare(ptr %2, !23, !DIExpression(DW_OP_deref, DW_OP_LLVM_convert, 4, DW_ATE_signed), !25)