// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
//
// 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.

#include "SpirvShader.hpp"

// If enabled, each instruction will be printed before processing.
#define PRINT_EACH_PROCESSED_INSTRUCTION 0

#ifdef ENABLE_VK_DEBUGGER

#	include "Vulkan/Debug/Context.hpp"
#	include "Vulkan/Debug/File.hpp"
#	include "Vulkan/Debug/Thread.hpp"
#	include "Vulkan/Debug/Variable.hpp"

#	include "spirv-tools/ext/OpenCLDebugInfo100.h"
#	include "spirv-tools/libspirv.h"

#	include <algorithm>

namespace {

// ArgTy<F>::type resolves to the single argument type of the function F.
template<typename F>
struct ArgTy
{
	using type = typename ArgTy<decltype(&F::operator())>::type;
};

template<typename R, typename C, typename Arg>
struct ArgTy<R (C::*)(Arg) const>
{
	using type = typename std::decay<Arg>::type;
};

template<typename T>
using ArgTyT = typename ArgTy<T>::type;

}  // anonymous namespace

namespace spvtools {

// Function implemented in third_party/SPIRV-Tools/source/disassemble.cpp
// but with no public header.
// This is a C++ function, so the name is mangled, and signature changes will
// result in a linker error instead of runtime signature mismatches.
extern std::string spvInstructionBinaryToText(const spv_target_env env,
                                              const uint32_t *inst_binary,
                                              const size_t inst_word_count,
                                              const uint32_t *binary,
                                              const size_t word_count,
                                              const uint32_t options);

}  // namespace spvtools

namespace {

const char *laneNames[] = { "Lane 0", "Lane 1", "Lane 2", "Lane 3" };
static_assert(sizeof(laneNames) / sizeof(laneNames[0]) == sw::SIMD::Width,
              "laneNames must have SIMD::Width entries");

template<typename T>
std::string tostring(const T &s)
{
	return std::to_string(s);
}
std::string tostring(char *s)
{
	return s;
}
std::string tostring(const char *s)
{
	return s;
}
std::string tostring(sw::SpirvShader::Object::ID id)
{
	return "%" + std::to_string(id.value());
}

////////////////////////////////////////////////////////////////////////////////
// OpenCL.Debug.100 data structures
////////////////////////////////////////////////////////////////////////////////
namespace debug {

struct Member;

struct Object
{
	enum class Kind
	{
		Object,
		Declare,
		Expression,
		Function,
		InlinedAt,
		LocalVariable,
		Member,
		Operation,
		Source,
		SourceScope,
		Value,

		// Scopes
		CompilationUnit,
		LexicalBlock,

		// Types
		BasicType,
		VectorType,
		FunctionType,
		CompositeType,
	};

	using ID = sw::SpirvID<Object>;
	static constexpr auto KIND = Kind::Object;
	inline Object(Kind kind)
	    : kind(kind)
	{}
	const Kind kind;

	// kindof() returns true iff kind is of this type, or any type deriving from
	// this type.
	static constexpr bool kindof(Object::Kind kind) { return true; }
};

template<typename TYPE_, typename BASE, Object::Kind KIND_>
struct ObjectImpl : public BASE
{
	using ID = sw::SpirvID<TYPE_>;
	static constexpr auto KIND = KIND_;

	ObjectImpl()
	    : BASE(KIND)
	{}
	static_assert(BASE::kindof(KIND), "BASE::kindof() returned false");

	// kindof() returns true iff kind is of this type, or any type deriving from
	// this type.
	static constexpr bool kindof(Object::Kind kind) { return kind == KIND; }
};

template<typename TO, typename FROM>
TO *cast(FROM *obj)
{
	return (TO::kindof(obj->kind)) ? static_cast<TO *>(obj) : nullptr;
}

template<typename TO, typename FROM>
const TO *cast(const FROM *obj)
{
	return (TO::kindof(obj->kind)) ? static_cast<const TO *>(obj) : nullptr;
}

struct Scope : public Object
{
	// Root represents the root stack frame scope.
	static const Scope Root;

	using ID = sw::SpirvID<Scope>;
	inline Scope(Kind kind)
	    : Object(kind)
	{}

	// kindof() returns true iff kind is of this type, or any type deriving from
	// this type.
	static constexpr bool kindof(Kind kind)
	{
		return kind == Kind::CompilationUnit ||
		       kind == Kind::LexicalBlock;
	}

	struct Source *source = nullptr;
};

struct Type : public Object
{
	using ID = sw::SpirvID<Type>;
	inline Type(Kind kind)
	    : Object(kind)
	{}

	// kindof() returns true iff kind is of this type, or any type deriving from
	// this type.
	static constexpr bool kindof(Kind kind)
	{
		return kind == Kind::BasicType ||
		       kind == Kind::VectorType ||
		       kind == Kind::FunctionType ||
		       kind == Kind::CompositeType;
	}
};

struct CompilationUnit : ObjectImpl<CompilationUnit, Scope, Object::Kind::CompilationUnit>
{
};

struct Source : ObjectImpl<Source, Object, Object::Kind::Source>
{
	spv::SourceLanguage language;
	uint32_t version = 0;
	std::string file;
	std::string source;

