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