1 //////////////////////////////////////////////////////////////////////// 2 // 3 // Copyright (C) 2012-2021 The Octave Project Developers 4 // 5 // See the file COPYRIGHT.md in the top-level directory of this 6 // distribution or <https://octave.org/copyright/>. 7 // 8 // This file is part of Octave. 9 // 10 // Octave is free software: you can redistribute it and/or modify it 11 // under the terms of the GNU General Public License as published by 12 // the Free Software Foundation, either version 3 of the License, or 13 // (at your option) any later version. 14 // 15 // Octave is distributed in the hope that it will be useful, but 16 // WITHOUT ANY WARRANTY; without even the implied warranty of 17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 // GNU General Public License for more details. 19 // 20 // You should have received a copy of the GNU General Public License 21 // along with Octave; see the file COPYING. If not, see 22 // <https://www.gnu.org/licenses/>. 23 // 24 //////////////////////////////////////////////////////////////////////// 25 26 // Some utility classes and functions used throughout jit 27 28 #if ! defined (octave_jit_util_h) 29 #define octave_jit_util_h 1 30 31 #include "octave-config.h" 32 33 #if defined (HAVE_LLVM) 34 35 #include <stdexcept> 36 37 #if defined (HAVE_LLVM_IR_DATALAYOUT_H) || defined (HAVE_LLVM_DATALAYOUT_H) 38 # define HAVE_LLVM_DATALAYOUT 39 #endif 40 41 // we don't want to include llvm headers here, as they require 42 // __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS be defined in the entire 43 // compilation unit 44 namespace llvm 45 { 46 class Value; 47 class Module; 48 class ExecutionEngine; 49 class Function; 50 class BasicBlock; 51 class LLVMContext; 52 class Type; 53 class StructType; 54 class FunctionType; 55 class Twine; 56 class GlobalValue; 57 class GlobalVariable; 58 class TerminatorInst; 59 class PHINode; 60 class TargetMachine; 61 62 class ConstantFolder; 63 64 #if defined LLVM_IRBUILDER_HAS_TWO_TEMPLATE_ARGS 65 66 class IRBuilderDefaultInserter; 67 68 template <typename T, typename Inserter> 69 class IRBuilder; 70 71 typedef IRBuilder<ConstantFolder, IRBuilderDefaultInserter> 72 IRBuilderD; 73 74 #else 75 76 template <bool preserveNames> 77 class IRBuilderDefaultInserter; 78 79 template <bool preserveNames, typename T, typename Inserter> 80 class IRBuilder; 81 82 typedef IRBuilder<true, ConstantFolder, IRBuilderDefaultInserter<true>> 83 IRBuilderD; 84 85 #endif 86 } 87 88 // some octave classes that are not (yet) in the octave namespace 89 class octave_base_value; 90 class octave_builtin; 91 class octave_value; 92 class tree; 93 class tree_expression; 94 95 namespace octave 96 { 97 // thrown when we should give up on JIT and interpret 98 class jit_fail_exception : public std::runtime_error 99 { 100 public: 101 jit_fail_exception(void)102 jit_fail_exception (void) 103 : std::runtime_error ("unknown"), m_known (false) 104 { } 105 jit_fail_exception(const std::string & reason)106 jit_fail_exception (const std::string& reason) 107 : std::runtime_error (reason), m_known (true) 108 { } 109 known(void)110 bool known (void) const { return m_known; } 111 112 private: 113 114 bool m_known; 115 }; 116 117 // llvm doesn't provide this, and it's really useful for debugging 118 std::ostream& operator<< (std::ostream& os, const llvm::Value& v); 119 120 template <typename HOLDER_T, typename SUB_T> 121 class jit_internal_node; 122 123 // jit_internal_list and jit_internal_node implement generic embedded doubly 124 // linked lists. List items extend from jit_internal_list, and can be placed 125 // in nodes of type jit_internal_node. We use CRTP twice. 126 127 template <typename LIST_T, typename NODE_T> 128 class 129 jit_internal_list 130 { 131 friend class jit_internal_node<LIST_T, NODE_T>; 132 133 public: 134 jit_internal_list(void)135 jit_internal_list (void) 136 : m_use_head (0), m_use_tail (0), m_use_count (0) 137 { } 138 ~jit_internal_list(void)139 virtual ~jit_internal_list (void) 140 { 141 while (m_use_head) 142 m_use_head->stash_value (0); 143 } 144 first_use(void)145 NODE_T * first_use (void) const { return m_use_head; } 146 use_count(void)147 std::size_t use_count (void) const { return m_use_count; } 148 149 private: 150 151 NODE_T *m_use_head; 152 NODE_T *m_use_tail; 153 std::size_t m_use_count; 154 }; 155 156 // a node for internal linked lists 157 template <typename LIST_T, typename NODE_T> 158 class 159 jit_internal_node 160 { 161 public: 162 163 typedef jit_internal_list<LIST_T, NODE_T> jit_ilist; 164 jit_internal_node(void)165 jit_internal_node (void) 166 : m_value (nullptr), m_next (nullptr), m_prev (nullptr) 167 { } 168 ~jit_internal_node(void)169 ~jit_internal_node (void) { remove (); } 170 value(void)171 LIST_T * value (void) const { return m_value; } 172 stash_value(LIST_T * avalue)173 void stash_value (LIST_T *avalue) 174 { 175 remove (); 176 177 m_value = avalue; 178 179 if (m_value) 180 { 181 jit_ilist *ilist = m_value; 182 NODE_T *sthis = static_cast<NODE_T *> (this); 183 if (ilist->m_use_head) 184 { 185 ilist->m_use_tail->m_next = sthis; 186 m_prev = ilist->m_use_tail; 187 } 188 else 189 ilist->m_use_head = sthis; 190 191 ilist->m_use_tail = sthis; 192 ++ilist->m_use_count; 193 } 194 } 195 next(void)196 NODE_T * next (void) const { return m_next; } 197 prev(void)198 NODE_T * prev (void) const { return m_prev; } 199 200 private: 201 remove(void)202 void remove (void) 203 { 204 if (m_value) 205 { 206 jit_ilist *ilist = m_value; 207 if (m_prev) 208 m_prev->m_next = m_next; 209 else 210 // we are the use_head 211 ilist->m_use_head = m_next; 212 213 if (m_next) 214 m_next->m_prev = m_prev; 215 else 216 // we are the use tail 217 ilist->m_use_tail = m_prev; 218 219 m_next = m_prev = 0; 220 --ilist->m_use_count; 221 m_value = 0; 222 } 223 } 224 225 LIST_T *m_value; 226 NODE_T *m_next; 227 NODE_T *m_prev; 228 }; 229 230 // Use like: isa<jit_phi> (value) 231 // basically just a short cut type typing dyanmic_cast. 232 template <typename T, typename U> isa(U * value)233 bool isa (U *value) 234 { 235 return dynamic_cast<T *> (value); 236 } 237 238 } 239 240 #endif 241 #endif 242