blob: cfced3e5608926da8bda47df0c273d4ad391b99b [file] [log] [blame]
Jim Cownie33f7b242014-04-09 15:40:23 +00001//===----------------------------------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.txt for details.
7//
8//===----------------------------------------------------------------------===//
9
10
11/*! \file
12 \brief Function and Variable tables used by the runtime library
13*/
14
15#ifndef OFFLOAD_TABLE_H_INCLUDED
16#define OFFLOAD_TABLE_H_INCLUDED
17
18#include <iterator>
19#include "offload_util.h"
20
21// Template representing double linked list of tables
22template <typename T> class TableList {
23public:
24 // table type
25 typedef T Table;
26
27 // List node
28 struct Node {
29 Table table;
30 Node* prev;
31 Node* next;
32 };
33
34public:
35 explicit TableList(Node *node = 0) : m_head(node) {}
36
37 void add_table(Node *node) {
38 m_lock.lock();
39
40 if (m_head != 0) {
41 node->next = m_head;
42 m_head->prev = node;
43 }
44 m_head = node;
45
46 m_lock.unlock();
47 }
48
49 void remove_table(Node *node) {
50 m_lock.lock();
51
52 if (node->next != 0) {
53 node->next->prev = node->prev;
54 }
55 if (node->prev != 0) {
56 node->prev->next = node->next;
57 }
58 if (m_head == node) {
59 m_head = node->next;
60 }
61
62 m_lock.unlock();
63 }
64
65protected:
66 Node* m_head;
67 mutex_t m_lock;
68};
69
70// Function lookup table.
71struct FuncTable {
72 //! Function table entry
73 /*! This table contains functions created from offload regions. */
74 /*! Each entry consists of a pointer to the function's "key"
75 and the function address. */
76 /*! Each shared library or executable may contain one such table. */
77 /*! The end of the table is marked with an entry whose name field
78 has value -1. */
79 struct Entry {
80 const char* name; //!< Name of the function
81 void* func; //!< Address of the function
82 };
83
84 // entries
85 const Entry *entries;
86
87 // max name length
88 int64_t max_name_len;
89};
90
91// Function table
92class FuncList : public TableList<FuncTable> {
93public:
94 explicit FuncList(Node *node = 0) : TableList<Table>(node),
95 m_max_name_len(-1)
96 {}
97
98 // add table to the list
99 void add_table(Node *node) {
100 // recalculate max function name length
101 m_max_name_len = -1;
102
103 // add table
104 TableList<Table>::add_table(node);
105 }
106
107 // find function address for the given name
108 const void* find_addr(const char *name);
109
110 // find function name for the given address
111 const char* find_name(const void *addr);
112
113 // max name length from all tables in the list
114 int64_t max_name_length(void);
115
116 // debug dump
117 void dump(void);
118
119private:
120 // max name length within from all tables
121 int64_t m_max_name_len;
122};
123
124// Table entry for static variables
125struct VarTable {
126 //! Variable table entry
127 /*! This table contains statically allocated variables marked with
128 __declspec(target(mic) or #pragma omp declare target. */
129 /*! Each entry consists of a pointer to the variable's "key",
130 the variable address and its size in bytes. */
131 /*! Because memory allocation is done from the host,
132 the MIC table does not need the size of the variable. */
133 /*! Padding to make the table entry size a power of 2 is necessary
134 to avoid "holes" between table contributions from different object
135 files on Windows when debug information is specified with /Zi. */
136 struct Entry {
137 const char* name; //!< Name of the variable
138 void* addr; //!< Address of the variable
139
140#if HOST_LIBRARY
141 uint64_t size;
142
143#ifdef TARGET_WINNT
144 // padding to make entry size a power of 2
145 uint64_t padding;
146#endif // TARGET_WINNT
147#endif
148 };
149
150 // Table terminated by an entry with name == -1
151 const Entry *entries;
152};
153
154// List of var tables
155class VarList : public TableList<VarTable> {
156public:
157 VarList() : TableList<Table>()
158 {}
159
160 // debug dump
161 void dump();
162
163public:
164 // var table list iterator
165 class Iterator : public std::iterator<std::input_iterator_tag,
166 Table::Entry> {
167 public:
168 Iterator() : m_node(0), m_entry(0) {}
169
170 explicit Iterator(Node *node) {
171 new_node(node);
172 }
173
174 Iterator& operator++() {
175 if (m_entry != 0) {
176 m_entry++;
177 while (m_entry->name == 0) {
178 m_entry++;
179 }
180 if (m_entry->name == reinterpret_cast<const char*>(-1)) {
181 new_node(m_node->next);
182 }
183 }
184 return *this;
185 }
186
187 bool operator==(const Iterator &other) const {
188 return m_entry == other.m_entry;
189 }
190
191 bool operator!=(const Iterator &other) const {
192 return m_entry != other.m_entry;
193 }
194
195 const Table::Entry* operator*() const {
196 return m_entry;
197 }
198
199 private:
200 void new_node(Node *node) {
201 m_node = node;
202 m_entry = 0;
203 while (m_node != 0) {
204 m_entry = m_node->table.entries;
205 while (m_entry->name == 0) {
206 m_entry++;
207 }
208 if (m_entry->name != reinterpret_cast<const char*>(-1)) {
209 break;
210 }
211 m_node = m_node->next;
212 m_entry = 0;
213 }
214 }
215
216 private:
217 Node *m_node;
218 const Table::Entry *m_entry;
219 };
220
221 Iterator begin() const {
222 return Iterator(m_head);
223 }
224
225 Iterator end() const {
226 return Iterator();
227 }
228
229public:
230 // Entry representation in a copy buffer
231 struct BufEntry {
232 intptr_t name;
233 intptr_t addr;
234 };
235
236 // Calculate the number of elements in the table and
237 // returns the size of buffer for the table
238 int64_t table_size(int64_t &nelems);
239
240 // Copy table contents to given buffer. It is supposed to be large
241 // enough to hold all elements as string table.
242 void table_copy(void *buf, int64_t nelems);
243
244 // Patch name offsets in a table after it's been copied to other side
245 static void table_patch_names(void *buf, int64_t nelems);
246};
247
248extern FuncList __offload_entries;
249extern FuncList __offload_funcs;
250extern VarList __offload_vars;
251
252// Section names where the lookup tables are stored
253#ifdef TARGET_WINNT
254#define OFFLOAD_ENTRY_TABLE_SECTION_START ".OffloadEntryTable$a"
255#define OFFLOAD_ENTRY_TABLE_SECTION_END ".OffloadEntryTable$z"
256
257#define OFFLOAD_FUNC_TABLE_SECTION_START ".OffloadFuncTable$a"
258#define OFFLOAD_FUNC_TABLE_SECTION_END ".OffloadFuncTable$z"
259
260#define OFFLOAD_VAR_TABLE_SECTION_START ".OffloadVarTable$a"
261#define OFFLOAD_VAR_TABLE_SECTION_END ".OffloadVarTable$z"
262
263#define OFFLOAD_CRTINIT_SECTION_START ".CRT$XCT"
264
265#pragma section(OFFLOAD_CRTINIT_SECTION_START, read)
266
267#else // TARGET_WINNT
268
269#define OFFLOAD_ENTRY_TABLE_SECTION_START ".OffloadEntryTable."
270#define OFFLOAD_ENTRY_TABLE_SECTION_END ".OffloadEntryTable."
271
272#define OFFLOAD_FUNC_TABLE_SECTION_START ".OffloadFuncTable."
273#define OFFLOAD_FUNC_TABLE_SECTION_END ".OffloadFuncTable."
274
275#define OFFLOAD_VAR_TABLE_SECTION_START ".OffloadVarTable."
276#define OFFLOAD_VAR_TABLE_SECTION_END ".OffloadVarTable."
277#endif // TARGET_WINNT
278
279#pragma section(OFFLOAD_ENTRY_TABLE_SECTION_START, read, write)
280#pragma section(OFFLOAD_ENTRY_TABLE_SECTION_END, read, write)
281
282#pragma section(OFFLOAD_FUNC_TABLE_SECTION_START, read, write)
283#pragma section(OFFLOAD_FUNC_TABLE_SECTION_END, read, write)
284
285#pragma section(OFFLOAD_VAR_TABLE_SECTION_START, read, write)
286#pragma section(OFFLOAD_VAR_TABLE_SECTION_END, read, write)
287
288
289// register/unregister given tables
290extern "C" void __offload_register_tables(
291 FuncList::Node *entry_table,
292 FuncList::Node *func_table,
293 VarList::Node *var_table
294);
295
296extern "C" void __offload_unregister_tables(
297 FuncList::Node *entry_table,
298 FuncList::Node *func_table,
299 VarList::Node *var_table
300);
301#endif // OFFLOAD_TABLE_H_INCLUDED