blob: 31f1a37ba083f6f5126ce7cae92621190425c620 [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 {
59 return llvm::StringRef(path).rsplit('/');
60 }
61
62 // Note: createGDBRegistrationListener() returns a pointer to a singleton.
63 // Nothing is actually created.
64 auto jitEventListener = llvm::JITEventListener::createGDBRegistrationListener(); // guarded by jitEventListenerMutex
65 std::mutex jitEventListenerMutex;
Ben Clayton90cb2602019-05-23 14:42:32 +010066
Ben Clayton713b8d32019-12-17 20:37:56 +000067} // namespace
Ben Claytonac07ed82019-03-26 14:17:41 +000068
Nicolas Capens157ba262019-12-10 17:49:14 -050069namespace rr {
70
71DebugInfo::DebugInfo(
Ben Clayton713b8d32019-12-17 20:37:56 +000072 llvm::IRBuilder<> *builder,
73 llvm::LLVMContext *context,
74 llvm::Module *module,
75 llvm::Function *function)
76 : builder(builder)
77 , context(context)
78 , module(module)
79 , function(function)
Ben Claytonac07ed82019-03-26 14:17:41 +000080{
Nicolas Capens157ba262019-12-10 17:49:14 -050081 using namespace ::llvm;
Ben Claytonac07ed82019-03-26 14:17:41 +000082
Nicolas Capens157ba262019-12-10 17:49:14 -050083 auto location = getCallerLocation();
Ben Claytonac07ed82019-03-26 14:17:41 +000084
Nicolas Capens157ba262019-12-10 17:49:14 -050085 auto fileAndDir = splitPath(location.function.file.c_str());
86 diBuilder.reset(new llvm::DIBuilder(*module));
87 diCU = diBuilder->createCompileUnit(
Ben Clayton713b8d32019-12-17 20:37:56 +000088 llvm::dwarf::DW_LANG_C,
89 diBuilder->createFile(fileAndDir.first, fileAndDir.second),
90 "Reactor",
91 0, "", 0);
Ben Claytonac07ed82019-03-26 14:17:41 +000092
Nicolas Capens157ba262019-12-10 17:49:14 -050093 registerBasicTypes();
Ben Claytonac07ed82019-03-26 14:17:41 +000094
Nicolas Capens157ba262019-12-10 17:49:14 -050095 SmallVector<Metadata *, 8> EltTys;
96 auto funcTy = diBuilder->createSubroutineType(diBuilder->getOrCreateTypeArray(EltTys));
Ben Claytonac07ed82019-03-26 14:17:41 +000097
Nicolas Capens157ba262019-12-10 17:49:14 -050098 auto file = getOrCreateFile(location.function.file.c_str());
99 auto sp = diBuilder->createFunction(
Ben Clayton713b8d32019-12-17 20:37:56 +0000100 file, // scope
101 "ReactorFunction", // function name
102 "ReactorFunction", // linkage
103 file, // file
104 location.line, // line
105 funcTy, // type
106 false, // internal linkage
107 true, // definition
108 location.line, // scope line
109 DINode::FlagPrototyped, // flags
110 false // is optimized
Nicolas Capens157ba262019-12-10 17:49:14 -0500111 );
112 diSubprogram = sp;
113 function->setSubprogram(sp);
114 diRootLocation = DILocation::get(*context, location.line, 0, sp);
115 builder->SetCurrentDebugLocation(diRootLocation);
116}
Ben Claytonac07ed82019-03-26 14:17:41 +0000117
Nicolas Capens157ba262019-12-10 17:49:14 -0500118DebugInfo::~DebugInfo() = default;
Ben Clayton90cb2602019-05-23 14:42:32 +0100119
Nicolas Capens157ba262019-12-10 17:49:14 -0500120void DebugInfo::Finalize()
121{
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500122 while(diScope.size() > 0)
Ben Claytonac07ed82019-03-26 14:17:41 +0000123 {
Ben Clayton90cb2602019-05-23 14:42:32 +0100124 emitPending(diScope.back(), builder);
Nicolas Capens157ba262019-12-10 17:49:14 -0500125 diScope.pop_back();
126 }
127 diBuilder->finalize();
128}
129
130void DebugInfo::EmitLocation()
131{
Ben Clayton713b8d32019-12-17 20:37:56 +0000132 auto const &backtrace = getCallerBacktrace();
Nicolas Capens157ba262019-12-10 17:49:14 -0500133 syncScope(backtrace);
134 builder->SetCurrentDebugLocation(getLocation(backtrace, backtrace.size() - 1));
135
Ben Clayton713b8d32019-12-17 20:37:56 +0000136# ifdef ENABLE_RR_EMIT_PRINT_LOCATION
Antonio Maioranoaae33732020-02-14 14:52:34 -0500137 emitPrintLocation(backtrace);
Ben Clayton713b8d32019-12-17 20:37:56 +0000138# endif // ENABLE_RR_EMIT_PRINT_LOCATION
Nicolas Capens157ba262019-12-10 17:49:14 -0500139}
140
141void DebugInfo::Flush()
142{
143 emitPending(diScope.back(), builder);
144}
145
Ben Clayton713b8d32019-12-17 20:37:56 +0000146void DebugInfo::syncScope(Backtrace const &backtrace)
Nicolas Capens157ba262019-12-10 17:49:14 -0500147{
Ben Clayton713b8d32019-12-17 20:37:56 +0000148 auto shrink = [this](size_t newsize) {
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500149 while(diScope.size() > newsize)
Nicolas Capens157ba262019-12-10 17:49:14 -0500150 {
151 auto &scope = diScope.back();
152 LOG("- STACK(%d): di: %p, location: %s:%d",
Ben Clayton713b8d32019-12-17 20:37:56 +0000153 int(diScope.size() - 1), scope.di,
154 scope.location.function.file.c_str(),
155 int(scope.location.line));
Nicolas Capens157ba262019-12-10 17:49:14 -0500156 emitPending(scope, builder);
157 diScope.pop_back();
158 }
159 };
160
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500161 if(backtrace.size() < diScope.size())
Nicolas Capens157ba262019-12-10 17:49:14 -0500162 {
163 shrink(backtrace.size());
Ben Claytonac07ed82019-03-26 14:17:41 +0000164 }
165
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500166 for(size_t i = 0; i < diScope.size(); i++)
Ben Claytonac07ed82019-03-26 14:17:41 +0000167 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500168 auto &scope = diScope[i];
169 auto const &oldLocation = scope.location;
170 auto const &newLocation = backtrace[i];
Ben Claytonac07ed82019-03-26 14:17:41 +0000171
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500172 if(oldLocation.function != newLocation.function)
Ben Claytonac07ed82019-03-26 14:17:41 +0000173 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500174 LOG(" STACK(%d): Changed function %s -> %s", int(i),
Ben Clayton713b8d32019-12-17 20:37:56 +0000175 oldLocation.function.name.c_str(), newLocation.function.name.c_str());
Nicolas Capens157ba262019-12-10 17:49:14 -0500176 shrink(i);
177 break;
Ben Claytonac07ed82019-03-26 14:17:41 +0000178 }
179
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500180 if(oldLocation.line > newLocation.line)
Ben Claytonac07ed82019-03-26 14:17:41 +0000181 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500182 // Create a new di block to shadow all the variables in the loop.
183 auto file = getOrCreateFile(newLocation.function.file.c_str());
184 auto di = diBuilder->createLexicalBlock(scope.di, file, newLocation.line, 0);
185 LOG(" STACK(%d): Jumped backwards %d -> %d. di: %p -> %p", int(i),
Ben Clayton713b8d32019-12-17 20:37:56 +0000186 oldLocation.line, newLocation.line, scope.di, di);
Nicolas Capens157ba262019-12-10 17:49:14 -0500187 emitPending(scope, builder);
Ben Clayton713b8d32019-12-17 20:37:56 +0000188 scope = { newLocation, di };
189 shrink(i + 1);
Nicolas Capens157ba262019-12-10 17:49:14 -0500190 break;
Ben Claytonac07ed82019-03-26 14:17:41 +0000191 }
192
Nicolas Capens157ba262019-12-10 17:49:14 -0500193 scope.location = newLocation;
Ben Claytonac07ed82019-03-26 14:17:41 +0000194 }
195
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500196 while(backtrace.size() > diScope.size())
Ben Claytonac07ed82019-03-26 14:17:41 +0000197 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500198 auto i = diScope.size();
199 auto location = backtrace[i];
200 auto file = getOrCreateFile(location.function.file.c_str());
201 auto funcTy = diBuilder->createSubroutineType(diBuilder->getOrCreateTypeArray({}));
202
203 char buf[1024];
204 size_t size = sizeof(buf);
205 int status = 0;
206 llvm::itaniumDemangle(location.function.name.c_str(), buf, &size, &status);
207 auto name = "jit!" + (status == 0 ? std::string(buf) : location.function.name);
208
209 auto func = diBuilder->createFunction(
Ben Clayton713b8d32019-12-17 20:37:56 +0000210 file, // scope
211 name, // function name
212 "", // linkage
213 file, // file
214 location.line, // line
215 funcTy, // type
216 false, // internal linkage
217 true, // definition
218 location.line, // scope line
219 llvm::DINode::FlagPrototyped, // flags
220 false // is optimized
Ben Claytonac07ed82019-03-26 14:17:41 +0000221 );
Ben Clayton713b8d32019-12-17 20:37:56 +0000222 diScope.push_back({ location, func });
Nicolas Capens157ba262019-12-10 17:49:14 -0500223 LOG("+ STACK(%d): di: %p, location: %s:%d", int(i), di,
Ben Clayton713b8d32019-12-17 20:37:56 +0000224 location.function.file.c_str(), int(location.line));
Ben Claytonac07ed82019-03-26 14:17:41 +0000225 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500226}
Ben Claytonac07ed82019-03-26 14:17:41 +0000227
Ben Clayton713b8d32019-12-17 20:37:56 +0000228llvm::DILocation *DebugInfo::getLocation(const Backtrace &backtrace, size_t i)
Nicolas Capens157ba262019-12-10 17:49:14 -0500229{
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500230 if(backtrace.size() == 0) { return nullptr; }
Nicolas Capens157ba262019-12-10 17:49:14 -0500231 assert(backtrace.size() == diScope.size());
232 return llvm::DILocation::get(
Ben Clayton713b8d32019-12-17 20:37:56 +0000233 *context,
234 backtrace[i].line,
235 0,
236 diScope[i].di,
237 i > 0 ? getLocation(backtrace, i - 1) : diRootLocation);
Nicolas Capens157ba262019-12-10 17:49:14 -0500238}
239
240void DebugInfo::EmitVariable(Value *variable)
241{
Ben Clayton713b8d32019-12-17 20:37:56 +0000242 auto const &backtrace = getCallerBacktrace();
Nicolas Capens157ba262019-12-10 17:49:14 -0500243 syncScope(backtrace);
244
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500245 for(int i = backtrace.size() - 1; i >= 0; i--)
Ben Claytonac07ed82019-03-26 14:17:41 +0000246 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500247 auto const &location = backtrace[i];
248 auto tokens = getOrParseFileTokens(location.function.file.c_str());
249 auto tokIt = tokens->find(location.line);
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500250 if(tokIt == tokens->end())
Ben Claytonac07ed82019-03-26 14:17:41 +0000251 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500252 break;
Ben Claytonac07ed82019-03-26 14:17:41 +0000253 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500254 auto token = tokIt->second;
255 auto name = token.identifier;
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500256 if(token.kind == Token::Return)
Ben Claytonac07ed82019-03-26 14:17:41 +0000257 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500258 // This is a:
Ben Claytonac07ed82019-03-26 14:17:41 +0000259 //
Nicolas Capens157ba262019-12-10 17:49:14 -0500260 // return <expr>;
Ben Claytonac07ed82019-03-26 14:17:41 +0000261 //
Nicolas Capens157ba262019-12-10 17:49:14 -0500262 // Emit this expression as two variables -
263 // Once as a synthetic 'return_value' variable at this scope.
264 // Again by bubbling the expression value up the callstack as
265 // Return Value Optimizations (RVOs) are likely to carry across
266 // the value to a local without calling a constructor in
267 // statements like:
268 //
269 // auto val = foo();
270 //
271 name = "return_value";
Ben Claytonac07ed82019-03-26 14:17:41 +0000272 }
273
Nicolas Capens157ba262019-12-10 17:49:14 -0500274 auto &scope = diScope[i];
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500275 if(scope.pending.location != location)
Ben Claytonac07ed82019-03-26 14:17:41 +0000276 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500277 emitPending(scope, builder);
278 }
279
280 auto value = V(variable);
281 auto block = builder->GetInsertBlock();
282
283 auto insertAfter = block->size() > 0 ? &block->back() : nullptr;
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500284 while(insertAfter != nullptr && insertAfter->isTerminator())
Nicolas Capens157ba262019-12-10 17:49:14 -0500285 {
286 insertAfter = insertAfter->getPrevNode();
Ben Claytonac07ed82019-03-26 14:17:41 +0000287 }
288
289 scope.pending = Pending{};
Nicolas Capens157ba262019-12-10 17:49:14 -0500290 scope.pending.name = name;
291 scope.pending.location = location;
292 scope.pending.diLocation = getLocation(backtrace, i);
293 scope.pending.value = value;
294 scope.pending.block = block;
295 scope.pending.insertAfter = insertAfter;
296 scope.pending.scope = scope.di;
Ben Claytonac07ed82019-03-26 14:17:41 +0000297
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500298 if(token.kind == Token::Return)
Antonio Maioranof448d8e2019-04-26 16:19:16 -0400299 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500300 // Insert a noop instruction so the debugger can inspect the
301 // return value before the function scope closes.
302 scope.pending.addNopOnNextLine = true;
303 }
304 else
305 {
306 break;
307 }
308 }
309}
Ben Claytonac07ed82019-03-26 14:17:41 +0000310
Nicolas Capens157ba262019-12-10 17:49:14 -0500311void DebugInfo::emitPending(Scope &scope, IRBuilder *builder)
312{
313 auto const &pending = scope.pending;
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500314 if(pending.value == nullptr)
Nicolas Capens157ba262019-12-10 17:49:14 -0500315 {
316 return;
317 }
Antonio Maioranof448d8e2019-04-26 16:19:16 -0400318
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500319 if(!scope.symbols.emplace(pending.name).second)
Nicolas Capens157ba262019-12-10 17:49:14 -0500320 {
321 return;
322 }
323
324 bool isAlloca = llvm::isa<llvm::AllocaInst>(pending.value);
325
326 LOG(" EMIT(%s): di: %p, location: %s:%d, isAlloca: %s", pending.name.c_str(), scope.di,
Ben Clayton713b8d32019-12-17 20:37:56 +0000327 pending.location.function.file.c_str(), pending.location.line, isAlloca ? "true" : "false");
Nicolas Capens157ba262019-12-10 17:49:14 -0500328
329 auto value = pending.value;
330
331 IRBuilder::InsertPointGuard guard(*builder);
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500332 if(pending.insertAfter != nullptr)
Nicolas Capens157ba262019-12-10 17:49:14 -0500333 {
334 builder->SetInsertPoint(pending.block, ++pending.insertAfter->getIterator());
335 }
336 else
337 {
338 builder->SetInsertPoint(pending.block);
339 }
340 builder->SetCurrentDebugLocation(pending.diLocation);
341
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500342 if(!isAlloca)
Nicolas Capens157ba262019-12-10 17:49:14 -0500343 {
344 // While insertDbgValueIntrinsic should be enough to declare a
345 // variable with no storage, variables of RValues can share the same
346 // llvm::Value, and only one can be named. Take for example:
347 //
348 // Int a = 42;
349 // RValue<Int> b = a;
350 // RValue<Int> c = b;
351 //
352 // To handle this, always promote named RValues to an alloca.
353
354 llvm::BasicBlock &entryBlock = function->getEntryBlock();
355 auto alloca = new llvm::AllocaInst(value->getType(), 0, pending.name);
356 entryBlock.getInstList().push_front(alloca);
357 builder->CreateStore(value, alloca);
358 value = alloca;
359 }
360
361 value->setName(pending.name);
362
363 auto diFile = getOrCreateFile(pending.location.function.file.c_str());
364 auto diType = getOrCreateType(value->getType()->getPointerElementType());
365 auto diVar = diBuilder->createAutoVariable(scope.di, pending.name, diFile, pending.location.line, diType);
366
367 auto di = diBuilder->insertDeclare(value, diVar, diBuilder->createExpression(), pending.diLocation, pending.block);
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500368 if(pending.insertAfter != nullptr) { di->moveAfter(pending.insertAfter); }
Nicolas Capens157ba262019-12-10 17:49:14 -0500369
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500370 if(pending.addNopOnNextLine)
Nicolas Capens157ba262019-12-10 17:49:14 -0500371 {
372 builder->SetCurrentDebugLocation(llvm::DILocation::get(
Ben Clayton713b8d32019-12-17 20:37:56 +0000373 *context,
374 pending.diLocation->getLine() + 1,
375 0,
376 pending.diLocation->getScope(),
377 pending.diLocation->getInlinedAt()));
Nicolas Capens157ba262019-12-10 17:49:14 -0500378 Nop();
379 }
380
381 scope.pending = Pending{};
382}
383
384void DebugInfo::NotifyObjectEmitted(const llvm::object::ObjectFile &Obj, const llvm::LoadedObjectInfo &L)
385{
386 std::unique_lock<std::mutex> lock(jitEventListenerMutex);
Ben Clayton713b8d32019-12-17 20:37:56 +0000387 jitEventListener->NotifyObjectEmitted(Obj, static_cast<const llvm::RuntimeDyld::LoadedObjectInfo &>(L));
Nicolas Capens157ba262019-12-10 17:49:14 -0500388}
389
390void DebugInfo::NotifyFreeingObject(const llvm::object::ObjectFile &Obj)
391{
392 std::unique_lock<std::mutex> lock(jitEventListenerMutex);
393 jitEventListener->NotifyFreeingObject(Obj);
394}
395
396void DebugInfo::registerBasicTypes()
397{
398 using namespace rr;
399 using namespace llvm;
400
401 auto vec4 = diBuilder->getOrCreateArray(diBuilder->getOrCreateSubrange(0, 4));
402 auto vec8 = diBuilder->getOrCreateArray(diBuilder->getOrCreateSubrange(0, 8));
403 auto vec16 = diBuilder->getOrCreateArray(diBuilder->getOrCreateSubrange(0, 16));
404
405 diTypes.emplace(T(Bool::getType()), diBuilder->createBasicType("Bool", sizeof(bool), dwarf::DW_ATE_boolean));
406 diTypes.emplace(T(Byte::getType()), diBuilder->createBasicType("Byte", 8, dwarf::DW_ATE_unsigned_char));
407 diTypes.emplace(T(SByte::getType()), diBuilder->createBasicType("SByte", 8, dwarf::DW_ATE_signed_char));
408 diTypes.emplace(T(Short::getType()), diBuilder->createBasicType("Short", 16, dwarf::DW_ATE_signed));
409 diTypes.emplace(T(UShort::getType()), diBuilder->createBasicType("UShort", 16, dwarf::DW_ATE_unsigned));
410 diTypes.emplace(T(Int::getType()), diBuilder->createBasicType("Int", 32, dwarf::DW_ATE_signed));
411 diTypes.emplace(T(UInt::getType()), diBuilder->createBasicType("UInt", 32, dwarf::DW_ATE_unsigned));
412 diTypes.emplace(T(Long::getType()), diBuilder->createBasicType("Long", 64, dwarf::DW_ATE_signed));
413 diTypes.emplace(T(Half::getType()), diBuilder->createBasicType("Half", 16, dwarf::DW_ATE_float));
414 diTypes.emplace(T(Float::getType()), diBuilder->createBasicType("Float", 32, dwarf::DW_ATE_float));
415
Ben Clayton713b8d32019-12-17 20:37:56 +0000416 diTypes.emplace(T(Byte4::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Byte::getType())], { vec16 }));
417 diTypes.emplace(T(SByte4::getType()), diBuilder->createVectorType(128, 128, diTypes[T(SByte::getType())], { vec16 }));
418 diTypes.emplace(T(Byte8::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Byte::getType())], { vec16 }));
419 diTypes.emplace(T(SByte8::getType()), diBuilder->createVectorType(128, 128, diTypes[T(SByte::getType())], { vec16 }));
420 diTypes.emplace(T(Byte16::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Byte::getType())], { vec16 }));
421 diTypes.emplace(T(SByte16::getType()), diBuilder->createVectorType(128, 128, diTypes[T(SByte::getType())], { vec16 }));
422 diTypes.emplace(T(Short2::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Short::getType())], { vec8 }));
423 diTypes.emplace(T(UShort2::getType()), diBuilder->createVectorType(128, 128, diTypes[T(UShort::getType())], { vec8 }));
424 diTypes.emplace(T(Short4::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Short::getType())], { vec8 }));
425 diTypes.emplace(T(UShort4::getType()), diBuilder->createVectorType(128, 128, diTypes[T(UShort::getType())], { vec8 }));
426 diTypes.emplace(T(Short8::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Short::getType())], { vec8 }));
427 diTypes.emplace(T(UShort8::getType()), diBuilder->createVectorType(128, 128, diTypes[T(UShort::getType())], { vec8 }));
428 diTypes.emplace(T(Int2::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Int::getType())], { vec4 }));
429 diTypes.emplace(T(UInt2::getType()), diBuilder->createVectorType(128, 128, diTypes[T(UInt::getType())], { vec4 }));
430 diTypes.emplace(T(Int4::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Int::getType())], { vec4 }));
431 diTypes.emplace(T(UInt4::getType()), diBuilder->createVectorType(128, 128, diTypes[T(UInt::getType())], { vec4 }));
432 diTypes.emplace(T(Float2::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Float::getType())], { vec4 }));
433 diTypes.emplace(T(Float4::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Float::getType())], { vec4 }));
Nicolas Capens157ba262019-12-10 17:49:14 -0500434}
435
Antonio Maioranoaae33732020-02-14 14:52:34 -0500436Location DebugInfo::getCallerLocation() const
Nicolas Capens157ba262019-12-10 17:49:14 -0500437{
438 return getCallerBacktrace(1)[0];
439}
440
Antonio Maioranoaae33732020-02-14 14:52:34 -0500441Backtrace DebugInfo::getCallerBacktrace(size_t limit /* = 0 */) const
Nicolas Capens157ba262019-12-10 17:49:14 -0500442{
Antonio Maioranoaae33732020-02-14 14:52:34 -0500443 return rr::getCallerBacktrace(limit);
Nicolas Capens157ba262019-12-10 17:49:14 -0500444}
445
Ben Clayton713b8d32019-12-17 20:37:56 +0000446llvm::DIType *DebugInfo::getOrCreateType(llvm::Type *type)
Nicolas Capens157ba262019-12-10 17:49:14 -0500447{
448 auto it = diTypes.find(type);
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500449 if(it != diTypes.end()) { return it->second; }
Nicolas Capens157ba262019-12-10 17:49:14 -0500450
451 if(type->isPointerTy())
Ben Claytonac07ed82019-03-26 14:17:41 +0000452 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500453 auto dbgTy = diBuilder->createPointerType(
Ben Clayton713b8d32019-12-17 20:37:56 +0000454 getOrCreateType(type->getPointerElementType()),
455 sizeof(void *) * 8, alignof(void *) * 8);
Nicolas Capens157ba262019-12-10 17:49:14 -0500456 diTypes.emplace(type, dbgTy);
457 return dbgTy;
458 }
459 llvm::errs() << "Unimplemented debug type: " << type << "\n";
460 assert(false);
461 return nullptr;
462}
463
Ben Clayton713b8d32019-12-17 20:37:56 +0000464llvm::DIFile *DebugInfo::getOrCreateFile(const char *path)
Nicolas Capens157ba262019-12-10 17:49:14 -0500465{
466 auto it = diFiles.find(path);
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500467 if(it != diFiles.end()) { return it->second; }
Nicolas Capens157ba262019-12-10 17:49:14 -0500468 auto dirAndName = splitPath(path);
469 auto file = diBuilder->createFile(dirAndName.second, dirAndName.first);
470 diFiles.emplace(path, file);
471 return file;
472}
473
Ben Clayton713b8d32019-12-17 20:37:56 +0000474DebugInfo::LineTokens const *DebugInfo::getOrParseFileTokens(const char *path)
Nicolas Capens157ba262019-12-10 17:49:14 -0500475{
476 static std::regex reLocalDecl(
Ben Clayton713b8d32019-12-17 20:37:56 +0000477 "^" // line start
478 "\\s*" // initial whitespace
479 "(?:For\\s*\\(\\s*)?" // optional 'For('
480 "((?:\\w+(?:<[^>]+>)?)(?:::\\w+(?:<[^>]+>)?)*)" // type (match group 1)
481 "\\s+" // whitespace between type and name
482 "(\\w+)" // identifier (match group 2)
483 "\\s*" // whitespace after identifier
484 "(\\[.*\\])?"); // optional array suffix (match group 3)
Nicolas Capens157ba262019-12-10 17:49:14 -0500485
486 auto it = fileTokens.find(path);
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500487 if(it != fileTokens.end())
Nicolas Capens157ba262019-12-10 17:49:14 -0500488 {
489 return it->second.get();
Ben Claytonac07ed82019-03-26 14:17:41 +0000490 }
491
Ben Clayton368d39c2020-01-08 23:10:47 +0000492 auto tokens = std::make_unique<LineTokens>();
Nicolas Capens157ba262019-12-10 17:49:14 -0500493
494 std::ifstream file(path);
495 std::string line;
496 int lineCount = 0;
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500497 while(std::getline(file, line))
Ben Claytonac07ed82019-03-26 14:17:41 +0000498 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500499 lineCount++;
500 std::smatch match;
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500501 if(std::regex_search(line, match, reLocalDecl) && match.size() > 3)
Ben Claytonac07ed82019-03-26 14:17:41 +0000502 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500503 bool isArray = match.str(3) != "";
Ben Clayton713b8d32019-12-17 20:37:56 +0000504 if(!isArray) // Cannot deal with C-arrays of values.
Ben Claytonac07ed82019-03-26 14:17:41 +0000505 {
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500506 if(match.str(1) == "return")
Ben Claytonac07ed82019-03-26 14:17:41 +0000507 {
Ben Clayton713b8d32019-12-17 20:37:56 +0000508 (*tokens)[lineCount] = Token{ Token::Return };
Nicolas Capens157ba262019-12-10 17:49:14 -0500509 }
510 else
511 {
Ben Clayton713b8d32019-12-17 20:37:56 +0000512 (*tokens)[lineCount] = Token{ Token::Identifier, match.str(2) };
Ben Claytonac07ed82019-03-26 14:17:41 +0000513 }
514 }
515 }
Ben Claytonac07ed82019-03-26 14:17:41 +0000516 }
517
Nicolas Capens157ba262019-12-10 17:49:14 -0500518 auto out = tokens.get();
519 fileTokens.emplace(path, std::move(tokens));
520 return out;
521}
522
523} // namespace rr
Ben Claytonac07ed82019-03-26 14:17:41 +0000524
Ben Clayton713b8d32019-12-17 20:37:56 +0000525#endif // ENABLE_RR_DEBUG_INFO