| /* | |
| Copyright (c) 2014-2016 Intel Corporation. All Rights Reserved. | |
| Redistribution and use in source and binary forms, with or without | |
| modification, are permitted provided that the following conditions | |
| are met: | |
| * Redistributions of source code must retain the above copyright | |
| notice, this list of conditions and the following disclaimer. | |
| * Redistributions in binary form must reproduce the above copyright | |
| notice, this list of conditions and the following disclaimer in the | |
| documentation and/or other materials provided with the distribution. | |
| * Neither the name of Intel Corporation nor the names of its | |
| contributors may be used to endorse or promote products derived | |
| from this software without specific prior written permission. | |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| */ | |
| /*! \file | |
| \brief Function and Variable tables used by the runtime library | |
| */ | |
| #ifndef OFFLOAD_TABLE_H_INCLUDED | |
| #define OFFLOAD_TABLE_H_INCLUDED | |
| #include "offload_util.h" | |
| #define OFFLOAD_VERSION_16 1600 | |
| #define OFFLOAD_VERSION_17 1700 | |
| // Template representing double linked list of tables | |
| template <typename T> class TableList { | |
| public: | |
| // table type | |
| typedef T Table; | |
| // List node | |
| struct Node { | |
| Table table; | |
| Node* prev; | |
| Node* next; | |
| }; | |
| public: | |
| explicit TableList(Node *node = 0) : m_head(node) {} | |
| void add_table(Node *node) { | |
| m_lock.lock(); | |
| if (m_head != 0) { | |
| node->next = m_head; | |
| m_head->prev = node; | |
| } | |
| m_head = node; | |
| m_lock.unlock(); | |
| } | |
| void remove_table(Node *node) { | |
| if (node->next != 0) { | |
| node->next->prev = node->prev; | |
| } | |
| if (node->prev != 0) { | |
| node->prev->next = node->next; | |
| } | |
| if (m_head == node) { | |
| m_head = node->next; | |
| } | |
| } | |
| protected: | |
| Node* m_head; | |
| mutex_t m_lock; | |
| }; | |
| // Function lookup table. | |
| struct FuncTable { | |
| //! Function table entry | |
| /*! This table contains functions created from offload regions. */ | |
| /*! Each entry consists of a pointer to the function's "key" | |
| and the function address. */ | |
| /*! Each shared library or executable may contain one such table. */ | |
| /*! The end of the table is marked with an entry whose name field | |
| has value -1. */ | |
| struct Entry { | |
| const char* name; //!< Name of the function | |
| void* func; //!< Address of the function | |
| }; | |
| // entries | |
| const Entry *entries; | |
| // max name length | |
| int64_t max_name_len; | |
| }; | |
| // Function table | |
| class DLL_LOCAL FuncList : public TableList<FuncTable> { | |
| public: | |
| explicit FuncList(Node *node = 0) : TableList<Table>(node), | |
| m_max_name_len(-1) | |
| {} | |
| // add table to the list | |
| void add_table(Node *node) { | |
| // recalculate max function name length | |
| m_max_name_len = -1; | |
| // add table | |
| TableList<Table>::add_table(node); | |
| } | |
| // find function address for the given name | |
| const void* find_addr(const char *name); | |
| // find function name for the given address | |
| const char* find_name(const void *addr); | |
| // max name length from all tables in the list | |
| int64_t max_name_length(void); | |
| // debug dump | |
| void dump(void); | |
| private: | |
| // max name length within from all tables | |
| int64_t m_max_name_len; | |
| }; | |
| #define VAR_ALLOC_TYPE uint64_t | |
| #define OPENMP_IMPLICIT 1 // Compiler promoted openmp declare var | |
| // due to implicit use without openmp declare | |
| #define OPENMP_LINK 2 // Openmp link clause in openmp declare | |
| #define IS_OPENMP_IMPLICIT(var_alloc_type) (var_alloc_type & 1) | |
| #define IS_OPENMP_LINK(var_alloc_type) (var_alloc_type & 2) | |
| #define IS_OPENMP_IMPLICIT_OR_LINK(var_alloc_type) (var_alloc_type & 3) | |
| // Table entry for static variables | |
| struct VarTable { | |
| //! Variable table entry | |
| /*! This table contains statically allocated variables marked with | |
| __declspec(target(mic) or #pragma omp declare target. */ | |
| /*! Each entry consists of a pointer to the variable's "key", | |
| the variable address and its size in bytes. */ | |
| /*! Because memory allocation is done from the host, | |
| the MIC table does not need the size of the variable. */ | |
| /*! Padding to make the table entry size a power of 2 is necessary | |
| to avoid "holes" between table contributions from different object | |
| files on Windows when debug information is specified with /Zi. */ | |
| struct Entry { | |
| const char* name; //!< Name of the variable | |
| void* addr; //!< Address of the variable | |
| #if HOST_LIBRARY | |
| VAR_ALLOC_TYPE var_alloc_type; | |
| uint64_t size; | |
| #endif | |
| }; | |
| // Table terminated by an entry with name == -1 | |
| const Entry *entries; | |
| }; | |
| // List of var tables | |
| class DLL_LOCAL VarList : public TableList<VarTable> { | |
| public: | |
| VarList() : TableList<Table>() | |
| {} | |
| // debug dump | |
| void dump(); | |
| public: | |
| Node * get_head() { | |
| return m_head; | |
| } | |
| public: | |
| // Entry representation in a copy buffer | |
| struct BufEntry { | |
| intptr_t name; | |
| intptr_t addr; | |
| }; | |
| // Calculate the number of elements in the table and | |
| // returns the size of buffer for the table | |
| int64_t table_size(int64_t &nelems); | |
| // Copy table contents to given buffer. It is supposed to be large | |
| // enough to hold all elements as string table. | |
| void table_copy(void *buf, int64_t nelems); | |
| // Patch name offsets in a table after it's been copied to other side | |
| static void table_patch_names(void *buf, int64_t nelems); | |
| }; | |
| DLL_LOCAL extern FuncList __offload_entries; | |
| DLL_LOCAL extern FuncList __offload_funcs; | |
| DLL_LOCAL extern VarList __offload_vars; | |
| // Section names where the lookup tables are stored | |
| #ifdef TARGET_WINNT | |
| #define OFFLOAD_ENTRY_TABLE_SECTION_START ".OffloadEntryTable$a" | |
| #define OFFLOAD_ENTRY_TABLE_SECTION_END ".OffloadEntryTable$z" | |
| #define OFFLOAD_FUNC_TABLE_SECTION_START ".OffloadFuncTable$a" | |
| #define OFFLOAD_FUNC_TABLE_SECTION_END ".OffloadFuncTable$z" | |
| #define OFFLOAD_VAR_TABLE_SECTION_START ".OffloadVarTable$a" | |
| #define OFFLOAD_VAR_TABLE_SECTION_END ".OffloadVarTable$z" | |
| #define OFFLOAD_CRTINIT_SECTION_START ".CRT$XCT" | |
| #pragma section(OFFLOAD_CRTINIT_SECTION_START, read) | |
| #else // TARGET_WINNT | |
| #define OFFLOAD_ENTRY_TABLE_SECTION_START ".OffloadEntryTable." | |
| #define OFFLOAD_ENTRY_TABLE_SECTION_END ".OffloadEntryTable." | |
| #define OFFLOAD_FUNC_TABLE_SECTION_START ".OffloadFuncTable." | |
| #define OFFLOAD_FUNC_TABLE_SECTION_END ".OffloadFuncTable." | |
| #define OFFLOAD_VAR_TABLE_SECTION_START ".OffloadVarTable." | |
| #define OFFLOAD_VAR_TABLE_SECTION_END ".OffloadVarTable." | |
| #endif // TARGET_WINNT | |
| #pragma section(OFFLOAD_ENTRY_TABLE_SECTION_START, read, write) | |
| #pragma section(OFFLOAD_ENTRY_TABLE_SECTION_END, read, write) | |
| #pragma section(OFFLOAD_FUNC_TABLE_SECTION_START, read, write) | |
| #pragma section(OFFLOAD_FUNC_TABLE_SECTION_END, read, write) | |
| #pragma section(OFFLOAD_VAR_TABLE_SECTION_START, read, write) | |
| #pragma section(OFFLOAD_VAR_TABLE_SECTION_END, read, write) | |
| // Set library version | |
| extern "C" void __offload_set_version(int v); | |
| // register/unregister given tables | |
| extern "C" void __offload_register_tables( | |
| FuncList::Node *entry_table, | |
| FuncList::Node *func_table, | |
| VarList::Node *var_table | |
| ); | |
| extern "C" void __offload_unregister_tables( | |
| FuncList::Node *entry_table, | |
| FuncList::Node *func_table, | |
| VarList::Node *var_table | |
| ); | |
| #ifdef MYO_SUPPORT | |
| #include <myotypes.h> | |
| #include <myoimpl.h> | |
| #include <myo.h> | |
| #ifdef TARGET_WINNT | |
| #define MYO_TABLE_END_MARKER() reinterpret_cast<const char*>(-1) | |
| #else // TARGET_WINNT | |
| #define MYO_TABLE_END_MARKER() reinterpret_cast<const char*>(0) | |
| #endif // TARGET_WINNT | |
| // Host and Target-side MYO shared variable table entry layout | |
| typedef MyoiSharedVarEntry SharedTableEntry; | |
| #if HOST_LIBRARY | |
| // Host-side MYO function table entry layout | |
| typedef struct { | |
| //! Function Name | |
| const char *funcName; | |
| //! Function Address | |
| void *funcAddr; | |
| //! Local Thunk Address | |
| void *localThunkAddr; | |
| #ifdef TARGET_WINNT | |
| // Dummy to pad up to 32 bytes | |
| void *dummy; | |
| #endif // TARGET_WINNT | |
| } FptrTableEntry; | |
| // Host-side MYO init routine table entry layout | |
| typedef struct { | |
| #ifdef TARGET_WINNT | |
| // Dummy to pad up to 16 bytes | |
| // Function Name | |
| const char *funcName; | |
| #endif // TARGET_WINNT | |
| void (*func)(MyoArena); | |
| } InitTableEntry; | |
| #else // HOST_LIBRARY | |
| // Target-side MYO function table entry layout | |
| typedef MyoiTargetSharedFptrEntry FptrTableEntry; | |
| // Target-side MYO init routine table entry layout | |
| struct InitTableEntry { | |
| void (*func)(void); | |
| }; | |
| #endif // HOST_LIBRARY | |
| #ifdef TARGET_WINNT | |
| #define OFFLOAD_MYO_SHARED_TABLE_SECTION_START ".MyoSharedTable$a" | |
| #define OFFLOAD_MYO_SHARED_TABLE_SECTION_END ".MyoSharedTable$z" | |
| #define OFFLOAD_MYO_SHARED_VTABLE_SECTION_START ".MyoSharedVTable$a" | |
| #define OFFLOAD_MYO_SHARED_VTABLE_SECTION_END ".MyoSharedVTable$z" | |
| #define OFFLOAD_MYO_SHARED_INIT_TABLE_SECTION_START ".MyoSharedInitTable$a" | |
| #define OFFLOAD_MYO_SHARED_INIT_TABLE_SECTION_END ".MyoSharedInitTable$z" | |
| #define OFFLOAD_MYO_FPTR_TABLE_SECTION_START ".MyoFptrTable$a" | |
| #define OFFLOAD_MYO_FPTR_TABLE_SECTION_END ".MyoFptrTable$z" | |
| #else // TARGET_WINNT | |
| #define OFFLOAD_MYO_SHARED_TABLE_SECTION_START ".MyoSharedTable." | |
| #define OFFLOAD_MYO_SHARED_TABLE_SECTION_END ".MyoSharedTable." | |
| #define OFFLOAD_MYO_SHARED_VTABLE_SECTION_START ".MyoSharedVTable." | |
| #define OFFLOAD_MYO_SHARED_VTABLE_SECTION_END ".MyoSharedVTable." | |
| #define OFFLOAD_MYO_SHARED_INIT_TABLE_SECTION_START ".MyoSharedInitTable." | |
| #define OFFLOAD_MYO_SHARED_INIT_TABLE_SECTION_END ".MyoSharedInitTable." | |
| #define OFFLOAD_MYO_FPTR_TABLE_SECTION_START ".MyoFptrTable." | |
| #define OFFLOAD_MYO_FPTR_TABLE_SECTION_END ".MyoFptrTable." | |
| #endif // TARGET_WINNT | |
| #pragma section(OFFLOAD_MYO_SHARED_TABLE_SECTION_START, read, write) | |
| #pragma section(OFFLOAD_MYO_SHARED_TABLE_SECTION_END, read, write) | |
| #pragma section(OFFLOAD_MYO_SHARED_VTABLE_SECTION_START, read, write) | |
| #pragma section(OFFLOAD_MYO_SHARED_VTABLE_SECTION_END, read, write) | |
| #pragma section(OFFLOAD_MYO_SHARED_INIT_TABLE_SECTION_START, read, write) | |
| #pragma section(OFFLOAD_MYO_SHARED_INIT_TABLE_SECTION_END, read, write) | |
| #pragma section(OFFLOAD_MYO_FPTR_TABLE_SECTION_START, read, write) | |
| #pragma section(OFFLOAD_MYO_FPTR_TABLE_SECTION_END, read, write) | |
| // List of MYO shared variable tables | |
| struct MYOVarTable { | |
| typedef SharedTableEntry Entry; | |
| const Entry *entries; | |
| }; | |
| class MYOVarTableList : public TableList<MYOVarTable> { | |
| public: | |
| MYOVarTableList() : TableList<Table>() | |
| {} | |
| // add table to the list | |
| void add_table(Node *node) { | |
| // add table | |
| TableList<Table>::add_table(node); | |
| } | |
| // debug dump | |
| void dump(void); | |
| // check if any shared variables | |
| bool is_empty(); | |
| // process the table contents for ordinary variables | |
| void process(); | |
| // process the table contents for vtable objects | |
| void process_vtable(); | |
| }; | |
| // List of MYO shared function tables | |
| struct MYOFuncTable { | |
| typedef FptrTableEntry Entry; | |
| const Entry *entries; | |
| }; | |
| class MYOFuncTableList : public TableList<MYOFuncTable> { | |
| public: | |
| MYOFuncTableList() : TableList<Table>() | |
| {} | |
| // add table to the list | |
| void add_table(Node *node) { | |
| // add table | |
| TableList<Table>::add_table(node); | |
| } | |
| // debug dump | |
| void dump(void); | |
| // check if any shared functions | |
| bool is_empty(); | |
| // process the table contents | |
| void process(); | |
| }; | |
| // List of MYO shared variable initialization routine tables | |
| struct MYOInitTable { | |
| typedef InitTableEntry Entry; | |
| const Entry *entries; | |
| }; | |
| class MYOInitTableList : public TableList<MYOInitTable> { | |
| public: | |
| MYOInitTableList() : TableList<Table>() | |
| {} | |
| // add table to the list | |
| void add_table(Node *node) { | |
| // add table | |
| TableList<Table>::add_table(node); | |
| } | |
| // debug dump | |
| void dump(void); | |
| // check if any init routines | |
| bool is_empty(); | |
| // process the table contents | |
| void process(); | |
| }; | |
| extern MYOVarTableList __offload_myo_var_tables; | |
| extern MYOVarTableList __offload_myo_vtable_tables; | |
| extern MYOFuncTableList __offload_myo_func_tables; | |
| extern MYOInitTableList __offload_myo_init_tables; | |
| extern "C" void __offload_myoRegisterTables1( | |
| MYOInitTableList::Node *init_table, | |
| MYOVarTableList::Node *shared_table, | |
| MYOVarTableList::Node *shared_vtable, | |
| MYOFuncTableList::Node *fptr_table | |
| ); | |
| extern "C" void __offload_myoRemoveTables( | |
| MYOInitTableList::Node *init_table, | |
| MYOVarTableList::Node *shared_table, | |
| MYOVarTableList::Node *shared_vtable, | |
| MYOFuncTableList::Node *fptr_table | |
| ); | |
| #endif // MYO_SUPPORT | |
| #endif // OFFLOAD_TABLE_H_INCLUDED |