/home/arjun/llvm-project/mlir/include/mlir/IR/Attributes.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- Attributes.h - MLIR Attribute Classes --------------------*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #ifndef MLIR_IR_ATTRIBUTES_H |
10 | | #define MLIR_IR_ATTRIBUTES_H |
11 | | |
12 | | #include "mlir/IR/AttributeSupport.h" |
13 | | #include "llvm/ADT/APFloat.h" |
14 | | #include "llvm/ADT/Sequence.h" |
15 | | #include "llvm/Support/PointerLikeTypeTraits.h" |
16 | | #include <complex> |
17 | | |
18 | | namespace mlir { |
19 | | class AffineMap; |
20 | | class Dialect; |
21 | | class FunctionType; |
22 | | class Identifier; |
23 | | class IntegerSet; |
24 | | class Location; |
25 | | class MLIRContext; |
26 | | class ShapedType; |
27 | | class Type; |
28 | | |
29 | | namespace detail { |
30 | | |
31 | | struct AffineMapAttributeStorage; |
32 | | struct ArrayAttributeStorage; |
33 | | struct BoolAttributeStorage; |
34 | | struct DictionaryAttributeStorage; |
35 | | struct IntegerAttributeStorage; |
36 | | struct IntegerSetAttributeStorage; |
37 | | struct FloatAttributeStorage; |
38 | | struct OpaqueAttributeStorage; |
39 | | struct StringAttributeStorage; |
40 | | struct SymbolRefAttributeStorage; |
41 | | struct TypeAttributeStorage; |
42 | | |
43 | | /// Elements Attributes. |
44 | | struct DenseIntOrFPElementsAttributeStorage; |
45 | | struct DenseStringElementsAttributeStorage; |
46 | | struct OpaqueElementsAttributeStorage; |
47 | | struct SparseElementsAttributeStorage; |
48 | | } // namespace detail |
49 | | |
50 | | /// Attributes are known-constant values of operations and functions. |
51 | | /// |
52 | | /// Instances of the Attribute class are references to immutable, uniqued, |
53 | | /// and immortal values owned by MLIRContext. As such, an Attribute is a thin |
54 | | /// wrapper around an underlying storage pointer. Attributes are usually passed |
55 | | /// by value. |
56 | | class Attribute { |
57 | | public: |
58 | | /// Integer identifier for all the concrete attribute kinds. |
59 | | enum Kind { |
60 | | // Reserve attribute kinds for dialect specific extensions. |
61 | | #define DEFINE_SYM_KIND_RANGE(Dialect) \ |
62 | | FIRST_##Dialect##_ATTR, LAST_##Dialect##_ATTR = FIRST_##Dialect##_ATTR + 0xff, |
63 | | #include "DialectSymbolRegistry.def" |
64 | | }; |
65 | | |
66 | | /// Utility class for implementing attributes. |
67 | | template <typename ConcreteType, typename BaseType = Attribute, |
68 | | typename StorageType = AttributeStorage> |
69 | | using AttrBase = detail::StorageUserBase<ConcreteType, BaseType, StorageType, |
70 | | detail::AttributeUniquer>; |
71 | | |
72 | | using ImplType = AttributeStorage; |
73 | | using ValueType = void; |
74 | | |
75 | 0 | constexpr Attribute() : impl(nullptr) {} |
76 | | /* implicit */ Attribute(const ImplType *impl) |
77 | 0 | : impl(const_cast<ImplType *>(impl)) {} |
78 | | |
79 | | Attribute(const Attribute &other) = default; |
80 | | Attribute &operator=(const Attribute &other) = default; |
81 | | |
82 | 0 | bool operator==(Attribute other) const { return impl == other.impl; } |
83 | 0 | bool operator!=(Attribute other) const { return !(*this == other); } |
84 | 0 | explicit operator bool() const { return impl; } |
85 | | |
86 | 0 | bool operator!() const { return impl == nullptr; } |
87 | | |
88 | | template <typename U> bool isa() const; |
89 | | template <typename U> U dyn_cast() const; |
90 | | template <typename U> U dyn_cast_or_null() const; |
91 | | template <typename U> U cast() const; |
92 | | |
93 | | // Support dyn_cast'ing Attribute to itself. |
94 | 0 | static bool classof(Attribute) { return true; } |
95 | | |
96 | | /// Return the classification for this attribute. |
97 | 0 | unsigned getKind() const { return impl->getKind(); } |
98 | | |
99 | | /// Return the type of this attribute. |
100 | | Type getType() const; |
101 | | |
102 | | /// Return the context this attribute belongs to. |
103 | | MLIRContext *getContext() const; |
104 | | |
105 | | /// Get the dialect this attribute is registered to. |
106 | | Dialect &getDialect() const; |
107 | | |
108 | | /// Print the attribute. |
109 | | void print(raw_ostream &os) const; |
110 | | void dump() const; |
111 | | |
112 | | /// Get an opaque pointer to the attribute. |
113 | 0 | const void *getAsOpaquePointer() const { return impl; } |
114 | | /// Construct an attribute from the opaque pointer representation. |
115 | 0 | static Attribute getFromOpaquePointer(const void *ptr) { |
116 | 0 | return Attribute(reinterpret_cast<const ImplType *>(ptr)); |
117 | 0 | } |
118 | | |
119 | | friend ::llvm::hash_code hash_value(Attribute arg); |
120 | | |
121 | | protected: |
122 | | ImplType *impl; |
123 | | }; |
124 | | |
125 | 0 | inline raw_ostream &operator<<(raw_ostream &os, Attribute attr) { |
126 | 0 | attr.print(os); |
127 | 0 | return os; |
128 | 0 | } |
129 | | |
130 | | namespace StandardAttributes { |
131 | | enum Kind { |
132 | | AffineMap = Attribute::FIRST_STANDARD_ATTR, |
133 | | Array, |
134 | | Bool, |
135 | | Dictionary, |
136 | | Float, |
137 | | Integer, |
138 | | IntegerSet, |
139 | | Opaque, |
140 | | String, |
141 | | SymbolRef, |
142 | | Type, |
143 | | Unit, |
144 | | |
145 | | /// Elements Attributes. |
146 | | DenseIntOrFPElements, |
147 | | DenseStringElements, |
148 | | OpaqueElements, |
149 | | SparseElements, |
150 | | FIRST_ELEMENTS_ATTR = DenseIntOrFPElements, |
151 | | LAST_ELEMENTS_ATTR = SparseElements, |
152 | | |
153 | | /// Locations. |
154 | | CallSiteLocation, |
155 | | FileLineColLocation, |
156 | | FusedLocation, |
157 | | NameLocation, |
158 | | OpaqueLocation, |
159 | | UnknownLocation, |
160 | | |
161 | | // Represents a location as a 'void*' pointer to a front-end's opaque |
162 | | // location information, which must live longer than the MLIR objects that |
163 | | // refer to it. OpaqueLocation's are never serialized. |
164 | | // |
165 | | // TODO: OpaqueLocation, |
166 | | |
167 | | // Represents a value inlined through a function call. |
168 | | // TODO: InlinedLocation, |
169 | | |
170 | | FIRST_LOCATION_ATTR = CallSiteLocation, |
171 | | LAST_LOCATION_ATTR = UnknownLocation, |
172 | | }; |
173 | | } // namespace StandardAttributes |
174 | | |
175 | | //===----------------------------------------------------------------------===// |
176 | | // AffineMapAttr |
177 | | //===----------------------------------------------------------------------===// |
178 | | |
179 | | class AffineMapAttr |
180 | | : public Attribute::AttrBase<AffineMapAttr, Attribute, |
181 | | detail::AffineMapAttributeStorage> { |
182 | | public: |
183 | | using Base::Base; |
184 | | using ValueType = AffineMap; |
185 | | |
186 | | static AffineMapAttr get(AffineMap value); |
187 | | |
188 | | AffineMap getValue() const; |
189 | | |
190 | | /// Methods for support type inquiry through isa, cast, and dyn_cast. |
191 | 0 | static bool kindof(unsigned kind) { |
192 | 0 | return kind == StandardAttributes::AffineMap; |
193 | 0 | } |
194 | | }; |
195 | | |
196 | | //===----------------------------------------------------------------------===// |
197 | | // ArrayAttr |
198 | | //===----------------------------------------------------------------------===// |
199 | | |
200 | | /// Array attributes are lists of other attributes. They are not necessarily |
201 | | /// type homogenous given that attributes don't, in general, carry types. |
202 | | class ArrayAttr : public Attribute::AttrBase<ArrayAttr, Attribute, |
203 | | detail::ArrayAttributeStorage> { |
204 | | public: |
205 | | using Base::Base; |
206 | | using ValueType = ArrayRef<Attribute>; |
207 | | |
208 | | static ArrayAttr get(ArrayRef<Attribute> value, MLIRContext *context); |
209 | | |
210 | | ArrayRef<Attribute> getValue() const; |
211 | | Attribute operator[](unsigned idx) const; |
212 | | |
213 | | /// Support range iteration. |
214 | | using iterator = llvm::ArrayRef<Attribute>::iterator; |
215 | 0 | iterator begin() const { return getValue().begin(); } |
216 | 0 | iterator end() const { return getValue().end(); } |
217 | 0 | size_t size() const { return getValue().size(); } |
218 | | |
219 | | /// Methods for support type inquiry through isa, cast, and dyn_cast. |
220 | 0 | static bool kindof(unsigned kind) { |
221 | 0 | return kind == StandardAttributes::Array; |
222 | 0 | } |
223 | | |
224 | | private: |
225 | | /// Class for underlying value iterator support. |
226 | | template <typename AttrTy> |
227 | | class attr_value_iterator final |
228 | | : public llvm::mapped_iterator<ArrayAttr::iterator, |
229 | | AttrTy (*)(Attribute)> { |
230 | | public: |
231 | | explicit attr_value_iterator(ArrayAttr::iterator it) |
232 | | : llvm::mapped_iterator<ArrayAttr::iterator, AttrTy (*)(Attribute)>( |
233 | | it, [](Attribute attr) { return attr.cast<AttrTy>(); }) {} |
234 | | AttrTy operator*() const { return (*this->I).template cast<AttrTy>(); } |
235 | | }; |
236 | | |
237 | | public: |
238 | | template <typename AttrTy> |
239 | | llvm::iterator_range<attr_value_iterator<AttrTy>> getAsRange() { |
240 | | return llvm::make_range(attr_value_iterator<AttrTy>(begin()), |
241 | | attr_value_iterator<AttrTy>(end())); |
242 | | } |
243 | | }; |
244 | | |
245 | | //===----------------------------------------------------------------------===// |
246 | | // BoolAttr |
247 | | //===----------------------------------------------------------------------===// |
248 | | |
249 | | class BoolAttr : public Attribute::AttrBase<BoolAttr, Attribute, |
250 | | detail::BoolAttributeStorage> { |
251 | | public: |
252 | | using Base::Base; |
253 | | using ValueType = bool; |
254 | | |
255 | | static BoolAttr get(bool value, MLIRContext *context); |
256 | | |
257 | | bool getValue() const; |
258 | | |
259 | | /// Methods for support type inquiry through isa, cast, and dyn_cast. |
260 | 0 | static bool kindof(unsigned kind) { return kind == StandardAttributes::Bool; } |
261 | | }; |
262 | | |
263 | | //===----------------------------------------------------------------------===// |
264 | | // DictionaryAttr |
265 | | //===----------------------------------------------------------------------===// |
266 | | |
267 | | /// NamedAttribute is used for dictionary attributes, it holds an identifier for |
268 | | /// the name and a value for the attribute. The attribute pointer should always |
269 | | /// be non-null. |
270 | | using NamedAttribute = std::pair<Identifier, Attribute>; |
271 | | |
272 | | bool operator<(const NamedAttribute &lhs, const NamedAttribute &rhs); |
273 | | bool operator<(const NamedAttribute &lhs, StringRef rhs); |
274 | | |
275 | | /// Dictionary attribute is an attribute that represents a sorted collection of |
276 | | /// named attribute values. The elements are sorted by name, and each name must |
277 | | /// be unique within the collection. |
278 | | class DictionaryAttr |
279 | | : public Attribute::AttrBase<DictionaryAttr, Attribute, |
280 | | detail::DictionaryAttributeStorage> { |
281 | | public: |
282 | | using Base::Base; |
283 | | using ValueType = ArrayRef<NamedAttribute>; |
284 | | |
285 | | /// Construct a dictionary attribute with the provided list of named |
286 | | /// attributes. This method assumes that the provided list is unordered. If |
287 | | /// the caller can guarantee that the attributes are ordered by name, |
288 | | /// getWithSorted should be used instead. |
289 | | static DictionaryAttr get(ArrayRef<NamedAttribute> value, |
290 | | MLIRContext *context); |
291 | | |
292 | | /// Construct a dictionary with an array of values that is known to already be |
293 | | /// sorted by name and uniqued. |
294 | | static DictionaryAttr getWithSorted(ArrayRef<NamedAttribute> value, |
295 | | MLIRContext *context); |
296 | | |
297 | | ArrayRef<NamedAttribute> getValue() const; |
298 | | |
299 | | /// Return the specified attribute if present, null otherwise. |
300 | | Attribute get(StringRef name) const; |
301 | | Attribute get(Identifier name) const; |
302 | | |
303 | | /// Return the specified named attribute if present, None otherwise. |
304 | | Optional<NamedAttribute> getNamed(StringRef name) const; |
305 | | Optional<NamedAttribute> getNamed(Identifier name) const; |
306 | | |
307 | | /// Support range iteration. |
308 | | using iterator = llvm::ArrayRef<NamedAttribute>::iterator; |
309 | | iterator begin() const; |
310 | | iterator end() const; |
311 | 0 | bool empty() const { return size() == 0; } |
312 | | size_t size() const; |
313 | | |
314 | | /// Sorts the NamedAttributes in the array ordered by name as expected by |
315 | | /// getWithSorted and returns whether the values were sorted. |
316 | | /// Requires: uniquely named attributes. |
317 | | static bool sort(ArrayRef<NamedAttribute> values, |
318 | | SmallVectorImpl<NamedAttribute> &storage); |
319 | | |
320 | | /// Sorts the NamedAttributes in the array ordered by name as expected by |
321 | | /// getWithSorted in place on an array and returns whether the values needed |
322 | | /// to be sorted. |
323 | | /// Requires: uniquely named attributes. |
324 | | static bool sortInPlace(SmallVectorImpl<NamedAttribute> &array); |
325 | | |
326 | | /// Methods for supporting type inquiry through isa, cast, and dyn_cast. |
327 | 0 | static bool kindof(unsigned kind) { |
328 | 0 | return kind == StandardAttributes::Dictionary; |
329 | 0 | } |
330 | | |
331 | | private: |
332 | | /// Return empty dictionary. |
333 | | static DictionaryAttr getEmpty(MLIRContext *context); |
334 | | }; |
335 | | |
336 | | //===----------------------------------------------------------------------===// |
337 | | // FloatAttr |
338 | | //===----------------------------------------------------------------------===// |
339 | | |
340 | | class FloatAttr : public Attribute::AttrBase<FloatAttr, Attribute, |
341 | | detail::FloatAttributeStorage> { |
342 | | public: |
343 | | using Base::Base; |
344 | | using ValueType = APFloat; |
345 | | |
346 | | /// Return a float attribute for the specified value in the specified type. |
347 | | /// These methods should only be used for simple constant values, e.g 1.0/2.0, |
348 | | /// that are known-valid both as host double and the 'type' format. |
349 | | static FloatAttr get(Type type, double value); |
350 | | static FloatAttr getChecked(Type type, double value, Location loc); |
351 | | |
352 | | /// Return a float attribute for the specified value in the specified type. |
353 | | static FloatAttr get(Type type, const APFloat &value); |
354 | | static FloatAttr getChecked(Type type, const APFloat &value, Location loc); |
355 | | |
356 | | APFloat getValue() const; |
357 | | |
358 | | /// This function is used to convert the value to a double, even if it loses |
359 | | /// precision. |
360 | | double getValueAsDouble() const; |
361 | | static double getValueAsDouble(APFloat val); |
362 | | |
363 | | /// Methods for support type inquiry through isa, cast, and dyn_cast. |
364 | 0 | static bool kindof(unsigned kind) { |
365 | 0 | return kind == StandardAttributes::Float; |
366 | 0 | } |
367 | | |
368 | | /// Verify the construction invariants for a double value. |
369 | | static LogicalResult verifyConstructionInvariants(Location loc, Type type, |
370 | | double value); |
371 | | static LogicalResult verifyConstructionInvariants(Location loc, Type type, |
372 | | const APFloat &value); |
373 | | }; |
374 | | |
375 | | //===----------------------------------------------------------------------===// |
376 | | // IntegerAttr |
377 | | //===----------------------------------------------------------------------===// |
378 | | |
379 | | class IntegerAttr |
380 | | : public Attribute::AttrBase<IntegerAttr, Attribute, |
381 | | detail::IntegerAttributeStorage> { |
382 | | public: |
383 | | using Base::Base; |
384 | | using ValueType = APInt; |
385 | | |
386 | | static IntegerAttr get(Type type, int64_t value); |
387 | | static IntegerAttr get(Type type, const APInt &value); |
388 | | |
389 | | APInt getValue() const; |
390 | | /// Return the integer value as a 64-bit int. The attribute must be a signless |
391 | | /// integer. |
392 | | // TODO(jpienaar): Change callers to use getValue instead. |
393 | | int64_t getInt() const; |
394 | | /// Return the integer value as a signed 64-bit int. The attribute must be |
395 | | /// a signed integer. |
396 | | int64_t getSInt() const; |
397 | | /// Return the integer value as a unsigned 64-bit int. The attribute must be |
398 | | /// an unsigned integer. |
399 | | uint64_t getUInt() const; |
400 | | |
401 | | /// Methods for support type inquiry through isa, cast, and dyn_cast. |
402 | 0 | static bool kindof(unsigned kind) { |
403 | 0 | return kind == StandardAttributes::Integer; |
404 | 0 | } |
405 | | |
406 | | static LogicalResult verifyConstructionInvariants(Location loc, Type type, |
407 | | int64_t value); |
408 | | static LogicalResult verifyConstructionInvariants(Location loc, Type type, |
409 | | const APInt &value); |
410 | | }; |
411 | | |
412 | | //===----------------------------------------------------------------------===// |
413 | | // IntegerSetAttr |
414 | | //===----------------------------------------------------------------------===// |
415 | | |
416 | | class IntegerSetAttr |
417 | | : public Attribute::AttrBase<IntegerSetAttr, Attribute, |
418 | | detail::IntegerSetAttributeStorage> { |
419 | | public: |
420 | | using Base::Base; |
421 | | using ValueType = IntegerSet; |
422 | | |
423 | | static IntegerSetAttr get(IntegerSet value); |
424 | | |
425 | | IntegerSet getValue() const; |
426 | | |
427 | | /// Methods for support type inquiry through isa, cast, and dyn_cast. |
428 | 0 | static bool kindof(unsigned kind) { |
429 | 0 | return kind == StandardAttributes::IntegerSet; |
430 | 0 | } |
431 | | }; |
432 | | |
433 | | //===----------------------------------------------------------------------===// |
434 | | // OpaqueAttr |
435 | | //===----------------------------------------------------------------------===// |
436 | | |
437 | | /// Opaque attributes represent attributes of non-registered dialects. These are |
438 | | /// attribute represented in their raw string form, and can only usefully be |
439 | | /// tested for attribute equality. |
440 | | class OpaqueAttr : public Attribute::AttrBase<OpaqueAttr, Attribute, |
441 | | detail::OpaqueAttributeStorage> { |
442 | | public: |
443 | | using Base::Base; |
444 | | |
445 | | /// Get or create a new OpaqueAttr with the provided dialect and string data. |
446 | | static OpaqueAttr get(Identifier dialect, StringRef attrData, Type type, |
447 | | MLIRContext *context); |
448 | | |
449 | | /// Get or create a new OpaqueAttr with the provided dialect and string data. |
450 | | /// If the given identifier is not a valid namespace for a dialect, then a |
451 | | /// null attribute is returned. |
452 | | static OpaqueAttr getChecked(Identifier dialect, StringRef attrData, |
453 | | Type type, Location location); |
454 | | |
455 | | /// Returns the dialect namespace of the opaque attribute. |
456 | | Identifier getDialectNamespace() const; |
457 | | |
458 | | /// Returns the raw attribute data of the opaque attribute. |
459 | | StringRef getAttrData() const; |
460 | | |
461 | | /// Verify the construction of an opaque attribute. |
462 | | static LogicalResult verifyConstructionInvariants(Location loc, |
463 | | Identifier dialect, |
464 | | StringRef attrData, |
465 | | Type type); |
466 | | |
467 | 0 | static bool kindof(unsigned kind) { |
468 | 0 | return kind == StandardAttributes::Opaque; |
469 | 0 | } |
470 | | }; |
471 | | |
472 | | //===----------------------------------------------------------------------===// |
473 | | // StringAttr |
474 | | //===----------------------------------------------------------------------===// |
475 | | |
476 | | class StringAttr : public Attribute::AttrBase<StringAttr, Attribute, |
477 | | detail::StringAttributeStorage> { |
478 | | public: |
479 | | using Base::Base; |
480 | | using ValueType = StringRef; |
481 | | |
482 | | /// Get an instance of a StringAttr with the given string. |
483 | | static StringAttr get(StringRef bytes, MLIRContext *context); |
484 | | |
485 | | /// Get an instance of a StringAttr with the given string and Type. |
486 | | static StringAttr get(StringRef bytes, Type type); |
487 | | |
488 | | StringRef getValue() const; |
489 | | |
490 | | /// Methods for support type inquiry through isa, cast, and dyn_cast. |
491 | 0 | static bool kindof(unsigned kind) { |
492 | 0 | return kind == StandardAttributes::String; |
493 | 0 | } |
494 | | }; |
495 | | |
496 | | //===----------------------------------------------------------------------===// |
497 | | // SymbolRefAttr |
498 | | //===----------------------------------------------------------------------===// |
499 | | |
500 | | class FlatSymbolRefAttr; |
501 | | |
502 | | /// A symbol reference attribute represents a symbolic reference to another |
503 | | /// operation. |
504 | | class SymbolRefAttr |
505 | | : public Attribute::AttrBase<SymbolRefAttr, Attribute, |
506 | | detail::SymbolRefAttributeStorage> { |
507 | | public: |
508 | | using Base::Base; |
509 | | |
510 | | /// Construct a symbol reference for the given value name. |
511 | | static FlatSymbolRefAttr get(StringRef value, MLIRContext *ctx); |
512 | | |
513 | | /// Construct a symbol reference for the given value name, and a set of nested |
514 | | /// references that are further resolve to a nested symbol. |
515 | | static SymbolRefAttr get(StringRef value, |
516 | | ArrayRef<FlatSymbolRefAttr> references, |
517 | | MLIRContext *ctx); |
518 | | |
519 | | /// Returns the name of the top level symbol reference, i.e. the root of the |
520 | | /// reference path. |
521 | | StringRef getRootReference() const; |
522 | | |
523 | | /// Returns the name of the fully resolved symbol, i.e. the leaf of the |
524 | | /// reference path. |
525 | | StringRef getLeafReference() const; |
526 | | |
527 | | /// Returns the set of nested references representing the path to the symbol |
528 | | /// nested under the root reference. |
529 | | ArrayRef<FlatSymbolRefAttr> getNestedReferences() const; |
530 | | |
531 | | /// Methods for support type inquiry through isa, cast, and dyn_cast. |
532 | 0 | static bool kindof(unsigned kind) { |
533 | 0 | return kind == StandardAttributes::SymbolRef; |
534 | 0 | } |
535 | | }; |
536 | | |
537 | | /// A symbol reference with a reference path containing a single element. This |
538 | | /// is used to refer to an operation within the current symbol table. |
539 | | class FlatSymbolRefAttr : public SymbolRefAttr { |
540 | | public: |
541 | | using SymbolRefAttr::SymbolRefAttr; |
542 | | using ValueType = StringRef; |
543 | | |
544 | | /// Construct a symbol reference for the given value name. |
545 | 0 | static FlatSymbolRefAttr get(StringRef value, MLIRContext *ctx) { |
546 | 0 | return SymbolRefAttr::get(value, ctx); |
547 | 0 | } |
548 | | |
549 | | /// Returns the name of the held symbol reference. |
550 | 0 | StringRef getValue() const { return getRootReference(); } |
551 | | |
552 | | /// Methods for support type inquiry through isa, cast, and dyn_cast. |
553 | 0 | static bool classof(Attribute attr) { |
554 | 0 | SymbolRefAttr refAttr = attr.dyn_cast<SymbolRefAttr>(); |
555 | 0 | return refAttr && refAttr.getNestedReferences().empty(); |
556 | 0 | } |
557 | | |
558 | | private: |
559 | | using SymbolRefAttr::get; |
560 | | using SymbolRefAttr::getNestedReferences; |
561 | | }; |
562 | | |
563 | | //===----------------------------------------------------------------------===// |
564 | | // Type |
565 | | //===----------------------------------------------------------------------===// |
566 | | |
567 | | class TypeAttr : public Attribute::AttrBase<TypeAttr, Attribute, |
568 | | detail::TypeAttributeStorage> { |
569 | | public: |
570 | | using Base::Base; |
571 | | using ValueType = Type; |
572 | | |
573 | | static TypeAttr get(Type value); |
574 | | |
575 | | Type getValue() const; |
576 | | |
577 | | /// Methods for support type inquiry through isa, cast, and dyn_cast. |
578 | 0 | static bool kindof(unsigned kind) { return kind == StandardAttributes::Type; } |
579 | | }; |
580 | | |
581 | | //===----------------------------------------------------------------------===// |
582 | | // UnitAttr |
583 | | //===----------------------------------------------------------------------===// |
584 | | |
585 | | /// Unit attributes are attributes that hold no specific value and are given |
586 | | /// meaning by their existence. |
587 | | class UnitAttr : public Attribute::AttrBase<UnitAttr> { |
588 | | public: |
589 | | using Base::Base; |
590 | | |
591 | | static UnitAttr get(MLIRContext *context); |
592 | | |
593 | 0 | static bool kindof(unsigned kind) { return kind == StandardAttributes::Unit; } |
594 | | }; |
595 | | |
596 | | //===----------------------------------------------------------------------===// |
597 | | // Elements Attributes |
598 | | //===----------------------------------------------------------------------===// |
599 | | |
600 | | namespace detail { |
601 | | template <typename T> class ElementsAttrIterator; |
602 | | template <typename T> class ElementsAttrRange; |
603 | | } // namespace detail |
604 | | |
605 | | /// A base attribute that represents a reference to a static shaped tensor or |
606 | | /// vector constant. |
607 | | class ElementsAttr : public Attribute { |
608 | | public: |
609 | | using Attribute::Attribute; |
610 | | template <typename T> using iterator = detail::ElementsAttrIterator<T>; |
611 | | template <typename T> using iterator_range = detail::ElementsAttrRange<T>; |
612 | | |
613 | | /// Return the type of this ElementsAttr, guaranteed to be a vector or tensor |
614 | | /// with static shape. |
615 | | ShapedType getType() const; |
616 | | |
617 | | /// Return the value at the given index. The index is expected to refer to a |
618 | | /// valid element. |
619 | | Attribute getValue(ArrayRef<uint64_t> index) const; |
620 | | |
621 | | /// Return the value of type 'T' at the given index, where 'T' corresponds to |
622 | | /// an Attribute type. |
623 | | template <typename T> T getValue(ArrayRef<uint64_t> index) const { |
624 | | return getValue(index).template cast<T>(); |
625 | | } |
626 | | |
627 | | /// Return the elements of this attribute as a value of type 'T'. Note: |
628 | | /// Aborts if the subclass is OpaqueElementsAttrs, these attrs do not support |
629 | | /// iteration. |
630 | | template <typename T> iterator_range<T> getValues() const; |
631 | | |
632 | | /// Return if the given 'index' refers to a valid element in this attribute. |
633 | | bool isValidIndex(ArrayRef<uint64_t> index) const; |
634 | | |
635 | | /// Returns the number of elements held by this attribute. |
636 | | int64_t getNumElements() const; |
637 | | |
638 | | /// Generates a new ElementsAttr by mapping each int value to a new |
639 | | /// underlying APInt. The new values can represent either an integer or float. |
640 | | /// This ElementsAttr should contain integers. |
641 | | ElementsAttr mapValues(Type newElementType, |
642 | | function_ref<APInt(const APInt &)> mapping) const; |
643 | | |
644 | | /// Generates a new ElementsAttr by mapping each float value to a new |
645 | | /// underlying APInt. The new values can represent either an integer or float. |
646 | | /// This ElementsAttr should contain floats. |
647 | | ElementsAttr mapValues(Type newElementType, |
648 | | function_ref<APInt(const APFloat &)> mapping) const; |
649 | | |
650 | | /// Method for support type inquiry through isa, cast and dyn_cast. |
651 | 0 | static bool classof(Attribute attr) { |
652 | 0 | return attr.getKind() >= StandardAttributes::FIRST_ELEMENTS_ATTR && |
653 | 0 | attr.getKind() <= StandardAttributes::LAST_ELEMENTS_ATTR; |
654 | 0 | } |
655 | | |
656 | | protected: |
657 | | /// Returns the 1 dimensional flattened row-major index from the given |
658 | | /// multi-dimensional index. |
659 | | uint64_t getFlattenedIndex(ArrayRef<uint64_t> index) const; |
660 | | }; |
661 | | |
662 | | namespace detail { |
663 | | /// DenseElementsAttr data is aligned to uint64_t, so this traits class is |
664 | | /// necessary to interop with PointerIntPair. |
665 | | class DenseElementDataPointerTypeTraits { |
666 | | public: |
667 | 0 | static inline const void *getAsVoidPointer(const char *ptr) { return ptr; } |
668 | 0 | static inline const char *getFromVoidPointer(const void *ptr) { |
669 | 0 | return static_cast<const char *>(ptr); |
670 | 0 | } |
671 | | |
672 | | // Note: We could steal more bits if the need arises. |
673 | | static constexpr int NumLowBitsAvailable = 1; |
674 | | }; |
675 | | |
676 | | /// Pair of raw pointer and a boolean flag of whether the pointer holds a splat, |
677 | | using DenseIterPtrAndSplat = |
678 | | llvm::PointerIntPair<const char *, 1, bool, |
679 | | DenseElementDataPointerTypeTraits>; |
680 | | |
681 | | /// Impl iterator for indexed DenseElementAttr iterators that records a data |
682 | | /// pointer and data index that is adjusted for the case of a splat attribute. |
683 | | template <typename ConcreteT, typename T, typename PointerT = T *, |
684 | | typename ReferenceT = T &> |
685 | | class DenseElementIndexedIteratorImpl |
686 | | : public llvm::indexed_accessor_iterator<ConcreteT, DenseIterPtrAndSplat, T, |
687 | | PointerT, ReferenceT> { |
688 | | protected: |
689 | | DenseElementIndexedIteratorImpl(const char *data, bool isSplat, |
690 | | size_t dataIndex) |
691 | | : llvm::indexed_accessor_iterator<ConcreteT, DenseIterPtrAndSplat, T, |
692 | | PointerT, ReferenceT>({data, isSplat}, |
693 | 0 | dataIndex) {} Unexecuted instantiation: _ZN4mlir6detail31DenseElementIndexedIteratorImplINS_17DenseElementsAttr19BoolElementIteratorEbbbEC2EPKcbm Unexecuted instantiation: _ZN4mlir6detail31DenseElementIndexedIteratorImplINS_17DenseElementsAttr18IntElementIteratorEN4llvm5APIntES5_S5_EC2EPKcbm Unexecuted instantiation: _ZN4mlir6detail31DenseElementIndexedIteratorImplINS_17DenseElementsAttr25ComplexIntElementIteratorESt7complexIN4llvm5APIntEES7_S7_EC2EPKcbm Unexecuted instantiation: _ZN4mlir6detail31DenseElementIndexedIteratorImplINS_17DenseElementsAttr15ElementIteratorImEEKmPS5_RS5_EC2EPKcbm Unexecuted instantiation: _ZN4mlir6detail31DenseElementIndexedIteratorImplINS_17DenseElementsAttr15ElementIteratorIiEEKiPS5_RS5_EC2EPKcbm |
694 | | |
695 | | /// Return the current index for this iterator, adjusted for the case of a |
696 | | /// splat. |
697 | 0 | ptrdiff_t getDataIndex() const { |
698 | 0 | bool isSplat = this->base.getInt(); |
699 | 0 | return isSplat ? 0 : this->index; |
700 | 0 | } Unexecuted instantiation: _ZNK4mlir6detail31DenseElementIndexedIteratorImplINS_17DenseElementsAttr19BoolElementIteratorEbbbE12getDataIndexEv Unexecuted instantiation: _ZNK4mlir6detail31DenseElementIndexedIteratorImplINS_17DenseElementsAttr18IntElementIteratorEN4llvm5APIntES5_S5_E12getDataIndexEv Unexecuted instantiation: _ZNK4mlir6detail31DenseElementIndexedIteratorImplINS_17DenseElementsAttr25ComplexIntElementIteratorESt7complexIN4llvm5APIntEES7_S7_E12getDataIndexEv Unexecuted instantiation: _ZNK4mlir6detail31DenseElementIndexedIteratorImplINS_17DenseElementsAttr15ElementIteratorImEEKmPS5_RS5_E12getDataIndexEv Unexecuted instantiation: _ZNK4mlir6detail31DenseElementIndexedIteratorImplINS_17DenseElementsAttr15ElementIteratorIiEEKiPS5_RS5_E12getDataIndexEv |
701 | | |
702 | | /// Return the data base pointer. |
703 | 0 | const char *getData() const { return this->base.getPointer(); } Unexecuted instantiation: _ZNK4mlir6detail31DenseElementIndexedIteratorImplINS_17DenseElementsAttr19BoolElementIteratorEbbbE7getDataEv Unexecuted instantiation: _ZNK4mlir6detail31DenseElementIndexedIteratorImplINS_17DenseElementsAttr18IntElementIteratorEN4llvm5APIntES5_S5_E7getDataEv Unexecuted instantiation: _ZNK4mlir6detail31DenseElementIndexedIteratorImplINS_17DenseElementsAttr25ComplexIntElementIteratorESt7complexIN4llvm5APIntEES7_S7_E7getDataEv Unexecuted instantiation: _ZNK4mlir6detail31DenseElementIndexedIteratorImplINS_17DenseElementsAttr15ElementIteratorImEEKmPS5_RS5_E7getDataEv Unexecuted instantiation: _ZNK4mlir6detail31DenseElementIndexedIteratorImplINS_17DenseElementsAttr15ElementIteratorIiEEKiPS5_RS5_E7getDataEv |
704 | | }; |
705 | | |
706 | | /// Type trait detector that checks if a given type T is a complex type. |
707 | | template <typename T> struct is_complex_t : public std::false_type {}; |
708 | | template <typename T> |
709 | | struct is_complex_t<std::complex<T>> : public std::true_type {}; |
710 | | } // namespace detail |
711 | | |
712 | | /// An attribute that represents a reference to a dense vector or tensor object. |
713 | | /// |
714 | | class DenseElementsAttr : public ElementsAttr { |
715 | | public: |
716 | | using ElementsAttr::ElementsAttr; |
717 | | |
718 | | /// Method for support type inquiry through isa, cast and dyn_cast. |
719 | 0 | static bool classof(Attribute attr) { |
720 | 0 | return attr.getKind() == StandardAttributes::DenseIntOrFPElements || |
721 | 0 | attr.getKind() == StandardAttributes::DenseStringElements; |
722 | 0 | } |
723 | | |
724 | | /// Constructs a dense elements attribute from an array of element values. |
725 | | /// Each element attribute value is expected to be an element of 'type'. |
726 | | /// 'type' must be a vector or tensor with static shape. If the element of |
727 | | /// `type` is non-integer/index/float it is assumed to be a string type. |
728 | | static DenseElementsAttr get(ShapedType type, ArrayRef<Attribute> values); |
729 | | |
730 | | /// Constructs a dense integer elements attribute from an array of integer |
731 | | /// or floating-point values. Each value is expected to be the same bitwidth |
732 | | /// of the element type of 'type'. 'type' must be a vector or tensor with |
733 | | /// static shape. |
734 | | template <typename T, typename = typename std::enable_if< |
735 | | std::numeric_limits<T>::is_integer || |
736 | | llvm::is_one_of<T, float, double>::value>::type> |
737 | 0 | static DenseElementsAttr get(const ShapedType &type, ArrayRef<T> values) { |
738 | 0 | const char *data = reinterpret_cast<const char *>(values.data()); |
739 | 0 | return getRawIntOrFloat( |
740 | 0 | type, ArrayRef<char>(data, values.size() * sizeof(T)), sizeof(T), |
741 | 0 | std::numeric_limits<T>::is_integer, std::numeric_limits<T>::is_signed); |
742 | 0 | } Unexecuted instantiation: _ZN4mlir17DenseElementsAttr3getIivEES0_RKNS_10ShapedTypeEN4llvm8ArrayRefIT_EE Unexecuted instantiation: _ZN4mlir17DenseElementsAttr3getIlvEES0_RKNS_10ShapedTypeEN4llvm8ArrayRefIT_EE |
743 | | |
744 | | /// Constructs a dense integer elements attribute from a single element. |
745 | | template <typename T, typename = typename std::enable_if< |
746 | | std::numeric_limits<T>::is_integer || |
747 | | llvm::is_one_of<T, float, double>::value || |
748 | | detail::is_complex_t<T>::value>::type> |
749 | | static DenseElementsAttr get(const ShapedType &type, T value) { |
750 | | return get(type, llvm::makeArrayRef(value)); |
751 | | } |
752 | | |
753 | | /// Constructs a dense complex elements attribute from an array of complex |
754 | | /// values. Each value is expected to be the same bitwidth of the element type |
755 | | /// of 'type'. 'type' must be a vector or tensor with static shape. |
756 | | template <typename T, typename ElementT = typename T::value_type, |
757 | | typename = typename std::enable_if< |
758 | | detail::is_complex_t<T>::value && |
759 | | (std::numeric_limits<ElementT>::is_integer || |
760 | | llvm::is_one_of<ElementT, float, double>::value)>::type> |
761 | | static DenseElementsAttr get(const ShapedType &type, ArrayRef<T> values) { |
762 | | const char *data = reinterpret_cast<const char *>(values.data()); |
763 | | return getRawComplex(type, ArrayRef<char>(data, values.size() * sizeof(T)), |
764 | | sizeof(T), std::numeric_limits<ElementT>::is_integer, |
765 | | std::numeric_limits<ElementT>::is_signed); |
766 | | } |
767 | | |
768 | | /// Overload of the above 'get' method that is specialized for boolean values. |
769 | | static DenseElementsAttr get(ShapedType type, ArrayRef<bool> values); |
770 | | |
771 | | /// Overload of the above 'get' method that is specialized for StringRef |
772 | | /// values. |
773 | | static DenseElementsAttr get(ShapedType type, ArrayRef<StringRef> values); |
774 | | |
775 | | /// Constructs a dense integer elements attribute from an array of APInt |
776 | | /// values. Each APInt value is expected to have the same bitwidth as the |
777 | | /// element type of 'type'. 'type' must be a vector or tensor with static |
778 | | /// shape. |
779 | | static DenseElementsAttr get(ShapedType type, ArrayRef<APInt> values); |
780 | | |
781 | | /// Constructs a dense complex elements attribute from an array of APInt |
782 | | /// values. Each APInt value is expected to have the same bitwidth as the |
783 | | /// element type of 'type'. 'type' must be a vector or tensor with static |
784 | | /// shape. |
785 | | static DenseElementsAttr get(ShapedType type, |
786 | | ArrayRef<std::complex<APInt>> values); |
787 | | |
788 | | /// Constructs a dense float elements attribute from an array of APFloat |
789 | | /// values. Each APFloat value is expected to have the same bitwidth as the |
790 | | /// element type of 'type'. 'type' must be a vector or tensor with static |
791 | | /// shape. |
792 | | static DenseElementsAttr get(ShapedType type, ArrayRef<APFloat> values); |
793 | | |
794 | | /// Constructs a dense complex elements attribute from an array of APFloat |
795 | | /// values. Each APFloat value is expected to have the same bitwidth as the |
796 | | /// element type of 'type'. 'type' must be a vector or tensor with static |
797 | | /// shape. |
798 | | static DenseElementsAttr get(ShapedType type, |
799 | | ArrayRef<std::complex<APFloat>> values); |
800 | | |
801 | | /// Construct a dense elements attribute for an initializer_list of values. |
802 | | /// Each value is expected to be the same bitwidth of the element type of |
803 | | /// 'type'. 'type' must be a vector or tensor with static shape. |
804 | | template <typename T> |
805 | | static DenseElementsAttr get(const ShapedType &type, |
806 | 0 | const std::initializer_list<T> &list) { |
807 | 0 | return get(type, ArrayRef<T>(list)); |
808 | 0 | } |
809 | | |
810 | | /// Construct a dense elements attribute from a raw buffer representing the |
811 | | /// data for this attribute. Users should generally not use this methods as |
812 | | /// the expected buffer format may not be a form the user expects. |
813 | | static DenseElementsAttr getFromRawBuffer(ShapedType type, |
814 | | ArrayRef<char> rawBuffer, |
815 | | bool isSplatBuffer); |
816 | | |
817 | | /// Returns true if the given buffer is a valid raw buffer for the given type. |
818 | | /// `detectedSplat` is set if the buffer is valid and represents a splat |
819 | | /// buffer. |
820 | | static bool isValidRawBuffer(ShapedType type, ArrayRef<char> rawBuffer, |
821 | | bool &detectedSplat); |
822 | | |
823 | | //===--------------------------------------------------------------------===// |
824 | | // Iterators |
825 | | //===--------------------------------------------------------------------===// |
826 | | |
827 | | /// A utility iterator that allows walking over the internal Attribute values |
828 | | /// of a DenseElementsAttr. |
829 | | class AttributeElementIterator |
830 | | : public llvm::indexed_accessor_iterator<AttributeElementIterator, |
831 | | const void *, Attribute, |
832 | | Attribute, Attribute> { |
833 | | public: |
834 | | /// Accesses the Attribute value at this iterator position. |
835 | | Attribute operator*() const; |
836 | | |
837 | | private: |
838 | | friend DenseElementsAttr; |
839 | | |
840 | | /// Constructs a new iterator. |
841 | | AttributeElementIterator(DenseElementsAttr attr, size_t index); |
842 | | }; |
843 | | |
844 | | /// Iterator for walking raw element values of the specified type 'T', which |
845 | | /// may be any c++ data type matching the stored representation: int32_t, |
846 | | /// float, etc. |
847 | | template <typename T> |
848 | | class ElementIterator |
849 | | : public detail::DenseElementIndexedIteratorImpl<ElementIterator<T>, |
850 | | const T> { |
851 | | public: |
852 | | /// Accesses the raw value at this iterator position. |
853 | 0 | const T &operator*() const { |
854 | 0 | return reinterpret_cast<const T *>(this->getData())[this->getDataIndex()]; |
855 | 0 | } Unexecuted instantiation: _ZNK4mlir17DenseElementsAttr15ElementIteratorImEdeEv Unexecuted instantiation: _ZNK4mlir17DenseElementsAttr15ElementIteratorIiEdeEv |
856 | | |
857 | | private: |
858 | | friend DenseElementsAttr; |
859 | | |
860 | | /// Constructs a new iterator. |
861 | | ElementIterator(const char *data, bool isSplat, size_t dataIndex) |
862 | | : detail::DenseElementIndexedIteratorImpl<ElementIterator<T>, const T>( |
863 | 0 | data, isSplat, dataIndex) {} Unexecuted instantiation: _ZN4mlir17DenseElementsAttr15ElementIteratorImEC2EPKcbm Unexecuted instantiation: _ZN4mlir17DenseElementsAttr15ElementIteratorIiEC2EPKcbm |
864 | | }; |
865 | | |
866 | | /// A utility iterator that allows walking over the internal bool values. |
867 | | class BoolElementIterator |
868 | | : public detail::DenseElementIndexedIteratorImpl<BoolElementIterator, |
869 | | bool, bool, bool> { |
870 | | public: |
871 | | /// Accesses the bool value at this iterator position. |
872 | | bool operator*() const; |
873 | | |
874 | | private: |
875 | | friend DenseElementsAttr; |
876 | | |
877 | | /// Constructs a new iterator. |
878 | | BoolElementIterator(DenseElementsAttr attr, size_t dataIndex); |
879 | | }; |
880 | | |
881 | | /// A utility iterator that allows walking over the internal raw APInt values. |
882 | | class IntElementIterator |
883 | | : public detail::DenseElementIndexedIteratorImpl<IntElementIterator, |
884 | | APInt, APInt, APInt> { |
885 | | public: |
886 | | /// Accesses the raw APInt value at this iterator position. |
887 | | APInt operator*() const; |
888 | | |
889 | | private: |
890 | | friend DenseElementsAttr; |
891 | | |
892 | | /// Constructs a new iterator. |
893 | | IntElementIterator(DenseElementsAttr attr, size_t dataIndex); |
894 | | |
895 | | /// The bitwidth of the element type. |
896 | | size_t bitWidth; |
897 | | }; |
898 | | |
899 | | /// A utility iterator that allows walking over the internal raw complex APInt |
900 | | /// values. |
901 | | class ComplexIntElementIterator |
902 | | : public detail::DenseElementIndexedIteratorImpl< |
903 | | ComplexIntElementIterator, std::complex<APInt>, std::complex<APInt>, |
904 | | std::complex<APInt>> { |
905 | | public: |
906 | | /// Accesses the raw std::complex<APInt> value at this iterator position. |
907 | | std::complex<APInt> operator*() const; |
908 | | |
909 | | private: |
910 | | friend DenseElementsAttr; |
911 | | |
912 | | /// Constructs a new iterator. |
913 | | ComplexIntElementIterator(DenseElementsAttr attr, size_t dataIndex); |
914 | | |
915 | | /// The bitwidth of the element type. |
916 | | size_t bitWidth; |
917 | | }; |
918 | | |
919 | | /// Iterator for walking over APFloat values. |
920 | | class FloatElementIterator final |
921 | | : public llvm::mapped_iterator<IntElementIterator, |
922 | | std::function<APFloat(const APInt &)>> { |
923 | | friend DenseElementsAttr; |
924 | | |
925 | | /// Initializes the float element iterator to the specified iterator. |
926 | | FloatElementIterator(const llvm::fltSemantics &smt, IntElementIterator it); |
927 | | |
928 | | public: |
929 | | using reference = APFloat; |
930 | | }; |
931 | | |
932 | | /// Iterator for walking over complex APFloat values. |
933 | | class ComplexFloatElementIterator final |
934 | | : public llvm::mapped_iterator< |
935 | | ComplexIntElementIterator, |
936 | | std::function<std::complex<APFloat>(const std::complex<APInt> &)>> { |
937 | | friend DenseElementsAttr; |
938 | | |
939 | | /// Initializes the float element iterator to the specified iterator. |
940 | | ComplexFloatElementIterator(const llvm::fltSemantics &smt, |
941 | | ComplexIntElementIterator it); |
942 | | |
943 | | public: |
944 | | using reference = std::complex<APFloat>; |
945 | | }; |
946 | | |
947 | | //===--------------------------------------------------------------------===// |
948 | | // Value Querying |
949 | | //===--------------------------------------------------------------------===// |
950 | | |
951 | | /// Returns if this attribute corresponds to a splat, i.e. if all element |
952 | | /// values are the same. |
953 | | bool isSplat() const; |
954 | | |
955 | | /// Return the splat value for this attribute. This asserts that the attribute |
956 | | /// corresponds to a splat. |
957 | 0 | Attribute getSplatValue() const { return getSplatValue<Attribute>(); } |
958 | | template <typename T> |
959 | | typename std::enable_if<!std::is_base_of<Attribute, T>::value || |
960 | | std::is_same<Attribute, T>::value, |
961 | | T>::type |
962 | 0 | getSplatValue() const { |
963 | 0 | assert(isSplat() && "expected the attribute to be a splat"); |
964 | 0 | return *getValues<T>().begin(); |
965 | 0 | } Unexecuted instantiation: _ZNK4mlir17DenseElementsAttr13getSplatValueINS_9AttributeEEENSt9enable_ifIXoontsr3std10is_base_ofIS2_T_EE5valuesr3std7is_sameIS2_S4_EE5valueES4_E4typeEv Unexecuted instantiation: _ZNK4mlir17DenseElementsAttr13getSplatValueIN4llvm7APFloatEEENSt9enable_ifIXoontsr3std10is_base_ofINS_9AttributeET_EE5valuesr3std7is_sameIS5_S6_EE5valueES6_E4typeEv Unexecuted instantiation: _ZNK4mlir17DenseElementsAttr13getSplatValueIN4llvm5APIntEEENSt9enable_ifIXoontsr3std10is_base_ofINS_9AttributeET_EE5valuesr3std7is_sameIS5_S6_EE5valueES6_E4typeEv |
966 | | /// Return the splat value for derived attribute element types. |
967 | | template <typename T> |
968 | | typename std::enable_if<std::is_base_of<Attribute, T>::value && |
969 | | !std::is_same<Attribute, T>::value, |
970 | | T>::type |
971 | 0 | getSplatValue() const { |
972 | 0 | return getSplatValue().template cast<T>(); |
973 | 0 | } |
974 | | |
975 | | /// Return the value at the given index. The 'index' is expected to refer to a |
976 | | /// valid element. |
977 | 0 | Attribute getValue(ArrayRef<uint64_t> index) const { |
978 | 0 | return getValue<Attribute>(index); |
979 | 0 | } |
980 | 0 | template <typename T> T getValue(ArrayRef<uint64_t> index) const { |
981 | 0 | // Skip to the element corresponding to the flattened index. |
982 | 0 | return *std::next(getValues<T>().begin(), getFlattenedIndex(index)); |
983 | 0 | } |
984 | | |
985 | | /// Return the held element values as a range of integer or floating-point |
986 | | /// values. |
987 | | template <typename T, typename = typename std::enable_if< |
988 | | (!std::is_same<T, bool>::value && |
989 | | std::numeric_limits<T>::is_integer) || |
990 | | llvm::is_one_of<T, float, double>::value>::type> |
991 | 0 | llvm::iterator_range<ElementIterator<T>> getValues() const { |
992 | 0 | assert(isValidIntOrFloat(sizeof(T), std::numeric_limits<T>::is_integer, |
993 | 0 | std::numeric_limits<T>::is_signed)); |
994 | 0 | const char *rawData = getRawData().data(); |
995 | 0 | bool splat = isSplat(); |
996 | 0 | return {ElementIterator<T>(rawData, splat, 0), |
997 | 0 | ElementIterator<T>(rawData, splat, getNumElements())}; |
998 | 0 | } Unexecuted instantiation: _ZNK4mlir17DenseElementsAttr9getValuesImvEEN4llvm14iterator_rangeINS0_15ElementIteratorIT_EEEEv Unexecuted instantiation: _ZNK4mlir17DenseElementsAttr9getValuesIivEEN4llvm14iterator_rangeINS0_15ElementIteratorIT_EEEEv |
999 | | |
1000 | | /// Return the held element values as a range of std::complex. |
1001 | | template <typename T, typename ElementT = typename T::value_type, |
1002 | | typename = typename std::enable_if< |
1003 | | detail::is_complex_t<T>::value && |
1004 | | (std::numeric_limits<ElementT>::is_integer || |
1005 | | llvm::is_one_of<ElementT, float, double>::value)>::type> |
1006 | | llvm::iterator_range<ElementIterator<T>> getValues() const { |
1007 | | assert(isValidComplex(sizeof(T), std::numeric_limits<ElementT>::is_integer, |
1008 | | std::numeric_limits<ElementT>::is_signed)); |
1009 | | const char *rawData = getRawData().data(); |
1010 | | bool splat = isSplat(); |
1011 | | return {ElementIterator<T>(rawData, splat, 0), |
1012 | | ElementIterator<T>(rawData, splat, getNumElements())}; |
1013 | | } |
1014 | | |
1015 | | /// Return the held element values as a range of StringRef. |
1016 | | template <typename T, typename = typename std::enable_if< |
1017 | | std::is_same<T, StringRef>::value>::type> |
1018 | | llvm::iterator_range<ElementIterator<StringRef>> getValues() const { |
1019 | | auto stringRefs = getRawStringData(); |
1020 | | const char *ptr = reinterpret_cast<const char *>(stringRefs.data()); |
1021 | | bool splat = isSplat(); |
1022 | | return {ElementIterator<StringRef>(ptr, splat, 0), |
1023 | | ElementIterator<StringRef>(ptr, splat, getNumElements())}; |
1024 | | } |
1025 | | |
1026 | | /// Return the held element values as a range of Attributes. |
1027 | | llvm::iterator_range<AttributeElementIterator> getAttributeValues() const; |
1028 | | template <typename T, typename = typename std::enable_if< |
1029 | | std::is_same<T, Attribute>::value>::type> |
1030 | 0 | llvm::iterator_range<AttributeElementIterator> getValues() const { |
1031 | 0 | return getAttributeValues(); |
1032 | 0 | } |
1033 | | AttributeElementIterator attr_value_begin() const; |
1034 | | AttributeElementIterator attr_value_end() const; |
1035 | | |
1036 | | /// Return the held element values a range of T, where T is a derived |
1037 | | /// attribute type. |
1038 | | template <typename T> |
1039 | | using DerivedAttributeElementIterator = |
1040 | | llvm::mapped_iterator<AttributeElementIterator, T (*)(Attribute)>; |
1041 | | template <typename T, typename = typename std::enable_if< |
1042 | | std::is_base_of<Attribute, T>::value && |
1043 | | !std::is_same<Attribute, T>::value>::type> |
1044 | | llvm::iterator_range<DerivedAttributeElementIterator<T>> getValues() const { |
1045 | | auto castFn = [](Attribute attr) { return attr.template cast<T>(); }; |
1046 | | return llvm::map_range(getAttributeValues(), |
1047 | | static_cast<T (*)(Attribute)>(castFn)); |
1048 | | } |
1049 | | |
1050 | | /// Return the held element values as a range of bool. The element type of |
1051 | | /// this attribute must be of integer type of bitwidth 1. |
1052 | | llvm::iterator_range<BoolElementIterator> getBoolValues() const; |
1053 | | template <typename T, typename = typename std::enable_if< |
1054 | | std::is_same<T, bool>::value>::type> |
1055 | | llvm::iterator_range<BoolElementIterator> getValues() const { |
1056 | | return getBoolValues(); |
1057 | | } |
1058 | | |
1059 | | /// Return the held element values as a range of APInts. The element type of |
1060 | | /// this attribute must be of integer type. |
1061 | | llvm::iterator_range<IntElementIterator> getIntValues() const; |
1062 | | template <typename T, typename = typename std::enable_if< |
1063 | | std::is_same<T, APInt>::value>::type> |
1064 | 0 | llvm::iterator_range<IntElementIterator> getValues() const { |
1065 | 0 | return getIntValues(); |
1066 | 0 | } |
1067 | | IntElementIterator int_value_begin() const; |
1068 | | IntElementIterator int_value_end() const; |
1069 | | |
1070 | | /// Return the held element values as a range of complex APInts. The element |
1071 | | /// type of this attribute must be a complex of integer type. |
1072 | | llvm::iterator_range<ComplexIntElementIterator> getComplexIntValues() const; |
1073 | | template <typename T, typename = typename std::enable_if< |
1074 | | std::is_same<T, std::complex<APInt>>::value>::type> |
1075 | | llvm::iterator_range<ComplexIntElementIterator> getValues() const { |
1076 | | return getComplexIntValues(); |
1077 | | } |
1078 | | |
1079 | | /// Return the held element values as a range of APFloat. The element type of |
1080 | | /// this attribute must be of float type. |
1081 | | llvm::iterator_range<FloatElementIterator> getFloatValues() const; |
1082 | | template <typename T, typename = typename std::enable_if< |
1083 | | std::is_same<T, APFloat>::value>::type> |
1084 | 0 | llvm::iterator_range<FloatElementIterator> getValues() const { |
1085 | 0 | return getFloatValues(); |
1086 | 0 | } |
1087 | | FloatElementIterator float_value_begin() const; |
1088 | | FloatElementIterator float_value_end() const; |
1089 | | |
1090 | | /// Return the held element values as a range of complex APFloat. The element |
1091 | | /// type of this attribute must be a complex of float type. |
1092 | | llvm::iterator_range<ComplexFloatElementIterator> |
1093 | | getComplexFloatValues() const; |
1094 | | template <typename T, typename = typename std::enable_if<std::is_same< |
1095 | | T, std::complex<APFloat>>::value>::type> |
1096 | | llvm::iterator_range<ComplexFloatElementIterator> getValues() const { |
1097 | | return getComplexFloatValues(); |
1098 | | } |
1099 | | |
1100 | | /// Return the raw storage data held by this attribute. Users should generally |
1101 | | /// not use this directly, as the internal storage format is not always in the |
1102 | | /// form the user might expect. |
1103 | | ArrayRef<char> getRawData() const; |
1104 | | |
1105 | | /// Return the raw StringRef data held by this attribute. |
1106 | | ArrayRef<StringRef> getRawStringData() const; |
1107 | | |
1108 | | //===--------------------------------------------------------------------===// |
1109 | | // Mutation Utilities |
1110 | | //===--------------------------------------------------------------------===// |
1111 | | |
1112 | | /// Return a new DenseElementsAttr that has the same data as the current |
1113 | | /// attribute, but has been reshaped to 'newType'. The new type must have the |
1114 | | /// same total number of elements as well as element type. |
1115 | | DenseElementsAttr reshape(ShapedType newType); |
1116 | | |
1117 | | /// Generates a new DenseElementsAttr by mapping each int value to a new |
1118 | | /// underlying APInt. The new values can represent either an integer or float. |
1119 | | /// This underlying type must be an DenseIntElementsAttr. |
1120 | | DenseElementsAttr mapValues(Type newElementType, |
1121 | | function_ref<APInt(const APInt &)> mapping) const; |
1122 | | |
1123 | | /// Generates a new DenseElementsAttr by mapping each float value to a new |
1124 | | /// underlying APInt. the new values can represent either an integer or float. |
1125 | | /// This underlying type must be an DenseFPElementsAttr. |
1126 | | DenseElementsAttr |
1127 | | mapValues(Type newElementType, |
1128 | | function_ref<APInt(const APFloat &)> mapping) const; |
1129 | | |
1130 | | protected: |
1131 | | /// Get iterators to the raw APInt values for each element in this attribute. |
1132 | 0 | IntElementIterator raw_int_begin() const { |
1133 | 0 | return IntElementIterator(*this, 0); |
1134 | 0 | } |
1135 | 0 | IntElementIterator raw_int_end() const { |
1136 | 0 | return IntElementIterator(*this, getNumElements()); |
1137 | 0 | } |
1138 | | |
1139 | | /// Overload of the raw 'get' method that asserts that the given type is of |
1140 | | /// complex type. This method is used to verify type invariants that the |
1141 | | /// templatized 'get' method cannot. |
1142 | | static DenseElementsAttr getRawComplex(ShapedType type, ArrayRef<char> data, |
1143 | | int64_t dataEltSize, bool isInt, |
1144 | | bool isSigned); |
1145 | | |
1146 | | /// Overload of the raw 'get' method that asserts that the given type is of |
1147 | | /// integer or floating-point type. This method is used to verify type |
1148 | | /// invariants that the templatized 'get' method cannot. |
1149 | | static DenseElementsAttr getRawIntOrFloat(ShapedType type, |
1150 | | ArrayRef<char> data, |
1151 | | int64_t dataEltSize, bool isInt, |
1152 | | bool isSigned); |
1153 | | |
1154 | | /// Check the information for a C++ data type, check if this type is valid for |
1155 | | /// the current attribute. This method is used to verify specific type |
1156 | | /// invariants that the templatized 'getValues' method cannot. |
1157 | | bool isValidIntOrFloat(int64_t dataEltSize, bool isInt, bool isSigned) const; |
1158 | | |
1159 | | /// Check the information for a C++ data type, check if this type is valid for |
1160 | | /// the current attribute. This method is used to verify specific type |
1161 | | /// invariants that the templatized 'getValues' method cannot. |
1162 | | bool isValidComplex(int64_t dataEltSize, bool isInt, bool isSigned) const; |
1163 | | }; |
1164 | | |
1165 | | /// An attribute class for representing dense arrays of strings. The structure |
1166 | | /// storing and querying a list of densely packed strings. |
1167 | | class DenseStringElementsAttr |
1168 | | : public Attribute::AttrBase<DenseStringElementsAttr, DenseElementsAttr, |
1169 | | detail::DenseStringElementsAttributeStorage> { |
1170 | | |
1171 | | public: |
1172 | | using Base::Base; |
1173 | | |
1174 | | /// Method for support type inquiry through isa, cast and dyn_cast. |
1175 | 0 | static bool kindof(unsigned kind) { |
1176 | 0 | return kind == StandardAttributes::DenseStringElements; |
1177 | 0 | } |
1178 | | |
1179 | | /// Overload of the raw 'get' method that asserts that the given type is of |
1180 | | /// integer or floating-point type. This method is used to verify type |
1181 | | /// invariants that the templatized 'get' method cannot. |
1182 | | static DenseStringElementsAttr get(ShapedType type, ArrayRef<StringRef> data); |
1183 | | |
1184 | | protected: |
1185 | | friend DenseElementsAttr; |
1186 | | }; |
1187 | | |
1188 | | /// An attribute class for specializing behavior of Int and Floating-point |
1189 | | /// densely packed string arrays. |
1190 | | class DenseIntOrFPElementsAttr |
1191 | | : public Attribute::AttrBase<DenseIntOrFPElementsAttr, DenseElementsAttr, |
1192 | | detail::DenseIntOrFPElementsAttributeStorage> { |
1193 | | |
1194 | | public: |
1195 | | using Base::Base; |
1196 | | |
1197 | | /// Method for support type inquiry through isa, cast and dyn_cast. |
1198 | 0 | static bool kindof(unsigned kind) { |
1199 | 0 | return kind == StandardAttributes::DenseIntOrFPElements; |
1200 | 0 | } |
1201 | | |
1202 | | protected: |
1203 | | friend DenseElementsAttr; |
1204 | | |
1205 | | /// Constructs a dense elements attribute from an array of raw APFloat values. |
1206 | | /// Each APFloat value is expected to have the same bitwidth as the element |
1207 | | /// type of 'type'. 'type' must be a vector or tensor with static shape. |
1208 | | static DenseElementsAttr getRaw(ShapedType type, size_t storageWidth, |
1209 | | ArrayRef<APFloat> values, bool isSplat); |
1210 | | |
1211 | | /// Constructs a dense elements attribute from an array of raw APInt values. |
1212 | | /// Each APInt value is expected to have the same bitwidth as the element type |
1213 | | /// of 'type'. 'type' must be a vector or tensor with static shape. |
1214 | | static DenseElementsAttr getRaw(ShapedType type, size_t storageWidth, |
1215 | | ArrayRef<APInt> values, bool isSplat); |
1216 | | |
1217 | | /// Get or create a new dense elements attribute instance with the given raw |
1218 | | /// data buffer. 'type' must be a vector or tensor with static shape. |
1219 | | static DenseElementsAttr getRaw(ShapedType type, ArrayRef<char> data, |
1220 | | bool isSplat); |
1221 | | |
1222 | | /// Overload of the raw 'get' method that asserts that the given type is of |
1223 | | /// complex type. This method is used to verify type invariants that the |
1224 | | /// templatized 'get' method cannot. |
1225 | | static DenseElementsAttr getRawComplex(ShapedType type, ArrayRef<char> data, |
1226 | | int64_t dataEltSize, bool isInt, |
1227 | | bool isSigned); |
1228 | | |
1229 | | /// Overload of the raw 'get' method that asserts that the given type is of |
1230 | | /// integer or floating-point type. This method is used to verify type |
1231 | | /// invariants that the templatized 'get' method cannot. |
1232 | | static DenseElementsAttr getRawIntOrFloat(ShapedType type, |
1233 | | ArrayRef<char> data, |
1234 | | int64_t dataEltSize, bool isInt, |
1235 | | bool isSigned); |
1236 | | }; |
1237 | | |
1238 | | /// An attribute that represents a reference to a dense float vector or tensor |
1239 | | /// object. Each element is stored as a double. |
1240 | | class DenseFPElementsAttr : public DenseIntOrFPElementsAttr { |
1241 | | public: |
1242 | | using iterator = DenseElementsAttr::FloatElementIterator; |
1243 | | |
1244 | | using DenseIntOrFPElementsAttr::DenseIntOrFPElementsAttr; |
1245 | | |
1246 | | /// Get an instance of a DenseFPElementsAttr with the given arguments. This |
1247 | | /// simply wraps the DenseElementsAttr::get calls. |
1248 | | template <typename Arg> |
1249 | | static DenseFPElementsAttr get(const ShapedType &type, Arg &&arg) { |
1250 | | return DenseElementsAttr::get(type, llvm::makeArrayRef(arg)) |
1251 | | .template cast<DenseFPElementsAttr>(); |
1252 | | } |
1253 | | template <typename T> |
1254 | | static DenseFPElementsAttr get(const ShapedType &type, |
1255 | | const std::initializer_list<T> &list) { |
1256 | | return DenseElementsAttr::get(type, list) |
1257 | | .template cast<DenseFPElementsAttr>(); |
1258 | | } |
1259 | | |
1260 | | /// Generates a new DenseElementsAttr by mapping each value attribute, and |
1261 | | /// constructing the DenseElementsAttr given the new element type. |
1262 | | DenseElementsAttr |
1263 | | mapValues(Type newElementType, |
1264 | | function_ref<APInt(const APFloat &)> mapping) const; |
1265 | | |
1266 | | /// Iterator access to the float element values. |
1267 | 0 | iterator begin() const { return float_value_begin(); } |
1268 | 0 | iterator end() const { return float_value_end(); } |
1269 | | |
1270 | | /// Method for supporting type inquiry through isa, cast and dyn_cast. |
1271 | | static bool classof(Attribute attr); |
1272 | | }; |
1273 | | |
1274 | | /// An attribute that represents a reference to a dense integer vector or tensor |
1275 | | /// object. |
1276 | | class DenseIntElementsAttr : public DenseIntOrFPElementsAttr { |
1277 | | public: |
1278 | | /// DenseIntElementsAttr iterates on APInt, so we can use the raw element |
1279 | | /// iterator directly. |
1280 | | using iterator = DenseElementsAttr::IntElementIterator; |
1281 | | |
1282 | | using DenseIntOrFPElementsAttr::DenseIntOrFPElementsAttr; |
1283 | | |
1284 | | /// Get an instance of a DenseIntElementsAttr with the given arguments. This |
1285 | | /// simply wraps the DenseElementsAttr::get calls. |
1286 | | template <typename Arg> |
1287 | 0 | static DenseIntElementsAttr get(const ShapedType &type, Arg &&arg) { |
1288 | 0 | return DenseElementsAttr::get(type, llvm::makeArrayRef(arg)) |
1289 | 0 | .template cast<DenseIntElementsAttr>(); |
1290 | 0 | } Unexecuted instantiation: _ZN4mlir20DenseIntElementsAttr3getIRN4llvm8ArrayRefIiEEEES0_RKNS_10ShapedTypeEOT_ Unexecuted instantiation: _ZN4mlir20DenseIntElementsAttr3getIRN4llvm8ArrayRefIlEEEES0_RKNS_10ShapedTypeEOT_ Unexecuted instantiation: _ZN4mlir20DenseIntElementsAttr3getIRN4llvm11SmallVectorIiLj8EEEEES0_RKNS_10ShapedTypeEOT_ |
1291 | | template <typename T> |
1292 | | static DenseIntElementsAttr get(const ShapedType &type, |
1293 | | const std::initializer_list<T> &list) { |
1294 | | return DenseElementsAttr::get(type, list) |
1295 | | .template cast<DenseIntElementsAttr>(); |
1296 | | } |
1297 | | |
1298 | | /// Generates a new DenseElementsAttr by mapping each value attribute, and |
1299 | | /// constructing the DenseElementsAttr given the new element type. |
1300 | | DenseElementsAttr mapValues(Type newElementType, |
1301 | | function_ref<APInt(const APInt &)> mapping) const; |
1302 | | |
1303 | | /// Iterator access to the integer element values. |
1304 | 0 | iterator begin() const { return raw_int_begin(); } |
1305 | 0 | iterator end() const { return raw_int_end(); } |
1306 | | |
1307 | | /// Method for supporting type inquiry through isa, cast and dyn_cast. |
1308 | | static bool classof(Attribute attr); |
1309 | | }; |
1310 | | |
1311 | | /// An opaque attribute that represents a reference to a vector or tensor |
1312 | | /// constant with opaque content. This representation is for tensor constants |
1313 | | /// which the compiler may not need to interpret. This attribute is always |
1314 | | /// associated with a particular dialect, which provides a method to convert |
1315 | | /// tensor representation to a non-opaque format. |
1316 | | class OpaqueElementsAttr |
1317 | | : public Attribute::AttrBase<OpaqueElementsAttr, ElementsAttr, |
1318 | | detail::OpaqueElementsAttributeStorage> { |
1319 | | public: |
1320 | | using Base::Base; |
1321 | | using ValueType = StringRef; |
1322 | | |
1323 | | static OpaqueElementsAttr get(Dialect *dialect, ShapedType type, |
1324 | | StringRef bytes); |
1325 | | |
1326 | | StringRef getValue() const; |
1327 | | |
1328 | | /// Return the value at the given index. The 'index' is expected to refer to a |
1329 | | /// valid element. |
1330 | | Attribute getValue(ArrayRef<uint64_t> index) const; |
1331 | | |
1332 | | /// Decodes the attribute value using dialect-specific decoding hook. |
1333 | | /// Returns false if decoding is successful. If not, returns true and leaves |
1334 | | /// 'result' argument unspecified. |
1335 | | bool decode(ElementsAttr &result); |
1336 | | |
1337 | | /// Returns dialect associated with this opaque constant. |
1338 | | Dialect *getDialect() const; |
1339 | | |
1340 | | /// Method for support type inquiry through isa, cast and dyn_cast. |
1341 | 0 | static bool kindof(unsigned kind) { |
1342 | 0 | return kind == StandardAttributes::OpaqueElements; |
1343 | 0 | } |
1344 | | }; |
1345 | | |
1346 | | /// An attribute that represents a reference to a sparse vector or tensor |
1347 | | /// object. |
1348 | | /// |
1349 | | /// This class uses COO (coordinate list) encoding to represent the sparse |
1350 | | /// elements in an element attribute. Specifically, the sparse vector/tensor |
1351 | | /// stores the indices and values as two separate dense elements attributes of |
1352 | | /// tensor type (even if the sparse attribute is of vector type, in order to |
1353 | | /// support empty lists). The dense elements attribute indices is a 2-D tensor |
1354 | | /// of 64-bit integer elements with shape [N, ndims], which specifies the |
1355 | | /// indices of the elements in the sparse tensor that contains nonzero values. |
1356 | | /// The dense elements attribute values is a 1-D tensor with shape [N], and it |
1357 | | /// supplies the corresponding values for the indices. |
1358 | | /// |
1359 | | /// For example, |
1360 | | /// `sparse<tensor<3x4xi32>, [[0, 0], [1, 2]], [1, 5]>` represents tensor |
1361 | | /// [[1, 0, 0, 0], |
1362 | | /// [0, 0, 5, 0], |
1363 | | /// [0, 0, 0, 0]]. |
1364 | | class SparseElementsAttr |
1365 | | : public Attribute::AttrBase<SparseElementsAttr, ElementsAttr, |
1366 | | detail::SparseElementsAttributeStorage> { |
1367 | | public: |
1368 | | using Base::Base; |
1369 | | |
1370 | | template <typename T> |
1371 | | using iterator = |
1372 | | llvm::mapped_iterator<llvm::detail::value_sequence_iterator<ptrdiff_t>, |
1373 | | std::function<T(ptrdiff_t)>>; |
1374 | | |
1375 | | /// 'type' must be a vector or tensor with static shape. |
1376 | | static SparseElementsAttr get(ShapedType type, DenseElementsAttr indices, |
1377 | | DenseElementsAttr values); |
1378 | | |
1379 | | DenseIntElementsAttr getIndices() const; |
1380 | | |
1381 | | DenseElementsAttr getValues() const; |
1382 | | |
1383 | | /// Return the values of this attribute in the form of the given type 'T'. 'T' |
1384 | | /// may be any of Attribute, APInt, APFloat, c++ integer/float types, etc. |
1385 | 0 | template <typename T> llvm::iterator_range<iterator<T>> getValues() const { |
1386 | 0 | auto zeroValue = getZeroValue<T>(); |
1387 | 0 | auto valueIt = getValues().getValues<T>().begin(); |
1388 | 0 | const std::vector<ptrdiff_t> flatSparseIndices(getFlattenedSparseIndices()); |
1389 | 0 | // TODO(riverriddle): Move-capture flatSparseIndices when c++14 is |
1390 | 0 | // available. |
1391 | 0 | std::function<T(ptrdiff_t)> mapFn = [=](ptrdiff_t index) { |
1392 | 0 | // Try to map the current index to one of the sparse indices. |
1393 | 0 | for (unsigned i = 0, e = flatSparseIndices.size(); i != e; ++i) |
1394 | 0 | if (flatSparseIndices[i] == index) |
1395 | 0 | return *std::next(valueIt, i); |
1396 | 0 | // Otherwise, return the zero value. |
1397 | 0 | return zeroValue; |
1398 | 0 | }; Unexecuted instantiation: _ZZNK4mlir18SparseElementsAttr9getValuesIN4llvm7APFloatEEENS2_14iterator_rangeINS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFT_lEEDTclclsr3stdE7declvalISC_EEdeclL_ZSt7declvalIS8_EDTcl9__declvalISA_ELi0EEEvEEEEEEEEvENKUllE_clEl Unexecuted instantiation: _ZZNK4mlir18SparseElementsAttr9getValuesIN4llvm5APIntEEENS2_14iterator_rangeINS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFT_lEEDTclclsr3stdE7declvalISC_EEdeclL_ZSt7declvalIS8_EDTcl9__declvalISA_ELi0EEEvEEEEEEEEvENKUllE_clEl |
1399 | 0 | return llvm::map_range(llvm::seq<ptrdiff_t>(0, getNumElements()), mapFn); |
1400 | 0 | } Unexecuted instantiation: _ZNK4mlir18SparseElementsAttr9getValuesIN4llvm7APFloatEEENS2_14iterator_rangeINS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFT_lEEDTclclsr3stdE7declvalISC_EEdeclL_ZSt7declvalIS8_EDTcl9__declvalISA_ELi0EEEvEEEEEEEEv Unexecuted instantiation: _ZNK4mlir18SparseElementsAttr9getValuesIN4llvm5APIntEEENS2_14iterator_rangeINS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFT_lEEDTclclsr3stdE7declvalISC_EEdeclL_ZSt7declvalIS8_EDTcl9__declvalISA_ELi0EEEvEEEEEEEEv |
1401 | | |
1402 | | /// Return the value of the element at the given index. The 'index' is |
1403 | | /// expected to refer to a valid element. |
1404 | | Attribute getValue(ArrayRef<uint64_t> index) const; |
1405 | | |
1406 | | /// Method for support type inquiry through isa, cast and dyn_cast. |
1407 | 0 | static bool kindof(unsigned kind) { |
1408 | 0 | return kind == StandardAttributes::SparseElements; |
1409 | 0 | } |
1410 | | |
1411 | | private: |
1412 | | /// Get a zero APFloat for the given sparse attribute. |
1413 | | APFloat getZeroAPFloat() const; |
1414 | | |
1415 | | /// Get a zero APInt for the given sparse attribute. |
1416 | | APInt getZeroAPInt() const; |
1417 | | |
1418 | | /// Get a zero attribute for the given sparse attribute. |
1419 | | Attribute getZeroAttr() const; |
1420 | | |
1421 | | /// Utility methods to generate a zero value of some type 'T'. This is used by |
1422 | | /// the 'iterator' class. |
1423 | | /// Get a zero for a given attribute type. |
1424 | | template <typename T> |
1425 | | typename std::enable_if<std::is_base_of<Attribute, T>::value, T>::type |
1426 | | getZeroValue() const { |
1427 | | return getZeroAttr().template cast<T>(); |
1428 | | } |
1429 | | /// Get a zero for an APInt. |
1430 | | template <typename T> |
1431 | | typename std::enable_if<std::is_same<APInt, T>::value, T>::type |
1432 | 0 | getZeroValue() const { |
1433 | 0 | return getZeroAPInt(); |
1434 | 0 | } |
1435 | | template <typename T> |
1436 | | typename std::enable_if<std::is_same<std::complex<APInt>, T>::value, T>::type |
1437 | | getZeroValue() const { |
1438 | | APInt intZero = getZeroAPInt(); |
1439 | | return {intZero, intZero}; |
1440 | | } |
1441 | | /// Get a zero for an APFloat. |
1442 | | template <typename T> |
1443 | | typename std::enable_if<std::is_same<APFloat, T>::value, T>::type |
1444 | 0 | getZeroValue() const { |
1445 | 0 | return getZeroAPFloat(); |
1446 | 0 | } |
1447 | | template <typename T> |
1448 | | typename std::enable_if<std::is_same<std::complex<APFloat>, T>::value, |
1449 | | T>::type |
1450 | | getZeroValue() const { |
1451 | | APFloat floatZero = getZeroAPFloat(); |
1452 | | return {floatZero, floatZero}; |
1453 | | } |
1454 | | |
1455 | | /// Get a zero for an C++ integer, float, StringRef, or complex type. |
1456 | | template <typename T> |
1457 | | typename std::enable_if< |
1458 | | std::numeric_limits<T>::is_integer || |
1459 | | llvm::is_one_of<T, float, double, StringRef>::value || |
1460 | | (detail::is_complex_t<T>::value && |
1461 | | !llvm::is_one_of<T, std::complex<APInt>, |
1462 | | std::complex<APFloat>>::value), |
1463 | | T>::type |
1464 | | getZeroValue() const { |
1465 | | return T(); |
1466 | | } |
1467 | | |
1468 | | /// Flatten, and return, all of the sparse indices in this attribute in |
1469 | | /// row-major order. |
1470 | | std::vector<ptrdiff_t> getFlattenedSparseIndices() const; |
1471 | | }; |
1472 | | |
1473 | | /// An attribute that represents a reference to a splat vector or tensor |
1474 | | /// constant, meaning all of the elements have the same value. |
1475 | | class SplatElementsAttr : public DenseElementsAttr { |
1476 | | public: |
1477 | | using DenseElementsAttr::DenseElementsAttr; |
1478 | | |
1479 | | /// Method for support type inquiry through isa, cast and dyn_cast. |
1480 | 0 | static bool classof(Attribute attr) { |
1481 | 0 | auto denseAttr = attr.dyn_cast<DenseElementsAttr>(); |
1482 | 0 | return denseAttr && denseAttr.isSplat(); |
1483 | 0 | } |
1484 | | }; |
1485 | | |
1486 | | namespace detail { |
1487 | | /// This class represents a general iterator over the values of an ElementsAttr. |
1488 | | /// It supports all subclasses aside from OpaqueElementsAttr. |
1489 | | template <typename T> |
1490 | | class ElementsAttrIterator |
1491 | | : public llvm::iterator_facade_base<ElementsAttrIterator<T>, |
1492 | | std::random_access_iterator_tag, T, |
1493 | | std::ptrdiff_t, T, T> { |
1494 | | // NOTE: We use a dummy enable_if here because MSVC cannot use 'decltype' |
1495 | | // inside of a conversion operator. |
1496 | | using DenseIteratorT = typename std::enable_if< |
1497 | | true, |
1498 | | decltype(std::declval<DenseElementsAttr>().getValues<T>().begin())>::type; |
1499 | | using SparseIteratorT = SparseElementsAttr::iterator<T>; |
1500 | | |
1501 | | /// A union containing the specific iterators for each derived attribute kind. |
1502 | | union Iterator { |
1503 | 0 | Iterator(DenseIteratorT &&it) : denseIt(std::move(it)) {} Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE8IteratorC2EONS_17DenseElementsAttr20FloatElementIteratorE Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE8IteratorC2EONS_17DenseElementsAttr18IntElementIteratorE |
1504 | 0 | Iterator(SparseIteratorT &&it) : sparseIt(std::move(it)) {} Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE8IteratorC2EONS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFS3_lEES3_EE Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE8IteratorC2EONS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFS3_lEES3_EE |
1505 | 0 | Iterator() {} Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE8IteratorC2Ev Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE8IteratorC2Ev |
1506 | 0 | ~Iterator() {} Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE8IteratorD2Ev Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE8IteratorD2Ev |
1507 | | |
1508 | 0 | operator const DenseIteratorT &() const { return denseIt; } Unexecuted instantiation: _ZNK4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE8IteratorcvRKNS_17DenseElementsAttr20FloatElementIteratorEEv Unexecuted instantiation: _ZNK4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE8IteratorcvRKNS_17DenseElementsAttr18IntElementIteratorEEv |
1509 | 0 | operator const SparseIteratorT &() const { return sparseIt; } Unexecuted instantiation: _ZNK4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE8IteratorcvRKNS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFS3_lEES3_EEEv Unexecuted instantiation: _ZNK4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE8IteratorcvRKNS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFS3_lEES3_EEEv |
1510 | 0 | operator DenseIteratorT &() { return denseIt; } Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE8IteratorcvRNS_17DenseElementsAttr20FloatElementIteratorEEv Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE8IteratorcvRNS_17DenseElementsAttr18IntElementIteratorEEv |
1511 | 0 | operator SparseIteratorT &() { return sparseIt; } Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE8IteratorcvRNS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFS3_lEES3_EEEv Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE8IteratorcvRNS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFS3_lEES3_EEEv |
1512 | | |
1513 | | /// An instance of a dense elements iterator. |
1514 | | DenseIteratorT denseIt; |
1515 | | /// An instance of a sparse elements iterator. |
1516 | | SparseIteratorT sparseIt; |
1517 | | }; |
1518 | | |
1519 | | /// Utility method to process a functor on each of the internal iterator |
1520 | | /// types. |
1521 | | template <typename RetT, template <typename> class ProcessFn, |
1522 | | typename... Args> |
1523 | 0 | RetT process(Args &... args) const { |
1524 | 0 | switch (attrKind) { |
1525 | 0 | case StandardAttributes::DenseIntOrFPElements: |
1526 | 0 | return ProcessFn<DenseIteratorT>()(args...); |
1527 | 0 | case StandardAttributes::SparseElements: |
1528 | 0 | return ProcessFn<SparseIteratorT>()(args...); |
1529 | 0 | } |
1530 | 0 | llvm_unreachable("unexpected attribute kind"); |
1531 | 0 | } Unexecuted instantiation: _ZNK4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE7processIvNS4_13ConstructIterEJNS4_8IteratorEKS7_EEET_DpRT1_ Unexecuted instantiation: _ZNK4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE7processIS3_NS4_11DereferenceEJNS4_8IteratorEEEET_DpRT1_ Unexecuted instantiation: _ZNK4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE7processIvNS4_10PlusAssignEJNS4_8IteratorElEEET_DpRT1_ Unexecuted instantiation: _ZNK4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE7processIvNS4_12DestructIterEJNS4_8IteratorEEEET_DpRT1_ Unexecuted instantiation: _ZNK4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE7processIvNS4_13ConstructIterEJNS4_8IteratorEKS7_EEET_DpRT1_ Unexecuted instantiation: _ZNK4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE7processIS3_NS4_11DereferenceEJNS4_8IteratorEEEET_DpRT1_ Unexecuted instantiation: _ZNK4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE7processIvNS4_10PlusAssignEJNS4_8IteratorElEEET_DpRT1_ Unexecuted instantiation: _ZNK4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE7processIvNS4_12DestructIterEJNS4_8IteratorEEEET_DpRT1_ |
1532 | | |
1533 | | /// Utility functors used to generically implement the iterators methods. |
1534 | | template <typename ItT> struct PlusAssign { |
1535 | 0 | void operator()(ItT &it, ptrdiff_t offset) { it += offset; } Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE10PlusAssignINS_17DenseElementsAttr20FloatElementIteratorEEclERS7_l Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE10PlusAssignINS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFS3_lEES3_EEEclERSD_l Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE10PlusAssignINS_17DenseElementsAttr18IntElementIteratorEEclERS7_l Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE10PlusAssignINS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFS3_lEES3_EEEclERSD_l |
1536 | | }; |
1537 | | template <typename ItT> struct Minus { |
1538 | | ptrdiff_t operator()(const ItT &lhs, const ItT &rhs) { return lhs - rhs; } |
1539 | | }; |
1540 | | template <typename ItT> struct MinusAssign { |
1541 | | void operator()(ItT &it, ptrdiff_t offset) { it -= offset; } |
1542 | | }; |
1543 | | template <typename ItT> struct Dereference { |
1544 | 0 | T operator()(ItT &it) { return *it; } Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE11DereferenceINS_17DenseElementsAttr20FloatElementIteratorEEclERS7_ Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE11DereferenceINS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFS3_lEES3_EEEclERSD_ Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE11DereferenceINS_17DenseElementsAttr18IntElementIteratorEEclERS7_ Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE11DereferenceINS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFS3_lEES3_EEEclERSD_ |
1545 | | }; |
1546 | | template <typename ItT> struct ConstructIter { |
1547 | 0 | void operator()(ItT &dest, const ItT &it) { ::new (&dest) ItT(it); } Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE13ConstructIterINS_17DenseElementsAttr20FloatElementIteratorEEclERS7_RKS7_ Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE13ConstructIterINS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFS3_lEES3_EEEclERSD_RKSD_ Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE13ConstructIterINS_17DenseElementsAttr18IntElementIteratorEEclERS7_RKS7_ Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE13ConstructIterINS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFS3_lEES3_EEEclERSD_RKSD_ |
1548 | | }; |
1549 | | template <typename ItT> struct DestructIter { |
1550 | 0 | void operator()(ItT &it) { it.~ItT(); } Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE12DestructIterINS_17DenseElementsAttr20FloatElementIteratorEEclERS7_ Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEE12DestructIterINS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFS3_lEES3_EEEclERSD_ Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE12DestructIterINS_17DenseElementsAttr18IntElementIteratorEEclERS7_ Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEE12DestructIterINS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFS3_lEES3_EEEclERSD_ |
1551 | | }; |
1552 | | |
1553 | | public: |
1554 | | ElementsAttrIterator(const ElementsAttrIterator<T> &rhs) |
1555 | 0 | : attrKind(rhs.attrKind) { |
1556 | 0 | process<void, ConstructIter>(it, rhs.it); |
1557 | 0 | } Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEEC2ERKS4_ Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEEC2ERKS4_ |
1558 | 0 | ~ElementsAttrIterator() { process<void, DestructIter>(it); } Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEED2Ev Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEED2Ev |
1559 | | |
1560 | | /// Methods necessary to support random access iteration. |
1561 | | ptrdiff_t operator-(const ElementsAttrIterator<T> &rhs) const { |
1562 | | assert(attrKind == rhs.attrKind && "incompatible iterators"); |
1563 | | return process<ptrdiff_t, Minus>(it, rhs.it); |
1564 | | } |
1565 | | bool operator==(const ElementsAttrIterator<T> &rhs) const { |
1566 | | return rhs.attrKind == attrKind && process<bool, std::equal_to>(it, rhs.it); |
1567 | | } |
1568 | | bool operator<(const ElementsAttrIterator<T> &rhs) const { |
1569 | | assert(attrKind == rhs.attrKind && "incompatible iterators"); |
1570 | | return process<bool, std::less>(it, rhs.it); |
1571 | | } |
1572 | 0 | ElementsAttrIterator<T> &operator+=(ptrdiff_t offset) { |
1573 | 0 | process<void, PlusAssign>(it, offset); |
1574 | 0 | return *this; |
1575 | 0 | } Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEEpLEl Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEEpLEl |
1576 | | ElementsAttrIterator<T> &operator-=(ptrdiff_t offset) { |
1577 | | process<void, MinusAssign>(it, offset); |
1578 | | return *this; |
1579 | | } |
1580 | | |
1581 | | /// Dereference the iterator at the current index. |
1582 | 0 | T operator*() { return process<T, Dereference>(it); } Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEEdeEv Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEEdeEv |
1583 | | |
1584 | | private: |
1585 | | template <typename IteratorT> |
1586 | | ElementsAttrIterator(unsigned attrKind, IteratorT &&it) |
1587 | 0 | : attrKind(attrKind), it(std::forward<IteratorT>(it)) {} Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEEC2INS_17DenseElementsAttr20FloatElementIteratorEEEjOT_ Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm7APFloatEEC2INS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFS3_lEES3_EEEEjOT_ Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEEC2INS_17DenseElementsAttr18IntElementIteratorEEEjOT_ Unexecuted instantiation: _ZN4mlir6detail20ElementsAttrIteratorIN4llvm5APIntEEC2INS2_15mapped_iteratorINS2_6detail23value_sequence_iteratorIlEESt8functionIFS3_lEES3_EEEEjOT_ |
1588 | | |
1589 | | /// Allow accessing the constructor. |
1590 | | friend ElementsAttr; |
1591 | | |
1592 | | /// The kind of derived elements attribute. |
1593 | | unsigned attrKind; |
1594 | | |
1595 | | /// A union containing the specific iterators for each derived kind. |
1596 | | Iterator it; |
1597 | | }; |
1598 | | |
1599 | | template <typename T> |
1600 | | class ElementsAttrRange : public llvm::iterator_range<ElementsAttrIterator<T>> { |
1601 | | using llvm::iterator_range<ElementsAttrIterator<T>>::iterator_range; |
1602 | | }; |
1603 | | } // namespace detail |
1604 | | |
1605 | | /// Return the elements of this attribute as a value of type 'T'. |
1606 | | template <typename T> |
1607 | 0 | auto ElementsAttr::getValues() const -> iterator_range<T> { |
1608 | 0 | if (DenseElementsAttr denseAttr = dyn_cast<DenseElementsAttr>()) { |
1609 | 0 | auto values = denseAttr.getValues<T>(); |
1610 | 0 | return {iterator<T>(getKind(), values.begin()), |
1611 | 0 | iterator<T>(getKind(), values.end())}; |
1612 | 0 | } |
1613 | 0 | if (SparseElementsAttr sparseAttr = dyn_cast<SparseElementsAttr>()) { |
1614 | 0 | auto values = sparseAttr.getValues<T>(); |
1615 | 0 | return {iterator<T>(getKind(), values.begin()), |
1616 | 0 | iterator<T>(getKind(), values.end())}; |
1617 | 0 | } |
1618 | 0 | llvm_unreachable("unexpected attribute kind"); |
1619 | 0 | } Unexecuted instantiation: _ZNK4mlir12ElementsAttr9getValuesIN4llvm7APFloatEEENS_6detail17ElementsAttrRangeIT_EEv Unexecuted instantiation: _ZNK4mlir12ElementsAttr9getValuesIN4llvm5APIntEEENS_6detail17ElementsAttrRangeIT_EEv |
1620 | | |
1621 | | //===----------------------------------------------------------------------===// |
1622 | | // Attributes Utils |
1623 | | //===----------------------------------------------------------------------===// |
1624 | | |
1625 | 0 | template <typename U> bool Attribute::isa() const { |
1626 | 0 | assert(impl && "isa<> used on a null attribute."); |
1627 | 0 | return U::classof(*this); |
1628 | 0 | } Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_13SymbolRefAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_17DenseElementsAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_11IntegerAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_13AffineMapAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_9ArrayAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_9FloatAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaIS0_EEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_14IntegerSetAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_8BoolAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_14DictionaryAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_8TypeAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_17SplatElementsAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_18SparseElementsAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_12ElementsAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_8UnitAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_10StringAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_17FlatSymbolRefAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_20DenseIntElementsAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_10OpaqueAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_18OpaqueElementsAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_24DenseIntOrFPElementsAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_23DenseStringElementsAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_9OpaqueLocEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_14FileLineColLocEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_7NameLocEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_10UnknownLocEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_11CallSiteLocEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_8FusedLocEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_12LocationAttrEEEbv Unexecuted instantiation: _ZNK4mlir9Attribute3isaINS_19DenseFPElementsAttrEEEbv |
1629 | 0 | template <typename U> U Attribute::dyn_cast() const { |
1630 | 0 | return isa<U>() ? U(impl) : U(nullptr); |
1631 | 0 | } Unexecuted instantiation: _ZNK4mlir9Attribute8dyn_castINS_13SymbolRefAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute8dyn_castINS_17DenseElementsAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute8dyn_castIS0_EET_v Unexecuted instantiation: _ZNK4mlir9Attribute8dyn_castINS_13AffineMapAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute8dyn_castINS_11IntegerAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute8dyn_castINS_14IntegerSetAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute8dyn_castINS_17SplatElementsAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute8dyn_castINS_17FlatSymbolRefAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute8dyn_castINS_18SparseElementsAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute8dyn_castINS_12ElementsAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute8dyn_castINS_10StringAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute8dyn_castINS_23DenseStringElementsAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute8dyn_castINS_9ArrayAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute8dyn_castINS_8TypeAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute8dyn_castINS_8FusedLocEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute8dyn_castINS_14DictionaryAttrEEET_v |
1632 | 0 | template <typename U> U Attribute::dyn_cast_or_null() const { |
1633 | 0 | return (impl && isa<U>()) ? U(impl) : U(nullptr); |
1634 | 0 | } Unexecuted instantiation: _ZNK4mlir9Attribute16dyn_cast_or_nullINS_11IntegerAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute16dyn_cast_or_nullINS_13SymbolRefAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute16dyn_cast_or_nullINS_9FloatAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute16dyn_cast_or_nullINS_14IntegerSetAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute16dyn_cast_or_nullINS_13AffineMapAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute16dyn_cast_or_nullINS_14DictionaryAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute16dyn_cast_or_nullINS_8TypeAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute16dyn_cast_or_nullINS_17FlatSymbolRefAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute16dyn_cast_or_nullINS_8BoolAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute16dyn_cast_or_nullINS_17SplatElementsAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute16dyn_cast_or_nullINS_20DenseIntElementsAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute16dyn_cast_or_nullINS_10StringAttrEEET_v |
1635 | 0 | template <typename U> U Attribute::cast() const { |
1636 | 0 | assert(isa<U>()); |
1637 | 0 | return U(impl); |
1638 | 0 | } Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_13SymbolRefAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_11IntegerAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_13AffineMapAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_9ArrayAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_8BoolAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_9FloatAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_17SplatElementsAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_12ElementsAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_17FlatSymbolRefAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_20DenseIntElementsAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castIS0_EET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_10OpaqueAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_14DictionaryAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_10StringAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_14IntegerSetAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_8TypeAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_18OpaqueElementsAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_24DenseIntOrFPElementsAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_23DenseStringElementsAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_18SparseElementsAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_9OpaqueLocEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_14FileLineColLocEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_7NameLocEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_11CallSiteLocEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_8FusedLocEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_12LocationAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_17DenseElementsAttrEEET_v Unexecuted instantiation: _ZNK4mlir9Attribute4castINS_19DenseFPElementsAttrEEET_v |
1639 | | |
1640 | | // Make Attribute hashable. |
1641 | 0 | inline ::llvm::hash_code hash_value(Attribute arg) { |
1642 | 0 | return ::llvm::hash_value(arg.impl); |
1643 | 0 | } |
1644 | | |
1645 | | //===----------------------------------------------------------------------===// |
1646 | | // MutableDictionaryAttr |
1647 | | //===----------------------------------------------------------------------===// |
1648 | | |
1649 | | /// A MutableDictionaryAttr is a mutable wrapper around a DictionaryAttr. It |
1650 | | /// provides additional interfaces for adding, removing, replacing attributes |
1651 | | /// within a DictionaryAttr. |
1652 | | /// |
1653 | | /// We assume there will be relatively few attributes on a given operation |
1654 | | /// (maybe a dozen or so, but not hundreds or thousands) so we use linear |
1655 | | /// searches for everything. |
1656 | | class MutableDictionaryAttr { |
1657 | | public: |
1658 | | MutableDictionaryAttr(DictionaryAttr attrs = nullptr) |
1659 | 0 | : attrs((attrs && !attrs.empty()) ? attrs : nullptr) {} |
1660 | | MutableDictionaryAttr(ArrayRef<NamedAttribute> attributes); |
1661 | | |
1662 | 0 | bool operator!=(const MutableDictionaryAttr &other) const { |
1663 | 0 | return !(*this == other); |
1664 | 0 | } |
1665 | 0 | bool operator==(const MutableDictionaryAttr &other) const { |
1666 | 0 | return attrs == other.attrs; |
1667 | 0 | } |
1668 | | |
1669 | | /// Return the underlying dictionary attribute. |
1670 | | DictionaryAttr getDictionary(MLIRContext *context) const; |
1671 | | |
1672 | | /// Return all of the attributes on this operation. |
1673 | | ArrayRef<NamedAttribute> getAttrs() const; |
1674 | | |
1675 | | /// Replace the held attributes with ones provided in 'newAttrs'. |
1676 | | void setAttrs(ArrayRef<NamedAttribute> attributes); |
1677 | | |
1678 | | /// Return the specified attribute if present, null otherwise. |
1679 | | Attribute get(StringRef name) const; |
1680 | | Attribute get(Identifier name) const; |
1681 | | |
1682 | | /// Return the specified named attribute if present, None otherwise. |
1683 | | Optional<NamedAttribute> getNamed(StringRef name) const; |
1684 | | Optional<NamedAttribute> getNamed(Identifier name) const; |
1685 | | |
1686 | | /// If the an attribute exists with the specified name, change it to the new |
1687 | | /// value. Otherwise, add a new attribute with the specified name/value. |
1688 | | void set(Identifier name, Attribute value); |
1689 | | |
1690 | | enum class RemoveResult { Removed, NotFound }; |
1691 | | |
1692 | | /// Remove the attribute with the specified name if it exists. The return |
1693 | | /// value indicates whether the attribute was present or not. |
1694 | | RemoveResult remove(Identifier name); |
1695 | | |
1696 | 0 | bool empty() const { return attrs == nullptr; } |
1697 | | |
1698 | | private: |
1699 | | friend ::llvm::hash_code hash_value(const MutableDictionaryAttr &arg); |
1700 | | |
1701 | | DictionaryAttr attrs; |
1702 | | }; |
1703 | | |
1704 | 0 | inline ::llvm::hash_code hash_value(const MutableDictionaryAttr &arg) { |
1705 | 0 | if (!arg.attrs) |
1706 | 0 | return ::llvm::hash_value((void *)nullptr); |
1707 | 0 | return hash_value(arg.attrs); |
1708 | 0 | } |
1709 | | |
1710 | | } // end namespace mlir. |
1711 | | |
1712 | | namespace llvm { |
1713 | | |
1714 | | // Attribute hash just like pointers. |
1715 | | template <> struct DenseMapInfo<mlir::Attribute> { |
1716 | 0 | static mlir::Attribute getEmptyKey() { |
1717 | 0 | auto pointer = llvm::DenseMapInfo<void *>::getEmptyKey(); |
1718 | 0 | return mlir::Attribute(static_cast<mlir::Attribute::ImplType *>(pointer)); |
1719 | 0 | } |
1720 | 0 | static mlir::Attribute getTombstoneKey() { |
1721 | 0 | auto pointer = llvm::DenseMapInfo<void *>::getTombstoneKey(); |
1722 | 0 | return mlir::Attribute(static_cast<mlir::Attribute::ImplType *>(pointer)); |
1723 | 0 | } |
1724 | 0 | static unsigned getHashValue(mlir::Attribute val) { |
1725 | 0 | return mlir::hash_value(val); |
1726 | 0 | } |
1727 | 0 | static bool isEqual(mlir::Attribute LHS, mlir::Attribute RHS) { |
1728 | 0 | return LHS == RHS; |
1729 | 0 | } |
1730 | | }; |
1731 | | |
1732 | | /// Allow LLVM to steal the low bits of Attributes. |
1733 | | template <> struct PointerLikeTypeTraits<mlir::Attribute> { |
1734 | 0 | static inline void *getAsVoidPointer(mlir::Attribute attr) { |
1735 | 0 | return const_cast<void *>(attr.getAsOpaquePointer()); |
1736 | 0 | } |
1737 | 0 | static inline mlir::Attribute getFromVoidPointer(void *ptr) { |
1738 | 0 | return mlir::Attribute::getFromOpaquePointer(ptr); |
1739 | 0 | } |
1740 | | static constexpr int NumLowBitsAvailable = 3; |
1741 | | }; |
1742 | | |
1743 | | template <> |
1744 | | struct PointerLikeTypeTraits<mlir::SymbolRefAttr> |
1745 | | : public PointerLikeTypeTraits<mlir::Attribute> { |
1746 | 0 | static inline mlir::SymbolRefAttr getFromVoidPointer(void *ptr) { |
1747 | 0 | return PointerLikeTypeTraits<mlir::Attribute>::getFromVoidPointer(ptr) |
1748 | 0 | .cast<mlir::SymbolRefAttr>(); |
1749 | 0 | } |
1750 | | }; |
1751 | | |
1752 | | } // namespace llvm |
1753 | | |
1754 | | #endif |