diff --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h --- a/llvm/include/llvm/TableGen/Record.h +++ b/llvm/include/llvm/TableGen/Record.h @@ -1640,6 +1640,16 @@ /// or if the value is not a string. StringRef getValueAsString(StringRef FieldName) const; + /// This method looks up the specified field and returns + /// its value as a string, throwing an exception if the field if the value is + /// not a string and llvm::Optional() if the field does not exist. + llvm::Optional getValueAsOptionalString(StringRef FieldName) const; + + /// This method looks up the specified field and returns + /// its value as a string, throwing an exception if the field if the value is + /// not a code block and llvm::Optional() if the field does not exist. + llvm::Optional getValueAsOptionalCode(StringRef FieldName) const; + /// This method looks up the specified field and returns /// its value as a BitsInit, throwing an exception if the field does not exist /// or if the value is not the right type. diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp --- a/llvm/lib/TableGen/Record.cpp +++ b/llvm/lib/TableGen/Record.cpp @@ -2241,18 +2241,43 @@ } StringRef Record::getValueAsString(StringRef FieldName) const { - const RecordVal *R = getValue(FieldName); - if (!R || !R->getValue()) + llvm::Optional S = getValueAsOptionalString(FieldName); + if (!S.hasValue()) PrintFatalError(getLoc(), "Record `" + getName() + "' does not have a field named `" + FieldName + "'!\n"); + return S.getValue(); +} +llvm::Optional +Record::getValueAsOptionalString(StringRef FieldName) const { + const RecordVal *R = getValue(FieldName); + if (!R || !R->getValue()) + return llvm::Optional(); + if (isa(R->getValue())) + return llvm::Optional(); if (StringInit *SI = dyn_cast(R->getValue())) return SI->getValue(); if (CodeInit *CI = dyn_cast(R->getValue())) return CI->getValue(); - PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + FieldName + - "' exists but does not have a string value"); + PrintFatalError(getLoc(), + "Record `" + getName() + "', ` field `" + FieldName + + "' exists but does not have a string initializer!"); +} +llvm::Optional +Record::getValueAsOptionalCode(StringRef FieldName) const { + const RecordVal *R = getValue(FieldName); + if (!R || !R->getValue()) + return llvm::Optional(); + if (isa(R->getValue())) + return llvm::Optional(); + + if (CodeInit *CI = dyn_cast(R->getValue())) + return CI->getValue(); + + PrintFatalError(getLoc(), + "Record `" + getName() + "', field `" + FieldName + + "' exists but does not have a code initializer!"); } BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const { diff --git a/mlir/include/mlir/TableGen/CodeGenHelpers.h b/mlir/include/mlir/TableGen/CodeGenHelpers.h new file mode 100644 --- /dev/null +++ b/mlir/include/mlir/TableGen/CodeGenHelpers.h @@ -0,0 +1,61 @@ +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines common utilities for generating C++ from tablegen +// structures. +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_TABLEGEN_CODEGENHELPERS_H +#define MLIR_TABLEGEN_CODEGENHELPERS_H + +#include "mlir/TableGen/Dialect.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" + +namespace mlir { +namespace tblgen { + +// Simple RAII helper for defining ifdef-undef-endif scopes. +class IfDefScope { +public: + IfDefScope(llvm::StringRef name, llvm::raw_ostream &os) : name(name), os(os) { + os << "#ifdef " << name << "\n" + << "#undef " << name << "\n\n"; + } + ~IfDefScope() { os << "\n#endif // " << name << "\n\n"; } + +private: + llvm::StringRef name; + llvm::raw_ostream &os; +}; + +// A helper RAII class to emit nested namespaces for this op. +class NamespaceEmitter { +public: + NamespaceEmitter(raw_ostream &os, const Dialect &dialect) : os(os) { + if (!dialect) + return; + llvm::SplitString(dialect.getCppNamespace(), namespaces, "::"); + for (StringRef ns : namespaces) + os << "namespace " << ns << " {\n"; + } + + ~NamespaceEmitter() { + for (StringRef ns : llvm::reverse(namespaces)) + os << "} // namespace " << ns << "\n"; + } + +private: + raw_ostream &os; + SmallVector namespaces; +}; + +} // namespace tblgen +} // namespace mlir + +#endif // MLIR_TABLEGEN_CODEGENHELPERS_H diff --git a/mlir/include/mlir/TableGen/Operator.h b/mlir/include/mlir/TableGen/Operator.h --- a/mlir/include/mlir/TableGen/Operator.h +++ b/mlir/include/mlir/TableGen/Operator.h @@ -242,17 +242,6 @@ // debugging purposes. void print(llvm::raw_ostream &os) const; - // A helper RAII class to emit nested namespaces for this op. - class NamespaceEmitter { - public: - NamespaceEmitter(raw_ostream &os, Operator &op); - ~NamespaceEmitter(); - - private: - raw_ostream &os; - SmallVector namespaces; - }; - // Return whether all the result types are known. bool allResultTypesKnown() const { return allResultsHaveKnownTypes; }; diff --git a/mlir/lib/TableGen/Operator.cpp b/mlir/lib/TableGen/Operator.cpp --- a/mlir/lib/TableGen/Operator.cpp +++ b/mlir/lib/TableGen/Operator.cpp @@ -566,21 +566,6 @@ } } -Operator::NamespaceEmitter::NamespaceEmitter(raw_ostream &os, Operator &op) - : os(os) { - auto dialect = op.getDialect(); - if (!dialect) - return; - llvm::SplitString(dialect.getCppNamespace(), namespaces, "::"); - for (StringRef ns : namespaces) - os << "namespace " << ns << " {\n"; -} - -Operator::NamespaceEmitter::~NamespaceEmitter() { - for (StringRef ns : llvm::reverse(namespaces)) - os << "} // namespace " << ns << "\n"; -} - auto Operator::VariableDecoratorIterator::unwrap(llvm::Init *init) -> VariableDecorator { return VariableDecorator(cast(init)->getDef()); diff --git a/mlir/tools/mlir-tblgen/DialectGen.cpp b/mlir/tools/mlir-tblgen/DialectGen.cpp --- a/mlir/tools/mlir-tblgen/DialectGen.cpp +++ b/mlir/tools/mlir-tblgen/DialectGen.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "mlir/TableGen/CodeGenHelpers.h" #include "mlir/TableGen/Format.h" #include "mlir/TableGen/GenInfo.h" #include "mlir/TableGen/Interfaces.h" @@ -155,12 +156,7 @@ } // Emit all nested namespaces. - StringRef cppNamespace = dialect.getCppNamespace(); - llvm::SmallVector namespaces; - llvm::SplitString(cppNamespace, namespaces, "::"); - - for (auto ns : namespaces) - os << "namespace " << ns << " {\n"; + NamespaceEmitter nsEmitter(os, dialect); // Emit the start of the decl. std::string cppName = dialect.getCppClassName(); @@ -188,10 +184,6 @@ // End the dialect decl. os << "};\n"; - - // Close all nested namespaces in reverse order. - for (auto ns : llvm::reverse(namespaces)) - os << "} // namespace " << ns << "\n"; } static bool emitDialectDecls(const llvm::RecordKeeper &recordKeeper, diff --git a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp --- a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp +++ b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "OpFormatGen.h" +#include "mlir/TableGen/CodeGenHelpers.h" #include "mlir/TableGen/Format.h" #include "mlir/TableGen/GenInfo.h" #include "mlir/TableGen/Interfaces.h" @@ -159,23 +160,6 @@ // Op emitter //===----------------------------------------------------------------------===// -namespace { -// Simple RAII helper for defining ifdef-undef-endif scopes. -class IfDefScope { -public: - IfDefScope(StringRef name, raw_ostream &os) : name(name), os(os) { - os << "#ifdef " << name << "\n" - << "#undef " << name << "\n\n"; - } - - ~IfDefScope() { os << "\n#endif // " << name << "\n\n"; } - -private: - StringRef name; - raw_ostream &os; -}; -} // end anonymous namespace - namespace { // Helper class to emit a record into the given output stream. class OpEmitter { @@ -2181,7 +2165,7 @@ os << "#undef GET_OP_FWD_DEFINES\n"; for (auto *def : defs) { Operator op(*def); - Operator::NamespaceEmitter emitter(os, op); + NamespaceEmitter emitter(os, op.getDialect()); os << "class " << op.getCppClassName() << ";\n"; } os << "#endif\n\n"; @@ -2190,7 +2174,7 @@ IfDefScope scope("GET_OP_CLASSES", os); for (auto *def : defs) { Operator op(*def); - Operator::NamespaceEmitter emitter(os, op); + NamespaceEmitter emitter(os, op.getDialect()); if (emitDecl) { os << formatv(opCommentHeader, op.getQualCppClassName(), "declarations"); OpOperandAdaptorEmitter::emitDecl(op, os);