[Mlir-commits] [mlir] 3bef1e0 - [mlir:LLVM] Add attribute/op definitions for debug info

River Riddle llvmlistbot at llvm.org
Mon Oct 24 00:00:15 PDT 2022


Author: River Riddle
Date: 2022-10-23T23:59:55-07:00
New Revision: 3bef1e0f4c1d7fd901b58abe0c5c0e67da764ba2

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

LOG: [mlir:LLVM] Add attribute/op definitions for debug info

This adds a subset of the necessary metadata for defining
debug info in the LLVM dialect. It doesn't import everything,
but just enough to start actually generating LLVM debug info
the expected way. Export/Import to LLVMIR will be added in a
followup.

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

Added: 
    mlir/test/Dialect/LLVMIR/debuginfo.mlir

Modified: 
    mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
    mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
    mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td
    mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
    mlir/lib/Dialect/LLVMIR/CMakeLists.txt
    mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
    mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index a4df5facd373e..b6b1f4c618ffd 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -12,10 +12,13 @@
 include "mlir/IR/AttrTypeBase.td"
 include "mlir/Dialect/LLVMIR/LLVMEnums.td"
 include "mlir/Dialect/LLVMIR/LLVMOpBase.td"
+include "mlir/IR/SubElementInterfaces.td"
 
 // All of the attributes will extend this class.