	std::shared_ptr<vk::dbg::File> dbgFile;
};

struct BasicType : ObjectImpl<BasicType, Type, Object::Kind::BasicType>
{
	std::string name;
	uint32_t size = 0;  // in bits.
	OpenCLDebugInfo100DebugBaseTypeAttributeEncoding encoding = OpenCLDebugInfo100Unspecified;
};

struct VectorType : ObjectImpl<VectorType, Type, Object::Kind::VectorType>
{
	Type *base = nullptr;
	uint32_t components = 0;
};

struct FunctionType : ObjectImpl<FunctionType, Type, Object::Kind::FunctionType>
{
	uint32_t flags = 0;  // OR'd from OpenCLDebugInfo100DebugInfoFlags
	Type *returnTy = nullptr;
	std::vector<Type *> paramTys;
};

struct CompositeType : ObjectImpl<CompositeType, Type, Object::Kind::CompositeType>
{
	std::string name;
	OpenCLDebugInfo100DebugCompositeType tag = OpenCLDebugInfo100Class;
	Source *source = nullptr;
	uint32_t line = 0;
	uint32_t column = 0;
	Object *parent = nullptr;
	std::string linkage;
	uint32_t size = 0;   // in bits.
	uint32_t flags = 0;  // OR'd from OpenCLDebugInfo100DebugInfoFlags
	std::vector<Member *> members;
};

struct Member : ObjectImpl<Member, Object, Object::Kind::Member>
{
	std::string name;
	Type *type = nullptr;
	Source *source = nullptr;
	uint32_t line = 0;
	uint32_t column = 0;
	CompositeType *parent = nullptr;
	uint32_t offset = 0;  // in bits
	uint32_t size = 0;    // in bits
	uint32_t flags = 0;   // OR'd from OpenCLDebugInfo100DebugInfoFlags
};

struct Function : ObjectImpl<Function, Object, Object::Kind::Function>
{
	std::string name;
	FunctionType *type = nullptr;
	Source *source = nullptr;
	uint32_t line = 0;
	uint32_t column = 0;
	struct LexicalBlock *parent = nullptr;
	std::string linkage;
	uint32_t flags = 0;  // OR'd from OpenCLDebugInfo100DebugInfoFlags
	uint32_t scopeLine = 0;
	sw::SpirvShader::Function::ID function;
};

struct LexicalBlock : ObjectImpl<LexicalBlock, Scope, Object::Kind::LexicalBlock>
{
	uint32_t line = 0;
	uint32_t column = 0;
	Scope *parent = nullptr;
	std::string name;
	Function *function = nullptr;
};

struct InlinedAt : ObjectImpl<InlinedAt, Object, Object::Kind::InlinedAt>
{
	uint32_t line = 0;
	Scope *scope = nullptr;
	InlinedAt *inlined = nullptr;
};

struct SourceScope : ObjectImpl<SourceScope, Object, Object::Kind::SourceScope>
{
	LexicalBlock *scope = nullptr;
	InlinedAt *inlinedAt = nullptr;
};

struct LocalVariable : ObjectImpl<LocalVariable, Object, Object::Kind::LocalVariable>
{
	static constexpr uint32_t NoArg = ~uint32_t(0);

	std::string name;
	Type *type = nullptr;
	Source *source = nullptr;
	uint32_t line = 0;
	uint32_t column = 0;
	Scope *parent = nullptr;
	uint32_t arg = NoArg;
};

struct Operation : ObjectImpl<Operation, Object, Object::Kind::Operation>
{
	uint32_t opcode = 0;
	std::vector<uint32_t> operands;
};

struct Expression : ObjectImpl<Expression, Object, Object::Kind::Expression>
{
	std::vector<Operation *> operations;
};

struct Declare : ObjectImpl<Declare, Object, Object::Kind::Declare>
{
	LocalVariable *local = nullptr;
	sw::SpirvShader::Object::ID variable;
	Expression *expression = nullptr;
};

struct Value : ObjectImpl<Value, Object, Object::Kind::Value>
{
	LocalVariable *local = nullptr;
	sw::SpirvShader::Object::ID variable;
	Expression *expression = nullptr;
	std::vector<uint32_t> indexes;
};

const Scope Scope::Root = CompilationUnit{};

}  // namespace debug
}  // anonymous namespace

namespace rr {

////////////////////////////////////////////////////////////////////////////////
// rr::CToReactor<T> specializations.
////////////////////////////////////////////////////////////////////////////////
template<typename T>
struct CToReactor<sw::SpirvID<T>>
{
	using type = rr::Int;
	static rr::Int cast(sw::SpirvID<T> id) { return rr::Int(id.value()); }
};

template<typename T>
struct CToReactor<vk::dbg::ID<T>>
{
	using type = rr::Int;
	static rr::Int cast(vk::dbg::ID<T> id) { return rr::Int(id.value()); }
};

}  // namespace rr

namespace sw {

////////////////////////////////////////////////////////////////////////////////
// sw::SpirvShader::Impl::Debugger
//
// Private struct holding debugger information for the SpirvShader.
////////////////////////////////////////////////////////////////////////////////
struct SpirvShader::Impl::Debugger
{
	class Group;
	class State;

	enum class Pass
	{
		Define,
		Emit
	};

	void process(const SpirvShader *shader, const InsnIterator &insn, EmitState *state, Pass pass);

	void setPosition(EmitState *state, const std::string &path, uint32_t line, uint32_t column);

	// exposeVariable exposes the variable with the given ID to the debugger
	// using the specified key.
	template<typename Key>
	void exposeVariable(
	    const SpirvShader *shader,
	    const Key &key,
	    const debug::Scope *scope,
	    const debug::Type *type,
	    Object::ID id,
	    EmitState *state) const;

	// exposeVariable exposes the variable with the given ID to the
	// debugger under the specified group, for the specified SIMD lane.
	template<typename Key>
	void exposeVariable(
	    const SpirvShader *shader,
	    const Group &group,
	    int lane,
	    const Key &key,
	    const debug::Type *type,
	    Object::ID id,
	    EmitState *state,
	    int wordOffset = 0) const;

	std::shared_ptr<vk::dbg::Context> ctx;
	std::shared_ptr<vk::dbg::File> spirvFile;
	std::unordered_map<const void *, int> spirvLineMappings;  // instruction pointer to line
	std::unordered_map<const void *, Object::ID> results;     // instruction pointer to result ID

private:
	// add() registers the debug object with the given id.
	template<typename ID, typename T>
	void add(ID id, T *);

	// get() returns the debug object with the given id.
	// The object must exist and be of type (or derive from type) T.
	template<typename T>
	T *get(SpirvID<T> id) const;

	// use get() and add() to access this
	std::unordered_map<debug::Object::ID, std::unique_ptr<debug::Object>> objects;

	std::unordered_map<std::string, vk::dbg::File::ID> fileIDs;

	// defineOrEmit() when called in Pass::Define, creates and stores a
	// zero-initialized object into the Debugger::objects map using the
	// object identifier held by second instruction operand.
	// When called in Pass::Emit, defineOrEmit() calls the function F with the
	// previously-built object.
	//
	// F must be a function with the signature:
	//   void(OBJECT_TYPE *)
	//
	// The object type is automatically inferred from the function signature.
	template<typename F, typename T = typename std::remove_pointer<ArgTyT<F>>::type>
	void defineOrEmit(InsnIterator insn, Pass pass, F &&emit);
};

////////////////////////////////////////////////////////////////////////////////
// sw::SpirvShader::Impl::Debugger::State
//
// State holds the runtime data structures for the shader debug session.
////////////////////////////////////////////////////////////////////////////////
class SpirvShader::Impl::Debugger::State
{
public:
	static State *create(const Debugger *debugger, const char *name);
	static void destroy(State *);

