1 /* 2 Copyright (c) 2014-2016 Intel Corporation. All Rights Reserved. 3 4 Redistribution and use in source and binary forms, with or without 5 modification, are permitted provided that the following conditions 6 are met: 7 8 * Redistributions of source code must retain the above copyright 9 notice, this list of conditions and the following disclaimer. 10 * Redistributions in binary form must reproduce the above copyright 11 notice, this list of conditions and the following disclaimer in the 12 documentation and/or other materials provided with the distribution. 13 * Neither the name of Intel Corporation nor the names of its 14 contributors may be used to endorse or promote products derived 15 from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 31 /*! \file 32 \brief Function and Variable tables used by the runtime library 33 */ 34 35 #ifndef OFFLOAD_TABLE_H_INCLUDED 36 #define OFFLOAD_TABLE_H_INCLUDED 37 38 #include "offload_util.h" 39 40 #define OFFLOAD_VERSION_16 1600 41 #define OFFLOAD_VERSION_17 1700 42 43 // Template representing double linked list of tables 44 template <typename T> class TableList { 45 public: 46 // table type 47 typedef T Table; 48 49 // List node 50 struct Node { 51 Table table; 52 Node* prev; 53 Node* next; 54 }; 55 56 public: m_head(node)57 explicit TableList(Node *node = 0) : m_head(node) {} 58 add_table(Node * node)59 void add_table(Node *node) { 60 m_lock.lock(); 61 if (m_head != 0) { 62 node->next = m_head; 63 m_head->prev = node; 64 } 65 m_head = node; 66 67 m_lock.unlock(); 68 } 69 remove_table(Node * node)70 void remove_table(Node *node) { 71 if (node->next != 0) { 72 node->next->prev = node->prev; 73 } 74 if (node->prev != 0) { 75 node->prev->next = node->next; 76 } 77 if (m_head == node) { 78 m_head = node->next; 79 } 80 } 81 82 protected: 83 Node* m_head; 84 mutex_t m_lock; 85 }; 86 87 // Function lookup table. 88 struct FuncTable { 89 //! Function table entry 90 /*! This table contains functions created from offload regions. */ 91 /*! Each entry consists of a pointer to the function's "key" 92 and the function address. */ 93 /*! Each shared library or executable may contain one such table. */ 94 /*! The end of the table is marked with an entry whose name field 95 has value -1. */ 96 struct Entry { 97 const char* name; //!< Name of the function 98 void* func; //!< Address of the function 99 }; 100 101 // entries 102 const Entry *entries; 103 104 // max name length 105 int64_t max_name_len; 106 }; 107 108 // Function table 109 class DLL_LOCAL FuncList : public TableList<FuncTable> { 110 public: 111 explicit FuncList(Node *node = 0) : TableList<Table>(node), 112 m_max_name_len(-1) 113 {} 114 115 // add table to the list add_table(Node * node)116 void add_table(Node *node) { 117 // recalculate max function name length 118 m_max_name_len = -1; 119 120 // add table 121 TableList<Table>::add_table(node); 122 } 123 124 // find function address for the given name 125 const void* find_addr(const char *name); 126 127 // find function name for the given address 128 const char* find_name(const void *addr); 129 130 // max name length from all tables in the list 131 int64_t max_name_length(void); 132 133 // debug dump 134 void dump(void); 135 136 private: 137 // max name length within from all tables 138 int64_t m_max_name_len; 139 }; 140 141 #define VAR_ALLOC_TYPE uint64_t 142 #define OPENMP_IMPLICIT 1 // Compiler promoted openmp declare var 143 // due to implicit use without openmp declare 144 #define OPENMP_LINK 2 // Openmp link clause in openmp declare 145 146 #define IS_OPENMP_IMPLICIT(var_alloc_type) (var_alloc_type & 1) 147 #define IS_OPENMP_LINK(var_alloc_type) (var_alloc_type & 2) 148 #define IS_OPENMP_IMPLICIT_OR_LINK(var_alloc_type) (var_alloc_type & 3) 149 150 // Table entry for static variables 151 struct VarTable { 152 //! Variable table entry 153 /*! This table contains statically allocated variables marked with 154 __declspec(target(mic) or #pragma omp declare target. */ 155 /*! Each entry consists of a pointer to the variable's "key", 156 the variable address and its size in bytes. */ 157 /*! Because memory allocation is done from the host, 158 the MIC table does not need the size of the variable. */ 159 /*! Padding to make the table entry size a power of 2 is necessary 160 to avoid "holes" between table contributions from different object 161 files on Windows when debug information is specified with /Zi. */ 162 struct Entry { 163 const char* name; //!< Name of the variable 164 void* addr; //!< Address of the variable 165 166 #if HOST_LIBRARY 167 VAR_ALLOC_TYPE var_alloc_type; 168 uint64_t size; 169 #endif 170 }; 171 172 // Table terminated by an entry with name == -1 173 const Entry *entries; 174 }; 175 176 // List of var tables 177 class DLL_LOCAL VarList : public TableList<VarTable> { 178 public: VarList()179 VarList() : TableList<Table>() 180 {} 181 182 // debug dump 183 void dump(); 184 185 public: 186 get_head()187 Node * get_head() { 188 return m_head; 189 } 190 191 public: 192 // Entry representation in a copy buffer 193 struct BufEntry { 194 intptr_t name; 195 intptr_t addr; 196 }; 197 198 // Calculate the number of elements in the table and 199 // returns the size of buffer for the table 200 int64_t table_size(int64_t &nelems); 201 202 // Copy table contents to given buffer. It is supposed to be large 203 // enough to hold all elements as string table. 204 void table_copy(void *buf, int64_t nelems); 205 206 // Patch name offsets in a table after it's been copied to other side 207 static void table_patch_names(void *buf, int64_t nelems); 208 }; 209 210 DLL_LOCAL extern FuncList __offload_entries; 211 DLL_LOCAL extern FuncList __offload_funcs; 212 DLL_LOCAL extern VarList __offload_vars; 213 214 // Section names where the lookup tables are stored 215 #ifdef TARGET_WINNT 216 #define OFFLOAD_ENTRY_TABLE_SECTION_START ".OffloadEntryTable$a" 217 #define OFFLOAD_ENTRY_TABLE_SECTION_END ".OffloadEntryTable$z" 218 219 #define OFFLOAD_FUNC_TABLE_SECTION_START ".OffloadFuncTable$a" 220 #define OFFLOAD_FUNC_TABLE_SECTION_END ".OffloadFuncTable$z" 221 222 #define OFFLOAD_VAR_TABLE_SECTION_START ".OffloadVarTable$a" 223 #define OFFLOAD_VAR_TABLE_SECTION_END ".OffloadVarTable$z" 224 225 #define OFFLOAD_CRTINIT_SECTION_START ".CRT$XCT" 226 227 #pragma section(OFFLOAD_CRTINIT_SECTION_START, read) 228 229 #else // TARGET_WINNT 230 231 #define OFFLOAD_ENTRY_TABLE_SECTION_START ".OffloadEntryTable." 232 #define OFFLOAD_ENTRY_TABLE_SECTION_END ".OffloadEntryTable." 233 234 #define OFFLOAD_FUNC_TABLE_SECTION_START ".OffloadFuncTable." 235 #define OFFLOAD_FUNC_TABLE_SECTION_END ".OffloadFuncTable." 236 237 #define OFFLOAD_VAR_TABLE_SECTION_START ".OffloadVarTable." 238 #define OFFLOAD_VAR_TABLE_SECTION_END ".OffloadVarTable." 239 #endif // TARGET_WINNT 240 241 #pragma section(OFFLOAD_ENTRY_TABLE_SECTION_START, read, write) 242 #pragma section(OFFLOAD_ENTRY_TABLE_SECTION_END, read, write) 243 244 #pragma section(OFFLOAD_FUNC_TABLE_SECTION_START, read, write) 245 #pragma section(OFFLOAD_FUNC_TABLE_SECTION_END, read, write) 246 247 #pragma section(OFFLOAD_VAR_TABLE_SECTION_START, read, write) 248 #pragma section(OFFLOAD_VAR_TABLE_SECTION_END, read, write) 249 250 251 // Set library version 252 extern "C" void __offload_set_version(int v); 253 254 // register/unregister given tables 255 extern "C" void __offload_register_tables( 256 FuncList::Node *entry_table, 257 FuncList::Node *func_table, 258 VarList::Node *var_table 259 ); 260 261 extern "C" void __offload_unregister_tables( 262 FuncList::Node *entry_table, 263 FuncList::Node *func_table, 264 VarList::Node *var_table 265 ); 266 267 268 #ifdef MYO_SUPPORT 269 270 #include <myotypes.h> 271 #include <myoimpl.h> 272 #include <myo.h> 273 274 #ifdef TARGET_WINNT 275 #define MYO_TABLE_END_MARKER() reinterpret_cast<const char*>(-1) 276 #else // TARGET_WINNT 277 #define MYO_TABLE_END_MARKER() reinterpret_cast<const char*>(0) 278 #endif // TARGET_WINNT 279 280 // Host and Target-side MYO shared variable table entry layout 281 typedef MyoiSharedVarEntry SharedTableEntry; 282 283 #if HOST_LIBRARY 284 285 // Host-side MYO function table entry layout 286 typedef struct { 287 //! Function Name 288 const char *funcName; 289 //! Function Address 290 void *funcAddr; 291 //! Local Thunk Address 292 void *localThunkAddr; 293 #ifdef TARGET_WINNT 294 // Dummy to pad up to 32 bytes 295 void *dummy; 296 #endif // TARGET_WINNT 297 } FptrTableEntry; 298 299 // Host-side MYO init routine table entry layout 300 typedef struct { 301 #ifdef TARGET_WINNT 302 // Dummy to pad up to 16 bytes 303 // Function Name 304 const char *funcName; 305 #endif // TARGET_WINNT 306 void (*func)(MyoArena); 307 } InitTableEntry; 308 309 #else // HOST_LIBRARY 310 311 // Target-side MYO function table entry layout 312 typedef MyoiTargetSharedFptrEntry FptrTableEntry; 313 314 // Target-side MYO init routine table entry layout 315 struct InitTableEntry { 316 void (*func)(void); 317 }; 318 319 #endif // HOST_LIBRARY 320 321 #ifdef TARGET_WINNT 322 323 #define OFFLOAD_MYO_SHARED_TABLE_SECTION_START ".MyoSharedTable$a" 324 #define OFFLOAD_MYO_SHARED_TABLE_SECTION_END ".MyoSharedTable$z" 325 326 #define OFFLOAD_MYO_SHARED_VTABLE_SECTION_START ".MyoSharedVTable$a" 327 #define OFFLOAD_MYO_SHARED_VTABLE_SECTION_END ".MyoSharedVTable$z" 328 329 #define OFFLOAD_MYO_SHARED_INIT_TABLE_SECTION_START ".MyoSharedInitTable$a" 330 #define OFFLOAD_MYO_SHARED_INIT_TABLE_SECTION_END ".MyoSharedInitTable$z" 331 332 #define OFFLOAD_MYO_FPTR_TABLE_SECTION_START ".MyoFptrTable$a" 333 #define OFFLOAD_MYO_FPTR_TABLE_SECTION_END ".MyoFptrTable$z" 334 335 #else // TARGET_WINNT 336 337 #define OFFLOAD_MYO_SHARED_TABLE_SECTION_START ".MyoSharedTable." 338 #define OFFLOAD_MYO_SHARED_TABLE_SECTION_END ".MyoSharedTable." 339 340 #define OFFLOAD_MYO_SHARED_VTABLE_SECTION_START ".MyoSharedVTable." 341 #define OFFLOAD_MYO_SHARED_VTABLE_SECTION_END ".MyoSharedVTable." 342 343 #define OFFLOAD_MYO_SHARED_INIT_TABLE_SECTION_START ".MyoSharedInitTable." 344 #define OFFLOAD_MYO_SHARED_INIT_TABLE_SECTION_END ".MyoSharedInitTable." 345 346 #define OFFLOAD_MYO_FPTR_TABLE_SECTION_START ".MyoFptrTable." 347 #define OFFLOAD_MYO_FPTR_TABLE_SECTION_END ".MyoFptrTable." 348 349 #endif // TARGET_WINNT 350 351 #pragma section(OFFLOAD_MYO_SHARED_TABLE_SECTION_START, read, write) 352 #pragma section(OFFLOAD_MYO_SHARED_TABLE_SECTION_END, read, write) 353 354 #pragma section(OFFLOAD_MYO_SHARED_VTABLE_SECTION_START, read, write) 355 #pragma section(OFFLOAD_MYO_SHARED_VTABLE_SECTION_END, read, write) 356 357 #pragma section(OFFLOAD_MYO_SHARED_INIT_TABLE_SECTION_START, read, write) 358 #pragma section(OFFLOAD_MYO_SHARED_INIT_TABLE_SECTION_END, read, write) 359 360 #pragma section(OFFLOAD_MYO_FPTR_TABLE_SECTION_START, read, write) 361 #pragma section(OFFLOAD_MYO_FPTR_TABLE_SECTION_END, read, write) 362 363 // List of MYO shared variable tables 364 struct MYOVarTable { 365 typedef SharedTableEntry Entry; 366 const Entry *entries; 367 }; 368 369 class MYOVarTableList : public TableList<MYOVarTable> { 370 public: MYOVarTableList()371 MYOVarTableList() : TableList<Table>() 372 {} 373 374 // add table to the list add_table(Node * node)375 void add_table(Node *node) { 376 // add table 377 TableList<Table>::add_table(node); 378 } 379 380 // debug dump 381 void dump(void); 382 383 // check if any shared variables 384 bool is_empty(); 385 386 // process the table contents for ordinary variables 387 void process(); 388 389 // process the table contents for vtable objects 390 void process_vtable(); 391 }; 392 393 // List of MYO shared function tables 394 struct MYOFuncTable { 395 typedef FptrTableEntry Entry; 396 const Entry *entries; 397 }; 398 399 class MYOFuncTableList : public TableList<MYOFuncTable> { 400 public: MYOFuncTableList()401 MYOFuncTableList() : TableList<Table>() 402 {} 403 404 // add table to the list add_table(Node * node)405 void add_table(Node *node) { 406 // add table 407 TableList<Table>::add_table(node); 408 } 409 410 // debug dump 411 void dump(void); 412 413 // check if any shared functions 414 bool is_empty(); 415 416 // process the table contents 417 void process(); 418 }; 419 420 // List of MYO shared variable initialization routine tables 421 struct MYOInitTable { 422 typedef InitTableEntry Entry; 423 const Entry *entries; 424 }; 425 426 class MYOInitTableList : public TableList<MYOInitTable> { 427 public: MYOInitTableList()428 MYOInitTableList() : TableList<Table>() 429 {} 430 431 // add table to the list add_table(Node * node)432 void add_table(Node *node) { 433 // add table 434 TableList<Table>::add_table(node); 435 } 436 437 // debug dump 438 void dump(void); 439 440 // check if any init routines 441 bool is_empty(); 442 443 // process the table contents 444 void process(); 445 }; 446 447 extern MYOVarTableList __offload_myo_var_tables; 448 extern MYOVarTableList __offload_myo_vtable_tables; 449 extern MYOFuncTableList __offload_myo_func_tables; 450 extern MYOInitTableList __offload_myo_init_tables; 451 452 extern "C" void __offload_myoRegisterTables1( 453 MYOInitTableList::Node *init_table, 454 MYOVarTableList::Node *shared_table, 455 MYOVarTableList::Node *shared_vtable, 456 MYOFuncTableList::Node *fptr_table 457 ); 458 459 extern "C" void __offload_myoRemoveTables( 460 MYOInitTableList::Node *init_table, 461 MYOVarTableList::Node *shared_table, 462 MYOVarTableList::Node *shared_vtable, 463 MYOFuncTableList::Node *fptr_table 464 ); 465 466 #endif // MYO_SUPPORT 467 468 #endif // OFFLOAD_TABLE_H_INCLUDED 469