Skip to content

Commit

Permalink
[MLIR][DebugInfo] Set debug info format in MLIR->IR translation
Browse files Browse the repository at this point in the history
MLIR's LLVM dialect does not internally support debug records, only
converting to/from debug intrinsics. To smooth the transition from
intrinsics to records, there is a step prior to IR->MLIR translation that
switches the IR module to intrinsic-form; this patch adds the equivalent
conversion to record-form at MLIR->IR translation.
  • Loading branch information
SLTozer committed Jun 12, 2024
1 parent d6bbe2e commit 66adcc0
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 11 deletions.
10 changes: 10 additions & 0 deletions mlir/lib/Target/LLVMIR/ConvertToLLVMIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@
#include "mlir/Target/LLVMIR/Dialect/All.h"
#include "mlir/Target/LLVMIR/Export.h"
#include "mlir/Tools/mlir-translate/Translation.h"
#include "llvm/IR/DebugProgramInstruction.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"

extern llvm::cl::opt<bool> WriteNewDbgInfoFormat;

using namespace mlir;

namespace mlir {
Expand All @@ -31,6 +34,13 @@ void registerToLLVMIRTranslation() {
if (!llvmModule)
return failure();

// When printing LLVM IR, we should convert the module to the debug info
// format that LLVM expects us to print.
// See https://llvm.org/docs/RemoveDIsDebugInfo.html
llvm::ScopedDbgInfoFormatSetter FormatSetter(*llvmModule,
WriteNewDbgInfoFormat);
if (WriteNewDbgInfoFormat)
llvmModule->removeDebugIntrinsicDeclarations();
llvmModule->print(output, nullptr);
return success();
},
Expand Down
10 changes: 10 additions & 0 deletions mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ using namespace mlir;
using namespace mlir::LLVM;
using namespace mlir::LLVM::detail;

extern llvm::cl::opt<bool> UseNewDbgInfoFormat;

#include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"

namespace {
Expand Down Expand Up @@ -1801,6 +1803,9 @@ prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext,
StringRef name) {
m->getContext()->getOrLoadDialect<LLVM::LLVMDialect>();
auto llvmModule = std::make_unique<llvm::Module>(name, llvmContext);
// ModuleTranslation can currently only construct modules in the old debug
// info format, so set the flag accordingly.
llvmModule->setNewDbgInfoFormatFlag(false);
if (auto dataLayoutAttr =
m->getDiscardableAttr(LLVM::LLVMDialect::getDataLayoutAttrName())) {
llvmModule->setDataLayout(cast<StringAttr>(dataLayoutAttr).getValue());
Expand Down Expand Up @@ -1879,6 +1884,11 @@ mlir::translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext,
if (failed(translator.convertFunctions()))
return nullptr;

// Once we've finished constructing elements in the module, we should convert
// it to use the debug info format desired by LLVM.
// See https://llvm.org/docs/RemoveDIsDebugInfo.html
translator.llvmModule->setIsNewDbgInfoFormat(UseNewDbgInfoFormat);

if (!disableVerification &&
llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
return nullptr;
Expand Down
33 changes: 22 additions & 11 deletions mlir/test/Target/LLVMIR/llvmir-debug.mlir
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: mlir-translate -mlir-to-llvmir --split-input-file %s | FileCheck %s
// RUN: mlir-translate -mlir-to-llvmir --write-experimental-debuginfo=false --split-input-file %s | FileCheck %s --check-prefixes=CHECK,INTRINSICS
// RUN: mlir-translate -mlir-to-llvmir --write-experimental-debuginfo=true --split-input-file %s | FileCheck %s --check-prefixes=CHECK,RECORDS

// CHECK-LABEL: define void @func_with_empty_named_info()
// Check that translation doens't crash in the presence of an inlineble call
Expand Down Expand Up @@ -98,13 +99,16 @@ llvm.func @func_with_debug(%arg: i64) {
%allocCount = llvm.mlir.constant(1 : i32) : i32
%alloc = llvm.alloca %allocCount x i64 : (i32) -> !llvm.ptr

// CHECK: call void @llvm.dbg.value(metadata i64 %[[ARG]], metadata ![[VAR_LOC:[0-9]+]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 1))
// INTRINSICS: call void @llvm.dbg.value(metadata i64 %[[ARG]], metadata ![[VAR_LOC:[0-9]+]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 1))
// RECORDS: #dbg_value(i64 %[[ARG]], ![[VAR_LOC:[0-9]+]], !DIExpression(DW_OP_LLVM_fragment, 0, 1), !{{.*}})
llvm.intr.dbg.value #variable #llvm.di_expression<[DW_OP_LLVM_fragment(0, 1)]> = %arg : i64

// CHECK: call void @llvm.dbg.declare(metadata ptr %[[ALLOC]], metadata ![[ADDR_LOC:[0-9]+]], metadata !DIExpression(DW_OP_deref, DW_OP_LLVM_convert, 4, DW_ATE_signed))
// INTRINSICS: call void @llvm.dbg.declare(metadata ptr %[[ALLOC]], metadata ![[ADDR_LOC:[0-9]+]], metadata !DIExpression(DW_OP_deref, DW_OP_LLVM_convert, 4, DW_ATE_signed))
// RECORDS: #dbg_declare(ptr %[[ALLOC]], ![[ADDR_LOC:[0-9]+]], !DIExpression(DW_OP_deref, DW_OP_LLVM_convert, 4, DW_ATE_signed), !{{.*}})
llvm.intr.dbg.declare #variableAddr #llvm.di_expression<[DW_OP_deref, DW_OP_LLVM_convert(4, DW_ATE_signed)]> = %alloc : !llvm.ptr

// CHECK: call void @llvm.dbg.value(metadata i64 %[[ARG]], metadata ![[NO_NAME_VAR:[0-9]+]], metadata !DIExpression())
// INTRINSICS: call void @llvm.dbg.value(metadata i64 %[[ARG]], metadata ![[NO_NAME_VAR:[0-9]+]], metadata !DIExpression())
// RECORDS: #dbg_value(i64 %[[ARG]], ![[NO_NAME_VAR:[0-9]+]], !DIExpression(), !{{.*}})
llvm.intr.dbg.value #noNameVariable = %arg : i64

// CHECK: call void @func_no_debug(), !dbg ![[FILE_LOC:[0-9]+]]
Expand Down Expand Up @@ -219,11 +223,14 @@ llvm.func @func_decl_with_subprogram() -> (i32) loc(fused<#di_subprogram>["foo.m
// CHECK-LABEL: define i32 @func_with_inlined_dbg_value(
// CHECK-SAME: i32 %[[ARG:.*]]) !dbg ![[OUTER_FUNC:[0-9]+]]
llvm.func @func_with_inlined_dbg_value(%arg0: i32) -> (i32) {
// CHECK: call void @llvm.dbg.value(metadata i32 %[[ARG]], metadata ![[VAR_LOC0:[0-9]+]], metadata !DIExpression()), !dbg ![[DBG_LOC0:.*]]
// INTRINSICS: call void @llvm.dbg.value(metadata i32 %[[ARG]], metadata ![[VAR_LOC0:[0-9]+]], metadata !DIExpression()), !dbg ![[DBG_LOC0:.*]]
// RECORDS: #dbg_value(i32 %[[ARG]], ![[VAR_LOC0:[0-9]+]], !DIExpression(), ![[DBG_LOC0:.*]])
llvm.intr.dbg.value #di_local_variable0 = %arg0 : i32 loc(fused<#di_subprogram>[#loc0])
// CHECK: call void @llvm.dbg.value(metadata i32 %[[ARG]], metadata ![[VAR_LOC1:[0-9]+]], metadata !DIExpression()), !dbg ![[DBG_LOC1:.*]]
// INTRINSICS: call void @llvm.dbg.value(metadata i32 %[[ARG]], metadata ![[VAR_LOC1:[0-9]+]], metadata !DIExpression()), !dbg ![[DBG_LOC1:.*]]
// RECORDS: #dbg_value(i32 %[[ARG]], ![[VAR_LOC1:[0-9]+]], !DIExpression(), ![[DBG_LOC1:.*]])
llvm.intr.dbg.value #di_local_variable1 = %arg0 : i32 loc(#loc1)
// CHECK: call void @llvm.dbg.label(metadata ![[LABEL:[0-9]+]]), !dbg ![[DBG_LOC1:.*]]
// INTRINSICS: call void @llvm.dbg.label(metadata ![[LABEL:[0-9]+]]), !dbg ![[DBG_LOC1:.*]]
// RECORDS: #dbg_label(![[LABEL:[0-9]+]], ![[DBG_LOC1:.*]])
llvm.intr.dbg.label #di_label loc(#loc1)
llvm.return %arg0 : i32
} loc(fused<#di_subprogram>["caller"])
Expand Down Expand Up @@ -254,7 +261,8 @@ llvm.func @func_with_inlined_dbg_value(%arg0: i32) -> (i32) {
// CHECK-LABEL: define void @func_without_subprogram(
// CHECK-SAME: i32 %[[ARG:.*]])
llvm.func @func_without_subprogram(%0 : i32) {
// CHECK: call void @llvm.dbg.value(metadata i32 %[[ARG]], metadata ![[VAR_LOC:[0-9]+]], metadata !DIExpression()), !dbg ![[DBG_LOC0:.*]]
// INTRINSICS: call void @llvm.dbg.value(metadata i32 %[[ARG]], metadata ![[VAR_LOC:[0-9]+]], metadata !DIExpression()), !dbg ![[DBG_LOC0:.*]]
// RECORDS: #dbg_value(i32 %[[ARG]], ![[VAR_LOC:[0-9]+]], !DIExpression(), ![[DBG_LOC0:.*]])
llvm.intr.dbg.value #di_local_variable = %0 : i32 loc(fused<#di_subprogram>[#loc])
llvm.return
}
Expand Down Expand Up @@ -285,11 +293,14 @@ llvm.func @func_without_subprogram(%0 : i32) {
llvm.func @dbg_intrinsics_with_no_location(%arg0: i32) -> (i32) {
%allocCount = llvm.mlir.constant(1 : i32) : i32
%alloc = llvm.alloca %allocCount x i64 : (i32) -> !llvm.ptr
// CHECK-NOT: @llvm.dbg.value
// INTRINSICS-NOT: @llvm.dbg.value
// RECORDS-NOT: #dbg_value
llvm.intr.dbg.value #di_local_variable = %arg0 : i32
// CHECK-NOT: @llvm.dbg.declare
// INTRINSICS-NOT: @llvm.dbg.declare
// RECORDS-NOT: #dbg_declare
llvm.intr.dbg.declare #declared_var = %alloc : !llvm.ptr
// CHECK-NOT: @llvm.dbg.label
// INTRINSICS-NOT: @llvm.dbg.label
// RECORDS-NOT: #dbg_label
llvm.intr.dbg.label #di_label
llvm.return %arg0 : i32
}
Expand Down
10 changes: 10 additions & 0 deletions mlir/test/lib/Dialect/Test/TestToLLVMIRTranslation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
#include "mlir/Tools/mlir-translate/Translation.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/IR/DebugProgramInstruction.h"

extern llvm::cl::opt<bool> WriteNewDbgInfoFormat;

using namespace mlir;

Expand Down Expand Up @@ -122,6 +125,13 @@ void registerTestToLLVMIR() {
if (!llvmModule)
return failure();

// When printing LLVM IR, we should convert the module to the debug info
// format that LLVM expects us to print.
// See https://llvm.org/docs/RemoveDIsDebugInfo.html
llvm::ScopedDbgInfoFormatSetter FormatSetter(*llvmModule,
WriteNewDbgInfoFormat);
if (WriteNewDbgInfoFormat)
llvmModule->removeDebugIntrinsicDeclarations();
llvmModule->print(output, nullptr);
return success();
},
Expand Down

0 comments on commit 66adcc0

Please sign in to comment.