Skip to content

Commit 2223b92

Browse files
author
Harlan Haskins
authored
Merge pull request #28193 from harlanhaskins/truncation-station
[TBDGen] Match TAPI's truncation behavior for dylib versions
2 parents ba5cfc6 + 3745dcc commit 2223b92

File tree

6 files changed

+93
-29
lines changed

6 files changed

+93
-29
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,15 @@ ERROR(error_formatting_invalid_range,none,
232232
WARNING(stats_disabled,none,
233233
"compiler was not built with support for collecting statistics", ())
234234

235+
WARNING(tbd_warn_truncating_version,none,
236+
"truncating %select{current|compatibility}0 version '%1' in TBD file "
237+
"to fit in 32-bit space used by old mach-o format",
238+
(unsigned, StringRef))
239+
240+
ERROR(tbd_err_invalid_version,none,
241+
"invalid dynamic library %select{current|compatibility}0 version '%1'",
242+
(unsigned, StringRef))
243+
235244
WARNING(tbd_only_supported_in_whole_module,none,
236245
"TBD generation is only supported when the whole module can be seen",
237246
())

include/swift/TBDGen/TBDGen.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ struct TBDGenOptions {
4040
std::string ModuleLinkName;
4141

4242
/// The current project version to use in the generated TBD file. Defaults
43-
/// to None.
44-
llvm::Optional<version::Version> CurrentVersion = None;
43+
/// to empty string if not provided.
44+
std::string CurrentVersion;
4545

4646
/// The dylib compatibility-version to use in the generated TBD file. Defaults
47-
/// to None.
48-
llvm::Optional<version::Version> CompatibilityVersion = None;
47+
/// to empty string if not provided.
48+
std::string CompatibilityVersion;
4949
};
5050

5151
void enumeratePublicSymbols(FileUnit *module, llvm::StringSet<> &symbols,

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -961,16 +961,11 @@ static bool ParseTBDGenArgs(TBDGenOptions &Opts, ArgList &Args,
961961
Opts.IsInstallAPI = Args.hasArg(OPT_tbd_is_installapi);
962962

963963
if (const Arg *A = Args.getLastArg(OPT_tbd_compatibility_version)) {
964-
if (auto vers = version::Version::parseVersionString(
965-
A->getValue(), SourceLoc(), &Diags)) {
966-
Opts.CompatibilityVersion = *vers;
967-
}
964+
Opts.CompatibilityVersion = A->getValue();
968965
}
966+
969967
if (const Arg *A = Args.getLastArg(OPT_tbd_current_version)) {
970-
if (auto vers = version::Version::parseVersionString(
971-
A->getValue(), SourceLoc(), &Diags)) {
972-
Opts.CurrentVersion = *vers;
973-
}
968+
Opts.CurrentVersion = A->getValue();
974969
}
975970
return false;
976971
}

lib/TBDGen/TBDGen.cpp

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "swift/AST/Availability.h"
2020
#include "swift/AST/ASTMangler.h"
2121
#include "swift/AST/ASTVisitor.h"
22+
#include "swift/AST/DiagnosticsFrontend.h"
2223
#include "swift/AST/Module.h"
2324
#include "swift/AST/ParameterList.h"
2425
#include "swift/AST/PropertyWrappers.h"
@@ -593,16 +594,44 @@ void TBDGenVisitor::addFirstFileSymbols() {
593594
}
594595
}
595596

596-
/// Converts a version tuple into a packed version, ignoring components beyond
597-
/// major, minor, and subminor.
598-
static llvm::MachO::PackedVersion
599-
convertToPacked(const version::Version &version) {
600-
// FIXME: Warn if version is greater than 3 components?
601-
unsigned major = 0, minor = 0, subminor = 0;
602-
if (version.size() > 0) major = version[0];
603-
if (version.size() > 1) minor = version[1];
604-
if (version.size() > 2) subminor = version[2];
605-
return llvm::MachO::PackedVersion(major, minor, subminor);
597+
/// The kind of version being parsed, used for diagnostics.
598+
/// Note: Must match the order in DiagnosticsFrontend.def
599+
enum DylibVersionKind_t: unsigned {
600+
CurrentVersion,
601+
CompatibilityVersion
602+
};
603+
604+
/// Converts a version string into a packed version, truncating each component
605+
/// if necessary to fit all 3 into a 32-bit packed structure.
606+
///
607+
/// For example, the version '1219.37.11' will be packed as
608+
///
609+
/// Major (1,219) Minor (37) Patch (11)
610+
/// ┌───────────────────┬──────────┬──────────┐
611+
/// │ 00001100 11000011 │ 00100101 │ 00001011 │
612+
/// └───────────────────┴──────────┴──────────┘
613+
///
614+
/// If an individual component is greater than the highest number that can be
615+
/// represented in its alloted space, it will be truncated to the maximum value
616+
/// that fits in the alloted space, which matches the behavior of the linker.
617+
static Optional<llvm::MachO::PackedVersion>
618+
parsePackedVersion(DylibVersionKind_t kind, StringRef versionString,
619+
ASTContext &ctx) {
620+
if (versionString.empty())
621+
return None;
622+
623+
llvm::MachO::PackedVersion version;
624+
auto result = version.parse64(versionString);
625+
if (!result.first) {
626+
ctx.Diags.diagnose(SourceLoc(), diag::tbd_err_invalid_version,
627+
(unsigned)kind, versionString);
628+
return None;
629+
}
630+
if (result.second) {
631+
ctx.Diags.diagnose(SourceLoc(), diag::tbd_warn_truncating_version,
632+
(unsigned)kind, versionString);
633+
}
634+
return version;
606635
}
607636

608637
static bool isApplicationExtensionSafe(const LangOptions &LangOpts) {
@@ -627,16 +656,20 @@ static void enumeratePublicSymbolsAndWrite(ModuleDecl *M, FileUnit *singleFile,
627656
file.setApplicationExtensionSafe(
628657
isApplicationExtensionSafe(M->getASTContext().LangOpts));
629658
file.setInstallName(opts.InstallName);
630-
if (auto currentVersion = opts.CurrentVersion) {
631-
file.setCurrentVersion(convertToPacked(*currentVersion));
632-
}
633-
if (auto compatibilityVersion = opts.CompatibilityVersion) {
634-
file.setCompatibilityVersion(convertToPacked(*compatibilityVersion));
635-
}
636659
file.setTwoLevelNamespace();
637660
file.setSwiftABIVersion(irgen::getSwiftABIVersion());
638661
file.setInstallAPI(opts.IsInstallAPI);
639662

663+
if (auto packed = parsePackedVersion(CurrentVersion,
664+
opts.CurrentVersion, ctx)) {
665+
file.setCurrentVersion(*packed);
666+
}
667+
668+
if (auto packed = parsePackedVersion(CompatibilityVersion,
669+
opts.CompatibilityVersion, ctx)) {
670+
file.setCompatibilityVersion(*packed);
671+
}
672+
640673
llvm::MachO::Target target(triple);
641674
file.addTarget(target);
642675

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// REQUIRES: VENDOR=apple
2+
// RUN: %empty-directory(%t)
3+
4+
// RUN: %target-swift-frontend -typecheck %s -emit-tbd-path - -tbd-current-version 2.0 | %FileCheck %s --check-prefix TWOPOINTZERO
5+
// RUN: %target-swift-frontend -typecheck %s -emit-tbd-path - -tbd-current-version 2 | %FileCheck %s --check-prefix TWOPOINTZERO
6+
// RUN: %target-swift-frontend -typecheck %s -emit-tbd-path - -tbd-current-version 20.10 | %FileCheck %s --check-prefix TWENTYPOINTTEN
7+
8+
// RUN: %target-swift-frontend -typecheck %s -emit-tbd-path - -tbd-compatibility-version 2.0 | %FileCheck %s --check-prefix TWOPOINTZEROCOMPAT
9+
// RUN: %target-swift-frontend -typecheck %s -emit-tbd-path - -tbd-compatibility-version 2 | %FileCheck %s --check-prefix TWOPOINTZEROCOMPAT
10+
// RUN: %target-swift-frontend -typecheck %s -emit-tbd-path - -tbd-compatibility-version 20.10 | %FileCheck %s --check-prefix TWENTYPOINTTENCOMPAT
11+
12+
// Make sure we correctly truncate a value over 255
13+
14+
// RUN: %target-swift-frontend -typecheck %s -emit-tbd-path - -tbd-current-version 20.300 2>&1 | %FileCheck %s --check-prefix TWENTYPOINTTHREEHUNDRED
15+
// RUN: %target-swift-frontend -typecheck %s -emit-tbd-path - -tbd-compatibility-version 20.300 2>&1 | %FileCheck %s --check-prefix TWENTYPOINTTHREEHUNDREDCOMPAT
16+
17+
// TWOPOINTZERO: current-version: 2
18+
// TWENTYPOINTTEN: current-version: 20.10
19+
20+
// TWOPOINTZEROCOMPAT: compatibility-version: 2
21+
// TWENTYPOINTTENCOMPAT: compatibility-version: 20.10
22+
23+
// TWENTYPOINTTHREEHUNDRED: warning: truncating current version '20.300' in TBD file to fit in 32-bit space used by old mach-o format
24+
// TWENTYPOINTTHREEHUNDRED: current-version: 20.255
25+
26+
// TWENTYPOINTTHREEHUNDREDCOMPAT: warning: truncating compatibility version '20.300' in TBD file to fit in 32-bit space used by old mach-o format
27+
// TWENTYPOINTTHREEHUNDREDCOMPAT: compatibility-version: 20.255

test/TBD/dylib-version.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@
1414
// CURRENT: current-version: 2
1515
// COMPAT: compatibility-version: 2
1616

17-
// BOGUS: version component contains non-numeric characters
17+
// BOGUS: invalid dynamic library compatibility version 'not_a_version_string'

0 commit comments

Comments
 (0)