aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Basic/DarwinSDKInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Basic/DarwinSDKInfo.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Basic/DarwinSDKInfo.cpp150
1 files changed, 150 insertions, 0 deletions
diff --git a/contrib/llvm-project/clang/lib/Basic/DarwinSDKInfo.cpp b/contrib/llvm-project/clang/lib/Basic/DarwinSDKInfo.cpp
new file mode 100644
index 000000000000..64bcb45a4cd8
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Basic/DarwinSDKInfo.cpp
@@ -0,0 +1,150 @@
+//===--- DarwinSDKInfo.cpp - SDK Information parser for darwin - ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/DarwinSDKInfo.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+
+using namespace clang;
+
+Optional<VersionTuple> DarwinSDKInfo::RelatedTargetVersionMapping::map(
+ const VersionTuple &Key, const VersionTuple &MinimumValue,
+ Optional<VersionTuple> MaximumValue) const {
+ if (Key < MinimumKeyVersion)
+ return MinimumValue;
+ if (Key > MaximumKeyVersion)
+ return MaximumValue;
+ auto KV = Mapping.find(Key.normalize());
+ if (KV != Mapping.end())
+ return KV->getSecond();
+ // If no exact entry found, try just the major key version. Only do so when
+ // a minor version number is present, to avoid recursing indefinitely into
+ // the major-only check.
+ if (Key.getMinor())
+ return map(VersionTuple(Key.getMajor()), MinimumValue, MaximumValue);
+ // If this a major only key, return None for a missing entry.
+ return None;
+}
+
+Optional<DarwinSDKInfo::RelatedTargetVersionMapping>
+DarwinSDKInfo::RelatedTargetVersionMapping::parseJSON(
+ const llvm::json::Object &Obj, VersionTuple MaximumDeploymentTarget) {
+ VersionTuple Min = VersionTuple(std::numeric_limits<unsigned>::max());
+ VersionTuple Max = VersionTuple(0);
+ VersionTuple MinValue = Min;
+ llvm::DenseMap<VersionTuple, VersionTuple> Mapping;
+ for (const auto &KV : Obj) {
+ if (auto Val = KV.getSecond().getAsString()) {
+ llvm::VersionTuple KeyVersion;
+ llvm::VersionTuple ValueVersion;
+ if (KeyVersion.tryParse(KV.getFirst()) || ValueVersion.tryParse(*Val))
+ return None;
+ Mapping[KeyVersion.normalize()] = ValueVersion;
+ if (KeyVersion < Min)
+ Min = KeyVersion;
+ if (KeyVersion > Max)
+ Max = KeyVersion;
+ if (ValueVersion < MinValue)
+ MinValue = ValueVersion;
+ }
+ }
+ if (Mapping.empty())
+ return None;
+ return RelatedTargetVersionMapping(
+ Min, Max, MinValue, MaximumDeploymentTarget, std::move(Mapping));
+}
+
+static Optional<VersionTuple> getVersionKey(const llvm::json::Object &Obj,
+ StringRef Key) {
+ auto Value = Obj.getString(Key);
+ if (!Value)
+ return None;
+ VersionTuple Version;
+ if (Version.tryParse(*Value))
+ return None;
+ return Version;
+}
+
+Optional<DarwinSDKInfo>
+DarwinSDKInfo::parseDarwinSDKSettingsJSON(const llvm::json::Object *Obj) {
+ auto Version = getVersionKey(*Obj, "Version");
+ if (!Version)
+ return None;
+ auto MaximumDeploymentVersion =
+ getVersionKey(*Obj, "MaximumDeploymentTarget");
+ if (!MaximumDeploymentVersion)
+ return None;
+ llvm::DenseMap<OSEnvPair::StorageType, Optional<RelatedTargetVersionMapping>>
+ VersionMappings;
+ if (const auto *VM = Obj->getObject("VersionMap")) {
+ // FIXME: Generalize this out beyond iOS-deriving targets.
+ // Look for ios_<targetos> version mapping for targets that derive from ios.
+ for (const auto &KV : *VM) {
+ auto Pair = StringRef(KV.getFirst()).split("_");
+ if (Pair.first.compare_insensitive("ios") == 0) {
+ llvm::Triple TT(llvm::Twine("--") + Pair.second.lower());
+ if (TT.getOS() != llvm::Triple::UnknownOS) {
+ auto Mapping = RelatedTargetVersionMapping::parseJSON(
+ *KV.getSecond().getAsObject(), *MaximumDeploymentVersion);
+ if (Mapping)
+ VersionMappings[OSEnvPair(llvm::Triple::IOS,
+ llvm::Triple::UnknownEnvironment,
+ TT.getOS(),
+ llvm::Triple::UnknownEnvironment)
+ .Value] = std::move(Mapping);
+ }
+ }
+ }
+
+ if (const auto *Mapping = VM->getObject("macOS_iOSMac")) {
+ auto VersionMap = RelatedTargetVersionMapping::parseJSON(
+ *Mapping, *MaximumDeploymentVersion);
+ if (!VersionMap)
+ return None;
+ VersionMappings[OSEnvPair::macOStoMacCatalystPair().Value] =
+ std::move(VersionMap);
+ }
+ if (const auto *Mapping = VM->getObject("iOSMac_macOS")) {
+ auto VersionMap = RelatedTargetVersionMapping::parseJSON(
+ *Mapping, *MaximumDeploymentVersion);
+ if (!VersionMap)
+ return None;
+ VersionMappings[OSEnvPair::macCatalystToMacOSPair().Value] =
+ std::move(VersionMap);
+ }
+ }
+
+ return DarwinSDKInfo(std::move(*Version),
+ std::move(*MaximumDeploymentVersion),
+ std::move(VersionMappings));
+}
+
+Expected<Optional<DarwinSDKInfo>>
+clang::parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS, StringRef SDKRootPath) {
+ llvm::SmallString<256> Filepath = SDKRootPath;
+ llvm::sys::path::append(Filepath, "SDKSettings.json");
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
+ VFS.getBufferForFile(Filepath);
+ if (!File) {
+ // If the file couldn't be read, assume it just doesn't exist.
+ return None;
+ }
+ Expected<llvm::json::Value> Result =
+ llvm::json::parse(File.get()->getBuffer());
+ if (!Result)
+ return Result.takeError();
+
+ if (const auto *Obj = Result->getAsObject()) {
+ if (auto SDKInfo = DarwinSDKInfo::parseDarwinSDKSettingsJSON(Obj))
+ return std::move(SDKInfo);
+ }
+ return llvm::make_error<llvm::StringError>("invalid SDKSettings.json",
+ llvm::inconvertibleErrorCode());
+}