2015-07-03 Richard Biener <rguenther@suse.de>
[official-gcc.git] / liboffloadmic / runtime / offload_table.h
blobcc4caad47a156725d93de6329b81a73a317cc0c9
1 /*
2 Copyright (c) 2014 Intel Corporation. All Rights Reserved.
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
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.
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.
31 /*! \file
32 \brief Function and Variable tables used by the runtime library
35 #ifndef OFFLOAD_TABLE_H_INCLUDED
36 #define OFFLOAD_TABLE_H_INCLUDED
38 #include <iterator>
39 #include "offload_util.h"
41 // Template representing double linked list of tables
42 template <typename T> class TableList {
43 public:
44 // table type
45 typedef T Table;
47 // List node
48 struct Node {
49 Table table;
50 Node* prev;
51 Node* next;
54 public:
55 explicit TableList(Node *node = 0) : m_head(node) {}
57 void add_table(Node *node) {
58 m_lock.lock();
60 if (m_head != 0) {
61 node->next = m_head;
62 m_head->prev = node;
64 m_head = node;
66 m_lock.unlock();
69 void remove_table(Node *node) {
70 m_lock.lock();
72 if (node->next != 0) {
73 node->next->prev = node->prev;
75 if (node->prev != 0) {
76 node->prev->next = node->next;
78 if (m_head == node) {
79 m_head = node->next;
82 m_lock.unlock();
85 protected:
86 Node* m_head;
87 mutex_t m_lock;
90 // Function lookup table.
91 struct FuncTable {
92 //! Function table entry
93 /*! This table contains functions created from offload regions. */
94 /*! Each entry consists of a pointer to the function's "key"
95 and the function address. */
96 /*! Each shared library or executable may contain one such table. */
97 /*! The end of the table is marked with an entry whose name field
98 has value -1. */
99 struct Entry {
100 const char* name; //!< Name of the function
101 void* func; //!< Address of the function
104 // entries
105 const Entry *entries;
107 // max name length
108 int64_t max_name_len;
111 // Function table
112 class FuncList : public TableList<FuncTable> {
113 public:
114 explicit FuncList(Node *node = 0) : TableList<Table>(node),
115 m_max_name_len(-1)
118 // add table to the list
119 void add_table(Node *node) {
120 // recalculate max function name length
121 m_max_name_len = -1;
123 // add table
124 TableList<Table>::add_table(node);
127 // find function address for the given name
128 const void* find_addr(const char *name);
130 // find function name for the given address
131 const char* find_name(const void *addr);
133 // max name length from all tables in the list
134 int64_t max_name_length(void);
136 // debug dump
137 void dump(void);
139 private:
140 // max name length within from all tables
141 int64_t m_max_name_len;
144 // Table entry for static variables
145 struct VarTable {
146 //! Variable table entry
147 /*! This table contains statically allocated variables marked with
148 __declspec(target(mic) or #pragma omp declare target. */
149 /*! Each entry consists of a pointer to the variable's "key",
150 the variable address and its size in bytes. */
151 /*! Because memory allocation is done from the host,
152 the MIC table does not need the size of the variable. */
153 /*! Padding to make the table entry size a power of 2 is necessary
154 to avoid "holes" between table contributions from different object
155 files on Windows when debug information is specified with /Zi. */
156 struct Entry {
157 const char* name; //!< Name of the variable
158 void* addr; //!< Address of the variable
160 #if HOST_LIBRARY
161 uint64_t size;
163 #ifdef TARGET_WINNT
164 // padding to make entry size a power of 2
165 uint64_t padding;
166 #endif // TARGET_WINNT
167 #endif
170 // Table terminated by an entry with name == -1
171 const Entry *entries;
174 // List of var tables
175 class VarList : public TableList<VarTable> {
176 public:
177 VarList() : TableList<Table>()
180 // debug dump
181 void dump();
183 public:
184 // var table list iterator
185 class Iterator : public std::iterator<std::input_iterator_tag,
186 Table::Entry> {
187 public:
188 Iterator() : m_node(0), m_entry(0) {}
190 explicit Iterator(Node *node) {
191 new_node(node);
194 Iterator& operator++() {
195 if (m_entry != 0) {
196 m_entry++;
197 while (m_entry->name == 0) {
198 m_entry++;
200 if (m_entry->name == reinterpret_cast<const char*>(-1)) {
201 new_node(m_node->next);
204 return *this;
207 bool operator==(const Iterator &other) const {
208 return m_entry == other.m_entry;
211 bool operator!=(const Iterator &other) const {
212 return m_entry != other.m_entry;
215 const Table::Entry* operator*() const {
216 return m_entry;
219 private:
220 void new_node(Node *node) {
221 m_node = node;
222 m_entry = 0;
223 while (m_node != 0) {
224 m_entry = m_node->table.entries;
225 while (m_entry->name == 0) {
226 m_entry++;
228 if (m_entry->name != reinterpret_cast<const char*>(-1)) {
229 break;
231 m_node = m_node->next;
232 m_entry = 0;
236 private:
237 Node *m_node;
238 const Table::Entry *m_entry;
241 Iterator begin() const {
242 return Iterator(m_head);
245 Iterator end() const {
246 return Iterator();
249 public:
250 // Entry representation in a copy buffer
251 struct BufEntry {
252 intptr_t name;
253 intptr_t addr;
256 // Calculate the number of elements in the table and
257 // returns the size of buffer for the table
258 int64_t table_size(int64_t &nelems);
260 // Copy table contents to given buffer. It is supposed to be large
261 // enough to hold all elements as string table.
262 void table_copy(void *buf, int64_t nelems);
264 // Patch name offsets in a table after it's been copied to other side
265 static void table_patch_names(void *buf, int64_t nelems);
268 extern FuncList __offload_entries;
269 extern FuncList __offload_funcs;
270 extern VarList __offload_vars;
272 // Section names where the lookup tables are stored
273 #ifdef TARGET_WINNT
274 #define OFFLOAD_ENTRY_TABLE_SECTION_START ".OffloadEntryTable$a"
275 #define OFFLOAD_ENTRY_TABLE_SECTION_END ".OffloadEntryTable$z"
277 #define OFFLOAD_FUNC_TABLE_SECTION_START ".OffloadFuncTable$a"
278 #define OFFLOAD_FUNC_TABLE_SECTION_END ".OffloadFuncTable$z"
280 #define OFFLOAD_VAR_TABLE_SECTION_START ".OffloadVarTable$a"
281 #define OFFLOAD_VAR_TABLE_SECTION_END ".OffloadVarTable$z"
283 #define OFFLOAD_CRTINIT_SECTION_START ".CRT$XCT"
285 #pragma section(OFFLOAD_CRTINIT_SECTION_START, read)
287 #else // TARGET_WINNT
289 #define OFFLOAD_ENTRY_TABLE_SECTION_START ".OffloadEntryTable."
290 #define OFFLOAD_ENTRY_TABLE_SECTION_END ".OffloadEntryTable."
292 #define OFFLOAD_FUNC_TABLE_SECTION_START ".OffloadFuncTable."
293 #define OFFLOAD_FUNC_TABLE_SECTION_END ".OffloadFuncTable."
295 #define OFFLOAD_VAR_TABLE_SECTION_START ".OffloadVarTable."
296 #define OFFLOAD_VAR_TABLE_SECTION_END ".OffloadVarTable."
297 #endif // TARGET_WINNT
299 #pragma section(OFFLOAD_ENTRY_TABLE_SECTION_START, read, write)
300 #pragma section(OFFLOAD_ENTRY_TABLE_SECTION_END, read, write)
302 #pragma section(OFFLOAD_FUNC_TABLE_SECTION_START, read, write)
303 #pragma section(OFFLOAD_FUNC_TABLE_SECTION_END, read, write)
305 #pragma section(OFFLOAD_VAR_TABLE_SECTION_START, read, write)
306 #pragma section(OFFLOAD_VAR_TABLE_SECTION_END, read, write)
309 // register/unregister given tables
310 extern "C" void __offload_register_tables(
311 FuncList::Node *entry_table,
312 FuncList::Node *func_table,
313 VarList::Node *var_table
316 extern "C" void __offload_unregister_tables(
317 FuncList::Node *entry_table,
318 FuncList::Node *func_table,
319 VarList::Node *var_table
321 #endif // OFFLOAD_TABLE_H_INCLUDED