blob: 2754bacbfcd857a42c3e068fce5834110e161b0f [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#ifndef rr_LLVMReactorDebugInfo_hpp
16#define rr_LLVMReactorDebugInfo_hpp
17
18#include "Reactor.hpp"
Antonio Maioranoaae33732020-02-14 14:52:34 -050019#include "ReactorDebugInfo.hpp"
Ben Claytonac07ed82019-03-26 14:17:41 +000020
21#ifdef ENABLE_RR_DEBUG_INFO
22
Ben Clayton713b8d32019-12-17 20:37:56 +000023# include <memory>
24# include <unordered_map>
25# include <unordered_set>
26# include <vector>
Ben Claytonac07ed82019-03-26 14:17:41 +000027
28// Forward declarations
Nicolas Capens157ba262019-12-10 17:49:14 -050029namespace llvm {
30
31class BasicBlock;
32class ConstantFolder;
33class DIBuilder;
34class DICompileUnit;
35class DIFile;
36class DILocation;
37class DIScope;
38class DISubprogram;
39class DIType;
40class Function;
41class Instruction;
42class IRBuilderDefaultInserter;
43class JITEventListener;
44class LLVMContext;
45class LoadedObjectInfo;
46class Module;
47class Type;
48class Value;
49
Ben Clayton713b8d32019-12-17 20:37:56 +000050namespace object {
51class ObjectFile;
Nicolas Capens157ba262019-12-10 17:49:14 -050052}
Ben Claytonac07ed82019-03-26 14:17:41 +000053
Ben Clayton713b8d32019-12-17 20:37:56 +000054template<typename T, typename Inserter>
55class IRBuilder;
Ben Claytonac07ed82019-03-26 14:17:41 +000056
Nicolas Capens157ba262019-12-10 17:49:14 -050057} // namespace llvm
Ben Claytonac07ed82019-03-26 14:17:41 +000058
Nicolas Capens157ba262019-12-10 17:49:14 -050059namespace rr {
60
61class Type;
62class Value;
63
64// DebugInfo generates LLVM DebugInfo IR from the C++ source that calls
65// into Reactor functions. See docs/ReactorDebugInfo.mk for more information.
66class DebugInfo
Ben Claytonac07ed82019-03-26 14:17:41 +000067{
Nicolas Capens157ba262019-12-10 17:49:14 -050068public:
69 using IRBuilder = llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>;
Ben Claytonac07ed82019-03-26 14:17:41 +000070
Nicolas Capens157ba262019-12-10 17:49:14 -050071 DebugInfo(IRBuilder *builder,
Ben Clayton713b8d32019-12-17 20:37:56 +000072 llvm::LLVMContext *context,
73 llvm::Module *module,
74 llvm::Function *function);
Nicolas Capens157ba262019-12-10 17:49:14 -050075
76 ~DebugInfo();
77
78 // Finalize debug info generation. Must be called before the LLVM module
79 // is built.
80 void Finalize();
81
82 // Updates the current source location.
83 void EmitLocation();
84
85 // Binds the value to its symbol in the source file.
86 // See docs/ReactorDebugInfo.mk for more information.
87 void EmitVariable(Value *value);
88
89 // Forcefully flush the binding of the last variable name.
90 // Used for binding the initializer of `For` loops.
91 void Flush();
92
93 // NotifyObjectEmitted informs any attached debuggers of the JIT'd
94 // object.
Ben Claytonee18f392020-10-19 16:54:21 -040095 static void NotifyObjectEmitted(uint64_t key, const llvm::object::ObjectFile &obj, const llvm::LoadedObjectInfo &l);
Nicolas Capens157ba262019-12-10 17:49:14 -050096
97 // NotifyFreeingObject informs any attached debuggers that the JIT'd
98 // object is now invalid.
Ben Claytonee18f392020-10-19 16:54:21 -040099 static void NotifyFreeingObject(uint64_t key);
Nicolas Capens157ba262019-12-10 17:49:14 -0500100
101private:
102 struct Token
Ben Claytonac07ed82019-03-26 14:17:41 +0000103 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500104 enum Kind
Ben Claytonac07ed82019-03-26 14:17:41 +0000105 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500106 Identifier,
107 Return
Ben Claytonac07ed82019-03-26 14:17:41 +0000108 };
Nicolas Capens157ba262019-12-10 17:49:14 -0500109 Kind kind;
110 std::string identifier;
Ben Claytonac07ed82019-03-26 14:17:41 +0000111 };
112
Nicolas Capens157ba262019-12-10 17:49:14 -0500113 using LineTokens = std::unordered_map<unsigned int, Token>;
114
Nicolas Capens157ba262019-12-10 17:49:14 -0500115 struct Pending
116 {
117 std::string name;
118 Location location;
119 llvm::DILocation *diLocation = nullptr;
120 llvm::Value *value = nullptr;
121 llvm::Instruction *insertAfter = nullptr;
122 llvm::BasicBlock *block = nullptr;
123 llvm::DIScope *scope = nullptr;
124 bool addNopOnNextLine = false;
125 };
126
127 struct Scope
128 {
129 Location location;
130 llvm::DIScope *di;
131 std::unordered_set<std::string> symbols;
132 Pending pending;
133 };
134
135 void registerBasicTypes();
136
137 void emitPending(Scope &scope, IRBuilder *builder);
138
139 // Returns the source location of the non-Reactor calling function.
140 Location getCallerLocation() const;
141
142 // Returns the backtrace for the callstack, starting at the first
143 // non-Reactor file. If limit is non-zero, then a maximum of limit
144 // frames will be returned.
145 Backtrace getCallerBacktrace(size_t limit = 0) const;
146
Ben Clayton713b8d32019-12-17 20:37:56 +0000147 llvm::DILocation *getLocation(const Backtrace &backtrace, size_t i);
Nicolas Capens157ba262019-12-10 17:49:14 -0500148
Ben Clayton713b8d32019-12-17 20:37:56 +0000149 llvm::DIType *getOrCreateType(llvm::Type *type);
150 llvm::DIFile *getOrCreateFile(const char *path);
Nicolas Capens3d7faaa2022-10-04 14:48:57 -0400151 const LineTokens *getOrParseFileTokens(const char *path);
Nicolas Capens157ba262019-12-10 17:49:14 -0500152
153 // Synchronizes diScope with the current backtrace.
Nicolas Capens7e1d67a2022-10-04 10:36:33 -0400154 void syncScope(const Backtrace &backtrace);
Nicolas Capens157ba262019-12-10 17:49:14 -0500155
156 IRBuilder *builder;
157 llvm::LLVMContext *context;
158 llvm::Module *module;
159 llvm::Function *function;
160
161 std::unique_ptr<llvm::DIBuilder> diBuilder;
162 llvm::DICompileUnit *diCU;
163 llvm::DISubprogram *diSubprogram;
164 llvm::DILocation *diRootLocation;
165 std::vector<Scope> diScope;
Ben Clayton713b8d32019-12-17 20:37:56 +0000166 std::unordered_map<std::string, llvm::DIFile *> diFiles;
167 std::unordered_map<llvm::Type *, llvm::DIType *> diTypes;
Nicolas Capens157ba262019-12-10 17:49:14 -0500168 std::unordered_map<std::string, std::unique_ptr<LineTokens>> fileTokens;
Nicolas Capens3d7faaa2022-10-04 14:48:57 -0400169 std::vector<const void *> pushed;
Nicolas Capens157ba262019-12-10 17:49:14 -0500170};
171
172} // namespace rr
Ben Claytonac07ed82019-03-26 14:17:41 +0000173
Ben Clayton713b8d32019-12-17 20:37:56 +0000174#endif // ENABLE_RR_DEBUG_INFO
Ben Claytonac07ed82019-03-26 14:17:41 +0000175
Ben Clayton713b8d32019-12-17 20:37:56 +0000176#endif // rr_LLVMReactorDebugInfo_hpp