//===--- DarwinSDKInfo.h - SDK Information parser for darwin ----*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_BASIC_DARWIN_SDK_INFO_H
#define LLVM_CLANG_BASIC_DARWIN_SDK_INFO_H

#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/VirtualFileSystem.h"

namespace llvm {
namespace json {
class Object;
} // end namespace json
} // end namespace llvm

namespace clang {

/// The information about the darwin SDK that was used during this compilation.
class DarwinSDKInfo {
public:
  /// A value that describes two os-environment pairs that can be used as a key
  /// to the version map in the SDK.
  struct OSEnvPair {
  public:
    using StorageType = uint64_t;

    constexpr OSEnvPair(llvm::Triple::OSType FromOS,
                        llvm::Triple::EnvironmentType FromEnv,
                        llvm::Triple::OSType ToOS,
                        llvm::Triple::EnvironmentType ToEnv)
        : Value(((StorageType(FromOS) * StorageType(llvm::Triple::LastOSType) +
                  StorageType(FromEnv))
                 << 32ull) |
                (StorageType(ToOS) * StorageType(llvm::Triple::LastOSType) +
                 StorageType(ToEnv))) {}

    /// Returns the os-environment mapping pair that's used to represent the
    /// macOS -> Mac Catalyst version mapping.
    static inline constexpr OSEnvPair macOStoMacCatalystPair() {
      return OSEnvPair(llvm::Triple::MacOSX, llvm::Triple::UnknownEnvironment,
                       llvm::Triple::IOS, llvm::Triple::MacABI);
    }

    /// Returns the os-environment mapping pair that's used to represent the
    /// Mac Catalyst -> macOS version mapping.
    static inline constexpr OSEnvPair macCatalystToMacOSPair() {
      return OSEnvPair(llvm::Triple::IOS, llvm::Triple::MacABI,
                       llvm::Triple::MacOSX, llvm::Triple::UnknownEnvironment);
    }

  private:
    StorageType Value;

    friend class DarwinSDKInfo;
  };

  /// Represents a version mapping that maps from a version of one target to a
  /// version of a related target.
  ///
  /// e.g. "macOS_iOSMac":{"10.15":"13.1"} is an example of a macOS -> Mac
  /// Catalyst version map.
  class RelatedTargetVersionMapping {
  public:
    RelatedTargetVersionMapping(
        VersionTuple MinimumKeyVersion, VersionTuple MaximumKeyVersion,
        VersionTuple MinimumValue, VersionTuple MaximumValue,
        llvm::DenseMap<VersionTuple, VersionTuple> Mapping)
        : MinimumKeyVersion(MinimumKeyVersion),
          MaximumKeyVersion(MaximumKeyVersion), MinimumValue(MinimumValue),
          MaximumValue(MaximumValue), Mapping(Mapping) {
      assert(!this->Mapping.empty() && "unexpected empty mapping");
    }

    /// Returns the value with the lowest version in the mapping.
    const VersionTuple &getMinimumValue() const { return MinimumValue; }

    /// Returns the mapped key, or the appropriate Minimum / MaximumValue if
    /// they key is outside of the mapping bounds. If they key isn't mapped, but
    /// within the minimum and maximum bounds, None is returned.
    Optional<VersionTuple> map(const VersionTuple &Key,
                               const VersionTuple &MinimumValue,
                               Optional<VersionTuple> MaximumValue) const;

    static Optional<RelatedTargetVersionMapping>
    parseJSON(const llvm::json::Object &Obj,
              VersionTuple MaximumDeploymentTarget);

  private:
    VersionTuple MinimumKeyVersion;
    VersionTuple MaximumKeyVersion;
    VersionTuple MinimumValue;
    VersionTuple MaximumValue;
    llvm::DenseMap<VersionTuple, VersionTuple> Mapping;
  };

  DarwinSDKInfo(VersionTuple Version, VersionTuple MaximumDeploymentTarget,
                llvm::DenseMap<OSEnvPair::StorageType,
                               Optional<RelatedTargetVersionMapping>>
                    VersionMappings =
                        llvm::DenseMap<OSEnvPair::StorageType,
                                       Optional<RelatedTargetVersionMapping>>())
      : Version(Version), MaximumDeploymentTarget(MaximumDeploymentTarget),
        VersionMappings(std::move(VersionMappings)) {}

  const llvm::VersionTuple &getVersion() const { return Version; }

  // Returns the optional, target-specific version mapping that maps from one
  // target to another target.
  //
  // This mapping is constructed from an appropriate mapping in the SDKSettings,
  // for instance, when building for Mac Catalyst, the mapping would contain the
  // "macOS_iOSMac" mapping as it maps the macOS versions to the Mac Catalyst
  // versions.
  //
  // This mapping does not exist when the target doesn't have an appropriate
  // related version mapping, or when there was an error reading the mapping
  // from the SDKSettings, or when it's missing in the SDKSettings.
  const RelatedTargetVersionMapping *getVersionMapping(OSEnvPair Kind) const {
    auto Mapping = VersionMappings.find(Kind.Value);
    if (Mapping == VersionMappings.end())
      return nullptr;
    return Mapping->getSecond().hasValue() ? Mapping->getSecond().getPointer()
                                           : nullptr;
  }

  static Optional<DarwinSDKInfo>
  parseDarwinSDKSettingsJSON(const llvm::json::Object *Obj);

private:
  VersionTuple Version;
  VersionTuple MaximumDeploymentTarget;
  // Need to wrap the value in an optional here as the value has to be default
  // constructible, and std::unique_ptr doesn't like DarwinSDKInfo being
  // Optional as Optional is trying to copy it in emplace.
  llvm::DenseMap<OSEnvPair::StorageType, Optional<RelatedTargetVersionMapping>>
      VersionMappings;
};

/// Parse the SDK information from the SDKSettings.json file.
///
/// \returns an error if the SDKSettings.json file is invalid, None if the
/// SDK has no SDKSettings.json, or a valid \c DarwinSDKInfo otherwise.
Expected<Optional<DarwinSDKInfo>> parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS,
                                                     StringRef SDKRootPath);

} // end namespace clang

#endif // LLVM_CLANG_BASIC_DARWIN_SDK_INFO_H
