18f5fa566SLei Zhang //===- Type.cpp - Type class ----------------------------------------------===//
2b2cc2c34SLei Zhang //
330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b2cc2c34SLei Zhang //
756222a06SMehdi Amini //===----------------------------------------------------------------------===//
8b2cc2c34SLei Zhang //
9b2cc2c34SLei Zhang // Type wrapper to simplify using TableGen Record defining a MLIR Type.
10b2cc2c34SLei Zhang //
11b2cc2c34SLei Zhang //===----------------------------------------------------------------------===//
12b2cc2c34SLei Zhang 
13b2cc2c34SLei Zhang #include "mlir/TableGen/Type.h"
14c42cee0cSRiver Riddle #include "mlir/TableGen/Dialect.h"
15c42cee0cSRiver Riddle #include "llvm/ADT/Twine.h"
16ebf190fcSRiver Riddle #include "llvm/ADT/TypeSwitch.h"
17b2cc2c34SLei Zhang #include "llvm/TableGen/Record.h"
18b2cc2c34SLei Zhang 
19b2cc2c34SLei Zhang using namespace mlir;
2027e8efedSJacques Pienaar using namespace mlir::tblgen;
21b2cc2c34SLei Zhang 
TypeConstraint(const llvm::DefInit * init)2227e8efedSJacques Pienaar TypeConstraint::TypeConstraint(const llvm::DefInit *init)
238f5fa566SLei Zhang     : TypeConstraint(init->getDef()) {}
2444e9869fSAlex Zinenko 
isOptional() const25aba1acc8SRiver Riddle bool TypeConstraint::isOptional() const {
26aba1acc8SRiver Riddle   return def->isSubClassOf("Optional");
27aba1acc8SRiver Riddle }
28aba1acc8SRiver Riddle 
isVariadic() const2927e8efedSJacques Pienaar bool TypeConstraint::isVariadic() const {
30509cd739SJacques Pienaar   return def->isSubClassOf("Variadic");
31509cd739SJacques Pienaar }
3227e8efedSJacques Pienaar 
isVariadicOfVariadic() const33*4e103a12SRiver Riddle bool TypeConstraint::isVariadicOfVariadic() const {
34*4e103a12SRiver Riddle   return def->isSubClassOf("VariadicOfVariadic");
35*4e103a12SRiver Riddle }
36*4e103a12SRiver Riddle 
getVariadicOfVariadicSegmentSizeAttr() const37*4e103a12SRiver Riddle StringRef TypeConstraint::getVariadicOfVariadicSegmentSizeAttr() const {
38*4e103a12SRiver Riddle   assert(isVariadicOfVariadic());
39*4e103a12SRiver Riddle   return def->getValueAsString("segmentAttrName");
40*4e103a12SRiver Riddle }
41*4e103a12SRiver Riddle 
42b3a1d09cSRiver Riddle // Returns the builder call for this constraint if this is a buildable type,
43b3a1d09cSRiver Riddle // returns None otherwise.
getBuilderCall() const44b3a1d09cSRiver Riddle Optional<StringRef> TypeConstraint::getBuilderCall() const {
45b3a1d09cSRiver Riddle   const llvm::Record *baseType = def;
46aba1acc8SRiver Riddle   if (isVariableLength())
47b3a1d09cSRiver Riddle     baseType = baseType->getValueAsDef("baseType");
48b3a1d09cSRiver Riddle 
49fbba6395SRiver Riddle   // Check to see if this type constraint has a builder call.
50fbba6395SRiver Riddle   const llvm::RecordVal *builderCall = baseType->getValue("builderCall");
51fbba6395SRiver Riddle   if (!builderCall || !builderCall->getValue())
52fbba6395SRiver Riddle     return llvm::None;
53fbba6395SRiver Riddle   return TypeSwitch<llvm::Init *, Optional<StringRef>>(builderCall->getValue())
54415fab6fSPaul C. Anagnostopoulos       .Case<llvm::StringInit>([&](auto *init) {
55fbba6395SRiver Riddle         StringRef value = init->getValue();
56fbba6395SRiver Riddle         return value.empty() ? Optional<StringRef>() : value;
57fbba6395SRiver Riddle       })
58fbba6395SRiver Riddle       .Default([](auto *) { return llvm::None; });
59b3a1d09cSRiver Riddle }
60b3a1d09cSRiver Riddle 
619eb3e564SChris Lattner // Return the C++ class name for this type (which may just be ::mlir::Type).
getCPPClassName() const62c42cee0cSRiver Riddle std::string TypeConstraint::getCPPClassName() const {
63c42cee0cSRiver Riddle   StringRef className = def->getValueAsString("cppClassName");
64c42cee0cSRiver Riddle 
65c42cee0cSRiver Riddle   // If the class name is already namespace resolved, use it.
66c42cee0cSRiver Riddle   if (className.contains("::"))
67c42cee0cSRiver Riddle     return className.str();
68c42cee0cSRiver Riddle 
69c42cee0cSRiver Riddle   // Otherwise, check to see if there is a namespace from a dialect to prepend.
70c42cee0cSRiver Riddle   if (const llvm::RecordVal *value = def->getValue("dialect")) {
71c42cee0cSRiver Riddle     Dialect dialect(cast<const llvm::DefInit>(value->getValue())->getDef());
72c42cee0cSRiver Riddle     return (dialect.getCppNamespace() + "::" + className).str();
73c42cee0cSRiver Riddle   }
74c42cee0cSRiver Riddle   return className.str();
759eb3e564SChris Lattner }
769eb3e564SChris Lattner 
Type(const llvm::Record * record)7727e8efedSJacques Pienaar Type::Type(const llvm::Record *record) : TypeConstraint(record) {}
7827e8efedSJacques Pienaar 
getDialect() const7927e8efedSJacques Pienaar Dialect Type::getDialect() const {
8027e8efedSJacques Pienaar   return Dialect(def->getValueAsDef("dialect"));
8127e8efedSJacques Pienaar }
82