	State(const Debugger *debugger, const char *stackBase, vk::dbg::Context::Lock &lock);
	~State();

	void enter(vk::dbg::Context::Lock &lock, const char *name);
	void exit();
	void updateActiveLaneMask(int lane, bool enabled);
	void update(vk::dbg::File::ID file, int line, int column);
	void createScope(const debug::Scope *);
	void setScope(debug::SourceScope *newScope);

	vk::dbg::VariableContainer *hovers(const debug::Scope *);
	vk::dbg::VariableContainer *localsLane(const debug::Scope *, int lane);
	vk::dbg::VariableContainer *builtinsLane(int lane);

	template<typename K>
	vk::dbg::VariableContainer *group(vk::dbg::VariableContainer *vc, K key);

	template<typename K, typename V>
	void putVal(vk::dbg::VariableContainer *vc, K key, V value);

	template<typename K, typename V>
	void putRef(vk::dbg::VariableContainer *vc, K key, V *ptr);

	// Scopes holds pointers to the vk::dbg::Scopes for local variables, hover
	// variables and the locals indexed by SIMD lane.
	struct Scopes
	{
		std::shared_ptr<vk::dbg::Scope> locals;
		std::shared_ptr<vk::dbg::Scope> hovers;
		std::array<std::shared_ptr<vk::dbg::VariableContainer>, sw::SIMD::Width> localsByLane;
	};

	// getScopes() returns the Scopes object for the given debug::Scope.
	const Scopes &getScopes(const debug::Scope *scope);

	const Debugger *debugger;
	const std::shared_ptr<vk::dbg::Thread> thread;
	std::unordered_map<const debug::Scope *, Scopes> scopes;
	Scopes rootScopes;                                                                        // Scopes for the root stack frame.
	std::array<std::shared_ptr<vk::dbg::VariableContainer>, sw::SIMD::Width> builtinsByLane;  // Scopes for builtin varibles (shared by all shader frames).
	debug::SourceScope *srcScope = nullptr;                                                   // Current source scope.
};

SpirvShader::Impl::Debugger::State *SpirvShader::Impl::Debugger::State::create(const Debugger *debugger, const char *name)
{
	auto lock = debugger->ctx->lock();
	return new State(debugger, name, lock);
}

void SpirvShader::Impl::Debugger::State::destroy(State *state)
{
	delete state;
}

SpirvShader::Impl::Debugger::State::State(const Debugger *debugger, const char *stackBase, vk::dbg::Context::Lock &lock)
    : debugger(debugger)
    , thread(lock.currentThread())
{
	enter(lock, stackBase);

	for(int i = 0; i < sw::SIMD::Width; i++)
	{
		builtinsByLane[i] = lock.createVariableContainer();
	}

	thread->update([&](vk::dbg::Frame &frame) {
		rootScopes.locals = frame.locals;
		rootScopes.hovers = frame.hovers;
		for(int i = 0; i < sw::SIMD::Width; i++)
		{
			auto locals = lock.createVariableContainer();
			locals->extend(builtinsByLane[i]);
			frame.locals->variables->put(laneNames[i], locals);
			rootScopes.localsByLane[i] = locals;
		}
	});
}

SpirvShader::Impl::Debugger::State::~State()
{
	exit();
}

void SpirvShader::Impl::Debugger::State::enter(vk::dbg::Context::Lock &lock, const char *name)
{
	thread->enter(lock, debugger->spirvFile, name);
}

void SpirvShader::Impl::Debugger::State::exit()
{
	thread->exit();
}

void SpirvShader::Impl::Debugger::State::updateActiveLaneMask(int lane, bool enabled)
{
	rootScopes.localsByLane[lane]->put("enabled", vk::dbg::make_constant(enabled));
}

void SpirvShader::Impl::Debugger::State::update(vk::dbg::File::ID fileID, int line, int column)
{
	auto file = debugger->ctx->lock().get(fileID);
	thread->update([&](vk::dbg::Frame &frame) {
		frame.location = { file, line, column };
	});
}

vk::dbg::VariableContainer *SpirvShader::Impl::Debugger::State::hovers(const debug::Scope *scope)
{
	return getScopes(scope).hovers->variables.get();
}

vk::dbg::VariableContainer *SpirvShader::Impl::Debugger::State::localsLane(const debug::Scope *scope, int i)
{
	return getScopes(scope).localsByLane[i].get();
}

vk::dbg::VariableContainer *SpirvShader::Impl::Debugger::State::builtinsLane(int i)
{
	return builtinsByLane[i].get();
}

template<typename K>
vk::dbg::VariableContainer *SpirvShader::Impl::Debugger::State::group(vk::dbg::VariableContainer *vc, K key)
{
	auto out = debugger->ctx->lock().createVariableContainer();
	vc->put(tostring(key), out);
	return out.get();
}

template<typename K, typename V>
void SpirvShader::Impl::Debugger::State::putVal(vk::dbg::VariableContainer *vc, K key, V value)
{
	vc->put(tostring(key), vk::dbg::make_constant(value));
}

template<typename K, typename V>
void SpirvShader::Impl::Debugger::State::putRef(vk::dbg::VariableContainer *vc, K key, V *ptr)
{
	vc->put(tostring(key), vk::dbg::make_reference(*ptr));
}

void SpirvShader::Impl::Debugger::State::createScope(const debug::Scope *spirvScope)
{
	ASSERT(spirvScope != nullptr);

	// TODO: Deal with scope nesting.

	auto lock = debugger->ctx->lock();
	Scopes s = {};
	s.locals = lock.createScope(spirvScope->source->dbgFile);
	s.hovers = lock.createScope(spirvScope->source->dbgFile);
	for(int i = 0; i < sw::SIMD::Width; i++)
	{
		auto locals = lock.createVariableContainer();
		locals->extend(builtinsByLane[i]);
		s.localsByLane[i] = locals;
		s.locals->variables->put(laneNames[i], locals);
	}
	scopes.emplace(spirvScope, std::move(s));
}

void SpirvShader::Impl::Debugger::State::setScope(debug::SourceScope *newSrcScope)
{
	auto oldSrcScope = srcScope;
	if(oldSrcScope == newSrcScope) { return; }
	srcScope = newSrcScope;

	auto lock = debugger->ctx->lock();
	auto thread = lock.currentThread();

	debug::Function *oldFunction = oldSrcScope ? oldSrcScope->scope->function : nullptr;
	debug::Function *newFunction = newSrcScope ? newSrcScope->scope->function : nullptr;

	if(oldFunction != newFunction)
	{
		if(oldFunction) { thread->exit(); }
		if(newFunction) { thread->enter(lock, newFunction->source->dbgFile, newFunction->name); }
	}

	auto dbgScope = getScopes(srcScope->scope);
	thread->update([&](vk::dbg::Frame &frame) {
		frame.locals = dbgScope.locals;
		frame.hovers = dbgScope.hovers;
	});
}

const SpirvShader::Impl::Debugger::State::Scopes &SpirvShader::Impl::Debugger::State::getScopes(const debug::Scope *scope)
{
	if(scope == &debug::Scope::Root)
	{
		return rootScopes;
	}

	auto dbgScopeIt = scopes.find(scope);
	ASSERT_MSG(dbgScopeIt != scopes.end(), "createScope() not called for debug::Scope %p", scope);
	return dbgScopeIt->second;
}

////////////////////////////////////////////////////////////////////////////////
// sw::SpirvShader::Impl::Debugger::Group
//
// This provides a convenient C++ interface for adding debugger values to
// VariableContainers.
////////////////////////////////////////////////////////////////////////////////
class SpirvShader::Impl::Debugger::Group
{
public:
	using Ptr = rr::Pointer<rr::Byte>;

