Skip to content

Commit e880caf

Browse files
committed
[mlir] Add support for recursive elements in DICompositeAttr.
Implements mutable storage for DICompositeTypeAttr in order to allow for self-references in its elements array. When the "identifier" parameter set non-empty, only this string participates in the hash key, though the storage is implemented such that only the "elements" parameter is mutable. The module translator will now create the respective instance of llvm::DICompositeType without elements and then it will call "llvm::DICompositeType::replaceElements" to set the elements after each element is translated. The only required IR change was that elements are explicitly wrapped in square brackets for the sake of parsing.
1 parent 2ec95c1 commit e880caf

File tree

7 files changed

+563
-31
lines changed

7 files changed

+563
-31
lines changed

mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -351,27 +351,6 @@ def LLVM_DICompileUnitAttr : LLVM_Attr<"DICompileUnit", "di_compile_unit",
351351
let assemblyFormat = "`<` struct(params) `>`";
352352
}
353353

354-
//===----------------------------------------------------------------------===//
355-
// DICompositeTypeAttr
356-
//===----------------------------------------------------------------------===//
357-
358-
def LLVM_DICompositeTypeAttr : LLVM_Attr<"DICompositeType", "di_composite_type",
359-
/*traits=*/[], "DITypeAttr"> {
360-
let parameters = (ins
361-
LLVM_DITagParameter:$tag,
362-
OptionalParameter<"StringAttr">:$name,
363-
OptionalParameter<"DIFileAttr">:$file,
364-
OptionalParameter<"uint32_t">:$line,
365-
OptionalParameter<"DIScopeAttr">:$scope,
366-
OptionalParameter<"DITypeAttr">:$baseType,
367-
OptionalParameter<"DIFlags", "DIFlags::Zero">:$flags,
368-
OptionalParameter<"uint64_t">:$sizeInBits,
369-
OptionalParameter<"uint64_t">:$alignInBits,
370-
OptionalArrayRefParameter<"DINodeAttr">:$elements
371-
);
372-
let assemblyFormat = "`<` struct(params) `>`";
373-
}
374-
375354
//===----------------------------------------------------------------------===//
376355
// DIDerivedTypeAttr
377356
//===----------------------------------------------------------------------===//
@@ -684,6 +663,61 @@ def LLVM_AliasScopeDomainAttr : LLVM_Attr<"AliasScopeDomain",
684663
let assemblyFormat = "`<` struct(params) `>`";
685664
}
686665

666+
//===----------------------------------------------------------------------===//
667+
// DICompositeTypeAttr
668+
//===----------------------------------------------------------------------===//
669+
670+
def LLVM_DICompositeTypeAttr : LLVM_Attr<"DICompositeType", "di_composite_type",
671+
/*traits=*/[NativeTypeTrait<"IsMutable">], "DITypeAttr"> {
672+
let parameters = (ins
673+
OptionalParameter<"unsigned">:$tag,
674+
OptionalParameter<"StringAttr">:$name,
675+
OptionalParameter<"DIFileAttr">:$file,
676+
OptionalParameter<"uint32_t">:$line,
677+
OptionalParameter<"DIScopeAttr">:$scope,
678+
OptionalParameter<"DITypeAttr">:$baseType,
679+
OptionalParameter<"DIFlags", "DIFlags::Zero">:$flags,
680+
OptionalParameter<"uint64_t">:$sizeInBits,
681+
OptionalParameter<"uint64_t">:$alignInBits,
682+
OptionalArrayRefParameter<"DINodeAttr">:$elements,
683+
OptionalParameter<"DistinctAttr">:$identifier
684+
);
685+
let hasCustomAssemblyFormat = 1;
686+
let genStorageClass = 0;
687+
let storageClass = "DICompositeTypeAttrStorage";
688+
let builders = [
689+
AttrBuilder<(ins
690+
"unsigned":$tag,
691+
"StringAttr":$name,
692+
"DIFileAttr":$file,
693+
"uint32_t":$line,
694+
"DIScopeAttr":$scope,
695+
"DITypeAttr":$baseType,
696+
"DIFlags":$flags,
697+
"uint64_t":$sizeInBits,
698+
"uint64_t":$alignInBits,
699+
"::llvm::ArrayRef<DINodeAttr>":$elements
700+
)>,
701+
AttrBuilder<(ins
702+
"DistinctAttr":$identifier,
703+
"unsigned":$tag,
704+
"StringAttr":$name,
705+
"DIFileAttr":$file,
706+
"uint32_t":$line,
707+
"DIScopeAttr":$scope,
708+
"DITypeAttr":$baseType,
709+
"DIFlags":$flags,
710+
"uint64_t":$sizeInBits,
711+
"uint64_t":$alignInBits,
712+
CArg<"::llvm::ArrayRef<DINodeAttr>", "{}">:$elements
713+
)>
714+
];
715+
let extraClassDeclaration = [{
716+
static DICompositeTypeAttr getIdentified(MLIRContext *context, DistinctAttr identifier);
717+
void replaceElements(const ArrayRef<DINodeAttr>& elements);
718+
}];
719+
}
720+
687721
//===----------------------------------------------------------------------===//
688722
// AliasScopeAttr
689723
//===----------------------------------------------------------------------===//

mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
namespace mlir {
2424
namespace LLVM {
2525

26+
namespace detail {
27+
struct DICompositeTypeAttrStorage;
28+
} // namespace detail
29+
2630
/// This class represents the base attribute for all debug info attributes.
2731
class DINodeAttr : public Attribute {
2832
public:

mlir/lib/AsmParser/AttributeParser.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ Attribute Parser::parseAttribute(Type type) {
248248
OptionalParseResult Parser::parseOptionalAttribute(Attribute &attribute,
249249
Type type) {
250250
switch (getToken().getKind()) {
251+
case Token::kw_distinct:
251252
case Token::at_identifier:
252253
case Token::floatliteral:
253254
case Token::integer:
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
//===- AttrDetail.h - Details of MLIR LLVM dialect attributes --------*- C++
2+
//-*-===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This file contains implementation details, such as storage structures, of
11+
// MLIR LLVM dialect attributes.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
#ifndef DIALECT_LLVMIR_IR_ATTRDETAIL_H
15+
#define DIALECT_LLVMIR_IR_ATTRDETAIL_H
16+
17+
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
18+
#include "mlir/IR/Types.h"
19+
20+
namespace mlir {
21+
namespace LLVM {
22+
namespace detail {
23+
24+
//===----------------------------------------------------------------------===//
25+
// DICompositeTypeAttrStorage
26+
//===----------------------------------------------------------------------===//
27+
28+
struct DICompositeTypeAttrStorage : public ::mlir::AttributeStorage {
29+
using KeyTy = std::tuple<unsigned, StringAttr, DIFileAttr, uint32_t,
30+
DIScopeAttr, DITypeAttr, DIFlags, uint64_t, uint64_t,
31+
ArrayRef<DINodeAttr>, DistinctAttr>;
32+
33+
DICompositeTypeAttrStorage(unsigned tag, StringAttr name, DIFileAttr file,
34+
uint32_t line, DIScopeAttr scope,
35+
DITypeAttr baseType, DIFlags flags,
36+
uint64_t sizeInBits, uint64_t alignInBits,
37+
ArrayRef<DINodeAttr> elements,
38+
DistinctAttr identifier = DistinctAttr())
39+
: tag(tag), name(name), file(file), line(line), scope(scope),
40+
baseType(baseType), flags(flags), sizeInBits(sizeInBits),
41+
alignInBits(alignInBits), elements(elements), identifier(identifier) {}
42+
43+
unsigned getTag() const { return tag; }
44+
StringAttr getName() const { return name; }
45+
DIFileAttr getFile() const { return file; }
46+
uint32_t getLine() const { return line; }
47+
DIScopeAttr getScope() const { return scope; }
48+
DITypeAttr getBaseType() const { return baseType; }
49+
DIFlags getFlags() const { return flags; }
50+
uint64_t getSizeInBits() const { return sizeInBits; }
51+
uint64_t getAlignInBits() const { return alignInBits; }
52+
ArrayRef<DINodeAttr> getElements() const { return elements; }
53+
DistinctAttr getIdentifier() const { return identifier; }
54+
55+
/// Returns true if this attribute is identified.
56+
bool isIdentified() const {
57+
return !(!identifier);
58+
}
59+
60+
/// Returns the respective key for this attribute.
61+
KeyTy getAsKey() const {
62+
if (isIdentified())
63+
return KeyTy(tag, name, file, line, scope, baseType, flags, sizeInBits,
64+
alignInBits, elements, identifier);
65+
66+
return KeyTy(tag, name, file, line, scope, baseType, flags, sizeInBits,
67+
alignInBits, elements, DistinctAttr());
68+
}
69+
70+
/// Compares two keys.
71+
bool operator==(const KeyTy &other) const {
72+
if (isIdentified())
73+
// Just compare against the identifier.
74+
return identifier == std::get<10>(other);
75+
76+
// Otherwise, compare the entire tuple.
77+
return other == getAsKey();
78+
}
79+
80+
/// Returns the hash value of the key.
81+
static llvm::hash_code hashKey(const KeyTy &key) {
82+
const auto &[tag, name, file, line, scope, baseType, flags, sizeInBits,
83+
alignInBits, elements, identifier] = key;
84+
85+
if (identifier)
86+
// Only the identifier participates in the hash id.
87+
return hash_value(identifier);
88+
89+
// Otherwise, everything else is included in the hash.
90+
return hash_combine(tag, name, file, line, scope, baseType, flags,
91+
sizeInBits, alignInBits, elements);
92+
}
93+
94+
/// Constructs new storage for an attribute.
95+
static DICompositeTypeAttrStorage *
96+
construct(AttributeStorageAllocator &allocator, const KeyTy &key) {
97+
auto [tag, name, file, line, scope, baseType, flags, sizeInBits,
98+
alignInBits, elements, identifier] = key;
99+
elements = allocator.copyInto(elements);
100+
if (identifier) {
101+
return new (allocator.allocate<DICompositeTypeAttrStorage>())
102+
DICompositeTypeAttrStorage(tag, name, file, line, scope, baseType,
103+
flags, sizeInBits, alignInBits, elements,
104+
identifier);
105+
}
106+
return new (allocator.allocate<DICompositeTypeAttrStorage>())
107+
DICompositeTypeAttrStorage(tag, name, file, line, scope, baseType,
108+
flags, sizeInBits, alignInBits, elements);
109+
}
110+
111+
LogicalResult mutate(AttributeStorageAllocator &allocator,
112+
const ArrayRef<DINodeAttr>& elements) {
113+
// Replace the elements.
114+
this->elements = allocator.copyInto(elements);
115+
return success();
116+
}
117+
118+
private:
119+
unsigned tag;
120+
StringAttr name;
121+
DIFileAttr file;
122+
uint32_t line;
123+
DIScopeAttr scope;
124+
DITypeAttr baseType;
125+
DIFlags flags;
126+
uint64_t sizeInBits;
127+
uint64_t alignInBits;
128+
ArrayRef<DINodeAttr> elements;
129+
DistinctAttr identifier;
130+
};
131+
132+
} // namespace detail
133+
} // namespace LLVM
134+
} // namespace mlir
135+
136+
#endif // DIALECT_LLVMIR_IR_ATTRDETAIL_H

0 commit comments

Comments
 (0)