xref: /aosp_15_r20/external/swiftshader/src/Vulkan/Debug/Server.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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 "Server.hpp"
16*03ce13f7SAndroid Build Coastguard Worker 
17*03ce13f7SAndroid Build Coastguard Worker #include "Context.hpp"
18*03ce13f7SAndroid Build Coastguard Worker #include "EventListener.hpp"
19*03ce13f7SAndroid Build Coastguard Worker #include "File.hpp"
20*03ce13f7SAndroid Build Coastguard Worker #include "Thread.hpp"
21*03ce13f7SAndroid Build Coastguard Worker #include "Variable.hpp"
22*03ce13f7SAndroid Build Coastguard Worker 
23*03ce13f7SAndroid Build Coastguard Worker #include "dap/network.h"
24*03ce13f7SAndroid Build Coastguard Worker #include "dap/protocol.h"
25*03ce13f7SAndroid Build Coastguard Worker #include "dap/session.h"
26*03ce13f7SAndroid Build Coastguard Worker #include "marl/waitgroup.h"
27*03ce13f7SAndroid Build Coastguard Worker 
28*03ce13f7SAndroid Build Coastguard Worker #include <thread>
29*03ce13f7SAndroid Build Coastguard Worker #include <unordered_set>
30*03ce13f7SAndroid Build Coastguard Worker 
31*03ce13f7SAndroid Build Coastguard Worker // Switch for controlling DAP debug logging
32*03ce13f7SAndroid Build Coastguard Worker #define ENABLE_DAP_LOGGING 0
33*03ce13f7SAndroid Build Coastguard Worker 
34*03ce13f7SAndroid Build Coastguard Worker #if ENABLE_DAP_LOGGING
35*03ce13f7SAndroid Build Coastguard Worker #	define DAP_LOG(msg, ...) printf(msg "\n", ##__VA_ARGS__)
36*03ce13f7SAndroid Build Coastguard Worker #else
37*03ce13f7SAndroid Build Coastguard Worker #	define DAP_LOG(...) \
38*03ce13f7SAndroid Build Coastguard Worker 		do               \
39*03ce13f7SAndroid Build Coastguard Worker 		{                \
40*03ce13f7SAndroid Build Coastguard Worker 		} while(false)
41*03ce13f7SAndroid Build Coastguard Worker #endif
42*03ce13f7SAndroid Build Coastguard Worker 
43*03ce13f7SAndroid Build Coastguard Worker namespace vk {
44*03ce13f7SAndroid Build Coastguard Worker namespace dbg {
45*03ce13f7SAndroid Build Coastguard Worker 
46*03ce13f7SAndroid Build Coastguard Worker class Server::Impl : public Server, public ServerEventListener
47*03ce13f7SAndroid Build Coastguard Worker {
48*03ce13f7SAndroid Build Coastguard Worker public:
49*03ce13f7SAndroid Build Coastguard Worker 	Impl(const std::shared_ptr<Context> &ctx, int port);
50*03ce13f7SAndroid Build Coastguard Worker 	~Impl();
51*03ce13f7SAndroid Build Coastguard Worker 
52*03ce13f7SAndroid Build Coastguard Worker 	// EventListener
53*03ce13f7SAndroid Build Coastguard Worker 	void onThreadStarted(ID<Thread>) override;
54*03ce13f7SAndroid Build Coastguard Worker 	void onThreadStepped(ID<Thread>) override;
55*03ce13f7SAndroid Build Coastguard Worker 	void onLineBreakpointHit(ID<Thread>) override;
56*03ce13f7SAndroid Build Coastguard Worker 	void onFunctionBreakpointHit(ID<Thread>) override;
57*03ce13f7SAndroid Build Coastguard Worker 
58*03ce13f7SAndroid Build Coastguard Worker 	dap::Scope scope(Context::Lock &lock, const char *type, Scope *);
59*03ce13f7SAndroid Build Coastguard Worker 	dap::Source source(File *);
60*03ce13f7SAndroid Build Coastguard Worker 	std::shared_ptr<File> file(const dap::Source &source);
61*03ce13f7SAndroid Build Coastguard Worker 
62*03ce13f7SAndroid Build Coastguard Worker 	const std::shared_ptr<Context> ctx;
63*03ce13f7SAndroid Build Coastguard Worker 	const std::unique_ptr<dap::net::Server> server;
64*03ce13f7SAndroid Build Coastguard Worker 	const std::unique_ptr<dap::Session> session;
65*03ce13f7SAndroid Build Coastguard Worker 	std::atomic<bool> clientIsVisualStudio = { false };
66*03ce13f7SAndroid Build Coastguard Worker };
67*03ce13f7SAndroid Build Coastguard Worker 
Impl(const std::shared_ptr<Context> & context,int port)68*03ce13f7SAndroid Build Coastguard Worker Server::Impl::Impl(const std::shared_ptr<Context> &context, int port)
69*03ce13f7SAndroid Build Coastguard Worker     : ctx(context)
70*03ce13f7SAndroid Build Coastguard Worker     , server(dap::net::Server::create())
71*03ce13f7SAndroid Build Coastguard Worker     , session(dap::Session::create())
72*03ce13f7SAndroid Build Coastguard Worker {
73*03ce13f7SAndroid Build Coastguard Worker 	session->registerHandler([](const dap::DisconnectRequest &req) {
74*03ce13f7SAndroid Build Coastguard Worker 		DAP_LOG("DisconnectRequest receieved");
75*03ce13f7SAndroid Build Coastguard Worker 		return dap::DisconnectResponse();
76*03ce13f7SAndroid Build Coastguard Worker 	});
77*03ce13f7SAndroid Build Coastguard Worker 
78*03ce13f7SAndroid Build Coastguard Worker 	session->registerHandler([&](const dap::InitializeRequest &req) {
79*03ce13f7SAndroid Build Coastguard Worker 		DAP_LOG("InitializeRequest receieved");
80*03ce13f7SAndroid Build Coastguard Worker 		dap::InitializeResponse response;
81*03ce13f7SAndroid Build Coastguard Worker 		response.supportsFunctionBreakpoints = true;
82*03ce13f7SAndroid Build Coastguard Worker 		response.supportsConfigurationDoneRequest = true;
83*03ce13f7SAndroid Build Coastguard Worker 		response.supportsEvaluateForHovers = true;
84*03ce13f7SAndroid Build Coastguard Worker 		clientIsVisualStudio = (req.clientID.value("") == "visualstudio");
85*03ce13f7SAndroid Build Coastguard Worker 		return response;
86*03ce13f7SAndroid Build Coastguard Worker 	});
87*03ce13f7SAndroid Build Coastguard Worker 
88*03ce13f7SAndroid Build Coastguard Worker 	session->registerSentHandler(
89*03ce13f7SAndroid Build Coastguard Worker 	    [&](const dap::ResponseOrError<dap::InitializeResponse> &response) {
90*03ce13f7SAndroid Build Coastguard Worker 		    DAP_LOG("InitializeResponse sent");
91*03ce13f7SAndroid Build Coastguard Worker 		    session->send(dap::InitializedEvent());
92*03ce13f7SAndroid Build Coastguard Worker 	    });
93*03ce13f7SAndroid Build Coastguard Worker 
94*03ce13f7SAndroid Build Coastguard Worker 	session->registerHandler([](const dap::SetExceptionBreakpointsRequest &req) {
95*03ce13f7SAndroid Build Coastguard Worker 		DAP_LOG("SetExceptionBreakpointsRequest receieved");
96*03ce13f7SAndroid Build Coastguard Worker 		dap::SetExceptionBreakpointsResponse response;
97*03ce13f7SAndroid Build Coastguard Worker 		return response;
98*03ce13f7SAndroid Build Coastguard Worker 	});
99*03ce13f7SAndroid Build Coastguard Worker 
100*03ce13f7SAndroid Build Coastguard Worker 	session->registerHandler(
101*03ce13f7SAndroid Build Coastguard Worker 	    [this](const dap::SetFunctionBreakpointsRequest &req) {
102*03ce13f7SAndroid Build Coastguard Worker 		    DAP_LOG("SetFunctionBreakpointsRequest receieved");
103*03ce13f7SAndroid Build Coastguard Worker 
104*03ce13f7SAndroid Build Coastguard Worker 		    dap::SetFunctionBreakpointsResponse response;
105*03ce13f7SAndroid Build Coastguard Worker 		    for(const auto &reqBP : req.breakpoints)
106*03ce13f7SAndroid Build Coastguard Worker 		    {
107*03ce13f7SAndroid Build Coastguard Worker 			    DAP_LOG("Setting breakpoint for function '%s'", reqBP.name.c_str());
108*03ce13f7SAndroid Build Coastguard Worker 
109*03ce13f7SAndroid Build Coastguard Worker 			    bool verified = false;
110*03ce13f7SAndroid Build Coastguard Worker 			    ctx->clientEventBroadcast()->onSetBreakpoint(reqBP.name, verified);
111*03ce13f7SAndroid Build Coastguard Worker 
112*03ce13f7SAndroid Build Coastguard Worker 			    dap::Breakpoint resBP{};
113*03ce13f7SAndroid Build Coastguard Worker 			    resBP.verified = verified;
114*03ce13f7SAndroid Build Coastguard Worker 			    response.breakpoints.emplace_back(std::move(resBP));
115*03ce13f7SAndroid Build Coastguard Worker 		    }
116*03ce13f7SAndroid Build Coastguard Worker 		    {
117*03ce13f7SAndroid Build Coastguard Worker 			    auto lock = ctx->lock();
118*03ce13f7SAndroid Build Coastguard Worker 			    lock.clearFunctionBreakpoints();
119*03ce13f7SAndroid Build Coastguard Worker 			    for(const auto &reqBP : req.breakpoints)
120*03ce13f7SAndroid Build Coastguard Worker 			    {
121*03ce13f7SAndroid Build Coastguard Worker 				    lock.addFunctionBreakpoint(reqBP.name.c_str());
122*03ce13f7SAndroid Build Coastguard Worker 			    }
123*03ce13f7SAndroid Build Coastguard Worker 		    }
124*03ce13f7SAndroid Build Coastguard Worker 		    ctx->clientEventBroadcast()->onBreakpointsChanged();
125*03ce13f7SAndroid Build Coastguard Worker 		    return response;
126*03ce13f7SAndroid Build Coastguard Worker 	    });
127*03ce13f7SAndroid Build Coastguard Worker 
128*03ce13f7SAndroid Build Coastguard Worker 	session->registerHandler(
129*03ce13f7SAndroid Build Coastguard Worker 	    [this](const dap::SetBreakpointsRequest &req)
130*03ce13f7SAndroid Build Coastguard Worker 	        -> dap::ResponseOrError<dap::SetBreakpointsResponse> {
131*03ce13f7SAndroid Build Coastguard Worker 		    DAP_LOG("SetBreakpointsRequest receieved");
132*03ce13f7SAndroid Build Coastguard Worker 
133*03ce13f7SAndroid Build Coastguard Worker 		    size_t numBreakpoints = 0;
134*03ce13f7SAndroid Build Coastguard Worker 		    if(req.breakpoints.has_value())
135*03ce13f7SAndroid Build Coastguard Worker 		    {
136*03ce13f7SAndroid Build Coastguard Worker 			    const auto &breakpoints = req.breakpoints.value();
137*03ce13f7SAndroid Build Coastguard Worker 			    numBreakpoints = breakpoints.size();
138*03ce13f7SAndroid Build Coastguard Worker 			    if(auto file = this->file(req.source))
139*03ce13f7SAndroid Build Coastguard Worker 			    {
140*03ce13f7SAndroid Build Coastguard Worker 				    dap::SetBreakpointsResponse response;
141*03ce13f7SAndroid Build Coastguard Worker 				    file->clearBreakpoints();
142*03ce13f7SAndroid Build Coastguard Worker 				    for(size_t i = 0; i < numBreakpoints; i++)
143*03ce13f7SAndroid Build Coastguard Worker 				    {
144*03ce13f7SAndroid Build Coastguard Worker 					    auto &reqBP = breakpoints[i];
145*03ce13f7SAndroid Build Coastguard Worker 					    Location location{ file, static_cast<int>(reqBP.line) };
146*03ce13f7SAndroid Build Coastguard Worker 					    file->addBreakpoint(location.line);
147*03ce13f7SAndroid Build Coastguard Worker 
148*03ce13f7SAndroid Build Coastguard Worker 					    bool verified = false;
149*03ce13f7SAndroid Build Coastguard Worker 					    ctx->clientEventBroadcast()->onSetBreakpoint(location, verified);
150*03ce13f7SAndroid Build Coastguard Worker 
151*03ce13f7SAndroid Build Coastguard Worker 					    dap::Breakpoint respBP;
152*03ce13f7SAndroid Build Coastguard Worker 					    respBP.verified = verified;
153*03ce13f7SAndroid Build Coastguard Worker 					    respBP.source = req.source;
154*03ce13f7SAndroid Build Coastguard Worker 					    response.breakpoints.push_back(respBP);
155*03ce13f7SAndroid Build Coastguard Worker 				    }
156*03ce13f7SAndroid Build Coastguard Worker 				    ctx->clientEventBroadcast()->onBreakpointsChanged();
157*03ce13f7SAndroid Build Coastguard Worker 				    return response;
158*03ce13f7SAndroid Build Coastguard Worker 			    }
159*03ce13f7SAndroid Build Coastguard Worker 
160*03ce13f7SAndroid Build Coastguard Worker 			    if(req.source.name.has_value())
161*03ce13f7SAndroid Build Coastguard Worker 			    {
162*03ce13f7SAndroid Build Coastguard Worker 				    std::vector<int> lines;
163*03ce13f7SAndroid Build Coastguard Worker 				    lines.reserve(breakpoints.size());
164*03ce13f7SAndroid Build Coastguard Worker 				    for(const auto &bp : breakpoints)
165*03ce13f7SAndroid Build Coastguard Worker 				    {
166*03ce13f7SAndroid Build Coastguard Worker 					    lines.push_back(bp.line);
167*03ce13f7SAndroid Build Coastguard Worker 				    }
168*03ce13f7SAndroid Build Coastguard Worker 				    ctx->lock().addPendingBreakpoints(req.source.name.value(),
169*03ce13f7SAndroid Build Coastguard Worker 				                                      lines);
170*03ce13f7SAndroid Build Coastguard Worker 			    }
171*03ce13f7SAndroid Build Coastguard Worker 		    }
172*03ce13f7SAndroid Build Coastguard Worker 
173*03ce13f7SAndroid Build Coastguard Worker 		    // Generic response.
174*03ce13f7SAndroid Build Coastguard Worker 		    dap::SetBreakpointsResponse response;
175*03ce13f7SAndroid Build Coastguard Worker 		    for(size_t i = 0; i < numBreakpoints; i++)
176*03ce13f7SAndroid Build Coastguard Worker 		    {
177*03ce13f7SAndroid Build Coastguard Worker 			    dap::Breakpoint bp;
178*03ce13f7SAndroid Build Coastguard Worker 			    bp.verified = false;
179*03ce13f7SAndroid Build Coastguard Worker 			    bp.source = req.source;
180*03ce13f7SAndroid Build Coastguard Worker 			    response.breakpoints.push_back(bp);
181*03ce13f7SAndroid Build Coastguard Worker 		    }
182*03ce13f7SAndroid Build Coastguard Worker 		    ctx->clientEventBroadcast()->onBreakpointsChanged();
183*03ce13f7SAndroid Build Coastguard Worker 		    return response;
184*03ce13f7SAndroid Build Coastguard Worker 	    });
185*03ce13f7SAndroid Build Coastguard Worker 
186*03ce13f7SAndroid Build Coastguard Worker 	session->registerHandler([this](const dap::ThreadsRequest &req) {
187*03ce13f7SAndroid Build Coastguard Worker 		DAP_LOG("ThreadsRequest receieved");
188*03ce13f7SAndroid Build Coastguard Worker 		auto lock = ctx->lock();
189*03ce13f7SAndroid Build Coastguard Worker 		dap::ThreadsResponse response;
190*03ce13f7SAndroid Build Coastguard Worker 		for(auto thread : lock.threads())
191*03ce13f7SAndroid Build Coastguard Worker 		{
192*03ce13f7SAndroid Build Coastguard Worker 			std::string name = thread->name();
193*03ce13f7SAndroid Build Coastguard Worker 			if(clientIsVisualStudio)
194*03ce13f7SAndroid Build Coastguard Worker 			{
195*03ce13f7SAndroid Build Coastguard Worker 				// WORKAROUND: https://github.com/microsoft/VSDebugAdapterHost/issues/15
196*03ce13f7SAndroid Build Coastguard Worker 				for(size_t i = 0; i < name.size(); i++)
197*03ce13f7SAndroid Build Coastguard Worker 				{
198*03ce13f7SAndroid Build Coastguard Worker 					if(name[i] == '.')
199*03ce13f7SAndroid Build Coastguard Worker 					{
200*03ce13f7SAndroid Build Coastguard Worker 						name[i] = '_';
201*03ce13f7SAndroid Build Coastguard Worker 					}
202*03ce13f7SAndroid Build Coastguard Worker 				}
203*03ce13f7SAndroid Build Coastguard Worker 			}
204*03ce13f7SAndroid Build Coastguard Worker 
205*03ce13f7SAndroid Build Coastguard Worker 			dap::Thread out;
206*03ce13f7SAndroid Build Coastguard Worker 			out.id = thread->id.value();
207*03ce13f7SAndroid Build Coastguard Worker 			out.name = name;
208*03ce13f7SAndroid Build Coastguard Worker 			response.threads.push_back(out);
209*03ce13f7SAndroid Build Coastguard Worker 		};
210*03ce13f7SAndroid Build Coastguard Worker 		return response;
211*03ce13f7SAndroid Build Coastguard Worker 	});
212*03ce13f7SAndroid Build Coastguard Worker 
213*03ce13f7SAndroid Build Coastguard Worker 	session->registerHandler(
214*03ce13f7SAndroid Build Coastguard Worker 	    [this](const dap::StackTraceRequest &req)
215*03ce13f7SAndroid Build Coastguard Worker 	        -> dap::ResponseOrError<dap::StackTraceResponse> {
216*03ce13f7SAndroid Build Coastguard Worker 		    DAP_LOG("StackTraceRequest receieved");
217*03ce13f7SAndroid Build Coastguard Worker 
218*03ce13f7SAndroid Build Coastguard Worker 		    auto lock = ctx->lock();
219*03ce13f7SAndroid Build Coastguard Worker 		    auto thread = lock.get(Thread::ID(req.threadId));
220*03ce13f7SAndroid Build Coastguard Worker 		    if(!thread)
221*03ce13f7SAndroid Build Coastguard Worker 		    {
222*03ce13f7SAndroid Build Coastguard Worker 			    return dap::Error("Thread %d not found", req.threadId);
223*03ce13f7SAndroid Build Coastguard Worker 		    }
224*03ce13f7SAndroid Build Coastguard Worker 
225*03ce13f7SAndroid Build Coastguard Worker 		    auto stack = thread->stack();
226*03ce13f7SAndroid Build Coastguard Worker 
227*03ce13f7SAndroid Build Coastguard Worker 		    dap::StackTraceResponse response;
228*03ce13f7SAndroid Build Coastguard Worker 		    response.totalFrames = stack.size();
229*03ce13f7SAndroid Build Coastguard Worker 		    response.stackFrames.reserve(stack.size());
230*03ce13f7SAndroid Build Coastguard Worker 		    for(int i = static_cast<int>(stack.size()) - 1; i >= 0; i--)
231*03ce13f7SAndroid Build Coastguard Worker 		    {
232*03ce13f7SAndroid Build Coastguard Worker 			    const auto &frame = stack[i];
233*03ce13f7SAndroid Build Coastguard Worker 			    const auto &loc = frame.location;
234*03ce13f7SAndroid Build Coastguard Worker 			    dap::StackFrame sf;
235*03ce13f7SAndroid Build Coastguard Worker 			    sf.column = 0;
236*03ce13f7SAndroid Build Coastguard Worker 			    sf.id = frame.id.value();
237*03ce13f7SAndroid Build Coastguard Worker 			    sf.name = frame.function;
238*03ce13f7SAndroid Build Coastguard Worker 			    sf.line = loc.line;
239*03ce13f7SAndroid Build Coastguard Worker 			    if(loc.file)
240*03ce13f7SAndroid Build Coastguard Worker 			    {
241*03ce13f7SAndroid Build Coastguard Worker 				    sf.source = source(loc.file.get());
242*03ce13f7SAndroid Build Coastguard Worker 			    }
243*03ce13f7SAndroid Build Coastguard Worker 			    response.stackFrames.emplace_back(std::move(sf));
244*03ce13f7SAndroid Build Coastguard Worker 		    }
245*03ce13f7SAndroid Build Coastguard Worker 		    return response;
246*03ce13f7SAndroid Build Coastguard Worker 	    });
247*03ce13f7SAndroid Build Coastguard Worker 
248*03ce13f7SAndroid Build Coastguard Worker 	session->registerHandler([this](const dap::ScopesRequest &req)
249*03ce13f7SAndroid Build Coastguard Worker 	                             -> dap::ResponseOrError<dap::ScopesResponse> {
250*03ce13f7SAndroid Build Coastguard Worker 		DAP_LOG("ScopesRequest receieved");
251*03ce13f7SAndroid Build Coastguard Worker 
252*03ce13f7SAndroid Build Coastguard Worker 		auto lock = ctx->lock();
253*03ce13f7SAndroid Build Coastguard Worker 		auto frame = lock.get(Frame::ID(req.frameId));
254*03ce13f7SAndroid Build Coastguard Worker 		if(!frame)
255*03ce13f7SAndroid Build Coastguard Worker 		{
256*03ce13f7SAndroid Build Coastguard Worker 			return dap::Error("Frame %d not found", req.frameId);
257*03ce13f7SAndroid Build Coastguard Worker 		}
258*03ce13f7SAndroid Build Coastguard Worker 
259*03ce13f7SAndroid Build Coastguard Worker 		dap::ScopesResponse response;
260*03ce13f7SAndroid Build Coastguard Worker 		response.scopes = {
261*03ce13f7SAndroid Build Coastguard Worker 			scope(lock, "locals", frame->locals.get()),
262*03ce13f7SAndroid Build Coastguard Worker 			scope(lock, "arguments", frame->arguments.get()),
263*03ce13f7SAndroid Build Coastguard Worker 			scope(lock, "registers", frame->registers.get()),
264*03ce13f7SAndroid Build Coastguard Worker 		};
265*03ce13f7SAndroid Build Coastguard Worker 		return response;
266*03ce13f7SAndroid Build Coastguard Worker 	});
267*03ce13f7SAndroid Build Coastguard Worker 
268*03ce13f7SAndroid Build Coastguard Worker 	session->registerHandler([this](const dap::VariablesRequest &req)
269*03ce13f7SAndroid Build Coastguard Worker 	                             -> dap::ResponseOrError<dap::VariablesResponse> {
270*03ce13f7SAndroid Build Coastguard Worker 		DAP_LOG("VariablesRequest receieved");
271*03ce13f7SAndroid Build Coastguard Worker 
272*03ce13f7SAndroid Build Coastguard Worker 		auto lock = ctx->lock();
273*03ce13f7SAndroid Build Coastguard Worker 		auto vars = lock.get(Variables::ID(req.variablesReference));
274*03ce13f7SAndroid Build Coastguard Worker 		if(!vars)
275*03ce13f7SAndroid Build Coastguard Worker 		{
276*03ce13f7SAndroid Build Coastguard Worker 			return dap::Error("VariablesReference %d not found",
277*03ce13f7SAndroid Build Coastguard Worker 			                  int(req.variablesReference));
278*03ce13f7SAndroid Build Coastguard Worker 		}
279*03ce13f7SAndroid Build Coastguard Worker 
280*03ce13f7SAndroid Build Coastguard Worker 		dap::VariablesResponse response;
281*03ce13f7SAndroid Build Coastguard Worker 		vars->foreach(req.start.value(0), req.count.value(~0), [&](const Variable &v) {
282*03ce13f7SAndroid Build Coastguard Worker 			dap::Variable out;
283*03ce13f7SAndroid Build Coastguard Worker 			out.evaluateName = v.name;
284*03ce13f7SAndroid Build Coastguard Worker 			out.name = v.name;
285*03ce13f7SAndroid Build Coastguard Worker 			out.type = v.value->type();
286*03ce13f7SAndroid Build Coastguard Worker 			out.value = v.value->get();
287*03ce13f7SAndroid Build Coastguard Worker 			if(auto children = v.value->children())
288*03ce13f7SAndroid Build Coastguard Worker 			{
289*03ce13f7SAndroid Build Coastguard Worker 				out.variablesReference = children->id.value();
290*03ce13f7SAndroid Build Coastguard Worker 				lock.track(children);
291*03ce13f7SAndroid Build Coastguard Worker 			}
292*03ce13f7SAndroid Build Coastguard Worker 			response.variables.push_back(out);
293*03ce13f7SAndroid Build Coastguard Worker 			return true;
294*03ce13f7SAndroid Build Coastguard Worker 		});
295*03ce13f7SAndroid Build Coastguard Worker 		return response;
296*03ce13f7SAndroid Build Coastguard Worker 	});
297*03ce13f7SAndroid Build Coastguard Worker 
298*03ce13f7SAndroid Build Coastguard Worker 	session->registerHandler([this](const dap::SourceRequest &req)
299*03ce13f7SAndroid Build Coastguard Worker 	                             -> dap::ResponseOrError<dap::SourceResponse> {
300*03ce13f7SAndroid Build Coastguard Worker 		DAP_LOG("SourceRequest receieved");
301*03ce13f7SAndroid Build Coastguard Worker 
302*03ce13f7SAndroid Build Coastguard Worker 		dap::SourceResponse response;
303*03ce13f7SAndroid Build Coastguard Worker 		uint64_t id = req.sourceReference;
304*03ce13f7SAndroid Build Coastguard Worker 
305*03ce13f7SAndroid Build Coastguard Worker 		auto lock = ctx->lock();
306*03ce13f7SAndroid Build Coastguard Worker 		auto file = lock.get(File::ID(id));
307*03ce13f7SAndroid Build Coastguard Worker 		if(!file)
308*03ce13f7SAndroid Build Coastguard Worker 		{
309*03ce13f7SAndroid Build Coastguard Worker 			return dap::Error("Source %d not found", id);
310*03ce13f7SAndroid Build Coastguard Worker 		}
311*03ce13f7SAndroid Build Coastguard Worker 		response.content = file->source;
312*03ce13f7SAndroid Build Coastguard Worker 		return response;
313*03ce13f7SAndroid Build Coastguard Worker 	});
314*03ce13f7SAndroid Build Coastguard Worker 
315*03ce13f7SAndroid Build Coastguard Worker 	session->registerHandler([this](const dap::PauseRequest &req)
316*03ce13f7SAndroid Build Coastguard Worker 	                             -> dap::ResponseOrError<dap::PauseResponse> {
317*03ce13f7SAndroid Build Coastguard Worker 		DAP_LOG("PauseRequest receieved");
318*03ce13f7SAndroid Build Coastguard Worker 
319*03ce13f7SAndroid Build Coastguard Worker 		dap::StoppedEvent event;
320*03ce13f7SAndroid Build Coastguard Worker 		event.reason = "pause";
321*03ce13f7SAndroid Build Coastguard Worker 
322*03ce13f7SAndroid Build Coastguard Worker 		auto lock = ctx->lock();
323*03ce13f7SAndroid Build Coastguard Worker 		if(auto thread = lock.get(Thread::ID(req.threadId)))
324*03ce13f7SAndroid Build Coastguard Worker 		{
325*03ce13f7SAndroid Build Coastguard Worker 			thread->pause();
326*03ce13f7SAndroid Build Coastguard Worker 			event.threadId = req.threadId;
327*03ce13f7SAndroid Build Coastguard Worker 		}
328*03ce13f7SAndroid Build Coastguard Worker 		else
329*03ce13f7SAndroid Build Coastguard Worker 		{
330*03ce13f7SAndroid Build Coastguard Worker 			auto threads = lock.threads();
331*03ce13f7SAndroid Build Coastguard Worker 			for(auto thread : threads)
332*03ce13f7SAndroid Build Coastguard Worker 			{
333*03ce13f7SAndroid Build Coastguard Worker 				thread->pause();
334*03ce13f7SAndroid Build Coastguard Worker 			}
335*03ce13f7SAndroid Build Coastguard Worker 			event.allThreadsStopped = true;
336*03ce13f7SAndroid Build Coastguard Worker 
337*03ce13f7SAndroid Build Coastguard Worker 			// Workaround for
338*03ce13f7SAndroid Build Coastguard Worker 			// https://github.com/microsoft/VSDebugAdapterHost/issues/11
339*03ce13f7SAndroid Build Coastguard Worker 			if(clientIsVisualStudio && !threads.empty())
340*03ce13f7SAndroid Build Coastguard Worker 			{
341*03ce13f7SAndroid Build Coastguard Worker 				event.threadId = threads.front()->id.value();
342*03ce13f7SAndroid Build Coastguard Worker 			}
343*03ce13f7SAndroid Build Coastguard Worker 		}
344*03ce13f7SAndroid Build Coastguard Worker 
345*03ce13f7SAndroid Build Coastguard Worker 		session->send(event);
346*03ce13f7SAndroid Build Coastguard Worker 
347*03ce13f7SAndroid Build Coastguard Worker 		dap::PauseResponse response;
348*03ce13f7SAndroid Build Coastguard Worker 		return response;
349*03ce13f7SAndroid Build Coastguard Worker 	});
350*03ce13f7SAndroid Build Coastguard Worker 
351*03ce13f7SAndroid Build Coastguard Worker 	session->registerHandler([this](const dap::ContinueRequest &req)
352*03ce13f7SAndroid Build Coastguard Worker 	                             -> dap::ResponseOrError<dap::ContinueResponse> {
353*03ce13f7SAndroid Build Coastguard Worker 		DAP_LOG("ContinueRequest receieved");
354*03ce13f7SAndroid Build Coastguard Worker 
355*03ce13f7SAndroid Build Coastguard Worker 		dap::ContinueResponse response;
356*03ce13f7SAndroid Build Coastguard Worker 
357*03ce13f7SAndroid Build Coastguard Worker 		auto lock = ctx->lock();
358*03ce13f7SAndroid Build Coastguard Worker 		if(auto thread = lock.get(Thread::ID(req.threadId)))
359*03ce13f7SAndroid Build Coastguard Worker 		{
360*03ce13f7SAndroid Build Coastguard Worker 			thread->resume();
361*03ce13f7SAndroid Build Coastguard Worker 			response.allThreadsContinued = false;
362*03ce13f7SAndroid Build Coastguard Worker 		}
363*03ce13f7SAndroid Build Coastguard Worker 		else
364*03ce13f7SAndroid Build Coastguard Worker 		{
365*03ce13f7SAndroid Build Coastguard Worker 			for(auto it : lock.threads())
366*03ce13f7SAndroid Build Coastguard Worker 			{
367*03ce13f7SAndroid Build Coastguard Worker 				thread->resume();
368*03ce13f7SAndroid Build Coastguard Worker 			}
369*03ce13f7SAndroid Build Coastguard Worker 			response.allThreadsContinued = true;
370*03ce13f7SAndroid Build Coastguard Worker 		}
371*03ce13f7SAndroid Build Coastguard Worker 
372*03ce13f7SAndroid Build Coastguard Worker 		return response;
373*03ce13f7SAndroid Build Coastguard Worker 	});
374*03ce13f7SAndroid Build Coastguard Worker 
375*03ce13f7SAndroid Build Coastguard Worker 	session->registerHandler([this](const dap::NextRequest &req)
376*03ce13f7SAndroid Build Coastguard Worker 	                             -> dap::ResponseOrError<dap::NextResponse> {
377*03ce13f7SAndroid Build Coastguard Worker 		DAP_LOG("NextRequest receieved");
378*03ce13f7SAndroid Build Coastguard Worker 
379*03ce13f7SAndroid Build Coastguard Worker 		auto lock = ctx->lock();
380*03ce13f7SAndroid Build Coastguard Worker 		auto thread = lock.get(Thread::ID(req.threadId));
381*03ce13f7SAndroid Build Coastguard Worker 		if(!thread)
382*03ce13f7SAndroid Build Coastguard Worker 		{
383*03ce13f7SAndroid Build Coastguard Worker 			return dap::Error("Unknown thread %d", int(req.threadId));
384*03ce13f7SAndroid Build Coastguard Worker 		}
385*03ce13f7SAndroid Build Coastguard Worker 
386*03ce13f7SAndroid Build Coastguard Worker 		thread->stepOver();
387*03ce13f7SAndroid Build Coastguard Worker 		return dap::NextResponse();
388*03ce13f7SAndroid Build Coastguard Worker 	});
389*03ce13f7SAndroid Build Coastguard Worker 
390*03ce13f7SAndroid Build Coastguard Worker 	session->registerHandler([this](const dap::StepInRequest &req)
391*03ce13f7SAndroid Build Coastguard Worker 	                             -> dap::ResponseOrError<dap::StepInResponse> {
392*03ce13f7SAndroid Build Coastguard Worker 		DAP_LOG("StepInRequest receieved");
393*03ce13f7SAndroid Build Coastguard Worker 
394*03ce13f7SAndroid Build Coastguard Worker 		auto lock = ctx->lock();
395*03ce13f7SAndroid Build Coastguard Worker 		auto thread = lock.get(Thread::ID(req.threadId));
396*03ce13f7SAndroid Build Coastguard Worker 		if(!thread)
397*03ce13f7SAndroid Build Coastguard Worker 		{
398*03ce13f7SAndroid Build Coastguard Worker 			return dap::Error("Unknown thread %d", int(req.threadId));
399*03ce13f7SAndroid Build Coastguard Worker 		}
400*03ce13f7SAndroid Build Coastguard Worker 
401*03ce13f7SAndroid Build Coastguard Worker 		thread->stepIn();
402*03ce13f7SAndroid Build Coastguard Worker 		return dap::StepInResponse();
403*03ce13f7SAndroid Build Coastguard Worker 	});
404*03ce13f7SAndroid Build Coastguard Worker 
405*03ce13f7SAndroid Build Coastguard Worker 	session->registerHandler([this](const dap::StepOutRequest &req)
406*03ce13f7SAndroid Build Coastguard Worker 	                             -> dap::ResponseOrError<dap::StepOutResponse> {
407*03ce13f7SAndroid Build Coastguard Worker 		DAP_LOG("StepOutRequest receieved");
408*03ce13f7SAndroid Build Coastguard Worker 
409*03ce13f7SAndroid Build Coastguard Worker 		auto lock = ctx->lock();
410*03ce13f7SAndroid Build Coastguard Worker 		auto thread = lock.get(Thread::ID(req.threadId));
411*03ce13f7SAndroid Build Coastguard Worker 		if(!thread)
412*03ce13f7SAndroid Build Coastguard Worker 		{
413*03ce13f7SAndroid Build Coastguard Worker 			return dap::Error("Unknown thread %d", int(req.threadId));
414*03ce13f7SAndroid Build Coastguard Worker 		}
415*03ce13f7SAndroid Build Coastguard Worker 
416*03ce13f7SAndroid Build Coastguard Worker 		thread->stepOut();
417*03ce13f7SAndroid Build Coastguard Worker 		return dap::StepOutResponse();
418*03ce13f7SAndroid Build Coastguard Worker 	});
419*03ce13f7SAndroid Build Coastguard Worker 
420*03ce13f7SAndroid Build Coastguard Worker 	session->registerHandler([this](const dap::EvaluateRequest &req)
421*03ce13f7SAndroid Build Coastguard Worker 	                             -> dap::ResponseOrError<dap::EvaluateResponse> {
422*03ce13f7SAndroid Build Coastguard Worker 		DAP_LOG("EvaluateRequest receieved");
423*03ce13f7SAndroid Build Coastguard Worker 
424*03ce13f7SAndroid Build Coastguard Worker 		auto lock = ctx->lock();
425*03ce13f7SAndroid Build Coastguard Worker 		if(req.frameId.has_value())
426*03ce13f7SAndroid Build Coastguard Worker 		{
427*03ce13f7SAndroid Build Coastguard Worker 			auto frame = lock.get(Frame::ID(req.frameId.value(0)));
428*03ce13f7SAndroid Build Coastguard Worker 			if(!frame)
429*03ce13f7SAndroid Build Coastguard Worker 			{
430*03ce13f7SAndroid Build Coastguard Worker 				return dap::Error("Unknown frame %d", int(req.frameId.value()));
431*03ce13f7SAndroid Build Coastguard Worker 			}
432*03ce13f7SAndroid Build Coastguard Worker 
433*03ce13f7SAndroid Build Coastguard Worker 			auto fmt = FormatFlags::Default;
434*03ce13f7SAndroid Build Coastguard Worker 			auto subfmt = FormatFlags::Default;
435*03ce13f7SAndroid Build Coastguard Worker 
436*03ce13f7SAndroid Build Coastguard Worker 			if(req.context.value("") == "hover")
437*03ce13f7SAndroid Build Coastguard Worker 			{
438*03ce13f7SAndroid Build Coastguard Worker 				subfmt.listPrefix = "\n";
439*03ce13f7SAndroid Build Coastguard Worker 				subfmt.listSuffix = "";
440*03ce13f7SAndroid Build Coastguard Worker 				subfmt.listDelimiter = "\n";
441*03ce13f7SAndroid Build Coastguard Worker 				subfmt.listIndent = "  ";
442*03ce13f7SAndroid Build Coastguard Worker 				fmt.listPrefix = "";
443*03ce13f7SAndroid Build Coastguard Worker 				fmt.listSuffix = "";
444*03ce13f7SAndroid Build Coastguard Worker 				fmt.listDelimiter = "\n";
445*03ce13f7SAndroid Build Coastguard Worker 				fmt.listIndent = "";
446*03ce13f7SAndroid Build Coastguard Worker 				fmt.subListFmt = &subfmt;
447*03ce13f7SAndroid Build Coastguard Worker 			}
448*03ce13f7SAndroid Build Coastguard Worker 
449*03ce13f7SAndroid Build Coastguard Worker 			dap::EvaluateResponse response;
450*03ce13f7SAndroid Build Coastguard Worker 
451*03ce13f7SAndroid Build Coastguard Worker 			std::vector<std::shared_ptr<vk::dbg::Variables>> variables = {
452*03ce13f7SAndroid Build Coastguard Worker 				frame->locals->variables,
453*03ce13f7SAndroid Build Coastguard Worker 				frame->arguments->variables,
454*03ce13f7SAndroid Build Coastguard Worker 				frame->registers->variables,
455*03ce13f7SAndroid Build Coastguard Worker 				frame->hovers->variables,
456*03ce13f7SAndroid Build Coastguard Worker 			};
457*03ce13f7SAndroid Build Coastguard Worker 
458*03ce13f7SAndroid Build Coastguard Worker 			for(const auto &vars : variables)
459*03ce13f7SAndroid Build Coastguard Worker 			{
460*03ce13f7SAndroid Build Coastguard Worker 				if(auto val = vars->get(req.expression))
461*03ce13f7SAndroid Build Coastguard Worker 				{
462*03ce13f7SAndroid Build Coastguard Worker 					response.result = val->get(fmt);
463*03ce13f7SAndroid Build Coastguard Worker 					response.type = val->type();
464*03ce13f7SAndroid Build Coastguard Worker 					return response;
465*03ce13f7SAndroid Build Coastguard Worker 				}
466*03ce13f7SAndroid Build Coastguard Worker 			}
467*03ce13f7SAndroid Build Coastguard Worker 
468*03ce13f7SAndroid Build Coastguard Worker 			// HACK: VSCode does not appear to include the % in %123 tokens
469*03ce13f7SAndroid Build Coastguard Worker 			// TODO: This might be a configuration problem of the SPIRV-Tools
470*03ce13f7SAndroid Build Coastguard Worker 			// spirv-ls plugin. Investigate.
471*03ce13f7SAndroid Build Coastguard Worker 			auto withPercent = "%" + req.expression;
472*03ce13f7SAndroid Build Coastguard Worker 			for(const auto &vars : variables)
473*03ce13f7SAndroid Build Coastguard Worker 			{
474*03ce13f7SAndroid Build Coastguard Worker 				if(auto val = vars->get(withPercent))
475*03ce13f7SAndroid Build Coastguard Worker 				{
476*03ce13f7SAndroid Build Coastguard Worker 					response.result = val->get(fmt);
477*03ce13f7SAndroid Build Coastguard Worker 					response.type = val->type();
478*03ce13f7SAndroid Build Coastguard Worker 					return response;
479*03ce13f7SAndroid Build Coastguard Worker 				}
480*03ce13f7SAndroid Build Coastguard Worker 			}
481*03ce13f7SAndroid Build Coastguard Worker 		}
482*03ce13f7SAndroid Build Coastguard Worker 
483*03ce13f7SAndroid Build Coastguard Worker 		return dap::Error("Could not evaluate expression");
484*03ce13f7SAndroid Build Coastguard Worker 	});
485*03ce13f7SAndroid Build Coastguard Worker 
486*03ce13f7SAndroid Build Coastguard Worker 	session->registerHandler([](const dap::LaunchRequest &req) {
487*03ce13f7SAndroid Build Coastguard Worker 		DAP_LOG("LaunchRequest receieved");
488*03ce13f7SAndroid Build Coastguard Worker 		return dap::LaunchResponse();
489*03ce13f7SAndroid Build Coastguard Worker 	});
490*03ce13f7SAndroid Build Coastguard Worker 
491*03ce13f7SAndroid Build Coastguard Worker 	marl::WaitGroup configurationDone(1);
492*03ce13f7SAndroid Build Coastguard Worker 	session->registerHandler([=](const dap::ConfigurationDoneRequest &req) {
493*03ce13f7SAndroid Build Coastguard Worker 		DAP_LOG("ConfigurationDoneRequest receieved");
494*03ce13f7SAndroid Build Coastguard Worker 		configurationDone.done();
495*03ce13f7SAndroid Build Coastguard Worker 		return dap::ConfigurationDoneResponse();
496*03ce13f7SAndroid Build Coastguard Worker 	});
497*03ce13f7SAndroid Build Coastguard Worker 
498*03ce13f7SAndroid Build Coastguard Worker 	server->start(port, [&](const std::shared_ptr<dap::ReaderWriter> &rw) {
499*03ce13f7SAndroid Build Coastguard Worker 		session->bind(rw);
500*03ce13f7SAndroid Build Coastguard Worker 		ctx->addListener(this);
501*03ce13f7SAndroid Build Coastguard Worker 	});
502*03ce13f7SAndroid Build Coastguard Worker 
503*03ce13f7SAndroid Build Coastguard Worker 	static bool waitForDebugger = getenv("VK_WAIT_FOR_DEBUGGER") != nullptr;
504*03ce13f7SAndroid Build Coastguard Worker 	if(waitForDebugger)
505*03ce13f7SAndroid Build Coastguard Worker 	{
506*03ce13f7SAndroid Build Coastguard Worker 		printf("Waiting for debugger connection...\n");
507*03ce13f7SAndroid Build Coastguard Worker 		configurationDone.wait();
508*03ce13f7SAndroid Build Coastguard Worker 		printf("Debugger connection established\n");
509*03ce13f7SAndroid Build Coastguard Worker 	}
510*03ce13f7SAndroid Build Coastguard Worker }
511*03ce13f7SAndroid Build Coastguard Worker 
~Impl()512*03ce13f7SAndroid Build Coastguard Worker Server::Impl::~Impl()
513*03ce13f7SAndroid Build Coastguard Worker {
514*03ce13f7SAndroid Build Coastguard Worker 	ctx->removeListener(this);
515*03ce13f7SAndroid Build Coastguard Worker 	server->stop();
516*03ce13f7SAndroid Build Coastguard Worker }
517*03ce13f7SAndroid Build Coastguard Worker 
onThreadStarted(ID<Thread> id)518*03ce13f7SAndroid Build Coastguard Worker void Server::Impl::onThreadStarted(ID<Thread> id)
519*03ce13f7SAndroid Build Coastguard Worker {
520*03ce13f7SAndroid Build Coastguard Worker 	dap::ThreadEvent event;
521*03ce13f7SAndroid Build Coastguard Worker 	event.reason = "started";
522*03ce13f7SAndroid Build Coastguard Worker 	event.threadId = id.value();
523*03ce13f7SAndroid Build Coastguard Worker 	session->send(event);
524*03ce13f7SAndroid Build Coastguard Worker }
525*03ce13f7SAndroid Build Coastguard Worker 
onThreadStepped(ID<Thread> id)526*03ce13f7SAndroid Build Coastguard Worker void Server::Impl::onThreadStepped(ID<Thread> id)
527*03ce13f7SAndroid Build Coastguard Worker {
528*03ce13f7SAndroid Build Coastguard Worker 	dap::StoppedEvent event;
529*03ce13f7SAndroid Build Coastguard Worker 	event.threadId = id.value();
530*03ce13f7SAndroid Build Coastguard Worker 	event.reason = "step";
531*03ce13f7SAndroid Build Coastguard Worker 	session->send(event);
532*03ce13f7SAndroid Build Coastguard Worker }
533*03ce13f7SAndroid Build Coastguard Worker 
onLineBreakpointHit(ID<Thread> id)534*03ce13f7SAndroid Build Coastguard Worker void Server::Impl::onLineBreakpointHit(ID<Thread> id)
535*03ce13f7SAndroid Build Coastguard Worker {
536*03ce13f7SAndroid Build Coastguard Worker 	dap::StoppedEvent event;
537*03ce13f7SAndroid Build Coastguard Worker 	event.threadId = id.value();
538*03ce13f7SAndroid Build Coastguard Worker 	event.reason = "breakpoint";
539*03ce13f7SAndroid Build Coastguard Worker 	session->send(event);
540*03ce13f7SAndroid Build Coastguard Worker }
541*03ce13f7SAndroid Build Coastguard Worker 
onFunctionBreakpointHit(ID<Thread> id)542*03ce13f7SAndroid Build Coastguard Worker void Server::Impl::onFunctionBreakpointHit(ID<Thread> id)
543*03ce13f7SAndroid Build Coastguard Worker {
544*03ce13f7SAndroid Build Coastguard Worker 	dap::StoppedEvent event;
545*03ce13f7SAndroid Build Coastguard Worker 	event.threadId = id.value();
546*03ce13f7SAndroid Build Coastguard Worker 	event.reason = "function breakpoint";
547*03ce13f7SAndroid Build Coastguard Worker 	session->send(event);
548*03ce13f7SAndroid Build Coastguard Worker }
549*03ce13f7SAndroid Build Coastguard Worker 
scope(Context::Lock & lock,const char * type,Scope * s)550*03ce13f7SAndroid Build Coastguard Worker dap::Scope Server::Impl::scope(Context::Lock &lock, const char *type, Scope *s)
551*03ce13f7SAndroid Build Coastguard Worker {
552*03ce13f7SAndroid Build Coastguard Worker 	dap::Scope out;
553*03ce13f7SAndroid Build Coastguard Worker 	// out.line = s->startLine;
554*03ce13f7SAndroid Build Coastguard Worker 	// out.endLine = s->endLine;
555*03ce13f7SAndroid Build Coastguard Worker 	out.source = source(s->file.get());
556*03ce13f7SAndroid Build Coastguard Worker 	out.name = type;
557*03ce13f7SAndroid Build Coastguard Worker 	out.presentationHint = type;
558*03ce13f7SAndroid Build Coastguard Worker 	out.variablesReference = s->variables->id.value();
559*03ce13f7SAndroid Build Coastguard Worker 	lock.track(s->variables);
560*03ce13f7SAndroid Build Coastguard Worker 	return out;
561*03ce13f7SAndroid Build Coastguard Worker }
562*03ce13f7SAndroid Build Coastguard Worker 
source(File * file)563*03ce13f7SAndroid Build Coastguard Worker dap::Source Server::Impl::source(File *file)
564*03ce13f7SAndroid Build Coastguard Worker {
565*03ce13f7SAndroid Build Coastguard Worker 	dap::Source out;
566*03ce13f7SAndroid Build Coastguard Worker 	out.name = file->name;
567*03ce13f7SAndroid Build Coastguard Worker 	if(file->isVirtual())
568*03ce13f7SAndroid Build Coastguard Worker 	{
569*03ce13f7SAndroid Build Coastguard Worker 		out.sourceReference = file->id.value();
570*03ce13f7SAndroid Build Coastguard Worker 	}
571*03ce13f7SAndroid Build Coastguard Worker 	out.path = file->path();
572*03ce13f7SAndroid Build Coastguard Worker 	return out;
573*03ce13f7SAndroid Build Coastguard Worker }
574*03ce13f7SAndroid Build Coastguard Worker 
file(const dap::Source & source)575*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<File> Server::Impl::file(const dap::Source &source)
576*03ce13f7SAndroid Build Coastguard Worker {
577*03ce13f7SAndroid Build Coastguard Worker 	auto lock = ctx->lock();
578*03ce13f7SAndroid Build Coastguard Worker 	if(source.sourceReference.has_value())
579*03ce13f7SAndroid Build Coastguard Worker 	{
580*03ce13f7SAndroid Build Coastguard Worker 		auto id = source.sourceReference.value();
581*03ce13f7SAndroid Build Coastguard Worker 		if(auto file = lock.get(File::ID(id)))
582*03ce13f7SAndroid Build Coastguard Worker 		{
583*03ce13f7SAndroid Build Coastguard Worker 			return file;
584*03ce13f7SAndroid Build Coastguard Worker 		}
585*03ce13f7SAndroid Build Coastguard Worker 	}
586*03ce13f7SAndroid Build Coastguard Worker 
587*03ce13f7SAndroid Build Coastguard Worker 	auto files = lock.files();
588*03ce13f7SAndroid Build Coastguard Worker 	if(source.path.has_value())
589*03ce13f7SAndroid Build Coastguard Worker 	{
590*03ce13f7SAndroid Build Coastguard Worker 		auto path = source.path.value();
591*03ce13f7SAndroid Build Coastguard Worker 		std::shared_ptr<File> out;
592*03ce13f7SAndroid Build Coastguard Worker 		for(auto file : files)
593*03ce13f7SAndroid Build Coastguard Worker 		{
594*03ce13f7SAndroid Build Coastguard Worker 			if(file->path() == path)
595*03ce13f7SAndroid Build Coastguard Worker 			{
596*03ce13f7SAndroid Build Coastguard Worker 				out = file;
597*03ce13f7SAndroid Build Coastguard Worker 				break;
598*03ce13f7SAndroid Build Coastguard Worker 			}
599*03ce13f7SAndroid Build Coastguard Worker 		}
600*03ce13f7SAndroid Build Coastguard Worker 		return out;
601*03ce13f7SAndroid Build Coastguard Worker 	}
602*03ce13f7SAndroid Build Coastguard Worker 
603*03ce13f7SAndroid Build Coastguard Worker 	if(source.name.has_value())
604*03ce13f7SAndroid Build Coastguard Worker 	{
605*03ce13f7SAndroid Build Coastguard Worker 		auto name = source.name.value();
606*03ce13f7SAndroid Build Coastguard Worker 		std::shared_ptr<File> out;
607*03ce13f7SAndroid Build Coastguard Worker 		for(auto file : files)
608*03ce13f7SAndroid Build Coastguard Worker 		{
609*03ce13f7SAndroid Build Coastguard Worker 			if(file->name == name)
610*03ce13f7SAndroid Build Coastguard Worker 			{
611*03ce13f7SAndroid Build Coastguard Worker 				out = file;
612*03ce13f7SAndroid Build Coastguard Worker 				break;
613*03ce13f7SAndroid Build Coastguard Worker 			}
614*03ce13f7SAndroid Build Coastguard Worker 		}
615*03ce13f7SAndroid Build Coastguard Worker 		return out;
616*03ce13f7SAndroid Build Coastguard Worker 	}
617*03ce13f7SAndroid Build Coastguard Worker 
618*03ce13f7SAndroid Build Coastguard Worker 	return nullptr;
619*03ce13f7SAndroid Build Coastguard Worker }
620*03ce13f7SAndroid Build Coastguard Worker 
create(const std::shared_ptr<Context> & ctx,int port)621*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<Server> Server::create(const std::shared_ptr<Context> &ctx, int port)
622*03ce13f7SAndroid Build Coastguard Worker {
623*03ce13f7SAndroid Build Coastguard Worker 	return std::make_shared<Server::Impl>(ctx, port);
624*03ce13f7SAndroid Build Coastguard Worker }
625*03ce13f7SAndroid Build Coastguard Worker 
626*03ce13f7SAndroid Build Coastguard Worker }  // namespace dbg
627*03ce13f7SAndroid Build Coastguard Worker }  // namespace vk
628