// Copyright 2023 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef TOOLS_GN_RESOLVED_TARGET_DATA_H_
#define TOOLS_GN_RESOLVED_TARGET_DATA_H_

#include <atomic>
#include <memory>
#include <mutex>
#include <shared_mutex>
#include <vector>

#include "base/containers/span.h"
#include "gn/lib_file.h"
#include "gn/output_file.h"
#include "gn/resolved_target_deps.h"
#include "gn/source_dir.h"
#include "gn/target.h"
#include "gn/target_public_pair.h"
#include "gn/unique_vector.h"

// A class used to compute target-specific data by collecting information
// from its tree of dependencies.
//
// For example, linkable targets can call GetLinkedLibraries() and
// GetLinkedLibraryDirs() to find the library files and library search
// paths to add to their final linker command string, based on the
// definitions of the `libs` and `lib_dirs` config values of their
// transitive dependencies.
//
// Values are computed on demand, but memorized by the class instance in order
// to speed up multiple queries for targets that share dependencies.
//
// Usage is:
//
//  1) Create instance.
//
//  2) Call any of the methods to retrieve the value of the corresponding
//     data. For all methods, the input Target instance passed as argument
//     must have been fully resolved (meaning that Target::OnResolved()
//     must have been called and completed). Input target pointers are
//     const and thus are never modified. This allows using multiple
//     ResolvedTargetData instances from the same input graph in multiple
//     threads safely.
//
class ResolvedTargetData {
 public:
  // Return the public/private/data/dependencies of a given target
  // as a ResolvedTargetDeps instance.
  const ResolvedTargetDeps& GetTargetDeps(const Target* target) const {
    return GetTargetInfo(target)->deps;
  }

  // Return the data dependencies of a given target.
  // Convenience shortcut for GetTargetDeps(target).data_deps().
  base::span<const Target*> GetDataDeps(const Target* target) const {
    return GetTargetDeps(target).data_deps();
  }

  // Return the public and private dependencies of a given target.
  // Convenience shortcut for GetTargetDeps(target).linked_deps().
  base::span<const Target*> GetLinkedDeps(const Target* target) const {
    return GetTargetDeps(target).linked_deps();
  }

  // The list of all library directory search path to add to the final link
  // command of linkable binary. For example, if this returns ['dir1', 'dir2']
  // a command for a C++ linker would typically use `-Ldir1 -Ldir2`.
  const std::vector<SourceDir>& GetLinkedLibraryDirs(
      const Target* target) const {
    return GetTargetLibInfo(target)->lib_dirs;
  }

  // The list of all library files to add to the final link command of linkable
  // binaries. For example, if this returns ['foo', '/path/to/bar'], the command
  // for a C++ linker would typically use '-lfoo /path/to/bar'.
  const std::vector<LibFile>& GetLinkedLibraries(const Target* target) const {
    return GetTargetLibInfo(target)->libs;
  }

  // The list of framework directories search paths to use at link time
  // when generating macOS or iOS linkable binaries.
  const std::vector<SourceDir>& GetLinkedFrameworkDirs(
      const Target* target) const {
    return GetTargetFrameworkInfo(target)->framework_dirs;
  }

  // The list of framework names to use at link time when generating macOS
  // or iOS linkable binaries.
  const std::vector<std::string>& GetLinkedFrameworks(
      const Target* target) const {
    return GetTargetFrameworkInfo(target)->frameworks;
  }

  // The list of weak framework names to use at link time when generating macOS
  // or iOS linkable binaries.
  const std::vector<std::string>& GetLinkedWeakFrameworks(
      const Target* target) const {
    return GetTargetFrameworkInfo(target)->weak_frameworks;
  }

  // The list of weak library files to use at link time when generating macOS
  // or iOS linkable binaries.
  const std::vector<std::string>& GetLinkedWeakLibraries(
      const Target* target) const {
    return GetTargetFrameworkInfo(target)->weak_libraries;
  }

  // Retrieves a set of hard dependencies for this target.
  // All hard deps from this target and all dependencies, but not the
  // target itself.
  const TargetSet& GetHardDeps(const Target* target) const {
    return GetTargetHardDeps(target)->hard_deps;
  }

  // Retrieves an ordered list of (target, is_public) pairs for all link-time
  // libraries inherited by this target.
  const std::vector<TargetPublicPair>& GetInheritedLibraries(
      const Target* target) const {
    return GetTargetInheritedLibs(target)->inherited_libs;
  }

  // Retrieves an ordered list of (target, is_public) pairs for all module
  // dependencies inherited by this target.
  const std::vector<TargetPublicPair>& GetModuleDepsInformation(
      const Target* target) const {
    return GetTargetModuleDepsInformation(target)->module_deps_information;
  }

  // Retrieves an ordered list of (target, is_public) paris for all link-time
  // libraries for Rust-specific binary targets.
  const std::vector<TargetPublicPair>& GetRustInheritedLibraries(
      const Target* target) const {
    return GetTargetRustLibs(target)->rust_inherited_libs;
  }

