Coverage Report

Created: 2020-06-26 05:44

/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