Skip to content

Commit 8150fb0

Browse files
[InterfaceFile] Improve flag extraction from interface file
Improve the version/flags extract from interface file by moving away from using Regex and limiting the search to the beginning of the file. Switch away from Regex will give 5-10% improvement in time and instruction counts, and limiting the search lines can save a lot of time if the swiftinterface is large. For example, the extract time for Swift stdlib is 10x faster after the patch. Current strategey for limiting the line to search is by only parsing the first comment block.
1 parent 56ec625 commit 8150fb0

File tree

5 files changed

+34
-24
lines changed

5 files changed

+34
-24
lines changed

include/swift/Frontend/ModuleInterfaceSupport.h

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#define SWIFT_COMPILER_VERSION_KEY "swift-compiler-version"
2323
#define SWIFT_MODULE_FLAGS_KEY "swift-module-flags"
2424
#define SWIFT_MODULE_FLAGS_IGNORABLE_KEY "swift-module-flags-ignorable"
25+
#define SWIFT_MODULE_FLAGS_IGNORABLE_PRIVATE_KEY \
26+
"swift-module-flags-ignorable-private"
2527

2628
namespace swift {
2729

lib/Serialization/SerializedModuleLoader.cpp

+32-21
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "llvm/Support/MemoryBuffer.h"
4242
#include "llvm/Support/Path.h"
4343
#include "llvm/Support/CommandLine.h"
44+
#include <optional>
4445
#include <system_error>
4546

4647
using namespace swift;
@@ -1389,17 +1390,33 @@ static bool tripleNeedsSubarchitectureAdjustment(const llvm::Triple &lhs, const
13891390
lhs.getEnvironment() == rhs.getEnvironment());
13901391
}
13911392

1393+
static std::optional<StringRef> getFlagsFromInterfaceFile(StringRef &file,
1394+
StringRef prefix) {
1395+
StringRef line, buffer = file;
1396+
while (!buffer.empty()) {
1397+
std::tie(line, buffer) = buffer.split('\n');
1398+
// If the line is no longer comments, return not found.
1399+
if (!line.consume_front("// "))
1400+
return std::nullopt;
1401+
1402+
if (line.consume_front(prefix) && line.consume_front(":")) {
1403+
file = buffer;
1404+
return line;
1405+
}
1406+
}
1407+
1408+
return std::nullopt;
1409+
}
1410+
13921411
bool swift::extractCompilerFlagsFromInterface(
13931412
StringRef interfacePath, StringRef buffer, llvm::StringSaver &ArgSaver,
13941413
SmallVectorImpl<const char *> &SubArgs,
13951414
std::optional<llvm::Triple> PreferredTarget,
13961415
std::optional<llvm::Triple> PreferredTargetVariant) {
1397-
SmallVector<StringRef, 1> FlagMatches;
1398-
auto FlagRe = llvm::Regex("^// swift-module-flags:(.*)$", llvm::Regex::Newline);
1399-
if (!FlagRe.match(buffer, &FlagMatches))
1416+
auto FlagMatch = getFlagsFromInterfaceFile(buffer, SWIFT_MODULE_FLAGS_KEY);
1417+
if (!FlagMatch)
14001418
return true;
1401-
assert(FlagMatches.size() == 2);
1402-
llvm::cl::TokenizeGNUCommandLine(FlagMatches[1], ArgSaver, SubArgs);
1419+
llvm::cl::TokenizeGNUCommandLine(*FlagMatch, ArgSaver, SubArgs);
14031420

14041421
// If the target triple parsed from the Swift interface file differs
14051422
// only in subarchitecture from the compatible target triple, then
@@ -1421,28 +1438,22 @@ bool swift::extractCompilerFlagsFromInterface(
14211438
}
14221439
}
14231440

1424-
SmallVector<StringRef, 1> IgnFlagMatches;
1425-
// Cherry-pick supported options from the ignorable list.
1426-
auto IgnFlagRe = llvm::Regex("^// swift-module-flags-ignorable:(.*)$",
1427-
llvm::Regex::Newline);
1428-
auto hasIgnorableFlags = IgnFlagRe.match(buffer, &IgnFlagMatches);
1429-
1430-
// Check for ignorable-private flags
1431-
SmallVector<StringRef, 1> IgnPrivateFlagMatches;
1432-
auto IgnPrivateFlagRe = llvm::Regex("^// swift-module-flags-ignorable-private:(.*)$",
1433-
llvm::Regex::Newline);
1434-
auto hasIgnorablePrivateFlags = IgnPrivateFlagRe.match(buffer, &IgnPrivateFlagMatches);
1441+
auto IgnFlagMatch =
1442+
getFlagsFromInterfaceFile(buffer, SWIFT_MODULE_FLAGS_IGNORABLE_KEY);
1443+
auto IgnPrivateFlagMatch = getFlagsFromInterfaceFile(
1444+
buffer, SWIFT_MODULE_FLAGS_IGNORABLE_PRIVATE_KEY);
14351445

14361446
// It's OK the interface doesn't have the ignorable list (private or not), we just
14371447
// ignore them all.
1438-
if (!hasIgnorableFlags && !hasIgnorablePrivateFlags)
1448+
if (!IgnFlagMatch && !IgnPrivateFlagMatch)
14391449
return false;
14401450

14411451
SmallVector<const char *, 8> IgnSubArgs;
1442-
if (hasIgnorableFlags)
1443-
llvm::cl::TokenizeGNUCommandLine(IgnFlagMatches[1], ArgSaver, IgnSubArgs);
1444-
if (hasIgnorablePrivateFlags)
1445-
llvm::cl::TokenizeGNUCommandLine(IgnPrivateFlagMatches[1], ArgSaver, IgnSubArgs);
1452+
if (IgnFlagMatch)
1453+
llvm::cl::TokenizeGNUCommandLine(*IgnFlagMatch, ArgSaver, IgnSubArgs);
1454+
if (IgnPrivateFlagMatch)
1455+
llvm::cl::TokenizeGNUCommandLine(*IgnPrivateFlagMatch, ArgSaver,
1456+
IgnSubArgs);
14461457

14471458
std::unique_ptr<llvm::opt::OptTable> table = swift::createSwiftOptTable();
14481459
unsigned missingArgIdx = 0;

test/ModuleInterface/SmokeTest.swiftinterface

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// The "flags" line in this test deliberately has no flags and no space after
22
// the colon, just to make sure that works (even though it'll never be printed
33
// that way).
4-
54
// swift-module-flags:
65
// swift-interface-format-version: 1.0
76

test/ModuleInterface/noncopyable_generics_interface_extensions.swift

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// RUN: %target-swift-typecheck-module-from-interface(%t/bug.swiftinterface) -I %t
44

55
//--- bug.swiftinterface
6-
76
// swift-interface-format-version: 1.0
87
// swift-compiler-version: Apple Swift version 6.0 effective-5.10 (swiftlang-6.0.0.4.52 clang-1600.0.21.1.3)
98
// swift-module-flags: -enable-objc-interop -enable-library-evolution -module-name bug

test/SPI/spi_only_import_flag_check.swift

-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
@_spiOnly import Empty // expected-error {{'@_spiOnly' requires setting the frontend flag '-experimental-spi-only-imports'}}
3232

3333
//--- Client.private.swiftinterface
34-
3534
// swift-interface-format-version: 1.0
3635
// swift-compiler-version: Swift version 5.8-dev effective-4.1.50
3736
// swift-module-flags: -swift-version 4 -module-name Client

0 commit comments

Comments
 (0)