-class LLVM_Attr<string name, string attrMnemonic>
-    : AttrDef<LLVM_Dialect, name, /*traits=*/[]> {
+class LLVM_Attr<string name, string attrMnemonic,
+                list<Trait> traits = [],
+                string baseCppClass = "::mlir::Attribute">
+    : AttrDef<LLVM_Dialect, name, traits, baseCppClass> {
   let mnemonic = attrMnemonic;
 }
 
@@ -81,4 +84,280 @@ def LoopOptionsAttr : LLVM_Attr<"LoopOptions", "loopopts"> {
   let skipDefaultBuilders = 1;
 }
 
+//===----------------------------------------------------------------------===//
+// DebugInfo Attributes
+//===----------------------------------------------------------------------===//
+
+class LLVM_DIParameter<string summary, string underlyingType, string parseName,
+                       string printName = parseName>
+    : AttrOrTypeParameter<underlyingType, "debug info " # summary> {
+  let parser = [{ [&]() -> FailureOr<unsigned> {
+    SMLoc tagLoc = $_parser.getCurrentLocation(); 
+    StringRef name;
+    if ($_parser.parseKeyword(&name))
+      return failure();
+
+    if (unsigned tag = llvm::dwarf::get}] # parseName # [{(name))
+      return tag;
+    return $_parser.emitError(tagLoc)
+      << "invalid debug info }] # summary # [{ name: " << name;
+  }() }];
+  let printer = "$_printer << llvm::dwarf::" # printName # "String($_self)";
+}
+
+def LLVM_DICallingConventionParameter : LLVM_DIParameter<
+  "calling convention", "unsigned", "CallingConvention", "Convention" 
+>;
+
+def LLVM_DIEncodingParameter : LLVM_DIParameter<
+  "encoding", "unsigned", "AttributeEncoding"
+>;
+
+def LLVM_DILanguageParameter : LLVM_DIParameter<
+  "language", "unsigned", "Language"
+>;
+
+def LLVM_DITagParameter : LLVM_DIParameter<
+  "tag", "unsigned", "Tag"
+>;
+
+//===----------------------------------------------------------------------===//
+// DIBasicTypeAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_DIBasicTypeAttr : LLVM_Attr<"DIBasicType", "di_basic_type",
+                                     /*traits=*/[], "DITypeAttr"> {
+  let parameters = (ins
+    LLVM_DITagParameter:$tag,
+    "StringAttr":$name,
+    "uint64_t":$sizeInBits,
+    LLVM_DIEncodingParameter:$encoding
+  );
+
+  let builders = [
+    TypeBuilder<(ins
+      "unsigned":$tag, "const Twine &":$name, "uint64_t":$sizeInBits,
+      "unsigned":$encoding
+    ), [{
+      return $_get($_ctxt, tag, StringAttr::get($_ctxt, name), sizeInBits,
+                   encoding);
+    }]>
+  ];
+  let assemblyFormat = "`<` struct(params) `>`";
+}
+
+//===----------------------------------------------------------------------===//
+// DICompileUnitAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_DICompileUnitAttr : LLVM_Attr<"DICompileUnit", "di_compile_unit", [
+    DeclareAttrInterfaceMethods<SubElementAttrInterface>
+  ], "DIScopeAttr"> {
+  let parameters = (ins
+    LLVM_DILanguageParameter:$sourceLanguage,
+    "DIFileAttr":$file,
+    "StringAttr":$producer,
+    "bool":$isOptimized,
+    "DIEmissionKind":$emissionKind
+  );
+  let assemblyFormat = "`<` struct(params) `>`";
+}
+
+//===----------------------------------------------------------------------===//
+// DICompositeTypeAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_DICompositeTypeAttr : LLVM_Attr<"DICompositeType", "di_composite_type", [
+    DeclareAttrInterfaceMethods<SubElementAttrInterface>
+  ], "DITypeAttr"> {
+  let parameters = (ins
+    LLVM_DITagParameter:$tag,
+    "StringAttr":$name,
+    OptionalParameter<"DIFileAttr">:$file,
+    "uint32_t":$line,
+    OptionalParameter<"DIScopeAttr">:$scope,
+    "uint64_t":$sizeInBits,
+    "uint64_t":$alignInBits,
+    OptionalArrayRefParameter<"DINodeAttr">:$elements
+  );
+  let assemblyFormat = "`<` struct(params) `>`";
+}
+
+//===----------------------------------------------------------------------===//
+// DIDerivedTypeAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_DIDerivedTypeAttr : LLVM_Attr<"DIDerivedType", "di_derived_type", [
+    DeclareAttrInterfaceMethods<SubElementAttrInterface>
+  ], "DITypeAttr"> {
+  let parameters = (ins
+    LLVM_DITagParameter:$tag,
+    "StringAttr":$name,
+    "DITypeAttr":$baseType,
+    "uint64_t":$sizeInBits,
+    "uint32_t":$alignInBits,
+    "uint64_t":$offsetInBits
+  );
+  let assemblyFormat = "`<` struct(params) `>`";
+}
+
+//===----------------------------------------------------------------------===//
+// DIFileAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_DIFileAttr : LLVM_Attr<"DIFile", "di_file", /*traits=*/[], "DIScopeAttr"> {
+  let parameters = (ins "StringAttr":$name, "StringAttr":$directory);
+  let builders = [AttrBuilder<(ins "StringRef":$name, "StringRef":$directory), [{
+      return $_get($_ctxt, StringAttr::get($_ctxt, name),
+                   StringAttr::get($_ctxt, directory));
+    }]>
+  ];
+  let assemblyFormat = "`<` $name `in` $directory `>`";
+}
+
+//===----------------------------------------------------------------------===//
+// DILexicalBlockAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_DILexicalBlockAttr : LLVM_Attr<"DILexicalBlock", "di_lexical_block", [
+    DeclareAttrInterfaceMethods<SubElementAttrInterface>
+  ], "DIScopeAttr"> {
+  let parameters = (ins
+    "DIScopeAttr":$scope,
+    "DIFileAttr":$file,
+    "unsigned":$line,
+    "unsigned":$column
+  );
+  let builders = [
+    AttrBuilderWithInferredContext<(ins
+      "DIScopeAttr":$scope, "DIFileAttr":$file, "unsigned":$line,
+      "unsigned":$column
+    ), [{
+      return $_get(file.getContext(), scope, file, line, column);
+    }]>
+  ];
+  let assemblyFormat = "`<` struct(params) `>`";
+}
+
+//===----------------------------------------------------------------------===//
+// DILexicalBlockFileAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_DILexicalBlockFile : LLVM_Attr<"DILexicalBlockFile", "di_lexical_block_file", [
+    DeclareAttrInterfaceMethods<SubElementAttrInterface>
+  ], "DIScopeAttr"> {
+  let parameters = (ins
+    "DIScopeAttr":$scope,
+    "DIFileAttr":$file,
+    "unsigned":$descriminator
+  );
+  let builders = [
+    AttrBuilderWithInferredContext<(ins
+      "DIScopeAttr":$scope, "DIFileAttr":$file, "unsigned":$descriminator
+    ), [{
+      return $_get(file.getContext(), scope, file, descriminator);
+    }]>
+  ];
+  let assemblyFormat = "`<` struct(params) `>`";
+}
+
+//===----------------------------------------------------------------------===//
+// DILocalVariableAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_DILocalVariableAttr : LLVM_Attr<"DILocalVariable", "di_local_variable", [
+    DeclareAttrInterfaceMethods<SubElementAttrInterface>
+  ], "DINodeAttr"> {
+  let parameters = (ins
+    "DIScopeAttr":$scope,
+    "StringAttr":$name,
+    "DIFileAttr":$file,
+    "unsigned":$line,
+    "unsigned":$arg,
+    "unsigned":$alignInBits,
+    "DITypeAttr":$type
+  );
+  let builders = [
+    AttrBuilderWithInferredContext<(ins
+      "DIScopeAttr":$scope, "StringRef":$name, "DIFileAttr":$file,
+      "unsigned":$line, "unsigned":$arg, "unsigned":$alignInBits,
+      "DITypeAttr":$type
+    ), [{
+      MLIRContext *ctx = file.getContext();
+      return $_get(ctx, scope, StringAttr::get(ctx, name), file, line,
+                   arg, alignInBits, type);
+    }]>
+  ];
+  let assemblyFormat = "`<` struct(params) `>`";
+}
+
+//===----------------------------------------------------------------------===//
+// DISubprogramAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_DISubprogramAttr : LLVM_Attr<"DISubprogram", "di_subprogram", [
+    DeclareAttrInterfaceMethods<SubElementAttrInterface>
+  ], "DIScopeAttr"> {
+  let parameters = (ins
+    "DICompileUnitAttr":$compileUnit,
+    "DIScopeAttr":$scope,
+    "StringAttr":$name,
+    "StringAttr":$linkageName,
+    "DIFileAttr":$file,
+    "unsigned":$line,
+    "unsigned":$scopeLine,
+    "DISubprogramFlags":$subprogramFlags,
+    "DISubroutineTypeAttr":$type
+  );
+  let builders = [
+    AttrBuilderWithInferredContext<(ins
+      "DICompileUnitAttr":$compileUnit, "DIScopeAttr":$scope, "StringRef":$name,
+      "StringRef":$linkageName, "DIFileAttr":$file, "unsigned":$line, 
+      "unsigned":$scopeLine, "DISubprogramFlags":$subprogramFlags, 
+      "DISubroutineTypeAttr":$type
+    ), [{
+      MLIRContext *ctx = file.getContext();
+      return $_get(ctx, compileUnit, scope, StringAttr::get(ctx, name),
+                   StringAttr::get(ctx, linkageName), file, line,
+                   scopeLine, subprogramFlags, type);
+    }]>
+  ];
+
+  let assemblyFormat = "`<` struct(params) `>`";
+}
+
+//===----------------------------------------------------------------------===//
+// DISubrangeAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_DISubrangeAttr : LLVM_Attr<"DISubrange", "di_subrange", /*traits=*/[],
+                                    "DINodeAttr"> {
+  let parameters = (ins
+    "IntegerAttr":$count,
+    "IntegerAttr":$lowerBound,
+    "IntegerAttr":$upperBound,
+    "IntegerAttr":$stride
+  );
+  let assemblyFormat = "`<` struct(params) `>`";
+}
+
+//===----------------------------------------------------------------------===//
+// DISubroutineTypeAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_DISubroutineTypeAttr : LLVM_Attr<"DISubroutineType", "di_subroutine_type", [
+    DeclareAttrInterfaceMethods<SubElementAttrInterface>
+  ], "DITypeAttr"> {
+  let parameters = (ins
+    LLVM_DICallingConventionParameter:$callingConvention,
+    OptionalArrayRefParameter<"DITypeAttr">:$types
+  );
+  let builders = [
+    TypeBuilder<(ins "ArrayRef<DITypeAttr>":$types), [{
+      return $_get($_ctxt, /*callingConvention=*/0, types);
+    }]>
+  ];
+  let assemblyFormat = "`<` struct(params) `>`";
+}
+
 #endif // LLVMIR_ATTRDEFS

diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
index 09e2d43a1677b..025093565fb39 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
@@ -23,6 +23,33 @@ namespace mlir {
 namespace LLVM {
 class LoopOptionsAttrBuilder;
 
+/// This class represents the base attribute for all debug info attributes.
+class DINodeAttr : public Attribute {
+public:
+  using Attribute::Attribute;
+
+  // Support LLVM type casting.
+  static bool classof(Attribute attr);
+};
+
+/// This class represents a LLVM attribute that describes a debug info scope.
+class DIScopeAttr : public DINodeAttr {
+public:
+  using DINodeAttr::DINodeAttr;
+
+  /// Support LLVM type casting.
+  static bool classof(Attribute attr);
+};
+
+/// This class represents a LLVM attribute that describes a debug info type.
+class DITypeAttr : public DINodeAttr {
+public:
+  using DINodeAttr::DINodeAttr;
+
+  /// Support LLVM type casting.
+  static bool classof(Attribute attr);
+};
+
 // Inline the LLVM generated Linkage enum and utility.
 // This is only necessary to isolate the "enum generated code" from the
 // attribute definition itself.

diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td
index f22b03f4f0b41..cfcff876bee83 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td
@@ -204,6 +204,61 @@ def CConv : DialectAttr<
           "::mlir::LLVM::CConvAttr::get($_builder.getContext(), $0)";
 }
 
+//===----------------------------------------------------------------------===//
+// DIEmissionKind
+//===----------------------------------------------------------------------===//
+
+def LLVM_DIEmissionNone                : I64EnumAttrCase<"None", 0>;
+def LLVM_DIEmissionFull                : I64EnumAttrCase<"Full", 1>;
+def LLVM_DIEmissionLineTablesOnly      : I64EnumAttrCase<"LineTablesOnly", 2>;
+def LLVM_DIEmissionDebugDirectivesOnly : I64EnumAttrCase<"DebugDirectivesOnly", 3>;
+
+def LLVM_DIEmissionKind : I64EnumAttr<
+    "DIEmissionKind",
+    "LLVM debug emission kind", [
+      LLVM_DIEmissionNone,
+      LLVM_DIEmissionFull,
+      LLVM_DIEmissionLineTablesOnly,
+      LLVM_DIEmissionDebugDirectivesOnly,
+    ]> {
+  let cppNamespace = "::mlir::LLVM";
+}
+
+//===----------------------------------------------------------------------===//
+// DISubprogramFlags
+//===----------------------------------------------------------------------===//
+
+def LLVM_DISPVirtual        : I32BitEnumAttrCaseBit<"Virtual", 0>;
+def LLVM_DISPPureVirtual    : I32BitEnumAttrCaseBit<"PureVirtual", 1>;
+def LLVM_DISPLocalToUnit    : I32BitEnumAttrCaseBit<"LocalToUnit", 2>;
+def LLVM_DISPDefinition     : I32BitEnumAttrCaseBit<"Definition", 3>;
+def LLVM_DISPOptimized      : I32BitEnumAttrCaseBit<"Optimized", 4>;
+def LLVM_DISPPure           : I32BitEnumAttrCaseBit<"Pure", 5>;
+def LLVM_DISPElemental      : I32BitEnumAttrCaseBit<"Elemental", 6>;
+def LLVM_DISPRecursive      : I32BitEnumAttrCaseBit<"Recursive", 7>;
+def LLVM_DISPMainSubprogram : I32BitEnumAttrCaseBit<"MainSubprogram", 8>;
+def LLVM_DISPDeleted        : I32BitEnumAttrCaseBit<"Deleted", 9>;
+def LLVM_DISPObjCDirect     : I32BitEnumAttrCaseBit<"ObjCDirect", 11>;
+
+def DISubprogramFlags : I32BitEnumAttr<
+    "DISubprogramFlags",
+    "LLVM DISubprogram flags", [
+      LLVM_DISPVirtual,
+      LLVM_DISPPureVirtual,
+      LLVM_DISPLocalToUnit,
+      LLVM_DISPDefinition,
+      LLVM_DISPOptimized,
+      LLVM_DISPPure, 
+      LLVM_DISPElemental,
+      LLVM_DISPRecursive,
+      LLVM_DISPMainSubprogram,
+      LLVM_DISPDeleted,
+      LLVM_DISPObjCDirect
+    ]> {
+  let cppNamespace = "::mlir::LLVM";
+  let printBitEnumPrimaryGroups = 1;
+}
+
 //===----------------------------------------------------------------------===//
 // FastmathFlags
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
index a6b47cf50e8b6..d78efa5c608e7 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
@@ -3,6 +3,7 @@
 
 include "mlir/IR/OpBase.td"
 include "mlir/Dialect/LLVMIR/LLVMOpBase.td"
+include "mlir/Dialect/LLVMIR/LLVMAttrDefs.td"
 include "mlir/Interfaces/InferTypeOpInterface.td"
 
 // Operations that correspond to LLVM intrinsics. With MLIR operation set being
@@ -228,6 +229,31 @@ def LLVM_CoroResumeOp : LLVM_IntrOp<"coro.resume", [], [], [], 0> {
   let assemblyFormat = "$handle attr-dict";
 }
 
+//
+// Debug function intrinsics.
+//
+
+def LLVM_DbgAddrOp : LLVM_Op<"dbg.addr"> {
+  let summary = "Describe the current address of a local debug info variable.";
+  let arguments = (ins LLVM_AnyPointer:$addr, LLVM_DILocalVariableAttr:$varInfo);
+
+  let assemblyFormat = "qualified($varInfo) `=` $addr `:` type($addr) attr-dict";
+}
+
+def LLVM_DbgDeclareOp : LLVM_Op<"dbg.declare"> {
+  let summary = "Declare the address of a local debug info variable.";
+  let arguments = (ins LLVM_AnyPointer:$addr, LLVM_DILocalVariableAttr:$varInfo);
+
+  let assemblyFormat = "qualified($varInfo) `=` $addr `:` type($addr) attr-dict";
+}
+
+def LLVM_DbgValueOp : LLVM_Op<"dbg.value"> {
+  let summary = "Describe the current value of a local debug info variable.";
+  let arguments = (ins LLVM_Type:$value, LLVM_DILocalVariableAttr:$varInfo);
+
+  let assemblyFormat = "qualified($varInfo) `=` $value `:` type($value) attr-dict";
+}
+
 //
 // Variadic function intrinsics.
 //

diff  --git a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
index 880e2fa7599d8..b3f13edb07eee 100644
--- a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
@@ -21,6 +21,7 @@ add_mlir_dialect_library(MLIRLLVMDialect
 
   LINK_COMPONENTS
   AsmParser
+  BinaryFormat
   BitReader
   BitWriter
   Core

diff  --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
index 894b3b2e9c54d..7d0c2297736b2 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
@@ -16,6 +16,7 @@
 #include "mlir/IR/DialectImplementation.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/TypeSwitch.h"
+#include "llvm/BinaryFormat/Dwarf.h"
 
 using namespace mlir;
 using namespace mlir::LLVM;
@@ -35,6 +36,197 @@ void LLVMDialect::registerAttributes() {
       >();
 }
 
+//===----------------------------------------------------------------------===//
+// DINodeAttr
+//===----------------------------------------------------------------------===//
+
+bool DINodeAttr::classof(Attribute attr) {
+  return llvm::isa<DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
+                   DIDerivedTypeAttr, DIFileAttr, DILexicalBlockAttr,
+                   DILexicalBlockFileAttr, DILocalVariableAttr,
+                   DISubprogramAttr, DISubroutineTypeAttr>(attr);
+}
+
+//===----------------------------------------------------------------------===//
+// DIScopeAttr
+//===----------------------------------------------------------------------===//
+
+bool DIScopeAttr::classof(Attribute attr) {
+  return llvm::isa<DICompileUnitAttr, DIFileAttr, DILexicalBlockAttr,
+                   DILexicalBlockFileAttr, DISubprogramAttr>(attr);
+}
+
+//===----------------------------------------------------------------------===//
+// DITypeAttr
+//===----------------------------------------------------------------------===//
+
+bool DITypeAttr::classof(Attribute attr) {
+  return llvm::isa<DIBasicTypeAttr, DISubroutineTypeAttr>(attr);
+}
+
+//===----------------------------------------------------------------------===//
+// DICompileUnitAttr
+//===----------------------------------------------------------------------===//
+
+void DICompileUnitAttr::walkImmediateSubElements(
+    function_ref<void(Attribute)> walkAttrsFn,
+    function_ref<void(Type)> walkTypesFn) const {
+  walkAttrsFn(getFile());
+  walkAttrsFn(getProducer());
+}
+
+Attribute
+DICompileUnitAttr::replaceImmediateSubElements(ArrayRef<Attribute> replAttrs,
+                                               ArrayRef<Type> replTypes) const {
+  return get(getContext(), getSourceLanguage(), replAttrs[0].cast<DIFileAttr>(),
+             replAttrs[1].cast<StringAttr>(), getIsOptimized(),
+             getEmissionKind());
+}
+
+//===----------------------------------------------------------------------===//
+// DICompositeTypeAttr
+//===----------------------------------------------------------------------===//
+
+void DICompositeTypeAttr::walkImmediateSubElements(
+    function_ref<void(Attribute)> walkAttrsFn,
+    function_ref<void(Type)> walkTypesFn) const {
+  walkAttrsFn(getName());
+  walkAttrsFn(getFile());
+  walkAttrsFn(getScope());
+  for (DINodeAttr element : getElements())
+    walkAttrsFn(element);
+}
+
+Attribute DICompositeTypeAttr::replaceImmediateSubElements(
+    ArrayRef<Attribute> replAttrs, ArrayRef<Type> replTypes) const {
+  ArrayRef<Attribute> elements = replAttrs.drop_front(3);
+  return get(
+      getContext(), getTag(), replAttrs[0].cast<StringAttr>(),
+      cast_or_null<DIFileAttr>(replAttrs[1]), getLine(),
+      cast_or_null<DIScopeAttr>(replAttrs[2]), getSizeInBits(),
+      getAlignInBits(),
+      ArrayRef<DINodeAttr>(static_cast<const DINodeAttr *>(elements.data()),
+                           elements.size()));
+}
+
+//===----------------------------------------------------------------------===//
+// DIDerivedTypeAttr
+//===----------------------------------------------------------------------===//
+
+void DIDerivedTypeAttr::walkImmediateSubElements(
+    function_ref<void(Attribute)> walkAttrsFn,
+    function_ref<void(Type)> walkTypesFn) const {
+  walkAttrsFn(getName());
+  walkAttrsFn(getBaseType());
+}
+
+Attribute
+DIDerivedTypeAttr::replaceImmediateSubElements(ArrayRef<Attribute> replAttrs,
+                                               ArrayRef<Type> replTypes) const {
+  return get(getContext(), getTag(), replAttrs[0].cast<StringAttr>(),
+             replAttrs[1].cast<DITypeAttr>(), getSizeInBits(), getAlignInBits(),
+             getOffsetInBits());
+}
+
+//===----------------------------------------------------------------------===//
+// DILexicalBlockAttr
+//===----------------------------------------------------------------------===//
+
+void DILexicalBlockAttr::walkImmediateSubElements(
+    function_ref<void(Attribute)> walkAttrsFn,
+    function_ref<void(Type)> walkTypesFn) const {
+  walkAttrsFn(getScope());
+  walkAttrsFn(getFile());
+}
+
+Attribute DILexicalBlockAttr::replaceImmediateSubElements(
+    ArrayRef<Attribute> replAttrs, ArrayRef<Type> replTypes) const {
+  return get(replAttrs[0].cast<DIScopeAttr>(), replAttrs[1].cast<DIFileAttr>(),
+             getLine(), getColumn());
+}
+
+//===----------------------------------------------------------------------===//
+// DILexicalBlockFileAttr
+//===----------------------------------------------------------------------===//
+
+void DILexicalBlockFileAttr::walkImmediateSubElements(
+    function_ref<void(Attribute)> walkAttrsFn,
+    function_ref<void(Type)> walkTypesFn) const {
+  walkAttrsFn(getScope());
+  walkAttrsFn(getFile());
+}
+
+Attribute DILexicalBlockFileAttr::replaceImmediateSubElements(
+    ArrayRef<Attribute> replAttrs, ArrayRef<Type> replTypes) const {
+  return get(replAttrs[0].cast<DIScopeAttr>(), replAttrs[1].cast<DIFileAttr>(),
+             getDescriminator());
+}
+
+//===----------------------------------------------------------------------===//
+// DILocalVariableAttr
+//===----------------------------------------------------------------------===//
+
+void DILocalVariableAttr::walkImmediateSubElements(
+    function_ref<void(Attribute)> walkAttrsFn,
+    function_ref<void(Type)> walkTypesFn) const {
+  walkAttrsFn(getScope());
+  walkAttrsFn(getName());
+  walkAttrsFn(getFile());
+  walkAttrsFn(getType());
+}
+
+Attribute DILocalVariableAttr::replaceImmediateSubElements(
+    ArrayRef<Attribute> replAttrs, ArrayRef<Type> replTypes) const {
+  return get(getContext(), replAttrs[0].cast<DIScopeAttr>(),
+             replAttrs[1].cast<StringAttr>(), replAttrs[2].cast<DIFileAttr>(),
+             getLine(), getArg(), getAlignInBits(),
+             replAttrs[3].cast<DITypeAttr>());
+}
+
+//===----------------------------------------------------------------------===//
+// DISubprogramAttr
+//===----------------------------------------------------------------------===//
+
+void DISubprogramAttr::walkImmediateSubElements(
+    function_ref<void(Attribute)> walkAttrsFn,
+    function_ref<void(Type)> walkTypesFn) const {
+  walkAttrsFn(getCompileUnit());
+  walkAttrsFn(getScope());
+  walkAttrsFn(getName());
+  walkAttrsFn(getLinkageName());
+  walkAttrsFn(getFile());
+  walkAttrsFn(getType());
+}
+
+Attribute
+DISubprogramAttr::replaceImmediateSubElements(ArrayRef<Attribute> replAttrs,
+                                              ArrayRef<Type> replTypes) const {
+  return get(getContext(), replAttrs[0].cast<DICompileUnitAttr>(),
+             replAttrs[1].cast<DIScopeAttr>(), replAttrs[2].cast<StringAttr>(),
+             replAttrs[3].cast<StringAttr>(), replAttrs[4].cast<DIFileAttr>(),
+             getLine(), getScopeLine(), getSubprogramFlags(),
+             replAttrs[5].cast<DISubroutineTypeAttr>());
+}
+
+//===----------------------------------------------------------------------===//
+// DISubroutineTypeAttr
+//===----------------------------------------------------------------------===//
+
+void DISubroutineTypeAttr::walkImmediateSubElements(
+    function_ref<void(Attribute)> walkAttrsFn,
+    function_ref<void(Type)> walkTypesFn) const {
+  for (DITypeAttr type : getTypes())
+    walkAttrsFn(type);
+}
+
+Attribute DISubroutineTypeAttr::replaceImmediateSubElements(
+    ArrayRef<Attribute> replAttrs, ArrayRef<Type> replTypes) const {
+  return get(
+      getContext(), getCallingConvention(),
+      ArrayRef<DITypeAttr>(static_cast<const DITypeAttr *>(replAttrs.data()),
+                           replAttrs.size()));
+}
+
 //===----------------------------------------------------------------------===//
 // LoopOptionsAttrBuilder
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 5476c949c0d15..375ec6ff0e78a 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -2556,6 +2556,28 @@ OpFoldResult LLVM::GEPOp::fold(ArrayRef<Attribute> operands) {
   return {};
 }
 
+//===----------------------------------------------------------------------===//
+// OpAsmDialectInterface
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct LLVMOpAsmDialectInterface : public OpAsmDialectInterface {
+  using OpAsmDialectInterface::OpAsmDialectInterface;
+
+  AliasResult getAlias(Attribute attr, raw_ostream &os) const override {
+    return TypeSwitch<Attribute, AliasResult>(attr)
+        .Case<DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
+              DIDerivedTypeAttr, DIFileAttr, DILexicalBlockAttr,
+              DILexicalBlockFileAttr, DILocalVariableAttr, DISubprogramAttr,
+              DISubroutineTypeAttr>([&](auto attr) {
+          os << decltype(attr)::getMnemonic();
+          return AliasResult::OverridableAlias;
+        })
+        .Default([](Attribute) { return AliasResult::NoAlias; });
+  }
+};
+} // namespace
+
 //===----------------------------------------------------------------------===//
 // LLVMDialect initialization, type parsing, and registration.
 //===----------------------------------------------------------------------===//
@@ -2584,6 +2606,7 @@ void LLVMDialect::initialize() {
 
   // Support unknown operations because not all LLVM operations are registered.
   allowUnknownOperations();
+  addInterfaces<LLVMOpAsmDialectInterface>();
 }
 
 #define GET_OP_CLASSES

diff  --git a/mlir/test/Dialect/LLVMIR/debuginfo.mlir b/mlir/test/Dialect/LLVMIR/debuginfo.mlir
new file mode 100644
index 0000000000000..5e7401f3e1d16
--- /dev/null
+++ b/mlir/test/Dialect/LLVMIR/debuginfo.mlir
@@ -0,0 +1,43 @@
+// RUN: mlir-opt %s | mlir-opt | FileCheck %s
+
+// CHECK: #[[TYPE:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "si64", sizeInBits = 0, encoding = DW_ATE_signed>
+#si64 = #llvm.di_basic_type<
+  tag = DW_TAG_base_type, name = "si64", sizeInBits = 0,
+  encoding = DW_ATE_signed
+>
+
+// CHECK: #[[FILE:.*]] = #llvm.di_file<"debuginfo.mlir" in "/test/">
+#file = #llvm.di_file<"debuginfo.mlir" in "/test/">
+
+// CHECK: #[[CU:.*]] = #llvm.di_compile_unit<sourceLanguage = DW_LANG_C, file = #[[FILE]], producer = "MLIR", isOptimized = true, emissionKind = Full>
+#cu = #llvm.di_compile_unit<
+  sourceLanguage = DW_LANG_C, file = #file, producer = "MLIR",
+  isOptimized = true, emissionKind = Full
+>
+
+// CHECK: #[[SPTYPE:.*]] = #llvm.di_subroutine_type<callingConvention = DW_CC_normal, types = #[[TYPE]]>
+#spType = #llvm.di_subroutine_type<callingConvention = DW_CC_normal, types = #si64>
+
+// CHECK: #[[SP:.*]] = #llvm.di_subprogram<compileUnit = #[[CU]], scope = #[[FILE]], name = "intrinsics", linkageName = "intrinsics", file = #[[FILE]], line = 3, scopeLine = 3, subprogramFlags = "Definition|Optimized", type = #[[SPTYPE]]>
+#sp = #llvm.di_subprogram<
+  compileUnit = #cu, scope = #file, name = "intrinsics", linkageName = "intrinsics",
+  file = #file, line = 3, scopeLine = 3, subprogramFlags = "Definition|Optimized", type = #spType
+>
+
+// CHECK: #[[VAR:.*]] = #llvm.di_local_variable<scope = #[[SP]], name = "arg", file = #[[FILE]], line = 6, arg = 1, alignInBits = 0, type = #[[TYPE]]>
+#variable = #llvm.di_local_variable<scope = #sp, name = "arg", file = #file, line = 6, arg = 1, alignInBits = 0, type = #si64>
+
+// CHECK: llvm.func @intrinsics(%[[ARG:.*]]: i64)
+llvm.func @intrinsics(%arg: i64) {
+  // CHECK: %[[ALLOC:.*]] = llvm.alloca 
+  %allocCount = llvm.mlir.constant(1 : i32) : i32
+  %alloc = llvm.alloca %allocCount x i64 : (i32) -> !llvm.ptr<i64>
+
+  // CHECK: llvm.dbg.value #[[VAR]] = %[[ARG]]
+  // CHECK: llvm.dbg.addr #[[VAR]] = %[[ALLOC]]
+  // CHECK: llvm.dbg.declare #[[VAR]] = %[[ALLOC]]
+  llvm.dbg.value #variable = %arg : i64
+  llvm.dbg.addr #variable = %alloc : !llvm.ptr<i64>
+  llvm.dbg.declare #variable = %alloc : !llvm.ptr<i64>
+  llvm.return
+}


        


More information about the Mlir-commits mailing list