diff --git a/flang/docs/FlangDriver.md b/flang/docs/FlangDriver.md --- a/flang/docs/FlangDriver.md +++ b/flang/docs/FlangDriver.md @@ -272,3 +272,78 @@ test as only available on Unix-like systems (i.e. systems that contain a Unix shell). In practice this means that the corresponding test is skipped on Windows. + +# Frontend Driver Plugins +Plugins are an extension to the Frontend Driver that make it possible to run +extra user defined actions, in the form of FrontendActions, during a compilation. +The Flang Plugins are based on how Clang Plugins work. +The process for using Plugins includes: +* Creating a Plugin Shared Object library +* Loading the Plugin library +* Registering the Plugin +* Calling the Plugin + +Plugins are currently only available / been tested on Linux. + +## Creating the Plugin +The two parts required for Plugins to work are: +1. A main class that inherits from `PluginParseTreeAction` +1. Plugin registration + +### A `PluginParseTreeAction` Subclass +The main class of the Plugin will need to inherit from `PluginParseTreeAction` +(defined in `FrontendActions.h`) so that it can have access to the Parse Tree +(referenced through `instance().parsing().parseTree()`). Additionally, like +normal FrontendActions, the Plugin class will need to override the +`ExecuteAction()` method with the implementation of what the Plugin will do. + +### Plugin Registration +The Plugin also needs to have a line for registration, which will add the Plugin +to a registry and allow it to be used. This is done by adding the Plugin class to +the `FrontendPluginRegistry` (see the Registry section below). This is done using: +```cpp +static FrontendPluginRegistry::Add X("plugin-name", "Plugin description"); +``` + +## The Plugin Registry +The registry for Flang Plugins, `FrontendPluginRegistry`, is defined in +`flang/include/flang/Frontend/FrontendPluginRegistry.h`. It is an alias of +`llvm::Registry` of type `PluginParseTreeAction`. It stores the name and +description of each Plugin. + +## Command Line +In order to use Plugins, there are 2 command line options for the Frontend Driver: +* `-load ` for loading the dynamic shared object of the Plugin +* `-plugin ` for calling the registered Plugin + +### The `-load` option +This option has a `` variable, which is the path to the dynamic shared +library Plugin. When used, this option adds the path to a list called `plugins` +in `FrontendOptions`. This list is then iterated through and each of the libraries +are loaded using `llvm::sys::DynamicLibrary::LoadLibraryPermantly()` which uses +`dlopen`. During this stage, the Plugin is registered with the registration line +from the Plugin, storing the name and description. + +### The `-plugin` option +This option has a `` variable, which is the name of the plugin to be used. +This option sets `programAction` in `FrontendOptions` to `PluginAction`. +The Plugin name is stored in `ActionName`, which is also in `FrontendOptions`. +In `ExecuteCompilerInvocation.cpp`, for the `programAction` switch case of +`PluginAction`, it goes through the entries in the +`Fortran::frontend::FrontendPluginRegistry` to find the Plugin name (stored in +`ActionName`). If found, it returns the plugin, otherwise it reports a diagnostic +and returns `nullptr`. + +## Example Plugin +In `flang/example/PrintFlangFunctionNames` is an example Plugin, to demonstrate +using the Parse Tree to print out function names. It has a `CMakeLists.txt` +alongside to build it into a shared object. This uses a Visitor struct, which +defines Pre/Post functions for different types of nodes, to traverse the Parse Tree. + +## Plugin CMake Flag +There is a CMake flag `FLANG_BUILD_EXAMPLES`, which when enabled, builds the +Plugins that are added to the `flang/example` directory and added as a +`sub_directory` to the `flang/examples/CMakeLists.txt`. Additionally, enabling +the flag also allows the example Plugin tests to run. Appending the Plugin to +`FLANG_TEST_DEPENDS` in `flang/test/CMakeLists.txt` means that tests can be +added for new Plugins.