blob: 7d10734335c45ab7256120473928c4387e3b5ac7 [file] [log] [blame]
Ben Claytonac07ed82019-03-26 14:17:41 +00001// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "LLVMReactorDebugInfo.hpp"
16
17#ifdef ENABLE_RR_DEBUG_INFO
18
Ben Clayton713b8d32019-12-17 20:37:56 +000019# include "LLVMReactor.hpp"
20# include "Reactor.hpp"
Antonio Maiorano415d1812020-02-11 16:22:55 -050021# include "Print.hpp"
Ben Claytonac07ed82019-03-26 14:17:41 +000022
Ben Clayton713b8d32019-12-17 20:37:56 +000023# include "boost/stacktrace.hpp"
Ben Claytonac07ed82019-03-26 14:17:41 +000024
Nicolas Capens41a73022020-01-30 00:30:14 -050025// TODO(b/143539525): Eliminate when warning has been fixed.
26# ifdef _MSC_VER
27__pragma(warning(push))
28 __pragma(warning(disable : 4146)) // unary minus operator applied to unsigned type, result still unsigned
29# endif
30
Ben Clayton713b8d32019-12-17 20:37:56 +000031# include "llvm/Demangle/Demangle.h"
32# include "llvm/ExecutionEngine/JITEventListener.h"
33# include "llvm/IR/DIBuilder.h"
34# include "llvm/IR/IRBuilder.h"
35# include "llvm/IR/Intrinsics.h"
Ben Claytonac07ed82019-03-26 14:17:41 +000036
Nicolas Capens41a73022020-01-30 00:30:14 -050037# ifdef _MSC_VER
38 __pragma(warning(pop))
39# endif
40
Ben Clayton713b8d32019-12-17 20:37:56 +000041# include <cctype>
42# include <fstream>
43# include <mutex>
44# include <regex>
45# include <sstream>
46# include <string>
Ben Claytonac07ed82019-03-26 14:17:41 +000047
Ben Clayton713b8d32019-12-17 20:37:56 +000048# if 0
49# define LOG(msg, ...) printf(msg "\n", ##__VA_ARGS__)
50# else
51# define LOG(msg, ...)
52# endif
Ben Claytonac07ed82019-03-26 14:17:41 +000053
Nicolas Capens41a73022020-01-30 00:30:14 -050054 namespace
Ben Claytonac07ed82019-03-26 14:17:41 +000055{
Ben Clayton90cb2602019-05-23 14:42:32 +010056
Nicolas Capens41a73022020-01-30 00:30:14 -050057 std::pair<llvm::StringRef, llvm::StringRef> splitPath(const char *path)
58 {
Ben Claytonee18f392020-10-19 16:54:21 -040059 auto dirAndFile = llvm::StringRef(path).rsplit('/');
60 if(dirAndFile.second == "")
61 {
62 dirAndFile.second = "<unknown>";
63 }
64 return dirAndFile;
Nicolas Capens41a73022020-01-30 00:30:14 -050065 }
66
67 // Note: createGDBRegistrationListener() returns a pointer to a singleton.
68 // Nothing is actually created.
69 auto jitEventListener = llvm::JITEventListener::createGDBRegistrationListener(); // guarded by jitEventListenerMutex
70 std::mutex jitEventListenerMutex;
Ben Clayton90cb2602019-05-23 14:42:32 +010071
Ben Clayton713b8d32019-12-17 20:37:56 +000072} // namespace
Ben Claytonac07ed82019-03-26 14:17:41 +000073
Nicolas Capens157ba262019-12-10 17:49:14 -050074namespace rr {
75
76DebugInfo::DebugInfo(
Ben Clayton713b8d32019-12-17 20:37:56 +000077 llvm::IRBuilder<> *builder,
78 llvm::LLVMContext *context,
79 llvm::Module *module,
80 llvm::Function *function)
81 : builder(builder)
82 , context(context)
83 , module(module)
84 , function(function)
Ben Claytonac07ed82019-03-26 14:17:41 +000085{
Nicolas Capens157ba262019-12-10 17:49:14 -050086 using namespace ::llvm;
Ben Claytonac07ed82019-03-26 14:17:41 +000087
Nicolas Capens157ba262019-12-10 17:49:14 -050088 auto location = getCallerLocation();
Ben Claytonac07ed82019-03-26 14:17:41 +000089
Ben Claytonee18f392020-10-19 16:54:21 -040090 auto dirAndFile = splitPath(location.function.file.c_str());
Nicolas Capens157ba262019-12-10 17:49:14 -050091 diBuilder.reset(new llvm::DIBuilder(*module));
92 diCU = diBuilder->createCompileUnit(
Ben Clayton713b8d32019-12-17 20:37:56 +000093 llvm::dwarf::DW_LANG_C,
Ben Claytonee18f392020-10-19 16:54:21 -040094 diBuilder->createFile(dirAndFile.second, dirAndFile.first),
Ben Clayton713b8d32019-12-17 20:37:56 +000095 "Reactor",
96 0, "", 0);
Ben Claytonac07ed82019-03-26 14:17:41 +000097
Nicolas Capens157ba262019-12-10 17:49:14 -050098 registerBasicTypes();
Ben Claytonac07ed82019-03-26 14:17:41 +000099
Nicolas Capens157ba262019-12-10 17:49:14 -0500100 SmallVector<Metadata *, 8> EltTys;
101 auto funcTy = diBuilder->createSubroutineType(diBuilder->getOrCreateTypeArray(EltTys));
Ben Claytonac07ed82019-03-26 14:17:41 +0000102
Nicolas Capens157ba262019-12-10 17:49:14 -0500103 auto file = getOrCreateFile(location.function.file.c_str());
104 auto sp = diBuilder->createFunction(
Antonio Maiorano7d529ff2020-07-20 15:27:02 -0400105 file, // scope
106 "ReactorFunction", // function name
107 "ReactorFunction", // linkage
108 file, // file
109 location.line, // line
110 funcTy, // type
111 location.line, // scope line
112 DINode::FlagPrototyped, // flags
113 DISubprogram::SPFlagDefinition // subprogram flags
Nicolas Capens157ba262019-12-10 17:49:14 -0500114 );
115 diSubprogram = sp;
116 function->setSubprogram(sp);
117 diRootLocation = DILocation::get(*context, location.line, 0, sp);
118 builder->SetCurrentDebugLocation(diRootLocation);
119}
Ben Claytonac07ed82019-03-26 14:17:41 +0000120
Nicolas Capens157ba262019-12-10 17:49:14 -0500121DebugInfo::~DebugInfo() = default;
Ben Clayton90cb2602019-05-23 14:42:32 +0100122
Nicolas Capens157ba262019-12-10 17:49:14 -0500123void DebugInfo::Finalize()
124{
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500125 while(diScope.size() > 0)
Ben Claytonac07ed82019-03-26 14:17:41 +0000126 {
Ben Clayton90cb2602019-05-23 14:42:32 +0100127 emitPending(diScope.back(), builder);
Nicolas Capens157ba262019-12-10 17:49:14 -0500128 diScope.pop_back();
129 }
130 diBuilder->finalize();
131}
132
133void DebugInfo::EmitLocation()
134{
Ben Clayton713b8d32019-12-17 20:37:56 +0000135 auto const &backtrace = getCallerBacktrace();
Nicolas Capens157ba262019-12-10 17:49:14 -0500136 syncScope(backtrace);
137 builder->SetCurrentDebugLocation(getLocation(backtrace, backtrace.size() - 1));
Antonio Maioranoaae33732020-02-14 14:52:34 -0500138 emitPrintLocation(backtrace);
Nicolas Capens157ba262019-12-10 17:49:14 -0500139}
140
141void DebugInfo::Flush()
142{
Ben Claytonee18f392020-10-19 16:54:21 -0400143 if(!diScope.empty())
144 {
145 emitPending(diScope.back(), builder);
146 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500147}
148
Ben Clayton713b8d32019-12-17 20:37:56 +0000149void DebugInfo::syncScope(Backtrace const &backtrace)
Nicolas Capens157ba262019-12-10 17:49:14 -0500150{
Antonio Maiorano7d529ff2020-07-20 15:27:02 -0400151 using namespace ::llvm;
152
Ben Clayton713b8d32019-12-17 20:37:56 +0000153 auto shrink = [this](size_t newsize) {
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500154 while(diScope.size() > newsize)
Nicolas Capens157ba262019-12-10 17:49:14 -0500155 {
156 auto &scope = diScope.back();
157 LOG("- STACK(%d): di: %p, location: %s:%d",
Ben Clayton713b8d32019-12-17 20:37:56 +0000158 int(diScope.size() - 1), scope.di,
159 scope.location.function.file.c_str(),
160 int(scope.location.line));
Nicolas Capens157ba262019-12-10 17:49:14 -0500161 emitPending(scope, builder);
162 diScope.pop_back();
163 }
164 };
165
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500166 if(backtrace.size() < diScope.size())
Nicolas Capens157ba262019-12-10 17:49:14 -0500167 {
168 shrink(backtrace.size());
Ben Claytonac07ed82019-03-26 14:17:41 +0000169 }
170
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500171 for(size_t i = 0; i < diScope.size(); i++)
Ben Claytonac07ed82019-03-26 14:17:41 +0000172 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500173 auto &scope = diScope[i];
174 auto const &oldLocation = scope.location;
175 auto const &newLocation = backtrace[i];
Ben Claytonac07ed82019-03-26 14:17:41 +0000176
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500177 if(oldLocation.function != newLocation.function)
Ben Claytonac07ed82019-03-26 14:17:41 +0000178 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500179 LOG(" STACK(%d): Changed function %s -> %s", int(i),
Ben Clayton713b8d32019-12-17 20:37:56 +0000180 oldLocation.function.name.c_str(), newLocation.function.name.c_str());
Nicolas Capens157ba262019-12-10 17:49:14 -0500181 shrink(i);
182 break;
Ben Claytonac07ed82019-03-26 14:17:41 +0000183 }
184
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500185 if(oldLocation.line > newLocation.line)
Ben Claytonac07ed82019-03-26 14:17:41 +0000186 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500187 // Create a new di block to shadow all the variables in the loop.
188 auto file = getOrCreateFile(newLocation.function.file.c_str());
189 auto di = diBuilder->createLexicalBlock(scope.di, file, newLocation.line, 0);
190 LOG(" STACK(%d): Jumped backwards %d -> %d. di: %p -> %p", int(i),
Ben Clayton713b8d32019-12-17 20:37:56 +0000191 oldLocation.line, newLocation.line, scope.di, di);
Nicolas Capens157ba262019-12-10 17:49:14 -0500192 emitPending(scope, builder);
Ben Clayton713b8d32019-12-17 20:37:56 +0000193 scope = { newLocation, di };
194 shrink(i + 1);
Nicolas Capens157ba262019-12-10 17:49:14 -0500195 break;
Ben Claytonac07ed82019-03-26 14:17:41 +0000196 }
197
Nicolas Capens157ba262019-12-10 17:49:14 -0500198 scope.location = newLocation;
Ben Claytonac07ed82019-03-26 14:17:41 +0000199 }
200
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500201 while(backtrace.size() > diScope.size())
Ben Claytonac07ed82019-03-26 14:17:41 +0000202 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500203 auto i = diScope.size();
204 auto location = backtrace[i];
205 auto file = getOrCreateFile(location.function.file.c_str());
206 auto funcTy = diBuilder->createSubroutineType(diBuilder->getOrCreateTypeArray({}));
207
208 char buf[1024];
209 size_t size = sizeof(buf);
210 int status = 0;
211 llvm::itaniumDemangle(location.function.name.c_str(), buf, &size, &status);
212 auto name = "jit!" + (status == 0 ? std::string(buf) : location.function.name);
213
214 auto func = diBuilder->createFunction(
Antonio Maiorano7d529ff2020-07-20 15:27:02 -0400215 file, // scope
216 name, // function name
217 "", // linkage
218 file, // file
219 location.line, // line
220 funcTy, // type
221 location.line, // scope line
222 DINode::FlagPrototyped, // flags
223 DISubprogram::SPFlagDefinition // subprogram flags
Ben Claytonac07ed82019-03-26 14:17:41 +0000224 );
Ben Clayton713b8d32019-12-17 20:37:56 +0000225 diScope.push_back({ location, func });
Nicolas Capens157ba262019-12-10 17:49:14 -0500226 LOG("+ STACK(%d): di: %p, location: %s:%d", int(i), di,
Ben Clayton713b8d32019-12-17 20:37:56 +0000227 location.function.file.c_str(), int(location.line));
Ben Claytonac07ed82019-03-26 14:17:41 +0000228 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500229}
Ben Claytonac07ed82019-03-26 14:17:41 +0000230
Ben Clayton713b8d32019-12-17 20:37:56 +0000231llvm::DILocation *DebugInfo::getLocation(const Backtrace &backtrace, size_t i)
Nicolas Capens157ba262019-12-10 17:49:14 -0500232{
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500233 if(backtrace.size() == 0) { return nullptr; }
Nicolas Capens157ba262019-12-10 17:49:14 -0500234 assert(backtrace.size() == diScope.size());
235 return llvm::DILocation::get(
Ben Clayton713b8d32019-12-17 20:37:56 +0000236 *context,
237 backtrace[i].line,
238 0,
239 diScope[i].di,
240 i > 0 ? getLocation(backtrace, i - 1) : diRootLocation);
Nicolas Capens157ba262019-12-10 17:49:14 -0500241}
242
243void DebugInfo::EmitVariable(Value *variable)
244{
Ben Clayton713b8d32019-12-17 20:37:56 +0000245 auto const &backtrace = getCallerBacktrace();
Nicolas Capens157ba262019-12-10 17:49:14 -0500246 syncScope(backtrace);
247
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500248 for(int i = backtrace.size() - 1; i >= 0; i--)
Ben Claytonac07ed82019-03-26 14:17:41 +0000249 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500250 auto const &location = backtrace[i];
251 auto tokens = getOrParseFileTokens(location.function.file.c_str());
252 auto tokIt = tokens->find(location.line);
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500253 if(tokIt == tokens->end())
Ben Claytonac07ed82019-03-26 14:17:41 +0000254 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500255 break;
Ben Claytonac07ed82019-03-26 14:17:41 +0000256 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500257 auto token = tokIt->second;
258 auto name = token.identifier;
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500259 if(token.kind == Token::Return)
Ben Claytonac07ed82019-03-26 14:17:41 +0000260 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500261 // This is a:
Ben Claytonac07ed82019-03-26 14:17:41 +0000262 //
Nicolas Capens157ba262019-12-10 17:49:14 -0500263 // return <expr>;
Ben Claytonac07ed82019-03-26 14:17:41 +0000264 //
Nicolas Capens157ba262019-12-10 17:49:14 -0500265 // Emit this expression as two variables -
266 // Once as a synthetic 'return_value' variable at this scope.
267 // Again by bubbling the expression value up the callstack as
268 // Return Value Optimizations (RVOs) are likely to carry across
269 // the value to a local without calling a constructor in
270 // statements like:
271 //
272 // auto val = foo();
273 //
274 name = "return_value";
Ben Claytonac07ed82019-03-26 14:17:41 +0000275 }
276
Nicolas Capens157ba262019-12-10 17:49:14 -0500277 auto &scope = diScope[i];
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500278 if(scope.pending.location != location)
Ben Claytonac07ed82019-03-26 14:17:41 +0000279 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500280 emitPending(scope, builder);
281 }
282
283 auto value = V(variable);
284 auto block = builder->GetInsertBlock();
285
286 auto insertAfter = block->size() > 0 ? &block->back() : nullptr;
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500287 while(insertAfter != nullptr && insertAfter->isTerminator())
Nicolas Capens157ba262019-12-10 17:49:14 -0500288 {
289 insertAfter = insertAfter->getPrevNode();
Ben Claytonac07ed82019-03-26 14:17:41 +0000290 }
291
292 scope.pending = Pending{};
Nicolas Capens157ba262019-12-10 17:49:14 -0500293 scope.pending.name = name;
294 scope.pending.location = location;
295 scope.pending.diLocation = getLocation(backtrace, i);
296 scope.pending.value = value;
297 scope.pending.block = block;
298 scope.pending.insertAfter = insertAfter;
299 scope.pending.scope = scope.di;
Ben Claytonac07ed82019-03-26 14:17:41 +0000300
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500301 if(token.kind == Token::Return)
Antonio Maioranof448d8e2019-04-26 16:19:16 -0400302 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500303 // Insert a noop instruction so the debugger can inspect the
304 // return value before the function scope closes.
305 scope.pending.addNopOnNextLine = true;
306 }
307 else
308 {
309 break;
310 }
311 }
312}
Ben Claytonac07ed82019-03-26 14:17:41 +0000313
Nicolas Capens157ba262019-12-10 17:49:14 -0500314void DebugInfo::emitPending(Scope &scope, IRBuilder *builder)
315{
316 auto const &pending = scope.pending;
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500317 if(pending.value == nullptr)
Nicolas Capens157ba262019-12-10 17:49:14 -0500318 {
319 return;
320 }
Antonio Maioranof448d8e2019-04-26 16:19:16 -0400321
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500322 if(!scope.symbols.emplace(pending.name).second)
Nicolas Capens157ba262019-12-10 17:49:14 -0500323 {
324 return;
325 }
326
327 bool isAlloca = llvm::isa<llvm::AllocaInst>(pending.value);
328
329 LOG(" EMIT(%s): di: %p, location: %s:%d, isAlloca: %s", pending.name.c_str(), scope.di,
Ben Clayton713b8d32019-12-17 20:37:56 +0000330 pending.location.function.file.c_str(), pending.location.line, isAlloca ? "true" : "false");
Nicolas Capens157ba262019-12-10 17:49:14 -0500331
332 auto value = pending.value;
333
334 IRBuilder::InsertPointGuard guard(*builder);
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500335 if(pending.insertAfter != nullptr)
Nicolas Capens157ba262019-12-10 17:49:14 -0500336 {
337 builder->SetInsertPoint(pending.block, ++pending.insertAfter->getIterator());
338 }
339 else
340 {
341 builder->SetInsertPoint(pending.block);
342 }
343 builder->SetCurrentDebugLocation(pending.diLocation);
344
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500345 if(!isAlloca)
Nicolas Capens157ba262019-12-10 17:49:14 -0500346 {
347 // While insertDbgValueIntrinsic should be enough to declare a
348 // variable with no storage, variables of RValues can share the same
349 // llvm::Value, and only one can be named. Take for example:
350 //
351 // Int a = 42;
352 // RValue<Int> b = a;
353 // RValue<Int> c = b;
354 //
355 // To handle this, always promote named RValues to an alloca.
356
357 llvm::BasicBlock &entryBlock = function->getEntryBlock();
358 auto alloca = new llvm::AllocaInst(value->getType(), 0, pending.name);
359 entryBlock.getInstList().push_front(alloca);
360 builder->CreateStore(value, alloca);
361 value = alloca;
362 }
363
364 value->setName(pending.name);
365
366 auto diFile = getOrCreateFile(pending.location.function.file.c_str());
367 auto diType = getOrCreateType(value->getType()->getPointerElementType());
368 auto diVar = diBuilder->createAutoVariable(scope.di, pending.name, diFile, pending.location.line, diType);
369
370 auto di = diBuilder->insertDeclare(value, diVar, diBuilder->createExpression(), pending.diLocation, pending.block);
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500371 if(pending.insertAfter != nullptr) { di->moveAfter(pending.insertAfter); }
Nicolas Capens157ba262019-12-10 17:49:14 -0500372
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500373 if(pending.addNopOnNextLine)
Nicolas Capens157ba262019-12-10 17:49:14 -0500374 {
375 builder->SetCurrentDebugLocation(llvm::DILocation::get(
Ben Clayton713b8d32019-12-17 20:37:56 +0000376 *context,
377 pending.diLocation->getLine() + 1,
378 0,
379 pending.diLocation->getScope(),
380 pending.diLocation->getInlinedAt()));
Nicolas Capens157ba262019-12-10 17:49:14 -0500381 Nop();
382 }
383
384 scope.pending = Pending{};
385}
386
Ben Claytonee18f392020-10-19 16:54:21 -0400387void DebugInfo::NotifyObjectEmitted(uint64_t key, const llvm::object::ObjectFile &obj, const llvm::LoadedObjectInfo &l)
Nicolas Capens157ba262019-12-10 17:49:14 -0500388{
389 std::unique_lock<std::mutex> lock(jitEventListenerMutex);
Ben Claytonee18f392020-10-19 16:54:21 -0400390 jitEventListener->notifyObjectLoaded(key, obj, static_cast<const llvm::RuntimeDyld::LoadedObjectInfo &>(l));
Nicolas Capens157ba262019-12-10 17:49:14 -0500391}
392
Ben Claytonee18f392020-10-19 16:54:21 -0400393void DebugInfo::NotifyFreeingObject(uint64_t key)
Nicolas Capens157ba262019-12-10 17:49:14 -0500394{
395 std::unique_lock<std::mutex> lock(jitEventListenerMutex);
Antonio Maiorano7d529ff2020-07-20 15:27:02 -0400396 jitEventListener->notifyFreeingObject(key);
Nicolas Capens157ba262019-12-10 17:49:14 -0500397}
398
399void DebugInfo::registerBasicTypes()
400{
401 using namespace rr;
402 using namespace llvm;
403
404 auto vec4 = diBuilder->getOrCreateArray(diBuilder->getOrCreateSubrange(0, 4));
405 auto vec8 = diBuilder->getOrCreateArray(diBuilder->getOrCreateSubrange(0, 8));
406 auto vec16 = diBuilder->getOrCreateArray(diBuilder->getOrCreateSubrange(0, 16));
407
Antonio Maiorano4b777772020-06-22 14:55:37 -0400408 diTypes.emplace(T(Bool::type()), diBuilder->createBasicType("Bool", sizeof(bool), dwarf::DW_ATE_boolean));
409 diTypes.emplace(T(Byte::type()), diBuilder->createBasicType("Byte", 8, dwarf::DW_ATE_unsigned_char));
410 diTypes.emplace(T(SByte::type()), diBuilder->createBasicType("SByte", 8, dwarf::DW_ATE_signed_char));
411 diTypes.emplace(T(Short::type()), diBuilder->createBasicType("Short", 16, dwarf::DW_ATE_signed));
412 diTypes.emplace(T(UShort::type()), diBuilder->createBasicType("UShort", 16, dwarf::DW_ATE_unsigned));
413 diTypes.emplace(T(Int::type()), diBuilder->createBasicType("Int", 32, dwarf::DW_ATE_signed));
414 diTypes.emplace(T(UInt::type()), diBuilder->createBasicType("UInt", 32, dwarf::DW_ATE_unsigned));
415 diTypes.emplace(T(Long::type()), diBuilder->createBasicType("Long", 64, dwarf::DW_ATE_signed));
416 diTypes.emplace(T(Half::type()), diBuilder->createBasicType("Half", 16, dwarf::DW_ATE_float));
417 diTypes.emplace(T(Float::type()), diBuilder->createBasicType("Float", 32, dwarf::DW_ATE_float));
Nicolas Capens157ba262019-12-10 17:49:14 -0500418
Antonio Maiorano4b777772020-06-22 14:55:37 -0400419 diTypes.emplace(T(Byte4::type()), diBuilder->createVectorType(128, 128, diTypes[T(Byte::type())], { vec16 }));
420 diTypes.emplace(T(SByte4::type()), diBuilder->createVectorType(128, 128, diTypes[T(SByte::type())], { vec16 }));
421 diTypes.emplace(T(Byte8::type()), diBuilder->createVectorType(128, 128, diTypes[T(Byte::type())], { vec16 }));
422 diTypes.emplace(T(SByte8::type()), diBuilder->createVectorType(128, 128, diTypes[T(SByte::type())], { vec16 }));
423 diTypes.emplace(T(Byte16::type()), diBuilder->createVectorType(128, 128, diTypes[T(Byte::type())], { vec16 }));
424 diTypes.emplace(T(SByte16::type()), diBuilder->createVectorType(128, 128, diTypes[T(SByte::type())], { vec16 }));
425 diTypes.emplace(T(Short2::type()), diBuilder->createVectorType(128, 128, diTypes[T(Short::type())], { vec8 }));
426 diTypes.emplace(T(UShort2::type()), diBuilder->createVectorType(128, 128, diTypes[T(UShort::type())], { vec8 }));
427 diTypes.emplace(T(Short4::type()), diBuilder->createVectorType(128, 128, diTypes[T(Short::type())], { vec8 }));
428 diTypes.emplace(T(UShort4::type()), diBuilder->createVectorType(128, 128, diTypes[T(UShort::type())], { vec8 }));
429 diTypes.emplace(T(Short8::type()), diBuilder->createVectorType(128, 128, diTypes[T(Short::type())], { vec8 }));
430 diTypes.emplace(T(UShort8::type()), diBuilder->createVectorType(128, 128, diTypes[T(UShort::type())], { vec8 }));
431 diTypes.emplace(T(Int2::type()), diBuilder->createVectorType(128, 128, diTypes[T(Int::type())], { vec4 }));
432 diTypes.emplace(T(UInt2::type()), diBuilder->createVectorType(128, 128, diTypes[T(UInt::type())], { vec4 }));
433 diTypes.emplace(T(Int4::type()), diBuilder->createVectorType(128, 128, diTypes[T(Int::type())], { vec4 }));
434 diTypes.emplace(T(UInt4::type()), diBuilder->createVectorType(128, 128, diTypes[T(UInt::type())], { vec4 }));
435 diTypes.emplace(T(Float2::type()), diBuilder->createVectorType(128, 128, diTypes[T(Float::type())], { vec4 }));
436 diTypes.emplace(T(Float4::type()), diBuilder->createVectorType(128, 128, diTypes[T(Float::type())], { vec4 }));
Nicolas Capens157ba262019-12-10 17:49:14 -0500437}
438
Antonio Maioranoaae33732020-02-14 14:52:34 -0500439Location DebugInfo::getCallerLocation() const
Nicolas Capens157ba262019-12-10 17:49:14 -0500440{
Ben Claytonee18f392020-10-19 16:54:21 -0400441 auto backtrace = getCallerBacktrace(1);
442 return backtrace.empty() ? Location{} : backtrace[0];
Nicolas Capens157ba262019-12-10 17:49:14 -0500443}
444
Antonio Maioranoaae33732020-02-14 14:52:34 -0500445Backtrace DebugInfo::getCallerBacktrace(size_t limit /* = 0 */) const
Nicolas Capens157ba262019-12-10 17:49:14 -0500446{
Antonio Maioranoaae33732020-02-14 14:52:34 -0500447 return rr::getCallerBacktrace(limit);
Nicolas Capens157ba262019-12-10 17:49:14 -0500448}
449
Ben Clayton713b8d32019-12-17 20:37:56 +0000450llvm::DIType *DebugInfo::getOrCreateType(llvm::Type *type)
Nicolas Capens157ba262019-12-10 17:49:14 -0500451{
452 auto it = diTypes.find(type);
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500453 if(it != diTypes.end()) { return it->second; }
Nicolas Capens157ba262019-12-10 17:49:14 -0500454
455 if(type->isPointerTy())
Ben Claytonac07ed82019-03-26 14:17:41 +0000456 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500457 auto dbgTy = diBuilder->createPointerType(
Ben Clayton713b8d32019-12-17 20:37:56 +0000458 getOrCreateType(type->getPointerElementType()),
459 sizeof(void *) * 8, alignof(void *) * 8);
Nicolas Capens157ba262019-12-10 17:49:14 -0500460 diTypes.emplace(type, dbgTy);
461 return dbgTy;
462 }
463 llvm::errs() << "Unimplemented debug type: " << type << "\n";
464 assert(false);
465 return nullptr;
466}
467
Ben Clayton713b8d32019-12-17 20:37:56 +0000468llvm::DIFile *DebugInfo::getOrCreateFile(const char *path)
Nicolas Capens157ba262019-12-10 17:49:14 -0500469{
470 auto it = diFiles.find(path);
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500471 if(it != diFiles.end()) { return it->second; }
Nicolas Capens157ba262019-12-10 17:49:14 -0500472 auto dirAndName = splitPath(path);
473 auto file = diBuilder->createFile(dirAndName.second, dirAndName.first);
474 diFiles.emplace(path, file);
475 return file;
476}
477
Ben Clayton713b8d32019-12-17 20:37:56 +0000478DebugInfo::LineTokens const *DebugInfo::getOrParseFileTokens(const char *path)
Nicolas Capens157ba262019-12-10 17:49:14 -0500479{
480 static std::regex reLocalDecl(
Ben Clayton713b8d32019-12-17 20:37:56 +0000481 "^" // line start
482 "\\s*" // initial whitespace
483 "(?:For\\s*\\(\\s*)?" // optional 'For('
484 "((?:\\w+(?:<[^>]+>)?)(?:::\\w+(?:<[^>]+>)?)*)" // type (match group 1)
485 "\\s+" // whitespace between type and name
486 "(\\w+)" // identifier (match group 2)
487 "\\s*" // whitespace after identifier
488 "(\\[.*\\])?"); // optional array suffix (match group 3)
Nicolas Capens157ba262019-12-10 17:49:14 -0500489
490 auto it = fileTokens.find(path);
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500491 if(it != fileTokens.end())
Nicolas Capens157ba262019-12-10 17:49:14 -0500492 {
493 return it->second.get();
Ben Claytonac07ed82019-03-26 14:17:41 +0000494 }
495
Ben Clayton368d39c2020-01-08 23:10:47 +0000496 auto tokens = std::make_unique<LineTokens>();
Nicolas Capens157ba262019-12-10 17:49:14 -0500497
498 std::ifstream file(path);
499 std::string line;
500 int lineCount = 0;
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500501 while(std::getline(file, line))
Ben Claytonac07ed82019-03-26 14:17:41 +0000502 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500503 lineCount++;
504 std::smatch match;
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500505 if(std::regex_search(line, match, reLocalDecl) && match.size() > 3)
Ben Claytonac07ed82019-03-26 14:17:41 +0000506 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500507 bool isArray = match.str(3) != "";
Ben Clayton713b8d32019-12-17 20:37:56 +0000508 if(!isArray) // Cannot deal with C-arrays of values.
Ben Claytonac07ed82019-03-26 14:17:41 +0000509 {
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500510 if(match.str(1) == "return")
Ben Claytonac07ed82019-03-26 14:17:41 +0000511 {
Ben Clayton713b8d32019-12-17 20:37:56 +0000512 (*tokens)[lineCount] = Token{ Token::Return };
Nicolas Capens157ba262019-12-10 17:49:14 -0500513 }
514 else
515 {
Ben Clayton713b8d32019-12-17 20:37:56 +0000516 (*tokens)[lineCount] = Token{ Token::Identifier, match.str(2) };
Ben Claytonac07ed82019-03-26 14:17:41 +0000517 }
518 }
519 }
Ben Claytonac07ed82019-03-26 14:17:41 +0000520 }
521
Nicolas Capens157ba262019-12-10 17:49:14 -0500522 auto out = tokens.get();
523 fileTokens.emplace(path, std::move(tokens));
524 return out;
525}
526
527} // namespace rr
Ben Claytonac07ed82019-03-26 14:17:41 +0000528
Ben Clayton713b8d32019-12-17 20:37:56 +0000529#endif // ENABLE_RR_DEBUG_INFO