Skip to content

Commit c41ca94

Browse files
committed
[Macros] Type check user-defined macro plugins
Type check user-defined macros plugins with user-provided type signatures. Also, load plugin libraries with `RTLD_LOCAL` instead of `RTLD_GLOBAL` to prevent symbol collision between plugins. `llvm::sys::DynamicLibrary` only supports `RTLD_GLOBAL` so we use plain the `dlopen` instead. This does not work on Windows and needs to be fixed.
1 parent 60c8b4b commit c41ca94

File tree

12 files changed

+213
-63
lines changed

12 files changed

+213
-63
lines changed

include/swift/AST/ASTContext.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
#include "llvm/ADT/TinyPtrVector.h"
4545
#include "llvm/Support/Allocator.h"
4646
#include "llvm/Support/DataTypes.h"
47-
#include "llvm/Support/DynamicLibrary.h"
4847
#include <functional>
4948
#include <memory>
5049
#include <utility>
@@ -1456,10 +1455,9 @@ class ASTContext final {
14561455
/// Finds the loaded compiler plugin given its name.
14571456
CompilerPlugin *getLoadedPlugin(StringRef name);
14581457

1459-
/// Finds the address of the given symbol. If `libraryHint` is non-null,
1458+
/// Finds the address of the given symbol. If `libraryHandleHint` is non-null,
14601459
/// search within the library.
1461-
void *getAddressOfSymbol(StringRef name,
1462-
llvm::sys::DynamicLibrary *libraryHint = nullptr);
1460+
void *getAddressOfSymbol(const char *name, void *libraryHandleHint = nullptr);
14631461

14641462
private:
14651463
friend Decl;

include/swift/AST/CompilerPlugin.h

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
#include "swift/AST/Type.h"
1818
#include "swift/Basic/LLVM.h"
1919
#include "swift/Basic/StringExtras.h"
20-
#include "llvm/Support/DynamicLibrary.h"
2120

2221
#ifndef SWIFT_AST_COMPILER_PLUGIN_H
2322
#define SWIFT_AST_COMPILER_PLUGIN_H
@@ -49,12 +48,16 @@ class CompilerPlugin {
4948
Kind = 2,
5049
// static func _rewrite(...) -> (UnsafePointer<UInt8>?, count: Int)
5150
Rewrite = 3,
51+
// static func _genericSignature(...) -> (UnsafePointer<UInt8>?, count: Int)
52+
GenericSignature = 4,
53+
// static func _typeSignature(...) -> (UnsafePointer<UInt8>, count: Int)
54+
TypeSignature = 5,
5255
};
5356

5457
/// The plugin type metadata.
5558
const void *metadata;
5659
/// The parent dynamic library containing the plugin.
57-
llvm::sys::DynamicLibrary parentLibrary;
60+
void *parentLibrary;
5861
/// The witness table proving that the plugin conforms to `_CompilerPlugin`.
5962
const void *witnessTable;
6063
/// The plugin name, aka. result of the `_name()` method.
@@ -68,8 +71,7 @@ class CompilerPlugin {
6871
}
6972

7073
protected:
71-
CompilerPlugin(const void *metadata, llvm::sys::DynamicLibrary parentLibrary,
72-
ASTContext &ctx);
74+
CompilerPlugin(const void *metadata, void *parentLibrary, ASTContext &ctx);
7375

7476
private:
7577
/// Invoke the `_name` method. The caller assumes ownership of the result
@@ -80,12 +82,24 @@ class CompilerPlugin {
8082
Kind invokeKind() const;
8183

8284
public:
83-
/// Invoke the `_rewrite` method. Invoke the `_name` method. The caller
84-
/// assumes ownership of the result string buffer.
85+
~CompilerPlugin();
86+
CompilerPlugin(const CompilerPlugin &) = delete;
87+
CompilerPlugin(CompilerPlugin &&) = default;
88+
89+
/// Invoke the `_rewrite` method. The caller assumes ownership of the result
90+
/// string buffer.
8591
Optional<NullTerminatedStringRef> invokeRewrite(
8692
StringRef targetModuleName, StringRef filePath, StringRef sourceFileText,
8793
CharSourceRange range, ASTContext &ctx) const;
8894

95+
/// Invoke the `_genericSignature` method. The caller assumes ownership of the
96+
/// result string buffer.
97+
Optional<StringRef> invokeGenericSignature() const;
98+
99+
/// Invoke the `_typeSignature` method. The caller assumes ownership of the
100+
/// result string buffer.
101+
StringRef invokeTypeSignature() const;
102+
89103
StringRef getName() const {
90104
return name;
91105
}

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6696,8 +6696,8 @@ ERROR(experimental_no_metadata_feature_can_only_be_used_when_enabled,
66966696
ERROR(expected_macro_expansion_expr,PointsToFirstBadToken,
66976697
"expected macro expansion to produce an expression", ())
66986698
ERROR(macro_undefined,PointsToFirstBadToken,
6699-
"macro '%0' is undefined; use `-load-plugin-library` to specify dynamic "
6700-
"libraries that contain this macro", (StringRef))
6699+
"macro %0 is undefined; use `-load-plugin-library` to specify dynamic "
6700+
"libraries that contain this macro", (Identifier))
67016701

67026702
#define UNDEFINE_DIAGNOSTIC_MACROS
67036703
#include "DefineDiagnosticMacros.h"

lib/AST/ASTContext.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@
7373
#include <queue>
7474
#include <memory>
7575

76+
#if !defined(_WIN32)
77+
#include <dlfcn.h>
78+
#endif
79+
7680
#include "RequirementMachine/RewriteContext.h"
7781

7882
using namespace swift;
@@ -6055,16 +6059,15 @@ CompilerPlugin *ASTContext::getLoadedPlugin(StringRef name) {
60556059
return &lookup->second;
60566060
}
60576061

6058-
void *ASTContext::getAddressOfSymbol(StringRef name,
6059-
llvm::sys::DynamicLibrary *libraryHint) {
6062+
void *ASTContext::getAddressOfSymbol(const char *name,
6063+
void *libraryHandleHint) {
60606064
auto lookup = LoadedSymbols.try_emplace(name, nullptr);
60616065
void *&address = lookup.first->getValue();
6066+
#if !defined(_WIN32)
60626067
if (lookup.second) {
6063-
if (libraryHint && libraryHint->isValid())
6064-
address = libraryHint->getAddressOfSymbol(name.data());
6065-
else
6066-
address = llvm::sys::DynamicLibrary::
6067-
SearchForAddressOfSymbol(name.data());
6068+
auto *handle = libraryHandleHint ? libraryHandleHint : RTLD_DEFAULT;
6069+
address = dlsym(handle, name);
60686070
}
6071+
#endif
60696072
return address;
60706073
}

lib/AST/CompilerPlugin.cpp

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,12 @@
2424
#include "swift/Parse/Lexer.h"
2525
#include "swift/Subsystems.h"
2626
#include "llvm/Config/config.h"
27-
#include "llvm/Support/DynamicLibrary.h"
2827
#include <cstdlib>
2928

29+
#if !defined(_WIN32)
30+
#include <dlfcn.h>
31+
#endif
32+
3033
using namespace swift;
3134

3235
#define ALLMACROS_PROPERTY_NAME "allMacros"
@@ -56,8 +59,7 @@ void swift_ASTGen_getMacroTypes(const void *getter,
5659
#endif
5760

5861
static const void *
59-
getMacroRegistrationPropertyGetter(llvm::sys::DynamicLibrary library,
60-
StringRef moduleName,
62+
getMacroRegistrationPropertyGetter(void *library, StringRef moduleName,
6163
ASTContext &ctx) {
6264
assert(!moduleName.empty());
6365
// TODO: Consider using runtime lookup to get all types that conform to the
@@ -147,23 +149,28 @@ getMacroRegistrationPropertyGetter(llvm::sys::DynamicLibrary library,
147149
assert(mangleResult.isSuccess());
148150
name = mangleResult.result();
149151
}
150-
return ctx.getAddressOfSymbol(name, &library);
152+
return ctx.getAddressOfSymbol(name.c_str(), library);
151153
}
152154

153155
void ASTContext::loadCompilerPlugins() {
154-
for (StringRef path : SearchPathOpts.getCompilerPluginLibraryPaths()) {
155-
std::string errorMsg;
156-
auto lib = llvm::sys::DynamicLibrary::getPermanentLibrary(
157-
path.data(), &errorMsg);
158-
if (!lib.isValid()) {
156+
for (auto &path : SearchPathOpts.getCompilerPluginLibraryPaths()) {
157+
void *lib = nullptr;
158+
#if !defined(_WIN32)
159+
lib = dlopen(path.c_str(), RTLD_LAZY|RTLD_LOCAL);
160+
#endif
161+
if (!lib) {
162+
const char *errorMsg = "Unsupported platform";
163+
#if !defined(_WIN32)
164+
errorMsg = dlerror();
165+
#endif
159166
Diags.diagnose(SourceLoc(), diag::compiler_plugin_not_loaded, path,
160167
errorMsg);
161168
continue;
162169
}
163170
auto moduleName = llvm::sys::path::filename(path);
164-
#if !defined(_WIN32)
171+
#if !defined(_WIN32)
165172
moduleName.consume_front("lib");
166-
#endif
173+
#endif
167174
moduleName.consume_back(LTDL_SHLIB_EXT);
168175
auto *getter = getMacroRegistrationPropertyGetter(lib, moduleName, *this);
169176
if (!getter) {
@@ -175,7 +182,7 @@ void ASTContext::loadCompilerPlugins() {
175182
// Note: We don't currently have a way to poke at the contents of a Swift
176183
// array `[Any.Type]` from C++. But this should not be an issue for release
177184
// toolchains where user-defined macros will be used.
178-
#if SWIFT_SWIFT_PARSER
185+
#if SWIFT_SWIFT_PARSER
179186
const void *const *metatypesAddress;
180187
ptrdiff_t metatypeCount;
181188
swift_ASTGen_getMacroTypes(getter, &metatypesAddress, &metatypeCount);
@@ -186,7 +193,7 @@ void ASTContext::loadCompilerPlugins() {
186193
LoadedPlugins.try_emplace(name, std::move(plugin));
187194
}
188195
free(const_cast<void *>((const void *)metatypes.data()));
189-
#endif
196+
#endif // SWIFT_SWIFT_PARSER
190197
}
191198
}
192199

@@ -197,8 +204,7 @@ using WitnessTableLookupFn = const void *(const void *type,
197204
extern "C" WitnessTableLookupFn swift_conformsToProtocol;
198205
#endif
199206

200-
CompilerPlugin::CompilerPlugin(const void *metadata,
201-
llvm::sys::DynamicLibrary parentLibrary,
207+
CompilerPlugin::CompilerPlugin(const void *metadata, void *parentLibrary,
202208
ASTContext &ctx)
203209
: metadata(metadata), parentLibrary(parentLibrary)
204210
{
@@ -208,6 +214,8 @@ CompilerPlugin::CompilerPlugin(const void *metadata,
208214
#endif
209215
void *protocolDescriptor =
210216
ctx.getAddressOfSymbol(COMPILER_PLUGIN_PROTOCOL_DESCRIPTOR);
217+
assert(swift_conformsToProtocol);
218+
assert(protocolDescriptor);
211219
witnessTable = swift_conformsToProtocol(metadata, protocolDescriptor);
212220
assert(witnessTable && "Type does not conform to _CompilerPlugin");
213221
auto returnedName = invokeName();
@@ -216,6 +224,12 @@ CompilerPlugin::CompilerPlugin(const void *metadata,
216224
kind = invokeKind();
217225
}
218226

227+
CompilerPlugin::~CompilerPlugin() {
228+
#if !defined(_WIN32)
229+
dlclose(parentLibrary);
230+
#endif
231+
}
232+
219233
namespace {
220234
struct CharBuffer {
221235
const char *data;
@@ -280,3 +294,28 @@ CompilerPlugin::invokeRewrite(StringRef targetModuleName,
280294
llvm_unreachable("Incompatible host compiler");
281295
#endif
282296
}
297+
298+
Optional<StringRef>
299+
CompilerPlugin::invokeGenericSignature() const {
300+
#if __clang__
301+
using Method = SWIFT_CC CharBuffer(
302+
SWIFT_CONTEXT const void *, const void *, const void *);
303+
auto method = getWitnessMethodUnsafe<Method>(
304+
WitnessTableEntry::GenericSignature);
305+
return method(metadata, metadata, witnessTable).str();
306+
#else
307+
llvm_unreachable("Incompatible host compiler");
308+
#endif
309+
}
310+
311+
StringRef CompilerPlugin::invokeTypeSignature() const {
312+
#if __clang__
313+
using Method = SWIFT_CC CharBuffer(
314+
SWIFT_CONTEXT const void *, const void *, const void *);
315+
auto method = getWitnessMethodUnsafe<Method>(
316+
WitnessTableEntry::TypeSignature);
317+
return method(metadata, metadata, witnessTable).str();
318+
#else
319+
llvm_unreachable("Incompatible host compiler");
320+
#endif
321+
}

lib/CompilerPluginSupport/CompilerPluginSupport.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,16 @@ public protocol _CompilerPlugin {
5757
localSourceText: UnsafePointer<UInt8>,
5858
localSourceTextCount: Int
5959
) -> (UnsafePointer<UInt8>?, count: Int)
60+
61+
/// Returns the generic signature of the plugin.
62+
///
63+
/// - Returns: A newly allocated buffer containing the generic signature.
64+
/// The caller is responsible for managing the memory.
65+
static func _genericSignature() -> (UnsafePointer<UInt8>?, count: Int)
66+
67+
/// Returns the type signature of the plugin.
68+
///
69+
/// - Returns: A newly allocated buffer containing the type signature. The
70+
/// caller is responsible for managing the memory.
71+
static func _typeSignature() -> (UnsafePointer<UInt8>, count: Int)
6072
}

lib/Sema/CSGen.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3635,10 +3635,10 @@ namespace {
36353635
auto macroIdent = expr->getMacroName().getBaseIdentifier();
36363636
auto refType = CS.getTypeOfMacroReference(macroIdent.str(), expr);
36373637
if (!refType) {
3638-
// FIXME: This is currently hard-coded to (Int, String) just for
3639-
// testing Stringify, before we can parse a type signature from the
3640-
// macro plugin.
3641-
return TupleType::get({ctx.getIntType(), ctx.getStringType()}, ctx);
3638+
ctx.Diags.diagnose(expr->getMacroNameLoc(), diag::macro_undefined,
3639+
macroIdent)
3640+
.highlight(expr->getMacroNameLoc().getSourceRange());
3641+
return Type();
36423642
}
36433643
if (expr->getArgs()) {
36443644
CS.associateArgumentList(CS.getConstraintLocator(expr), expr->getArgs());

0 commit comments

Comments
 (0)