diff --git a/llvm/include/llvm/TableGen/Parser.h b/llvm/include/llvm/TableGen/Parser.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/TableGen/Parser.h @@ -0,0 +1,39 @@ +//===- llvm/TableGen/Parser.h - tblgen parser entry point -------*- C++ -*-===// +// +// 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 declares an entry point into the tablegen parser for use by tools. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TABLEGEN_PARSER_H +#define LLVM_TABLEGEN_PARSER_H + +#include "llvm/ADT/STLExtras.h" +#include +#include + +namespace llvm { +class MemoryBuffer; +class RecordKeeper; + +/// Peform the tablegen action using the given set of parsed records. Returns +/// true on error, false otherwise. +using TableGenParserFn = function_ref; + +/// Parse the given input buffer containing a tablegen file, invoking the +/// provided parser function with the set of parsed records. All tablegen state +/// is reset after the provided parser function is invoked, i.e., the provided +/// parser function should not maintain references to any tablegen constructs +/// after executing. Returns true on failure, false otherwise. +bool TableGenParseFile(std::unique_ptr Buffer, + std::vector IncludeDirs, + TableGenParserFn ParserFn); + +} // end namespace llvm + +#endif // LLVM_TABLEGEN_PARSER_H diff --git a/llvm/lib/TableGen/CMakeLists.txt b/llvm/lib/TableGen/CMakeLists.txt --- a/llvm/lib/TableGen/CMakeLists.txt +++ b/llvm/lib/TableGen/CMakeLists.txt @@ -3,6 +3,7 @@ Error.cpp JSONBackend.cpp Main.cpp + Parser.cpp Record.cpp SetTheory.cpp StringMatcher.cpp diff --git a/llvm/lib/TableGen/Parser.cpp b/llvm/lib/TableGen/Parser.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/TableGen/Parser.cpp @@ -0,0 +1,38 @@ +//===- Parser.cpp - Top-Level TableGen Parser implementation --------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "llvm/TableGen/Parser.h" +#include "RecordContext.h" +#include "TGParser.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" + +using namespace llvm; + +bool llvm::TableGenParseFile(std::unique_ptr Buffer, + std::vector IncludeDirs, + TableGenParserFn ParserFn) { + RecordKeeper Records; + Records.saveInputFilename(Buffer->getBufferIdentifier().str()); + + SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); + SrcMgr.setIncludeDirs(IncludeDirs); + TGParser Parser(SrcMgr, /*Macros=*/None, Records); + if (Parser.ParseFile()) + return true; + + // Invoke the provided handler function. + if (ParserFn(Records)) + return true; + + // After parsing, reset the tablegen data. + detail::resetTablegenRecordContext(); + SrcMgr = SourceMgr(); + return false; +} 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 @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "llvm/TableGen/Record.h" +#include "RecordContext.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" @@ -93,6 +94,8 @@ ManagedStatic Context; +void llvm::detail::resetTablegenRecordContext() { Context.destroy(); } + //===----------------------------------------------------------------------===// // Type implementations //===----------------------------------------------------------------------===// diff --git a/llvm/lib/TableGen/RecordContext.h b/llvm/lib/TableGen/RecordContext.h new file mode 100644 --- /dev/null +++ b/llvm/lib/TableGen/RecordContext.h @@ -0,0 +1,27 @@ +//===- RecordContext.h - RecordContext implementation ---------------------===// +// +// 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 contains functions for interacting with the tablegen record +// context. +// +//===----------------------------------------------------------------------===// + +namespace llvm { +namespace detail { + +/// Resets the Tablegen record context and all currently parsed record data. +/// Tablegen currently relies on a lot of static data to keep track of parsed +/// records, which accumulates into static fields. This method resets all of +/// that data to enable successive executions of the tablegen parser. +/// FIXME: Ideally tablegen would use a properly scoped (non-static) context, +/// which would remove any need for managing the context in this way. In that +/// case, this method could be removed. +void resetTablegenRecordContext(); + +} // end namespace detail +} // end namespace llvm diff --git a/llvm/unittests/TableGen/CMakeLists.txt b/llvm/unittests/TableGen/CMakeLists.txt --- a/llvm/unittests/TableGen/CMakeLists.txt +++ b/llvm/unittests/TableGen/CMakeLists.txt @@ -10,8 +10,9 @@ add_public_tablegen_target(AutomataTestTableGen) add_llvm_unittest(TableGenTests DISABLE_LLVM_LINK_LLVM_DYLIB - CodeExpanderTest.cpp AutomataTest.cpp + CodeExpanderTest.cpp + ParserEntryPointTest.cpp ) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../utils/TableGen) target_link_libraries(TableGenTests PRIVATE LLVMTableGenGlobalISel LLVMTableGen) diff --git a/llvm/unittests/TableGen/ParserEntryPointTest.cpp b/llvm/unittests/TableGen/ParserEntryPointTest.cpp new file mode 100644 --- /dev/null +++ b/llvm/unittests/TableGen/ParserEntryPointTest.cpp @@ -0,0 +1,39 @@ +//===- unittest/TableGen/ParserEntryPointTest.cpp - Parser tests ----------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/TableGen/Parser.h" +#include "llvm/TableGen/Record.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace llvm; + +TEST(Parser, SanityTest) { + // Simple TableGen source file with a single record. + const char *SimpleTdSource = R"td( + def Foo { + string strField = "value"; + } + )td"; + + auto ProcessFn = [&](const RecordKeeper &Records) { + Record *Foo = Records.getDef("Foo"); + Optional Field = Foo->getValueAsOptionalString("strField"); + EXPECT_TRUE(Field.hasValue()); + EXPECT_EQ(Field.getValue(), "value"); + return false; + }; + + bool ProcessResult = TableGenParseFile( + MemoryBuffer::getMemBuffer(SimpleTdSource, "test_buffer"), + /*IncludeDirs=*/{}, ProcessFn); + EXPECT_FALSE(ProcessResult); +}