	static Group hovers(Ptr state, const debug::Scope *scope);
	static Group locals(Ptr state, const debug::Scope *scope);
	static Group localsLane(Ptr state, const debug::Scope *scope, int lane);
	static Group builtinsLane(Ptr state, int lane);

	Group(Ptr state, Ptr group);

	template<typename K, typename RK>
	Group group(RK key) const;

	template<typename K, typename V, typename RK, typename RV>
	void put(RK key, RV value) const;

	template<typename K, typename V, typename RK>
	void putRef(RK key, RValue<Pointer<Byte>> ref) const;

	template<typename K, typename V, typename RK, typename RV>
	void put(RK key, RV x, RV y) const;

	template<typename K, typename V, typename RK, typename RV>
	void put(RK key, RV x, RV y, RV z) const;

	template<typename K, typename V, typename RK, typename RV>
	void put(RK key, RV x, RV y, RV z, RV w) const;

	template<typename K, typename V, typename VEC>
	void putVec3(K key, const VEC &v) const;

private:
	Ptr state;
	Ptr ptr;
};

SpirvShader::Impl::Debugger::Group
SpirvShader::Impl::Debugger::Group::hovers(Ptr state, const debug::Scope *scope)
{
	return Group(state, rr::Call(&State::hovers, state, scope));
}

SpirvShader::Impl::Debugger::Group
SpirvShader::Impl::Debugger::Group::localsLane(Ptr state, const debug::Scope *scope, int lane)
{
	return Group(state, rr::Call(&State::localsLane, state, scope, lane));
}

SpirvShader::Impl::Debugger::Group
SpirvShader::Impl::Debugger::Group::builtinsLane(Ptr state, int lane)
{
	return Group(state, rr::Call(&State::builtinsLane, state, lane));
}

SpirvShader::Impl::Debugger::Group::Group(Ptr state, Ptr group)
    : state(state)
    , ptr(group)
{}

template<typename K, typename RK>
SpirvShader::Impl::Debugger::Group SpirvShader::Impl::Debugger::Group::group(RK key) const
{
	return Group(state, rr::Call(&State::group<K>, state, ptr, key));
}

template<typename K, typename V, typename RK, typename RV>
void SpirvShader::Impl::Debugger::Group::put(RK key, RV value) const
{
	rr::Call(&State::putVal<K, V>, state, ptr, key, value);
}

template<typename K, typename V, typename RK>
void SpirvShader::Impl::Debugger::Group::putRef(RK key, RValue<Pointer<Byte>> ref) const
{
	rr::Call(&State::putRef<K, V>, state, ptr, key, ref);
}

template<typename K, typename V, typename RK, typename RV>
void SpirvShader::Impl::Debugger::Group::put(RK key, RV x, RV y) const
{
	auto vec = group<K>(key);
	vec.template put<const char *, V>("x", x);
	vec.template put<const char *, V>("y", y);
}

template<typename K, typename V, typename RK, typename RV>
void SpirvShader::Impl::Debugger::Group::put(RK key, RV x, RV y, RV z) const
{
	auto vec = group<K>(key);
	vec.template put<const char *, V>("x", x);
	vec.template put<const char *, V>("y", y);
	vec.template put<const char *, V>("z", z);
}

template<typename K, typename V, typename RK, typename RV>
void SpirvShader::Impl::Debugger::Group::put(RK key, RV x, RV y, RV z, RV w) const
{
	auto vec = group<K>(key);
	vec.template put<const char *, V>("x", x);
	vec.template put<const char *, V>("y", y);
	vec.template put<const char *, V>("z", z);
	vec.template put<const char *, V>("w", w);
}

template<typename K, typename V, typename VEC>
void SpirvShader::Impl::Debugger::Group::putVec3(K key, const VEC &v) const
{
	auto vec = group<K>(key);
	vec.template put<const char *, V>("x", Extract(v, 0));
	vec.template put<const char *, V>("y", Extract(v, 1));
	vec.template put<const char *, V>("z", Extract(v, 2));
}

////////////////////////////////////////////////////////////////////////////////
// sw::SpirvShader::Impl::Debugger methods
////////////////////////////////////////////////////////////////////////////////
template<typename F, typename T>
void SpirvShader::Impl::Debugger::defineOrEmit(InsnIterator insn, Pass pass, F &&emit)
{
	auto id = SpirvID<T>(insn.word(2));
	switch(pass)
	{
		case Pass::Define:
			add(id, new T());
			break;
		case Pass::Emit:
			emit(get<T>(id));
			break;
	}
}

void SpirvShader::Impl::Debugger::process(const SpirvShader *shader, const InsnIterator &insn, EmitState *state, Pass pass)
{
	auto dbg = shader->impl.debugger;
	auto extInstIndex = insn.word(4);
	switch(extInstIndex)
	{
		case OpenCLDebugInfo100DebugCompilationUnit:
			defineOrEmit(insn, pass, [&](debug::CompilationUnit *cu) {
				cu->source = get(debug::Source::ID(insn.word(7)));
			});
			break;
		case OpenCLDebugInfo100DebugTypeBasic:
			defineOrEmit(insn, pass, [&](debug::BasicType *type) {
				type->name = shader->getString(insn.word(5));
				type->size = shader->GetConstScalarInt(insn.word(6));
				type->encoding = static_cast<OpenCLDebugInfo100DebugBaseTypeAttributeEncoding>(insn.word(7));
			});
			break;
		case OpenCLDebugInfo100DebugTypeVector:
			defineOrEmit(insn, pass, [&](debug::VectorType *type) {
				type->base = get(debug::Type::ID(insn.word(5)));
				type->components = insn.word(6);
			});
			break;
		case OpenCLDebugInfo100DebugTypeFunction:
			defineOrEmit(insn, pass, [&](debug::FunctionType *type) {
				type->flags = insn.word(5);
				type->returnTy = get(debug::Type::ID(insn.word(6)));
				for(uint32_t i = 7; i < insn.wordCount(); i++)
				{
					type->paramTys.push_back(get(debug::Type::ID(insn.word(i))));
				}
			});
			break;
		case OpenCLDebugInfo100DebugTypeComposite:
			defineOrEmit(insn, pass, [&](debug::CompositeType *type) {
				type->name = shader->getString(insn.word(5));
				type->tag = static_cast<OpenCLDebugInfo100DebugCompositeType>(insn.word(6));
				type->source = get(debug::Source::ID(insn.word(7)));
				type->line = insn.word(8);
				type->column = insn.word(9);
				type->parent = get(debug::Object::ID(insn.word(10)));
				type->linkage = shader->getString(insn.word(11));
				type->size = shader->GetConstScalarInt(insn.word(12));
				type->flags = insn.word(13);
				for(uint32_t i = 14; i < insn.wordCount(); i++)
				{
					auto obj = get(debug::Object::ID(insn.word(i)));
					if(auto member = debug::cast<debug::Member>(obj))  // Can also be Function or TypeInheritance, which we don't care about.
					{
						type->members.push_back(member);
					}
				}
			});
			break;
		case OpenCLDebugInfo100DebugTypeMember:
			defineOrEmit(insn, pass, [&](debug::Member *member) {
				member->name = shader->getString(insn.word(5));
				member->type = get(debug::Type::ID(insn.word(6)));
				member->source = get(debug::Source::ID(insn.word(7)));
				member->line = insn.word(8);
				member->column = insn.word(9);
				member->parent = get(debug::CompositeType::ID(insn.word(10)));
				member->offset = shader->GetConstScalarInt(insn.word(11));
				member->size = shader->GetConstScalarInt(insn.word(12));
				member->flags = insn.word(13);
			});
			break;
		case OpenCLDebugInfo100DebugFunction:
			defineOrEmit(insn, pass, [&](debug::Function *func) {
				func->name = shader->getString(insn.word(5));
				func->type = get(debug::FunctionType::ID(insn.word(6)));
				func->source = get(debug::Source::ID(insn.word(7)));
				func->line = insn.word(8);
				func->column = insn.word(9);
				func->parent = get(debug::LexicalBlock::ID(insn.word(10)));
				func->linkage = shader->getString(insn.word(11));
				func->flags = insn.word(12);
				func->scopeLine = insn.word(13);
				func->function = Function::ID(insn.word(14));
				// declaration: word(13)

				func->parent->function = func;
			});
			break;
		case OpenCLDebugInfo100DebugLexicalBlock:
			defineOrEmit(insn, pass, [&](debug::LexicalBlock *scope) {
				scope->source = get(debug::Source::ID(insn.word(5)));
				scope->line = insn.word(6);
				scope->column = insn.word(7);
				scope->parent = get(debug::Scope::ID(insn.word(8)));
				if(insn.wordCount() > 9)
				{
					scope->name = shader->getString(insn.word(9));
				}

				// TODO: We're creating scopes per-shader invocation.
				// This is all really static information, and should only be created
				// once *per program*.
				rr::Call(&State::createScope, state->routine->dbgState, scope);
			});
			break;
		case OpenCLDebugInfo100DebugScope:
			defineOrEmit(insn, pass, [&](debug::SourceScope *ss) {
				ss->scope = get(debug::LexicalBlock::ID(insn.word(5)));
				if(insn.wordCount() > 6)
				{
					ss->inlinedAt = get(debug::InlinedAt::ID(insn.word(6)));
				}

				rr::Call(&State::setScope, state->routine->dbgState, ss);
			});
			break;
		case OpenCLDebugInfo100DebugNoScope:
			break;
		case OpenCLDebugInfo100DebugLocalVariable:
			defineOrEmit(insn, pass, [&](debug::LocalVariable *var) {
				var->name = shader->getString(insn.word(5));
				var->type = get(debug::Type::ID(insn.word(6)));
				var->source = get(debug::Source::ID(insn.word(7)));
				var->line = insn.word(8);
				var->column = insn.word(9);
				var->parent = get(debug::Scope::ID(insn.word(10)));
				if(insn.wordCount() > 11)
				{
					var->arg = insn.word(11);
				}
			});
			break;
		case OpenCLDebugInfo100DebugDeclare:
			defineOrEmit(insn, pass, [&](debug::Declare *decl) {
				decl->local = get(debug::LocalVariable::ID(insn.word(5)));
				decl->variable = Object::ID(insn.word(6));
				decl->expression = get(debug::Expression::ID(insn.word(7)));
				exposeVariable(
				    shader,
				    decl->local->name.c_str(),
				    decl->local->parent,
				    decl->local->type,
				    decl->variable,
				    state);
			});
			break;
		case OpenCLDebugInfo100DebugValue:
			defineOrEmit(insn, pass, [&](debug::Value *value) {
				value->local = get(debug::LocalVariable::ID(insn.word(5)));
				value->variable = Object::ID(insn.word(6));
				value->expression = get(debug::Expression::ID(insn.word(7)));
				for(uint32_t i = 8; i < insn.wordCount(); i++)
				{
					value->indexes.push_back(insn.word(i));
				}
			});
			break;
		case OpenCLDebugInfo100DebugExpression:
			defineOrEmit(insn, pass, [&](debug::Expression *expr) {
				for(uint32_t i = 5; i < insn.wordCount(); i++)
				{
					expr->operations.push_back(get(debug::Operation::ID(insn.word(i))));
				}
			});
			break;
		case OpenCLDebugInfo100DebugSource:
			defineOrEmit(insn, pass, [&](debug::Source *source) {
				source->file = shader->getString(insn.word(5));
				if(insn.wordCount() > 6)
				{
					source->source = shader->getString(insn.word(6));
				}

				auto file = dbg->ctx->lock().createVirtualFile(source->file.c_str(), source->source.c_str());
				source->dbgFile = file;
				fileIDs.emplace(source->file.c_str(), file->id);
			});
			break;
		default:
			UNSUPPORTED("Unsupported OpenCLDebugInfo100 instruction %d", int(extInstIndex));
	}
}

void SpirvShader::Impl::Debugger::setPosition(EmitState *state, const std::string &path, uint32_t line, uint32_t column)
{
	auto it = fileIDs.find(path);
	if(it != fileIDs.end())
	{
		rr::Call(&State::update, state->routine->dbgState, it->second, line, column);
	}
}

template<typename ID, typename T>
void SpirvShader::Impl::Debugger::add(ID id, T *obj)
{
	auto added = objects.emplace(debug::Object::ID(id.value()), obj).second;
	ASSERT_MSG(added, "Debug object with %d already exists", id.value());
}

template<typename T>
T *SpirvShader::Impl::Debugger::get(SpirvID<T> id) const
{
	auto it = objects.find(debug::Object::ID(id.value()));
	ASSERT_MSG(it != objects.end(), "Unknown debug object %d", id.value());
	auto ptr = debug::cast<T>(it->second.get());
	ASSERT_MSG(ptr, "Debug object %d is not of the correct type. Got: %d, want: %d",
	           id.value(), int(it->second->kind), int(T::KIND));
	return ptr;
}

template<typename Key>
void SpirvShader::Impl::Debugger::exposeVariable(
    const SpirvShader *shader,
    const Key &key,
    const debug::Scope *scope,
    const debug::Type *type,
    Object::ID id,
    EmitState *state) const
{
	auto dbgState = state->routine->dbgState;
	auto hover = Group::hovers(dbgState, scope).group<Key>(key);
	for(int lane = 0; lane < SIMD::Width; lane++)
	{
		exposeVariable(shader, Group::localsLane(dbgState, scope, lane), lane, key, type, id, state);
		exposeVariable(shader, hover, lane, laneNames[lane], type, id, state);
	}
}

template<typename Key>
void SpirvShader::Impl::Debugger::exposeVariable(
    const SpirvShader *shader,
    const Group &group,
    int l,
    const Key &key,
    const debug::Type *type,
    Object::ID id,
    EmitState *state,
    int wordOffset /* = 0 */) const
{
	if(type != nullptr)
	{
		if(auto ty = debug::cast<debug::BasicType>(type))
		{
			auto &obj = shader->getObject(id);
			SIMD::Int val;
			switch(obj.kind)
			{
				case Object::Kind::InterfaceVariable:
				case Object::Kind::Pointer:
				{
					auto ptr = shader->GetPointerToData(id, 0, state) + sizeof(uint32_t) * wordOffset;
					auto &ptrTy = shader->getType(obj.type);
					if(IsStorageInterleavedByLane(ptrTy.storageClass))
					{
						ptr = InterleaveByLane(ptr);
					}
					auto addr = &ptr.base[Extract(ptr.offsets(), l)];
					switch(ty->encoding)
					{
						case OpenCLDebugInfo100Address:
							// TODO: This function takes a SIMD vector, and pointers cannot
							// be held in them.
							break;
						case OpenCLDebugInfo100Boolean:
							group.putRef<Key, bool>(key, addr);
							break;
						case OpenCLDebugInfo100Float:
							group.putRef<Key, float>(key, addr);
							break;
						case OpenCLDebugInfo100Signed:
							group.putRef<Key, int>(key, addr);
							break;
						case OpenCLDebugInfo100SignedChar:
							group.putRef<Key, int8_t>(key, addr);
							break;
						case OpenCLDebugInfo100Unsigned:
							group.putRef<Key, unsigned int>(key, addr);
							break;
						case OpenCLDebugInfo100UnsignedChar:
							group.putRef<Key, uint8_t>(key, addr);
							break;
						default:
							break;
					}
				}
				break;
				case Object::Kind::Constant:
				case Object::Kind::Intermediate:
				{
					auto val = GenericValue(shader, state, id).Int(wordOffset);

					switch(ty->encoding)
					{
						case OpenCLDebugInfo100Address:
							// TODO: This function takes a SIMD vector, and pointers cannot
							// be held in them.
							break;
						case OpenCLDebugInfo100Boolean:
							group.put<Key, bool>(key, Extract(val, l) != 0);
							break;
						case OpenCLDebugInfo100Float:
							group.put<Key, float>(key, Extract(As<SIMD::Float>(val), l));
							break;
						case OpenCLDebugInfo100Signed:
							group.put<Key, int>(key, Extract(val, l));
							break;
						case OpenCLDebugInfo100SignedChar:
							group.put<Key, int8_t>(key, SByte(Extract(val, l)));
							break;
						case OpenCLDebugInfo100Unsigned:
							group.put<Key, unsigned int>(key, Extract(val, l));
							break;
						case OpenCLDebugInfo100UnsignedChar:
							group.put<Key, uint8_t>(key, Byte(Extract(val, l)));
							break;
						default:
							break;
					}
				}
				break;
				default:
					break;
			}
			return;
		}
		else if(auto ty = debug::cast<debug::VectorType>(type))
		{
			auto elWords = 1;  // Currently vector elements must only be basic types, 32-bit wide
			auto elTy = ty->base;
			auto vecGroup = group.group<Key>(key);
			switch(ty->components)
			{
				case 1:
					exposeVariable(shader, vecGroup, l, "x", elTy, id, state, wordOffset + 0 * elWords);
					break;
				case 2:
					exposeVariable(shader, vecGroup, l, "x", elTy, id, state, wordOffset + 0 * elWords);
					exposeVariable(shader, vecGroup, l, "y", elTy, id, state, wordOffset + 1 * elWords);
					break;
				case 3:
					exposeVariable(shader, vecGroup, l, "x", elTy, id, state, wordOffset + 0 * elWords);
					exposeVariable(shader, vecGroup, l, "y", elTy, id, state, wordOffset + 1 * elWords);
					exposeVariable(shader, vecGroup, l, "z", elTy, id, state, wordOffset + 2 * elWords);
					break;
				case 4:
					exposeVariable(shader, vecGroup, l, "x", elTy, id, state, wordOffset + 0 * elWords);
					exposeVariable(shader, vecGroup, l, "y", elTy, id, state, wordOffset + 1 * elWords);
					exposeVariable(shader, vecGroup, l, "z", elTy, id, state, wordOffset + 2 * elWords);
					exposeVariable(shader, vecGroup, l, "w", elTy, id, state, wordOffset + 3 * elWords);
					break;
				default:
					for(uint32_t i = 0; i < ty->components; i++)
					{
						exposeVariable(shader, vecGroup, l, std::to_string(i).c_str(), elTy, id, state, wordOffset + i * elWords);
					}
					break;
			}
			return;
		}
		else if(auto ty = debug::cast<debug::CompositeType>(type))
		{
			auto objectGroup = group.group<Key>(key);

			for(auto member : ty->members)
			{
				exposeVariable(shader, objectGroup, l, member->name.c_str(), member->type, id, state, member->offset / 32);
			}

			return;
		}
	}

	// No debug type information. Derive from SPIR-V.
	GenericValue val(shader, state, id);
	switch(shader->getType(val.type).opcode())
	{
		case spv::OpTypeInt:
		{
			group.put<Key, int>(key, Extract(val.Int(0), l));
		}
		break;
		case spv::OpTypeFloat:
		{
			group.put<Key, float>(key, Extract(val.Float(0), l));
		}
		break;
		case spv::OpTypeVector:
		{
			auto count = shader->getType(val.type).definition.word(3);
			switch(count)
			{
				case 1:
					group.put<Key, float>(key, Extract(val.Float(0), l));
					break;
				case 2:
					group.put<Key, float>(key, Extract(val.Float(0), l), Extract(val.Float(1), l));
					break;
				case 3:
					group.put<Key, float>(key, Extract(val.Float(0), l), Extract(val.Float(1), l), Extract(val.Float(2), l));
					break;
				case 4:
					group.put<Key, float>(key, Extract(val.Float(0), l), Extract(val.Float(1), l), Extract(val.Float(2), l), Extract(val.Float(3), l));
					break;
				default:
				{
					auto vec = group.group<Key>(key);
					for(uint32_t i = 0; i < count; i++)
					{
						vec.template put<int, float>(i, Extract(val.Float(i), l));
					}
				}
				break;
			}
		}
		break;
		case spv::OpTypePointer:
		{
			auto objectTy = shader->getType(shader->getObject(id).type);
			bool interleavedByLane = IsStorageInterleavedByLane(objectTy.storageClass);
			auto ptr = state->getPointer(id);
			auto ptrGroup = group.group<Key>(key);
			shader->VisitMemoryObject(id, [&](const MemoryElement &el) {
				auto p = ptr + el.offset;
				if(interleavedByLane) { p = InterleaveByLane(p); }  // TODO: Interleave once, then add offset?
				auto simd = p.Load<SIMD::Float>(sw::OutOfBoundsBehavior::Nullify, state->activeLaneMask());
				ptrGroup.template put<int, float>(el.index, Extract(simd, l));
			});
		}
		break;
		default:
			break;
	}
}

////////////////////////////////////////////////////////////////////////////////
// sw::SpirvShader
////////////////////////////////////////////////////////////////////////////////
void SpirvShader::dbgInit(const std::shared_ptr<vk::dbg::Context> &dbgctx)
{
	impl.debugger = new Impl::Debugger();
	impl.debugger->ctx = dbgctx;
}

void SpirvShader::dbgTerm()
{
	if(impl.debugger)
	{
		delete impl.debugger;
	}
}

void SpirvShader::dbgCreateFile()
{
	auto dbg = impl.debugger;
	if(!dbg) { return; }

	int currentLine = 1;
	std::string source;
	for(auto insn : *this)
	{
		auto instruction = spvtools::spvInstructionBinaryToText(
		                       SPV_ENV_VULKAN_1_1,
		                       insn.wordPointer(0),
		                       insn.wordCount(),
		                       insns.data(),
		                       insns.size(),
		                       SPV_BINARY_TO_TEXT_OPTION_NO_HEADER) +
		                   "\n";
		dbg->spirvLineMappings[insn.wordPointer(0)] = currentLine;
		currentLine += std::count(instruction.begin(), instruction.end(), '\n');
		source += instruction;
	}
	std::string name;
	switch(executionModel)
	{
		case spv::ExecutionModelVertex: name = "VertexShader"; break;
		case spv::ExecutionModelFragment: name = "FragmentShader"; break;
		case spv::ExecutionModelGLCompute: name = "ComputeShader"; break;
		default: name = "SPIR-V Shader"; break;
	}
	static std::atomic<int> id = { 0 };
	name += std::to_string(id++) + ".spvasm";
	dbg->spirvFile = dbg->ctx->lock().createVirtualFile(name.c_str(), source.c_str());
}

void SpirvShader::dbgBeginEmit(EmitState *state) const
{
	auto dbg = impl.debugger;
	if(!dbg) { return; }

	using Group = Impl::Debugger::Group;

	auto routine = state->routine;

	auto type = "SPIR-V";
	switch(executionModel)
	{
		case spv::ExecutionModelVertex: type = "VertexShader"; break;
		case spv::ExecutionModelFragment: type = "FragmentShader"; break;
		case spv::ExecutionModelGLCompute: type = "ComputeShader"; break;
		default: type = "SPIR-V Shader"; break;
	}
	auto dbgState = rr::Call(&Impl::Debugger::State::create, dbg, type);

	routine->dbgState = dbgState;

	SetActiveLaneMask(state->activeLaneMask(), state);

	for(int i = 0; i < SIMD::Width; i++)
	{
		auto builtins = Group::builtinsLane(dbgState, i);
		builtins.put<const char *, int>("subgroupSize", routine->invocationsPerSubgroup);

		switch(executionModel)
		{
			case spv::ExecutionModelGLCompute:
				builtins.putVec3<const char *, int>("numWorkgroups", routine->numWorkgroups);
				builtins.putVec3<const char *, int>("workgroupID", routine->workgroupID);
				builtins.putVec3<const char *, int>("workgroupSize", routine->workgroupSize);
				builtins.put<const char *, int>("numSubgroups", routine->subgroupsPerWorkgroup);
				builtins.put<const char *, int>("subgroupIndex", routine->subgroupIndex);

				builtins.put<const char *, int>("globalInvocationId",
				                                rr::Extract(routine->globalInvocationID[0], i),
				                                rr::Extract(routine->globalInvocationID[1], i),
				                                rr::Extract(routine->globalInvocationID[2], i));
				builtins.put<const char *, int>("localInvocationId",
				                                rr::Extract(routine->localInvocationID[0], i),
				                                rr::Extract(routine->localInvocationID[1], i),
				                                rr::Extract(routine->localInvocationID[2], i));
				builtins.put<const char *, int>("localInvocationIndex", rr::Extract(routine->localInvocationIndex, i));
				break;

			case spv::ExecutionModelFragment:
				builtins.put<const char *, int>("viewIndex", routine->viewID);
				builtins.put<const char *, float>("fragCoord",
				                                  rr::Extract(routine->fragCoord[0], i),
				                                  rr::Extract(routine->fragCoord[1], i),
				                                  rr::Extract(routine->fragCoord[2], i),
				                                  rr::Extract(routine->fragCoord[3], i));
				builtins.put<const char *, float>("pointCoord",
				                                  rr::Extract(routine->pointCoord[0], i),
				                                  rr::Extract(routine->pointCoord[1], i));
				builtins.put<const char *, int>("windowSpacePosition",
				                                rr::Extract(routine->windowSpacePosition[0], i),
				                                rr::Extract(routine->windowSpacePosition[1], i));
				builtins.put<const char *, int>("helperInvocation", rr::Extract(routine->helperInvocation, i));
				break;

			case spv::ExecutionModelVertex:
				builtins.put<const char *, int>("viewIndex", routine->viewID);
				builtins.put<const char *, int>("instanceIndex", routine->instanceID);
				builtins.put<const char *, int>("vertexIndex",
				                                rr::Extract(routine->vertexIndex, i));
				break;

			default:
				break;
		}
	}
}

void SpirvShader::dbgEndEmit(EmitState *state) const
{
	auto dbg = impl.debugger;
	if(!dbg) { return; }

	rr::Call(&Impl::Debugger::State::destroy, state->routine->dbgState);
}

void SpirvShader::dbgBeginEmitInstruction(InsnIterator insn, EmitState *state) const
{
#	if PRINT_EACH_PROCESSED_INSTRUCTION
	auto instruction = spvtools::spvInstructionBinaryToText(
	    SPV_ENV_VULKAN_1_1,
	    insn.wordPointer(0),
	    insn.wordCount(),
	    insns.data(),
	    insns.size(),
	    SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
	printf("%s\n", instruction.c_str());
#	endif  // PRINT_EACH_PROCESSED_INSTRUCTION

	if(extensionsImported.count(Extension::OpenCLDebugInfo100) == 0)
	{
		// We're emitting debugger logic for SPIR-V.
		// Only single line step over statement instructions.
		if(IsStatement(insn.opcode()))
		{
			auto dbg = impl.debugger;
			if(!dbg) { return; }

			auto line = dbg->spirvLineMappings.at(insn.wordPointer(0));
			auto column = 0;
			rr::Call(&Impl::Debugger::State::update, state->routine->dbgState, dbg->spirvFile->id, line, column);
		}
	}
}

void SpirvShader::dbgEndEmitInstruction(InsnIterator insn, EmitState *state) const
{
	auto dbg = impl.debugger;
	if(!dbg) { return; }

	auto resIt = dbg->results.find(insn.wordPointer(0));
	if(resIt != dbg->results.end())
	{
		auto id = resIt->second;
		dbgExposeIntermediate(id, state);
	}
}

void SpirvShader::dbgExposeIntermediate(Object::ID id, EmitState *state) const
{
	auto dbg = impl.debugger;
	if(!dbg) { return; }

	dbg->exposeVariable(this, id, &debug::Scope::Root, nullptr, id, state);
}

void SpirvShader::dbgUpdateActiveLaneMask(RValue<SIMD::Int> mask, EmitState *state) const
{
	auto dbg = impl.debugger;
	if(!dbg) { return; }

	for(int lane = 0; lane < SIMD::Width; lane++)
	{
		rr::Call(&Impl::Debugger::State::updateActiveLaneMask, state->routine->dbgState, lane, rr::Extract(mask, lane) != 0);
	}
}

void SpirvShader::dbgDeclareResult(const InsnIterator &insn, Object::ID resultId) const
{
	auto dbg = impl.debugger;
	if(!dbg) { return; }

	dbg->results.emplace(insn.wordPointer(0), resultId);
}

SpirvShader::EmitResult SpirvShader::EmitLine(InsnIterator insn, EmitState *state) const
{
	if(auto dbg = impl.debugger)
	{
		auto path = getString(insn.word(1));
		auto line = insn.word(2);
		auto column = insn.word(3);
		dbg->setPosition(state, path, line, column);
	}
	return EmitResult::Continue;
}

void SpirvShader::DefineOpenCLDebugInfo100(const InsnIterator &insn)
{
	auto dbg = impl.debugger;
	if(!dbg) { return; }

	dbg->process(this, insn, nullptr, Impl::Debugger::Pass::Define);
}

SpirvShader::EmitResult SpirvShader::EmitOpenCLDebugInfo100(InsnIterator insn, EmitState *state) const
{
	if(auto dbg = impl.debugger)
	{
		dbg->process(this, insn, state, Impl::Debugger::Pass::Emit);
	}
	return EmitResult::Continue;
}

}  // namespace sw

#else  // ENABLE_VK_DEBUGGER

// Stub implementations of the dbgXXX functions.
namespace sw {

void SpirvShader::dbgInit(const std::shared_ptr<vk::dbg::Context> &dbgctx) {}
void SpirvShader::dbgTerm() {}
void SpirvShader::dbgCreateFile() {}
void SpirvShader::dbgBeginEmit(EmitState *state) const {}
void SpirvShader::dbgEndEmit(EmitState *state) const {}
void SpirvShader::dbgBeginEmitInstruction(InsnIterator insn, EmitState *state) const {}
void SpirvShader::dbgEndEmitInstruction(InsnIterator insn, EmitState *state) const {}
void SpirvShader::dbgExposeIntermediate(Object::ID id, EmitState *state) const {}
void SpirvShader::dbgUpdateActiveLaneMask(RValue<SIMD::Int> mask, EmitState *state) const {}
void SpirvShader::dbgDeclareResult(const InsnIterator &insn, Object::ID resultId) const {}

void SpirvShader::DefineOpenCLDebugInfo100(const InsnIterator &insn) {}

SpirvShader::EmitResult SpirvShader::EmitOpenCLDebugInfo100(InsnIterator insn, EmitState *state) const
{
	return EmitResult::Continue;
}

SpirvShader::EmitResult SpirvShader::EmitLine(InsnIterator insn, EmitState *state) const
{
	return EmitResult::Continue;
}

}  // namespace sw

#endif  // ENABLE_VK_DEBUGGER
