19415241cSJakub Kuderski //===- SPIRVParsingUtils.h - MLIR SPIR-V Dialect Parsing Utilities --------===//
29415241cSJakub Kuderski //
39415241cSJakub Kuderski // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
49415241cSJakub Kuderski // See https://llvm.org/LICENSE.txt for license information.
59415241cSJakub Kuderski // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69415241cSJakub Kuderski //
79415241cSJakub Kuderski //===----------------------------------------------------------------------===//
89415241cSJakub Kuderski
99415241cSJakub Kuderski #include "mlir/Dialect/SPIRV/IR/SPIRVAttributes.h"
109415241cSJakub Kuderski #include "mlir/IR/Builders.h"
119415241cSJakub Kuderski #include "mlir/IR/OpDefinition.h"
129415241cSJakub Kuderski #include "mlir/IR/OpImplementation.h"
139415241cSJakub Kuderski
149415241cSJakub Kuderski #include "llvm/ADT/ArrayRef.h"
159415241cSJakub Kuderski #include "llvm/ADT/FunctionExtras.h"
169415241cSJakub Kuderski #include "llvm/ADT/SmallVector.h"
179415241cSJakub Kuderski #include "llvm/ADT/StringRef.h"
189415241cSJakub Kuderski
199415241cSJakub Kuderski #include <type_traits>
209415241cSJakub Kuderski
219415241cSJakub Kuderski namespace mlir::spirv {
229415241cSJakub Kuderski namespace AttrNames {
23*1d5e3b2dStw-ilson
24*1d5e3b2dStw-ilson inline constexpr char kClusterSize[] = "cluster_size"; // no ODS generation
25*1d5e3b2dStw-ilson inline constexpr char kControl[] = "control"; // no ODS generation
26*1d5e3b2dStw-ilson inline constexpr char kFnNameAttrName[] = "fn"; // no ODS generation
27*1d5e3b2dStw-ilson inline constexpr char kSpecIdAttrName[] = "spec_id"; // no ODS generation
28*1d5e3b2dStw-ilson
299415241cSJakub Kuderski } // namespace AttrNames
309415241cSJakub Kuderski
319415241cSJakub Kuderski template <typename Ty>
getStrArrayAttrForEnumList(Builder & builder,ArrayRef<Ty> enumValues,function_ref<StringRef (Ty)> stringifyFn)329415241cSJakub Kuderski ArrayAttr getStrArrayAttrForEnumList(Builder &builder, ArrayRef<Ty> enumValues,
339415241cSJakub Kuderski function_ref<StringRef(Ty)> stringifyFn) {
349415241cSJakub Kuderski if (enumValues.empty()) {
359415241cSJakub Kuderski return nullptr;
369415241cSJakub Kuderski }
379415241cSJakub Kuderski SmallVector<StringRef, 1> enumValStrs;
389415241cSJakub Kuderski enumValStrs.reserve(enumValues.size());
399415241cSJakub Kuderski for (auto val : enumValues) {
409415241cSJakub Kuderski enumValStrs.emplace_back(stringifyFn(val));
419415241cSJakub Kuderski }
429415241cSJakub Kuderski return builder.getStrArrayAttr(enumValStrs);
439415241cSJakub Kuderski }
449415241cSJakub Kuderski
459415241cSJakub Kuderski /// Parses the next keyword in `parser` as an enumerant of the given
469415241cSJakub Kuderski /// `EnumClass`.
479415241cSJakub Kuderski template <typename EnumClass, typename ParserType>
489415241cSJakub Kuderski ParseResult
499415241cSJakub Kuderski parseEnumKeywordAttr(EnumClass &value, ParserType &parser,
509415241cSJakub Kuderski StringRef attrName = spirv::attributeName<EnumClass>()) {
519415241cSJakub Kuderski StringRef keyword;
529415241cSJakub Kuderski SmallVector<NamedAttribute, 1> attr;
539415241cSJakub Kuderski auto loc = parser.getCurrentLocation();
549415241cSJakub Kuderski if (parser.parseKeyword(&keyword))
559415241cSJakub Kuderski return failure();
569415241cSJakub Kuderski
579415241cSJakub Kuderski if (std::optional<EnumClass> attr =
589415241cSJakub Kuderski spirv::symbolizeEnum<EnumClass>(keyword)) {
599415241cSJakub Kuderski value = *attr;
609415241cSJakub Kuderski return success();
619415241cSJakub Kuderski }
629415241cSJakub Kuderski return parser.emitError(loc, "invalid ")
639415241cSJakub Kuderski << attrName << " attribute specification: " << keyword;
649415241cSJakub Kuderski }
659415241cSJakub Kuderski
669415241cSJakub Kuderski /// Parses the next string attribute in `parser` as an enumerant of the given
679415241cSJakub Kuderski /// `EnumClass`.
689415241cSJakub Kuderski template <typename EnumClass>
699415241cSJakub Kuderski ParseResult
709415241cSJakub Kuderski parseEnumStrAttr(EnumClass &value, OpAsmParser &parser,
719415241cSJakub Kuderski StringRef attrName = spirv::attributeName<EnumClass>()) {
729415241cSJakub Kuderski static_assert(std::is_enum_v<EnumClass>);
739415241cSJakub Kuderski Attribute attrVal;
749415241cSJakub Kuderski NamedAttrList attr;
759415241cSJakub Kuderski auto loc = parser.getCurrentLocation();
769415241cSJakub Kuderski if (parser.parseAttribute(attrVal, parser.getBuilder().getNoneType(),
779415241cSJakub Kuderski attrName, attr))
789415241cSJakub Kuderski return failure();
799415241cSJakub Kuderski if (!llvm::isa<StringAttr>(attrVal))
809415241cSJakub Kuderski return parser.emitError(loc, "expected ")
819415241cSJakub Kuderski << attrName << " attribute specified as string";
829415241cSJakub Kuderski auto attrOptional = spirv::symbolizeEnum<EnumClass>(
839415241cSJakub Kuderski llvm::cast<StringAttr>(attrVal).getValue());
849415241cSJakub Kuderski if (!attrOptional)
859415241cSJakub Kuderski return parser.emitError(loc, "invalid ")
869415241cSJakub Kuderski << attrName << " attribute specification: " << attrVal;
879415241cSJakub Kuderski value = *attrOptional;
889415241cSJakub Kuderski return success();
899415241cSJakub Kuderski }
909415241cSJakub Kuderski
919415241cSJakub Kuderski /// Parses the next string attribute in `parser` as an enumerant of the given
929415241cSJakub Kuderski /// `EnumClass` and inserts the enumerant into `state` as an 32-bit integer
939415241cSJakub Kuderski /// attribute with the enum class's name as attribute name.
949415241cSJakub Kuderski template <typename EnumAttrClass,
959415241cSJakub Kuderski typename EnumClass = typename EnumAttrClass::ValueType>
969415241cSJakub Kuderski ParseResult
979415241cSJakub Kuderski parseEnumStrAttr(EnumClass &value, OpAsmParser &parser, OperationState &state,
989415241cSJakub Kuderski StringRef attrName = spirv::attributeName<EnumClass>()) {
999415241cSJakub Kuderski static_assert(std::is_enum_v<EnumClass>);
1009415241cSJakub Kuderski if (parseEnumStrAttr(value, parser, attrName))
1019415241cSJakub Kuderski return failure();
1029415241cSJakub Kuderski state.addAttribute(attrName,
1039415241cSJakub Kuderski parser.getBuilder().getAttr<EnumAttrClass>(value));
1049415241cSJakub Kuderski return success();
1059415241cSJakub Kuderski }
1069415241cSJakub Kuderski
1079415241cSJakub Kuderski /// Parses the next keyword in `parser` as an enumerant of the given `EnumClass`
1089415241cSJakub Kuderski /// and inserts the enumerant into `state` as an 32-bit integer attribute with
1099415241cSJakub Kuderski /// the enum class's name as attribute name.
1109415241cSJakub Kuderski template <typename EnumAttrClass,
1119415241cSJakub Kuderski typename EnumClass = typename EnumAttrClass::ValueType>
1129415241cSJakub Kuderski ParseResult
1139415241cSJakub Kuderski parseEnumKeywordAttr(EnumClass &value, OpAsmParser &parser,
1149415241cSJakub Kuderski OperationState &state,
1159415241cSJakub Kuderski StringRef attrName = spirv::attributeName<EnumClass>()) {
1169415241cSJakub Kuderski static_assert(std::is_enum_v<EnumClass>);
1179415241cSJakub Kuderski if (parseEnumKeywordAttr(value, parser))
1189415241cSJakub Kuderski return failure();
1199415241cSJakub Kuderski state.addAttribute(attrName,
1209415241cSJakub Kuderski parser.getBuilder().getAttr<EnumAttrClass>(value));
1219415241cSJakub Kuderski return success();
1229415241cSJakub Kuderski }
1239415241cSJakub Kuderski
12481b4e7d2Svarconst ParseResult parseVariableDecorations(OpAsmParser &parser,
12581b4e7d2Svarconst OperationState &state);
12681b4e7d2Svarconst
1279415241cSJakub Kuderski } // namespace mlir::spirv
128