/*
 * Copyright 2018-2021 Arm Limited
 * SPDX-License-Identifier: Apache-2.0 OR MIT
 *
 * 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.
 */

/*
 * At your option, you may choose to accept this material under either:
 *  1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
 *  2. The MIT License, found at <http://opensource.org/licenses/MIT>.
 */

#ifndef SPIRV_CROSS_PARSED_IR_HPP
#define SPIRV_CROSS_PARSED_IR_HPP

#include "spirv_common.hpp"
#include <stdint.h>
#include <unordered_map>

namespace SPIRV_CROSS_NAMESPACE
{

// This data structure holds all information needed to perform cross-compilation and reflection.
// It is the output of the Parser, but any implementation could create this structure.
// It is intentionally very "open" and struct-like with some helper functions to deal with decorations.
// Parser is the reference implementation of how this data structure should be filled in.

class ParsedIR
{
private:
	// This must be destroyed after the "ids" vector.
	std::unique_ptr<ObjectPoolGroup> pool_group;

public:
	ParsedIR();

	// Due to custom allocations from object pools, we cannot use a default copy constructor.
	ParsedIR(const ParsedIR &other);
	ParsedIR &operator=(const ParsedIR &other);

	// Moves are unproblematic, but we need to implement it anyways, since MSVC 2013 does not understand
	// how to default-implement these.
	ParsedIR(ParsedIR &&other) SPIRV_CROSS_NOEXCEPT;
	ParsedIR &operator=(ParsedIR &&other) SPIRV_CROSS_NOEXCEPT;

	// Resizes ids, meta and block_meta.
	void set_id_bounds(uint32_t bounds);

	// The raw SPIR-V, instructions and opcodes refer to this by offset + count.
	std::vector<uint32_t> spirv;

	// Holds various data structures which inherit from IVariant.
	SmallVector<Variant> ids;

	// Various meta data for IDs, decorations, names, etc.
	std::unordered_map<ID, Meta> meta;

	// Holds all IDs which have a certain type.
	// This is needed so we can iterate through a specific kind of resource quickly,
	// and in-order of module declaration.
	SmallVector<ID> ids_for_type[TypeCount];

	// Special purpose lists which contain a union of types.
	// This is needed so we can declare specialization constants and structs in an interleaved fashion,
	// among other things.
	// Constants can be undef or of struct type, and struct array sizes can use specialization constants.
	SmallVector<ID> ids_for_constant_undef_or_type;
	SmallVector<ID> ids_for_constant_or_variable;

	// We need to keep track of the width the Ops that contains a type for the
	// OpSwitch instruction, since this one doesn't contains the type in the
	// instruction itself. And in some case we need to cast the condition to
	// wider types. We only need the width to do the branch fixup since the
	// type check itself can be done at runtime
	std::unordered_map<ID, uint32_t> load_type_width;

	// Declared capabilities and extensions in the SPIR-V module.
	// Not really used except for reflection at the moment.
	SmallVector<spv::Capability> declared_capabilities;
	SmallVector<std::string> declared_extensions;

	// Meta data about blocks. The cross-compiler needs to query if a block is either of these types.
	// It is a bitset as there can be more than one tag per block.
	enum BlockMetaFlagBits
	{
		BLOCK_META_LOOP_HEADER_BIT = 1 << 0,
		BLOCK_META_CONTINUE_BIT = 1 << 1,
		BLOCK_META_LOOP_MERGE_BIT = 1 << 2,
		BLOCK_META_SELECTION_MERGE_BIT = 1 << 3,
		BLOCK_META_MULTISELECT_MERGE_BIT = 1 << 4
	};
	using BlockMetaFlags = uint8_t;
	SmallVector<BlockMetaFlags> block_meta;
	std::unordered_map<BlockID, BlockID> continue_block_to_loop_header;

	// Normally, we'd stick SPIREntryPoint in ids array, but it conflicts with SPIRFunction.
	// Entry points can therefore be seen as some sort of meta structure.
	std::unordered_map<FunctionID, SPIREntryPoint> entry_points;
	FunctionID default_entry_point = 0;

	struct Source
	{
		uint32_t version = 0;
		bool es = false;
		bool known = false;
		bool hlsl = false;

		Source() = default;
	};

	Source source;

	spv::AddressingModel addressing_model = spv::AddressingModelMax;
	spv::MemoryModel memory_model = spv::MemoryModelMax;

	// Decoration handling methods.
	// Can be useful for simple "raw" reflection.
	// However, most members are here because the Parser needs most of these,
	// and might as well just have the whole suite of decoration/name handling in one place.
	void set_name(ID id, const std::string &name);
	const std::string &get_name(ID id) const;
	void set_decoration(ID id, spv::Decoration decoration, uint32_t argument = 0);
	void set_decoration_string(ID id, spv::Decoration decoration, const std::string &argument);
	bool has_decoration(ID id, spv::Decoration decoration) const;
	uint32_t get_decoration(ID id, spv::Decoration decoration) const;
	const std::string &get_decoration_string(ID id, spv::Decoration decoration) const;
	const Bitset &get_decoration_bitset(ID id) const;
	void unset_decoration(ID id, spv::Decoration decoration);

	// Decoration handling methods (for members of a struct).
	void set_member_name(TypeID id, uint32_t index, const std::string &name);
	const std::string &get_member_name(TypeID id, uint32_t index) const;
	void set_member_decoration(TypeID id, uint32_t index, spv::Decoration decoration, uint32_t argument = 0);
	void set_member_decoration_string(TypeID id, uint32_t index, spv::Decoration decoration,
	                                  const std::string &argument);
	uint32_t get_member_decoration(TypeID id, uint32_t index, spv::Decoration decoration) const;
	const std::string &get_member_decoration_string(TypeID id, uint32_t index, spv::Decoration decoration) const;
	bool has_member_decoration(TypeID id, uint32_t index, spv::Decoration decoration) const;
	const Bitset &get_member_decoration_bitset(TypeID id, uint32_t index) const;
	void unset_member_decoration(TypeID id, uint32_t index, spv::Decoration decoration);

	void mark_used_as_array_length(ID id);
	uint32_t increase_bound_by(uint32_t count);
	Bitset get_buffer_block_flags(const SPIRVariable &var) const;
	Bitset get_buffer_block_type_flags(const SPIRType &type) const;

	void add_typed_id(Types type, ID id);
	void remove_typed_id(Types type, ID id);

	class LoopLock
	{
	public:
		explicit LoopLock(uint32_t *counter);
		LoopLock(const LoopLock &) = delete;
		void operator=(const LoopLock &) = delete;
		LoopLock(LoopLock &&other) SPIRV_CROSS_NOEXCEPT;
		LoopLock &operator=(LoopLock &&other) SPIRV_CROSS_NOEXCEPT;
		~LoopLock();

	private:
		uint32_t *lock;
	};

	// This must be held while iterating over a type ID array.
	// It is undefined if someone calls set<>() while we're iterating over a data structure, so we must
	// make sure that this case is avoided.

	// If we have a hard lock, it is an error to call set<>(), and an exception is thrown.
	// If we have a soft lock, we silently ignore any additions to the typed arrays.
	// This should only be used for physical ID remapping where we need to create an ID, but we will never
	// care about iterating over them.
	LoopLock create_loop_hard_lock() const;
	LoopLock create_loop_soft_lock() const;

	template <typename T, typename Op>
	void for_each_typed_id(const Op &op)
	{
		auto loop_lock = create_loop_hard_lock();
		for (auto &id : ids_for_type[T::type])
		{
			if (ids[id].get_type() == static_cast<Types>(T::type))
				op(id, get<T>(id));
		}
	}

	template <typename T, typename Op>
	void for_each_typed_id(const Op &op) const
	{
		auto loop_lock = create_loop_hard_lock();
		for (auto &id : ids_for_type[T::type])
		{
			if (ids[id].get_type() == static_cast<Types>(T::type))
				op(id, get<T>(id));
		}
	}

	template <typename T>
	void reset_all_of_type()
	{
		reset_all_of_type(static_cast<Types>(T::type));
	}

	void reset_all_of_type(Types type);

	Meta *find_meta(ID id);
	const Meta *find_meta(ID id) const;

	const std::string &get_empty_string() const
	{
		return empty_string;
	}

	void make_constant_null(uint32_t id, uint32_t type, bool add_to_typed_id_set);

	void fixup_reserved_names();

	static void sanitize_underscores(std::string &str);
	static void sanitize_identifier(std::string &str, bool member, bool allow_reserved_prefixes);
	static bool is_globally_reserved_identifier(std::string &str, bool allow_reserved_prefixes);

	uint32_t get_spirv_version() const;

private:
	template <typename T>
	T &get(uint32_t id)
	{
		return variant_get<T>(ids[id]);
	}

	template <typename T>
	const T &get(uint32_t id) const
	{
		return variant_get<T>(ids[id]);
	}

	mutable uint32_t loop_iteration_depth_hard = 0;
	mutable uint32_t loop_iteration_depth_soft = 0;
	std::string empty_string;
	Bitset cleared_bitset;

	std::unordered_set<uint32_t> meta_needing_name_fixup;
};
} // namespace SPIRV_CROSS_NAMESPACE

#endif
