Currently, we allow only one DIGlobalVariableExpressionAttr per global.
It is especially evident in import where we pick the first from the list
and ignore the rest. In contrast, LLVM allows multiple
DIGlobalVariableExpression to be attached to the global. They are needed
for correct working of things like DICommonBlock. This PR removes this
restriction in mlir. Changes are mostly mechanical. One thing on which I
went a bit back and forth was the representation inside GlobalOp. I
would be happy to change if there are better ways to do this.
---------
Co-authored-by: Tobias Gysi <tobias.gysi@nextsilicon.com>
A COMMON block is a named area of memory that holds a collection of
variables. Fortran subprograms may map the COMMON block memory area to a
list of variables. A common block is represented in LLVM debug by
DICommonBlock.
This PR adds support for this in MLIR. The changes are mostly mechanical
apart from small change to access the DICompileUnit when the scope of
the variable is DICommonBlock.
---------
Co-authored-by: Tobias Gysi <tobias.gysi@nextsilicon.com>
LLVM already supports `DW_TAG_LLVM_annotation` entries for subprograms,
but this hasn't been surfaced to the LLVM dialect.
I'm doing the minimal amount of work to support string-based
annotations, which is useful for attaching metadata to
functions, which is useful for debuggers to offer features beyond basic
DWARF.
As LLVM already supports this, this patch is not controversial.
This reverts commit fa93be4, restoring
commit d884b77, with fixes that ensure the CAPI declarations are
exported properly.
This commit implements LLVM_DIRecursiveTypeAttrInterface for the
DISubprogramAttr to ensure cyclic subprograms can be imported properly.
In the process multiple shortcuts around the recently introduced
DIImportedEntityAttr can be removed.
This commit implements LLVM_DIRecursiveTypeAttrInterface for the
DISubprogramAttr to ensure cyclic subprograms can be imported properly.
In the process multiple shortcuts around the recently introduced
DIImportedEntityAttr can be removed.
The `DIImporedEntity` can be used to represent imported entities like
C++'s namespace with using directive or fortran's moudule with use
statement.
This PR adds `DIImportedEntityAttr` and 2-way translation from
`DIImportedEntity` to `DIImportedEntityAttr` and vice versa.
When an entity is imported in a function, the `retainedNodes` field of
the `DISubprogram` contains all the imported nodes. See the C++ code and
the LLVM IR below.
```
void test() {
using namespace n1;
...
}
!2 = !DINamespace(name: "n1", scope: null)
!16 = distinct !DISubprogram(name: "test", ..., retainedNodes: !19) !19 = !{!20}
!20 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !16, entity: !2 ...)
```
This PR makes sure that the translation from mlir to `retainedNodes`
field happens correctly both ways.
To side step the cyclic dependency between `DISubprogramAttr` and `DIImportedEntityAttr`,
we have decided to not have `scope` field in the `DIImportedEntityAttr` and it is inferred
from the entity which hold the list of `DIImportedEntityAttr`. A `retainedNodes` field has been
added in the `DISubprogramAttr` which contains the list of `DIImportedEntityAttr` for that
function.
This PR currently does not handle entities imported in a global scope
but that should be easy to handle in a subsequent PR.
Use the new CyclicReplacerCache from
https://github.com/llvm/llvm-project/pull/98202 to support importing of
recursive DITypes in LLVM dialect's DebugImporter. This helps simplify
the implementation, allows for separate testing of the cache infra
itself, and as a result we even got more efficient translations.
This PR handle translation of DIStringType. Mostly mechanical changes to
translate DIStringType to/from DIStringTypeAttr. The 'stringLength'
field is 'DIVariable' in DIStringType. As there was no `DIVariableAttr`
previously, it has been added to ease the translation.
---------
Co-authored-by: Tobias Gysi <tobias.gysi@nextsilicon.com>
The DISubrange can take integer, dwarf expressions or variables. The
current translation only handled integers. This PR adds handling of
dwarf expressions and variables.
This field is present in LLVM, but was missing from the MLIR wrapper
type. This addition allows MLIR languages to add proper DWARF info for
GPU programs.
Followup to this discussion:
https://github.com/llvm/llvm-project/pull/80251#discussion_r1535599920.
The previous debug importer was correct but inefficient. For cases with
mutual recursion that contain more than one back-edge, each back-edge
would result in a new translated instance. This is because the previous
implementation never caches any translated result with unbounded
self-references. This means all translation inside a recursive context
is performed from scratch, which will incur repeated run-time cost as
well as repeated attribute sub-trees in the translated IR (differing
only in their `recId`s).
This PR refactors the importer to handle caching inside a recursive
context.
- In the presence of unbound self-refs, the translation result is cached
in a separate cache that keeps track of the set of dependent unbound
self-refs.
- A dependent cache entry is valid only when all the unbound self-refs
are in scope. Whenever a cached entry goes out of scope, it will be
removed the next time it is looked up.
This revision makes the subprogramFlags field in the DISubprogrammAttr
optional. This is necessary since the DISubprogram attached to a
declaration may have none of the subprogram flags set.
This commit extends the DIDerivedTypeAttr with the `extraData` field.
For now, the type of it is limited to be a `DINodeAttr`, as extending
the debug metadata handling to support arbitrary metadata nodes does not
seem to be necessary so far.
Following the discussion from [this
thread](https://discourse.llvm.org/t/handling-cyclic-dependencies-in-debug-info/67526/11),
this PR adds support for recursive DITypes.
This PR adds:
1. DIRecursiveTypeAttrInterface: An interface that DITypeAttrs can
implement to indicate that it supports recursion. See full description
in code.
2. Importer & exporter support (The only DITypeAttr that implements the
interface is DICompositeTypeAttr, so the exporter is only implemented
for composites too. There will be two methods that each llvm DI type
that supports mutation needs to implement since there's nothing
general).
---------
Co-authored-by: Tobias Gysi <tobias.gysi@nextsilicon.com>
This commit adds an optional distinct attribute parameter to the
DISubprogramAttr. This enables modeling of distinct subprograms, as
required for LLVM IR. This change is required to avoid accidential
uniquing of subprograms on functions that would lead to invalid LLVM IR
post export.
This commit adds a distinct attribute parameter to the DICompileUnit to
enable the modeling of distinctness. LLVM requires DICompileUnits to be
distinct and there are cases where one gets two equivalent compilation
units but LLVM still requires differentiates them. We observed such
cases for combinations of LTO and inline functions.
This patch also changes the DIScopeForLLVMFuncOp pass to a module pass,
to ensure that only one distinct DICompileUnit is created, instead of
one for each function.
There's an issue in the translator today where, for a CallsiteLoc, if
the callee does not have a DI scope (perhaps due to compile options or
optimizations), it may get propagated the DI scope of its callsite's
parent function, which will create a non-existent DILocation combining
line & col number from one file, and the filename from another.
The root problem is we cannot propagate the parent scope when
translating the callee location, as it no longer applies to inlined
locations (see code diff and hopefully this will make sense).
To facilitate this, the importer is also changed so that callee scopes
are fused with the callee FileLineCol loc, instead of on the Callsite
loc itself. This comes with the benefit that we now have a symmetric
Callsite loc representation. If we required the callee scope be always
annotated on the Callsite loc, it would be hard for generic inlining
passes to maintain that, since it would have to somehow understand the
semantics of the fused metadata and pull it out while inlining.
This PR introduces DIGlobalVariableAttr and
DIGlobalVariableExpressionAttr so that ModuleTranslation can emit the
required metadata needed for debug information about global variable.
The translator implementation for debug metadata needed to be refactored
in order to allow translation of nodes based on MDNode
(DIGlobalVariableExpressionAttr and DIExpression) in addition to
DINode-based nodes.
A DIGlobalVariableExpressionAttr can now be passed to the GlobalOp
operation directly and ModuleTranslation will create the respective
DIGlobalVariable and DIGlobalVariableExpression nodes. The compile unit
that DIGlobalVariable is expected to be configured with will be updated
with the created DIGlobalVariableExpression.
Add initial support for DIExpression in LLVM dialect.
Similar to LLVM IR, DI Expression is encoded as a list of uint64. The
difference is that LLVM IR has helpers for understanding the expression
(e.g. for verification and pretty printing), whereas the current support
added by this PR treats the expression elements as opaque.
This commit ensures that the debug info import skips `DICompositeTypes`
that have an array type tag and failed to translate the base type. This
is necessary because array `DICompositeTypes` require a base type to be
valid.
Note that this is currently not verified in LLVM, instead it leads to an
explosion of the `ASMPrinter`.
This commit ensures that debug intrinsics are imported after all other
instructions of a function were imported.
Debug intrinsics in LLVM are excluded from the define-before-use
invariant, i.e., they can reference SSA values that do not dominate
them. So far, we had implemented checks to stop the import of such
intrinsics, but there were always additional cases that were not
covered (the latest being terminators that define such used values).
Reviewed By: gysit, zero9178
Differential Revision: https://reviews.llvm.org/D157496
This commit adds a DIModuleAttr to the set of debug info attributes and
extends the LLVM IR import and export to support it.
DIModule metadata is missing in the LLVM LangRef and cannot be produced
from C or C++ input. So far, we only observed classic flang producing
such DI metadata.
Reviewed By: zero9178
Differential Revision: https://reviews.llvm.org/D156969
This commit changes the LLVM IR import to use UnkownLoc for missing
debug locations. This change ensures that we do not accidentially
introduce faulty locations that can influence debugging post export.
This behavior change is not applied to locations of global metadata
operations, as their location will not be exported.
Reviewed By: gysit
Differential Revision: https://reviews.llvm.org/D154416
Debug intrinsics are allowed to violate SSA dominance and might thus
cause the LLVM import to produce invalid LLVM dialect. This commit
ensures that the debug intrinsics are emitted right after the definition
of their SSA operands.
As the position of debug intrinsics has no meaning, changing it has no
semantic implication.
Reviewed By: gysit
Differential Revision: https://reviews.llvm.org/D153984
This revision adds support for the llvm.dbg.label.intrinsic
and the corresponding DILabel metadata.
Reviewed By: Dinistro
Differential Revision: https://reviews.llvm.org/D153975
This commit make the name parameter of the DISubprogramAttr optional.
LLVM will for example omit these subprogram names in initialization
functions for globals.
Reviewed By: gysit
Differential Revision: https://reviews.llvm.org/D145046
This commit ensures that no empty debug metadata strings are exported as
these are not legal names. Additionally, this commit ensures that
non-existing strings are not accidentially imported as empty strings.
Reviewed By: gysit
Differential Revision: https://reviews.llvm.org/D144263
This commit introduces the DINamespaceAttr to model LLVM's DINamespace metadata.
Reviewed By: gysit
Differential Revision: https://reviews.llvm.org/D144243
This commit adds special handling for the debug intrinsic value
handling. LLVM allows to relax the def before use property for debug
intrinsics, so this property cannot be assumed for metadata values.
Reviewed By: gysit
Differential Revision: https://reviews.llvm.org/D144177
This commit renames the "di_void_result_type" to "di_null_type" as LLVM
does use null not exclusively for void types. An added test demonstrates
this for variadic function declarations, whose DISubroutine indicates the
start of variadic types with `null`.
Reviewed By: gysit
Differential Revision: https://reviews.llvm.org/D144109
This revision fixes the import of LLVM IR to handle debug metadata with
cyclic dependencies. It deletes the elements list of the composite type
if a cyclic dependency is detected. The revision is meant as a band aid
to avoid infinite recursion during the import of cyclic debug metadata.
Long term solutions are currently discussed here:
https://discourse.llvm.org/t/handling-cyclic-dependencies-in-debug-info/67526/4
Reviewed By: Dinistro
Differential Revision: https://reviews.llvm.org/D142086
Previously, the DISubroutineType attribute used an optional result
parameter and an optional argument types array to model the subroutine
signature. LLVM IR debug metadata, on the other hand, has one types
list whose first entry maps to the result type. That entry may be
null to model a void result type. The type list may also be entirely
empty not specifying any type information. The latter is problematic
since the current DISubroutineType attribute cannot express it.
The revision changes DISubroutineTypeAttr to closely follow the
LLVM metadata design. In particular, it uses a single types parameter
array to model the subroutine signature and introduces an explicit
DIVoidResultTypeAttr to model the null entries.
Reviewed By: Dinistro
Differential Revision: https://reviews.llvm.org/D141261
This reverts commit 81f57b6
and relands commit a960547
Fixes flang build and drop_begin on an empty array ref.
Previously, the DISubroutineType attribute used an optional result
parameter and an optional argument types array to model the subroutine
signature. LLVM IR debug metadata, on the other hand, has one types
list whose first entry maps to the result type. That entry may be
null to model a void result type. The type list may also be entirely
empty not specifying any type information. The latter is problematic
since the current DISubroutineType attribute cannot express it.
The revision changes DISubroutineTypeAttr to closely follow the
LLVM metadata design. In particular, it uses a single types parameter
array to model the subroutine signature and introduces an explicit
DIVoidResultTypeAttr to model the null entries.
Reviewed By: Dinistro
Differential Revision: https://reviews.llvm.org/D141261
A DICompositeTypeAttr is the MLIR counterpart of LLVMIR's
DICompositeType debug metadata node. It can be used to store debug
information associated to a class or struct type definition. Any class
member method then sets its scope to the parent DICompositeType. This
revision adds DICompositeTypeAttr to the list of DIScopeAttrs to
prevent verification failures for legal debug information. Additionally,
it adds a number of test cases.
Reviewed By: Dinistro
Differential Revision: https://reviews.llvm.org/D141480
Use the module location instead of unknown location if the imported
LLVM IR module does not have more precise debug information.
Additionally, use the diagMD function to print the metadata instead
of just the metadata kind if the import fails.
Reviewed By: definelicht
Differential Revision: https://reviews.llvm.org/D141357
This commit refactors attribute/type alias generation to be similar to how
we do it for operations, i.e. we generate aliases determined on what is
actually necessary when printing the IR (using a dummy printer for alias
collection). This allows for generating aliases only when necessary, and
also allows for proper propagation of when a nested alias can be deferred.
This also necessitated a fix for location parsing to actually parse aliases
instead of ignoring them.
Fixes#59041
Differential Revision: https://reviews.llvm.org/D138886
The revision makes additional integer debug info parameters such as
line or column numbers optional (e.g. the line and column numbers 0 are
elided when printing, which is in line with the LLVM implementation).
Depends on D138405
Reviewed By: rriddle
Differential Revision: https://reviews.llvm.org/D138437
Currently, the import of LLVMIR fails if the program contains debug
intrinsics. The revision adds support to import debug intrinsics that
have no debug expression attached and drops all debug intrinsics with a
non-empty debug expression. It also moves the existing debug intrinsics
into the "intr" namespace by deriving from LLVM_IntrOp.
Reviewed By: rriddle
Differential Revision: https://reviews.llvm.org/D138405
We properly order dependencies between attribute/type aliases,
but we currently always print attribute aliases separately from type
aliases. This creates problems if an attribute wants to use a type
alias during printing.
This commit refactors alias collection such that attribute/type aliases
are collected together and printed together.
Differential Revision: https://reviews.llvm.org/D138162
Add a DebugImporter to convert LLVMIR debug metadata into
MLIR debug attributes. It is the counterpart to the
DebugTranslation class and supports the same attributes.
The revision only supports the translation of instruction,
function, and module debug information. The import of
intrinsics is left to a later revision.
Depends on D138206
Reviewed By: rriddle
Differential Revision: https://reviews.llvm.org/D138209
The revision enriches the debug locations generated during LLVMIR to MLIR translation with file name information and adds a separate test to exercise the debug location translation.
Reviewed By: ftynse
Differential Revision: https://reviews.llvm.org/D135069