diff --git a/llvm/include/llvm/TextAPI/MachO/Platform.h b/llvm/include/llvm/TextAPI/MachO/Platform.h --- a/llvm/include/llvm/TextAPI/MachO/Platform.h +++ b/llvm/include/llvm/TextAPI/MachO/Platform.h @@ -25,11 +25,16 @@ iOS = MachO::PLATFORM_IOS, tvOS = MachO::PLATFORM_TVOS, watchOS = MachO::PLATFORM_WATCHOS, - bridgeOS = MachO::PLATFORM_BRIDGEOS + bridgeOS = MachO::PLATFORM_BRIDGEOS, + macCatalyst = MachO::PLATFORM_MACCATALYST, + iOSSimulator = MachO::PLATFORM_IOSSIMULATOR, + tvOSSimulator = MachO::PLATFORM_TVOSSIMULATOR, + watchOSSimulator = MachO::PLATFORM_WATCHOSSIMULATOR }; using PlatformSet = SmallSet; +PlatformKind mapToPlatformKind(PlatformKind Platform, bool WantSim); PlatformKind mapToPlatformKind(const Triple &Target); PlatformSet mapToPlatformSet(ArrayRef Targets); StringRef getPlatformName(PlatformKind Platform); diff --git a/llvm/lib/TextAPI/MachO/Platform.cpp b/llvm/lib/TextAPI/MachO/Platform.cpp --- a/llvm/lib/TextAPI/MachO/Platform.cpp +++ b/llvm/lib/TextAPI/MachO/Platform.cpp @@ -17,6 +17,19 @@ namespace llvm { namespace MachO { +PlatformKind mapToPlatformKind(PlatformKind Platform, bool WantSim) { + switch (Platform) { + default: + return Platform; + case PlatformKind::iOS: + return WantSim ? PlatformKind::iOSSimulator : PlatformKind::iOS; + case PlatformKind::tvOS: + return WantSim ? PlatformKind::tvOSSimulator : PlatformKind::tvOS; + case PlatformKind::watchOS: + return WantSim ? PlatformKind::watchOSSimulator : PlatformKind::watchOS; + } +} + PlatformKind mapToPlatformKind(const Triple &Target) { switch (Target.getOS()) { default: @@ -24,11 +37,17 @@ case Triple::MacOSX: return PlatformKind::macOS; case Triple::IOS: + if (Target.isSimulatorEnvironment()) + return PlatformKind::iOSSimulator; + if (Target.getEnvironment() == Triple::MacABI) + return PlatformKind::macCatalyst; return PlatformKind::iOS; case Triple::TvOS: - return PlatformKind::tvOS; + return Target.isSimulatorEnvironment() ? PlatformKind::tvOSSimulator + : PlatformKind::tvOS; case Triple::WatchOS: - return PlatformKind::watchOS; + return Target.isSimulatorEnvironment() ? PlatformKind::watchOSSimulator + : PlatformKind::watchOS; // TODO: add bridgeOS once in llvm::Triple } } @@ -54,8 +73,16 @@ return "watchOS"; case PlatformKind::bridgeOS: return "bridgeOS"; + case PlatformKind::macCatalyst: + return "macCatalyst"; + case PlatformKind::iOSSimulator: + return "iOS Simulator"; + case PlatformKind::tvOSSimulator: + return "tvOS Simulator"; + case PlatformKind::watchOSSimulator: + return "watchOS Simulator"; } } } // end namespace MachO. } // end namespace llvm. \ No newline at end of file diff --git a/llvm/lib/TextAPI/MachO/TextStub.cpp b/llvm/lib/TextAPI/MachO/TextStub.cpp --- a/llvm/lib/TextAPI/MachO/TextStub.cpp +++ b/llvm/lib/TextAPI/MachO/TextStub.cpp @@ -399,13 +399,25 @@ } } + // TBD v1 - TBD v3 files only support one platform and several + // architectures. It is possible to have more than one platform for TBD v3 + // files, but the architectures don't apply to all + // platforms, specifically to filter out the i386 slice from + // platform macCatalyst. TargetList synthesizeTargets(ArchitectureSet Architectures, - const PlatformSet &Platforms) { + const PlatformSet &Platforms) { TargetList Targets; for (auto Platform : Platforms) { - for (const auto &&Architecture : Architectures) + Platform = mapToPlatformKind(Platform, Architectures.hasX86()); + + for (const auto &&Architecture : Architectures) { + if ((Architecture == AK_i386) && + (Platform == PlatformKind::macCatalyst)) + continue; + Targets.emplace_back(Architecture, Platform); + } } return Targets; } diff --git a/llvm/lib/TextAPI/MachO/TextStubCommon.cpp b/llvm/lib/TextAPI/MachO/TextStubCommon.cpp --- a/llvm/lib/TextAPI/MachO/TextStubCommon.cpp +++ b/llvm/lib/TextAPI/MachO/TextStubCommon.cpp @@ -43,6 +43,17 @@ void ScalarTraits::output(const PlatformSet &Values, void *IO, raw_ostream &OS) { + + const auto *Ctx = reinterpret_cast(IO); + assert((!Ctx || Ctx && Ctx->FileKind != FileType::Invalid) && + "File type is not set in context"); + + if ( Ctx && Ctx->FileKind == TBD_V3 && Values.count(PlatformKind::macOS) && + Values.count(PlatformKind::macCatalyst) ) { + OS << "zippered"; + return; + } + assert(Values.size() == 1U); switch (*Values.begin()) { default: @@ -68,6 +79,19 @@ StringRef ScalarTraits::input(StringRef Scalar, void *IO, PlatformSet &Values) { + const auto *Ctx = reinterpret_cast(IO); + assert((!Ctx || Ctx && Ctx->FileKind != FileType::Invalid) && + "File type is not set in context"); + + if (Scalar == "zippered") { + if (Ctx && Ctx->FileKind == FileType::TBD_V3) { + Values.insert(PlatformKind::macOS); + Values.insert(PlatformKind::macCatalyst); + return {}; + } + return "invalid platform"; + } + auto Platform = StringSwitch(Scalar) .Case("unknown", PlatformKind::unknown) .Case("macosx", PlatformKind::macOS) @@ -75,8 +99,13 @@ .Case("watchos", PlatformKind::watchOS) .Case("tvos", PlatformKind::tvOS) .Case("bridgeos", PlatformKind::bridgeOS) + .Case("iosmac", PlatformKind::macCatalyst) .Default(PlatformKind::unknown); + if (Platform == PlatformKind::macCatalyst) + if (Ctx && Ctx->FileKind != FileType::TBD_V3) + return "invalid platform"; + if (Platform == PlatformKind::unknown) return "unknown platform"; diff --git a/llvm/unittests/TextAPI/TextStubV2Tests.cpp b/llvm/unittests/TextAPI/TextStubV2Tests.cpp --- a/llvm/unittests/TextAPI/TextStubV2Tests.cpp +++ b/llvm/unittests/TextAPI/TextStubV2Tests.cpp @@ -457,6 +457,23 @@ errorMessage); } +TEST(TBDv2, InvalidPlatform) { + static const char tbd_v2_file_invalid_platform[] = + "--- !tapi-tbd-v2\n" + "archs: [ i386 ]\n" + "platform: iosmac\n" + "install-name: Test.dylib\n" + "...\n"; + + auto Result = TextAPIReader::get( + MemoryBufferRef(tbd_v2_file_invalid_platform, "Test.tbd")); + EXPECT_FALSE(!!Result); + auto errorMessage = toString(Result.takeError()); + EXPECT_EQ("malformed file\nTest.tbd:3:11: error: invalid platform\nplatform: " + "iosmac\n ^~~~~~\n", + errorMessage); +} + TEST(TBDv2, MalformedFile1) { static const char malformed_file1[] = "--- !tapi-tbd-v2\n" "archs: [ arm64 ]\n" diff --git a/llvm/unittests/TextAPI/TextStubV3Tests.cpp b/llvm/unittests/TextAPI/TextStubV3Tests.cpp --- a/llvm/unittests/TextAPI/TextStubV3Tests.cpp +++ b/llvm/unittests/TextAPI/TextStubV3Tests.cpp @@ -274,6 +274,43 @@ EXPECT_EQ(Platform, *File->getPlatforms().begin()); } +TEST(TBDv3, Platform_macCatalyst) { + static const char tbd_v1_platform_iosmac[] = "--- !tapi-tbd-v3\n" + "archs: [ armv7k ]\n" + "platform: iosmac\n" + "install-name: Test.dylib\n" + "...\n"; + + auto Result = + TextAPIReader::get(MemoryBufferRef(tbd_v1_platform_iosmac, "Test.tbd")); + EXPECT_TRUE(!!Result); + auto Platform = PlatformKind::macCatalyst; + auto File = std::move(Result.get()); + EXPECT_EQ(FileType::TBD_V3, File->getFileType()); + EXPECT_EQ(Platform, *File->getPlatforms().begin()); +} + +TEST(TBDv3, Platform_zippered) { + static const char tbd_v1_platform_zip[] = "--- !tapi-tbd-v3\n" + "archs: [ armv7k ]\n" + "platform: zippered\n" + "install-name: Test.dylib\n" + "...\n"; + + auto Result = + TextAPIReader::get(MemoryBufferRef(tbd_v1_platform_zip, "Test.tbd")); + EXPECT_TRUE(!!Result); + auto File = std::move(Result.get()); + EXPECT_EQ(FileType::TBD_V3, File->getFileType()); + + PlatformSet Platforms; + Platforms.insert(PlatformKind::macOS); + Platforms.insert(PlatformKind::macCatalyst); + EXPECT_EQ(Platforms.size(), File->getPlatforms().size()); + for (auto Platform : File->getPlatforms()) + EXPECT_EQ(Platforms.count(Platform), 1U); +} + TEST(TBDv3, Swift_1_0) { static const char tbd_v1_swift_1_0[] = "--- !tapi-tbd-v3\n" "archs: [ arm64 ]\n"