* decl.c (start_decl): Don't push the plain VAR_DECL for a
[official-gcc.git] / liboffloadmic / plugin / offload_target_main.cpp
blob3fead0190cbf16b03d68848b03830aceb63c0de0
1 /* Plugin for offload execution on Intel MIC devices.
3 Copyright (C) 2014 Free Software Foundation, Inc.
5 Contributed by Ilya Verbin <ilya.verbin@intel.com>.
7 This file is part of the GNU Offloading and Multi Processing Library
8 (libgomp).
10 Libgomp is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3, or (at your option)
13 any later version.
15 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 more details.
20 Under Section 7 of GPL version 3, you are granted additional
21 permissions described in the GCC Runtime Library Exception, version
22 3.1, as published by the Free Software Foundation.
24 You should have received a copy of the GNU General Public License and
25 a copy of the GCC Runtime Library Exception along with this program;
26 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
27 <http://www.gnu.org/licenses/>. */
29 /* Target side part of a libgomp plugin. */
31 #include <stdint.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include "compiler_if_target.h"
37 #ifdef DEBUG
38 #define TRACE(...) \
39 { \
40 fprintf (stderr, "TARGET:\t%s:%s ", __FILE__, __FUNCTION__); \
41 fprintf (stderr, __VA_ARGS__); \
42 fprintf (stderr, "\n"); \
44 #else
45 #define TRACE { }
46 #endif
49 static VarDesc vd_host2tgt = {
50 { 1, 1 }, /* dst, src */
51 { 1, 0 }, /* in, out */
52 1, /* alloc_if */
53 1, /* free_if */
54 4, /* align */
55 0, /* mic_offset */
56 { 0, 0, 0, 0, 0, 0, 0, 0 }, /* is_static, is_static_dstn, has_length,
57 is_stack_buf, sink_addr, alloc_disp,
58 is_noncont_src, is_noncont_dst */
59 0, /* offset */
60 0, /* size */
61 1, /* count */
62 0, /* alloc */
63 0, /* into */
64 0 /* ptr */
67 static VarDesc vd_tgt2host = {
68 { 1, 1 }, /* dst, src */
69 { 0, 1 }, /* in, out */
70 1, /* alloc_if */
71 1, /* free_if */
72 4, /* align */
73 0, /* mic_offset */
74 { 0, 0, 0, 0, 0, 0, 0, 0 }, /* is_static, is_static_dstn, has_length,
75 is_stack_buf, sink_addr, alloc_disp,
76 is_noncont_src, is_noncont_dst */
77 0, /* offset */
78 0, /* size */
79 1, /* count */
80 0, /* alloc */
81 0, /* into */
82 0 /* ptr */
85 /* Pointer to the descriptor of the last loaded shared library. */
86 static void *last_loaded_library = NULL;
88 /* Pointer and size of the variable, used in __offload_target_host2tgt_p[12]
89 and __offload_target_tgt2host_p[12]. */
90 static void *last_var_ptr = NULL;
91 static int last_var_size = 0;
94 /* Override the corresponding functions from libgomp. */
95 extern "C" int
96 omp_is_initial_device (void) __GOMP_NOTHROW
98 return 0;
101 extern "C" int32_t
102 omp_is_initial_device_ (void)
104 return omp_is_initial_device ();
108 /* Dummy function needed for the initialization of target process during the
109 first call to __offload_offload1. */
110 static void
111 __offload_target_init_proc (OFFLOAD ofldt)
113 TRACE ("");
116 /* Collect addresses of the offload functions and of the global variables from
117 the library descriptor and send them to host.
118 Part 1: Send num_funcs and num_vars to host. */
119 static void
120 __offload_target_table_p1 (OFFLOAD ofldt)
122 void ***lib_descr = (void ***) last_loaded_library;
124 if (lib_descr == NULL)
126 TRACE ("");
127 fprintf (stderr, "Error! No shared libraries loaded on target.\n");
128 return;
131 void **func_table_begin = lib_descr[0];
132 void **func_table_end = lib_descr[1];
133 void **var_table_begin = lib_descr[2];
134 void **var_table_end = lib_descr[3];
136 /* The func table contains only addresses, the var table contains addresses
137 and corresponding sizes. */
138 int num_funcs = func_table_end - func_table_begin;
139 int num_vars = (var_table_end - var_table_begin) / 2;
140 TRACE ("(num_funcs = %d, num_vars = %d)", num_funcs, num_vars);
142 VarDesc vd1[2] = { vd_tgt2host, vd_tgt2host };
143 vd1[0].ptr = &num_funcs;
144 vd1[0].size = sizeof (num_funcs);
145 vd1[1].ptr = &num_vars;
146 vd1[1].size = sizeof (num_vars);
147 VarDesc2 vd2[2] = { { "num_funcs", 0 }, { "num_vars", 0 } };
149 __offload_target_enter (ofldt, 2, vd1, vd2);
150 __offload_target_leave (ofldt);
153 /* Part 2: Send the table with addresses to host. */
154 static void
155 __offload_target_table_p2 (OFFLOAD ofldt)
157 void ***lib_descr = (void ***) last_loaded_library;
158 void **func_table_begin = lib_descr[0];
159 void **func_table_end = lib_descr[1];
160 void **var_table_begin = lib_descr[2];
161 void **var_table_end = lib_descr[3];
163 int num_funcs = func_table_end - func_table_begin;
164 int num_vars = (var_table_end - var_table_begin) / 2;
165 int table_size = (num_funcs + 2 * num_vars) * sizeof (void *);
166 void **table = (void **) malloc (table_size);
167 TRACE ("(table_size = %d)", table_size);
169 VarDesc vd1;
170 vd1 = vd_tgt2host;
171 vd1.ptr = table;
172 vd1.size = table_size;
173 VarDesc2 vd2 = { "table", 0 };
175 __offload_target_enter (ofldt, 1, &vd1, &vd2);
177 void **p;
178 int i = 0;
179 for (p = func_table_begin; p < func_table_end; p++, i++)
180 table[i] = *p;
182 for (p = var_table_begin; p < var_table_end; p++, i++)
183 table[i] = *p;
185 __offload_target_leave (ofldt);
186 free (table);
189 /* Allocate size bytes and send a pointer to the allocated memory to host. */
190 static void
191 __offload_target_alloc (OFFLOAD ofldt)
193 size_t size = 0;
194 void *ptr = NULL;
196 VarDesc vd1[2] = { vd_host2tgt, vd_tgt2host };
197 vd1[0].ptr = &size;
198 vd1[0].size = sizeof (size);
199 vd1[1].ptr = &ptr;
200 vd1[1].size = sizeof (void *);
201 VarDesc2 vd2[2] = { { "size", 0 }, { "ptr", 0 } };
203 __offload_target_enter (ofldt, 2, vd1, vd2);
204 ptr = malloc (size);
205 TRACE ("(size = %d): ptr = %p", size, ptr);
206 __offload_target_leave (ofldt);
209 /* Free the memory space pointed to by ptr. */
210 static void
211 __offload_target_free (OFFLOAD ofldt)
213 void *ptr = 0;
215 VarDesc vd1 = vd_host2tgt;
216 vd1.ptr = &ptr;
217 vd1.size = sizeof (void *);
218 VarDesc2 vd2 = { "ptr", 0 };
220 __offload_target_enter (ofldt, 1, &vd1, &vd2);
221 TRACE ("(ptr = %p)", ptr);
222 free (ptr);
223 __offload_target_leave (ofldt);
226 /* Receive var_size bytes from host and store to var_ptr.
227 Part 1: Receive var_ptr and var_size from host. */
228 static void
229 __offload_target_host2tgt_p1 (OFFLOAD ofldt)
231 void *var_ptr = NULL;
232 size_t var_size = 0;
234 VarDesc vd1[2] = { vd_host2tgt, vd_host2tgt };
235 vd1[0].ptr = &var_ptr;
236 vd1[0].size = sizeof (void *);
237 vd1[1].ptr = &var_size;
238 vd1[1].size = sizeof (var_size);
239 VarDesc2 vd2[2] = { { "var_ptr", 0 }, { "var_size", 0 } };
241 __offload_target_enter (ofldt, 2, vd1, vd2);
242 TRACE ("(var_ptr = %p, var_size = %d)", var_ptr, var_size);
243 last_var_ptr = var_ptr;
244 last_var_size = var_size;
245 __offload_target_leave (ofldt);
248 /* Part 2: Receive the data from host. */
249 static void
250 __offload_target_host2tgt_p2 (OFFLOAD ofldt)
252 TRACE ("(last_var_ptr = %p, last_var_size = %d)",
253 last_var_ptr, last_var_size);
255 VarDesc vd1 = vd_host2tgt;
256 vd1.ptr = last_var_ptr;
257 vd1.size = last_var_size;
258 VarDesc2 vd2 = { "var", 0 };
260 __offload_target_enter (ofldt, 1, &vd1, &vd2);
261 __offload_target_leave (ofldt);
264 /* Send var_size bytes from var_ptr to host.
265 Part 1: Receive var_ptr and var_size from host. */
266 static void
267 __offload_target_tgt2host_p1 (OFFLOAD ofldt)
269 void *var_ptr = NULL;
270 size_t var_size = 0;
272 VarDesc vd1[2] = { vd_host2tgt, vd_host2tgt };
273 vd1[0].ptr = &var_ptr;
274 vd1[0].size = sizeof (void *);
275 vd1[1].ptr = &var_size;
276 vd1[1].size = sizeof (var_size);
277 VarDesc2 vd2[2] = { { "var_ptr", 0 }, { "var_size", 0 } };
279 __offload_target_enter (ofldt, 2, vd1, vd2);
280 TRACE ("(var_ptr = %p, var_size = %d)", var_ptr, var_size);
281 last_var_ptr = var_ptr;
282 last_var_size = var_size;
283 __offload_target_leave (ofldt);
286 /* Part 2: Send the data to host. */
287 static void
288 __offload_target_tgt2host_p2 (OFFLOAD ofldt)
290 TRACE ("(last_var_ptr = %p, last_var_size = %d)",
291 last_var_ptr, last_var_size);
293 VarDesc vd1 = vd_tgt2host;
294 vd1.ptr = last_var_ptr;
295 vd1.size = last_var_size;
296 VarDesc2 vd2 = { "var", 0 };
298 __offload_target_enter (ofldt, 1, &vd1, &vd2);
299 __offload_target_leave (ofldt);
302 /* Call offload function by the address fn_ptr and pass vars_ptr to it. */
303 static void
304 __offload_target_run (OFFLOAD ofldt)
306 void *fn_ptr;
307 void *vars_ptr;
309 VarDesc vd1[2] = { vd_host2tgt, vd_host2tgt };
310 vd1[0].ptr = &fn_ptr;
311 vd1[0].size = sizeof (void *);
312 vd1[1].ptr = &vars_ptr;
313 vd1[1].size = sizeof (void *);
314 VarDesc2 vd2[2] = { { "fn_ptr", 0 }, { "vars_ptr", 0 } };
316 __offload_target_enter (ofldt, 2, vd1, vd2);
317 TRACE ("(fn_ptr = %p, vars_ptr = %p)", fn_ptr, vars_ptr);
318 void (*fn)(void *) = (void (*)(void *)) fn_ptr;
319 fn (vars_ptr);
320 __offload_target_leave (ofldt);
324 /* This should be called from every library with offloading. */
325 extern "C" void
326 target_register_lib (const void *target_table)
328 TRACE ("(target_table = %p { %p, %p, %p, %p })", target_table,
329 ((void **) target_table)[0], ((void **) target_table)[1],
330 ((void **) target_table)[2], ((void **) target_table)[3]);
332 last_loaded_library = (void *) target_table;
335 /* Use __offload_target_main from liboffload. */
337 main (int argc, char **argv)
339 __offload_target_main ();
340 return 0;
344 /* Register offload_target_main's functions in the liboffload. */
346 struct Entry {
347 const char *name;
348 void *func;
351 #define REGISTER(f) \
352 extern "C" const Entry __offload_target_##f##_$entry \
353 __attribute__ ((section(".OffloadEntryTable."))) = { \
354 "__offload_target_"#f, \
355 (void *) __offload_target_##f \
357 REGISTER (init_proc);
358 REGISTER (table_p1);
359 REGISTER (table_p2);
360 REGISTER (alloc);
361 REGISTER (free);
362 REGISTER (host2tgt_p1);
363 REGISTER (host2tgt_p2);
364 REGISTER (tgt2host_p1);
365 REGISTER (tgt2host_p2);
366 REGISTER (run);
367 #undef REGISTER