Skip to content

Commit 9318937

Browse files
Merge pull request #75082 from cachemeifyoucan/eng/PR-131214106
[Macro] Fix bugs in macro dependency scanning
2 parents 588a7db + da10a02 commit 9318937

File tree

9 files changed

+252
-16
lines changed

9 files changed

+252
-16
lines changed

include/swift-c/DependencyScan/DependencyScan.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ typedef struct swiftscan_dependency_info_s *swiftscan_dependency_info_t;
4949
/// Opaque container to a link library info.
5050
typedef struct swiftscan_link_library_info_s *swiftscan_link_library_info_t;
5151

52+
/// Opaque container to a macro dependency.
53+
typedef struct swiftscan_macro_dependency_s *swiftscan_macro_dependency_t;
54+
5255
/// Opaque container to an overall result of a dependency scan.
5356
typedef struct swiftscan_dependency_graph_s *swiftscan_dependency_graph_t;
5457

@@ -73,6 +76,12 @@ typedef struct {
7376
size_t count;
7477
} swiftscan_link_library_set_t;
7578

79+
/// Set of macro dependency
80+
typedef struct {
81+
swiftscan_macro_dependency_t *macro_dependencies;
82+
size_t count;
83+
} swiftscan_macro_dependency_set_t;
84+
7685
typedef enum {
7786
SWIFTSCAN_DIAGNOSTIC_SEVERITY_ERROR = 0,
7887
SWIFTSCAN_DIAGNOSTIC_SEVERITY_WARNING = 1,

include/swift/AST/ModuleDependencies.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ struct CommonSwiftTextualModuleDependencyDetails {
253253
std::vector<std::string> bridgingModuleDependencies;
254254

255255
/// The macro dependencies.
256-
llvm::StringMap<MacroPluginDependency> macroDependencies;
256+
std::map<std::string, MacroPluginDependency> macroDependencies;
257257

258258
/// The Swift frontend invocation arguments to build the Swift module from the
259259
/// interface.
@@ -324,7 +324,7 @@ class SwiftInterfaceModuleDependenciesStorage
324324
void addMacroDependency(StringRef macroModuleName, StringRef libraryPath,
325325
StringRef executablePath) {
326326
textualModuleDetails.macroDependencies.insert(
327-
{macroModuleName, {libraryPath.str(), executablePath.str()}});
327+
{macroModuleName.str(), {libraryPath.str(), executablePath.str()}});
328328
}
329329
};
330330

@@ -380,7 +380,7 @@ class SwiftSourceModuleDependenciesStorage
380380
void addMacroDependency(StringRef macroModuleName, StringRef libraryPath,
381381
StringRef executablePath) {
382382
textualModuleDetails.macroDependencies.insert(
383-
{macroModuleName, {libraryPath.str(), executablePath.str()}});
383+
{macroModuleName.str(), {libraryPath.str(), executablePath.str()}});
384384
}
385385
};
386386

