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,121 @@ 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 plugin 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
+ // We don't check if the result it a valid identifier. Even if we put
50
+ // invalid name in the lookup table, clients wound not be able to lookup
51
+ // that name, thus harmless.
52
+ return filename.drop_front (libPrefix.size ()).drop_back (libSuffix.size ());
53
+ }
54
+ return " " ;
55
+ }
56
+
57
+ llvm::DenseMap<Identifier, PluginLoader::PluginEntry> &
58
+ PluginLoader::getPluginMap () {
59
+ if (PluginMap.has_value ()) {
60
+ return PluginMap.value ();
61
+ }
62
+
63
+ // Create and populate the map.
64
+ PluginMap.emplace ();
65
+ auto &map = PluginMap.value ();
66
+
67
+ // Helper function to try inserting an entry if there's no existing entry
68
+ // associated with the module name.
69
+ auto try_emplace = [&](StringRef moduleName, StringRef libPath,
70
+ StringRef execPath) {
71
+ auto moduleNameIdentifier = Ctx.getIdentifier (moduleName);
72
+ if (map.find (moduleNameIdentifier) != map.end ()) {
73
+ // Specified module name is already in the map.
74
+ return ;
75
+ }
76
+
77
+ libPath = libPath.empty () ? " " : Ctx.AllocateCopy (libPath);
78
+ execPath = execPath.empty () ? " " : Ctx.AllocateCopy (execPath);
79
+ auto result = map.insert ({moduleNameIdentifier, {libPath, execPath}});
80
+ assert (result.second );
81
+ (void )result;
82
+ };
83
+
84
+ auto fs = Ctx.SourceMgr .getFileSystem ();
85
+ std::error_code ec;
61
86
62
- // FIXME: Should we create a lookup table keyed by module name?
63
87
for (auto &entry : Ctx.SearchPathOpts .PluginSearchOpts ) {
64
88
switch (entry.getKind ()) {
65
- // Try '-load-plugin-library'.
89
+
90
+ // '-load-plugin-library <library path>'.
66
91
case PluginSearchOption::Kind::LoadPluginLibrary: {
67
92
auto &val = entry.get <PluginSearchOption::LoadPluginLibrary>();
68
- if (llvm::sys::path::filename (val.LibraryPath ) == pluginLibBasename) {
69
- return {val.LibraryPath , " " };
93
+ auto moduleName = pluginModuleNameStringFromPath (val.LibraryPath );
94
+ if (!moduleName.empty ()) {
95
+ try_emplace (moduleName, val.LibraryPath , /* executablePath=*/ " " );
70
96
}
71
97
continue ;
72
98
}
73
99
74
- // Try '-load-plugin-executable'.
100
+ // '-load-plugin-executable <executable path>#<module name>, ... '.
75
101
case PluginSearchOption::Kind::LoadPluginExecutable: {
76
102
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 };
103
+ assert (!val.ExecutablePath .empty () && " empty plugin path" );
104
+ for (auto &moduleName : val.ModuleNames ) {
105
+ try_emplace (moduleName, /* libraryPath=*/ " " , val.ExecutablePath );
81
106
}
82
107
continue ;
83
108
}
84
109
85
- // Try '-plugin-path'.
110
+ // '-plugin-path <library search path> '.
86
111
case PluginSearchOption::Kind::PluginPath: {
87
112
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), " " };
113
+ for (auto i = fs->dir_begin (val.SearchPath , ec);
114
+ i != llvm::vfs::directory_iterator (); i = i.increment (ec)) {
115
+ auto libPath = i->path ();
116
+ auto moduleName = pluginModuleNameStringFromPath (libPath);
117
+ if (!moduleName.empty ()) {
118
+ try_emplace (moduleName, libPath, /* executablePath=*/ " " );
119
+ }
92
120
}
93
121
continue ;
94
122
}
95
123
96
- // Try '-external-plugin-path'.
124
+ // '-external-plugin-path <library search path>#<server path> '.
97
125
case PluginSearchOption::Kind::ExternalPluginPath: {
98
126
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 };
127
+ for (auto i = fs->dir_begin (val.SearchPath , ec);
128
+ i != llvm::vfs::directory_iterator (); i = i.increment (ec)) {
129
+ auto libPath = i->path ();
130
+ auto moduleName = pluginModuleNameStringFromPath (libPath);
131
+ if (!moduleName.empty ()) {
132
+ try_emplace (moduleName, libPath, val.ServerPath );
133
+ }
103
134
}
104
135
continue ;
105
136
}
106
137
}
138
+ llvm_unreachable (" unhandled PluginSearchOption::Kind" );
107
139
}
108
140
109
- return {};
141
+ return map;
142
+ }
143
+
144
+ const PluginLoader::PluginEntry &
145
+ PluginLoader::lookupPluginByModuleName (Identifier moduleName) {
146
+ auto &map = getPluginMap ();
147
+ auto found = map.find (moduleName);
148
+ if (found != map.end ()) {
149
+ return found->second ;
150
+ } else {
151
+ static PluginEntry notFound{" " , " " };
152
+ return notFound;
153
+ }
110
154
}
111
155
112
156
LoadedLibraryPlugin *PluginLoader::loadLibraryPlugin (StringRef path) {
0 commit comments