Skip to content

Commit 2293235

Browse files
[Driver][Frontend] Introduce load-pass-plugin option
Allow dynamic loading of LLVM passes via `load-pass-plugin` option passed to the Swift compiler driver.
1 parent 903c1e5 commit 2293235

File tree

13 files changed

+200
-23
lines changed

13 files changed

+200
-23
lines changed

include/swift/AST/DiagnosticsIRGen.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,8 @@ ERROR(temporary_allocation_alignment_not_power_of_2,none,
6565
ERROR(explosion_size_oveflow,none,
6666
"explosion size too large", ())
6767

68+
ERROR(unable_to_load_pass_plugin,none,
69+
"unable to load plugin '%0': '%1'", (StringRef, StringRef))
70+
6871
#define UNDEFINE_DIAGNOSTIC_MACROS
6972
#include "DefineDiagnosticMacros.h"

include/swift/AST/IRGenOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,9 @@ class IRGenOptions {
491491
/// The calling convention used to perform non-swift calls.
492492
llvm::CallingConv::ID PlatformCCallingConvention;
493493

494+
/// Paths to the pass plugins registered via -load-pass-plugin.
495+
std::vector<std::string> LLVMPassPlugins;
496+
494497
IRGenOptions()
495498
: DWARFVersion(2),
496499
OutputKind(IRGenOutputKind::LLVMAssemblyAfterOptimization),

include/swift/Option/Options.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,6 +1698,11 @@ def use_interface_for_module: Separate<["-", "--"], "use-interface-for-module">,
16981698
HelpText<"Prefer loading these modules via interface">,
16991699
MetaVarName<"<name>">;
17001700

1701+
def load_pass_plugin_EQ : Joined<["-"], "load-pass-plugin=">,
1702+
Flags<[FrontendOption, ArgumentIsPath]>,
1703+
HelpText<"Load LLVM pass plugin from a dynamic shared object file.">,
1704+
MetaVarName<"<path>">;
1705+
17011706
// ONLY SUPPORTED IN NEW DRIVER
17021707

17031708
// These flags only exist here so that the old driver doesn't fail with unknown

include/swift/Subsystems.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,10 @@ namespace swift {
252252
/// Given an already created LLVM module, construct a pass pipeline and run
253253
/// the Swift LLVM Pipeline upon it. This will include the emission of LLVM IR
254254
/// if requested (\out is not null).
255-
void performLLVMOptimizations(const IRGenOptions &Opts, llvm::Module *Module,
255+
void performLLVMOptimizations(const IRGenOptions &Opts,
256+
DiagnosticEngine &Diags,
257+
llvm::sys::Mutex *DiagMutex,
258+
llvm::Module *Module,
256259
llvm::TargetMachine *TargetMachine,
257260
llvm::raw_pwrite_stream *out);
258261

lib/Driver/ToolChains.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI,
320320
inputArgs.AddLastArg(arguments, options::OPT_enable_experimental_cxx_interop);
321321
inputArgs.AddLastArg(arguments, options::OPT_cxx_interoperability_mode);
322322
inputArgs.AddLastArg(arguments, options::OPT_enable_builtin_module);
323+
inputArgs.AddLastArg(arguments, options::OPT_load_pass_plugin_EQ);
323324

324325
// Pass on any build config options
325326
inputArgs.AddAllArgs(arguments, options::OPT_D);

lib/DriverTool/swift_llvm_opt_main.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,10 @@ int swift_llvm_opt_main(ArrayRef<const char *> argv, void *MainAddr) {
315315
Opts.OutputKind = IRGenOutputKind::LLVMAssemblyAfterOptimization;
316316

317317
// Then perform the optimizations.
318-
performLLVMOptimizations(Opts, M.get(), TM.get(), &Out->os());
318+
SourceManager SM;
319+
DiagnosticEngine Diags(SM);
320+
performLLVMOptimizations(Opts, Diags, nullptr, M.get(), TM.get(),
321+
&Out->os());
319322
} else {
320323
runSpecificPasses(argv[0], M.get(), TM.get(), ModuleTriple, options);
321324
// Finally dump the output.

lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2602,6 +2602,10 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
26022602
}
26032603
}
26042604

2605+
for (const Arg *A : Args.filtered(OPT_load_pass_plugin_EQ)) {
2606+
Opts.LLVMPassPlugins.push_back(A->getValue());
2607+
}
2608+
26052609
for (const Arg *A : Args.filtered(OPT_verify_type_layout)) {
26062610
Opts.VerifyTypeLayoutNames.push_back(A->getValue());
26072611
}

lib/IRGen/IRGen.cpp

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
#include "llvm/MC/TargetRegistry.h"
6868
#include "llvm/Object/ObjectFile.h"
6969
#include "llvm/Passes/PassBuilder.h"
70+
#include "llvm/Passes/PassPlugin.h"
7071
#include "llvm/Passes/StandardInstrumentations.h"
7172
#include "llvm/Support/CommandLine.h"
7273
#include "llvm/Support/Debug.h"
@@ -188,7 +189,23 @@ static void align(llvm::Module *Module) {
188189
}
189190
}
190191

192+
template <typename... ArgTypes>
193+
void diagnoseSync(
194+
DiagnosticEngine &Diags, llvm::sys::Mutex *DiagMutex, SourceLoc Loc,
195+
Diag<ArgTypes...> ID,
196+
typename swift::detail::PassArgument<ArgTypes>::type... Args) {
197+
if (DiagMutex)
198+
DiagMutex->lock();
199+
200+
Diags.diagnose(Loc, ID, std::move(Args)...);
201+
202+
if (DiagMutex)
203+
DiagMutex->unlock();
204+
}
205+
191206
void swift::performLLVMOptimizations(const IRGenOptions &Opts,
207+
DiagnosticEngine &Diags,
208+
llvm::sys::Mutex *DiagMutex,
192209
llvm::Module *Module,
193210
llvm::TargetMachine *TargetMachine,
194211
llvm::raw_pwrite_stream *out) {
@@ -238,6 +255,18 @@ void swift::performLLVMOptimizations(const IRGenOptions &Opts,
238255

239256
PassBuilder PB(TargetMachine, PTO, PGOOpt, &PIC);
240257

258+
// Attempt to load pass plugins and register their callbacks with PB.
259+
for (const auto &PluginFile : Opts.LLVMPassPlugins) {
260+
Expected<PassPlugin> PassPlugin = PassPlugin::Load(PluginFile);
261+
if (PassPlugin) {
262+
PassPlugin->registerPassBuilderCallbacks(PB);
263+
} else {
264+
diagnoseSync(Diags, DiagMutex, SourceLoc(),
265+
diag::unable_to_load_pass_plugin, PluginFile,
266+
toString(PassPlugin.takeError()));
267+
}
268+
}
269+
241270
// Register the AA manager first so that our version is the one used.
242271
FAM.registerPass([&] {
243272
auto AA = PB.buildDefaultAAPipeline();
@@ -512,20 +541,6 @@ static void countStatsPostIRGen(UnifiedStatsReporter &Stats,
512541
}
513542
}
514543

515-
template<typename ...ArgTypes>
516-
void
517-
diagnoseSync(DiagnosticEngine &Diags, llvm::sys::Mutex *DiagMutex,
518-
SourceLoc Loc, Diag<ArgTypes...> ID,
519-
typename swift::detail::PassArgument<ArgTypes>::type... Args) {
520-
if (DiagMutex)
521-
DiagMutex->lock();
522-
523-
Diags.diagnose(Loc, ID, std::move(Args)...);
524-
525-
if (DiagMutex)
526-
DiagMutex->unlock();
527-
}
528-
529544
/// Run the LLVM passes. In multi-threaded compilation this will be done for
530545
/// multiple LLVM modules in parallel.
531546
bool swift::performLLVM(const IRGenOptions &Opts,
@@ -594,7 +609,7 @@ bool swift::performLLVM(const IRGenOptions &Opts,
594609
assert(Opts.OutputKind == IRGenOutputKind::Module && "no output specified");
595610
}
596611

597-
performLLVMOptimizations(Opts, Module, TargetMachine,
612+
performLLVMOptimizations(Opts, Diags, DiagMutex, Module, TargetMachine,
598613
OutputFile ? &OutputFile->getOS() : nullptr);
599614

600615
if (Stats) {
@@ -1683,7 +1698,7 @@ GeneratedModule OptimizedIRRequest::evaluate(Evaluator &evaluator,
16831698
if (!irMod)
16841699
return irMod;
16851700

1686-
performLLVMOptimizations(desc.Opts, irMod.getModule(),
1701+
performLLVMOptimizations(desc.Opts, ctx.Diags, nullptr, irMod.getModule(),
16871702
irMod.getTargetMachine(), desc.out);
16881703
return irMod;
16891704
}

unittests/Driver/CMakeLists.txt

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,27 @@
1-
add_swift_unittest(SwiftDriverTests
1+
set(SWIFT_DRIVER_TESTS_SOURCE_FILES
22
FineGrainedDependencyGraphTests.cpp
33
MockingFineGrainedDependencyGraphs.cpp
44
UnitTestSourceFileDepGraphFactory.cpp
55
)
66

7+
set(SWIFT_DRIVER_TESTS_LIBRARIES
8+
swiftAST
9+
swiftClangImporter
10+
swiftSema
11+
swiftDriver
12+
)
13+
14+
# PassPlugin not supported on Windows
15+
if(NOT SWIFT_HOST_VARIANT STREQUAL "windows")
16+
list(APPEND SWIFT_DRIVER_TESTS_SOURCE_FILES
17+
PassPluginTest.cpp)
18+
list(APPEND SWIFT_DRIVER_TESTS_LIBRARIES
19+
LLVMTestingSupport)
20+
add_subdirectory(PassPluginInput)
21+
endif()
22+
23+
add_swift_unittest(SwiftDriverTests
24+
${SWIFT_DRIVER_TESTS_SOURCE_FILES})
25+
726
target_link_libraries(SwiftDriverTests PRIVATE
8-
swiftAST
9-
swiftClangImporter
10-
swiftSema
11-
swiftDriver)
27+
${SWIFT_DRIVER_TESTS_LIBRARIES})
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
add_library(InputTestPlugin MODULE
2+
TestPlugin.cpp)
3+
4+
# Put PLUGIN next to the unit test executable.
5+
set_output_directory(InputTestPlugin
6+
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/../
7+
LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/../
8+
)
9+
10+
llvm_map_components_to_libnames(LLVM_LIBRARIES Core)
11+
target_link_libraries(InputTestPlugin PRIVATE ${LLVM_LIBRARIES})
12+
13+
set_target_properties(InputTestPlugin PROPERTIES FOLDER "Tests")

0 commit comments

Comments
 (0)