@@ -796,7 +796,7 @@ class ModuleDependencyInfo {
796796
/// For a Source dependency, register a `Testable` import
797797
void addTestableImport(ImportPath::Module module);
798798

799-
/// For a Source dependency, register a macro dependency.
799+
/// For a Source/Textual dependency, register a macro dependency.
800800
void addMacroDependency(StringRef macroModuleName, StringRef libraryPath,
801801
StringRef executablePath);
802802

include/swift/DependencyScan/DependencyScanImpl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ struct swiftscan_link_library_info_s {
7373
bool forceLoad;
7474
};
7575

76+
struct swiftscan_macro_dependency_s {
77+
swiftscan_string_ref_t moduleName;
78+
swiftscan_string_ref_t libraryPath;
79+
swiftscan_string_ref_t executablePath;
80+
};
81+
7682
/// Swift modules to be built from a module interface, may have a bridging
7783
/// header.
7884
typedef struct {
@@ -123,6 +129,9 @@ typedef struct {
123129

124130
/// ModuleCacheKey
125131
swiftscan_string_ref_t module_cache_key;
132+
133+
/// Macro dependecies.
134+
swiftscan_macro_dependency_set_t *macro_dependencies;
126135
} swiftscan_swift_textual_details_t;
127136

128137
/// Swift modules with only a binary module file.

lib/DependencyScan/DependencyScanJSON.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,49 @@ void writeLinkLibraries(llvm::raw_ostream &out,
243243
out << "\n";
244244
}
245245

246+
static void
247+
writeMacroDependencies(llvm::raw_ostream &out,
248+
const swiftscan_macro_dependency_set_t *macro_deps,
249+
unsigned indentLevel, bool trailingComma) {
250+
if (macro_deps->count == 0)
251+
return;
252+
253+
out.indent(indentLevel * 2);
254+
out << "\"macroDependencies\": ";
255+
out << "[\n";
256+
for (size_t i = 0; i < macro_deps->count; ++i) {
257+
const auto &macroInfo = *macro_deps->macro_dependencies[i];
258+
out.indent((indentLevel + 1) * 2);
259+
out << "{\n";
260+
auto entryIndentLevel = ((indentLevel + 2) * 2);
261+
out.indent(entryIndentLevel);
262+
out << "\"moduleName\": ";
263+
writeJSONValue(out, macroInfo.moduleName, indentLevel);
264+
out << ",\n";
265+
out.indent(entryIndentLevel);
266+
out << "\"libraryPath\": ";
267+
writeJSONValue(out, macroInfo.libraryPath, entryIndentLevel);
268+
out << ",\n";
269+
out.indent(entryIndentLevel);
270+
out << "\"executablePath\": ";
271+
writeJSONValue(out, macroInfo.executablePath, entryIndentLevel);
272+
out << "\n";
273+
out.indent((indentLevel + 1) * 2);
274+
out << "}";
275+
if (i != macro_deps->count - 1) {
276+
out << ",";
277+
}
278+
out << "\n";
279+
}
280+
281+
out.indent(indentLevel * 2);
282+
out << "]";
283+
284+
if (trailingComma)
285+
out << ",";
286+
out << "\n";
287+
}
288+
246289
static const swiftscan_swift_textual_details_t *
247290
getAsTextualDependencyModule(swiftscan_module_details_t details) {
248291
if (details->kind == SWIFTSCAN_DEPENDENCY_INFO_SWIFT_TEXTUAL)
@@ -413,6 +456,8 @@ void writeJSON(llvm::raw_ostream &out,
413456
swiftTextualDeps->module_cache_key, 5,
414457
/*trailingComma=*/true);
415458
}
459+
writeMacroDependencies(out, swiftTextualDeps->macro_dependencies, 5,
460+
/*trailingComma=*/true);
416461
writeJSONSingleField(out, "isFramework", swiftTextualDeps->is_framework,
417462
5, commaAfterFramework);
418463
if (swiftTextualDeps->extra_pcm_args->count != 0) {

lib/DependencyScan/ModuleDependencyCacheSerialization.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi
305305
if (!moduleCacheKeyID)
306306
llvm::report_fatal_error("Bad moduleCacheKey");
307307

308-
// TODO: LinkLibraries
308+
// TODO: LinkLibraries, MacroDependencies
309309
// Form the dependencies storage object
310310
auto moduleDep = ModuleDependencyInfo::forSwiftInterfaceModule(
311311
outputModulePath.value(), optionalSwiftInterfaceFile.value(),

lib/DependencyScan/ScanDependencies.cpp

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include "swift-c/DependencyScan/DependencyScan.h"
1314
#include "swift/Basic/PrettyStackTrace.h"
1415

1516
#include "swift/AST/ASTContext.h"
@@ -256,14 +257,6 @@ static llvm::Error resolveExplicitModuleInputs(
256257
: interfaceDepDetails->moduleCacheKey;
257258
commandLine.push_back("-swift-module-file=" + depModuleID.ModuleName + "=" +
258259
path);
259-
// Add the exported macro from interface into current module.
260-
llvm::for_each(
261-
interfaceDepDetails->textualModuleDetails.macroDependencies,
262-
[&](const auto &entry) {
263-
dependencyInfoCopy.addMacroDependency(entry.first(),
264-
entry.second.LibraryPath,
265-
entry.second.ExecutablePath);
266-
});
267260
} break;
268261
case swift::ModuleDependencyKind::SwiftBinary: {
269262
auto binaryDepDetails = depInfo.getAsSwiftBinaryModule();
@@ -282,7 +275,7 @@ static llvm::Error resolveExplicitModuleInputs(
282275
{bridgingHeaderDepName, ModuleDependencyKind::Clang});
283276
const auto bridgingHeaderDepModuleDetails =
284277
optionalBridgingHeaderDepModuleInfo.getAsClangModule();
285-
commandLine.push_back("-Xcc");
278+
commandLine.push_back("-Xcc");
286279
commandLine.push_back(
287280
"-fmodule-map-file=" +
288281
remapPath(bridgingHeaderDepModuleDetails->moduleMapFile));
@@ -372,6 +365,10 @@ static llvm::Error resolveExplicitModuleInputs(
372365
llvm::for_each(
373366
textualDep->auxiliaryFiles,
374367
[&tracker](const std::string &file) { tracker->trackFile(file); });
368+
llvm::for_each(textualDep->textualModuleDetails.macroDependencies,
369+
[&tracker](const auto &entry) {
370+
tracker->trackFile(entry.second.LibraryPath);
371+
});
375372
auto root = tracker->createTreeFromDependencies();
376373
if (!root)
377374
return root.takeError();
@@ -642,6 +639,28 @@ static swiftscan_diagnostic_set_t *mapCollectedDiagnosticsForOutput(
642639
return diagnosticOutput;
643640
}
644641

642+
static swiftscan_macro_dependency_set_t *createMacroDependencySet(
643+
const std::map<std::string, MacroPluginDependency> &macroDeps) {
644+
swiftscan_macro_dependency_set_t *set = new swiftscan_macro_dependency_set_t;
645+
if (macroDeps.empty()) {
646+
set->count = 0;
647+
set->macro_dependencies = nullptr;
648+
return set;
649+
}
650+
set->count = macroDeps.size();
651+
set->macro_dependencies = new swiftscan_macro_dependency_t[set->count];
652+
unsigned SI = 0;
653+
for (auto &entry : macroDeps) {
654+
set->macro_dependencies[SI] = new swiftscan_macro_dependency_s;
655+
set->macro_dependencies[SI]->moduleName = create_clone(entry.first.c_str());
656+
set->macro_dependencies[SI]->libraryPath =
657+
create_clone(entry.second.LibraryPath.c_str());
658+
set->macro_dependencies[SI]->executablePath =
659+
create_clone(entry.second.ExecutablePath.c_str());
660+
}
661+
return set;
662+
}
663+
645664
static swiftscan_dependency_graph_t
646665
generateFullDependencyGraph(const CompilerInstance &instance,
647666
const DependencyScanDiagnosticCollector *diagnosticCollector,
@@ -732,7 +751,9 @@ generateFullDependencyGraph(const CompilerInstance &instance,
732751
.CASFileSystemRootID.c_str()),
733752
create_clone(swiftTextualDeps->textualModuleDetails
734753
.CASBridgingHeaderIncludeTreeRootID.c_str()),
735-
create_clone(swiftTextualDeps->moduleCacheKey.c_str())};
754+
create_clone(swiftTextualDeps->moduleCacheKey.c_str()),
755+
createMacroDependencySet(
756+
swiftTextualDeps->textualModuleDetails.macroDependencies)};
736757
} else if (swiftSourceDeps) {
737758
swiftscan_string_ref_t moduleInterfacePath = create_null();
738759
swiftscan_string_ref_t bridgingHeaderPath =
@@ -767,7 +788,9 @@ generateFullDependencyGraph(const CompilerInstance &instance,
767788
/*IncludeTree*/
768789
create_clone(swiftSourceDeps->textualModuleDetails
769790
.CASBridgingHeaderIncludeTreeRootID.c_str()),
770-
/*CacheKey*/ create_clone("")};
791+
/*CacheKey*/ create_clone(""),
792+
createMacroDependencySet(
793+
swiftSourceDeps->textualModuleDetails.macroDependencies)};
771794
} else if (swiftPlaceholderDeps) {
772795
details->kind = SWIFTSCAN_DEPENDENCY_INFO_SWIFT_PLACEHOLDER;
773796
details->swift_placeholder_details = {

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "swift/AST/DiagnosticsSema.h"
2020
#include "swift/AST/FileSystem.h"
2121
#include "swift/AST/Module.h"
22+
#include "swift/AST/SearchPathOptions.h"
2223
#include "swift/Basic/Assertions.h"
2324
#include "swift/Basic/Platform.h"
2425
#include "swift/Basic/StringExtras.h"
@@ -1697,6 +1698,39 @@ void InterfaceSubContextDelegateImpl::inheritOptionsForBuildingInterface(
16971698
genericSubInvocation.setPlatformAvailabilityInheritanceMapPath(*SearchPathOpts.PlatformAvailabilityInheritanceMapPath);
16981699
}
16991700

1701+
for (auto &entry : SearchPathOpts.PluginSearchOpts) {
1702+
switch (entry.getKind()) {
1703+
case PluginSearchOption::Kind::LoadPluginLibrary: {
1704+
auto &val = entry.get<PluginSearchOption::LoadPluginLibrary>();
1705+
GenericArgs.push_back("-load-plugin-library");
1706+
GenericArgs.push_back(ArgSaver.save(val.LibraryPath));
1707+
break;
1708+
}
1709+
case PluginSearchOption::Kind::LoadPluginExecutable: {
1710+
auto &val = entry.get<PluginSearchOption::LoadPluginExecutable>();
1711+
for (auto &moduleName : val.ModuleNames) {
1712+
GenericArgs.push_back("-load-plugin-executable");
1713+
GenericArgs.push_back(
1714+
ArgSaver.save(val.ExecutablePath + "#" + moduleName));
1715+
}
1716+
break;
1717+
}
1718+
case PluginSearchOption::Kind::PluginPath: {
1719+
auto &val = entry.get<PluginSearchOption::PluginPath>();
1720+
GenericArgs.push_back("-plugin-path");
1721+
GenericArgs.push_back(ArgSaver.save(val.SearchPath));
1722+
break;
1723+
}
1724+
case PluginSearchOption::Kind::ExternalPluginPath: {
1725+
auto &val = entry.get<PluginSearchOption::ExternalPluginPath>();
1726+
GenericArgs.push_back("-external-plugin-path");
1727+
GenericArgs.push_back(
1728+
ArgSaver.save(val.SearchPath + "#" + val.ServerPath));
1729+
break;
1730+
}
1731+
}
1732+
}
1733+
17001734
genericSubInvocation.getFrontendOptions().InputMode
17011735
= FrontendOptions::ParseInputMode::SwiftModuleInterface;
17021736
if (!SearchPathOpts.RuntimeResourcePath.empty()) {

test/CAS/macro_deps.swift

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
/// Test loading dependencies that has macros.
4+
// RUN: %empty-directory(%t)
5+
// RUN: split-file %s %t
6+
7+
/// Build macros.
8+
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroOne) -module-name=MacroOne %t/macro-1.swift
9+
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroTwo) -module-name=MacroTwo %t/macro-2.swift
10+
11+
/// Build binary module that depends on textual module that uses macro.
12+
// RUN: %target-swift-frontend -emit-module -module-cache-path %t/clang-module-cache %t/test.swift -module-name Test -o %t/include/Test.swiftmodule -I %t/include \
13+
// RUN: -O -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -swift-version 5 -external-plugin-path %t#%swift-plugin-server
14+
15+
// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-serialized -module-name MyApp -module-cache-path %t/clang-module-cache -O \
16+
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -I %t/include \
17+
// RUN: %t/main.swift -o %t/deps.json -swift-version 5 -cache-compile-job -cas-path %t/cas -external-plugin-path %t#%swift-plugin-server
18+
19+
// RUN: %{python} %S/Inputs/SwiftDepsExtractor.py %t/deps.json Foo macroDependencies | %FileCheck %s --check-prefix=FOO-DEPS
20+
// FOO-DEPS: MacroOne
21+
// FOO-DEPS-NOT: MacroTwo
22+
23+
// RUN: %{python} %S/Inputs/SwiftDepsExtractor.py %t/deps.json MyApp macroDependencies | %FileCheck %s --check-prefix=APP-DEPS
24+
// APP-DEPS: MacroTwo
25+
// APP-DEPS-NOT: MacroOne
26+
27+
/// Build all dependencies.
28+
// RUN: %S/Inputs/BuildCommandExtractor.py %t/deps.json clang:SwiftShims > %t/SwiftShims.cmd
29+
// RUN: %swift_frontend_plain @%t/SwiftShims.cmd
30+
// RUN: %S/Inputs/BuildCommandExtractor.py %t/deps.json Foo > %t/Foo.cmd
31+
// RUN: %swift_frontend_plain @%t/Foo.cmd
32+
33+
// RUN: %S/Inputs/BuildCommandExtractor.py %t/deps.json MyApp > %t/MyApp.cmd
34+
// RUN: %{python} %S/Inputs/GenerateExplicitModuleMap.py %t/deps.json > %t/map.json
35+
// RUN: llvm-cas --cas %t/cas --make-blob --data %t/map.json > %t/map.casid
36+
37+
// RUN: %target-swift-frontend -diagnostic-style=swift \
38+
// RUN: -emit-module -o %t/Test.swiftmodule -cache-compile-job -cas-path %t/cas \
39+
// RUN: -swift-version 5 -disable-implicit-swift-modules \
40+
// RUN: -external-plugin-path %t#%swift-plugin-server \
41+
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \
42+
// RUN: -module-name MyApp -explicit-swift-module-map-file @%t/map.casid -O \
43+
// RUN: %t/main.swift @%t/MyApp.cmd
44+
45+
//--- macro-1.swift
46+
import SwiftSyntax
47+
@_spi(ExperimentalLanguageFeature) import SwiftSyntaxMacros
48+
49+
public struct AssertMacro: ExpressionMacro {
50+
public static func expansion(
51+
of macro: some FreestandingMacroExpansionSyntax,
52+
in context: some MacroExpansionContext
53+
) -> ExprSyntax {
54+
guard let argument = macro.arguments.first?.expression else {
55+
fatalError("boom")
56+
}
57+
58+
return "assert(\(argument))"
59+
}
60+
}
61+
62+
//--- macro-2.swift
63+
import SwiftSyntax
64+
@_spi(ExperimentalLanguageFeature) import SwiftSyntaxMacros
65+
66+
public struct StringifyMacro: ExpressionMacro {
67+
public static func expansion(
68+
of macro: some FreestandingMacroExpansionSyntax,
69+
in context: some MacroExpansionContext
70+
) -> ExprSyntax {
71+
guard let argument = macro.arguments.first?.expression else {
72+
fatalError("boom")
73+
}
74+
75+
return "(\(argument), \(StringLiteralExprSyntax(content: argument.description)))"
76+
}
77+
}
78+
79+
//--- include/Foo.swiftinterface
80+
// swift-interface-format-version: 1.0
81+
// swift-module-flags: -enable-library-evolution -swift-version 5 -O -module-name Foo -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import
82+
import Swift
83+
public func foo()
84+
@freestanding(expression) public macro assert(_: Bool) = #externalMacro(module: "MacroOne", type: "AssertMacro")
85+
@inlinable
86+
public func assertFalse() {
87+
#assert(false)
88+
}
89+
90+
//--- test.swift
91+
import Foo
92+
@inlinable
93+
public func test() {
94+
#assert(true)
95+
}
96+
97+
//--- main.swift
98+
import Test
99+
@freestanding(expression) macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "MacroTwo", type: "StringifyMacro")
100+
101+
func appTest() {
102+
let str = #stringify("test")
103+
test()
104+
}

0 commit comments

Comments
 (0)