Skip to content

Commit 07b4018

Browse files
committed
[Macros] Resolve in-process macros via external type name.
This approach works for both macros built into the compiler (e.g., the builtin macros) as well as those that are loaded via plugin but don't conform to the _CompilerPluginSupport protocol. This eliminates all uses of the `MacroSystem` itself in ASTGen, and pushes more of the implementation through ASTGen.
1 parent 0f31305 commit 07b4018

File tree

6 files changed

+72
-47
lines changed

6 files changed

+72
-47
lines changed

include/swift/AST/CompilerPlugin.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ class CompilerPlugin {
7474
return reinterpret_cast<const Func *const *>(witnessTable)[(unsigned)entry];
7575
}
7676

77-
public:
78-
CompilerPlugin(const void *metadata, void *parentLibrary, ASTContext &ctx);
77+
CompilerPlugin(
78+
const void *metadata, void *parentLibrary, const void *witnessTable);
7979

8080
private:
8181
/// Invoke the `_kind` method.
@@ -86,6 +86,9 @@ class CompilerPlugin {
8686
CompilerPlugin(const CompilerPlugin &) = delete;
8787
CompilerPlugin(CompilerPlugin &&) = default;
8888

89+
/// Try to resolve a compiler plugin given the metadata point.
90+
static CompilerPlugin *fromMetatype(const void *metadata, ASTContext &ctx);
91+
8992
/// Invoke the `_rewrite` method. The caller assumes ownership of the result
9093
/// string buffer and diagnostic buffers.
9194
Optional<NullTerminatedStringRef> invokeRewrite(

lib/AST/CompilerPlugin.cpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,24 +57,37 @@ using WitnessTableLookupFn = const void *(const void *type,
5757
extern "C" WitnessTableLookupFn swift_conformsToProtocol;
5858
#endif
5959

60-
CompilerPlugin::CompilerPlugin(const void *metadata, void *parentLibrary,
61-
ASTContext &ctx)
62-
: metadata(metadata), parentLibrary(parentLibrary)
60+
CompilerPlugin::CompilerPlugin(
61+
const void *metadata, void *parentLibrary, const void *witnessTable)
62+
: metadata(metadata), parentLibrary(parentLibrary),
63+
witnessTable(witnessTable)
6364
{
65+
assert(witnessTable && "Type does not conform to _CompilerPlugin");
66+
kind = invokeKind();
67+
}
68+
69+
CompilerPlugin::~CompilerPlugin() { }
70+
71+
CompilerPlugin *CompilerPlugin::fromMetatype(
72+
const void *metadata, ASTContext &ctx
73+
) {
6474
#if !SWIFT_SWIFT_PARSER
6575
auto *swift_conformsToProtocol = reinterpret_cast<WitnessTableLookupFn *>(
6676
ctx.getAddressOfSymbol("swift_conformsToProtocol"));
6777
#endif
6878
void *protocolDescriptor =
6979
ctx.getAddressOfSymbol(COMPILER_PLUGIN_PROTOCOL_DESCRIPTOR);
70-
assert(swift_conformsToProtocol);
71-
assert(protocolDescriptor);
72-
witnessTable = swift_conformsToProtocol(metadata, protocolDescriptor);
73-
assert(witnessTable && "Type does not conform to _CompilerPlugin");
74-
kind = invokeKind();
75-
}
80+
if ((&swift_conformsToProtocol == nullptr) || !protocolDescriptor)
81+
return nullptr;
7682

77-
CompilerPlugin::~CompilerPlugin() { }
83+
auto witnessTable = swift_conformsToProtocol(metadata, protocolDescriptor);
84+
if (!witnessTable)
85+
return nullptr;
86+
87+
auto plugin = new CompilerPlugin(metadata, nullptr, witnessTable);
88+
ctx.addCleanup([plugin] { delete plugin; });
89+
return plugin;
90+
}
7891

7992
namespace {
8093
// Corresponds to Swift type `(UnsafePointer<UInt8>, Int)`.

lib/ASTGen/Sources/ASTGen/Macros.swift

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,20 @@ struct ExportedMacro {
2727
var macro: Macro.Type
2828
}
2929

30-
/// Look up a macro with the given name.
30+
/// Resolve a reference to type metadata into a macro, if posible.
3131
///
3232
/// Returns an unmanaged pointer to an ExportedMacro instance that describes
3333
/// the specified macro. If there is no macro with the given name, produces
3434
/// nil.
35-
@_cdecl("swift_ASTGen_lookupMacro")
36-
public func lookupMacro(
37-
macroNamePtr: UnsafePointer<UInt8>
35+
@_cdecl("swift_ASTGen_resolveMacroType")
36+
public func resolveMacroType(
37+
macroTypePtr: UnsafePointer<UInt8>
3838
) -> UnsafeRawPointer? {
39-
let macroSystem = MacroSystem.exampleSystem
39+
let macroType = unsafeBitCast(macroTypePtr, to: Any.Type.self)
4040

41-
// Look for a macro with this name.
42-
let macroName = String(cString: macroNamePtr)
43-
guard let macro = macroSystem.lookup(macroName) else { return nil }
41+
guard let macro = macroType as? Macro.Type else {
42+
return nil
43+
}
4444

4545
// Allocate and initialize the exported macro.
4646
let exportedPtr = UnsafeMutablePointer<ExportedMacro>.allocate(capacity: 1)
@@ -158,3 +158,16 @@ func evaluateMacro(
158158
return 0
159159
}
160160
}
161+
162+
// Makes sure that the type metadata for these macros can be found.
163+
public var allBuiltinMacros: [Any.Type] = [
164+
ColorLiteralMacro.self,
165+
ColumnMacro.self,
166+
FileIDMacro.self,
167+
FileLiteralMacro.self,
168+
FilePathMacro.self,
169+
FunctionMacro.self,
170+
ImageLiteralMacro.self,
171+
LineMacro.self,
172+
StringifyMacro.self
173+
]

lib/Sema/TypeCheckMacros.cpp

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636
using namespace swift;
3737

38-
extern "C" void *swift_ASTGen_lookupMacro(const char *macroName);
38+
extern "C" void *swift_ASTGen_resolveMacroType(const void *macroType);
3939

4040
extern "C" void swift_ASTGen_destroyMacro(void *macro);
4141

@@ -101,34 +101,30 @@ MacroDefinition MacroDefinitionRequest::evaluate(
101101
#if SWIFT_SWIFT_PARSER
102102
ASTContext &ctx = macro->getASTContext();
103103

104-
// FIXME: We need to perform lookups by resolving the external module name.
105-
106-
StringRef macroName = macro->getName().getBaseName().userFacingName();
107-
// Look for a builtin macro with this name.
108-
if (auto *builtinHandle = swift_ASTGen_lookupMacro(
109-
macroName.str().c_str())) {
110-
// Make sure we clean up after the macro.
111-
ctx.addCleanup([builtinHandle]() {
112-
swift_ASTGen_destroyMacro(builtinHandle);
113-
});
114-
115-
return MacroDefinition::forBuiltin(
116-
MacroDefinition::Expression, builtinHandle);
117-
}
118-
119104
/// Look for the type metadata given the external module and type names.
120105
auto macroMetatype = lookupMacroTypeMetadataByExternalName(
121106
ctx, macro->externalModuleName.str(),
122107
macro->externalMacroTypeName.str());
123108
if (macroMetatype) {
124-
auto plugin = new CompilerPlugin(macroMetatype, nullptr, ctx);
125-
ctx.addCleanup([plugin] { delete plugin; });
126-
// FIXME: Handle other kinds of macros.
127-
return MacroDefinition::forCompilerPlugin(
128-
MacroDefinition::Expression, plugin);
129-
}
109+
// Check whether the macro metatype can be handled as a compiler plugin.
110+
// We look here first, because compiler plugins are meant to be resilient.
111+
if (auto plugin = CompilerPlugin::fromMetatype(macroMetatype, ctx)) {
112+
// FIXME: Handle other kinds of macros.
113+
return MacroDefinition::forCompilerPlugin(
114+
MacroDefinition::Expression, plugin);
115+
}
130116

117+
// Otherwise, check whether the macro metatype can be handled as a builtin.
118+
if (auto builtin = swift_ASTGen_resolveMacroType(macroMetatype)) {
119+
// Make sure we clean up after the macro.
120+
ctx.addCleanup([builtin]() {
121+
swift_ASTGen_destroyMacro(builtin);
122+
});
131123

124+
return MacroDefinition::forBuiltin(
125+
MacroDefinition::Expression, builtin);
126+
}
127+
}
132128
#endif
133129

134130
ctx.Diags.diagnose(
@@ -206,7 +202,7 @@ Expr *swift::expandMacroExpr(
206202
/*range*/ Lexer::getCharSourceRangeFromSourceRange(
207203
sourceMgr, expr->getSourceRange()), ctx, pluginDiags);
208204
for (auto &diag : pluginDiags) {
209-
\ auto loc = sourceMgr.getLocForOffset(*bufferID, diag.position);
205+
auto loc = sourceMgr.getLocForOffset(*bufferID, diag.position);
210206
Diag<DeclName, StringRef> diagID;
211207
switch (diag.severity) {
212208
case CompilerPlugin::DiagnosticSeverity::Note:

test/Macros/builtin_macros.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// RUN: %target-swift-frontend -enable-experimental-feature Macros -enable-experimental-feature BuiltinMacros -dump-ast %s -module-name MacrosTest 2>&1 | %FileCheck %s
22
// REQUIRES: OS=macosx
33

4-
macro function<T: ExpressibleByStringLiteral>: T = BuiltinMacros.FunctionMacro
5-
macro line<T: ExpressibleByIntegerLiteral>: T = BuiltinMacros.LineMacro
6-
macro column<T: ExpressibleByIntegerLiteral>: T = BuiltinMacros.ColumnMacro
4+
macro function<T: ExpressibleByStringLiteral>: T = _SwiftSyntaxMacros.FunctionMacro
5+
macro line<T: ExpressibleByIntegerLiteral>: T = _SwiftSyntaxMacros.LineMacro
6+
macro column<T: ExpressibleByIntegerLiteral>: T = _SwiftSyntaxMacros.ColumnMacro
77

88
// CHECK: macro_expansion_expr implicit type='String'
99
// CHECK-NEXT: string_literal_expr{{.*}}Macro expansion of #function in{{.*}}value="MacrosTest"

test/Macros/macros.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: %target-swift-frontend -enable-experimental-feature Macros -dump-ast %s -module-name MacrosTest 2>&1 | %FileCheck %s
22
// REQUIRES: OS=macosx
33

4-
macro stringify<T>(_ value: T) -> (T, String) = BuiltinMacros.StringifyMacro
4+
macro stringify<T>(_ value: T) -> (T, String) = _SwiftSyntaxMacros.StringifyMacro
55

66
func test(a: Int, b: Int) {
77
let s = #stringify(a + b)

0 commit comments

Comments
 (0)