1 // 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"
19 #include "ReactorDebugInfo.hpp"
20 
21 #ifdef ENABLE_RR_DEBUG_INFO
22 
23 #	include <memory>
24 #	include <unordered_map>
25 #	include <unordered_set>
26 #	include <vector>
27 
28 // Forward declarations
29 namespace llvm {
30 
31 class BasicBlock;
32 class ConstantFolder;
33 class DIBuilder;
34 class DICompileUnit;
35 class DIFile;
36 class DILocation;
37 class DIScope;
38 class DISubprogram;
39 class DIType;
40 class Function;
41 class Instruction;
42 class IRBuilderDefaultInserter;
43 class JITEventListener;
44 class LLVMContext;
45 class LoadedObjectInfo;
46 class Module;
47 class Type;
48 class Value;
49 
50 namespace object {
51 class ObjectFile;
52 }
53 
54 template<typename T, typename Inserter>
55 class IRBuilder;
56 
57 }  // namespace llvm
58 
59 namespace rr {
60 
61 class Type;
62 class 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.
66 class DebugInfo
67 {
68 public:
69 	using IRBuilder = llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>;
70 
71 	DebugInfo(IRBuilder *builder,
72 	          llvm::LLVMContext *context,
73 	          llvm::Module *module,
74 	          llvm::Function *function);
75 
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.
95 	static void NotifyObjectEmitted(uint64_t key, const llvm::object::ObjectFile &obj, const llvm::LoadedObjectInfo &l);
96 
97 	// NotifyFreeingObject informs any attached debuggers that the JIT'd
98 	// object is now invalid.
99 	static void NotifyFreeingObject(uint64_t key);
100 
101 private:
102 	struct Token
103 	{
104 		enum Kind
105 		{
106 			Identifier,
107 			Return
108 		};
109 		Kind kind;
110 		std::string identifier;
111 	};
112 
113 	using LineTokens = std::unordered_map<unsigned int, Token>;
114 
115 	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 
147 	llvm::DILocation *getLocation(const Backtrace &backtrace, size_t i);
148 
149 	llvm::DIType *getOrCreateType(llvm::Type *type);
150 	llvm::DIFile *getOrCreateFile(const char *path);
151 	LineTokens const *getOrParseFileTokens(const char *path);
152 
153 	// Synchronizes diScope with the current backtrace.
154 	void syncScope(Backtrace const &backtrace);
155 
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;
166 	std::unordered_map<std::string, llvm::DIFile *> diFiles;
167 	std::unordered_map<llvm::Type *, llvm::DIType *> diTypes;
168 	std::unordered_map<std::string, std::unique_ptr<LineTokens>> fileTokens;
169 	std::vector<void const *> pushed;
170 };
171 
172 }  // namespace rr
173 
174 #endif  // ENABLE_RR_DEBUG_INFO
175 
176 #endif  // rr_LLVMReactorDebugInfo_hpp
177