diff --git a/flang/examples/CMakeLists.txt b/flang/examples/CMakeLists.txt --- a/flang/examples/CMakeLists.txt +++ b/flang/examples/CMakeLists.txt @@ -8,3 +8,4 @@ ) add_subdirectory(HelloWorld) +add_subdirectory(PrintFlangFunctionNames) diff --git a/flang/examples/PrintFlangFunctionNames/CMakeLists.txt b/flang/examples/PrintFlangFunctionNames/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/flang/examples/PrintFlangFunctionNames/CMakeLists.txt @@ -0,0 +1,5 @@ +add_llvm_library( + flangPrintFunctionNames + MODULE + PrintFlangFunctionNames.cpp +) \ No newline at end of file diff --git a/flang/examples/PrintFlangFunctionNames/PrintFlangFunctionNames.cpp b/flang/examples/PrintFlangFunctionNames/PrintFlangFunctionNames.cpp new file mode 100644 --- /dev/null +++ b/flang/examples/PrintFlangFunctionNames/PrintFlangFunctionNames.cpp @@ -0,0 +1,57 @@ +//===-- PrintFlangFunctionNames.cpp ---------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Small example Flang plugin which walks the Parse Tree using a visitor struct +// that has Post functions for FunctionStmt and SubroutineStmt to count and +// print out the names of the functions and subroutines +// +//===----------------------------------------------------------------------===// + +#include "flang/Frontend/CompilerInstance.h" +#include "flang/Frontend/FrontendActions.h" +#include "flang/Frontend/FrontendPluginRegistry.h" +#include "flang/Parser/dump-parse-tree.h" +#include "flang/Parser/parsing.h" + +using namespace Fortran::frontend; + +class PrintFunctionNamesAction : public PluginParseTreeAction { + + // Visitor struct that defines Pre/Post functions for different types of nodes + struct ParseTreeVisitor { + template bool Pre(const A &) { return true; } + template void Post(const A &) {} + + void Post(const Fortran::parser::FunctionStmt &f) { + llvm::outs() << "Function:\t" + << std::get(f.t).ToString() << "\n"; + fcounter++; + } + void Post(const Fortran::parser::SubroutineStmt &s) { + llvm::outs() << "Subroutine:\t" + << std::get(s.t).ToString() << "\n"; + scounter++; + } + + int fcounter{0}; + int scounter{0}; + }; + + void ExecuteAction() override { + auto &parseTree{instance().parsing().parseTree()}; + + ParseTreeVisitor visitor; + Fortran::parser::Walk(parseTree, visitor); + + llvm::outs() << "\n==== Functions: " << visitor.fcounter << " ====\n"; + llvm::outs() << "==== Subroutines: " << visitor.scounter << " ====\n"; + } +}; + +static FrontendPluginRegistry::Add X( + "print-fns", "Print Function names"); \ No newline at end of file diff --git a/flang/include/flang/Frontend/FrontendActions.h b/flang/include/flang/Frontend/FrontendActions.h --- a/flang/include/flang/Frontend/FrontendActions.h +++ b/flang/include/flang/Frontend/FrontendActions.h @@ -30,10 +30,6 @@ // Custom Consumer Actions //===----------------------------------------------------------------------===// -class PluginParseTreeAction : public FrontendAction { - void ExecuteAction() override; -}; - class InputOutputTestAction : public FrontendAction { void ExecuteAction() override; }; @@ -140,6 +136,10 @@ void ExecuteAction() override; }; +class PluginParseTreeAction : public PrescanAndSemaAction { + void ExecuteAction() override; +}; + } // namespace Fortran::frontend #endif // LLVM_FLANG_FRONTEND_FRONTENDACTIONS_H diff --git a/flang/test/CMakeLists.txt b/flang/test/CMakeLists.txt --- a/flang/test/CMakeLists.txt +++ b/flang/test/CMakeLists.txt @@ -50,7 +50,10 @@ endif() if (FLANG_BUILD_EXAMPLES) - list(APPEND FLANG_TEST_DEPENDS flangHelloWorldPlugin) + list(APPEND FLANG_TEST_DEPENDS + flangHelloWorldPlugin + flangPrintFunctionNames + ) endif () add_custom_target(flang-test-depends DEPENDS ${FLANG_TEST_DEPENDS}) diff --git a/flang/test/Driver/plugin-print-fns.f90 b/flang/test/Driver/plugin-print-fns.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Driver/plugin-print-fns.f90 @@ -0,0 +1,28 @@ +! Check that the Flang Print Function Names example plugin prints out and counts the function and subroutine names +! This requires that the examples are built (FLANG_BUILD_EXAMPLES=ON) + +! REQUIRES: new-flang-driver, plugins, examples, shell + +! RUN: %flang_fc1 -load %llvmshlibdir/flangPrintFunctionNames%pluginext -plugin print-fns %s 2>&1 | FileCheck %s + +!------------------------------------------------ +! EXPECTED OUTPUT: Print names & num of each type +!------------------------------------------------ +! CHECK: Function: func1 +! CHECK-NEXT: Function: func2 +! CHECK-NEXT: Subroutine: routine +! CHECK-EMPTY: +! CHECK-NEXT: ==== Functions: 2 ==== +! CHECK-NEXT: ==== Subroutines: 1 ==== + +!-------------------------- +! INPUT +!-------------------------- +function func1() +end function func1 + +function func2() +end function func2 + +subroutine routine() +end subroutine routine \ No newline at end of file