1 // Copyright 2019 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "SpirvShader.hpp"
16 
17 #include "System/Types.hpp"
18 
19 // If enabled, each instruction will be printed before defining.
20 #define PRINT_EACH_DEFINED_DBG_INSTRUCTION 0
21 // If enabled, each instruction will be printed before emitting.
22 #define PRINT_EACH_EMITTED_INSTRUCTION 0
23 // If enabled, each instruction will be printed before executing.
24 #define PRINT_EACH_EXECUTED_INSTRUCTION 0
25 // If enabled, debugger variables will contain debug information (addresses,
26 // byte offset, etc).
27 #define DEBUG_ANNOTATE_VARIABLE_KEYS 0
28 
29 #ifdef ENABLE_VK_DEBUGGER
30 
31 #	include "Vulkan/Debug/Context.hpp"
32 #	include "Vulkan/Debug/File.hpp"
33 #	include "Vulkan/Debug/Thread.hpp"
34 #	include "Vulkan/Debug/Variable.hpp"
35 #	include "Vulkan/Debug/EventListener.hpp"
36 
37 #	include "spirv/unified1/OpenCLDebugInfo100.h"
38 #	include "spirv-tools/libspirv.h"
39 
40 #	include <algorithm>
41 #	include <queue>
42 
43 ////////////////////////////////////////////////////////////////////////////////
44 // namespace sw::SIMD
45 // Adds sw::SIMD::PerLane<> and typedefs for C++ versions of the Reactor SIMD
46 // types (sw::SIMD::Int, etc)
47 ////////////////////////////////////////////////////////////////////////////////
48 namespace sw {
49 namespace SIMD {
50 
51 // PerLane is a SIMD vector that holds N vectors of width SIMD::Width.
52 // PerLane operator[] returns the elements of a single lane (a transpose of the
53 // storage arrays).
54 template<typename T, int N = 1>
55 struct PerLane
56 {
operator []sw::SIMD::PerLane57 	sw::vec<T, N> operator[](int lane) const
58 	{
59 		sw::vec<T, N> out;
60 		for(int i = 0; i < N; i++)
61 		{
62 			out[i] = elements[i][lane];
63 		}
64 		return out;
65 	}
66 	std::array<sw::vec<T, Width>, N> elements;
67 };
68 
69 template<typename T>
70 struct PerLane<T, 1>
71 {
operator []sw::SIMD::PerLane72 	const T &operator[](int lane) const { return data[lane]; }
73 	std::array<T, Width> data;
74 };
75 
76 using uint_t = PerLane<unsigned int>;
77 using uint2 = PerLane<unsigned int, 2>;
78 using uint3 = PerLane<unsigned int, 3>;
79 using uint4 = PerLane<unsigned int, 4>;
80 
81 using int_t = PerLane<int>;
82 using int2 = PerLane<int, 2>;
83 using int3 = PerLane<int, 3>;
84 using int4 = PerLane<int, 4>;
85 
86 using float_t = PerLane<float>;
87 using vec2 = PerLane<float, 2>;
88 using vec3 = PerLane<float, 3>;
89 using vec4 = PerLane<float, 4>;
90 
91 }  // namespace SIMD
92 }  // namespace sw
93 
94 ////////////////////////////////////////////////////////////////////////////////
95 // namespace ::(anonymous)
96 // Utility functions
97 ////////////////////////////////////////////////////////////////////////////////
98 namespace {
99 
100 // vecElementName() returns the element name for the i'th vector element of
101 // size n.
102 // Vectors of size 4 or less use a [x,y,z,w] element naming scheme.
103 // Larger vectors use a number index naming scheme.
vecElementName(int i,int n)104 std::string vecElementName(int i, int n)
105 {
106 	return (n > 4) ? std::to_string(i) : &"x\0y\0z\0w\0"[i * 2];
107 }
108 
109 // laneName() returns a string describing values for the lane i.
laneName(int i)110 std::string laneName(int i)
111 {
112 	return "Lane " + std::to_string(i);
113 }
114 
115 // isEntryBreakpointForShaderType() returns true if name is equal to the
116 // special entry breakpoint name for the given shader type.
117 // This allows the IDE to request all shaders of the given type to break on
118 // entry.
isEntryBreakpointForShaderType(spv::ExecutionModel type,const std::string & name)119 bool isEntryBreakpointForShaderType(spv::ExecutionModel type, const std::string &name)
120 {
121 	switch(type)
122 	{
123 		case spv::ExecutionModelGLCompute: return name == "ComputeShader";
124 		case spv::ExecutionModelFragment: return name == "FragmentShader";
125 		case spv::ExecutionModelVertex: return name == "VertexShader";
126 		default: return false;
127 	}
128 }
129 
130 // makeDbgValue() returns a vk::dbg::Value that contains a copy of val.
131 template<typename T>
makeDbgValue(const T & val)132 std::shared_ptr<vk::dbg::Value> makeDbgValue(const T &val)
133 {
134 	return vk::dbg::make_constant(val);
135 }
136 
137 // makeDbgValue() returns a vk::dbg::Value that contains a copy of vec.
138 template<typename T, int N>
makeDbgValue(const sw::vec<T,N> & vec)139 std::shared_ptr<vk::dbg::Value> makeDbgValue(const sw::vec<T, N> &vec)
140 {
141 	return vk::dbg::Struct::create("vec" + std::to_string(N), [&](auto &vc) {
142 		for(int i = 0; i < N; i++)
143 		{
144 			vc->put(vecElementName(i, N), makeDbgValue<T>(vec[i]));
145 		}
146 	});
147 }
148 
149 // store() emits a store instruction to copy val into ptr.
150 template<typename T>
store(const rr::RValue<rr::Pointer<rr::Byte>> & ptr,const rr::RValue<T> & val)151 void store(const rr::RValue<rr::Pointer<rr::Byte>> &ptr, const rr::RValue<T> &val)
152 {
153 	*rr::Pointer<T>(ptr) = val;
154 }
155 
156 // store() emits a store instruction to copy val into ptr.
157 template<typename T>
store(const rr::RValue<rr::Pointer<rr::Byte>> & ptr,const T & val)158 void store(const rr::RValue<rr::Pointer<rr::Byte>> &ptr, const T &val)
159 {
160 	*rr::Pointer<T>(ptr) = val;
161 }
162 
163 // clang-format off
164 template<typename T> struct ReactorTypeSize {};
165 template<> struct ReactorTypeSize<rr::Int>    { static constexpr const int value = 4; };
166 template<> struct ReactorTypeSize<rr::Float>  { static constexpr const int value = 4; };
167 template<> struct ReactorTypeSize<rr::Int4>   { static constexpr const int value = 16; };
168 template<> struct ReactorTypeSize<rr::Float4> { static constexpr const int value = 16; };
169 // clang-format on
170 
171 // store() emits a store instruction to copy val into ptr.
172 template<typename T, std::size_t N>
store(const rr::RValue<rr::Pointer<rr::Byte>> & ptr,const std::array<T,N> & val)173 void store(const rr::RValue<rr::Pointer<rr::Byte>> &ptr, const std::array<T, N> &val)
174 {
175 	for(std::size_t i = 0; i < N; i++)
176 	{
177 		store<T>(ptr + i * ReactorTypeSize<T>::value, val[i]);
178 	}
179 }
180 
181 // ArgTy<F>::type resolves to the single argument type of the function F.
182 template<typename F>
183 struct ArgTy
184 {
185 	using type = typename ArgTy<decltype(&F::operator())>::type;
186 };
187 
188 // ArgTy<F>::type resolves to the single argument type of the template method.
189 template<typename R, typename C, typename Arg>
190 struct ArgTy<R (C::*)(Arg) const>
191 {
192 	using type = typename std::decay<Arg>::type;
193 };
194 
195 // ArgTyT resolves to the single argument type of the template function or
196 // method F.
197 template<typename F>
198 using ArgTyT = typename ArgTy<F>::type;
199 
200 // getOrCreate() searchs the map for the given key. If the map contains an entry
201 // with the given key, then the value is returned. Otherwise, create() is called
202 // and the returned value is placed into the map with the given key, and this
203 // value is returned.
204 // create is a function with the signature:
205 //   V()
206 template<typename K, typename V, typename CREATE, typename HASH>
207 V getOrCreate(std::unordered_map<K, V, HASH> &map, const K &key, CREATE &&create)
208 {
209 	auto it = map.find(key);
210 	if(it != map.end())
211 	{
212 		return it->second;
213 	}
214 	auto val = create();
215 	map.emplace(key, val);
216 	return val;
217 }
218 
219 // HoversFromLocals is an implementation of vk::dbg::Variables that is used to
220 // provide a scope's 'hover' variables - those that appear when you place the
221 // cursor over a variable in an IDE.
222 // Unlike the top-level SIMD lane grouping of variables in Frame::locals,
223 // Frame::hovers displays each variable as a value per SIMD lane.
224 // Instead maintaining another collection of variables per scope,
225 // HoversFromLocals dynamically builds the hover information from the locals.
226 class HoversFromLocals : public vk::dbg::Variables
227 {
228 public:
HoversFromLocals(const std::shared_ptr<vk::dbg::Variables> & locals)229 	HoversFromLocals(const std::shared_ptr<vk::dbg::Variables> &locals)
230 	    : locals(locals)
231 	{}
232 
foreach(size_t startIndex,size_t count,const ForeachCallback & cb)233 	void foreach(size_t startIndex, size_t count, const ForeachCallback &cb) override
234 	{
235 		// No op - hovers are only searched, never iterated.
236 	}
237 
get(const std::string & name)238 	std::shared_ptr<vk::dbg::Value> get(const std::string &name) override
239 	{
240 		// Is the hover variable a SIMD-common variable? If so, just return
241 		// that.
242 		if(auto val = locals->get(name))
243 		{
244 			return val;
245 		}
246 
247 		// Search each of the lanes for the named variable.
248 		// Collect them all up, and return that in a new Struct value.
249 		bool found = false;
250 		auto str = vk::dbg::Struct::create("", [&](auto &vc) {
251 			for(int lane = 0; lane < sw::SIMD::Width; lane++)
252 			{
253 				auto laneN = laneName(lane);
254 				if(auto laneV = locals->get(laneN))
255 				{
256 					if(auto children = laneV->children())
257 					{
258 						if(auto val = children->get(name))
259 						{
260 							vc->put(laneN, val);
261 							found = true;
262 						}
263 					}
264 				}
265 			}
266 		});
267 
268 		if(found)
269 		{
270 			// The value returned will be returned to the debug client by
271 			// identifier. As the value is a Struct, the server will include
272 			// a handle to the Variables, which needs to be kept alive so the
273 			// client can send a request for its members.
274 			// lastFind keeps any nested Variables alive long enough for them to
275 			// be requested.
276 			lastFind = str;
277 			return str;
278 		}
279 
280 		return nullptr;
281 	}
282 
283 private:
284 	std::shared_ptr<vk::dbg::Variables> locals;
285 	std::shared_ptr<vk::dbg::Struct> lastFind;
286 };
287 
288 }  // anonymous namespace
289 
290 namespace spvtools {
291 
292 // Function implemented in third_party/SPIRV-Tools/source/disassemble.cpp
293 // but with no public header.
294 // This is a C++ function, so the name is mangled, and signature changes will
295 // result in a linker error instead of runtime signature mismatches.
296 extern std::string spvInstructionBinaryToText(const spv_target_env env,
297                                               const uint32_t *inst_binary,
298                                               const size_t inst_word_count,
299                                               const uint32_t *binary,
300                                               const size_t word_count,
301                                               const uint32_t options);
302 
303 }  // namespace spvtools
304 
305 ////////////////////////////////////////////////////////////////////////////////
306 // namespace ::(anonymous)::debug
307 // OpenCL.Debug.100 data structures
308 ////////////////////////////////////////////////////////////////////////////////
309 namespace {
310 namespace debug {
311 
312 struct Declare;
313 struct LocalVariable;
314 struct Member;
315 struct Value;
316 
317 // Object is the common base class for all the OpenCL.Debug.100 data structures.
318 struct Object
319 {
320 	enum class Kind
321 	{
322 		Object,
323 		Declare,
324 		Expression,
325 		Function,
326 		InlinedAt,
327 		GlobalVariable,
328 		LocalVariable,
329 		Member,
330 		Operation,
331 		Source,
332 		SourceScope,
333 		Value,
334 		TemplateParameter,
335 
336 		// Scopes
337 		CompilationUnit,
338 		LexicalBlock,
339 
340 		// Types
341 		BasicType,
342 		ArrayType,
343 		VectorType,
344 		FunctionType,
345 		CompositeType,
346 		TemplateType,
347 	};
348 
349 	using ID = sw::SpirvID<Object>;
350 	static constexpr auto KIND = Kind::Object;
Object__anon5bdf0e0e0411::debug::Object351 	inline Object(Kind kind)
352 	    : kind(kind)
353 	{
354 		(void)KIND;  // Used in debug builds. Avoid unused variable warnings in NDEBUG builds.
355 	}
356 	const Kind kind;
357 
358 	// kindof() returns true iff kind is of this type, or any type deriving from
359 	// this type.
kindof__anon5bdf0e0e0411::debug::Object360 	static constexpr bool kindof(Object::Kind kind) { return true; }
361 
362 	virtual ~Object() = default;
363 };
364 
365 // cstr() returns the c-string name of the given Object::Kind.
cstr(Object::Kind k)366 constexpr const char *cstr(Object::Kind k)
367 {
368 	switch(k)
369 	{
370 		case Object::Kind::Object: return "Object";
371 		case Object::Kind::Declare: return "Declare";
372 		case Object::Kind::Expression: return "Expression";
373 		case Object::Kind::Function: return "Function";
374 		case Object::Kind::InlinedAt: return "InlinedAt";
375 		case Object::Kind::GlobalVariable: return "GlobalVariable";
376 		case Object::Kind::LocalVariable: return "LocalVariable";
377 		case Object::Kind::Member: return "Member";
378 		case Object::Kind::Operation: return "Operation";
379 		case Object::Kind::Source: return "Source";
380 		case Object::Kind::SourceScope: return "SourceScope";
381 		case Object::Kind::Value: return "Value";
382 		case Object::Kind::TemplateParameter: return "TemplateParameter";
383 		case Object::Kind::CompilationUnit: return "CompilationUnit";
384 		case Object::Kind::LexicalBlock: return "LexicalBlock";
385 		case Object::Kind::BasicType: return "BasicType";
386 		case Object::Kind::ArrayType: return "ArrayType";
387 		case Object::Kind::VectorType: return "VectorType";
388 		case Object::Kind::FunctionType: return "FunctionType";
389 		case Object::Kind::CompositeType: return "CompositeType";
390 		case Object::Kind::TemplateType: return "TemplateType";
391 	}
392 	return "<unknown>";
393 }
394 
395 // ObjectImpl is a helper template struct which simplifies deriving from Object.
396 // ObjectImpl passes down the KIND to the Object constructor, and implements
397 // kindof().
398 template<typename TYPE, typename BASE, Object::Kind KIND>
399 struct ObjectImpl : public BASE
400 {
401 	using ID = sw::SpirvID<TYPE>;
402 	static constexpr auto Kind = KIND;
403 
ObjectImpl__anon5bdf0e0e0411::debug::ObjectImpl404 	ObjectImpl()
405 	    : BASE(Kind)
406 	{}
407 	static_assert(BASE::kindof(KIND), "BASE::kindof() returned false");
408 
409 	// kindof() returns true iff kind is of this type, or any type deriving from
410 	// this type.
kindof__anon5bdf0e0e0411::debug::ObjectImpl411 	static constexpr bool kindof(Object::Kind kind) { return kind == Kind; }
412 };
413 
414 // cast() casts the debug type pointer obj to TO.
415 // If obj is null or not of the type TO, then nullptr is returned.
416 template<typename TO, typename FROM>
417 TO *cast(FROM *obj)
418 {
419 	if(obj == nullptr) { return nullptr; }  // None
420 	return (TO::kindof(obj->kind)) ? static_cast<TO *>(obj) : nullptr;
421 }
422 
423 // cast() casts the debug type pointer obj to TO.
424 // If obj is null or not of the type TO, then nullptr is returned.
425 template<typename TO, typename FROM>
cast(const FROM * obj)426 const TO *cast(const FROM *obj)
427 {
428 	if(obj == nullptr) { return nullptr; }  // None
429 	return (TO::kindof(obj->kind)) ? static_cast<const TO *>(obj) : nullptr;
430 }
431 
432 // Scope is the base class for all OpenCL.DebugInfo.100 scope objects.
433 struct Scope : public Object
434 {
435 	using ID = sw::SpirvID<Scope>;
Scope__anon5bdf0e0e0411::debug::Scope436 	inline Scope(Kind kind)
437 	    : Object(kind)
438 	{}
439 
440 	// kindof() returns true iff kind is of this type, or any type deriving from
441 	// this type.
kindof__anon5bdf0e0e0411::debug::Scope442 	static constexpr bool kindof(Kind kind)
443 	{
444 		return kind == Kind::CompilationUnit ||
445 		       kind == Kind::Function ||
446 		       kind == Kind::LexicalBlock;
447 	}
448 
449 	struct Source *source = nullptr;
450 	Scope *parent = nullptr;
451 };
452 
453 // Type is the base class for all OpenCL.DebugInfo.100 type objects.
454 struct Type : public Object
455 {
456 	using ID = sw::SpirvID<Type>;
457 
458 	struct Member
459 	{
460 		Type *type;
461 		std::string name;
462 	};
463 
Type__anon5bdf0e0e0411::debug::Type464 	inline Type(Kind kind)
465 	    : Object(kind)
466 	{}
467 
468 	// kindof() returns true iff kind is of this type, or any type deriving from
469 	// this type.
kindof__anon5bdf0e0e0411::debug::Type470 	static constexpr bool kindof(Kind kind)
471 	{
472 		return kind == Kind::BasicType ||
473 		       kind == Kind::ArrayType ||
474 		       kind == Kind::VectorType ||
475 		       kind == Kind::FunctionType ||
476 		       kind == Kind::CompositeType ||
477 		       kind == Kind::TemplateType;
478 	}
479 
480 	// name() returns the type name.
481 	virtual std::string name() const = 0;
482 
483 	// sizeInBytes() returns the number of bytes of the given debug type.
484 	virtual uint32_t sizeInBytes() const = 0;
485 
486 	// value() returns a shared pointer to a vk::dbg::Value that views the data
487 	// at ptr of this type.
488 	virtual std::shared_ptr<vk::dbg::Value> value(void *ptr, bool interleaved) const = 0;
489 
490 	// numMembers() returns the number of members for the given type.
491 	virtual size_t numMembers() const = 0;
492 
493 	// getMember() returns the member by index.
494 	virtual Member getMember(size_t) const = 0;
495 
496 	// undefined() returns a shared pointer to a vk::dbg::Value that represents
497 	// an undefined value of this type.
undefined__anon5bdf0e0e0411::debug::Type498 	std::shared_ptr<vk::dbg::Value> undefined() const
499 	{
500 		struct Undef : public vk::dbg::Value
501 		{
502 			Undef(const std::string &ty)
503 			    : ty(ty)
504 			{}
505 			const std::string ty;
506 			std::string type() override { return ty; }
507 			std::string get(const vk::dbg::FormatFlags &) override { return "<undefined>"; }
508 		};
509 		return std::make_shared<Undef>(name());
510 	}
511 };
512 
513 // CompilationUnit represents the OpenCL.DebugInfo.100 DebugCompilationUnit
514 // instruction.
515 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugCompilationUnit
516 struct CompilationUnit : ObjectImpl<CompilationUnit, Scope, Object::Kind::CompilationUnit>
517 {
518 };
519 
520 // Source represents the OpenCL.DebugInfo.100 DebugSource instruction.
521 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugSource
522 struct Source : ObjectImpl<Source, Object, Object::Kind::Source>
523 {
524 	spv::SourceLanguage language;
525 	uint32_t version = 0;
526 	std::string file;
527 	std::string source;
528 
529 	std::shared_ptr<vk::dbg::File> dbgFile;
530 };
531 
532 // BasicType represents the OpenCL.DebugInfo.100 DebugBasicType instruction.
533 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugBasicType
534 struct BasicType : ObjectImpl<BasicType, Type, Object::Kind::BasicType>
535 {
536 	std::string name_;
537 	uint32_t size = 0;  // in bits.
538 	OpenCLDebugInfo100DebugBaseTypeAttributeEncoding encoding = OpenCLDebugInfo100Unspecified;
539 
name__anon5bdf0e0e0411::debug::BasicType540 	std::string name() const override { return name_; }
sizeInBytes__anon5bdf0e0e0411::debug::BasicType541 	uint32_t sizeInBytes() const override { return size / 8; }
numMembers__anon5bdf0e0e0411::debug::BasicType542 	size_t numMembers() const override { return 0; }
getMember__anon5bdf0e0e0411::debug::BasicType543 	Member getMember(size_t) const override { return {}; }
544 
value__anon5bdf0e0e0411::debug::BasicType545 	std::shared_ptr<vk::dbg::Value> value(void *ptr, bool interleaved) const override
546 	{
547 		switch(encoding)
548 		{
549 			case OpenCLDebugInfo100Address:
550 				// return vk::dbg::make_reference(*static_cast<void **>(ptr));
551 				UNIMPLEMENTED("b/148401179 OpenCLDebugInfo100 OpenCLDebugInfo100Address BasicType");
552 				return nullptr;
553 			case OpenCLDebugInfo100Boolean:
554 				return vk::dbg::make_reference(*static_cast<bool *>(ptr));
555 			case OpenCLDebugInfo100Float:
556 				return vk::dbg::make_reference(*static_cast<float *>(ptr));
557 			case OpenCLDebugInfo100Signed:
558 				return vk::dbg::make_reference(*static_cast<int32_t *>(ptr));
559 			case OpenCLDebugInfo100SignedChar:
560 				return vk::dbg::make_reference(*static_cast<int8_t *>(ptr));
561 			case OpenCLDebugInfo100Unsigned:
562 				return vk::dbg::make_reference(*static_cast<uint32_t *>(ptr));
563 			case OpenCLDebugInfo100UnsignedChar:
564 				return vk::dbg::make_reference(*static_cast<uint8_t *>(ptr));
565 			default:
566 				UNIMPLEMENTED("b/148401179 OpenCLDebugInfo100 encoding %d", int(encoding));
567 				return nullptr;
568 		}
569 	}
570 };
571 
572 // ArrayType represents the OpenCL.DebugInfo.100 DebugTypeArray instruction.
573 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugTypeArray
574 //
575 // Unlike OpenCL.DebugInfo.100's DebugTypeArray, ArrayType is always
576 // single-dimensional. Multi-dimensional arrays are transformed into multiple
577 // nested ArrayTypes. This is done to simplify logic.
578 struct ArrayType : ObjectImpl<ArrayType, Type, Object::Kind::ArrayType>
579 {
580 	Type *base = nullptr;
581 	bool ownsBase = false;  // If true, base is owned by this ArrayType.
582 	uint32_t size;          // In elements
583 
~ArrayType__anon5bdf0e0e0411::debug::ArrayType584 	~ArrayType()
585 	{
586 		if(ownsBase) { delete base; }
587 	}
588 
name__anon5bdf0e0e0411::debug::ArrayType589 	std::string name() const override { return base->name() + "[]"; }
sizeInBytes__anon5bdf0e0e0411::debug::ArrayType590 	uint32_t sizeInBytes() const override { return base->sizeInBytes() * size; }
numMembers__anon5bdf0e0e0411::debug::ArrayType591 	size_t numMembers() const override { return size; }
getMember__anon5bdf0e0e0411::debug::ArrayType592 	Member getMember(size_t i) const override { return { base, std::to_string(i) }; }
593 
value__anon5bdf0e0e0411::debug::ArrayType594 	std::shared_ptr<vk::dbg::Value> value(void *ptr, bool interleaved) const override
595 	{
596 		auto members = std::make_shared<vk::dbg::VariableContainer>();
597 
598 		auto addr = static_cast<uint8_t *>(ptr);
599 		for(size_t i = 0; i < size; i++)
600 		{
601 			auto member = getMember(i);
602 
603 #	if DEBUG_ANNOTATE_VARIABLE_KEYS
604 			key += " (" + std::to_string(addr) + " +" + std::to_string(offset) + ", i: " + std::to_string(i) + ")" + (interleaved ? "I" : "F");
605 #	endif
606 			members->put(member.name, base->value(addr, interleaved));
607 
608 			addr += base->sizeInBytes() * (interleaved ? sw::SIMD::Width : 1);
609 		}
610 		return std::make_shared<vk::dbg::Struct>(name(), members);
611 	}
612 };
613 
614 // VectorType represents the OpenCL.DebugInfo.100 DebugTypeVector instruction.
615 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugTypeVector
616 struct VectorType : ObjectImpl<VectorType, Type, Object::Kind::VectorType>
617 {
618 	Type *base = nullptr;
619 	uint32_t components = 0;
620 
name__anon5bdf0e0e0411::debug::VectorType621 	std::string name() const override { return "vec" + std::to_string(components) + "<" + base->name() + ">"; }
sizeInBytes__anon5bdf0e0e0411::debug::VectorType622 	uint32_t sizeInBytes() const override { return base->sizeInBytes() * components; }
numMembers__anon5bdf0e0e0411::debug::VectorType623 	size_t numMembers() const override { return components; }
getMember__anon5bdf0e0e0411::debug::VectorType624 	Member getMember(size_t i) const override { return { base, vecElementName(i, components) }; }
625 
value__anon5bdf0e0e0411::debug::VectorType626 	std::shared_ptr<vk::dbg::Value> value(void *ptr, bool interleaved) const override
627 	{
628 		const auto elSize = base->sizeInBytes();
629 		auto members = std::make_shared<vk::dbg::VariableContainer>();
630 		for(uint32_t i = 0; i < components; i++)
631 		{
632 			auto offset = elSize * i * (interleaved ? sw::SIMD::Width : 1);
633 			auto elPtr = static_cast<uint8_t *>(ptr) + offset;
634 #	if DEBUG_ANNOTATE_VARIABLE_KEYS
635 			elKey += " (" + std::to_string(elPtr) + " +" + std::to_string(offset) + ")" + (interleaved ? "I" : "F");
636 #	endif
637 			members->put(getMember(i).name, base->value(elPtr, interleaved));
638 		}
639 		return std::make_shared<vk::dbg::Struct>(name(), members);
640 	}
641 };
642 
643 // FunctionType represents the OpenCL.DebugInfo.100 DebugTypeFunction
644 // instruction.
645 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugTypeFunction
646 struct FunctionType : ObjectImpl<FunctionType, Type, Object::Kind::FunctionType>
647 {
648 	uint32_t flags = 0;  // OR'd from OpenCLDebugInfo100DebugInfoFlags
649 	Type *returnTy = nullptr;
650 	std::vector<Type *> paramTys;
651 
name__anon5bdf0e0e0411::debug::FunctionType652 	std::string name() const override { return "function"; }
sizeInBytes__anon5bdf0e0e0411::debug::FunctionType653 	uint32_t sizeInBytes() const override { return 0; }
numMembers__anon5bdf0e0e0411::debug::FunctionType654 	size_t numMembers() const override { return 0; }
getMember__anon5bdf0e0e0411::debug::FunctionType655 	Member getMember(size_t i) const override { return {}; }
value__anon5bdf0e0e0411::debug::FunctionType656 	std::shared_ptr<vk::dbg::Value> value(void *ptr, bool interleaved) const override { return nullptr; }
657 };
658 
659 // Member represents the OpenCL.DebugInfo.100 DebugTypeMember instruction.
660 // Despite the instruction name, this is not a type - rather a member of a type.
661 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugTypeMember
662 struct Member : ObjectImpl<Member, Object, Object::Kind::Member>
663 {
664 	std::string name;
665 	Type *type = nullptr;
666 	Source *source = nullptr;
667 	uint32_t line = 0;
668 	uint32_t column = 0;
669 	struct CompositeType *parent = nullptr;
670 	uint32_t offset = 0;  // in bits
671 	uint32_t size = 0;    // in bits
672 	uint32_t flags = 0;   // OR'd from OpenCLDebugInfo100DebugInfoFlags
673 };
674 
675 // CompositeType represents the OpenCL.DebugInfo.100 DebugTypeComposite
676 // instruction.
677 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugTypeComposite
678 struct CompositeType : ObjectImpl<CompositeType, Type, Object::Kind::CompositeType>
679 {
680 	std::string name_;
681 	OpenCLDebugInfo100DebugCompositeType tag = OpenCLDebugInfo100Class;
682 	Source *source = nullptr;
683 	uint32_t line = 0;
684 	uint32_t column = 0;
685 	Object *parent = nullptr;
686 	std::string linkage;
687 	uint32_t size = 0;   // in bits.
688 	uint32_t flags = 0;  // OR'd from OpenCLDebugInfo100DebugInfoFlags
689 	std::vector<debug::Member *> members_;
690 
name__anon5bdf0e0e0411::debug::CompositeType691 	std::string name() const override { return name_; }
sizeInBytes__anon5bdf0e0e0411::debug::CompositeType692 	uint32_t sizeInBytes() const override { return size / 8; }
numMembers__anon5bdf0e0e0411::debug::CompositeType693 	size_t numMembers() const override { return members_.size(); }
getMember__anon5bdf0e0e0411::debug::CompositeType694 	Member getMember(size_t i) const override { return { members_[i]->type, members_[i]->name }; }
695 
value__anon5bdf0e0e0411::debug::CompositeType696 	std::shared_ptr<vk::dbg::Value> value(void *ptr, bool interleaved) const override
697 	{
698 		auto fields = std::make_shared<vk::dbg::VariableContainer>();
699 		for(auto &member : members_)
700 		{
701 			auto offset = (member->offset / 8) * (interleaved ? sw::SIMD::Width : 1);
702 			auto elPtr = static_cast<uint8_t *>(ptr) + offset;
703 			auto elKey = member->name;
704 #	if DEBUG_ANNOTATE_VARIABLE_KEYS
705 			// elKey += " (" + std::to_string(elPtr) + " +" + std::to_string(offset) + ")" + (interleaved ? "I" : "F");
706 #	endif
707 			fields->put(elKey, member->type->value(elPtr, interleaved));
708 		}
709 		return std::make_shared<vk::dbg::Struct>(name_, fields);
710 	}
711 };
712 
713 // TemplateParameter represents the OpenCL.DebugInfo.100
714 // DebugTypeTemplateParameter instruction.
715 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugTypeTemplateParameter
716 struct TemplateParameter : ObjectImpl<TemplateParameter, Object, Object::Kind::TemplateParameter>
717 {
718 	std::string name;
719 	Type *type = nullptr;
720 	uint32_t value = 0;
721 	Source *source = nullptr;
722 	uint32_t line = 0;
723 	uint32_t column = 0;
724 };
725 
726 // TemplateType represents the OpenCL.DebugInfo.100 DebugTypeTemplate
727 // instruction.
728 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugTypeTemplate
729 struct TemplateType : ObjectImpl<TemplateType, Type, Object::Kind::TemplateType>
730 {
731 	Type *target = nullptr;  // Class, struct or function.
732 	std::vector<TemplateParameter *> parameters;
733 
name__anon5bdf0e0e0411::debug::TemplateType734 	std::string name() const override { return "template<>"; }
sizeInBytes__anon5bdf0e0e0411::debug::TemplateType735 	uint32_t sizeInBytes() const override { return target->sizeInBytes(); }
numMembers__anon5bdf0e0e0411::debug::TemplateType736 	size_t numMembers() const override { return 0; }
getMember__anon5bdf0e0e0411::debug::TemplateType737 	Member getMember(size_t i) const override { return {}; }
value__anon5bdf0e0e0411::debug::TemplateType738 	std::shared_ptr<vk::dbg::Value> value(void *ptr, bool interleaved) const override
739 	{
740 		return target->value(ptr, interleaved);
741 	}
742 };
743 
744 // LexicalBlock represents the OpenCL.DebugInfo.100 DebugLexicalBlock instruction.
745 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugLexicalBlock
746 struct LexicalBlock : Scope
747 {
748 	using ID = sw::SpirvID<LexicalBlock>;
749 	static constexpr auto Kind = Object::Kind::LexicalBlock;
750 
LexicalBlock__anon5bdf0e0e0411::debug::LexicalBlock751 	inline LexicalBlock(Object::Kind kind = Kind)
752 	    : Scope(kind)
753 	{}
754 
755 	uint32_t line = 0;
756 	uint32_t column = 0;
757 	std::string name;
758 
759 	std::vector<LocalVariable *> variables;
760 
kindof__anon5bdf0e0e0411::debug::LexicalBlock761 	static constexpr bool kindof(Object::Kind kind) { return kind == Kind || kind == Object::Kind::Function; }
762 };
763 
764 // Function represents the OpenCL.DebugInfo.100 DebugFunction instruction.
765 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugFunction
766 struct Function : ObjectImpl<Function, LexicalBlock, Object::Kind::Function>
767 {
768 	std::string name;
769 	FunctionType *type = nullptr;
770 	uint32_t declLine = 0;
771 	uint32_t declColumn = 0;
772 	std::string linkage;
773 	uint32_t flags = 0;  // OR'd from OpenCLDebugInfo100DebugInfoFlags
774 	sw::SpirvShader::Function::ID function;
775 };
776 
777 // InlinedAt represents the OpenCL.DebugInfo.100 DebugInlinedAt instruction.
778 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugInlinedAt
779 struct InlinedAt : ObjectImpl<InlinedAt, Object, Object::Kind::InlinedAt>
780 {
781 	uint32_t line = 0;
782 	Scope *scope = nullptr;
783 	InlinedAt *inlined = nullptr;
784 };
785 
786 // SourceScope represents the OpenCL.DebugInfo.100 DebugScope instruction.
787 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugScope
788 struct SourceScope : ObjectImpl<SourceScope, Object, Object::Kind::SourceScope>
789 {
790 	Scope *scope = nullptr;
791 	InlinedAt *inlinedAt = nullptr;
792 };
793 
794 // GlobalVariable represents the OpenCL.DebugInfo.100 DebugGlobalVariable instruction.
795 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugGlobalVariable
796 struct GlobalVariable : ObjectImpl<GlobalVariable, Object, Object::Kind::GlobalVariable>
797 {
798 	std::string name;
799 	Type *type = nullptr;
800 	Source *source = nullptr;
801 	uint32_t line = 0;
802 	uint32_t column = 0;
803 	Scope *parent = nullptr;
804 	std::string linkage;
805 	sw::SpirvShader::Object::ID variable;
806 	uint32_t flags = 0;  // OR'd from OpenCLDebugInfo100DebugInfoFlags
807 };
808 
809 // LocalVariable represents the OpenCL.DebugInfo.100 DebugLocalVariable
810 // instruction.
811 // Local variables are essentially just a scoped variable name.
812 // Their value comes from either a DebugDeclare (which has an immutable pointer
813 // to the actual data), or from a number of DebugValues (which can change
814 // any nested members of the variable over time).
815 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugLocalVariable
816 struct LocalVariable : ObjectImpl<LocalVariable, Object, Object::Kind::LocalVariable>
817 {
818 	static constexpr uint32_t NoArg = ~uint32_t(0);
819 
820 	enum class Definition
821 	{
822 		Undefined,    // Variable has no defined value
823 		Declaration,  // Variable value comes from definition
824 		Values        // Variable value comes from values
825 	};
826 
827 	std::string name;
828 	Type *type = nullptr;
829 	Source *source = nullptr;
830 	uint32_t line = 0;
831 	uint32_t column = 0;
832 	Scope *parent = nullptr;
833 	uint32_t arg = NoArg;
834 
835 	Definition definition = Definition::Undefined;
836 	Declare *declaration = nullptr;  // Used if definition == Definition::Declaration
837 
838 	// ValueNode is a tree node of debug::Value definitions.
839 	// Each node in the tree represents an element in the type tree.
840 	struct ValueNode
841 	{
842 		// NoDebugValueIndex indicates that this node is never assigned a value.
843 		static constexpr const uint32_t NoDebugValueIndex = ~0u;
844 
845 		uint32_t debugValueIndex = NoDebugValueIndex;  // Index into State::lastReachedDebugValues
846 		std::unordered_map<uint32_t, std::unique_ptr<ValueNode>> children;
847 	};
848 	ValueNode values;  // Used if definition == Definition::Values
849 };
850 
851 // Operation represents the OpenCL.DebugInfo.100 DebugOperation instruction.
852 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugOperation
853 struct Operation : ObjectImpl<Operation, Object, Object::Kind::Operation>
854 {
855 	uint32_t opcode = 0;
856 	std::vector<uint32_t> operands;
857 };
858 
859 // Expression represents the OpenCL.DebugInfo.100 DebugExpression instruction.
860 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugExpression
861 struct Expression : ObjectImpl<Expression, Object, Object::Kind::Expression>
862 {
863 	std::vector<Operation *> operations;
864 };
865 
866 // Declare represents the OpenCL.DebugInfo.100 DebugDeclare instruction.
867 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugDeclare
868 struct Declare : ObjectImpl<Declare, Object, Object::Kind::Declare>
869 {
870 	LocalVariable *local = nullptr;
871 	sw::SpirvShader::Object::ID variable;
872 	Expression *expression = nullptr;
873 };
874 
875 // Value represents the OpenCL.DebugInfo.100 DebugValue instruction.
876 // https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugValue
877 struct Value : ObjectImpl<Value, Object, Object::Kind::Value>
878 {
879 	LocalVariable *local = nullptr;
880 	sw::SpirvShader::Object::ID value;
881 	Expression *expression = nullptr;
882 	std::vector<uint32_t> indexes;
883 };
884 
885 // find<T>() searches the nested scopes, returning for the first scope that is
886 // castable to type T. If no scope can be found of type T, then nullptr is
887 // returned.
888 template<typename T>
find(Scope * scope)889 T *find(Scope *scope)
890 {
891 	if(auto out = cast<T>(scope)) { return out; }
892 	return scope->parent ? find<T>(scope->parent) : nullptr;
893 }
894 
tostring(LocalVariable::Definition def)895 inline const char *tostring(LocalVariable::Definition def)
896 {
897 	switch(def)
898 	{
899 		case LocalVariable::Definition::Undefined: return "Undefined";
900 		case LocalVariable::Definition::Declaration: return "Declaration";
901 		case LocalVariable::Definition::Values: return "Values";
902 		default: return "<unknown>";
903 	}
904 }
905 
906 }  // namespace debug
907 }  // anonymous namespace
908 
909 ////////////////////////////////////////////////////////////////////////////////
910 // namespace ::sw
911 //
912 // Implementations for:
913 //   sw::SpirvShader::Impl::Debugger
914 //   sw::SpirvShader::Impl::Debugger::LocalVariableValue
915 //   sw::SpirvShader::Impl::Debugger::State
916 //   sw::SpirvShader::Impl::Debugger::State::Data
917 ////////////////////////////////////////////////////////////////////////////////
918 namespace sw {
919 
920 ////////////////////////////////////////////////////////////////////////////////
921 // sw::SpirvShader::Impl::Debugger
922 //
923 // SpirvShader-private struct holding compile-time-mutable and
924 // execution-time-immutable debugger information.
925 //
926 // There is an instance of this class per shader program.
927 ////////////////////////////////////////////////////////////////////////////////
928 struct SpirvShader::Impl::Debugger : public vk::dbg::ClientEventListener
929 {
930 	class State;
931 	class LocalVariableValue;
932 
933 	Debugger(const SpirvShader *shader, const std::shared_ptr<vk::dbg::Context> &ctx);
934 	~Debugger();
935 
936 	enum class Pass
937 	{
938 		Define,  // Pre-pass (called from SpirvShader constructor)
939 		Emit     // Code generation pass (called from SpirvShader::emit()).
940 	};
941 
942 	// process() is called for each debugger instruction in two compiler passes.
943 	// For the Define pass, process() constructs ::debug objects and
944 	// registers them in the objects map.
945 	// For the Emit pass, process() populates the fields of ::debug objects and
946 	// potentially emits instructions for the shader program.
947 	void process(const InsnIterator &insn, EmitState *state, Pass pass);
948 
949 	// finalize() must be called after all shader instruction have been emitted.
950 	// finalize() allocates the trap memory and registers the Debugger for
951 	// client debugger events so that it can monitor for changes in breakpoints.
952 	void finalize();
953 
954 	// setNextSetLocationIsSteppable() indicates that the next call to
955 	// setLocation() must be a debugger steppable line.
956 	void setNextSetLocationIsSteppable();
957 
958 	// setScope() sets the current debug source scope. Used by setLocation()
959 	// when the next location is debugger steppable.
960 	void setScope(debug::SourceScope *);
961 
962 	// setLocation() sets the current codegen source location to the given file
963 	// and line.
964 	void setLocation(EmitState *state, const std::shared_ptr<vk::dbg::File> &, int line);
965 	void setLocation(EmitState *state, const char *file, int line);
966 
967 	using SpirvInstruction = const void *;
968 
969 	const SpirvShader *const shader;                              // The shader program being debugged
970 	std::shared_ptr<vk::dbg::Context> const ctx;                  // The debugger context
971 	bool shaderHasDebugInfo;                                      // True if the shader has high-level debug info (OpenCL.Debug100 instructions)
972 	std::shared_ptr<vk::dbg::File> spirvFile;                     // Virtual file containing SPIR-V disassembly instructions
973 	std::unordered_map<SpirvInstruction, int> spirvLineMappings;  // Instruction pointer to line
974 	std::unordered_map<SpirvInstruction, Object::ID> results;     // Instruction pointer to result ID
975 
976 	// LocationAndScope holds a source location and scope pair.
977 	struct LocationAndScope
978 	{
979 		vk::dbg::Location location;
980 		debug::SourceScope *scope;
981 
operator ==sw::SpirvShader::Impl::Debugger::LocationAndScope982 		inline bool operator==(const LocationAndScope &other) const
983 		{
984 			return location == other.location && scope == other.scope;
985 		}
986 		struct Hash
987 		{
operator ()sw::SpirvShader::Impl::Debugger::LocationAndScope::Hash988 			uint64_t operator()(const LocationAndScope &l) const
989 			{
990 				return std::hash<decltype(l.location)>()(l.location) ^ std::hash<decltype(l.scope)>()(l.scope);
991 			}
992 		};
993 	};
994 
995 	// Traps holds information about debugger traps - points in the shader
996 	// program where execution may pause for the debugger, either due to hitting
997 	// a breakpoint or following a single line step.
998 	// The Traps::memory is continually read during execution of a shader,
999 	// triggering a trap when the byte is non-zero. Traps can also be enabled
1000 	// via the State::alwaysTrap field.
1001 	struct Traps
1002 	{
1003 		// Source location + scope -> line trap index
1004 		std::unordered_map<LocationAndScope, size_t, LocationAndScope::Hash> byLocationAndScope;
1005 
1006 		// Function name -> entry trap index
1007 		std::unordered_map<std::string, size_t> byFunctionName;
1008 
1009 		// Trap index -> source location + scope
1010 		std::vector<LocationAndScope> byIndex;
1011 
1012 		// Trap memory - shared for all running instances of the shader.
1013 		// Each byte represents a single trap enabled (1) / disabled (0) state.
1014 		std::unique_ptr<uint8_t[]> memory;
1015 	} traps;
1016 
1017 	// Shadow memory is used to construct a contiguous memory block
1018 	// (State::shadow) that contains an up-to-date copy of each
1019 	// SpirvShader::Object's value(s) in the currently executing shader.
1020 	// Shadow memory either contains SIMD-interleaved values for all components
1021 	// in the object, or a SIMD-pointer (Shadow::Pointer).
1022 	struct Shadow
1023 	{
1024 		// Entry describes the byte offset and kind of the shadow memory for
1025 		// a single SpirvShader::Object.
1026 		struct Entry
1027 		{
1028 			enum class Kind
1029 			{
1030 				Value,
1031 				Pointer,
1032 			};
1033 			Kind kind;
1034 			uint32_t offset;
1035 		};
1036 
1037 		// Pointer is the structure stored in shadow memory for pointer types.
1038 		// The address for a given SIMD lane is the base + offsets[lane].
1039 		struct Pointer
1040 		{
1041 			uint8_t *base;                      // Common base address for all SIMD lanes.
1042 			uint32_t offsets[sw::SIMD::Width];  // Per lane offsets.
1043 		};
1044 
1045 		// Memory is returned by get().
1046 		// Memory holds a pointer (addr) to the entry in the shadow memory, and
1047 		// provides the dref() method for dereferencing a pointer for the given
1048 		// SIMD lane.
1049 		struct Memory
1050 		{
1051 			inline operator void *();
1052 			inline Memory dref(int lane) const;
1053 			uint8_t *addr;
1054 		};
1055 
1056 		// create() adds a new entry for the object with the given id.
1057 		void create(const SpirvShader *, const EmitState *, Object::ID);
1058 
1059 		// get() returns a Memory pointing to the shadow memory for the object
1060 		// with the given id for the given SIMD lane.
1061 		Memory get(const State *, Object::ID, int lane) const;
1062 
1063 		std::unordered_map<Object::ID, Entry> entries;
1064 		uint32_t size = 0;  // Total size of the shadow memory in bytes.
1065 	} shadow;
1066 
1067 	// vk::dbg::ClientEventListener
1068 	void onSetBreakpoint(const vk::dbg::Location &location, bool &handled) override;
1069 	void onSetBreakpoint(const std::string &func, bool &handled) override;
1070 	void onBreakpointsChanged() override;
1071 
1072 private:
1073 	// add() registers the debug object with the given id.
1074 	template<typename ID>
1075 	void add(ID id, std::unique_ptr<debug::Object> &&);
1076 
1077 	// addNone() registers given id as a None value or type.
1078 	void addNone(debug::Object::ID id);
1079 
1080 	// isNone() returns true if the given id was registered as none with
1081 	// addNone().
1082 	bool isNone(debug::Object::ID id) const;
1083 
1084 	// get() returns the debug object with the given id.
1085 	// The object must exist and be of type (or derive from type) T.
1086 	// A returned nullptr represents a None value or type.
1087 	template<typename T>
1088 	T *get(SpirvID<T> id) const;
1089 
1090 	// getOrNull() returns the debug object with the given id if
1091 	// the object exists and is of type (or derive from type) T.
1092 	// Otherwise, returns nullptr.
1093 	template<typename T>
1094 	T *getOrNull(SpirvID<T> id) const;
1095 
1096 	// use get() and add() to access this
1097 	std::unordered_map<debug::Object::ID, std::unique_ptr<debug::Object>> objects;
1098 
1099 	// defineOrEmit() when called in Pass::Define, creates and stores a
1100 	// zero-initialized object into the Debugger::objects map using the
1101 	// object identifier held by second instruction operand.
1102 	// When called in Pass::Emit, defineOrEmit() calls the function F with the
1103 	// previously-built object.
1104 	//
1105 	// F must be a function with the signature:
1106 	//   void(OBJECT_TYPE *)
1107 	//
1108 	// The object type is automatically inferred from the function signature.
1109 	template<typename F, typename T = typename std::remove_pointer<ArgTyT<F>>::type>
1110 	void defineOrEmit(InsnIterator insn, Pass pass, F &&emit);
1111 
1112 	std::unordered_map<std::string, std::shared_ptr<vk::dbg::File>> files;
1113 	uint32_t numDebugValueSlots = 0;  // Number of independent debug::Values which need to be tracked
1114 	bool nextSetLocationIsSteppable = true;
1115 	debug::SourceScope *lastSetScope = nullptr;
1116 	vk::dbg::Location lastSetLocation;
1117 };
1118 
1119 ////////////////////////////////////////////////////////////////////////////////
1120 // sw::SpirvShader::Impl::Debugger::LocalVariableValue
1121 //
1122 // Implementation of vk::dbg::Value that displays a debug::LocalVariable that
1123 // has its value(s) defined by debug::Value(s).
1124 //
1125 // TODO(b/145351270) Note: The OpenCL.DebugInfo.100 spec does not state how
1126 // DebugValues should be applied to the DebugLocalVariable.
1127 //
1128 // This implementation keeps track of the order of DebugValues as they are
1129 // 'executed', and uses the most recent values for each specific index.
1130 // OpenCL.DebugInfo.100 is significantly derived from the LLVM debug
1131 // instructions, and so it can be assumed that DebugValue is intended to behave
1132 // like llvm.dbg.value.
1133 //
1134 // https://llvm.org/docs/SourceLevelDebugging.html#object-lifetime-in-optimized-code
1135 // describes the expected behavior of llvm.dbg.value, which instead of runtime
1136 // tracking, uses static analysis of the LLVM IR to determine which debug
1137 // values should be used.
1138 //
1139 // If DebugValue is to behave the same way as llvm.dbg.value, then this
1140 // implementation should be changed to examine the order of DebugValue
1141 // instructions in the SPIR-V. This can only be done once the SPIR-V generating
1142 // compiler and SPIR-V optimization passes generate and preserve the DebugValue
1143 // ordering as described in the LLVM SourceLevelDebugging document.
1144 ////////////////////////////////////////////////////////////////////////////////
1145 class sw::SpirvShader::Impl::Debugger::LocalVariableValue : public vk::dbg::Value
1146 {
1147 public:
1148 	// Data shared across all nodes in the LocalVariableValue.
1149 	struct Shared
1150 	{
Sharedsw::sw::SpirvShader::Impl::Debugger::LocalVariableValue::Shared1151 		Shared(debug::LocalVariable const *const variable, State const *const state, int const lane)
1152 		    : variable(variable)
1153 		    , state(state)
1154 		    , lane(lane)
1155 		{
1156 			ASSERT(variable->definition == debug::LocalVariable::Definition::Values);
1157 		}
1158 
1159 		debug::LocalVariable const *const variable;
1160 		State const *const state;
1161 		int const lane;
1162 	};
1163 
1164 	LocalVariableValue(debug::LocalVariable *variable, State const *const state, int lane);
1165 
1166 	LocalVariableValue(
1167 	    std::shared_ptr<const Shared> const &shared,
1168 	    debug::Type const *ty,
1169 	    debug::LocalVariable::ValueNode const *node);
1170 
1171 private:
1172 	// vk::dbg::Value
1173 	std::string type() override;
1174 	std::string get(const vk::dbg::FormatFlags &) override;
1175 	std::shared_ptr<vk::dbg::Variables> children() override;
1176 
1177 	void updateValue();
1178 	std::shared_ptr<const Shared> const shared;
1179 	debug::Type const *const ty;
1180 	debug::LocalVariable::ValueNode const *const node;
1181 	debug::Value *activeValue = nullptr;
1182 	std::shared_ptr<vk::dbg::Value> value;
1183 };
1184 
1185 ////////////////////////////////////////////////////////////////////////////////
1186 // sw::SpirvShader::Impl::Debugger::State
1187 //
1188 // State holds the runtime data structures for the shader debug session.
1189 //
1190 // When debugging is enabled, the shader program will construct a State with a
1191 // call to create(), and during execution write shader information into fields
1192 // of this class, including:
1193 //  * Shadow memory for keeping track of register-held values.
1194 //  * Global variables.
1195 //  * Last reached ::debug::Values (see LocalVariableValue)
1196 //
1197 // Bulky data that is only needed once the shader has hit a trap is held by
1198 // State::Data. This is lazily constructed by the first call to trap().
1199 //
1200 // There is an instance of this class per shader invocation.
1201 ////////////////////////////////////////////////////////////////////////////////
1202 class SpirvShader::Impl::Debugger::State
1203 {
1204 public:
1205 	// Globals holds a copy of the shader's builtin global variables.
1206 	struct Globals
1207 	{
1208 		struct Compute
1209 		{
1210 			sw::uint3 numWorkgroups;
1211 			sw::uint3 workgroupID;
1212 			sw::uint3 workgroupSize;
1213 			uint32_t numSubgroups;
1214 			uint32_t subgroupIndex;
1215 			sw::SIMD::uint3 globalInvocationId;
1216 			sw::SIMD::uint3 localInvocationId;
1217 			sw::SIMD::uint3 localInvocationIndex;
1218 		};
1219 		struct Fragment
1220 		{
1221 			uint32_t viewIndex;
1222 			sw::SIMD::vec4 fragCoord;
1223 			sw::SIMD::vec4 pointCoord;
1224 			sw::SIMD::int2 windowSpacePosition;
1225 			sw::SIMD::uint_t helperInvocation;
1226 		};
1227 		struct Vertex
1228 		{
1229 			uint32_t viewIndex;
1230 			uint32_t instanceIndex;
1231 			sw::SIMD::uint_t vertexIndex;
1232 		};
1233 
1234 		// Common for all shader types
1235 		uint32_t subgroupSize;
1236 		sw::SIMD::uint_t activeLaneMask;
1237 
1238 		// Shader type specific globals
1239 		union
1240 		{
1241 			Compute compute;
1242 			Fragment fragment;
1243 			Vertex vertex;
1244 		};
1245 	};
1246 
1247 	// create() allocates, constructs and returns a State.
1248 	// Called at the start of the debugger-enabled shader program.
1249 	static State *create(const Debugger *debugger);
1250 
1251 	// destroy() destructs and frees a state.
1252 	// Called at the end of the debugger-enabled shader program.
1253 	static void destroy(State *);
1254 
1255 	// trap() is called by the debugger-enabled shader program to suspend
1256 	// execution of the shader. This will appear in the attached debugger as if
1257 	// a breakpoint has been hit.
1258 	// trap() will be called if the Debugger::Traps::memory[index] is non-zero,
1259 	// or if alwaysTrap is non-zero.
1260 	// index is the index of the trap (see Debugger::Traps).
1261 	void trap(int index);
1262 
1263 	const Debugger *const debugger;
1264 
1265 	// traps is a simple copy of Debugger::Traps::memory.
1266 	// Copied here to reduce pointer chasing during shader execution.
1267 	uint8_t *traps = nullptr;
1268 
1269 	// alwaysTrap (if non-zero) forces a call trap() even if
1270 	// Debugger::Traps::memory[index] is zero. Used to perform single line
1271 	// stepping (pause at next line / instruction).
1272 	uint8_t alwaysTrap = 0;
1273 
1274 	// Global variable values. Written to at shader start.
1275 	Globals globals;
1276 
1277 	// Shadow memory for all SpirvShader::Objects in the executing shader
1278 	// program.
1279 	// See Debugger::Shadow for more information.
1280 	std::unique_ptr<uint8_t[]> const shadow;
1281 
1282 	// Array of last reached debug::Value.
1283 	// Indexed by ::debug::LocalVariable::ValueNode::debugValueIndex.
1284 	std::unique_ptr<debug::Value *[]> const lastReachedDebugValues;
1285 
1286 private:
1287 	// Data holds the debugger-interface state (vk::dbg::*).
1288 	// This is only constructed on the first call to Debugger::State::trap() as
1289 	// it contains data that is only needed when the debugger is actively
1290 	// inspecting execution of the shader program.
1291 	struct Data
1292 	{
1293 		Data(State *state);
1294 
1295 		// terminate() is called at the end of execution of the shader program.
1296 		// terminate() ensures that the debugger thread stack is at the same
1297 		// level as when the program entered.
1298 		void terminate(State *state);
1299 
1300 		// trap() updates the debugger thread with the stack frames and
1301 		// variables at the trap's scoped location.
1302 		// trap() will notify the debugger that the thread has paused, and will
1303 		// block until instructed to resume (either continue or step) by the
1304 		// user.
1305 		void trap(int index, State *state);
1306 
1307 	private:
1308 		using PerLaneVariables = std::array<std::shared_ptr<vk::dbg::VariableContainer>, sw::SIMD::Width>;
1309 
1310 		struct StackEntry
1311 		{
1312 			debug::LexicalBlock *block;
1313 			uint32_t line;
1314 
operator !=sw::SpirvShader::Impl::Debugger::State::Data::StackEntry1315 			bool operator!=(const StackEntry &other) const { return block != other.block || line != other.line; }
1316 		};
1317 
1318 		struct GlobalVariables
1319 		{
1320 			std::shared_ptr<vk::dbg::VariableContainer> common;
1321 			PerLaneVariables lanes;
1322 		};
1323 
1324 		// updateFrameLocals() updates the local variables in the frame with
1325 		// those in the lexical block.
1326 		void updateFrameLocals(State *state, vk::dbg::Frame &frame, debug::LexicalBlock *block);
1327 
1328 		// getOrCreateLocals() creates and returns the per-lane local variables
1329 		// from those in the lexical block.
1330 		PerLaneVariables getOrCreateLocals(State *state, debug::LexicalBlock const *block);
1331 
1332 		// buildGlobal() creates and adds to globals global variable with the
1333 		// given name and value. The value is copied instead of holding a
1334 		// pointer to val.
1335 		template<typename T>
1336 		void buildGlobal(const char *name, const T &val);
1337 		template<typename T, int N>
1338 		void buildGlobal(const char *name, const sw::SIMD::PerLane<T, N> &vec);
1339 
1340 		// buildGlobals() builds all the global variable values, populating
1341 		// globals.
1342 		void buildGlobals(State *state);
1343 
1344 		// buildSpirvVariables() builds a Struct holding all the SPIR-V named
1345 		// values for the given lane.
1346 		std::shared_ptr<vk::dbg::Struct> buildSpirvVariables(State *state, int lane) const;
1347 
1348 		// buildSpirvValue() returns a debugger value for the SPIR-V shadow
1349 		// value at memory of the given type and for the given lane.
1350 		std::shared_ptr<vk::dbg::Value> buildSpirvValue(State *state, Shadow::Memory memory, const SpirvShader::Type &type, int lane) const;
1351 
1352 		GlobalVariables globals;
1353 		std::shared_ptr<vk::dbg::Thread> thread;
1354 		std::vector<StackEntry> stack;
1355 		std::unordered_map<debug::LexicalBlock const *, PerLaneVariables> locals;
1356 	};
1357 
1358 	State(const Debugger *debugger);
1359 	~State();
1360 	std::unique_ptr<Data> data;
1361 };
1362 
1363 ////////////////////////////////////////////////////////////////////////////////
1364 // sw::SpirvShader::Impl::Debugger methods
1365 ////////////////////////////////////////////////////////////////////////////////
Debugger(const SpirvShader * shader,const std::shared_ptr<vk::dbg::Context> & ctx)1366 SpirvShader::Impl::Debugger::Debugger(const SpirvShader *shader, const std::shared_ptr<vk::dbg::Context> &ctx)
1367     : shader(shader)
1368     , ctx(ctx)
1369 {
1370 }
1371 
~Debugger()1372 SpirvShader::Impl::Debugger::~Debugger()
1373 {
1374 	ctx->removeListener(this);
1375 }
1376 
finalize()1377 void SpirvShader::Impl::Debugger::finalize()
1378 {
1379 	ASSERT(traps.byIndex.size() == traps.byLocationAndScope.size());
1380 	traps.memory = std::make_unique<uint8_t[]>(traps.byIndex.size());
1381 
1382 	ctx->addListener(this);
1383 
1384 	// Register existing breakpoints.
1385 	onBreakpointsChanged();
1386 }
1387 
setNextSetLocationIsSteppable()1388 void sw::SpirvShader::Impl::Debugger::setNextSetLocationIsSteppable()
1389 {
1390 	nextSetLocationIsSteppable = true;
1391 }
1392 
setScope(debug::SourceScope * scope)1393 void SpirvShader::Impl::Debugger::setScope(debug::SourceScope *scope)
1394 {
1395 	lastSetScope = scope;
1396 }
1397 
setLocation(EmitState * state,const std::shared_ptr<vk::dbg::File> & file,int line)1398 void SpirvShader::Impl::Debugger::setLocation(EmitState *state, const std::shared_ptr<vk::dbg::File> &file, int line)
1399 {
1400 	vk::dbg::Location location{ file, line };
1401 
1402 	if(location != lastSetLocation)
1403 	{
1404 		// If the location has changed, then this is always a step.
1405 		nextSetLocationIsSteppable = true;
1406 		lastSetLocation = location;
1407 	}
1408 
1409 	if(nextSetLocationIsSteppable)
1410 	{
1411 		// Get or create the trap for the given location and scope.
1412 		LocationAndScope locationAndScope{ location, lastSetScope };
1413 		int index = getOrCreate(traps.byLocationAndScope, locationAndScope, [&] {
1414 			traps.byIndex.emplace_back(locationAndScope);
1415 			return traps.byIndex.size() - 1;
1416 		});
1417 
1418 		// Also create a map index for the given scope's function so we can
1419 		// break on function entry.
1420 		if(lastSetScope)
1421 		{
1422 			if(auto func = debug::find<debug::Function>(lastSetScope->scope))
1423 			{
1424 				getOrCreate(traps.byFunctionName, func->name, [&] { return index; });
1425 			}
1426 		}
1427 
1428 		// Emit the shader logic to test the trap value (either through via
1429 		// Debugger::State::traps[] or Debugger::State::alwaysTrap), and call
1430 		// Debugger::State::trap() if either are true.
1431 		auto dbgState = state->routine->dbgState;
1432 		auto alwaysTrap = *Pointer<Byte>(dbgState + OFFSET(Impl::Debugger::State, alwaysTrap));
1433 		auto traps = *Pointer<Pointer<Byte>>(dbgState + OFFSET(Impl::Debugger::State, traps));
1434 		auto trap = Pointer<Byte>(traps)[index];
1435 		If(alwaysTrap != Byte(0) || trap != Byte(0))
1436 		{
1437 			rr::Call(&State::trap, state->routine->dbgState, index);
1438 		}
1439 		nextSetLocationIsSteppable = false;
1440 	}
1441 }
1442 
setLocation(EmitState * state,const char * path,int line)1443 void SpirvShader::Impl::Debugger::setLocation(EmitState *state, const char *path, int line)
1444 {
1445 	auto lock = ctx->lock();
1446 	auto file = lock.findFile(path);
1447 	if(!file)
1448 	{
1449 		file = lock.createPhysicalFile(path);
1450 	}
1451 	setLocation(state, file, line);
1452 }
1453 
onSetBreakpoint(const vk::dbg::Location & location,bool & handled)1454 void SpirvShader::Impl::Debugger::onSetBreakpoint(const vk::dbg::Location &location, bool &handled)
1455 {
1456 	// Notify the debugger if the breakpoint location is handled.
1457 	// We don't actually set the trap here as this is performed by
1458 	// onBreakpointsChanged(), which is only called once, even for multiple
1459 	// breakpoint changes.
1460 	for(auto it : traps.byLocationAndScope)
1461 	{
1462 		if(location == it.first.location)
1463 		{
1464 			handled = true;
1465 			return;
1466 		}
1467 	}
1468 }
1469 
onSetBreakpoint(const std::string & func,bool & handled)1470 void SpirvShader::Impl::Debugger::onSetBreakpoint(const std::string &func, bool &handled)
1471 {
1472 	// Notify the debugger if the function-entry breakpoint is handled.
1473 	// We don't actually set the trap here as this is performed by
1474 	// onBreakpointsChanged(), which is only called once, even for multiple
1475 	// breakpoint changes.
1476 	auto it = traps.byFunctionName.find(func);
1477 	if(it != traps.byFunctionName.end())
1478 	{
1479 		handled = true;
1480 	}
1481 
1482 	if(isEntryBreakpointForShaderType(shader->executionModel, func))
1483 	{
1484 		handled = true;
1485 	}
1486 }
1487 
onBreakpointsChanged()1488 void SpirvShader::Impl::Debugger::onBreakpointsChanged()
1489 {
1490 	// TODO(b/145351270): TSAN will probably moan that traps.memory is being
1491 	// modified while being read on othe threads. We can solve this by adding
1492 	// a shared mutex (RWMutex) for the traps, read-locking for execution, and
1493 	// write locking here. This will prevent setting breakpoints while a shader
1494 	// is executing (maybe problematic if you want to debug a slow or
1495 	// never-completing shader).
1496 	// For now, just be racy. It's unlikely that this will cause any noticable
1497 	// problems.
1498 
1499 	// Start by disabling all traps.
1500 	memset(traps.memory.get(), 0, traps.byIndex.size() * sizeof(traps.memory[0]));
1501 
1502 	// Add traps for all breakpoints by location.
1503 	for(auto it : files)
1504 	{
1505 		auto &file = it.second;
1506 		for(auto line : file->getBreakpoints())
1507 		{
1508 			for(auto it : traps.byLocationAndScope)
1509 			{
1510 				if(it.first.location == vk::dbg::Location{ file, line })
1511 				{
1512 					traps.memory[it.second] = 1;
1513 				}
1514 			}
1515 		}
1516 	}
1517 
1518 	// Add traps for all breakpoints by function name.
1519 	auto lock = ctx->lock();
1520 	for(auto it : traps.byFunctionName)
1521 	{
1522 		if(lock.isFunctionBreakpoint(it.first))
1523 		{
1524 			traps.memory[it.second] = 1;
1525 		}
1526 	}
1527 
1528 	// Add traps for breakpoints by shader type.
1529 	for(auto bp : lock.getFunctionBreakpoints())
1530 	{
1531 		if(isEntryBreakpointForShaderType(shader->executionModel, bp))
1532 		{
1533 			traps.memory[0] = 1;
1534 		}
1535 	}
1536 }
1537 
1538 template<typename F, typename T>
defineOrEmit(InsnIterator insn,Pass pass,F && emit)1539 void SpirvShader::Impl::Debugger::defineOrEmit(InsnIterator insn, Pass pass, F &&emit)
1540 {
1541 	auto id = SpirvID<T>(insn.word(2));
1542 	switch(pass)
1543 	{
1544 		case Pass::Define:
1545 			add(id, std::unique_ptr<debug::Object>(new T()));
1546 			break;
1547 		case Pass::Emit:
1548 			emit(get<T>(id));
1549 			break;
1550 	}
1551 }
1552 
process(const InsnIterator & insn,EmitState * state,Pass pass)1553 void SpirvShader::Impl::Debugger::process(const InsnIterator &insn, EmitState *state, Pass pass)
1554 {
1555 	auto extInstIndex = insn.word(4);
1556 	switch(extInstIndex)
1557 	{
1558 		case OpenCLDebugInfo100DebugInfoNone:
1559 			if(pass == Pass::Define)
1560 			{
1561 				addNone(debug::Object::ID(insn.word(2)));
1562 			}
1563 			break;
1564 		case OpenCLDebugInfo100DebugCompilationUnit:
1565 			defineOrEmit(insn, pass, [&](debug::CompilationUnit *cu) {
1566 				cu->source = get(debug::Source::ID(insn.word(7)));
1567 			});
1568 			break;
1569 		case OpenCLDebugInfo100DebugTypeBasic:
1570 			defineOrEmit(insn, pass, [&](debug::BasicType *type) {
1571 				type->name_ = shader->getString(insn.word(5));
1572 				type->size = shader->GetConstScalarInt(insn.word(6));
1573 				type->encoding = static_cast<OpenCLDebugInfo100DebugBaseTypeAttributeEncoding>(insn.word(7));
1574 			});
1575 			break;
1576 		case OpenCLDebugInfo100DebugTypeArray:
1577 			defineOrEmit(insn, pass, [&](debug::ArrayType *type) {
1578 				type->base = get(debug::Type::ID(insn.word(5)));
1579 				type->size = shader->GetConstScalarInt(insn.word(6));
1580 				for(uint32_t i = 7; i < insn.wordCount(); i++)
1581 				{
1582 					// Decompose multi-dimentional into nested single
1583 					// dimensional arrays. Greatly simplifies logic.
1584 					auto inner = new debug::ArrayType();
1585 					inner->base = type->base;
1586 					type->size = shader->GetConstScalarInt(insn.word(i));
1587 					type->base = inner;
1588 					type->ownsBase = true;
1589 					type = inner;
1590 				}
1591 			});
1592 			break;
1593 		case OpenCLDebugInfo100DebugTypeVector:
1594 			defineOrEmit(insn, pass, [&](debug::VectorType *type) {
1595 				type->base = get(debug::Type::ID(insn.word(5)));
1596 				type->components = insn.word(6);
1597 			});
1598 			break;
1599 		case OpenCLDebugInfo100DebugTypeFunction:
1600 			defineOrEmit(insn, pass, [&](debug::FunctionType *type) {
1601 				type->flags = insn.word(5);
1602 				type->returnTy = getOrNull(debug::Type::ID(insn.word(6)));
1603 
1604 				// 'Return Type' operand must be a debug type or OpTypeVoid. See
1605 				// https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.DebugInfo.100.html#DebugTypeFunction
1606 				ASSERT_MSG(type->returnTy != nullptr || shader->getType(insn.word(6)).opcode() == spv::Op::OpTypeVoid, "Invalid return type of DebugTypeFunction: %d", insn.word(6));
1607 
1608 				for(uint32_t i = 7; i < insn.wordCount(); i++)
1609 				{
1610 					type->paramTys.push_back(get(debug::Type::ID(insn.word(i))));
1611 				}
1612 			});
1613 			break;
1614 		case OpenCLDebugInfo100DebugTypeComposite:
1615 			defineOrEmit(insn, pass, [&](debug::CompositeType *type) {
1616 				type->name_ = shader->getString(insn.word(5));
1617 				type->tag = static_cast<OpenCLDebugInfo100DebugCompositeType>(insn.word(6));
1618 				type->source = get(debug::Source::ID(insn.word(7)));
1619 				type->line = insn.word(8);
1620 				type->column = insn.word(9);
1621 				type->parent = get(debug::Object::ID(insn.word(10)));
1622 				type->linkage = shader->getString(insn.word(11));
1623 				type->size = isNone(insn.word(12)) ? 0 : shader->GetConstScalarInt(insn.word(12));
1624 				type->flags = insn.word(13);
1625 				for(uint32_t i = 14; i < insn.wordCount(); i++)
1626 				{
1627 					auto obj = get(debug::Object::ID(insn.word(i)));
1628 					if(auto member = debug::cast<debug::Member>(obj))  // Can also be Function or TypeInheritance, which we don't care about.
1629 					{
1630 						type->members_.push_back(member);
1631 					}
1632 				}
1633 			});
1634 			break;
1635 		case OpenCLDebugInfo100DebugTypeMember:
1636 			defineOrEmit(insn, pass, [&](debug::Member *member) {
1637 				member->name = shader->getString(insn.word(5));
1638 				member->type = get(debug::Type::ID(insn.word(6)));
1639 				member->source = get(debug::Source::ID(insn.word(7)));
1640 				member->line = insn.word(8);
1641 				member->column = insn.word(9);
1642 				member->parent = get(debug::CompositeType::ID(insn.word(10)));
1643 				member->offset = shader->GetConstScalarInt(insn.word(11));
1644 				member->size = shader->GetConstScalarInt(insn.word(12));
1645 				member->flags = insn.word(13);
1646 			});
1647 			break;
1648 		case OpenCLDebugInfo100DebugTypeTemplate:
1649 			defineOrEmit(insn, pass, [&](debug::TemplateType *tpl) {
1650 				tpl->target = get(debug::Type::ID(insn.word(5)));
1651 				for(size_t i = 6, c = insn.wordCount(); i < c; i++)
1652 				{
1653 					tpl->parameters.emplace_back(get(debug::TemplateParameter::ID(insn.word(i))));
1654 				}
1655 			});
1656 			break;
1657 		case OpenCLDebugInfo100DebugTypeTemplateParameter:
1658 			defineOrEmit(insn, pass, [&](debug::TemplateParameter *param) {
1659 				param->name = shader->getString(insn.word(5));
1660 				param->type = get(debug::Type::ID(insn.word(6)));
1661 				param->value = 0;  // TODO: Get value from OpConstant if "a template value parameter".
1662 				param->source = get(debug::Source::ID(insn.word(8)));
1663 				param->line = insn.word(9);
1664 				param->column = insn.word(10);
1665 			});
1666 			break;
1667 		case OpenCLDebugInfo100DebugGlobalVariable:
1668 			defineOrEmit(insn, pass, [&](debug::GlobalVariable *var) {
1669 				var->name = shader->getString(insn.word(5));
1670 				var->type = get(debug::Type::ID(insn.word(6)));
1671 				var->source = get(debug::Source::ID(insn.word(7)));
1672 				var->line = insn.word(8);
1673 				var->column = insn.word(9);
1674 				var->parent = get(debug::Scope::ID(insn.word(10)));
1675 				var->linkage = shader->getString(insn.word(11));
1676 				var->variable = isNone(insn.word(12)) ? 0 : insn.word(12);
1677 				var->flags = insn.word(13);
1678 				// static member declaration: word(14)
1679 			});
1680 			break;
1681 		case OpenCLDebugInfo100DebugFunction:
1682 			defineOrEmit(insn, pass, [&](debug::Function *func) {
1683 				func->name = shader->getString(insn.word(5));
1684 				func->type = get(debug::FunctionType::ID(insn.word(6)));
1685 				func->source = get(debug::Source::ID(insn.word(7)));
1686 				func->declLine = insn.word(8);
1687 				func->declColumn = insn.word(9);
1688 				func->parent = get(debug::Scope::ID(insn.word(10)));
1689 				func->linkage = shader->getString(insn.word(11));
1690 				func->flags = insn.word(12);
1691 				func->line = insn.word(13);
1692 				func->function = Function::ID(insn.word(14));
1693 				// declaration: word(13)
1694 			});
1695 			break;
1696 		case OpenCLDebugInfo100DebugLexicalBlock:
1697 			defineOrEmit(insn, pass, [&](debug::LexicalBlock *scope) {
1698 				scope->source = get(debug::Source::ID(insn.word(5)));
1699 				scope->line = insn.word(6);
1700 				scope->column = insn.word(7);
1701 				scope->parent = get(debug::Scope::ID(insn.word(8)));
1702 				if(insn.wordCount() > 9)
1703 				{
1704 					scope->name = shader->getString(insn.word(9));
1705 				}
1706 			});
1707 			break;
1708 		case OpenCLDebugInfo100DebugScope:
1709 			defineOrEmit(insn, pass, [&](debug::SourceScope *ss) {
1710 				ss->scope = get(debug::Scope::ID(insn.word(5)));
1711 				if(insn.wordCount() > 6)
1712 				{
1713 					ss->inlinedAt = get(debug::InlinedAt::ID(insn.word(6)));
1714 				}
1715 				setScope(ss);
1716 			});
1717 			break;
1718 		case OpenCLDebugInfo100DebugNoScope:
1719 			break;
1720 		case OpenCLDebugInfo100DebugInlinedAt:
1721 			defineOrEmit(insn, pass, [&](debug::InlinedAt *ia) {
1722 				ia->line = insn.word(5);
1723 				ia->scope = get(debug::Scope::ID(insn.word(6)));
1724 				if(insn.wordCount() > 7)
1725 				{
1726 					ia->inlined = get(debug::InlinedAt::ID(insn.word(7)));
1727 				}
1728 			});
1729 			break;
1730 		case OpenCLDebugInfo100DebugLocalVariable:
1731 			defineOrEmit(insn, pass, [&](debug::LocalVariable *var) {
1732 				var->name = shader->getString(insn.word(5));
1733 				var->type = get(debug::Type::ID(insn.word(6)));
1734 				var->source = get(debug::Source::ID(insn.word(7)));
1735 				var->line = insn.word(8);
1736 				var->column = insn.word(9);
1737 				var->parent = get(debug::Scope::ID(insn.word(10)));
1738 				if(insn.wordCount() > 11)
1739 				{
1740 					var->arg = insn.word(11);
1741 				}
1742 				if(auto block = debug::find<debug::LexicalBlock>(var->parent))
1743 				{
1744 					block->variables.emplace_back(var);
1745 				}
1746 			});
1747 			break;
1748 		case OpenCLDebugInfo100DebugDeclare:
1749 			defineOrEmit(insn, pass, [&](debug::Declare *decl) {
1750 				decl->local = get(debug::LocalVariable::ID(insn.word(5)));
1751 				decl->variable = Object::ID(insn.word(6));
1752 				decl->expression = get(debug::Expression::ID(insn.word(7)));
1753 
1754 				decl->local->declaration = decl;
1755 
1756 				ASSERT_MSG(decl->local->definition == debug::LocalVariable::Definition::Undefined,
1757 				           "DebugLocalVariable '%s' declared at %s:%d was previously defined as %s, now again as %s",
1758 				           decl->local->name.c_str(),
1759 				           decl->local->source ? decl->local->source->file.c_str() : "<unknown>",
1760 				           (int)decl->local->line,
1761 				           tostring(decl->local->definition),
1762 				           tostring(debug::LocalVariable::Definition::Declaration));
1763 				decl->local->definition = debug::LocalVariable::Definition::Declaration;
1764 			});
1765 			break;
1766 		case OpenCLDebugInfo100DebugValue:
1767 			defineOrEmit(insn, pass, [&](debug::Value *value) {
1768 				value->local = get(debug::LocalVariable::ID(insn.word(5)));
1769 				value->value = insn.word(6);
1770 				value->expression = get(debug::Expression::ID(insn.word(7)));
1771 
1772 				if(value->local->definition == debug::LocalVariable::Definition::Undefined)
1773 				{
1774 					value->local->definition = debug::LocalVariable::Definition::Values;
1775 				}
1776 				else
1777 				{
1778 					ASSERT_MSG(value->local->definition == debug::LocalVariable::Definition::Values,
1779 					           "DebugLocalVariable '%s' declared at %s:%d was previously defined as %s, now again as %s",
1780 					           value->local->name.c_str(),
1781 					           value->local->source ? value->local->source->file.c_str() : "<unknown>",
1782 					           (int)value->local->line,
1783 					           tostring(value->local->definition),
1784 					           tostring(debug::LocalVariable::Definition::Values));
1785 				}
1786 
1787 				auto node = &value->local->values;
1788 				for(uint32_t i = 8; i < insn.wordCount(); i++)
1789 				{
1790 					auto idx = shader->GetConstScalarInt(insn.word(i));
1791 					value->indexes.push_back(idx);
1792 
1793 					auto it = node->children.find(idx);
1794 					if(it != node->children.end())
1795 					{
1796 						node = it->second.get();
1797 					}
1798 					else
1799 					{
1800 						auto parent = node;
1801 						auto child = std::make_unique<debug::LocalVariable::ValueNode>();
1802 						node = child.get();
1803 						parent->children.emplace(idx, std::move(child));
1804 					}
1805 				}
1806 
1807 				if(node->debugValueIndex == debug::LocalVariable::ValueNode::NoDebugValueIndex)
1808 				{
1809 					node->debugValueIndex = numDebugValueSlots++;
1810 				}
1811 
1812 				rr::Pointer<rr::Pointer<Byte>> lastReachedArray = *rr::Pointer<rr::Pointer<rr::Pointer<Byte>>>(
1813 				    state->routine->dbgState + OFFSET(Impl::Debugger::State, lastReachedDebugValues));
1814 				rr::Pointer<rr::Pointer<Byte>> lastReached = &lastReachedArray[node->debugValueIndex];
1815 				*lastReached = rr::ConstantPointer(value);
1816 			});
1817 			break;
1818 		case OpenCLDebugInfo100DebugExpression:
1819 			defineOrEmit(insn, pass, [&](debug::Expression *expr) {
1820 				for(uint32_t i = 5; i < insn.wordCount(); i++)
1821 				{
1822 					expr->operations.push_back(get(debug::Operation::ID(insn.word(i))));
1823 				}
1824 			});
1825 			break;
1826 		case OpenCLDebugInfo100DebugSource:
1827 			defineOrEmit(insn, pass, [&](debug::Source *source) {
1828 				source->file = shader->getString(insn.word(5));
1829 				if(insn.wordCount() > 6)
1830 				{
1831 					source->source = shader->getString(insn.word(6));
1832 					auto file = ctx->lock().createVirtualFile(source->file.c_str(), source->source.c_str());
1833 					source->dbgFile = file;
1834 					files.emplace(source->file.c_str(), file);
1835 				}
1836 				else
1837 				{
1838 					auto file = ctx->lock().createPhysicalFile(source->file.c_str());
1839 					source->dbgFile = file;
1840 					files.emplace(source->file.c_str(), file);
1841 				}
1842 			});
1843 			break;
1844 		case OpenCLDebugInfo100DebugOperation:
1845 			defineOrEmit(insn, pass, [&](debug::Operation *operation) {
1846 				operation->opcode = insn.word(5);
1847 				for(uint32_t i = 6; i < insn.wordCount(); i++)
1848 				{
1849 					operation->operands.push_back(insn.word(i));
1850 				}
1851 			});
1852 			break;
1853 
1854 		case OpenCLDebugInfo100DebugTypePointer:
1855 		case OpenCLDebugInfo100DebugTypeQualifier:
1856 		case OpenCLDebugInfo100DebugTypedef:
1857 		case OpenCLDebugInfo100DebugTypeEnum:
1858 		case OpenCLDebugInfo100DebugTypeInheritance:
1859 		case OpenCLDebugInfo100DebugTypePtrToMember:
1860 		case OpenCLDebugInfo100DebugTypeTemplateTemplateParameter:
1861 		case OpenCLDebugInfo100DebugTypeTemplateParameterPack:
1862 		case OpenCLDebugInfo100DebugFunctionDeclaration:
1863 		case OpenCLDebugInfo100DebugLexicalBlockDiscriminator:
1864 		case OpenCLDebugInfo100DebugInlinedVariable:
1865 		case OpenCLDebugInfo100DebugMacroDef:
1866 		case OpenCLDebugInfo100DebugMacroUndef:
1867 		case OpenCLDebugInfo100DebugImportedEntity:
1868 			UNIMPLEMENTED("b/148401179 OpenCLDebugInfo100 instruction %d", int(extInstIndex));
1869 			break;
1870 		default:
1871 			UNSUPPORTED("OpenCLDebugInfo100 instruction %d", int(extInstIndex));
1872 	}
1873 }
1874 
1875 template<typename ID>
add(ID id,std::unique_ptr<debug::Object> && obj)1876 void SpirvShader::Impl::Debugger::add(ID id, std::unique_ptr<debug::Object> &&obj)
1877 {
1878 	ASSERT_MSG(obj != nullptr, "add() called with nullptr obj");
1879 	bool added = objects.emplace(debug::Object::ID(id.value()), std::move(obj)).second;
1880 	ASSERT_MSG(added, "Debug object with %d already exists", id.value());
1881 }
1882 
addNone(debug::Object::ID id)1883 void SpirvShader::Impl::Debugger::addNone(debug::Object::ID id)
1884 {
1885 	bool added = objects.emplace(debug::Object::ID(id.value()), nullptr).second;
1886 	ASSERT_MSG(added, "Debug object with %d already exists", id.value());
1887 }
1888 
isNone(debug::Object::ID id) const1889 bool SpirvShader::Impl::Debugger::isNone(debug::Object::ID id) const
1890 {
1891 	auto it = objects.find(debug::Object::ID(id.value()));
1892 	if(it == objects.end()) { return false; }
1893 	return it->second.get() == nullptr;
1894 }
1895 
1896 template<typename T>
get(SpirvID<T> id) const1897 T *SpirvShader::Impl::Debugger::get(SpirvID<T> id) const
1898 {
1899 	auto it = objects.find(debug::Object::ID(id.value()));
1900 	ASSERT_MSG(it != objects.end(), "Unknown debug object %d", id.value());
1901 	auto ptr = debug::cast<T>(it->second.get());
1902 	ASSERT_MSG(ptr, "Debug object %d is not of the correct type. Got: %s, want: %s",
1903 	           id.value(), cstr(it->second->kind), cstr(T::KIND));
1904 	return ptr;
1905 }
1906 
1907 template<typename T>
getOrNull(SpirvID<T> id) const1908 T *SpirvShader::Impl::Debugger::getOrNull(SpirvID<T> id) const
1909 {
1910 	auto it = objects.find(debug::Object::ID(id.value()));
1911 	if(it == objects.end()) { return nullptr; }  // Not found.
1912 	auto ptr = debug::cast<T>(it->second.get());
1913 	ASSERT_MSG(ptr, "Debug object %d is not of the correct type. Got: %s, want: %s",
1914 	           id.value(), cstr(it->second->kind), cstr(T::KIND));
1915 	return ptr;
1916 }
1917 
1918 ////////////////////////////////////////////////////////////////////////////////
1919 // SpirvShader::Impl::Debugger::Shadow methods
1920 ////////////////////////////////////////////////////////////////////////////////
create(const SpirvShader * shader,const EmitState * state,Object::ID objId)1921 void SpirvShader::Impl::Debugger::Shadow::create(const SpirvShader *shader, const EmitState *state, Object::ID objId)
1922 {
1923 	ASSERT_MSG(entries.find(objId) == entries.end(),
1924 	           "Object %%%d already has shadow memory allocated?", (int)objId.value());
1925 
1926 	Entry entry{};
1927 	entry.offset = size;
1928 
1929 	rr::Pointer<Byte> base = *rr::Pointer<rr::Pointer<Byte>>(state->routine->dbgState + OFFSET(Impl::Debugger::State, shadow));
1930 	base += entry.offset;
1931 
1932 	auto &obj = shader->getObject(objId);
1933 	auto &objTy = shader->getType(obj.typeId());
1934 	auto mask = state->activeLaneMask();
1935 	switch(obj.kind)
1936 	{
1937 		case Object::Kind::Constant:
1938 		case Object::Kind::Intermediate:
1939 		{
1940 			size += objTy.componentCount * sizeof(uint32_t) * sw::SIMD::Width;
1941 			auto dst = InterleaveByLane(SIMD::Pointer(base, 0));
1942 			for(uint32_t i = 0u; i < objTy.componentCount; i++)
1943 			{
1944 				auto val = SpirvShader::Operand(shader, state, objId).Int(i);
1945 				dst.Store(val, sw::OutOfBoundsBehavior::UndefinedBehavior, mask);
1946 				dst += sizeof(uint32_t) * SIMD::Width;
1947 			}
1948 			entry.kind = Entry::Kind::Value;
1949 			break;
1950 		}
1951 		case Object::Kind::Pointer:
1952 		case Object::Kind::InterfaceVariable:
1953 		{
1954 			size += sizeof(void *) + sizeof(uint32_t) * SIMD::Width;
1955 			auto ptr = state->getPointer(objId);
1956 			store(base, ptr.base);
1957 			store(base + sizeof(void *), ptr.offsets());
1958 			entry.kind = Entry::Kind::Pointer;
1959 			break;
1960 		}
1961 		default:
1962 			break;
1963 	}
1964 	entries.emplace(objId, entry);
1965 }
1966 
1967 SpirvShader::Impl::Debugger::Shadow::Memory
get(const State * state,Object::ID objId,int lane) const1968 SpirvShader::Impl::Debugger::Shadow::get(const State *state, Object::ID objId, int lane) const
1969 {
1970 	auto entryIt = entries.find(objId);
1971 	ASSERT_MSG(entryIt != entries.end(), "Missing shadow entry for object %%%d (%s)",
1972 	           (int)objId.value(),
1973 	           OpcodeName(state->debugger->shader->getObject(objId).opcode()).c_str());
1974 	auto &entry = entryIt->second;
1975 	auto data = &state->shadow[entry.offset];
1976 	return Memory{ data };
1977 }
1978 
operator void*()1979 SpirvShader::Impl::Debugger::Shadow::Memory::operator void *()
1980 {
1981 	return addr;
1982 }
1983 
1984 SpirvShader::Impl::Debugger::Shadow::Memory
dref(int lane) const1985 SpirvShader::Impl::Debugger::Shadow::Memory::dref(int lane) const
1986 {
1987 	auto ptr = *reinterpret_cast<Pointer *>(addr);
1988 	return Memory{ ptr.base + ptr.offsets[lane] };
1989 }
1990 
1991 ////////////////////////////////////////////////////////////////////////////////
1992 // sw::SpirvShader::Impl::Debugger::LocalVariableValue methods
1993 ////////////////////////////////////////////////////////////////////////////////
LocalVariableValue(debug::LocalVariable * variable,State const * const state,int lane)1994 sw::SpirvShader::Impl::Debugger::LocalVariableValue::LocalVariableValue(
1995     debug::LocalVariable *variable,
1996     State const *const state,
1997     int lane)
1998     : LocalVariableValue(std::make_shared<Shared>(variable, state, lane), variable->type, &variable->values)
1999 {}
2000 
LocalVariableValue(std::shared_ptr<const Shared> const & shared,debug::Type const * ty,debug::LocalVariable::ValueNode const * node)2001 sw::SpirvShader::Impl::Debugger::LocalVariableValue::LocalVariableValue(
2002     std::shared_ptr<const Shared> const &shared,
2003     debug::Type const *ty,
2004     debug::LocalVariable::ValueNode const *node)
2005     : shared(shared)
2006     , ty(ty)
2007     , node(node)
2008 {
2009 }
2010 
type()2011 std::string sw::SpirvShader::Impl::Debugger::LocalVariableValue::type()
2012 {
2013 	updateValue();
2014 	return value->type();
2015 }
2016 
get(const vk::dbg::FormatFlags & fmt)2017 std::string sw::SpirvShader::Impl::Debugger::LocalVariableValue::get(const vk::dbg::FormatFlags &fmt)
2018 {
2019 	updateValue();
2020 	return value->get(fmt);
2021 }
2022 
children()2023 std::shared_ptr<vk::dbg::Variables> sw::SpirvShader::Impl::Debugger::LocalVariableValue::children()
2024 {
2025 	updateValue();
2026 	return value->children();
2027 }
2028 
updateValue()2029 void sw::SpirvShader::Impl::Debugger::LocalVariableValue::updateValue()
2030 {
2031 	// Fetch the last reached ::debug::Value for this local variable node.
2032 	auto newActiveValue = (node->debugValueIndex != debug::LocalVariable::ValueNode::NoDebugValueIndex)
2033 	                          ? shared->state->lastReachedDebugValues[node->debugValueIndex]
2034 	                          : nullptr;
2035 	auto activeValueChanged = activeValue != newActiveValue;
2036 	activeValue = newActiveValue;
2037 
2038 	if(activeValue && activeValueChanged)
2039 	{  // We have a new ::debug::Value, read it.
2040 
2041 		ASSERT(activeValue->local == shared->variable);  // If this isn't true, then something is very wonky.
2042 
2043 		// Update the value.
2044 		auto ptr = shared->state->debugger->shadow.get(shared->state, activeValue->value, shared->lane);
2045 		for(auto op : activeValue->expression->operations)
2046 		{
2047 			switch(op->opcode)
2048 			{
2049 				case OpenCLDebugInfo100Deref:
2050 					ptr = ptr.dref(shared->lane);
2051 					break;
2052 				default:
2053 					UNIMPLEMENTED("b/148401179 OpenCLDebugInfo100DebugOperation %d", (int)op->opcode);
2054 					break;
2055 			}
2056 		}
2057 		value = ty->value(ptr, true);
2058 	}
2059 	else if(!value || activeValueChanged)
2060 	{  // We have no ::debug::Value. Display <undefined>
2061 
2062 		if(node->children.empty())
2063 		{  // No children? Just have the node display <undefined>
2064 			value = ty->undefined();
2065 		}
2066 		else
2067 		{  // Node has children.
2068 			// Display <undefined> for those that don't have sub-nodes, and
2069 			// create child LocalVariableValues for those that do.
2070 			value = vk::dbg::Struct::create(ty->name(), [&](auto &vc) {
2071 				auto numMembers = ty->numMembers();
2072 				for(size_t i = 0; i < numMembers; i++)
2073 				{
2074 					auto member = ty->getMember(i);
2075 
2076 					auto it = node->children.find(i);
2077 					if(it != node->children.end())
2078 					{
2079 						auto child = std::make_shared<LocalVariableValue>(shared, member.type, it->second.get());
2080 						vc->put(member.name, child);
2081 					}
2082 					else
2083 					{
2084 						vc->put(member.name, member.type->undefined());
2085 					}
2086 				}
2087 			});
2088 		}
2089 	}
2090 }
2091 
2092 ////////////////////////////////////////////////////////////////////////////////
2093 // sw::SpirvShader::Impl::Debugger::State methods
2094 ////////////////////////////////////////////////////////////////////////////////
create(const Debugger * debugger)2095 SpirvShader::Impl::Debugger::State *SpirvShader::Impl::Debugger::State::create(const Debugger *debugger)
2096 {
2097 	return new State(debugger);
2098 }
2099 
destroy(State * state)2100 void SpirvShader::Impl::Debugger::State::destroy(State *state)
2101 {
2102 	delete state;
2103 }
2104 
State(const Debugger * debugger)2105 SpirvShader::Impl::Debugger::State::State(const Debugger *debugger)
2106     : debugger(debugger)
2107     , traps(debugger->traps.memory.get())
2108     , shadow(new uint8_t[debugger->shadow.size])
2109     , lastReachedDebugValues(new debug::Value *[debugger->numDebugValueSlots])
2110 {
2111 	memset(shadow.get(), 0, debugger->shadow.size);
2112 	memset(lastReachedDebugValues.get(), 0, sizeof(lastReachedDebugValues[0]) * debugger->numDebugValueSlots);
2113 }
2114 
~State()2115 SpirvShader::Impl::Debugger::State::~State()
2116 {
2117 	if(data) { data->terminate(this); }
2118 }
2119 
trap(int index)2120 void SpirvShader::Impl::Debugger::State::trap(int index)
2121 {
2122 	if(std::all_of(globals.activeLaneMask.data.begin(),
2123 	               globals.activeLaneMask.data.end(),
2124 	               [](auto v) { return v == 0; }))
2125 	{
2126 		// Don't trap if no lanes are active.
2127 		// Ideally, we would be simply jumping over blocks that have no active
2128 		// lanes, but this is complicated due to ensuring that all reactor
2129 		// RValues dominate their usage blocks.
2130 		return;
2131 	}
2132 
2133 	if(!data)
2134 	{
2135 		data = std::make_unique<Data>(this);
2136 	}
2137 	data->trap(index, this);
2138 }
2139 
Data(State * state)2140 SpirvShader::Impl::Debugger::State::Data::Data(State *state)
2141 {
2142 	buildGlobals(state);
2143 
2144 	thread = state->debugger->ctx->lock().currentThread();
2145 
2146 	if(!state->debugger->shaderHasDebugInfo)
2147 	{
2148 		// Enter the stack frame entry for the SPIR-V.
2149 		thread->enter(state->debugger->spirvFile, "SPIR-V", [&](vk::dbg::Frame &frame) {
2150 			for(size_t lane = 0; lane < sw::SIMD::Width; lane++)
2151 			{
2152 				auto laneLocals = std::make_shared<vk::dbg::Struct>("Lane", globals.lanes[lane]);
2153 				frame.locals->variables->put(laneName(lane), laneLocals);
2154 				frame.hovers->variables->extend(std::make_shared<HoversFromLocals>(frame.locals->variables));
2155 			}
2156 		});
2157 	}
2158 }
2159 
terminate(State * state)2160 void SpirvShader::Impl::Debugger::State::Data::terminate(State *state)
2161 {
2162 	if(state->debugger->shaderHasDebugInfo)
2163 	{
2164 		for(size_t i = 0; i < stack.size(); i++)
2165 		{
2166 			thread->exit();
2167 		}
2168 	}
2169 	else
2170 	{
2171 		thread->exit();
2172 	}
2173 }
2174 
trap(int index,State * state)2175 void SpirvShader::Impl::Debugger::State::Data::trap(int index, State *state)
2176 {
2177 	auto debugger = state->debugger;
2178 
2179 	// Update the thread frames from the stack of scopes
2180 	auto const &locationAndScope = debugger->traps.byIndex[index];
2181 
2182 	if(locationAndScope.scope)
2183 	{
2184 		// Gather the new stack as LexicalBlocks.
2185 		std::vector<StackEntry> newStack;
2186 		if(auto block = debug::find<debug::LexicalBlock>(locationAndScope.scope->scope))
2187 		{
2188 			newStack.emplace_back(StackEntry{ block, block->line });
2189 		}
2190 		for(auto inlined = locationAndScope.scope->inlinedAt; inlined != nullptr; inlined = inlined->inlined)
2191 		{
2192 			if(auto block = debug::find<debug::LexicalBlock>(inlined->scope))
2193 			{
2194 				newStack.emplace_back(StackEntry{ block, inlined->line });
2195 			}
2196 		}
2197 		std::reverse(newStack.begin(), newStack.end());
2198 
2199 		// shrink pop stack frames until stack length is at most maxLen.
2200 		auto shrink = [&](size_t maxLen) {
2201 			while(stack.size() > maxLen)
2202 			{
2203 				thread->exit(true);
2204 				stack.pop_back();
2205 			}
2206 		};
2207 
2208 		// Pop stack frames until stack length is at most newStack length.
2209 		shrink(newStack.size());
2210 
2211 		// Find first deviation in stack frames, and shrink to that point.
2212 		// Special care is taken for deviation in just the top most frame so we
2213 		// don't end up reconstructing the top most stack frame every scope
2214 		// change.
2215 		for(size_t i = 0; i < stack.size(); i++)
2216 		{
2217 			if(stack[i] != newStack[i])
2218 			{
2219 				bool wasTopMostFrame = i == (stack.size() - 1);
2220 				auto oldFunction = debug::find<debug::Function>(stack[i].block);
2221 				auto newFunction = debug::find<debug::Function>(newStack[i].block);
2222 				if(wasTopMostFrame && oldFunction == newFunction)
2223 				{
2224 					// Deviation is just a movement in the top most frame's
2225 					// function.
2226 					// Don't exit() and enter() for the same function - it'll
2227 					// be treated as a step out and step in, breaking stepping
2228 					// commands. Instead, just update the frame variables for
2229 					// the new scope.
2230 					stack[i] = newStack[i];
2231 					thread->update(true, [&](vk::dbg::Frame &frame) {
2232 						// Update the frame location if we're entering a
2233 						// function. This allows the debugger to pause at the
2234 						// line (which may not have any instructions or OpLines)
2235 						// of a inlined function call. This is less jarring
2236 						// than magically appearing in another function before
2237 						// you've reached the line of the call site.
2238 						// See b/170650010 for more context.
2239 						if(stack.size() < newStack.size())
2240 						{
2241 							auto function = debug::find<debug::Function>(stack[i].block);
2242 							frame.location = vk::dbg::Location{ function->source->dbgFile, (int)stack[i].line };
2243 						}
2244 						updateFrameLocals(state, frame, stack[i].block);
2245 					});
2246 				}
2247 				else
2248 				{
2249 					shrink(i);
2250 				}
2251 				break;
2252 			}
2253 		}
2254 
2255 		// Now rebuild the parts of stack frames that are new.
2256 		//
2257 		// This is done in two stages:
2258 		// (1) thread->enter() is called to construct the new stack frame with
2259 		//     the opening scope line. The frames locals and hovers are built
2260 		//     and assigned.
2261 		// (2) thread->update() is called to adjust the frame's location to
2262 		//     entry.line. This may be different to the function entry in the
2263 		//     case of multiple nested inline functions. If its the same, then
2264 		//     this is a no-op.
2265 		//
2266 		// This two-stage approach allows the debugger to step through chains of
2267 		// inlined function calls without having a jarring jump from the outer
2268 		// function to the first statement within the function.
2269 		// See b/170650010 for more context.
2270 		for(size_t i = stack.size(); i < newStack.size(); i++)
2271 		{
2272 			auto entry = newStack[i];
2273 			stack.emplace_back(entry);
2274 			auto function = debug::find<debug::Function>(entry.block);
2275 			thread->enter(entry.block->source->dbgFile, function->name, [&](vk::dbg::Frame &frame) {
2276 				frame.location = vk::dbg::Location{ function->source->dbgFile, (int)function->line };
2277 				frame.hovers->variables->extend(std::make_shared<HoversFromLocals>(frame.locals->variables));
2278 				updateFrameLocals(state, frame, entry.block);
2279 			});
2280 			thread->update(true, [&](vk::dbg::Frame &frame) {
2281 				frame.location.line = (int)entry.line;
2282 			});
2283 		}
2284 	}
2285 
2286 	// If the debugger thread is running, notify that we're pausing due to the
2287 	// trap.
2288 	if(thread->state() == vk::dbg::Thread::State::Running)
2289 	{
2290 		// pause() changes the thread state Paused, and will cause the next
2291 		// frame location changing call update() to block until the debugger
2292 		// instructs the thread to resume or step.
2293 		thread->pause();
2294 		debugger->ctx->serverEventBroadcast()->onLineBreakpointHit(thread->id);
2295 	}
2296 
2297 	// Update the frame location. This will likely block until the debugger
2298 	// instructs the thread to resume or step.
2299 	thread->update(true, [&](vk::dbg::Frame &frame) {
2300 		frame.location = locationAndScope.location;
2301 	});
2302 
2303 	// Clear the alwaysTrap state if the debugger instructed the thread to
2304 	// resume, or set it if we're single line stepping (so we can keep track of
2305 	// location).
2306 	state->alwaysTrap = thread->state() != vk::dbg::Thread::State::Running;
2307 }
2308 
updateFrameLocals(State * state,vk::dbg::Frame & frame,debug::LexicalBlock * block)2309 void SpirvShader::Impl::Debugger::State::Data::updateFrameLocals(State *state, vk::dbg::Frame &frame, debug::LexicalBlock *block)
2310 {
2311 	auto locals = getOrCreateLocals(state, block);
2312 	for(size_t lane = 0; lane < sw::SIMD::Width; lane++)
2313 	{
2314 		auto laneLocals = std::make_shared<vk::dbg::Struct>("Lane", locals[lane]);
2315 		frame.locals->variables->put(laneName(lane), laneLocals);
2316 	}
2317 }
2318 
2319 SpirvShader::Impl::Debugger::State::Data::PerLaneVariables
getOrCreateLocals(State * state,debug::LexicalBlock const * block)2320 SpirvShader::Impl::Debugger::State::Data::getOrCreateLocals(State *state, debug::LexicalBlock const *block)
2321 {
2322 	return getOrCreate(locals, block, [&] {
2323 		PerLaneVariables locals;
2324 		for(int lane = 0; lane < sw::SIMD::Width; lane++)
2325 		{
2326 			auto vc = std::make_shared<vk::dbg::VariableContainer>();
2327 
2328 			for(auto var : block->variables)
2329 			{
2330 				auto name = var->name;
2331 
2332 				switch(var->definition)
2333 				{
2334 					case debug::LocalVariable::Definition::Undefined:
2335 					{
2336 						vc->put(name, var->type->undefined());
2337 						break;
2338 					}
2339 					case debug::LocalVariable::Definition::Declaration:
2340 					{
2341 						auto data = state->debugger->shadow.get(state, var->declaration->variable, lane);
2342 						vc->put(name, var->type->value(data.dref(lane), true));
2343 						break;
2344 					}
2345 					case debug::LocalVariable::Definition::Values:
2346 					{
2347 						vc->put(name, std::make_shared<LocalVariableValue>(var, state, lane));
2348 						break;
2349 					}
2350 				}
2351 			}
2352 
2353 			locals[lane] = std::move(vc);
2354 		}
2355 		if(auto parent = debug::find<debug::LexicalBlock>(block->parent))
2356 		{
2357 			auto extend = getOrCreateLocals(state, parent);
2358 			for(int lane = 0; lane < sw::SIMD::Width; lane++)
2359 			{
2360 				locals[lane]->extend(extend[lane]);
2361 			}
2362 		}
2363 		else
2364 		{
2365 			for(int lane = 0; lane < sw::SIMD::Width; lane++)
2366 			{
2367 				locals[lane]->extend(globals.lanes[lane]);
2368 			}
2369 		}
2370 		return locals;
2371 	});
2372 }
2373 
2374 template<typename T>
buildGlobal(const char * name,const T & val)2375 void SpirvShader::Impl::Debugger::State::Data::buildGlobal(const char *name, const T &val)
2376 {
2377 	globals.common->put(name, makeDbgValue(val));
2378 }
2379 
2380 template<typename T, int N>
buildGlobal(const char * name,const sw::SIMD::PerLane<T,N> & simd)2381 void SpirvShader::Impl::Debugger::State::Data::buildGlobal(const char *name, const sw::SIMD::PerLane<T, N> &simd)
2382 {
2383 	for(int lane = 0; lane < sw::SIMD::Width; lane++)
2384 	{
2385 		globals.lanes[lane]->put(name, makeDbgValue(simd[lane]));
2386 	}
2387 }
2388 
buildGlobals(State * state)2389 void SpirvShader::Impl::Debugger::State::Data::buildGlobals(State *state)
2390 {
2391 	globals.common = std::make_shared<vk::dbg::VariableContainer>();
2392 	globals.common->put("subgroupSize", vk::dbg::make_reference(state->globals.subgroupSize));
2393 
2394 	for(int lane = 0; lane < sw::SIMD::Width; lane++)
2395 	{
2396 		auto vc = std::make_shared<vk::dbg::VariableContainer>();
2397 
2398 		vc->put("enabled", vk::dbg::make_reference(reinterpret_cast<const bool &>(state->globals.activeLaneMask[lane])));
2399 
2400 		for(auto &it : state->debugger->objects)
2401 		{
2402 			if(auto var = debug::cast<debug::GlobalVariable>(it.second.get()))
2403 			{
2404 				if(var->variable != 0)
2405 				{
2406 					auto data = state->debugger->shadow.get(state, var->variable, lane);
2407 					vc->put(var->name, var->type->value(data.dref(lane), true));
2408 				}
2409 			}
2410 		}
2411 
2412 		auto spirv = buildSpirvVariables(state, lane);
2413 		if(state->debugger->shaderHasDebugInfo)
2414 		{
2415 			vc->put("SPIR-V", spirv);
2416 		}
2417 		else
2418 		{
2419 			vc->extend(spirv->children());
2420 		}
2421 
2422 		vc->extend(globals.common);
2423 		globals.lanes[lane] = vc;
2424 	}
2425 
2426 	switch(state->debugger->shader->executionModel)
2427 	{
2428 		case spv::ExecutionModelGLCompute:
2429 		{
2430 			buildGlobal("numWorkgroups", state->globals.compute.numWorkgroups);
2431 			buildGlobal("workgroupID", state->globals.compute.workgroupID);
2432 			buildGlobal("workgroupSize", state->globals.compute.workgroupSize);
2433 			buildGlobal("numSubgroups", state->globals.compute.numSubgroups);
2434 			buildGlobal("subgroupIndex", state->globals.compute.subgroupIndex);
2435 			buildGlobal("globalInvocationId", state->globals.compute.globalInvocationId);
2436 			buildGlobal("localInvocationIndex", state->globals.compute.localInvocationIndex);
2437 			break;
2438 		}
2439 		case spv::ExecutionModelFragment:
2440 		{
2441 			buildGlobal("viewIndex", state->globals.fragment.viewIndex);
2442 			buildGlobal("fragCoord", state->globals.fragment.fragCoord);
2443 			buildGlobal("pointCoord", state->globals.fragment.pointCoord);
2444 			buildGlobal("windowSpacePosition", state->globals.fragment.windowSpacePosition);
2445 			buildGlobal("helperInvocation", state->globals.fragment.helperInvocation);
2446 			break;
2447 		}
2448 		case spv::ExecutionModelVertex:
2449 		{
2450 			buildGlobal("viewIndex", state->globals.vertex.viewIndex);
2451 			buildGlobal("instanceIndex", state->globals.vertex.instanceIndex);
2452 			buildGlobal("vertexIndex", state->globals.vertex.vertexIndex);
2453 			break;
2454 		}
2455 		default:
2456 			break;
2457 	}
2458 }
2459 
2460 std::shared_ptr<vk::dbg::Struct>
buildSpirvVariables(State * state,int lane) const2461 SpirvShader::Impl::Debugger::State::Data::buildSpirvVariables(State *state, int lane) const
2462 {
2463 	return vk::dbg::Struct::create("SPIR-V", [&](auto &vc) {
2464 		auto debugger = state->debugger;
2465 		auto &entries = debugger->shadow.entries;
2466 		std::vector<Object::ID> ids;
2467 		ids.reserve(entries.size());
2468 		for(auto it : entries)
2469 		{
2470 			ids.emplace_back(it.first);
2471 		}
2472 		std::sort(ids.begin(), ids.end());
2473 		for(auto id : ids)
2474 		{
2475 			auto &obj = debugger->shader->getObject(id);
2476 			auto &objTy = debugger->shader->getType(obj.typeId());
2477 			auto name = "%" + std::to_string(id.value());
2478 			auto memory = debugger->shadow.get(state, id, lane);
2479 			switch(obj.kind)
2480 			{
2481 				case Object::Kind::Intermediate:
2482 				case Object::Kind::Constant:
2483 					if(auto val = buildSpirvValue(state, memory, objTy, lane))
2484 					{
2485 						vc->put(name, val);
2486 					}
2487 					break;
2488 				default:
2489 					break;  // Not handled yet.
2490 			}
2491 		}
2492 	});
2493 }
2494 
2495 std::shared_ptr<vk::dbg::Value>
buildSpirvValue(State * state,Shadow::Memory memory,const SpirvShader::Type & type,int lane) const2496 SpirvShader::Impl::Debugger::State::Data::buildSpirvValue(State *state, Shadow::Memory memory, const SpirvShader::Type &type, int lane) const
2497 {
2498 	auto debugger = state->debugger;
2499 	auto shader = debugger->shader;
2500 
2501 	switch(type.definition.opcode())
2502 	{
2503 		case spv::OpTypeInt:
2504 			return vk::dbg::make_reference(reinterpret_cast<uint32_t *>(memory.addr)[lane]);
2505 		case spv::OpTypeFloat:
2506 			return vk::dbg::make_reference(reinterpret_cast<float *>(memory.addr)[lane]);
2507 		case spv::OpTypeVector:
2508 		{
2509 			auto elTy = shader->getType(type.element);
2510 			return vk::dbg::Struct::create("vector", [&](auto &fields) {
2511 				for(uint32_t i = 0; i < type.componentCount; i++)
2512 				{
2513 					if(auto val = buildSpirvValue(state, memory, elTy, lane))
2514 					{
2515 						fields->put(vecElementName(i, type.componentCount), val);
2516 						memory.addr += sizeof(uint32_t) * sw::SIMD::Width;
2517 					}
2518 				}
2519 			});
2520 		}
2521 		default:
2522 			return nullptr;  // Not handled yet
2523 	}
2524 }
2525 
2526 ////////////////////////////////////////////////////////////////////////////////
2527 // sw::SpirvShader methods
2528 ////////////////////////////////////////////////////////////////////////////////
dbgInit(const std::shared_ptr<vk::dbg::Context> & ctx)2529 void SpirvShader::dbgInit(const std::shared_ptr<vk::dbg::Context> &ctx)
2530 {
2531 	impl.debugger = new Impl::Debugger(this, ctx);
2532 }
2533 
dbgTerm()2534 void SpirvShader::dbgTerm()
2535 {
2536 	if(impl.debugger)
2537 	{
2538 		delete impl.debugger;
2539 	}
2540 }
2541 
dbgCreateFile()2542 void SpirvShader::dbgCreateFile()
2543 {
2544 	auto dbg = impl.debugger;
2545 	if(!dbg) { return; }
2546 
2547 	int currentLine = 1;
2548 	std::string source;
2549 	for(auto insn : *this)
2550 	{
2551 		auto instruction = spvtools::spvInstructionBinaryToText(
2552 		                       vk::SPIRV_VERSION,
2553 		                       insn.wordPointer(0),
2554 		                       insn.wordCount(),
2555 		                       insns.data(),
2556 		                       insns.size(),
2557 		                       SPV_BINARY_TO_TEXT_OPTION_NO_HEADER) +
2558 		                   "\n";
2559 		dbg->spirvLineMappings[insn.wordPointer(0)] = currentLine;
2560 		currentLine += std::count(instruction.begin(), instruction.end(), '\n');
2561 		source += instruction;
2562 	}
2563 	std::string name;
2564 	switch(executionModel)
2565 	{
2566 		case spv::ExecutionModelVertex: name = "VertexShader"; break;
2567 		case spv::ExecutionModelFragment: name = "FragmentShader"; break;
2568 		case spv::ExecutionModelGLCompute: name = "ComputeShader"; break;
2569 		default: name = "SPIR-V Shader"; break;
2570 	}
2571 	static std::atomic<int> id = { 0 };
2572 	name += std::to_string(id++) + ".spvasm";
2573 	dbg->spirvFile = dbg->ctx->lock().createVirtualFile(name.c_str(), source.c_str());
2574 }
2575 
dbgBeginEmit(EmitState * state) const2576 void SpirvShader::dbgBeginEmit(EmitState *state) const
2577 {
2578 	auto dbg = impl.debugger;
2579 	if(!dbg) { return; }
2580 
2581 	dbg->shaderHasDebugInfo = extensionsImported.count(Extension::OpenCLDebugInfo100) > 0;
2582 
2583 	auto routine = state->routine;
2584 
2585 	auto dbgState = rr::Call(&Impl::Debugger::State::create, dbg);
2586 
2587 	routine->dbgState = dbgState;
2588 
2589 	SetActiveLaneMask(state->activeLaneMask(), state);
2590 
2591 	for(int i = 0; i < SIMD::Width; i++)
2592 	{
2593 		using Globals = Impl::Debugger::State::Globals;
2594 
2595 		auto globals = dbgState + OFFSET(Impl::Debugger::State, globals);
2596 		store(globals + OFFSET(Globals, subgroupSize), routine->invocationsPerSubgroup);
2597 
2598 		switch(executionModel)
2599 		{
2600 			case spv::ExecutionModelGLCompute:
2601 			{
2602 				auto compute = globals + OFFSET(Globals, compute);
2603 				store(compute + OFFSET(Globals::Compute, numWorkgroups), routine->numWorkgroups);
2604 				store(compute + OFFSET(Globals::Compute, workgroupID), routine->workgroupID);
2605 				store(compute + OFFSET(Globals::Compute, workgroupSize), routine->workgroupSize);
2606 				store(compute + OFFSET(Globals::Compute, numSubgroups), routine->subgroupsPerWorkgroup);
2607 				store(compute + OFFSET(Globals::Compute, subgroupIndex), routine->subgroupIndex);
2608 				store(compute + OFFSET(Globals::Compute, globalInvocationId), routine->globalInvocationID);
2609 				store(compute + OFFSET(Globals::Compute, localInvocationIndex), routine->localInvocationIndex);
2610 				break;
2611 			}
2612 			case spv::ExecutionModelFragment:
2613 			{
2614 				auto fragment = globals + OFFSET(Globals, fragment);
2615 				store(fragment + OFFSET(Globals::Fragment, viewIndex), routine->viewID);
2616 				store(fragment + OFFSET(Globals::Fragment, fragCoord), routine->fragCoord);
2617 				store(fragment + OFFSET(Globals::Fragment, pointCoord), routine->pointCoord);
2618 				store(fragment + OFFSET(Globals::Fragment, windowSpacePosition), routine->windowSpacePosition);
2619 				store(fragment + OFFSET(Globals::Fragment, helperInvocation), routine->helperInvocation);
2620 				break;
2621 			}
2622 			case spv::ExecutionModelVertex:
2623 			{
2624 				auto vertex = globals + OFFSET(Globals, vertex);
2625 				store(vertex + OFFSET(Globals::Vertex, viewIndex), routine->viewID);
2626 				store(vertex + OFFSET(Globals::Vertex, instanceIndex), routine->instanceID);
2627 				store(vertex + OFFSET(Globals::Vertex, vertexIndex), routine->vertexIndex);
2628 				break;
2629 			}
2630 			default:
2631 				break;
2632 		}
2633 	}
2634 }
2635 
dbgEndEmit(EmitState * state) const2636 void SpirvShader::dbgEndEmit(EmitState *state) const
2637 {
2638 	auto dbg = impl.debugger;
2639 	if(!dbg) { return; }
2640 
2641 	dbg->finalize();
2642 
2643 	rr::Call(&Impl::Debugger::State::destroy, state->routine->dbgState);
2644 }
2645 
dbgBeginEmitInstruction(InsnIterator insn,EmitState * state) const2646 void SpirvShader::dbgBeginEmitInstruction(InsnIterator insn, EmitState *state) const
2647 {
2648 #	if PRINT_EACH_EMITTED_INSTRUCTION
2649 	{
2650 		auto instruction = spvtools::spvInstructionBinaryToText(
2651 		    vk::SPIRV_VERSION,
2652 		    insn.wordPointer(0),
2653 		    insn.wordCount(),
2654 		    insns.data(),
2655 		    insns.size(),
2656 		    SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
2657 		printf("%s\n", instruction.c_str());
2658 	}
2659 #	endif  // PRINT_EACH_EMITTED_INSTRUCTION
2660 
2661 #	if PRINT_EACH_EXECUTED_INSTRUCTION
2662 	{
2663 		auto instruction = spvtools::spvInstructionBinaryToText(
2664 		    vk::SPIRV_VERSION,
2665 		    insn.wordPointer(0),
2666 		    insn.wordCount(),
2667 		    insns.data(),
2668 		    insns.size(),
2669 		    SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
2670 		rr::Print("{0}\n", instruction);
2671 	}
2672 #	endif  // PRINT_EACH_EXECUTED_INSTRUCTION
2673 
2674 	// Only single line step over statement instructions.
2675 
2676 	if(auto dbg = impl.debugger)
2677 	{
2678 		if(insn.opcode() == spv::OpLabel)
2679 		{
2680 			// Whenever we hit a label, force the next OpLine to be steppable.
2681 			// This handles the case where we have control flow on the same line
2682 			// For example:
2683 			//   while(true) { foo(); }
2684 			// foo() should be repeatedly steppable.
2685 			dbg->setNextSetLocationIsSteppable();
2686 		}
2687 
2688 		if(!dbg->shaderHasDebugInfo)
2689 		{
2690 			// We're emitting debugger logic for SPIR-V.
2691 			if(IsStatement(insn.opcode()))
2692 			{
2693 				auto line = dbg->spirvLineMappings.at(insn.wordPointer(0));
2694 				dbg->setLocation(state, dbg->spirvFile, line);
2695 			}
2696 		}
2697 	}
2698 }
2699 
dbgEndEmitInstruction(InsnIterator insn,EmitState * state) const2700 void SpirvShader::dbgEndEmitInstruction(InsnIterator insn, EmitState *state) const
2701 {
2702 	auto dbg = impl.debugger;
2703 	if(!dbg) { return; }
2704 
2705 	switch(insn.opcode())
2706 	{
2707 		case spv::OpVariable:
2708 		case spv::OpConstant:  // TODO: Move constants out of shadow memory.
2709 		case spv::OpConstantNull:
2710 		case spv::OpConstantTrue:
2711 		case spv::OpConstantFalse:
2712 		case spv::OpConstantComposite:
2713 			dbg->shadow.create(this, state, insn.resultId());
2714 			break;
2715 		default:
2716 		{
2717 			auto resIt = dbg->results.find(insn.wordPointer(0));
2718 			if(resIt != dbg->results.end())
2719 			{
2720 				dbg->shadow.create(this, state, resIt->second);
2721 			}
2722 		}
2723 	}
2724 }
2725 
dbgUpdateActiveLaneMask(RValue<SIMD::Int> mask,EmitState * state) const2726 void SpirvShader::dbgUpdateActiveLaneMask(RValue<SIMD::Int> mask, EmitState *state) const
2727 {
2728 	auto dbg = impl.debugger;
2729 	if(!dbg) { return; }
2730 
2731 	auto dbgState = state->routine->dbgState;
2732 	auto globals = dbgState + OFFSET(Impl::Debugger::State, globals);
2733 	store(globals + OFFSET(Impl::Debugger::State::Globals, activeLaneMask), mask);
2734 }
2735 
dbgDeclareResult(const InsnIterator & insn,Object::ID resultId) const2736 void SpirvShader::dbgDeclareResult(const InsnIterator &insn, Object::ID resultId) const
2737 {
2738 	auto dbg = impl.debugger;
2739 	if(!dbg) { return; }
2740 
2741 	dbg->results.emplace(insn.wordPointer(0), resultId);
2742 }
2743 
EmitLine(InsnIterator insn,EmitState * state) const2744 SpirvShader::EmitResult SpirvShader::EmitLine(InsnIterator insn, EmitState *state) const
2745 {
2746 	if(auto dbg = impl.debugger)
2747 	{
2748 		auto path = getString(insn.word(1));
2749 		auto line = insn.word(2);
2750 		dbg->setLocation(state, path.c_str(), line);
2751 	}
2752 	return EmitResult::Continue;
2753 }
2754 
DefineOpenCLDebugInfo100(const InsnIterator & insn)2755 void SpirvShader::DefineOpenCLDebugInfo100(const InsnIterator &insn)
2756 {
2757 #	if PRINT_EACH_DEFINED_DBG_INSTRUCTION
2758 	{
2759 		auto instruction = spvtools::spvInstructionBinaryToText(
2760 		    vk::SPIRV_VERSION,
2761 		    insn.wordPointer(0),
2762 		    insn.wordCount(),
2763 		    insns.data(),
2764 		    insns.size(),
2765 		    SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
2766 		printf("%s\n", instruction.c_str());
2767 	}
2768 #	endif  // PRINT_EACH_DEFINED_DBG_INSTRUCTION
2769 
2770 	auto dbg = impl.debugger;
2771 	if(!dbg) { return; }
2772 
2773 	dbg->process(insn, nullptr, Impl::Debugger::Pass::Define);
2774 }
2775 
EmitOpenCLDebugInfo100(InsnIterator insn,EmitState * state) const2776 SpirvShader::EmitResult SpirvShader::EmitOpenCLDebugInfo100(InsnIterator insn, EmitState *state) const
2777 {
2778 	if(auto dbg = impl.debugger)
2779 	{
2780 		dbg->process(insn, state, Impl::Debugger::Pass::Emit);
2781 	}
2782 	return EmitResult::Continue;
2783 }
2784 
2785 }  // namespace sw
2786 
2787 #else  // ENABLE_VK_DEBUGGER
2788 
2789 // Stub implementations of the dbgXXX functions.
2790 namespace sw {
2791 
dbgInit(const std::shared_ptr<vk::dbg::Context> & dbgctx)2792 void SpirvShader::dbgInit(const std::shared_ptr<vk::dbg::Context> &dbgctx) {}
dbgTerm()2793 void SpirvShader::dbgTerm() {}
dbgCreateFile()2794 void SpirvShader::dbgCreateFile() {}
dbgBeginEmit(EmitState * state) const2795 void SpirvShader::dbgBeginEmit(EmitState *state) const {}
dbgEndEmit(EmitState * state) const2796 void SpirvShader::dbgEndEmit(EmitState *state) const {}
dbgBeginEmitInstruction(InsnIterator insn,EmitState * state) const2797 void SpirvShader::dbgBeginEmitInstruction(InsnIterator insn, EmitState *state) const {}
dbgEndEmitInstruction(InsnIterator insn,EmitState * state) const2798 void SpirvShader::dbgEndEmitInstruction(InsnIterator insn, EmitState *state) const {}
dbgExposeIntermediate(Object::ID id,EmitState * state) const2799 void SpirvShader::dbgExposeIntermediate(Object::ID id, EmitState *state) const {}
dbgUpdateActiveLaneMask(RValue<SIMD::Int> mask,EmitState * state) const2800 void SpirvShader::dbgUpdateActiveLaneMask(RValue<SIMD::Int> mask, EmitState *state) const {}
dbgDeclareResult(const InsnIterator & insn,Object::ID resultId) const2801 void SpirvShader::dbgDeclareResult(const InsnIterator &insn, Object::ID resultId) const {}
2802 
DefineOpenCLDebugInfo100(const InsnIterator & insn)2803 void SpirvShader::DefineOpenCLDebugInfo100(const InsnIterator &insn) {}
2804 
EmitOpenCLDebugInfo100(InsnIterator insn,EmitState * state) const2805 SpirvShader::EmitResult SpirvShader::EmitOpenCLDebugInfo100(InsnIterator insn, EmitState *state) const
2806 {
2807 	return EmitResult::Continue;
2808 }
2809 
EmitLine(InsnIterator insn,EmitState * state) const2810 SpirvShader::EmitResult SpirvShader::EmitLine(InsnIterator insn, EmitState *state) const
2811 {
2812 	return EmitResult::Continue;
2813 }
2814 
2815 }  // namespace sw
2816 
2817 #endif  // ENABLE_VK_DEBUGGER
2818