Ben Clayton | ac07ed8 | 2019-03-26 14:17:41 +0000 | [diff] [blame] | 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" |
Antonio Maiorano | aae3373 | 2020-02-14 14:52:34 -0500 | [diff] [blame] | 19 | #include "ReactorDebugInfo.hpp" |
Ben Clayton | ac07ed8 | 2019-03-26 14:17:41 +0000 | [diff] [blame] | 20 | |
| 21 | #ifdef ENABLE_RR_DEBUG_INFO |
| 22 | |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 23 | # include <memory> |
| 24 | # include <unordered_map> |
| 25 | # include <unordered_set> |
| 26 | # include <vector> |
Ben Clayton | ac07ed8 | 2019-03-26 14:17:41 +0000 | [diff] [blame] | 27 | |
| 28 | // Forward declarations |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 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 | |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 50 | namespace object { |
| 51 | class ObjectFile; |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 52 | } |
Ben Clayton | ac07ed8 | 2019-03-26 14:17:41 +0000 | [diff] [blame] | 53 | |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 54 | template<typename T, typename Inserter> |
| 55 | class IRBuilder; |
Ben Clayton | ac07ed8 | 2019-03-26 14:17:41 +0000 | [diff] [blame] | 56 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 57 | } // namespace llvm |
Ben Clayton | ac07ed8 | 2019-03-26 14:17:41 +0000 | [diff] [blame] | 58 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 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 |
Ben Clayton | ac07ed8 | 2019-03-26 14:17:41 +0000 | [diff] [blame] | 67 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 68 | public: |
| 69 | using IRBuilder = llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>; |
Ben Clayton | ac07ed8 | 2019-03-26 14:17:41 +0000 | [diff] [blame] | 70 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 71 | DebugInfo(IRBuilder *builder, |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 72 | llvm::LLVMContext *context, |
| 73 | llvm::Module *module, |
| 74 | llvm::Function *function); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 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. |
Ben Clayton | ee18f39 | 2020-10-19 16:54:21 -0400 | [diff] [blame] | 95 | static void NotifyObjectEmitted(uint64_t key, const llvm::object::ObjectFile &obj, const llvm::LoadedObjectInfo &l); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 96 | |
| 97 | // NotifyFreeingObject informs any attached debuggers that the JIT'd |
| 98 | // object is now invalid. |
Ben Clayton | ee18f39 | 2020-10-19 16:54:21 -0400 | [diff] [blame] | 99 | static void NotifyFreeingObject(uint64_t key); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 100 | |
| 101 | private: |
| 102 | struct Token |
Ben Clayton | ac07ed8 | 2019-03-26 14:17:41 +0000 | [diff] [blame] | 103 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 104 | enum Kind |
Ben Clayton | ac07ed8 | 2019-03-26 14:17:41 +0000 | [diff] [blame] | 105 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 106 | Identifier, |
| 107 | Return |
Ben Clayton | ac07ed8 | 2019-03-26 14:17:41 +0000 | [diff] [blame] | 108 | }; |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 109 | Kind kind; |
| 110 | std::string identifier; |
Ben Clayton | ac07ed8 | 2019-03-26 14:17:41 +0000 | [diff] [blame] | 111 | }; |
| 112 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 113 | using LineTokens = std::unordered_map<unsigned int, Token>; |
| 114 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 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 | |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 147 | llvm::DILocation *getLocation(const Backtrace &backtrace, size_t i); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 148 | |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 149 | llvm::DIType *getOrCreateType(llvm::Type *type); |
| 150 | llvm::DIFile *getOrCreateFile(const char *path); |
Nicolas Capens | 3d7faaa | 2022-10-04 14:48:57 -0400 | [diff] [blame] | 151 | const LineTokens *getOrParseFileTokens(const char *path); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 152 | |
| 153 | // Synchronizes diScope with the current backtrace. |
Nicolas Capens | 7e1d67a | 2022-10-04 10:36:33 -0400 | [diff] [blame] | 154 | void syncScope(const Backtrace &backtrace); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 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; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 166 | std::unordered_map<std::string, llvm::DIFile *> diFiles; |
| 167 | std::unordered_map<llvm::Type *, llvm::DIType *> diTypes; |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 168 | std::unordered_map<std::string, std::unique_ptr<LineTokens>> fileTokens; |
Nicolas Capens | 3d7faaa | 2022-10-04 14:48:57 -0400 | [diff] [blame] | 169 | std::vector<const void *> pushed; |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 170 | }; |
| 171 | |
| 172 | } // namespace rr |
Ben Clayton | ac07ed8 | 2019-03-26 14:17:41 +0000 | [diff] [blame] | 173 | |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 174 | #endif // ENABLE_RR_DEBUG_INFO |
Ben Clayton | ac07ed8 | 2019-03-26 14:17:41 +0000 | [diff] [blame] | 175 | |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 176 | #endif // rr_LLVMReactorDebugInfo_hpp |