Skip to content

Commit 80d6230

Browse files
authored
Merge pull request swiftlang#29241 from nkcsgexi/refactor-originally-defined
TBDGen: some refactoring to allow multiple platform kinds for linker directives. NFC
2 parents a0b0e36 + caf88fb commit 80d6230

File tree

5 files changed

+114
-65
lines changed

5 files changed

+114
-65
lines changed

include/swift/AST/Attr.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,8 +1606,15 @@ class OriginallyDefinedInAttr: public DeclAttribute {
16061606
/// Indicates when the symbol was moved here.
16071607
const llvm::VersionTuple MovedVersion;
16081608

1609-
/// Returns true if this attribute is active given the current platform.
1610-
bool isActivePlatform(const ASTContext &ctx) const;
1609+
struct ActiveVersion {
1610+
PlatformKind Platform;
1611+
bool IsSimulator;
1612+
llvm::VersionTuple Version;
1613+
};
1614+
1615+
/// Returns non-optional if this attribute is active given the current platform.
1616+
/// The value provides more details about the active platform.
1617+
Optional<ActiveVersion> isActivePlatform(const ASTContext &ctx) const;
16111618
static bool classof(const DeclAttribute *DA) {
16121619
return DA->getKind() == DAK_OriginallyDefinedIn;
16131620
}

lib/AST/Attr.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,8 +1286,16 @@ bool AvailableAttr::isActivePlatform(const ASTContext &ctx) const {
12861286
return isPlatformActive(Platform, ctx.LangOpts);
12871287
}
12881288

1289-
bool OriginallyDefinedInAttr::isActivePlatform(const ASTContext &ctx) const {
1290-
return isPlatformActive(Platform, ctx.LangOpts);
1289+
Optional<OriginallyDefinedInAttr::ActiveVersion>
1290+
OriginallyDefinedInAttr::isActivePlatform(const ASTContext &ctx) const {
1291+
OriginallyDefinedInAttr::ActiveVersion Result;
1292+
Result.Platform = Platform;
1293+
Result.Version = MovedVersion;
1294+
if (isPlatformActive(Platform, ctx.LangOpts)) {
1295+
Result.IsSimulator = ctx.LangOpts.Target.isSimulatorEnvironment();
1296+
return Result;
1297+
}
1298+
return None;
12911299
}
12921300

12931301
bool AvailableAttr::isLanguageVersionSpecific() const {

lib/TBDGen/TBDGen.cpp

Lines changed: 74 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -72,20 +72,31 @@ void TBDGenVisitor::addSymbolInternal(StringRef name,
7272
}
7373
}
7474

75-
static Optional<llvm::VersionTuple> getDeclMoveOSVersion(Decl *D) {
75+
static std::vector<OriginallyDefinedInAttr::ActiveVersion>
76+
getAllMovedPlatformVersions(Decl *D) {
77+
std::vector<OriginallyDefinedInAttr::ActiveVersion> Results;
7678
for (auto *attr: D->getAttrs()) {
7779
if (auto *ODA = dyn_cast<OriginallyDefinedInAttr>(attr)) {
78-
if (ODA->isActivePlatform(D->getASTContext()))
79-
return ODA->MovedVersion;
80+
auto Active = ODA->isActivePlatform(D->getASTContext());
81+
if (Active.hasValue()) {
82+
Results.push_back(*Active);
83+
}
8084
}
8185
}
82-
return None;
86+
return Results;
8387
}
8488

85-
enum class LinkerPlatformId: uint8_t {
86-
#define LD_PLATFORM(Name, Id) Name = Id,
87-
#include "ldPlatformKinds.def"
88-
};
89+
static Optional<llvm::VersionTuple>
90+
getIntroducedOSVersion(Decl *D, PlatformKind Kind) {
91+
for (auto *attr: D->getAttrs()) {
92+
if (auto *ava = dyn_cast<AvailableAttr>(attr)) {
93+
if (ava->Platform == Kind && ava->Introduced) {
94+
return ava->Introduced;
95+
}
96+
}
97+
}
98+
return None;
99+
}
89100

90101
static StringRef getLinkerPlatformName(uint8_t Id) {
91102
switch (Id) {
@@ -103,29 +114,23 @@ static Optional<uint8_t> getLinkerPlatformId(StringRef Platform) {
103114
.Default(None);
104115
}
105116

106-
struct InstallNameStore {
107-
// The default install name to use when no specific install name is specified.
108-
std::string InstallName;
109-
// The install name specific to the platform id. This takes precedence over
110-
// the default install name.
111-
std::map<uint8_t, std::string> PlatformInstallName;
112-
StringRef getInstallName(LinkerPlatformId Id) const {
113-
auto It = PlatformInstallName.find((uint8_t)Id);
114-
if (It == PlatformInstallName.end())
115-
return InstallName;
116-
else
117-
return It->second;
118-
}
119-
void remark(ASTContext &Ctx, StringRef ModuleName) const {
120-
Ctx.Diags.diagnose(SourceLoc(), diag::default_previous_install_name,
121-
ModuleName, InstallName);
122-
for (auto Pair: PlatformInstallName) {
123-
Ctx.Diags.diagnose(SourceLoc(), diag::platform_previous_install_name,
124-
ModuleName, getLinkerPlatformName(Pair.first),
125-
Pair.second);
126-
}
117+
StringRef InstallNameStore::getInstallName(LinkerPlatformId Id) const {
118+
auto It = PlatformInstallName.find((uint8_t)Id);
119+
if (It == PlatformInstallName.end())
120+
return InstallName;
121+
else
122+
return It->second;
123+
}
124+
125+
void InstallNameStore::remark(ASTContext &Ctx, StringRef ModuleName) const {
126+
Ctx.Diags.diagnose(SourceLoc(), diag::default_previous_install_name,
127+
ModuleName, InstallName);
128+
for (auto Pair: PlatformInstallName) {
129+
Ctx.Diags.diagnose(SourceLoc(), diag::platform_previous_install_name,
130+
ModuleName, getLinkerPlatformName(Pair.first),
131+
Pair.second);
127132
}
128-
};
133+
}
129134

130135
static std::string getScalaNodeText(Node *N) {
131136
SmallString<32> Buffer;
@@ -195,37 +200,49 @@ parseEntry(ASTContext &Ctx,
195200
return 0;
196201
}
197202

198-
static std::map<std::string, InstallNameStore>
199-
parsePreviousModuleInstallNameMap(ASTContext &Ctx, StringRef FileName) {
203+
std::unique_ptr<std::map<std::string, InstallNameStore>>
204+
TBDGenVisitor::parsePreviousModuleInstallNameMap() {
205+
StringRef FileName = Opts.ModuleInstallNameMapPath;
206+
// Nothing to parse.
207+
if (FileName.empty())
208+
return nullptr;
200209
namespace yaml = llvm::yaml;
201-
std::map<std::string, InstallNameStore> AllInstallNames;
210+
ASTContext &Ctx = SwiftModule->getASTContext();
211+
std::unique_ptr<std::map<std::string, InstallNameStore>> pResult(
212+
new std::map<std::string, InstallNameStore>());
213+
auto &AllInstallNames = *pResult;
202214
SWIFT_DEFER {
203215
for (auto Pair: AllInstallNames) {
204216
Pair.second.remark(Ctx, Pair.first);
205217
}
206218
};
219+
207220
// Load the input file.
208221
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
209-
vfs::getFileOrSTDIN(*Ctx.SourceMgr.getFileSystem(), FileName);
222+
llvm::MemoryBuffer::getFile(FileName);
210223
if (!FileBufOrErr) {
211224
Ctx.Diags.diagnose(SourceLoc(), diag::previous_installname_map_missing,
212225
FileName);
213-
return AllInstallNames;
226+
return nullptr;
214227
}
215228
StringRef Buffer = FileBufOrErr->get()->getBuffer();
229+
230+
// Use a new source manager instead of the one from ASTContext because we
231+
// don't want the Json file to be persistent.
232+
SourceManager SM;
216233
yaml::Stream Stream(llvm::MemoryBufferRef(Buffer, FileName),
217-
Ctx.SourceMgr.getLLVMSourceMgr());
234+
SM.getLLVMSourceMgr());
218235
for (auto DI = Stream.begin(); DI != Stream.end(); ++ DI) {
219236
assert(DI != Stream.end() && "Failed to read a document");
220237
yaml::Node *N = DI->getRoot();
221238
assert(N && "Failed to find a root");
222239
if (parseEntry(Ctx, N, AllInstallNames)) {
223240
Ctx.Diags.diagnose(SourceLoc(), diag::previous_installname_map_corrupted,
224241
FileName);
225-
return AllInstallNames;
242+
return nullptr;
226243
}
227244
}
228-
return AllInstallNames;
245+
return pResult;
229246
}
230247

231248
void TBDGenVisitor::addLinkerDirectiveSymbols(StringRef name,
@@ -234,26 +251,29 @@ void TBDGenVisitor::addLinkerDirectiveSymbols(StringRef name,
234251
return;
235252
if (!TopLevelDecl)
236253
return;
237-
auto MovedVer = getDeclMoveOSVersion(TopLevelDecl);
238-
if (!MovedVer.hasValue())
254+
auto MovedVers = getAllMovedPlatformVersions(TopLevelDecl);
255+
if (MovedVers.empty())
239256
return;
240-
assert(MovedVer.hasValue());
257+
assert(!MovedVers.empty());
258+
259+
// Using $ld$add and $ld$hide cannot encode platform name in the version number,
260+
// so we can only handle one version.
261+
// FIXME: use $ld$previous instead
262+
auto MovedVer = MovedVers.front().Version;
263+
auto Platform = MovedVers.front().Platform;
241264
unsigned Major[2];
242265
unsigned Minor[2];
243-
Major[1] = MovedVer->getMajor();
244-
Minor[1] = MovedVer->getMinor().hasValue() ? *MovedVer->getMinor(): 0;
245-
auto AvailRange = AvailabilityInference::availableRange(TopLevelDecl,
246-
TopLevelDecl->getASTContext()).getOSVersion();
247-
assert(AvailRange.hasLowerEndpoint() &&
248-
"cannot find the start point of availability");
249-
if (!AvailRange.hasLowerEndpoint())
266+
Major[1] = MovedVer.getMajor();
267+
Minor[1] = MovedVer.getMinor().hasValue() ? *MovedVer.getMinor(): 0;
268+
auto IntroVer = getIntroducedOSVersion(TopLevelDecl, Platform);
269+
assert(IntroVer && "cannot find the start point of availability");
270+
if (!IntroVer.hasValue())
250271
return;
251-
assert(AvailRange.getLowerEndpoint() < *MovedVer);
252-
if (AvailRange.getLowerEndpoint() >= *MovedVer)
272+
assert(*IntroVer < MovedVer);
273+
if (*IntroVer >= MovedVer)
253274
return;
254-
Major[0] = AvailRange.getLowerEndpoint().getMajor();
255-
Minor[0] = AvailRange.getLowerEndpoint().getMinor().hasValue() ?
256-
AvailRange.getLowerEndpoint().getMinor().getValue() : 0;
275+
Major[0] = IntroVer->getMajor();
276+
Minor[0] = IntroVer->getMinor().hasValue() ? IntroVer->getMinor().getValue() : 0;
257277
for (auto CurMaj = Major[0]; CurMaj <= Major[1]; ++ CurMaj) {
258278
unsigned MinRange[2] = {0, 31};
259279
if (CurMaj == Major[0])
@@ -850,7 +870,7 @@ static bool isApplicationExtensionSafe(const LangOptions &LangOpts) {
850870
}
851871

852872
static bool hasLinkerDirective(Decl *D) {
853-
return getDeclMoveOSVersion(D).hasValue();
873+
return !getAllMovedPlatformVersions(D).empty();
854874
}
855875

856876
static void enumeratePublicSymbolsAndWrite(ModuleDecl *M, FileUnit *singleFile,
@@ -882,10 +902,6 @@ static void enumeratePublicSymbolsAndWrite(ModuleDecl *M, FileUnit *singleFile,
882902
file.setCompatibilityVersion(*packed);
883903
}
884904

885-
if (!opts.ModuleInstallNameMapPath.empty()) {
886-
parsePreviousModuleInstallNameMap(ctx, opts.ModuleInstallNameMapPath);
887-
}
888-
889905
llvm::MachO::Target target(triple);
890906
file.addTarget(target);
891907

lib/TBDGen/TBDGenVisitor.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,21 @@ struct TBDGenOptions;
4444

4545
namespace tbdgen {
4646

47+
enum class LinkerPlatformId: uint8_t {
48+
#define LD_PLATFORM(Name, Id) Name = Id,
49+
#include "ldPlatformKinds.def"
50+
};
51+
52+
struct InstallNameStore {
53+
// The default install name to use when no specific install name is specified.
54+
std::string InstallName;
55+
// The install name specific to the platform id. This takes precedence over
56+
// the default install name.
57+
std::map<uint8_t, std::string> PlatformInstallName;
58+
StringRef getInstallName(LinkerPlatformId Id) const;
59+
void remark(ASTContext &Ctx, StringRef ModuleName) const;
60+
};
61+
4762
class TBDGenVisitor : public ASTVisitor<TBDGenVisitor> {
4863
public:
4964
llvm::MachO::InterfaceFile &Symbols;
@@ -57,6 +72,10 @@ class TBDGenVisitor : public ASTVisitor<TBDGenVisitor> {
5772
Decl* TopLevelDecl = nullptr;
5873

5974
private:
75+
std::unique_ptr<std::map<std::string, InstallNameStore>>
76+
previousInstallNameMap;
77+
std::unique_ptr<std::map<std::string, InstallNameStore>>
78+
parsePreviousModuleInstallNameMap();
6079
void addSymbolInternal(StringRef name, llvm::MachO::SymbolKind kind,
6180
bool isLinkerDirective = false);
6281
void addLinkerDirectiveSymbols(StringRef name, llvm::MachO::SymbolKind kind);
@@ -86,7 +105,8 @@ class TBDGenVisitor : public ASTVisitor<TBDGenVisitor> {
86105
ModuleDecl *swiftModule, const TBDGenOptions &opts)
87106
: Symbols(symbols), Targets(targets), StringSymbols(stringSymbols),
88107
DataLayout(dataLayout), UniversalLinkInfo(universalLinkInfo),
89-
SwiftModule(swiftModule), Opts(opts) {}
108+
SwiftModule(swiftModule), Opts(opts),
109+
previousInstallNameMap(parsePreviousModuleInstallNameMap()) {}
90110

91111
void addMainIfNecessary(FileUnit *file) {
92112
// HACK: 'main' is a special symbol that's always emitted in SILGen if

test/TBD/previous-install-name-map.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,3 @@
1111
// CHECK: remark: previous install name for Foo in iOS is /System/Others
1212
// CHECK: remark: previous install name for Foo in tvOS is /System/Others
1313
// CHECK: remark: previous install name for Foo in watchOS is /System/Others
14-
15-
// REQUIRES: rdar58569201

0 commit comments

Comments
 (0)