// Copyright (c) 2017 Pierre Moreau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef INCLUDE_SPIRV_TOOLS_LINKER_HPP_
#define INCLUDE_SPIRV_TOOLS_LINKER_HPP_

#include <cstdint>
#include <memory>
#include <vector>

#include "libspirv.hpp"

namespace spvtools {

class SPIRV_TOOLS_EXPORT LinkerOptions {
 public:
  // Returns whether a library or an executable should be produced by the
  // linking phase.
  //
  // All exported symbols are kept when creating a library, whereas they will
  // be removed when creating an executable.
  // The returned value will be true if creating a library, and false if
  // creating an executable.
  bool GetCreateLibrary() const { return create_library_; }

  // Sets whether a library or an executable should be produced.
  void SetCreateLibrary(bool create_library) {
    create_library_ = create_library;
  }

  // Returns whether to verify the uniqueness of the unique ids in the merged
  // context.
  bool GetVerifyIds() const { return verify_ids_; }

  // Sets whether to verify the uniqueness of the unique ids in the merged
  // context.
  void SetVerifyIds(bool verify_ids) { verify_ids_ = verify_ids; }

  // Returns whether to allow for imported symbols to have no corresponding
  // exported symbols
  bool GetAllowPartialLinkage() const { return allow_partial_linkage_; }

  // Sets whether to allow for imported symbols to have no corresponding
  // exported symbols
  void SetAllowPartialLinkage(bool allow_partial_linkage) {
    allow_partial_linkage_ = allow_partial_linkage;
  }

  bool GetUseHighestVersion() const { return use_highest_version_; }
  void SetUseHighestVersion(bool use_highest_vers) {
    use_highest_version_ = use_highest_vers;
  }

  bool GetAllowPtrTypeMismatch() const { return allow_ptr_type_mismatch_; }
  void SetAllowPtrTypeMismatch(bool allow_ptr_type_mismatch) {
    allow_ptr_type_mismatch_ = allow_ptr_type_mismatch;
  }

  std::string GetFnVarTargetsCsv() const { return fnvar_targets_csv_; }
  void SetFnVarTargetsCsv(std::string fnvar_targets_csv) {
    fnvar_targets_csv_ = fnvar_targets_csv;
  }

  std::string GetFnVarArchitecturesCsv() const {
    return fnvar_architectures_csv_;
  }
  void SetFnVarArchitecturesCsv(std::string fnvar_architectures_csv) {
    fnvar_architectures_csv_ = fnvar_architectures_csv;
  }

  bool GetHasFnVarCapabilities() const { return has_fnvar_capabilities_; }
  void SetHasFnVarCapabilities(bool fnvar_capabilities) {
    has_fnvar_capabilities_ = fnvar_capabilities;
  }

  std::vector<std::string> GetInFiles() const { return in_files_; }
  void SetInFiles(std::vector<std::string> in_files) { in_files_ = in_files; }

 private:
  bool create_library_{false};
  bool verify_ids_{false};
  bool allow_partial_linkage_{false};
  bool use_highest_version_{false};
  bool allow_ptr_type_mismatch_{false};
  std::string fnvar_targets_csv_{""};
  std::string fnvar_architectures_csv_{""};
  bool has_fnvar_capabilities_ = false;
  std::vector<std::string> in_files_{{}};
};

// Links one or more SPIR-V modules into a new SPIR-V module. That is, combine
// several SPIR-V modules into one, resolving link dependencies between them.
//
// At least one binary has to be provided in |binaries|. Those binaries do not
// have to be valid, but they should be at least parseable.
// The functions can fail due to the following:
// * The given context was not initialised using `spvContextCreate()`;
// * No input modules were given;
// * One or more of those modules were not parseable;
// * The input modules used different addressing or memory models;
// * The ID or global variable number limit were exceeded;
// * Some entry points were defined multiple times;
// * Some imported symbols did not have an exported counterpart;
// * Possibly other reasons.
SPIRV_TOOLS_EXPORT spv_result_t
Link(const Context& context, const std::vector<std::vector<uint32_t>>& binaries,
     std::vector<uint32_t>* linked_binary,
     const LinkerOptions& options = LinkerOptions());
SPIRV_TOOLS_EXPORT spv_result_t
Link(const Context& context, const uint32_t* const* binaries,
     const size_t* binary_sizes, size_t num_binaries,
     std::vector<uint32_t>* linked_binary,
     const LinkerOptions& options = LinkerOptions());

}  // namespace spvtools

#endif  // INCLUDE_SPIRV_TOOLS_LINKER_HPP_
