forked from OSchip/llvm-project
PoC for Flang Driver Plugins
This commit is contained in:
parent
226f925c3f
commit
788a5d4afe
|
@ -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]
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -390,7 +390,6 @@ endif()
|
|||
include(CMakeParseArguments)
|
||||
include(AddFlang)
|
||||
|
||||
|
||||
add_subdirectory(include)
|
||||
add_subdirectory(lib)
|
||||
add_subdirectory(cmake/modules)
|
||||
|
|
|
@ -6,3 +6,5 @@ add_executable(external-hello-world
|
|||
target_link_libraries(external-hello-world
|
||||
FortranRuntime
|
||||
)
|
||||
#add_subdirectory(HelloEarth)
|
||||
add_subdirectory(HelloWorld)
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
add_llvm_library(
|
||||
flangHelloWorldPlugin
|
||||
MODULE
|
||||
HelloWorldPlugin.cpp
|
||||
|
||||
DEPENDS
|
||||
clangBasic
|
||||
|
||||
LINK_COMPONENTS
|
||||
Option
|
||||
Support
|
||||
)
|
|
@ -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");
|
|
@ -30,6 +30,10 @@ struct MeasurementVisitor {
|
|||
// Custom Consumer Actions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class PluginParseTreeAction : public FrontendAction {
|
||||
void ExecuteAction() override;
|
||||
};
|
||||
|
||||
class InputOutputTestAction : public FrontendAction {
|
||||
void ExecuteAction() override;
|
||||
};
|
||||
|
|
|
@ -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 @@ public:
|
|||
// 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),
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -488,3 +488,7 @@ void InitOnlyAction::ExecuteAction() {
|
|||
"Use `-init-only` for testing purposes only");
|
||||
ci.diagnostics().Report(DiagID);
|
||||
}
|
||||
|
||||
void PluginParseTreeAction::ExecuteAction() {
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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; \
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue