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

#include "spirv_cross_parsed_ir.hpp"
#include <algorithm>
#include <assert.h>

using namespace std;
using namespace spv;

namespace SPIRV_CROSS_NAMESPACE
{
ParsedIR::ParsedIR()
{
	// If we move ParsedIR, we need to make sure the pointer stays fixed since the child Variant objects consume a pointer to this group,
	// so need an extra pointer here.
	pool_group.reset(new ObjectPoolGroup);

	pool_group->pools[TypeType].reset(new ObjectPool<SPIRType>);
	pool_group->pools[TypeVariable].reset(new ObjectPool<SPIRVariable>);
	pool_group->pools[TypeConstant].reset(new ObjectPool<SPIRConstant>);
	pool_group->pools[TypeFunction].reset(new ObjectPool<SPIRFunction>);
	pool_group->pools[TypeFunctionPrototype].reset(new ObjectPool<SPIRFunctionPrototype>);
	pool_group->pools[TypeBlock].reset(new ObjectPool<SPIRBlock>);
	pool_group->pools[TypeExtension].reset(new ObjectPool<SPIRExtension>);
	pool_group->pools[TypeExpression].reset(new ObjectPool<SPIRExpression>);
	pool_group->pools[TypeConstantOp].reset(new ObjectPool<SPIRConstantOp>);
	pool_group->pools[TypeCombinedImageSampler].reset(new ObjectPool<SPIRCombinedImageSampler>);
	pool_group->pools[TypeAccessChain].reset(new ObjectPool<SPIRAccessChain>);
	pool_group->pools[TypeUndef].reset(new ObjectPool<SPIRUndef>);
	pool_group->pools[TypeString].reset(new ObjectPool<SPIRString>);
}

// Should have been default-implemented, but need this on MSVC 2013.
ParsedIR::ParsedIR(ParsedIR &&other) SPIRV_CROSS_NOEXCEPT
{
	*this = move(other);
}

ParsedIR &ParsedIR::operator=(ParsedIR &&other) SPIRV_CROSS_NOEXCEPT
{
	if (this != &other)
	{
		pool_group = move(other.pool_group);
		spirv = move(other.spirv);
		meta = move(other.meta);
		for (int i = 0; i < TypeCount; i++)
			ids_for_type[i] = move(other.ids_for_type[i]);
		ids_for_constant_or_type = move(other.ids_for_constant_or_type);
		ids_for_constant_or_variable = move(other.ids_for_constant_or_variable);
		declared_capabilities = move(other.declared_capabilities);
		declared_extensions = move(other.declared_extensions);
		block_meta = move(other.block_meta);
		continue_block_to_loop_header = move(other.continue_block_to_loop_header);
		entry_points = move(other.entry_points);
		ids = move(other.ids);
		addressing_model = other.addressing_model;
		memory_model = other.memory_model;

		default_entry_point = other.default_entry_point;
		source = other.source;
		loop_iteration_depth_hard = other.loop_iteration_depth_hard;
		loop_iteration_depth_soft = other.loop_iteration_depth_soft;

		meta_needing_name_fixup = std::move(other.meta_needing_name_fixup);
	}
	return *this;
}

ParsedIR::ParsedIR(const ParsedIR &other)
    : ParsedIR()
{
	*this = other;
}

ParsedIR &ParsedIR::operator=(const ParsedIR &other)
{
	if (this != &other)
	{
		spirv = other.spirv;
		meta = other.meta;
		for (int i = 0; i < TypeCount; i++)
			ids_for_type[i] = other.ids_for_type[i];
		ids_for_constant_or_type = other.ids_for_constant_or_type;
		ids_for_constant_or_variable = other.ids_for_constant_or_variable;
		declared_capabilities = other.declared_capabilities;
		declared_extensions = other.declared_extensions;
		block_meta = other.block_meta;
		continue_block_to_loop_header = other.continue_block_to_loop_header;
		entry_points = other.entry_points;
		default_entry_point = other.default_entry_point;
		source = other.source;
		loop_iteration_depth_hard = other.loop_iteration_depth_hard;
		loop_iteration_depth_soft = other.loop_iteration_depth_soft;
		addressing_model = other.addressing_model;
		memory_model = other.memory_model;

		meta_needing_name_fixup = other.meta_needing_name_fixup;

		// Very deliberate copying of IDs. There is no default copy constructor, nor a simple default constructor.
		// Construct object first so we have the correct allocator set-up, then we can copy object into our new pool group.
		ids.clear();
		ids.reserve(other.ids.size());
		for (size_t i = 0; i < other.ids.size(); i++)
		{
			ids.emplace_back(pool_group.get());
			ids.back() = other.ids[i];
		}
	}
	return *this;
}

void ParsedIR::set_id_bounds(uint32_t bounds)
{
	ids.reserve(bounds);
	while (ids.size() < bounds)
		ids.emplace_back(pool_group.get());

	block_meta.resize(bounds);
}

// Roll our own versions of these functions to avoid potential locale shenanigans.
static bool is_alpha(char c)
{
	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}

static bool is_numeric(char c)
{
	return c >= '0' && c <= '9';
}

static bool is_alphanumeric(char c)
{
	return is_alpha(c) || is_numeric(c);
}

static bool is_valid_identifier(const string &name)
{
	if (name.empty())
		return true;

	if (is_numeric(name[0]))
		return false;

	for (auto c : name)
		if (!is_alphanumeric(c) && c != '_')
			return false;

	bool saw_underscore = false;
	// Two underscores in a row is not a valid identifier either.
	// Technically reserved, but it's easier to treat it as invalid.
	for (auto c : name)
	{
		bool is_underscore = c == '_';
		if (is_underscore && saw_underscore)
			return false;
		saw_underscore = is_underscore;
	}

	return true;
}

static bool is_reserved_prefix(const string &name)
{
	// Generic reserved identifiers used by the implementation.
	return name.compare(0, 3, "gl_", 3) == 0 ||
	       // Ignore this case for now, might rewrite internal code to always use spv prefix.
	       //name.compare(0, 11, "SPIRV_Cross", 11) == 0 ||
	       name.compare(0, 3, "spv", 3) == 0;
}

static bool is_reserved_identifier(const string &name, bool member, bool allow_reserved_prefixes)
{
	if (!allow_reserved_prefixes && is_reserved_prefix(name))
		return true;

	if (member)
	{
		// Reserved member identifiers come in one form:
		// _m[0-9]+$.
		if (name.size() < 3)
			return false;

		if (name.compare(0, 2, "_m", 2) != 0)
			return false;

		size_t index = 2;
		while (index < name.size() && is_numeric(name[index]))
			index++;

		return index == name.size();
	}
	else
	{
		// Reserved non-member identifiers come in two forms:
		// _[0-9]+$, used for temporaries which map directly to a SPIR-V ID.
		// _[0-9]+_, used for auxillary temporaries which derived from a SPIR-V ID.
		if (name.size() < 2)
			return false;

		if (name[0] != '_' || !is_numeric(name[1]))
			return false;

		size_t index = 2;
		while (index < name.size() && is_numeric(name[index]))
			index++;

		return index == name.size() || (index < name.size() && name[index] == '_');
	}
}

bool ParsedIR::is_globally_reserved_identifier(std::string &str, bool allow_reserved_prefixes)
{
	return is_reserved_identifier(str, false, allow_reserved_prefixes);
}

static string make_unreserved_identifier(const string &name)
{
	if (is_reserved_prefix(name))
		return "_RESERVED_IDENTIFIER_FIXUP_" + name;
	else
		return "_RESERVED_IDENTIFIER_FIXUP" + name;
}

void ParsedIR::sanitize_underscores(std::string &str)
{
	// Compact adjacent underscores to make it valid.
	auto dst = str.begin();
	auto src = dst;
	bool saw_underscore = false;
	while (src != str.end())
	{
		bool is_underscore = *src == '_';
		if (saw_underscore && is_underscore)
		{
			src++;
		}
		else
		{
			if (dst != src)
				*dst = *src;
			dst++;
			src++;
			saw_underscore = is_underscore;
		}
	}
	str.erase(dst, str.end());
}

static string ensure_valid_identifier(const string &name)
{
	// Functions in glslangValidator are mangled with name(<mangled> stuff.
	// Normally, we would never see '(' in any legal identifiers, so just strip them out.
	auto str = name.substr(0, name.find('('));

	if (str.empty())
		return str;

	if (is_numeric(str[0]))
		str[0] = '_';

	for (auto &c : str)
		if (!is_alphanumeric(c) && c != '_')
			c = '_';

	ParsedIR::sanitize_underscores(str);
	return str;
}

const string &ParsedIR::get_name(ID id) const
{
	auto *m = find_meta(id);
	if (m)
		return m->decoration.alias;
	else
		return empty_string;
}

const string &ParsedIR::get_member_name(TypeID id, uint32_t index) const
{
	auto *m = find_meta(id);
	if (m)
	{
		if (index >= m->members.size())
			return empty_string;
		return m->members[index].alias;
	}
	else
		return empty_string;
}

void ParsedIR::sanitize_identifier(std::string &name, bool member, bool allow_reserved_prefixes)
{
	if (!is_valid_identifier(name))
		name = ensure_valid_identifier(name);
	if (is_reserved_identifier(name, member, allow_reserved_prefixes))
		name = make_unreserved_identifier(name);
}

void ParsedIR::fixup_reserved_names()
{
	for (uint32_t id : meta_needing_name_fixup)
	{
		auto &m = meta[id];
		sanitize_identifier(m.decoration.alias, false, false);
		for (auto &memb : m.members)
			sanitize_identifier(memb.alias, true, false);
	}
	meta_needing_name_fixup.clear();
}

void ParsedIR::set_name(ID id, const string &name)
{
	auto &m = meta[id];
	m.decoration.alias = name;
	if (!is_valid_identifier(name) || is_reserved_identifier(name, false, false))
		meta_needing_name_fixup.insert(id);
}

void ParsedIR::set_member_name(TypeID id, uint32_t index, const string &name)
{
	auto &m = meta[id];
	m.members.resize(max(meta[id].members.size(), size_t(index) + 1));
	m.members[index].alias = name;
	if (!is_valid_identifier(name) || is_reserved_identifier(name, true, false))
		meta_needing_name_fixup.insert(id);
}

void ParsedIR::set_decoration_string(ID id, Decoration decoration, const string &argument)
{
	auto &dec = meta[id].decoration;
	dec.decoration_flags.set(decoration);

	switch (decoration)
	{
	case DecorationHlslSemanticGOOGLE:
		dec.hlsl_semantic = argument;
		break;

	default:
		break;
	}
}

void ParsedIR::set_decoration(ID id, Decoration decoration, uint32_t argument)
{
	auto &dec = meta[id].decoration;
	dec.decoration_flags.set(decoration);

	switch (decoration)
	{
	case DecorationBuiltIn:
		dec.builtin = true;
		dec.builtin_type = static_cast<BuiltIn>(argument);
		break;

	case DecorationLocation:
		dec.location = argument;
		break;

	case DecorationComponent:
		dec.component = argument;
		break;

	case DecorationOffset:
		dec.offset = argument;
		break;

	case DecorationXfbBuffer:
		dec.xfb_buffer = argument;
		break;

	case DecorationXfbStride:
		dec.xfb_stride = argument;
		break;

	case DecorationStream:
		dec.stream = argument;
		break;

	case DecorationArrayStride:
		dec.array_stride = argument;
		break;

	case DecorationMatrixStride:
		dec.matrix_stride = argument;
		break;

	case DecorationBinding:
		dec.binding = argument;
		break;

	case DecorationDescriptorSet:
		dec.set = argument;
		break;

	case DecorationInputAttachmentIndex:
		dec.input_attachment = argument;
		break;

	case DecorationSpecId:
		dec.spec_id = argument;
		break;

	case DecorationIndex:
		dec.index = argument;
		break;

	case DecorationHlslCounterBufferGOOGLE:
		meta[id].hlsl_magic_counter_buffer = argument;
		meta[argument].hlsl_is_magic_counter_buffer = true;
		break;

	case DecorationFPRoundingMode:
		dec.fp_rounding_mode = static_cast<FPRoundingMode>(argument);
		break;

	default:
		break;
	}
}

void ParsedIR::set_member_decoration(TypeID id, uint32_t index, Decoration decoration, uint32_t argument)
{
	meta[id].members.resize(max(meta[id].members.size(), size_t(index) + 1));
	auto &dec = meta[id].members[index];
	dec.decoration_flags.set(decoration);

	switch (decoration)
	{
	case DecorationBuiltIn:
		dec.builtin = true;
		dec.builtin_type = static_cast<BuiltIn>(argument);
		break;

	case DecorationLocation:
		dec.location = argument;
		break;

	case DecorationComponent:
		dec.component = argument;
		break;

	case DecorationBinding:
		dec.binding = argument;
		break;

	case DecorationOffset:
		dec.offset = argument;
		break;

	case DecorationXfbBuffer:
		dec.xfb_buffer = argument;
		break;

	case DecorationXfbStride:
		dec.xfb_stride = argument;
		break;

	case DecorationStream:
		dec.stream = argument;
		break;

	case DecorationSpecId:
		dec.spec_id = argument;
		break;

	case DecorationMatrixStride:
		dec.matrix_stride = argument;
		break;

	case DecorationIndex:
		dec.index = argument;
		break;

	default:
		break;
	}
}

// Recursively marks any constants referenced by the specified constant instruction as being used
// as an array length. The id must be a constant instruction (SPIRConstant or SPIRConstantOp).
void ParsedIR::mark_used_as_array_length(ID id)
{
	switch (ids[id].get_type())
	{
	case TypeConstant:
		get<SPIRConstant>(id).is_used_as_array_length = true;
		break;

	case TypeConstantOp:
	{
		auto &cop = get<SPIRConstantOp>(id);
		if (cop.opcode == OpCompositeExtract)
			mark_used_as_array_length(cop.arguments[0]);
		else if (cop.opcode == OpCompositeInsert)
		{
			mark_used_as_array_length(cop.arguments[0]);
			mark_used_as_array_length(cop.arguments[1]);
		}
		else
			for (uint32_t arg_id : cop.arguments)
				mark_used_as_array_length(arg_id);
		break;
	}

	case TypeUndef:
		break;

	default:
		assert(0);
	}
}

Bitset ParsedIR::get_buffer_block_type_flags(const SPIRType &type) const
{
	if (type.member_types.empty())
		return {};

	Bitset all_members_flags = get_member_decoration_bitset(type.self, 0);
	for (uint32_t i = 1; i < uint32_t(type.member_types.size()); i++)
		all_members_flags.merge_and(get_member_decoration_bitset(type.self, i));
	return all_members_flags;
}

Bitset ParsedIR::get_buffer_block_flags(const SPIRVariable &var) const
{
	auto &type = get<SPIRType>(var.basetype);
	assert(type.basetype == SPIRType::Struct);

	// Some flags like non-writable, non-readable are actually found
	// as member decorations. If all members have a decoration set, propagate
	// the decoration up as a regular variable decoration.
	Bitset base_flags;
	auto *m = find_meta(var.self);
	if (m)
		base_flags = m->decoration.decoration_flags;

	if (type.member_types.empty())
		return base_flags;

	auto all_members_flags = get_buffer_block_type_flags(type);
	base_flags.merge_or(all_members_flags);
	return base_flags;
}

const Bitset &ParsedIR::get_member_decoration_bitset(TypeID id, uint32_t index) const
{
	auto *m = find_meta(id);
	if (m)
	{
		if (index >= m->members.size())
			return cleared_bitset;
		return m->members[index].decoration_flags;
	}
	else
		return cleared_bitset;
}

bool ParsedIR::has_decoration(ID id, Decoration decoration) const
{
	return get_decoration_bitset(id).get(decoration);
}

uint32_t ParsedIR::get_decoration(ID id, Decoration decoration) const
{
	auto *m = find_meta(id);
	if (!m)
		return 0;

	auto &dec = m->decoration;
	if (!dec.decoration_flags.get(decoration))
		return 0;

	switch (decoration)
	{
	case DecorationBuiltIn:
		return dec.builtin_type;
	case DecorationLocation:
		return dec.location;
	case DecorationComponent:
		return dec.component;
	case DecorationOffset:
		return dec.offset;
	case DecorationXfbBuffer:
		return dec.xfb_buffer;
	case DecorationXfbStride:
		return dec.xfb_stride;
	case DecorationStream:
		return dec.stream;
	case DecorationBinding:
		return dec.binding;
	case DecorationDescriptorSet:
		return dec.set;
	case DecorationInputAttachmentIndex:
		return dec.input_attachment;
	case DecorationSpecId:
		return dec.spec_id;
	case DecorationArrayStride:
		return dec.array_stride;
	case DecorationMatrixStride:
		return dec.matrix_stride;
	case DecorationIndex:
		return dec.index;
	case DecorationFPRoundingMode:
		return dec.fp_rounding_mode;
	default:
		return 1;
	}
}

const string &ParsedIR::get_decoration_string(ID id, Decoration decoration) const
{
	auto *m = find_meta(id);
	if (!m)
		return empty_string;

	auto &dec = m->decoration;

	if (!dec.decoration_flags.get(decoration))
		return empty_string;

	switch (decoration)
	{
	case DecorationHlslSemanticGOOGLE:
		return dec.hlsl_semantic;

	default:
		return empty_string;
	}
}

void ParsedIR::unset_decoration(ID id, Decoration decoration)
{
	auto &dec = meta[id].decoration;
	dec.decoration_flags.clear(decoration);
	switch (decoration)
	{
	case DecorationBuiltIn:
		dec.builtin = false;
		break;

	case DecorationLocation:
		dec.location = 0;
		break;

	case DecorationComponent:
		dec.component = 0;
		break;

	case DecorationOffset:
		dec.offset = 0;
		break;

	case DecorationXfbBuffer:
		dec.xfb_buffer = 0;
		break;

	case DecorationXfbStride:
		dec.xfb_stride = 0;
		break;

	case DecorationStream:
		dec.stream = 0;
		break;

	case DecorationBinding:
		dec.binding = 0;
		break;

	case DecorationDescriptorSet:
		dec.set = 0;
		break;

	case DecorationInputAttachmentIndex:
		dec.input_attachment = 0;
		break;

	case DecorationSpecId:
		dec.spec_id = 0;
		break;

	case DecorationHlslSemanticGOOGLE:
		dec.hlsl_semantic.clear();
		break;

	case DecorationFPRoundingMode:
		dec.fp_rounding_mode = FPRoundingModeMax;
		break;

	case DecorationHlslCounterBufferGOOGLE:
	{
		auto &counter = meta[id].hlsl_magic_counter_buffer;
		if (counter)
		{
			meta[counter].hlsl_is_magic_counter_buffer = false;
			counter = 0;
		}
		break;
	}

	default:
		break;
	}
}

bool ParsedIR::has_member_decoration(TypeID id, uint32_t index, Decoration decoration) const
{
	return get_member_decoration_bitset(id, index).get(decoration);
}

uint32_t ParsedIR::get_member_decoration(TypeID id, uint32_t index, Decoration decoration) const
{
	auto *m = find_meta(id);
	if (!m)
		return 0;

	if (index >= m->members.size())
		return 0;

	auto &dec = m->members[index];
	if (!dec.decoration_flags.get(decoration))
		return 0;

	switch (decoration)
	{
	case DecorationBuiltIn:
		return dec.builtin_type;
	case DecorationLocation:
		return dec.location;
	case DecorationComponent:
		return dec.component;
	case DecorationBinding:
		return dec.binding;
	case DecorationOffset:
		return dec.offset;
	case DecorationXfbBuffer:
		return dec.xfb_buffer;
	case DecorationXfbStride:
		return dec.xfb_stride;
	case DecorationStream:
		return dec.stream;
	case DecorationSpecId:
		return dec.spec_id;
	case DecorationIndex:
		return dec.index;
	default:
		return 1;
	}
}

const Bitset &ParsedIR::get_decoration_bitset(ID id) const
{
	auto *m = find_meta(id);
	if (m)
	{
		auto &dec = m->decoration;
		return dec.decoration_flags;
	}
	else
		return cleared_bitset;
}

void ParsedIR::set_member_decoration_string(TypeID id, uint32_t index, Decoration decoration, const string &argument)
{
	meta[id].members.resize(max(meta[id].members.size(), size_t(index) + 1));
	auto &dec = meta[id].members[index];
	dec.decoration_flags.set(decoration);

	switch (decoration)
	{
	case DecorationHlslSemanticGOOGLE:
		dec.hlsl_semantic = argument;
		break;

	default:
		break;
	}
}

const string &ParsedIR::get_member_decoration_string(TypeID id, uint32_t index, Decoration decoration) const
{
	auto *m = find_meta(id);
	if (m)
	{
		if (!has_member_decoration(id, index, decoration))
			return empty_string;

		auto &dec = m->members[index];

		switch (decoration)
		{
		case DecorationHlslSemanticGOOGLE:
			return dec.hlsl_semantic;

		default:
			return empty_string;
		}
	}
	else
		return empty_string;
}

void ParsedIR::unset_member_decoration(TypeID id, uint32_t index, Decoration decoration)
{
	auto &m = meta[id];
	if (index >= m.members.size())
		return;

	auto &dec = m.members[index];

	dec.decoration_flags.clear(decoration);
	switch (decoration)
	{
	case DecorationBuiltIn:
		dec.builtin = false;
		break;

	case DecorationLocation:
		dec.location = 0;
		break;

	case DecorationComponent:
		dec.component = 0;
		break;

	case DecorationOffset:
		dec.offset = 0;
		break;

	case DecorationXfbBuffer:
		dec.xfb_buffer = 0;
		break;

	case DecorationXfbStride:
		dec.xfb_stride = 0;
		break;

	case DecorationStream:
		dec.stream = 0;
		break;

	case DecorationSpecId:
		dec.spec_id = 0;
		break;

	case DecorationHlslSemanticGOOGLE:
		dec.hlsl_semantic.clear();
		break;

	default:
		break;
	}
}

uint32_t ParsedIR::increase_bound_by(uint32_t incr_amount)
{
	auto curr_bound = ids.size();
	auto new_bound = curr_bound + incr_amount;

	ids.reserve(ids.size() + incr_amount);
	for (uint32_t i = 0; i < incr_amount; i++)
		ids.emplace_back(pool_group.get());

	block_meta.resize(new_bound);
	return uint32_t(curr_bound);
}

void ParsedIR::remove_typed_id(Types type, ID id)
{
	auto &type_ids = ids_for_type[type];
	type_ids.erase(remove(begin(type_ids), end(type_ids), id), end(type_ids));
}

void ParsedIR::reset_all_of_type(Types type)
{
	for (auto &id : ids_for_type[type])
		if (ids[id].get_type() == type)
			ids[id].reset();

	ids_for_type[type].clear();
}

void ParsedIR::add_typed_id(Types type, ID id)
{
	if (loop_iteration_depth_hard != 0)
		SPIRV_CROSS_THROW("Cannot add typed ID while looping over it.");

	if (loop_iteration_depth_soft != 0)
	{
		if (!ids[id].empty())
			SPIRV_CROSS_THROW("Cannot override IDs when loop is soft locked.");
		return;
	}

	if (ids[id].empty() || ids[id].get_type() != type)
	{
		switch (type)
		{
		case TypeConstant:
			ids_for_constant_or_variable.push_back(id);
			ids_for_constant_or_type.push_back(id);
			break;

		case TypeVariable:
			ids_for_constant_or_variable.push_back(id);
			break;

		case TypeType:
		case TypeConstantOp:
			ids_for_constant_or_type.push_back(id);
			break;

		default:
			break;
		}
	}

	if (ids[id].empty())
	{
		ids_for_type[type].push_back(id);
	}
	else if (ids[id].get_type() != type)
	{
		remove_typed_id(ids[id].get_type(), id);
		ids_for_type[type].push_back(id);
	}
}

const Meta *ParsedIR::find_meta(ID id) const
{
	auto itr = meta.find(id);
	if (itr != end(meta))
		return &itr->second;
	else
		return nullptr;
}

Meta *ParsedIR::find_meta(ID id)
{
	auto itr = meta.find(id);
	if (itr != end(meta))
		return &itr->second;
	else
		return nullptr;
}

ParsedIR::LoopLock ParsedIR::create_loop_hard_lock() const
{
	return ParsedIR::LoopLock(&loop_iteration_depth_hard);
}

ParsedIR::LoopLock ParsedIR::create_loop_soft_lock() const
{
	return ParsedIR::LoopLock(&loop_iteration_depth_soft);
}

ParsedIR::LoopLock::~LoopLock()
{
	if (lock)
		(*lock)--;
}

ParsedIR::LoopLock::LoopLock(uint32_t *lock_)
    : lock(lock_)
{
	if (lock)
		(*lock)++;
}

ParsedIR::LoopLock::LoopLock(LoopLock &&other) SPIRV_CROSS_NOEXCEPT
{
	*this = move(other);
}

ParsedIR::LoopLock &ParsedIR::LoopLock::operator=(LoopLock &&other) SPIRV_CROSS_NOEXCEPT
{
	if (lock)
		(*lock)--;
	lock = other.lock;
	other.lock = nullptr;
	return *this;
}

void ParsedIR::make_constant_null(uint32_t id, uint32_t type, bool add_to_typed_id_set)
{
	auto &constant_type = get<SPIRType>(type);

	if (constant_type.pointer)
	{
		if (add_to_typed_id_set)
			add_typed_id(TypeConstant, id);
		auto &constant = variant_set<SPIRConstant>(ids[id], type);
		constant.self = id;
		constant.make_null(constant_type);
	}
	else if (!constant_type.array.empty())
	{
		assert(constant_type.parent_type);
		uint32_t parent_id = increase_bound_by(1);
		make_constant_null(parent_id, constant_type.parent_type, add_to_typed_id_set);

		if (!constant_type.array_size_literal.back())
			SPIRV_CROSS_THROW("Array size of OpConstantNull must be a literal.");

		SmallVector<uint32_t> elements(constant_type.array.back());
		for (uint32_t i = 0; i < constant_type.array.back(); i++)
			elements[i] = parent_id;

		if (add_to_typed_id_set)
			add_typed_id(TypeConstant, id);
		variant_set<SPIRConstant>(ids[id], type, elements.data(), uint32_t(elements.size()), false).self = id;
	}
	else if (!constant_type.member_types.empty())
	{
		uint32_t member_ids = increase_bound_by(uint32_t(constant_type.member_types.size()));
		SmallVector<uint32_t> elements(constant_type.member_types.size());
		for (uint32_t i = 0; i < constant_type.member_types.size(); i++)
		{
			make_constant_null(member_ids + i, constant_type.member_types[i], add_to_typed_id_set);
			elements[i] = member_ids + i;
		}

		if (add_to_typed_id_set)
			add_typed_id(TypeConstant, id);
		variant_set<SPIRConstant>(ids[id], type, elements.data(), uint32_t(elements.size()), false).self = id;
	}
	else
	{
		if (add_to_typed_id_set)
			add_typed_id(TypeConstant, id);
		auto &constant = variant_set<SPIRConstant>(ids[id], type);
		constant.self = id;
		constant.make_null(constant_type);
	}
}

} // namespace SPIRV_CROSS_NAMESPACE
