15
15
#include " swift/AST/DiagnosticEngine.h"
16
16
#include " swift/AST/DiagnosticsFrontend.h"
17
17
#include " swift/Basic/SourceManager.h"
18
+ #include " swift/Parse/Lexer.h"
18
19
#include " llvm/Config/config.h"
19
20
20
21
using namespace swift ;
21
22
22
- void PluginLoader::createModuleToExecutablePluginMap () {
23
- for (auto &elem : Ctx.SearchPathOpts .PluginSearchOpts ) {
24
- if (auto *arg = elem.dyn_cast <PluginSearchOption::LoadPluginExecutable>()) {
25
- // Create a moduleName -> pluginPath mapping.
26
- assert (!arg->ExecutablePath .empty () && " empty plugin path" );
27
- StringRef pathStr = Ctx.AllocateCopy (arg->ExecutablePath );
28
- for (auto moduleName : arg->ModuleNames ) {
29
- ExecutablePluginPaths[Ctx.getIdentifier (moduleName)] = pathStr;
30
- }
31
- }
32
- }
33
- }
34
-
35
23
void PluginLoader::setRegistry (PluginRegistry *newValue) {
36
24
assert (Registry == nullptr && " Too late to set a new plugin registry" );
37
25
Registry = newValue;
@@ -48,65 +36,124 @@ PluginRegistry *PluginLoader::getRegistry() {
48
36
return Registry;
49
37
}
50
38
51
- std::pair<std::string, std::string>
52
- PluginLoader::lookupPluginByModuleName (Identifier moduleName) {
53
- auto fs = Ctx.SourceMgr .getFileSystem ();
54
-
55
- // Look for 'lib${module name}(.dylib|.so)'.
39
+ // / Get plug module name from \p path if the path looks like a shared library
40
+ // / path. Otherwise, returns an empty string.
41
+ static StringRef pluginModuleNameStringFromPath (StringRef path) {
42
+ // Plugin library must be named 'lib${module name}(.dylib|.so|.dll)'.
56
43
// FIXME: Shared library prefix might be different between platforms.
57
- SmallString<64 > pluginLibBasename;
58
- pluginLibBasename.append (" lib" );
59
- pluginLibBasename.append (moduleName.str ());
60
- pluginLibBasename.append (LTDL_SHLIB_EXT);
44
+ constexpr StringRef libPrefix = " lib" ;
45
+ constexpr StringRef libSuffix = LTDL_SHLIB_EXT;
46
+
47
+ StringRef filename = llvm::sys::path::filename (path);
48
+ if (filename.starts_with (libPrefix) && filename.ends_with (libSuffix)) {
49
+ auto moduleName =
50
+ filename.drop_front (libPrefix.size ()).drop_back (libSuffix.size ());
51
+
52
+ // FIXME: layering violation / circular linkage.
53
+ // libAST should not call libParse.
54
+ if (Lexer::isIdentifier (moduleName))
55
+ return moduleName;
56
+ }
57
+ return " " ;
58
+ }
59
+
60
+ llvm::DenseMap<Identifier, PluginLoader::PluginEntry> &
61
+ PluginLoader::getPluginMap () {
62
+ if (PluginMap.has_value ()) {
63
+ return PluginMap.value ();
64
+ }
65
+
66
+ // Create and populate the map.
67
+ PluginMap.emplace ();
68
+ auto &map = PluginMap.value ();
69
+
70
+ // Helper function to try inserting an entry if there's no existing entry
71
+ // associated with the module name.
72
+ auto try_emplace = [&](StringRef moduleName, StringRef libPath,
73
+ StringRef execPath) {
74
+ auto moduleNameIdentifier = Ctx.getIdentifier (moduleName);
75
+ if (map.find (moduleNameIdentifier) != map.end ()) {
76
+ // Specified module name is already in the map.
77
+ return ;
78
+ }
79
+
80
+ libPath = libPath.empty () ? " " : Ctx.AllocateCopy (libPath);
81
+ execPath = execPath.empty () ? " " : Ctx.AllocateCopy (execPath);
82
+ auto result = map.try_emplace (moduleNameIdentifier, libPath, execPath);
83
+ assert (result.second );
84
+ (void )result;
85
+ };
86
+
87
+ auto fs = Ctx.SourceMgr .getFileSystem ();
88
+ std::error_code ec;
61
89
62
- // FIXME: Should we create a lookup table keyed by module name?
63
90
for (auto &entry : Ctx.SearchPathOpts .PluginSearchOpts ) {
64
91
switch (entry.getKind ()) {
65
- // Try '-load-plugin-library'.
92
+
93
+ // '-load-plugin-library <library path>'.
66
94
case PluginSearchOption::Kind::LoadPluginLibrary: {
67
95
auto &val = entry.get <PluginSearchOption::LoadPluginLibrary>();
68
- if (llvm::sys::path::filename (val.LibraryPath ) == pluginLibBasename) {
69
- return {val.LibraryPath , " " };
96
+ auto moduleName = pluginModuleNameStringFromPath (val.LibraryPath );
97
+ if (!moduleName.empty ()) {
98
+ try_emplace (moduleName, val.LibraryPath , /* executablePath=*/ " " );
70
99
}
71
100
continue ;
72
101
}
73
102
74
- // Try '-load-plugin-executable'.
103
+ // '-load-plugin-executable <executable path>#<module name>, ... '.
75
104
case PluginSearchOption::Kind::LoadPluginExecutable: {
76
105
auto &val = entry.get <PluginSearchOption::LoadPluginExecutable>();
77
- auto found = ExecutablePluginPaths.find (moduleName);
78
- if (found != ExecutablePluginPaths.end () &&
79
- found->second == val.ExecutablePath ) {
80
- return {" " , val.ExecutablePath };
106
+ assert (!val.ExecutablePath .empty () && " empty plugin path" );
107
+ for (auto &moduleName : val.ModuleNames ) {
108
+ try_emplace (moduleName, /* libraryPath=*/ " " , val.ExecutablePath );
81
109
}
82
110
continue ;
83
111
}
84
112
85
- // Try '-plugin-path'.
113
+ // '-plugin-path <library search path> '.
86
114
case PluginSearchOption::Kind::PluginPath: {
87
115
auto &val = entry.get <PluginSearchOption::PluginPath>();
88
- SmallString<128 > fullPath (val.SearchPath );
89
- llvm::sys::path::append (fullPath, pluginLibBasename);
90
- if (fs->exists (fullPath)) {
91
- return {std::string (fullPath), " " };
116
+ for (auto i = fs->dir_begin (val.SearchPath , ec);
117
+ i != llvm::vfs::directory_iterator (); i = i.increment (ec)) {
118
+ auto libPath = i->path ();
119
+ auto moduleName = pluginModuleNameStringFromPath (libPath);
120
+ if (!moduleName.empty ()) {
121
+ try_emplace (moduleName, libPath, /* executablePath=*/ " " );
122
+ }
92
123
}
93
124
continue ;
94
125
}
95
126
96
- // Try '-external-plugin-path'.
127
+ // '-external-plugin-path <library search path>#<server path> '.
97
128
case PluginSearchOption::Kind::ExternalPluginPath: {
98
129
auto &val = entry.get <PluginSearchOption::ExternalPluginPath>();
99
- SmallString<128 > fullPath (val.SearchPath );
100
- llvm::sys::path::append (fullPath, pluginLibBasename);
101
- if (fs->exists (fullPath)) {
102
- return {std::string (fullPath), val.ServerPath };
130
+ for (auto i = fs->dir_begin (val.SearchPath , ec);
131
+ i != llvm::vfs::directory_iterator (); i = i.increment (ec)) {
132
+ auto libPath = i->path ();
133
+ auto moduleName = pluginModuleNameStringFromPath (libPath);
134
+ if (!moduleName.empty ()) {
135
+ try_emplace (moduleName, libPath, val.ServerPath );
136
+ }
103
137
}
104
138
continue ;
105
139
}
106
140
}
141
+ llvm_unreachable (" unhandled PluginSearchOption::Kind" );
107
142
}
108
143
109
- return {};
144
+ return map;
145
+ }
146
+
147
+ const PluginLoader::PluginEntry &
148
+ PluginLoader::lookupPluginByModuleName (Identifier moduleName) {
149
+ auto &map = getPluginMap ();
150
+ auto found = map.find (moduleName);
151
+ if (found != map.end ()) {
152
+ return found->second ;
153
+ } else {
154
+ static PluginEntry notFound{" " , " " };
155
+ return notFound;
156
+ }
110
157
}
111
158
112
159
LoadedLibraryPlugin *PluginLoader::loadLibraryPlugin (StringRef path) {
0 commit comments