Skip to content

Commit ff803c6

Browse files
committed
Sema: Move the availability macros cache to the ASTContext
The availability macros definitions are parsed from the command line and stored in a cache. The cache was in the Parser, which would have it be computed for each file using availability macros. Let's move it to the ASTContext instead where it can generally be computed once per invocation and used across the module. rdar://134797088
1 parent 353a1c2 commit ff803c6

File tree

6 files changed

+67
-36
lines changed

6 files changed

+67
-36
lines changed

include/swift/AST/ASTContext.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ namespace swift {
6969
class AbstractFunctionDecl;
7070
class ASTContext;
7171
enum class Associativity : unsigned char;
72+
class AvailabilityMacroMap;
7273
class AvailabilityRange;
7374
class BoundGenericType;
7475
class BuiltinTupleDecl;
@@ -987,6 +988,12 @@ class ASTContext final {
987988
return getMultiPayloadEnumTagSinglePayloadAvailability();
988989
}
989990

991+
/// Cache of the availability macros parsed from the command line arguments.
992+
///
993+
/// This is an implementation detail, access via
994+
/// \c Parser::parseAllAvailabilityMacroArguments.
995+
AvailabilityMacroMap &getAvailabilityMacroCache() const;
996+
990997
/// Test support utility for loading a platform remap file
991998
/// in case an SDK is not specified to the compilation.
992999
const clang::DarwinSDKInfo::RelatedTargetVersionMapping *

include/swift/AST/AvailabilitySpec.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,19 @@ class OtherPlatformAvailabilitySpec : public AvailabilitySpec {
215215
}
216216
};
217217

218+
/// Maps of macro name and version to availability specifications.
219+
/// Organized as two nested \c DenseMap keyed first on the macro name then
220+
/// the macro version. This structure allows to peek at macro names before
221+
/// parsing a version tuple.
222+
class AvailabilityMacroMap {
223+
public:
224+
typedef llvm::DenseMap<llvm::VersionTuple,
225+
SmallVector<AvailabilitySpec *, 4>> VersionEntry;
226+
227+
bool WasParsed = false;
228+
llvm::DenseMap<StringRef, VersionEntry> Impl;
229+
};
230+
218231
} // end namespace swift
219232

220233
#endif