  // List of dependent target that generate a .swiftmodule. The current target
  // is assumed to depend on those modules, and will add them to the module
  // search path.
  base::span<const Target*> GetSwiftModuleDependencies(
      const Target* target) const {
    const TargetInfo* info = GetTargetSwiftValues(target);
    if (!info->swift_values.get())
      return {};
    return info->swift_values->modules;
  }

  // Retrieves an ordered list of all order-only dependency outputs for this
  // target.
  const std::vector<OutputFile>& GetOrderOnlyDeps(const Target* target) const {
    return GetTargetOrderOnlyDeps(target)->order_only_deps;
  }

  // Returns true if this target exports public inputs, either directly or from
  // public dependencies which do.
  bool ExportsPublicInputs(const Target* target) const {
    TargetInfo* info = GetTargetInfo(target);
    LazyBool value =
        info->does_export_public_inputs.load(std::memory_order_acquire);
    if (value == LazyBool::kUnknown) {
      value =
          ComputeExportsPublicInputs(info) ? LazyBool::kTrue : LazyBool::kFalse;
      info->does_export_public_inputs.store(value, std::memory_order_release);
    }
    return value == LazyBool::kTrue;
  }

 private:
  enum class LazyBool : uint8_t {
    kUnknown,
    kTrue,
    kFalse,
  };

  // The information associated with a given Target pointer.
  struct TargetInfo {
    TargetInfo() = default;

    TargetInfo(const Target* target)
        : target(target),
          deps(target->public_deps(),
               target->private_deps(),
               target->data_deps()) {}

    const Target* target = nullptr;
    ResolvedTargetDeps deps;
    mutable std::mutex mutex;

    std::atomic<bool> has_lib_info = false;
    std::atomic<bool> has_framework_info = false;
    std::atomic<bool> has_hard_deps = false;
    std::atomic<bool> has_inherited_libs = false;
    std::atomic<bool> has_module_deps_information = false;
    std::atomic<bool> has_rust_libs = false;
    std::atomic<bool> has_swift_values = false;
    std::atomic<bool> has_order_only_deps = false;
    std::atomic<LazyBool> does_export_public_inputs = LazyBool::kUnknown;

    // Only valid if |has_lib_info| is true.
    std::vector<SourceDir> lib_dirs;
    std::vector<LibFile> libs;

    // Only valid if |has_framework_info| is true.
    std::vector<SourceDir> framework_dirs;
    std::vector<std::string> frameworks;
    std::vector<std::string> weak_frameworks;
    std::vector<std::string> weak_libraries;

    // Only valid if |has_hard_deps| is true.
    TargetSet hard_deps;

    // Only valid if |has_inherited_libs| is true.
    std::vector<TargetPublicPair> inherited_libs;

    // Only valid if |has_module_deps_information| is true.
    std::vector<TargetPublicPair> module_deps_information;

    // Only valid if |has_rust_libs| is true.
    std::vector<TargetPublicPair> rust_inherited_libs;
    std::vector<TargetPublicPair> rust_inheritable_libs;

    // Only valid if |has_swift_values| is true.
    // Most targets will not have Swift dependencies, so only
    // allocate a SwiftValues struct when needed. A null pointer
    // indicates empty lists.
    struct SwiftValues {
      std::vector<const Target*> modules;
      std::vector<const Target*> public_modules;

      SwiftValues(std::vector<const Target*> modules,
                  std::vector<const Target*> public_modules)
          : modules(std::move(modules)),
            public_modules(std::move(public_modules)) {}
    };
    std::unique_ptr<SwiftValues> swift_values;

    // Only valid if |has_order_only_deps| is true.
    std::vector<OutputFile> order_only_deps;
  };

  // Retrieve TargetInfo value associated with |target|. Create
  // a new empty instance on demand if none is already available.
  TargetInfo* GetTargetInfo(const Target* target) const;

  const TargetInfo* GetTargetLibInfo(const Target* target) const {
    TargetInfo* info = GetTargetInfo(target);
    if (!info->has_lib_info.load(std::memory_order_acquire)) {
      std::lock_guard<std::mutex> lock(info->mutex);
      if (!info->has_lib_info.load(std::memory_order_relaxed)) {
        ComputeLibInfo(info);
        info->has_lib_info.store(true, std::memory_order_release);
      }
    }
    return info;
  }

  const TargetInfo* GetTargetFrameworkInfo(const Target* target) const {
    TargetInfo* info = GetTargetInfo(target);
    if (!info->has_framework_info.load(std::memory_order_acquire)) {
      std::lock_guard<std::mutex> lock(info->mutex);
      if (!info->has_framework_info.load(std::memory_order_relaxed)) {
        ComputeFrameworkInfo(info);
        info->has_framework_info.store(true, std::memory_order_release);
      }
    }
    return info;
  }

  const TargetInfo* GetTargetHardDeps(const Target* target) const {
    TargetInfo* info = GetTargetInfo(target);
    if (!info->has_hard_deps.load(std::memory_order_acquire)) {
      std::lock_guard<std::mutex> lock(info->mutex);
      if (!info->has_hard_deps.load(std::memory_order_relaxed)) {
        ComputeHardDeps(info);
        info->has_hard_deps.store(true, std::memory_order_release);
      }
    }
    return info;
  }

  const TargetInfo* GetTargetInheritedLibs(const Target* target) const {
    TargetInfo* info = GetTargetInfo(target);
    if (!info->has_inherited_libs.load(std::memory_order_acquire)) {
      std::lock_guard<std::mutex> lock(info->mutex);
      if (!info->has_inherited_libs.load(std::memory_order_relaxed)) {
        ComputeInheritedLibs(info);
        info->has_inherited_libs.store(true, std::memory_order_release);
      }
    }
    return info;
  }

  const TargetInfo* GetTargetModuleDepsInformation(const Target* target) const {
    TargetInfo* info = GetTargetInfo(target);
    if (!info->has_module_deps_information.load(std::memory_order_acquire)) {
      std::lock_guard<std::mutex> lock(info->mutex);
      if (!info->has_module_deps_information.load(std::memory_order_relaxed)) {
        ComputeModuleDepsInformation(info);
        info->has_module_deps_information.store(true,
                                                std::memory_order_release);
      }
    }
    return info;
  }

  const TargetInfo* GetTargetRustLibs(const Target* target) const {
    TargetInfo* info = GetTargetInfo(target);
    if (!info->has_rust_libs.load(std::memory_order_acquire)) {
      std::lock_guard<std::mutex> lock(info->mutex);
      if (!info->has_rust_libs.load(std::memory_order_relaxed)) {
        ComputeRustLibs(info);
        info->has_rust_libs.store(true, std::memory_order_release);
      }
    }
    return info;
  }

  const TargetInfo* GetTargetSwiftValues(const Target* target) const {
    TargetInfo* info = GetTargetInfo(target);
    if (!info->has_swift_values.load(std::memory_order_acquire)) {
      std::lock_guard<std::mutex> lock(info->mutex);
      if (!info->has_swift_values.load(std::memory_order_relaxed)) {
        ComputeSwiftValues(info);
        info->has_swift_values.store(true, std::memory_order_release);
      }
    }
    return info;
  }

  const TargetInfo* GetTargetOrderOnlyDeps(const Target* target) const {
    TargetInfo* info = GetTargetInfo(target);
    if (!info->has_order_only_deps.load(std::memory_order_acquire)) {
      std::lock_guard<std::mutex> lock(info->mutex);
      if (!info->has_order_only_deps.load(std::memory_order_relaxed)) {
        ComputeOrderOnlyDeps(info);
        info->has_order_only_deps.store(true, std::memory_order_release);
      }
    }
    return info;
  }

  // Compute the portion of TargetInfo guarded by one of the |has_xxx|
  // booleans. This performs recursive and expensive computations and
  // should only be called once per TargetInfo instance.
  void ComputeLibInfo(TargetInfo* info) const;
  void ComputeFrameworkInfo(TargetInfo* info) const;
  void ComputeHardDeps(TargetInfo* info) const;
  void ComputeInheritedLibs(TargetInfo* info) const;
  void ComputeModuleDepsInformation(TargetInfo* info) const;
  void ComputeRustLibs(TargetInfo* info) const;
  void ComputeSwiftValues(TargetInfo* info) const;
  void ComputeOrderOnlyDeps(TargetInfo* info) const;
  bool ComputeExportsPublicInputs(const TargetInfo* info) const;

  // Helper function used by ComputeInheritedLibs().
  void ComputeInheritedLibsFor(
      base::span<const Target*> deps,
      bool is_public,
      TargetPublicPairListBuilder* inherited_libraries) const;

  // Helper function used by ComputeModuleDepsInformation().
  void ComputeModuleDepsInformationFor(
      base::span<const Target*> deps,
      bool is_public,
      TargetPublicPairListBuilder* module_deps_information) const;

  // Helper data structure and function used by ComputeRustLibs().
  struct RustLibsBuilder {
    TargetPublicPairListBuilder inherited;
    TargetPublicPairListBuilder inheritable;
  };

  void ComputeRustLibsFor(base::span<const Target*> deps,
                          bool is_public,
                          RustLibsBuilder* rust_libs) const;

  // A { Target* -> TargetInfo } map that will create entries
  // on demand (hence the mutable qualifier). Implemented with a
  // UniqueVector<> and a parallel vector of unique TargetInfo
  // instances for best performance.
  // We shard the TargetInfo map to reduce lock contention under the
  // high-concurrency parallel writing phase of 'gn gen'. 128 shards is chosen
  // as the sweet spot based on benchmarking, providing optimal scaling for
  // high-core workstation counts (up to 128 threads) with negligible memory
  // overhead from empty shards.
  static constexpr size_t kNumShards = 128;
  struct Shard {
    mutable std::shared_mutex mutex;
    UniqueVector<const Target*> targets;
    std::vector<std::unique_ptr<TargetInfo>> infos;
  };

  // We use std::hash to distribute targets evenly across shards and avoid
  // pointer alignment biases.
  size_t GetShardIndex(const Target* target) const {
    return std::hash<const Target*>()(target) % kNumShards;
  }

  mutable Shard shards_[kNumShards];
};

#endif  // TOOLS_GN_RESOLVED_TARGET_DATA_H_
