1//===- Attribute.cpp - Attribute wrapper class ----------------------------===//
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// Attribute wrapper to simplify using TableGen Record defining a MLIR
10// Attribute.
11//
12//===----------------------------------------------------------------------===//
13
14#include "mlir/TableGen/Operator.h"
15#include "llvm/TableGen/Record.h"
16
17using namespace mlir;
18using namespace mlir::tblgen;
19
20using llvm::DefInit;
21using llvm::Init;
22using llvm::Record;
23using llvm::StringInit;
24
25// Returns the initializer's value as string if the given TableGen initializer
26// is a code or string initializer. Returns the empty StringRef otherwise.
27static StringRef getValueAsString(const Init *init) {
28 if (const auto *str = dyn_cast<StringInit>(Val: init))
29 return str->getValue().trim();
30 return {};
31}
32
33bool AttrConstraint::isSubClassOf(StringRef className) const {
34 return def->isSubClassOf(Name: className);
35}
36
37Attribute::Attribute(const Record *record) : AttrConstraint(record) {
38 assert(record->isSubClassOf("Attr") &&
39 "must be subclass of TableGen 'Attr' class");
40}
41
42Attribute::Attribute(const DefInit *init) : Attribute(init->getDef()) {}
43
44bool Attribute::isDerivedAttr() const { return isSubClassOf(className: "DerivedAttr"); }
45
46bool Attribute::isTypeAttr() const { return isSubClassOf(className: "TypeAttrBase"); }
47
48bool Attribute::isSymbolRefAttr() const {
49 StringRef defName = def->getName();
50 if (defName == "SymbolRefAttr" || defName == "FlatSymbolRefAttr")
51 return true;
52 return isSubClassOf(className: "SymbolRefAttr") || isSubClassOf(className: "FlatSymbolRefAttr");
53}
54
55bool Attribute::isEnumAttr() const { return isSubClassOf(className: "EnumAttrInfo"); }
56
57StringRef Attribute::getStorageType() const {
58 const auto *init = def->getValueInit(FieldName: "storageType");
59 auto type = getValueAsString(init);
60 if (type.empty())
61 return "::mlir::Attribute";
62 return type;
63}
64
65StringRef Attribute::getReturnType() const {
66 const auto *init = def->getValueInit(FieldName: "returnType");
67 return getValueAsString(init);
68}
69
70// Return the type constraint corresponding to the type of this attribute, or
71// std::nullopt if this is not a TypedAttr.
72std::optional<Type> Attribute::getValueType() const {
73 if (const auto *defInit = dyn_cast<DefInit>(Val: def->getValueInit(FieldName: "valueType")))
74 return Type(defInit->getDef());
75 return std::nullopt;
76}
77
78StringRef Attribute::getConvertFromStorageCall() const {
79 const auto *init = def->getValueInit(FieldName: "convertFromStorage");
80 return getValueAsString(init);
81}
82
83bool Attribute::isConstBuildable() const {
84 const auto *init = def->getValueInit(FieldName: "constBuilderCall");
85 return !getValueAsString(init).empty();
86}
87
88StringRef Attribute::getConstBuilderTemplate() const {
89 const auto *init = def->getValueInit(FieldName: "constBuilderCall");
90 return getValueAsString(init);
91}
92
93Attribute Attribute::getBaseAttr() const {
94 if (const auto *defInit = dyn_cast<DefInit>(Val: def->getValueInit(FieldName: "baseAttr"))) {
95 return Attribute(defInit).getBaseAttr();
96 }
97 return *this;
98}
99
100bool Attribute::hasDefaultValue() const {
101 const auto *init = def->getValueInit(FieldName: "defaultValue");
102 return !getValueAsString(init).empty();
103}
104
105StringRef Attribute::getDefaultValue() const {
106 const auto *init = def->getValueInit(FieldName: "defaultValue");
107 return getValueAsString(init);
108}
109
110bool Attribute::isOptional() const { return def->getValueAsBit(FieldName: "isOptional"); }
111
112StringRef Attribute::getAttrDefName() const {
113 if (def->isAnonymous()) {
114 return getBaseAttr().def->getName();
115 }
116 return def->getName();
117}
118
119StringRef Attribute::getDerivedCodeBody() const {
120 assert(isDerivedAttr() && "only derived attribute has 'body' field");
121 return def->getValueAsString(FieldName: "body");
122}
123
124Dialect Attribute::getDialect() const {
125 const llvm::RecordVal *record = def->getValue(Name: "dialect");
126 if (record && record->getValue()) {
127 if (const DefInit *init = dyn_cast<DefInit>(Val: record->getValue()))
128 return Dialect(init->getDef());
129 }
130 return Dialect(nullptr);
131}
132
133const Record &Attribute::getDef() const { return *def; }
134
135ConstantAttr::ConstantAttr(const DefInit *init) : def(init->getDef()) {
136 assert(def->isSubClassOf("ConstantAttr") &&
137 "must be subclass of TableGen 'ConstantAttr' class");
138}
139
140Attribute ConstantAttr::getAttribute() const {
141 return Attribute(def->getValueAsDef(FieldName: "attr"));
142}
143
144StringRef ConstantAttr::getConstantValue() const {
145 return def->getValueAsString(FieldName: "value");
146}
147
148const char * ::mlir::tblgen::inferTypeOpInterface = "InferTypeOpInterface";
149

source code of mlir/lib/TableGen/Attribute.cpp