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