include/swift/Parse/Parser.h

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -346,22 +346,6 @@ class Parser {
346346
/// This vector is managed by \c StructureMarkerRAII objects.
347347
llvm::SmallVector<StructureMarker, 16> StructureMarkers;
348348

349-
/// Maps of macro name and version to availability specifications.
350-
typedef llvm::DenseMap<llvm::VersionTuple,
351-
SmallVector<AvailabilitySpec *, 4>>
352-
AvailabilityMacroVersionMap;
353-
typedef llvm::DenseMap<StringRef, AvailabilityMacroVersionMap>
354-
AvailabilityMacroMap;
355-
356-
/// Cache of the availability macros parsed from the command line arguments.
357-
/// Organized as two nested \c DenseMap keyed first on the macro name then
358-
/// the macro version. This structure allows to peek at macro names before
359-
/// parsing a version tuple.
360-
AvailabilityMacroMap AvailabilityMacros;
361-
362-
/// Has \c AvailabilityMacros been computed?
363-
bool AvailabilityMacrosComputed = false;
364-
365349
public:
366350
Parser(unsigned BufferID, SourceFile &SF, DiagnosticEngine* LexerDiags,
367351
SILParserStateBase *SIL, PersistentParserState *PersistentState);
@@ -2080,7 +2064,7 @@ class Parser {
20802064
parseAvailabilityMacro(SmallVectorImpl<AvailabilitySpec *> &Specs);
20812065

20822066
/// Parse the availability macros definitions passed as arguments.
2083-
void parseAllAvailabilityMacroArguments();
2067+
AvailabilityMacroMap &parseAllAvailabilityMacroArguments();
20842068

20852069
/// Result of parsing an availability macro definition.
20862070
struct AvailabilityMacroDefinition {

lib/AST/ASTContext.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,9 @@ struct ASTContext::Implementation {
426426
/// Singleton used to cache the import graph.
427427
swift::namelookup::ImportCache TheImportCache;
428428

429+
/// Cache of availability macros parsed from the command line.
430+
AvailabilityMacroMap TheAvailabilityMacroCache;
431+
429432
/// The module loader used to load Clang modules.
430433
ClangModuleLoader *TheClangModuleLoader = nullptr;
431434

@@ -2281,6 +2284,10 @@ swift::namelookup::ImportCache &ASTContext::getImportCache() const {
22812284
return getImpl().TheImportCache;
22822285
}
22832286

2287+
AvailabilityMacroMap &ASTContext::getAvailabilityMacroCache() const {
2288+
return getImpl().TheAvailabilityMacroCache;
2289+
}
2290+
22842291
ClangModuleLoader *ASTContext::getClangModuleLoader() const {
22852292
return getImpl().TheClangModuleLoader;
22862293
}

lib/Parse/ParseDecl.cpp

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2063,22 +2063,20 @@ void Parser::parseObjCSelector(SmallVector<Identifier, 4> &Names,
20632063
}
20642064

20652065
bool Parser::peekAvailabilityMacroName() {
2066-
parseAllAvailabilityMacroArguments();
2067-
AvailabilityMacroMap Map = AvailabilityMacros;
2066+
AvailabilityMacroMap &Map = parseAllAvailabilityMacroArguments();
20682067

20692068
StringRef MacroName = Tok.getText();
2070-
return Map.find(MacroName) != Map.end();
2069+
return Map.Impl.find(MacroName) != Map.Impl.end();
20712070
}
20722071

20732072
ParserStatus
20742073
Parser::parseAvailabilityMacro(SmallVectorImpl<AvailabilitySpec *> &Specs) {
20752074
// Get the macros from the compiler arguments.
2076-
parseAllAvailabilityMacroArguments();
2077-
AvailabilityMacroMap Map = AvailabilityMacros;
2075+
AvailabilityMacroMap &Map = parseAllAvailabilityMacroArguments();
20782076

20792077
StringRef MacroName = Tok.getText();
2080-
auto NameMatch = Map.find(MacroName);
2081-
if (NameMatch == Map.end())
2078+
auto NameMatch = Map.Impl.find(MacroName);
2079+
if (NameMatch == Map.Impl.end())
20822080
return makeParserSuccess(); // No match, it could be a standard platform.
20832081

20842082
consumeToken();
@@ -2114,11 +2112,10 @@ Parser::parseAvailabilityMacro(SmallVectorImpl<AvailabilitySpec *> &Specs) {
21142112
return makeParserSuccess();
21152113
}
21162114

2117-
void Parser::parseAllAvailabilityMacroArguments() {
2118-
2119-
if (AvailabilityMacrosComputed) return;
2120-
2121-
AvailabilityMacroMap Map;
2115+
AvailabilityMacroMap &Parser::parseAllAvailabilityMacroArguments() {
2116+
AvailabilityMacroMap &Map = Context.getAvailabilityMacroCache();
2117+
if (Map.WasParsed)
2118+
return Map;
21222119

21232120
SourceManager &SM = Context.SourceMgr;
21242121
LangOptions LangOpts = Context.LangOpts;
@@ -2156,9 +2153,9 @@ void Parser::parseAllAvailabilityMacroArguments() {
21562153
ParsedMacro.Specs = SpecsCopy;
21572154

21582155
// Find the macro info by name.
2159-
AvailabilityMacroVersionMap MacroDefinition;
2160-
auto NameMatch = Map.find(ParsedMacro.Name);
2161-
if (NameMatch != Map.end()) {
2156+
AvailabilityMacroMap::VersionEntry MacroDefinition;
2157+
auto NameMatch = Map.Impl.find(ParsedMacro.Name);
2158+
if (NameMatch != Map.Impl.end()) {
21622159
MacroDefinition = NameMatch->getSecond();
21632160
}
21642161

@@ -2171,12 +2168,12 @@ void Parser::parseAllAvailabilityMacroArguments() {
21712168
}
21722169

21732170
// Save back the macro spec.
2174-
Map.erase(ParsedMacro.Name);
2175-
Map.insert({ParsedMacro.Name, MacroDefinition});
2171+
Map.Impl.erase(ParsedMacro.Name);
2172+
Map.Impl.insert({ParsedMacro.Name, MacroDefinition});
21762173
}
21772174

2178-
AvailabilityMacros = Map;
2179-
AvailabilityMacrosComputed = true;
2175+
Map.WasParsed = true;
2176+
return Map;
21802177
}
21812178

21822179
ParserStatus Parser::parsePlatformVersionInList(StringRef AttrName,
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t --leading-lines
3+
4+
// RUN: not %target-swift-frontend -typecheck -diagnostic-style llvm \
5+
// RUN: %t/FileA.swift %t/FileB.swift \
6+
// RUN: -define-availability "_justAName" \
7+
// RUN: 2>&1 | %FileCheck %s
8+
9+
// CHECK: -define-availability argument:1:11: error: expected ':' after '_justAName' in availability macro definition
10+
// CHECK-NEXT: _justAName
11+
12+
/// It's parsed once so the diagnostic is produced once as well.
13+
// CHECK-NOT: _justAName
14+
15+
//--- FileA.swift
16+
17+
@available(_triggerParsingMacros)
18+
public func brokenPlatforms() {}
19+
20+
//--- FileB.swift
21+
22+
@available(_triggerParsingMacros)
23+
public func brokenPlatforms() {}

0 commit comments

Comments
 (0)