1 // common.h (Oclgrind) 2 // Copyright (c) 2013-2019, James Price and Simon McIntosh-Smith, 3 // University of Bristol. All rights reserved. 4 // 5 // This program is provided under a three-clause BSD license. For full 6 // license terms please see the LICENSE file distributed with this 7 // source code. 8 9 #ifndef __common_h_ 10 #define __common_h_ 11 12 #define CL_TARGET_OPENCL_VERSION 300 13 #include "CL/cl.h" 14 15 #include <cassert> 16 #include <cstdio> 17 #include <cstdlib> 18 #include <cstring> 19 #include <iomanip> 20 #include <iostream> 21 #include <list> 22 #include <map> 23 #include <memory> 24 #include <queue> 25 #include <set> 26 #include <sstream> 27 #include <stack> 28 #include <stdexcept> 29 #include <stdint.h> 30 #include <unordered_map> 31 #include <vector> 32 33 #if defined(_WIN32) && !defined(__MINGW32__) 34 #define snprintf _snprintf 35 #undef ERROR 36 #endif 37 38 #ifdef __APPLE__ 39 // TODO: Remove this when thread_local fixed on OS X 40 #define THREAD_LOCAL __thread 41 #elif defined(_WIN32) && !defined(__MINGW32__) 42 // TODO: Remove this when thread_local fixed on Windows 43 #define THREAD_LOCAL __declspec(thread) 44 #else 45 #define THREAD_LOCAL thread_local 46 #endif 47 48 #define CLK_NORMALIZED_COORDS_TRUE 0x0001 49 50 #define CLK_ADDRESS_NONE 0x0000 51 #define CLK_ADDRESS_CLAMP_TO_EDGE 0x0002 52 #define CLK_ADDRESS_CLAMP 0x0004 53 #define CLK_ADDRESS_REPEAT 0x0006 54 #define CLK_ADDRESS_MIRRORED_REPEAT 0x0008 55 #define CLK_ADDRESS_MASK 0x000E 56 57 #define CLK_FILTER_NEAREST 0x0010 58 #define CLK_FILTER_LINEAR 0x0020 59 60 namespace llvm 61 { 62 class Constant; 63 class ConstantExpr; 64 class ConstantInt; 65 class Instruction; 66 class Metadata; 67 class StructType; 68 class Type; 69 class Value; 70 } // namespace llvm 71 72 namespace oclgrind 73 { 74 class Kernel; 75 76 // Enumeration for address spaces 77 enum AddressSpace 78 { 79 AddrSpacePrivate = 0, 80 AddrSpaceGlobal = 1, 81 AddrSpaceConstant = 2, 82 AddrSpaceLocal = 3, 83 }; 84 85 enum AtomicOp 86 { 87 AtomicAdd, 88 AtomicAnd, 89 AtomicCmpXchg, 90 AtomicDec, 91 AtomicInc, 92 AtomicMax, 93 AtomicMin, 94 AtomicOr, 95 AtomicSub, 96 AtomicXchg, 97 AtomicXor, 98 }; 99 100 // Enumeration for different log message types 101 enum MessageType 102 { 103 DEBUG, 104 INFO, 105 WARNING, 106 ERROR, 107 }; 108 109 // 3-dimensional size 110 struct Size3 111 { 112 size_t x, y, z; 113 Size3(); 114 Size3(size_t x, size_t y, size_t z); 115 Size3(size_t linear, Size3 dimensions); 116 size_t& operator[](unsigned i); 117 const size_t& operator[](unsigned i) const; 118 bool operator==(const Size3& rhs) const; 119 bool operator!=(const Size3& rhs) const; 120 friend std::ostream& operator<<(std::ostream& stream, const Size3& sz); 121 }; 122 123 // Structure for a value with a size/type 124 struct TypedValue 125 { 126 unsigned size; 127 unsigned num; 128 unsigned char* data; 129 130 bool operator==(const TypedValue& rhs) const; 131 bool operator!=(const TypedValue& rhs) const; 132 133 friend std::ostream& operator<<(std::ostream& stream, const TypedValue& tv); 134 135 struct TypedValue clone() const; 136 137 double getFloat(unsigned index = 0) const; 138 size_t getPointer(unsigned index = 0) const; 139 int64_t getSInt(unsigned index = 0) const; 140 uint64_t getUInt(unsigned index = 0) const; 141 void setFloat(double value, unsigned index = 0); 142 void setPointer(size_t value, unsigned index = 0); 143 void setSInt(int64_t value, unsigned index = 0); 144 void setUInt(uint64_t value, unsigned index = 0); 145 }; 146 147 // Private memory map type 148 typedef std::map<const llvm::Value*, TypedValue> TypedValueMap; 149 150 // Image object 151 struct Image 152 { 153 size_t address; 154 cl_image_format format; 155 cl_image_desc desc; 156 }; 157 158 // Check if an environment variable is set to 1 159 bool checkEnv(const char* var); 160 161 // Get an environment variable as an integer 162 unsigned getEnvInt(const char* var, int def = 0, bool allowZero = true); 163 164 // Output an instruction in human-readable format 165 void dumpInstruction(std::ostream& out, const llvm::Instruction* instruction); 166 167 // Get the human readable name of an address space 168 const char* getAddressSpaceName(unsigned addrSpace); 169 170 // Retrieve the raw data for a constant 171 void getConstantData(unsigned char* data, const llvm::Constant* constant); 172 173 // Creates an instruction from a constant expression 174 llvm::Instruction* getConstExprAsInstruction(const llvm::ConstantExpr* expr); 175 176 // Get the ConstantInt object for a Metadata node 177 const llvm::ConstantInt* getMDAsConstInt(const llvm::Metadata* md); 178 179 // Get the byte offset of a struct member 180 unsigned getStructMemberOffset(const llvm::StructType* type, unsigned index); 181 182 // Returns the size of a type 183 unsigned getTypeSize(const llvm::Type* type); 184 185 /// Returns the alignment requirements of this type 186 unsigned getTypeAlignment(const llvm::Type* type); 187 188 // Returns the size of a value 189 std::pair<unsigned, unsigned> getValueSize(const llvm::Value* value); 190 191 // Returns true if the operand is a constant value 192 bool isConstantOperand(const llvm::Value* operand); 193 194 // Returns true if the value is a 3-element vector 195 bool isVector3(const llvm::Value* value); 196 197 // Return the current time in nanoseconds since the epoch 198 double now(); 199 200 // Print data in a human readable format (according to its type) 201 void printTypedData(const llvm::Type* type, const unsigned char* data); 202 203 // Resolve a constant pointer, using a set of known constant values 204 size_t resolveConstantPointer(const llvm::Value* ptr, TypedValueMap& values); 205 206 // Resolve a GEP from a base address and list of offsets 207 size_t resolveGEP(size_t base, const llvm::Type* ptrType, 208 std::vector<int64_t>& offsets); 209 210 // Exception class for raising fatal errors 211 class FatalError : std::runtime_error 212 { 213 public: 214 FatalError(const std::string& msg, const std::string& file, size_t line); 215 ~FatalError() throw(); 216 virtual const std::string& getFile() const; 217 virtual size_t getLine() const; 218 virtual const char* what() const throw(); 219 220 protected: 221 std::string m_file; 222 size_t m_line; 223 }; 224 225 // Utility macro for raising an exception with a sprintf-based message 226 #define FATAL_ERROR(format, ...) \ 227 { \ 228 int sz = snprintf(NULL, 0, format, ##__VA_ARGS__); \ 229 char* str = new char[sz + 1]; \ 230 sprintf(str, format, ##__VA_ARGS__); \ 231 string msg = str; \ 232 delete[] str; \ 233 throw FatalError(msg, __FILE__, __LINE__); \ 234 } 235 236 class MemoryPool 237 { 238 public: 239 MemoryPool(size_t blockSize = 1024); 240 ~MemoryPool(); 241 uint8_t* alloc(size_t size); 242 TypedValue clone(const TypedValue& source); 243 244 private: 245 size_t m_blockSize; 246 size_t m_offset; 247 std::list<uint8_t*> m_blocks; 248 }; 249 250 // Pool allocator class for STL containers 251 template <class T, size_t BLOCKSIZE> class PoolAllocator 252 { 253 template <typename U, size_t BS> friend class PoolAllocator; 254 255 public: 256 typedef T value_type; 257 typedef T* pointer; 258 typedef T& reference; 259 typedef const T* const_pointer; 260 typedef const T& const_reference; 261 typedef size_t size_type; 262 typedef ptrdiff_t difference_type; 263 264 template <typename U> struct rebind 265 { 266 typedef PoolAllocator<U, BLOCKSIZE> other; 267 }; 268 PoolAllocator()269 PoolAllocator() 270 { 271 pool.reset(new MemoryPool(BLOCKSIZE)); 272 } 273 PoolAllocator(const PoolAllocator & p)274 PoolAllocator(const PoolAllocator& p) 275 { 276 this->pool = p.pool; 277 } 278 PoolAllocator(const PoolAllocator<U,BLOCKSIZE> & p)279 template <typename U> PoolAllocator(const PoolAllocator<U, BLOCKSIZE>& p) 280 { 281 this->pool = p.pool; 282 } 283 284 pointer allocate(size_type n, const_pointer hint = 0) 285 { 286 return (pointer)(pool->alloc(n * sizeof(value_type))); 287 } 288 deallocate(pointer p,size_type n)289 void deallocate(pointer p, size_type n) {} 290 construct(U * p,Args &&...args)291 template <class U, class... Args> void construct(U* p, Args&&... args) 292 { 293 new ((void*)p) U(std::forward<Args>(args)...); 294 } 295 destroy(U * p)296 template <class U> void destroy(U* p) 297 { 298 p->~U(); 299 } 300 301 bool operator==(const PoolAllocator& p) const 302 { 303 return this->pool == p.pool; 304 } 305 306 bool operator!=(const PoolAllocator& p) const 307 { 308 return this->pool != p.pool; 309 } 310 311 private: 312 std::shared_ptr<MemoryPool> pool; 313 }; 314 315 } // namespace oclgrind 316 317 #endif // __common_h_ 318