| /* |
| 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 |