1 //===- Type.cpp - Type 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 // Type wrapper to simplify using TableGen Record defining a MLIR Type.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "mlir/TableGen/Type.h"
14 #include "mlir/TableGen/Dialect.h"
15 #include "llvm/ADT/Twine.h"
16 #include "llvm/ADT/TypeSwitch.h"
17 #include "llvm/TableGen/Record.h"
18 
19 using namespace mlir;
20 using namespace mlir::tblgen;
21 
22 TypeConstraint::TypeConstraint(const llvm::Record *record)
23     : Constraint(Constraint::CK_Type, record) {
24   assert(def->isSubClassOf("TypeConstraint") &&
25          "must be subclass of TableGen 'TypeConstraint' class");
26 }
27 
28 TypeConstraint::TypeConstraint(const llvm::DefInit *init)
29     : TypeConstraint(init->getDef()) {}
30 
31 bool TypeConstraint::isOptional() const {
32   return def->isSubClassOf("Optional");
33 }
34 
35 bool TypeConstraint::isVariadic() const {
36   return def->isSubClassOf("Variadic");
37 }
38 
39 bool TypeConstraint::isVariadicOfVariadic() const {
40   return def->isSubClassOf("VariadicOfVariadic");
41 }
42 
43 StringRef TypeConstraint::getVariadicOfVariadicSegmentSizeAttr() const {
44   assert(isVariadicOfVariadic());
45   return def->getValueAsString("segmentAttrName");
46 }
47 
48 // Returns the builder call for this constraint if this is a buildable type,
49 // returns None otherwise.
50 Optional<StringRef> TypeConstraint::getBuilderCall() const {
51   const llvm::Record *baseType = def;
52   if (isVariableLength())
53     baseType = baseType->getValueAsDef("baseType");
54 
55   // Check to see if this type constraint has a builder call.
56   const llvm::RecordVal *builderCall = baseType->getValue("builderCall");
57   if (!builderCall || !builderCall->getValue())
58     return llvm::None;
59   return TypeSwitch<llvm::Init *, Optional<StringRef>>(builderCall->getValue())
60       .Case<llvm::StringInit>([&](auto *init) {
61         StringRef value = init->getValue();
62         return value.empty() ? Optional<StringRef>() : value;
63       })
64       .Default([](auto *) { return llvm::None; });
65 }
66 
67 // Return the C++ class name for this type (which may just be ::mlir::Type).
68 std::string TypeConstraint::getCPPClassName() const {
69   StringRef className = def->getValueAsString("cppClassName");
70 
71   // If the class name is already namespace resolved, use it.
72   if (className.contains("::"))
73     return className.str();
74 
75   // Otherwise, check to see if there is a namespace from a dialect to prepend.
76   if (const llvm::RecordVal *value = def->getValue("dialect")) {
77     Dialect dialect(cast<const llvm::DefInit>(value->getValue())->getDef());
78     return (dialect.getCppNamespace() + "::" + className).str();
79   }
80   return className.str();
81 }
82 
83 Type::Type(const llvm::Record *record) : TypeConstraint(record) {}
84 
85 StringRef Type::getDescription() const {
86   return def->getValueAsString("description");
87 }
88 
89 Dialect Type::getDialect() const {
90   return Dialect(def->getValueAsDef("dialect"));
91 }
92