[clang] 788a5d4 - PoC for Flang Driver Plugins
Andrzej Warzynski via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 1 01:15:25 PDT 2021
Author: Stuart Ellis
Date: 2021-07-01T08:10:40Z
New Revision: 788a5d4afe6407e647454a9832a7b4a27fba06bf
URL: https://github.com/llvm/llvm-project/commit/788a5d4afe6407e647454a9832a7b4a27fba06bf
DIFF: https://github.com/llvm/llvm-project/commit/788a5d4afe6407e647454a9832a7b4a27fba06bf.diff
LOG: PoC for Flang Driver Plugins
Added:
flang/examples/HelloWorld/CMakeLists.txt
flang/examples/HelloWorld/HelloWorldPlugin.cpp
flang/include/flang/Frontend/FrontendPluginRegistry.h
Modified:
clang/include/clang/Driver/Options.td
flang/CMakeLists.txt
flang/examples/CMakeLists.txt
flang/include/flang/Frontend/FrontendActions.h
flang/include/flang/Frontend/FrontendOptions.h
flang/lib/Frontend/CompilerInvocation.cpp
flang/lib/Frontend/FrontendAction.cpp
flang/lib/Frontend/FrontendActions.cpp
flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
llvm/include/llvm/Support/Registry.h
llvm/lib/Support/DynamicLibrary.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 41b7299b02745..1629a74ae62c9 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5221,10 +5221,6 @@ def enable_noundef_analysis : Flag<["-"], "enable-noundef-analysis">, Group<f_Gr
def discard_value_names : Flag<["-"], "discard-value-names">,
HelpText<"Discard value names in LLVM IR">,
MarshallingInfoFlag<CodeGenOpts<"DiscardValueNames">>;
-def load : Separate<["-"], "load">, MetaVarName<"<dsopath>">,
- HelpText<"Load the named plugin (dynamic shared object)">;
-def plugin : Separate<["-"], "plugin">, MetaVarName<"<name>">,
- HelpText<"Use the named plugin action instead of the default action (use \"help\" to list available options)">;
def plugin_arg : JoinedAndSeparate<["-"], "plugin-arg-">,
MetaVarName<"<name> <arg>">,
HelpText<"Pass <arg> to plugin <name>">;
@@ -5788,6 +5784,12 @@ def init_only : Flag<["-"], "init-only">,
HelpText<"Only execute frontend initialization">;
} // let Group = Action_Group
+
+def load : Separate<["-"], "load">, MetaVarName<"<dsopath>">,
+ HelpText<"Load the named plugin (dynamic shared object)">;
+def plugin : Separate<["-"], "plugin">, MetaVarName<"<name>">,
+ HelpText<"Use the named plugin action instead of the default action (use \"help\" to list available options)">;
+
} // let Flags = [CC1Option, FC1Option, NoDriverOption]
//===----------------------------------------------------------------------===//
diff --git a/flang/CMakeLists.txt b/flang/CMakeLists.txt
index adf3dc819dc93..d9495c4748ce5 100644
--- a/flang/CMakeLists.txt
+++ b/flang/CMakeLists.txt
@@ -390,7 +390,6 @@ endif()
include(CMakeParseArguments)
include(AddFlang)
-
add_subdirectory(include)
add_subdirectory(lib)
add_subdirectory(cmake/modules)
diff --git a/flang/examples/CMakeLists.txt b/flang/examples/CMakeLists.txt
index 3ca9feddf33e9..f896874f7f89b 100644
--- a/flang/examples/CMakeLists.txt
+++ b/flang/examples/CMakeLists.txt
@@ -6,3 +6,5 @@ add_executable(external-hello-world
target_link_libraries(external-hello-world
FortranRuntime
)
+#add_subdirectory(HelloEarth)
+add_subdirectory(HelloWorld)
diff --git a/flang/examples/HelloWorld/CMakeLists.txt b/flang/examples/HelloWorld/CMakeLists.txt
new file mode 100644
index 0000000000000..eb716c2f17b49
--- /dev/null
+++ b/flang/examples/HelloWorld/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_llvm_library(
+ flangHelloWorldPlugin
+ MODULE
+ HelloWorldPlugin.cpp
+
+ DEPENDS
+ clangBasic
+
+ LINK_COMPONENTS
+ Option
+ Support
+)
diff --git a/flang/examples/HelloWorld/HelloWorldPlugin.cpp b/flang/examples/HelloWorld/HelloWorldPlugin.cpp
new file mode 100644
index 0000000000000..30d23ce104227
--- /dev/null
+++ b/flang/examples/HelloWorld/HelloWorldPlugin.cpp
@@ -0,0 +1,18 @@
+#include "flang/Frontend/FrontendActions.h"
+#include "flang/Frontend/FrontendPluginRegistry.h"
+
+__attribute__((constructor))
+static void printing() {
+ llvm::outs() << " > Plugin Constructed\n";
+}
+
+using namespace Fortran::frontend;
+
+class HelloWorldFlangPlugin : public PluginParseTreeAction
+{
+ void ExecuteAction() override {
+ llvm::outs() << "Hello World from your new plugin (Remote plugin)\n";
+ }
+};
+
+static FrontendPluginRegistry::Add<HelloWorldFlangPlugin> X("-hello-w", "Hello World Plugin example");
diff --git a/flang/include/flang/Frontend/FrontendActions.h b/flang/include/flang/Frontend/FrontendActions.h
index 72eb44223fe49..d30ae1dbed0ff 100644
--- a/flang/include/flang/Frontend/FrontendActions.h
+++ b/flang/include/flang/Frontend/FrontendActions.h
@@ -30,6 +30,10 @@ struct MeasurementVisitor {
// Custom Consumer Actions
//===----------------------------------------------------------------------===//
+class PluginParseTreeAction : public FrontendAction {
+ void ExecuteAction() override;
+};
+
class InputOutputTestAction : public FrontendAction {
void ExecuteAction() override;
};
diff --git a/flang/include/flang/Frontend/FrontendOptions.h b/flang/include/flang/Frontend/FrontendOptions.h
index 42ce499566e9f..5867b790f6fce 100644
--- a/flang/include/flang/Frontend/FrontendOptions.h
+++ b/flang/include/flang/Frontend/FrontendOptions.h
@@ -77,7 +77,10 @@ enum ActionKind {
GetSymbolsSources,
/// Only execute frontend initialization
- InitOnly
+ InitOnly,
+
+ /// Run a plugin action, \see ActionName.
+ PluginAction
/// TODO: RunPreprocessor, EmitLLVM, EmitLLVMOnly,
/// EmitCodeGenOnly, EmitAssembly, (...)
@@ -249,6 +252,12 @@ class FrontendOptions {
// Source file encoding
Fortran::parser::Encoding encoding_{Fortran::parser::Encoding::UTF_8};
+ /// The list of plugins to load.
+ std::vector<std::string> plugins;
+
+ /// The name of the action to run when using a plugin action.
+ std::string ActionName;
+
public:
FrontendOptions()
: showHelp_(false), showVersion_(false), instrumentedParse_(false),
diff --git a/flang/include/flang/Frontend/FrontendPluginRegistry.h b/flang/include/flang/Frontend/FrontendPluginRegistry.h
new file mode 100644
index 0000000000000..d775393afe7f6
--- /dev/null
+++ b/flang/include/flang/Frontend/FrontendPluginRegistry.h
@@ -0,0 +1,26 @@
+//===- FrontendPluginRegistry.h ---------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Pluggable Frontend Action Interface
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H
+#define LLVM_FLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H
+
+#include "flang/Frontend/FrontendAction.h"
+#include "llvm/Support/Registry.h"
+
+namespace Fortran::frontend {
+
+/// The frontend plugin registry.
+using FrontendPluginRegistry = llvm::Registry<PluginParseTreeAction>;
+
+} // namespace flang
+
+#endif // LLVM_FLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H
\ No newline at end of file
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 6a2bf1947e350..20d3d2d253a75 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -199,6 +199,23 @@ static bool ParseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
}
}
+ printf("--------- (ParseFrontendArgs) ----------\n");
+
+ if (llvm::opt::Arg *a = args.getLastArg(clang::driver::options::OPT_load)) {
+ llvm::outs() << " " << a->getOption().getName() << " >>> " << a->getValue() << "\n";
+ //opts.plugins = a->getValue();
+ opts.plugins.push_back(a->getValue());
+ }
+
+ if (const llvm::opt::Arg *a = args.getLastArg(clang::driver::options::OPT_plugin)) {
+ llvm::outs() << " " << a->getOption().getName() << " >>> " << a->getValue() << "\n";
+ //opts.plugins.emplace_back(a->getValue());
+ opts.programAction_ = PluginAction;
+ opts.ActionName = a->getValue();
+ }
+
+ printf("-------- (\\ParseFrontendArgs) ----------\n");
+
opts.outputFile_ = args.getLastArgValue(clang::driver::options::OPT_o);
opts.showHelp_ = args.hasArg(clang::driver::options::OPT_help);
opts.showVersion_ = args.hasArg(clang::driver::options::OPT_version);
diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp
index 23e4ca3f33063..62d4bac0df6fa 100644
--- a/flang/lib/Frontend/FrontendAction.cpp
+++ b/flang/lib/Frontend/FrontendAction.cpp
@@ -10,6 +10,7 @@
#include "flang/Frontend/CompilerInstance.h"
#include "flang/Frontend/FrontendActions.h"
#include "flang/Frontend/FrontendOptions.h"
+#include "flang/Frontend/FrontendPluginRegistry.h"
#include "flang/FrontendTool/Utils.h"
#include "clang/Basic/DiagnosticFrontend.h"
#include "llvm/Support/Errc.h"
@@ -17,6 +18,9 @@
using namespace Fortran::frontend;
+LLVM_INSTANTIATE_REGISTRY(FrontendPluginRegistry)
+
+
void FrontendAction::set_currentInput(const FrontendInputFile ¤tInput) {
this->currentInput_ = currentInput;
}
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 8ee42d73c6e46..d067ebd141b85 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -488,3 +488,7 @@ void InitOnlyAction::ExecuteAction() {
"Use `-init-only` for testing purposes only");
ci.diagnostics().Report(DiagID);
}
+
+void PluginParseTreeAction::ExecuteAction() {
+
+}
diff --git a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 243e25163dc05..8ef0c93404c10 100644
--- a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -13,11 +13,14 @@
#include "flang/Frontend/CompilerInstance.h"
#include "flang/Frontend/FrontendActions.h"
+#include "flang/Frontend/FrontendAction.h"
+#include "flang/Frontend/FrontendPluginRegistry.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/BuryPointer.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/DynamicLibrary.h"
namespace Fortran::frontend {
@@ -79,6 +82,22 @@ static std::unique_ptr<FrontendAction> CreateFrontendBaseAction(
case InitOnly:
return std::make_unique<InitOnlyAction>();
break;
+ case PluginAction: {
+ llvm::outs() << "---------- (case: PluginAction) --------\n";
+ llvm::outs() << " Plugin Action: " << ci.frontendOpts().ActionName << "\n";
+ for (const FrontendPluginRegistry::entry &plugin : FrontendPluginRegistry::entries()) {
+ llvm::outs() << " " << plugin.getName() << "\t-- " << plugin.getDesc() << "\n";
+ if (plugin.getName() == ci.frontendOpts().ActionName) {
+ llvm::outs() << "We have found the plugin name!! :-)\n";
+ std::unique_ptr<PluginParseTreeAction> P(plugin.instantiate());
+ return std::move(P);
+ }
+ }
+
+ unsigned diagID = ci.diagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, "unable to find plugin '%0'");
+ ci.diagnostics().Report(diagID) << ci.frontendOpts().ActionName;
+ return nullptr;
+ }
default:
break;
// TODO:
@@ -92,6 +111,26 @@ static std::unique_ptr<FrontendAction> CreateFrontendBaseAction(
return 0;
}
+/// <<< TEMP Plugin Example
+
+class HelloWorldFlangPlugin : public PluginParseTreeAction
+{
+ protected:
+ void ExecuteAction() override {
+ llvm::outs() << "Hello World from your new plugin (Hello World)\n";
+ }
+};
+
+class HelloTwoFlangPlugin : public PluginParseTreeAction
+{
+ protected:
+ void ExecuteAction() override {
+ llvm::outs() << "Hello World from your new plugin (Hello Two)\n";
+ }
+};
+
+/// <<<<< TEMP Plugin Example
+
std::unique_ptr<FrontendAction> CreateFrontendAction(CompilerInstance &ci) {
// Create the underlying action.
std::unique_ptr<FrontendAction> act = CreateFrontendBaseAction(ci);
@@ -100,6 +139,7 @@ std::unique_ptr<FrontendAction> CreateFrontendAction(CompilerInstance &ci) {
return act;
}
+
bool ExecuteCompilerInvocation(CompilerInstance *flang) {
// Honor -help.
if (flang->frontendOpts().showHelp_) {
@@ -117,6 +157,33 @@ bool ExecuteCompilerInvocation(CompilerInstance *flang) {
return true;
}
+ llvm::outs() << "------ (ExecuteCompilerInvocation) -----\n";
+
+ // Load any requested plugins.
+ for (const std::string &Path : flang->frontendOpts().plugins) {
+ llvm::outs() << " Load :: Path >> " << Path << "\n";
+ std::string Error;
+ if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error)) {
+ unsigned diagID = flang->diagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, "unable to load plugin '%0': '%1'");
+ flang->diagnostics().Report(diagID) << Path << Error;
+ }
+ }
+
+ llvm::outs() << " Plugin Registry List >>\n";
+ for (const FrontendPluginRegistry::entry &plugin : FrontendPluginRegistry::entries()) {
+ llvm::outs() << plugin.getName() << " -- " << plugin.getDesc() << "\n";
+ }
+ llvm::outs() << " << Plugin Registry List\n";
+
+ static FrontendPluginRegistry::Add<HelloWorldFlangPlugin> X("-hello-wor", "simple Plugin example");
+ static FrontendPluginRegistry::Add<HelloTwoFlangPlugin> Y("hellotwo", "another print plugin example");
+
+ llvm::outs() << "----- (\\ExecuteCompilerInvocation) -----\n";
+
+ // If there were errors in processing arguments, don't do anything else.
+ if (flang->diagnostics().hasErrorOccurred())
+ return false;
+
// Create and execute the frontend action.
std::unique_ptr<FrontendAction> act(CreateFrontendAction(*flang));
if (!act)
diff --git a/llvm/include/llvm/Support/Registry.h b/llvm/include/llvm/Support/Registry.h
index 5bb6a254a47f4..58b1825a71c06 100644
--- a/llvm/include/llvm/Support/Registry.h
+++ b/llvm/include/llvm/Support/Registry.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/CommandLine.h"
#include <memory>
namespace llvm {
@@ -120,7 +121,10 @@ namespace llvm {
public:
Add(StringRef Name, StringRef Desc)
: Entry(Name, Desc, CtorFn), Node(Entry) {
+ llvm::outs() << " -------------- (Registry) --------------\n";
+ llvm::outs() << " \tAdd :: " << Name << "\n";
add_node(&Node);
+ llvm::outs() << " ------------- (\\Registry) --------------\n";
}
};
};
@@ -145,8 +149,14 @@ namespace llvm {
else \
Head = N; \
Tail = N; \
+ llvm::outs() << " REGISTRY_CLASS :: list >> \n"; \
+ for (const REGISTRY_CLASS::entry &plugin : REGISTRY_CLASS::entries()) { \
+ llvm::outs() << " " << plugin.getName() << " \t-- " << plugin.getDesc() << "\n"; \
+ } \
} \
template<typename T> typename Registry<T>::iterator Registry<T>::begin() { \
+ llvm::outs() << "iterator (head)\n"; \
+ llvm::outs() << Head << "\n"; \
return iterator(Head); \
} \
template REGISTRY_CLASS::node *Registry<REGISTRY_CLASS::type>::Head; \
diff --git a/llvm/lib/Support/DynamicLibrary.cpp b/llvm/lib/Support/DynamicLibrary.cpp
index 2bcdbdcdb9b0d..ff989da453652 100644
--- a/llvm/lib/Support/DynamicLibrary.cpp
+++ b/llvm/lib/Support/DynamicLibrary.cpp
@@ -149,12 +149,18 @@ DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName,
// ManagedStatic can be added from static constructors in HandleSet::DLOpen.
HandleSet& HS = *OpenedHandles;
+ printf(" -------- (getPermantentLibrary) --------\n");
+ printf(" get Lib: %s \n", FileName);
+
void *Handle = HandleSet::DLOpen(FileName, Err);
if (Handle != &Invalid) {
+ printf(" Handle != Invalid \n");
SmartScopedLock<true> Lock(*SymbolsMutex);
HS.AddLibrary(Handle, /*IsProcess*/ FileName == nullptr);
}
+ printf(" ------- (\\getPermantentLibrary) --------\n");
+
return DynamicLibrary(Handle);
}
More information about the cfe-commits
mailing list