Implement C _FloatN, _FloatNx types.
[gcc.git] / gcc / hsa-brig.c
1 /* Producing binary form of HSA BRIG from our internal representation.
2 Copyright (C) 2013-2016 Free Software Foundation, Inc.
3 Contributed by Martin Jambor <mjambor@suse.cz> and
4 Martin Liska <mliska@suse.cz>.
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "target.h"
27 #include "tm_p.h"
28 #include "is-a.h"
29 #include "vec.h"
30 #include "hash-table.h"
31 #include "hash-map.h"
32 #include "tree.h"
33 #include "tree-iterator.h"
34 #include "stor-layout.h"
35 #include "output.h"
36 #include "cfg.h"
37 #include "function.h"
38 #include "fold-const.h"
39 #include "stringpool.h"
40 #include "gimple-pretty-print.h"
41 #include "diagnostic-core.h"
42 #include "cgraph.h"
43 #include "dumpfile.h"
44 #include "print-tree.h"
45 #include "symbol-summary.h"
46 #include "hsa.h"
47 #include "gomp-constants.h"
48
49 /* Convert VAL to little endian form, if necessary. */
50
51 static uint16_t
52 lendian16 (uint16_t val)
53 {
54 #if GCC_VERSION >= 4008
55 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
56 return val;
57 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
58 return __builtin_bswap16 (val);
59 #else /* __ORDER_PDP_ENDIAN__ */
60 return val;
61 #endif
62 #else
63 // provide a safe slower default, with shifts and masking
64 #ifndef WORDS_BIGENDIAN
65 return val;
66 #else
67 return (val >> 8) | (val << 8);
68 #endif
69 #endif
70 }
71
72 /* Convert VAL to little endian form, if necessary. */
73
74 static uint32_t
75 lendian32 (uint32_t val)
76 {
77 #if GCC_VERSION >= 4006
78 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
79 return val;
80 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
81 return __builtin_bswap32 (val);
82 #else /* __ORDER_PDP_ENDIAN__ */
83 return (val >> 16) | (val << 16);
84 #endif
85 #else
86 // provide a safe slower default, with shifts and masking
87 #ifndef WORDS_BIGENDIAN
88 return val;
89 #else
90 val = ((val & 0xff00ff00) >> 8) | ((val & 0xff00ff) << 8);
91 return (val >> 16) | (val << 16);
92 #endif
93 #endif
94 }
95
96 /* Convert VAL to little endian form, if necessary. */
97
98 static uint64_t
99 lendian64 (uint64_t val)
100 {
101 #if GCC_VERSION >= 4006
102 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
103 return val;
104 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
105 return __builtin_bswap64 (val);
106 #else /* __ORDER_PDP_ENDIAN__ */
107 return (((val & 0xffffll) << 48)
108 | ((val & 0xffff0000ll) << 16)
109 | ((val & 0xffff00000000ll) >> 16)
110 | ((val & 0xffff000000000000ll) >> 48));
111 #endif
112 #else
113 // provide a safe slower default, with shifts and masking
114 #ifndef WORDS_BIGENDIAN
115 return val;
116 #else
117 val = (((val & 0xff00ff00ff00ff00ll) >> 8)
118 | ((val & 0x00ff00ff00ff00ffll) << 8));
119 val = ((( val & 0xffff0000ffff0000ll) >> 16)
120 | (( val & 0x0000ffff0000ffffll) << 16));
121 return (val >> 32) | (val << 32);
122 #endif
123 #endif
124 }
125
126 #define BRIG_ELF_SECTION_NAME ".brig"
127 #define BRIG_LABEL_STRING "hsa_brig"
128 #define BRIG_SECTION_DATA_NAME "hsa_data"
129 #define BRIG_SECTION_CODE_NAME "hsa_code"
130 #define BRIG_SECTION_OPERAND_NAME "hsa_operand"
131
132 #define BRIG_CHUNK_MAX_SIZE (64 * 1024)
133
134 /* Required HSA section alignment. */
135
136 #define HSA_SECTION_ALIGNMENT 16
137
138 /* Chunks of BRIG binary data. */
139
140 struct hsa_brig_data_chunk
141 {
142 /* Size of the data already stored into a chunk. */
143 unsigned size;
144
145 /* Pointer to the data. */
146 char *data;
147 };
148
149 /* Structure representing a BRIG section, holding and writing its data. */
150
151 class hsa_brig_section
152 {
153 public:
154 /* Section name that will be output to the BRIG. */
155 const char *section_name;
156 /* Size in bytes of all data stored in the section. */
157 unsigned total_size;
158 /* The size of the header of the section including padding. */
159 unsigned header_byte_count;
160 /* The size of the header of the section without any padding. */
161 unsigned header_byte_delta;
162
163 /* Buffers of binary data, each containing BRIG_CHUNK_MAX_SIZE bytes. */
164 vec <struct hsa_brig_data_chunk> chunks;
165
166 /* More convenient access to the last chunk from the vector above. */
167 struct hsa_brig_data_chunk *cur_chunk;
168
169 void allocate_new_chunk ();
170 void init (const char *name);
171 void release ();
172 void output ();
173 unsigned add (const void *data, unsigned len);
174 void round_size_up (int factor);
175 void *get_ptr_by_offset (unsigned int offset);
176 };
177
178 static struct hsa_brig_section brig_data, brig_code, brig_operand;
179 static uint32_t brig_insn_count;
180 static bool brig_initialized = false;
181
182 /* Mapping between emitted HSA functions and their offset in code segment. */
183 static hash_map<tree, BrigCodeOffset32_t> *function_offsets;
184
185 /* Hash map of emitted function declarations. */
186 static hash_map <tree, BrigDirectiveExecutable *> *emitted_declarations;
187
188 /* Hash table of emitted internal function declaration offsets. */
189 hash_table <hsa_internal_fn_hasher> *hsa_emitted_internal_decls;
190
191 /* List of sbr instructions. */
192 static vec <hsa_insn_sbr *> *switch_instructions;
193
194 struct function_linkage_pair
195 {
196 function_linkage_pair (tree decl, unsigned int off)
197 : function_decl (decl), offset (off) {}
198
199 /* Declaration of called function. */
200 tree function_decl;
201
202 /* Offset in operand section. */
203 unsigned int offset;
204 };
205
206 /* Vector of function calls where we need to resolve function offsets. */
207 static auto_vec <function_linkage_pair> function_call_linkage;
208
209 /* Add a new chunk, allocate data for it and initialize it. */
210
211 void
212 hsa_brig_section::allocate_new_chunk ()
213 {
214 struct hsa_brig_data_chunk new_chunk;
215
216 new_chunk.data = XCNEWVEC (char, BRIG_CHUNK_MAX_SIZE);
217 new_chunk.size = 0;
218 cur_chunk = chunks.safe_push (new_chunk);
219 }
220
221 /* Initialize the brig section. */
222
223 void
224 hsa_brig_section::init (const char *name)
225 {
226 section_name = name;
227 /* While the following computation is basically wrong, because the intent
228 certainly wasn't to have the first character of name and padding, which
229 are a part of sizeof (BrigSectionHeader), included in the first addend,
230 this is what the disassembler expects. */
231 total_size = sizeof (BrigSectionHeader) + strlen (section_name);
232 chunks.create (1);
233 allocate_new_chunk ();
234 header_byte_delta = total_size;
235 round_size_up (4);
236 header_byte_count = total_size;
237 }
238
239 /* Free all data in the section. */
240
241 void
242 hsa_brig_section::release ()
243 {
244 for (unsigned i = 0; i < chunks.length (); i++)
245 free (chunks[i].data);
246 chunks.release ();
247 cur_chunk = NULL;
248 }
249
250 /* Write the section to the output file to a section with the name given at
251 initialization. Switches the output section and does not restore it. */
252
253 void
254 hsa_brig_section::output ()
255 {
256 struct BrigSectionHeader section_header;
257 char padding[8];
258
259 section_header.byteCount = lendian64 (total_size);
260 section_header.headerByteCount = lendian32 (header_byte_count);
261 section_header.nameLength = lendian32 (strlen (section_name));
262 assemble_string ((const char *) &section_header, 16);
263 assemble_string (section_name, (section_header.nameLength));
264 memset (&padding, 0, sizeof (padding));
265 /* This is also a consequence of the wrong header size computation described
266 in a comment in hsa_brig_section::init. */
267 assemble_string (padding, 8);
268 for (unsigned i = 0; i < chunks.length (); i++)
269 assemble_string (chunks[i].data, chunks[i].size);
270 }
271
272 /* Add to the stream LEN bytes of opaque binary DATA. Return the offset at
273 which it was stored. */
274
275 unsigned
276 hsa_brig_section::add (const void *data, unsigned len)
277 {
278 unsigned offset = total_size;
279
280 gcc_assert (len <= BRIG_CHUNK_MAX_SIZE);
281 if (cur_chunk->size > (BRIG_CHUNK_MAX_SIZE - len))
282 allocate_new_chunk ();
283
284 memcpy (cur_chunk->data + cur_chunk->size, data, len);
285 cur_chunk->size += len;
286 total_size += len;
287
288 return offset;
289 }
290
291 /* Add padding to section so that its size is divisible by FACTOR. */
292
293 void
294 hsa_brig_section::round_size_up (int factor)
295 {
296 unsigned padding, res = total_size % factor;
297
298 if (res == 0)
299 return;
300
301 padding = factor - res;
302 total_size += padding;
303 if (cur_chunk->size > (BRIG_CHUNK_MAX_SIZE - padding))
304 {
305 padding -= BRIG_CHUNK_MAX_SIZE - cur_chunk->size;
306 cur_chunk->size = BRIG_CHUNK_MAX_SIZE;
307 allocate_new_chunk ();
308 }
309
310 cur_chunk->size += padding;
311 }
312
313 /* Return pointer to data by global OFFSET in the section. */
314
315 void *
316 hsa_brig_section::get_ptr_by_offset (unsigned int offset)
317 {
318 gcc_assert (offset < total_size);
319 offset -= header_byte_delta;
320
321 unsigned i;
322 for (i = 0; offset >= chunks[i].size; i++)
323 offset -= chunks[i].size;
324
325 return chunks[i].data + offset;
326 }
327
328 /* BRIG string data hashing. */
329
330 struct brig_string_slot
331 {
332 const char *s;
333 char prefix;
334 int len;
335 uint32_t offset;
336 };
337
338 /* Hash table helpers. */
339
340 struct brig_string_slot_hasher : pointer_hash <brig_string_slot>
341 {
342 static inline hashval_t hash (const value_type);
343 static inline bool equal (const value_type, const compare_type);
344 static inline void remove (value_type);
345 };
346
347 /* Returns a hash code for DS. Adapted from libiberty's htab_hash_string
348 to support strings that may not end in '\0'. */
349
350 inline hashval_t
351 brig_string_slot_hasher::hash (const value_type ds)
352 {
353 hashval_t r = ds->len;
354 int i;
355
356 for (i = 0; i < ds->len; i++)
357 r = r * 67 + (unsigned) ds->s[i] - 113;
358 r = r * 67 + (unsigned) ds->prefix - 113;
359 return r;
360 }
361
362 /* Returns nonzero if DS1 and DS2 are equal. */
363
364 inline bool
365 brig_string_slot_hasher::equal (const value_type ds1, const compare_type ds2)
366 {
367 if (ds1->len == ds2->len)
368 return ds1->prefix == ds2->prefix
369 && memcmp (ds1->s, ds2->s, ds1->len) == 0;
370
371 return 0;
372 }
373
374 /* Deallocate memory for DS upon its removal. */
375
376 inline void
377 brig_string_slot_hasher::remove (value_type ds)
378 {
379 free (const_cast<char *> (ds->s));
380 free (ds);
381 }
382
383 /* Hash for strings we output in order not to duplicate them needlessly. */
384
385 static hash_table<brig_string_slot_hasher> *brig_string_htab;
386
387 /* Emit a null terminated string STR to the data section and return its
388 offset in it. If PREFIX is non-zero, output it just before STR too.
389 Sanitize the string if SANITIZE option is set to true. */
390
391 static unsigned
392 brig_emit_string (const char *str, char prefix = 0, bool sanitize = true)
393 {
394 unsigned slen = strlen (str);
395 unsigned offset, len = slen + (prefix ? 1 : 0);
396 uint32_t hdr_len = lendian32 (len);
397 brig_string_slot s_slot;
398 brig_string_slot **slot;
399 char *str2;
400
401 str2 = xstrdup (str);
402
403 if (sanitize)
404 hsa_sanitize_name (str2);
405 s_slot.s = str2;
406 s_slot.len = slen;
407 s_slot.prefix = prefix;
408 s_slot.offset = 0;
409
410 slot = brig_string_htab->find_slot (&s_slot, INSERT);
411 if (*slot == NULL)
412 {
413 brig_string_slot *new_slot = XCNEW (brig_string_slot);
414
415 /* In theory we should fill in BrigData but that would mean copying
416 the string to a buffer for no reason, so we just emulate it. */
417 offset = brig_data.add (&hdr_len, sizeof (hdr_len));
418 if (prefix)
419 brig_data.add (&prefix, 1);
420
421 brig_data.add (str2, slen);
422 brig_data.round_size_up (4);
423
424 /* TODO: could use the string we just copied into
425 brig_string->cur_chunk */
426 new_slot->s = str2;
427 new_slot->len = slen;
428 new_slot->prefix = prefix;
429 new_slot->offset = offset;
430 *slot = new_slot;
431 }
432 else
433 {
434 offset = (*slot)->offset;
435 free (str2);
436 }
437
438 return offset;
439 }
440
441 /* Linked list of queued operands. */
442
443 static struct operand_queue
444 {
445 /* First from the chain of queued operands. */
446 hsa_op_base *first_op, *last_op;
447
448 /* The offset at which the next operand will be enqueued. */
449 unsigned projected_size;
450
451 } op_queue;
452
453 /* Unless already initialized, initialize infrastructure to produce BRIG. */
454
455 static void
456 brig_init (void)
457 {
458 brig_insn_count = 0;
459
460 if (brig_initialized)
461 return;
462
463 brig_string_htab = new hash_table<brig_string_slot_hasher> (37);
464 brig_data.init (BRIG_SECTION_DATA_NAME);
465 brig_code.init (BRIG_SECTION_CODE_NAME);
466 brig_operand.init (BRIG_SECTION_OPERAND_NAME);
467 brig_initialized = true;
468
469 struct BrigDirectiveModule moddir;
470 memset (&moddir, 0, sizeof (moddir));
471 moddir.base.byteCount = lendian16 (sizeof (moddir));
472
473 char *modname;
474 if (main_input_filename && *main_input_filename != '\0')
475 {
476 const char *part = strrchr (main_input_filename, '/');
477 if (!part)
478 part = main_input_filename;
479 else
480 part++;
481 modname = concat ("&__hsa_module_", part, NULL);
482 char *extension = strchr (modname, '.');
483 if (extension)
484 *extension = '\0';
485
486 /* As in LTO mode, we have to emit a different module names. */
487 if (flag_ltrans)
488 {
489 part = strrchr (asm_file_name, '/');
490 if (!part)
491 part = asm_file_name;
492 else
493 part++;
494 char *modname2;
495 asprintf (&modname2, "%s_%s", modname, part);
496 free (modname);
497 modname = modname2;
498 }
499
500 hsa_sanitize_name (modname);
501 moddir.name = brig_emit_string (modname);
502 free (modname);
503 }
504 else
505 moddir.name = brig_emit_string ("__hsa_module_unnamed", '&');
506 moddir.base.kind = lendian16 (BRIG_KIND_DIRECTIVE_MODULE);
507 moddir.hsailMajor = lendian32 (BRIG_VERSION_HSAIL_MAJOR);
508 moddir.hsailMinor = lendian32 (BRIG_VERSION_HSAIL_MINOR);
509 moddir.profile = hsa_full_profile_p () ? BRIG_PROFILE_FULL: BRIG_PROFILE_BASE;
510 if (hsa_machine_large_p ())
511 moddir.machineModel = BRIG_MACHINE_LARGE;
512 else
513 moddir.machineModel = BRIG_MACHINE_SMALL;
514 moddir.defaultFloatRound = BRIG_ROUND_FLOAT_DEFAULT;
515 brig_code.add (&moddir, sizeof (moddir));
516 }
517
518 /* Free all BRIG data. */
519
520 static void
521 brig_release_data (void)
522 {
523 delete brig_string_htab;
524 brig_data.release ();
525 brig_code.release ();
526 brig_operand.release ();
527
528 brig_initialized = 0;
529 }
530
531 /* Enqueue operation OP. Return the offset at which it will be stored. */
532
533 static unsigned int
534 enqueue_op (hsa_op_base *op)
535 {
536 unsigned ret;
537
538 if (op->m_brig_op_offset)
539 return op->m_brig_op_offset;
540
541 ret = op_queue.projected_size;
542 op->m_brig_op_offset = op_queue.projected_size;
543
544 if (!op_queue.first_op)
545 op_queue.first_op = op;
546 else
547 op_queue.last_op->m_next = op;
548 op_queue.last_op = op;
549
550 if (is_a <hsa_op_immed *> (op))
551 op_queue.projected_size += sizeof (struct BrigOperandConstantBytes);
552 else if (is_a <hsa_op_reg *> (op))
553 op_queue.projected_size += sizeof (struct BrigOperandRegister);
554 else if (is_a <hsa_op_address *> (op))
555 op_queue.projected_size += sizeof (struct BrigOperandAddress);
556 else if (is_a <hsa_op_code_ref *> (op))
557 op_queue.projected_size += sizeof (struct BrigOperandCodeRef);
558 else if (is_a <hsa_op_code_list *> (op))
559 op_queue.projected_size += sizeof (struct BrigOperandCodeList);
560 else if (is_a <hsa_op_operand_list *> (op))
561 op_queue.projected_size += sizeof (struct BrigOperandOperandList);
562 else
563 gcc_unreachable ();
564 return ret;
565 }
566
567
568 /* Emit directive describing a symbol if it has not been emitted already.
569 Return the offset of the directive. */
570
571 static unsigned
572 emit_directive_variable (struct hsa_symbol *symbol)
573 {
574 struct BrigDirectiveVariable dirvar;
575 unsigned name_offset;
576 static unsigned res_name_offset;
577
578 if (symbol->m_directive_offset)
579 return symbol->m_directive_offset;
580
581 memset (&dirvar, 0, sizeof (dirvar));
582 dirvar.base.byteCount = lendian16 (sizeof (dirvar));
583 dirvar.base.kind = lendian16 (BRIG_KIND_DIRECTIVE_VARIABLE);
584 dirvar.allocation = symbol->m_allocation;
585
586 char prefix = symbol->m_global_scope_p ? '&' : '%';
587
588 if (symbol->m_decl && TREE_CODE (symbol->m_decl) == RESULT_DECL)
589 {
590 if (res_name_offset == 0)
591 res_name_offset = brig_emit_string (symbol->m_name, '%');
592 name_offset = res_name_offset;
593 }
594 else if (symbol->m_name)
595 name_offset = brig_emit_string (symbol->m_name, prefix);
596 else
597 {
598 char buf[64];
599 snprintf (buf, 64, "__%s_%i", hsa_seg_name (symbol->m_segment),
600 symbol->m_name_number);
601 name_offset = brig_emit_string (buf, prefix);
602 }
603
604 dirvar.name = lendian32 (name_offset);
605 dirvar.init = 0;
606 dirvar.type = lendian16 (symbol->m_type);
607 dirvar.segment = symbol->m_segment;
608 dirvar.align = symbol->m_align;
609 dirvar.linkage = symbol->m_linkage;
610 dirvar.dim.lo = symbol->m_dim;
611 dirvar.dim.hi = symbol->m_dim >> 32;
612
613 /* Global variables are just declared and linked via HSA runtime. */
614 if (symbol->m_linkage != BRIG_ALLOCATION_PROGRAM)
615 dirvar.modifier |= BRIG_VARIABLE_DEFINITION;
616 dirvar.reserved = 0;
617
618 if (symbol->m_cst_value)
619 {
620 dirvar.modifier |= BRIG_VARIABLE_CONST;
621 dirvar.init = lendian32 (enqueue_op (symbol->m_cst_value));
622 }
623
624 symbol->m_directive_offset = brig_code.add (&dirvar, sizeof (dirvar));
625 return symbol->m_directive_offset;
626 }
627
628 /* Emit directives describing either a function declaration or
629 definition F. */
630
631 static BrigDirectiveExecutable *
632 emit_function_directives (hsa_function_representation *f, bool is_declaration)
633 {
634 struct BrigDirectiveExecutable fndir;
635 unsigned name_offset, inarg_off, scoped_off, next_toplev_off;
636 int count = 0;
637 BrigDirectiveExecutable *ptr_to_fndir;
638 hsa_symbol *sym;
639
640 if (!f->m_declaration_p)
641 for (int i = 0; f->m_global_symbols.iterate (i, &sym); i++)
642 {
643 gcc_assert (!sym->m_emitted_to_brig);
644 sym->m_emitted_to_brig = true;
645 emit_directive_variable (sym);
646 brig_insn_count++;
647 }
648
649 name_offset = brig_emit_string (f->m_name, '&');
650 inarg_off = brig_code.total_size + sizeof (fndir)
651 + (f->m_output_arg ? sizeof (struct BrigDirectiveVariable) : 0);
652 scoped_off = inarg_off
653 + f->m_input_args.length () * sizeof (struct BrigDirectiveVariable);
654
655 if (!f->m_declaration_p)
656 {
657 count += f->m_spill_symbols.length ();
658 count += f->m_private_variables.length ();
659 }
660
661 next_toplev_off = scoped_off + count * sizeof (struct BrigDirectiveVariable);
662
663 memset (&fndir, 0, sizeof (fndir));
664 fndir.base.byteCount = lendian16 (sizeof (fndir));
665 fndir.base.kind = lendian16 (f->m_kern_p ? BRIG_KIND_DIRECTIVE_KERNEL
666 : BRIG_KIND_DIRECTIVE_FUNCTION);
667 fndir.name = lendian32 (name_offset);
668 fndir.inArgCount = lendian16 (f->m_input_args.length ());
669 fndir.outArgCount = lendian16 (f->m_output_arg ? 1 : 0);
670 fndir.firstInArg = lendian32 (inarg_off);
671 fndir.firstCodeBlockEntry = lendian32 (scoped_off);
672 fndir.nextModuleEntry = lendian32 (next_toplev_off);
673 fndir.linkage = f->get_linkage ();
674 if (!f->m_declaration_p)
675 fndir.modifier |= BRIG_EXECUTABLE_DEFINITION;
676 memset (&fndir.reserved, 0, sizeof (fndir.reserved));
677
678 /* Once we put a definition of function_offsets, we should not overwrite
679 it with a declaration of the function. */
680 if (f->m_internal_fn == NULL)
681 {
682 if (!function_offsets->get (f->m_decl) || !is_declaration)
683 function_offsets->put (f->m_decl, brig_code.total_size);
684 }
685 else
686 {
687 /* Internal function. */
688 hsa_internal_fn **slot
689 = hsa_emitted_internal_decls->find_slot (f->m_internal_fn, INSERT);
690 hsa_internal_fn *int_fn = new hsa_internal_fn (f->m_internal_fn);
691 int_fn->m_offset = brig_code.total_size;
692 *slot = int_fn;
693 }
694
695 brig_code.add (&fndir, sizeof (fndir));
696 /* terrible hack: we need to set instCount after we emit all
697 insns, but we need to emit directive in order, and we emit directives
698 during insn emitting. So we need to emit the FUNCTION directive
699 early, then the insns, and then we need to set instCount, so remember
700 a pointer to it, in some horrible way. cur_chunk.data+size points
701 directly to after fndir here. */
702 ptr_to_fndir
703 = (BrigDirectiveExecutable *)(brig_code.cur_chunk->data
704 + brig_code.cur_chunk->size
705 - sizeof (fndir));
706
707 if (f->m_output_arg)
708 emit_directive_variable (f->m_output_arg);
709 for (unsigned i = 0; i < f->m_input_args.length (); i++)
710 emit_directive_variable (f->m_input_args[i]);
711
712 if (!f->m_declaration_p)
713 {
714 for (int i = 0; f->m_spill_symbols.iterate (i, &sym); i++)
715 {
716 emit_directive_variable (sym);
717 brig_insn_count++;
718 }
719 for (unsigned i = 0; i < f->m_private_variables.length (); i++)
720 {
721 emit_directive_variable (f->m_private_variables[i]);
722 brig_insn_count++;
723 }
724 }
725
726 return ptr_to_fndir;
727 }
728
729 /* Emit a label directive for the given HBB. We assume it is about to start on
730 the current offset in the code section. */
731
732 static void
733 emit_bb_label_directive (hsa_bb *hbb)
734 {
735 struct BrigDirectiveLabel lbldir;
736
737 lbldir.base.byteCount = lendian16 (sizeof (lbldir));
738 lbldir.base.kind = lendian16 (BRIG_KIND_DIRECTIVE_LABEL);
739 char buf[32];
740 snprintf (buf, 32, "BB_%u_%i", DECL_UID (current_function_decl),
741 hbb->m_index);
742 lbldir.name = lendian32 (brig_emit_string (buf, '@'));
743
744 hbb->m_label_ref.m_directive_offset = brig_code.add (&lbldir,
745 sizeof (lbldir));
746 brig_insn_count++;
747 }
748
749 /* Map a normal HSAIL type to the type of the equivalent BRIG operand
750 holding such, for constants and registers. */
751
752 static BrigType16_t
753 regtype_for_type (BrigType16_t t)
754 {
755 switch (t)
756 {
757 case BRIG_TYPE_B1:
758 return BRIG_TYPE_B1;
759
760 case BRIG_TYPE_U8:
761 case BRIG_TYPE_U16:
762 case BRIG_TYPE_U32:
763 case BRIG_TYPE_S8:
764 case BRIG_TYPE_S16:
765 case BRIG_TYPE_S32:
766 case BRIG_TYPE_B8:
767 case BRIG_TYPE_B16:
768 case BRIG_TYPE_B32:
769 case BRIG_TYPE_F16:
770 case BRIG_TYPE_F32:
771 case BRIG_TYPE_U8X4:
772 case BRIG_TYPE_U16X2:
773 case BRIG_TYPE_S8X4:
774 case BRIG_TYPE_S16X2:
775 case BRIG_TYPE_F16X2:
776 return BRIG_TYPE_B32;
777
778 case BRIG_TYPE_U64:
779 case BRIG_TYPE_S64:
780 case BRIG_TYPE_F64:
781 case BRIG_TYPE_B64:
782 case BRIG_TYPE_U8X8:
783 case BRIG_TYPE_U16X4:
784 case BRIG_TYPE_U32X2:
785 case BRIG_TYPE_S8X8:
786 case BRIG_TYPE_S16X4:
787 case BRIG_TYPE_S32X2:
788 case BRIG_TYPE_F16X4:
789 case BRIG_TYPE_F32X2:
790 return BRIG_TYPE_B64;
791
792 case BRIG_TYPE_B128:
793 case BRIG_TYPE_U8X16:
794 case BRIG_TYPE_U16X8:
795 case BRIG_TYPE_U32X4:
796 case BRIG_TYPE_U64X2:
797 case BRIG_TYPE_S8X16:
798 case BRIG_TYPE_S16X8:
799 case BRIG_TYPE_S32X4:
800 case BRIG_TYPE_S64X2:
801 case BRIG_TYPE_F16X8:
802 case BRIG_TYPE_F32X4:
803 case BRIG_TYPE_F64X2:
804 return BRIG_TYPE_B128;
805
806 default:
807 gcc_unreachable ();
808 }
809 }
810
811 /* Return the length of the BRIG type TYPE that is going to be streamed out as
812 an immediate constant (so it must not be B1). */
813
814 unsigned
815 hsa_get_imm_brig_type_len (BrigType16_t type)
816 {
817 BrigType16_t base_type = type & BRIG_TYPE_BASE_MASK;
818 BrigType16_t pack_type = type & BRIG_TYPE_PACK_MASK;
819
820 switch (pack_type)
821 {
822 case BRIG_TYPE_PACK_NONE:
823 break;
824 case BRIG_TYPE_PACK_32:
825 return 4;
826 case BRIG_TYPE_PACK_64:
827 return 8;
828 case BRIG_TYPE_PACK_128:
829 return 16;
830 default:
831 gcc_unreachable ();
832 }
833
834 switch (base_type)
835 {
836 case BRIG_TYPE_U8:
837 case BRIG_TYPE_S8:
838 case BRIG_TYPE_B8:
839 return 1;
840 case BRIG_TYPE_U16:
841 case BRIG_TYPE_S16:
842 case BRIG_TYPE_F16:
843 case BRIG_TYPE_B16:
844 return 2;
845 case BRIG_TYPE_U32:
846 case BRIG_TYPE_S32:
847 case BRIG_TYPE_F32:
848 case BRIG_TYPE_B32:
849 return 4;
850 case BRIG_TYPE_U64:
851 case BRIG_TYPE_S64:
852 case BRIG_TYPE_F64:
853 case BRIG_TYPE_B64:
854 return 8;
855 case BRIG_TYPE_B128:
856 return 16;
857 default:
858 gcc_unreachable ();
859 }
860 }
861
862 /* Emit one scalar VALUE to the buffer DATA intended for BRIG emission.
863 If NEED_LEN is not equal to zero, shrink or extend the value
864 to NEED_LEN bytes. Return how many bytes were written. */
865
866 static int
867 emit_immediate_scalar_to_buffer (tree value, char *data, unsigned need_len)
868 {
869 union hsa_bytes bytes;
870
871 memset (&bytes, 0, sizeof (bytes));
872 tree type = TREE_TYPE (value);
873 gcc_checking_assert (TREE_CODE (type) != VECTOR_TYPE);
874
875 unsigned data_len = tree_to_uhwi (TYPE_SIZE (type)) / BITS_PER_UNIT;
876 if (INTEGRAL_TYPE_P (type)
877 || (POINTER_TYPE_P (type) && TREE_CODE (value) == INTEGER_CST))
878 switch (data_len)
879 {
880 case 1:
881 bytes.b8 = (uint8_t) TREE_INT_CST_LOW (value);
882 break;
883 case 2:
884 bytes.b16 = (uint16_t) TREE_INT_CST_LOW (value);
885 break;
886 case 4:
887 bytes.b32 = (uint32_t) TREE_INT_CST_LOW (value);
888 break;
889 case 8:
890 bytes.b64 = (uint64_t) TREE_INT_CST_LOW (value);
891 break;
892 default:
893 gcc_unreachable ();
894 }
895 else if (SCALAR_FLOAT_TYPE_P (type))
896 {
897 if (data_len == 2)
898 {
899 sorry ("Support for HSA does not implement immediate 16 bit FPU "
900 "operands");
901 return 2;
902 }
903 unsigned int_len = GET_MODE_SIZE (TYPE_MODE (type));
904 /* There are always 32 bits in each long, no matter the size of
905 the hosts long. */
906 long tmp[6];
907
908 real_to_target (tmp, TREE_REAL_CST_PTR (value), TYPE_MODE (type));
909
910 if (int_len == 4)
911 bytes.b32 = (uint32_t) tmp[0];
912 else
913 {
914 bytes.b64 = (uint64_t)(uint32_t) tmp[1];
915 bytes.b64 <<= 32;
916 bytes.b64 |= (uint32_t) tmp[0];
917 }
918 }
919 else
920 gcc_unreachable ();
921
922 int len;
923 if (need_len == 0)
924 len = data_len;
925 else
926 len = need_len;
927
928 memcpy (data, &bytes, len);
929 return len;
930 }
931
932 char *
933 hsa_op_immed::emit_to_buffer (unsigned *brig_repr_size)
934 {
935 char *brig_repr;
936 *brig_repr_size = hsa_get_imm_brig_type_len (m_type);
937
938 if (m_tree_value != NULL_TREE)
939 {
940 /* Update brig_repr_size for special tree values. */
941 if (TREE_CODE (m_tree_value) == STRING_CST)
942 *brig_repr_size = TREE_STRING_LENGTH (m_tree_value);
943 else if (TREE_CODE (m_tree_value) == CONSTRUCTOR)
944 *brig_repr_size
945 = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (m_tree_value)));
946
947 unsigned total_len = *brig_repr_size;
948
949 /* As we can have a constructor with fewer elements, fill the memory
950 with zeros. */
951 brig_repr = XCNEWVEC (char, total_len);
952 char *p = brig_repr;
953
954 if (TREE_CODE (m_tree_value) == VECTOR_CST)
955 {
956 int i, num = VECTOR_CST_NELTS (m_tree_value);
957 for (i = 0; i < num; i++)
958 {
959 tree v = VECTOR_CST_ELT (m_tree_value, i);
960 unsigned actual = emit_immediate_scalar_to_buffer (v, p, 0);
961 total_len -= actual;
962 p += actual;
963 }
964 /* Vectors should have the exact size. */
965 gcc_assert (total_len == 0);
966 }
967 else if (TREE_CODE (m_tree_value) == STRING_CST)
968 memcpy (brig_repr, TREE_STRING_POINTER (m_tree_value),
969 TREE_STRING_LENGTH (m_tree_value));
970 else if (TREE_CODE (m_tree_value) == COMPLEX_CST)
971 {
972 gcc_assert (total_len % 2 == 0);
973 unsigned actual;
974 actual
975 = emit_immediate_scalar_to_buffer (TREE_REALPART (m_tree_value), p,
976 total_len / 2);
977
978 gcc_assert (actual == total_len / 2);
979 p += actual;
980
981 actual
982 = emit_immediate_scalar_to_buffer (TREE_IMAGPART (m_tree_value), p,
983 total_len / 2);
984 gcc_assert (actual == total_len / 2);
985 }
986 else if (TREE_CODE (m_tree_value) == CONSTRUCTOR)
987 {
988 unsigned len = vec_safe_length (CONSTRUCTOR_ELTS (m_tree_value));
989 for (unsigned i = 0; i < len; i++)
990 {
991 tree v = CONSTRUCTOR_ELT (m_tree_value, i)->value;
992 unsigned actual = emit_immediate_scalar_to_buffer (v, p, 0);
993 total_len -= actual;
994 p += actual;
995 }
996 }
997 else
998 emit_immediate_scalar_to_buffer (m_tree_value, p, total_len);
999 }
1000 else
1001 {
1002 hsa_bytes bytes;
1003
1004 switch (*brig_repr_size)
1005 {
1006 case 1:
1007 bytes.b8 = (uint8_t) m_int_value;
1008 break;
1009 case 2:
1010 bytes.b16 = (uint16_t) m_int_value;
1011 break;
1012 case 4:
1013 bytes.b32 = (uint32_t) m_int_value;
1014 break;
1015 case 8:
1016 bytes.b64 = (uint64_t) m_int_value;
1017 break;
1018 default:
1019 gcc_unreachable ();
1020 }
1021
1022 brig_repr = XNEWVEC (char, *brig_repr_size);
1023 memcpy (brig_repr, &bytes, *brig_repr_size);
1024 }
1025
1026 return brig_repr;
1027 }
1028
1029 /* Emit an immediate BRIG operand IMM. The BRIG type of the immediate might
1030 have been massaged to comply with various HSA/BRIG type requirements, so the
1031 only important aspect of that is the length (because HSAIL might expect
1032 smaller constants or become bit-data). The data should be represented
1033 according to what is in the tree representation. */
1034
1035 static void
1036 emit_immediate_operand (hsa_op_immed *imm)
1037 {
1038 unsigned brig_repr_size;
1039 char *brig_repr = imm->emit_to_buffer (&brig_repr_size);
1040 struct BrigOperandConstantBytes out;
1041
1042 memset (&out, 0, sizeof (out));
1043 out.base.byteCount = lendian16 (sizeof (out));
1044 out.base.kind = lendian16 (BRIG_KIND_OPERAND_CONSTANT_BYTES);
1045 uint32_t byteCount = lendian32 (brig_repr_size);
1046 out.type = lendian16 (imm->m_type);
1047 out.bytes = lendian32 (brig_data.add (&byteCount, sizeof (byteCount)));
1048 brig_operand.add (&out, sizeof (out));
1049 brig_data.add (brig_repr, brig_repr_size);
1050 brig_data.round_size_up (4);
1051
1052 free (brig_repr);
1053 }
1054
1055 /* Emit a register BRIG operand REG. */
1056
1057 static void
1058 emit_register_operand (hsa_op_reg *reg)
1059 {
1060 struct BrigOperandRegister out;
1061
1062 out.base.byteCount = lendian16 (sizeof (out));
1063 out.base.kind = lendian16 (BRIG_KIND_OPERAND_REGISTER);
1064 out.regNum = lendian32 (reg->m_hard_num);
1065
1066 switch (regtype_for_type (reg->m_type))
1067 {
1068 case BRIG_TYPE_B32:
1069 out.regKind = BRIG_REGISTER_KIND_SINGLE;
1070 break;
1071 case BRIG_TYPE_B64:
1072 out.regKind = BRIG_REGISTER_KIND_DOUBLE;
1073 break;
1074 case BRIG_TYPE_B128:
1075 out.regKind = BRIG_REGISTER_KIND_QUAD;
1076 break;
1077 case BRIG_TYPE_B1:
1078 out.regKind = BRIG_REGISTER_KIND_CONTROL;
1079 break;
1080 default:
1081 gcc_unreachable ();
1082 }
1083
1084 brig_operand.add (&out, sizeof (out));
1085 }
1086
1087 /* Emit an address BRIG operand ADDR. */
1088
1089 static void
1090 emit_address_operand (hsa_op_address *addr)
1091 {
1092 struct BrigOperandAddress out;
1093
1094 out.base.byteCount = lendian16 (sizeof (out));
1095 out.base.kind = lendian16 (BRIG_KIND_OPERAND_ADDRESS);
1096 out.symbol = addr->m_symbol
1097 ? lendian32 (emit_directive_variable (addr->m_symbol)) : 0;
1098 out.reg = addr->m_reg ? lendian32 (enqueue_op (addr->m_reg)) : 0;
1099
1100 if (sizeof (addr->m_imm_offset) == 8)
1101 {
1102 out.offset.lo = lendian32 (addr->m_imm_offset);
1103 out.offset.hi = lendian32 (addr->m_imm_offset >> 32);
1104 }
1105 else
1106 {
1107 gcc_assert (sizeof (addr->m_imm_offset) == 4);
1108 out.offset.lo = lendian32 (addr->m_imm_offset);
1109 out.offset.hi = 0;
1110 }
1111
1112 brig_operand.add (&out, sizeof (out));
1113 }
1114
1115 /* Emit a code reference operand REF. */
1116
1117 static void
1118 emit_code_ref_operand (hsa_op_code_ref *ref)
1119 {
1120 struct BrigOperandCodeRef out;
1121
1122 out.base.byteCount = lendian16 (sizeof (out));
1123 out.base.kind = lendian16 (BRIG_KIND_OPERAND_CODE_REF);
1124 out.ref = lendian32 (ref->m_directive_offset);
1125 brig_operand.add (&out, sizeof (out));
1126 }
1127
1128 /* Emit a code list operand CODE_LIST. */
1129
1130 static void
1131 emit_code_list_operand (hsa_op_code_list *code_list)
1132 {
1133 struct BrigOperandCodeList out;
1134 unsigned args = code_list->m_offsets.length ();
1135
1136 for (unsigned i = 0; i < args; i++)
1137 gcc_assert (code_list->m_offsets[i]);
1138
1139 out.base.byteCount = lendian16 (sizeof (out));
1140 out.base.kind = lendian16 (BRIG_KIND_OPERAND_CODE_LIST);
1141
1142 uint32_t byteCount = lendian32 (4 * args);
1143
1144 out.elements = lendian32 (brig_data.add (&byteCount, sizeof (byteCount)));
1145 brig_data.add (code_list->m_offsets.address (), args * sizeof (uint32_t));
1146 brig_data.round_size_up (4);
1147 brig_operand.add (&out, sizeof (out));
1148 }
1149
1150 /* Emit an operand list operand OPERAND_LIST. */
1151
1152 static void
1153 emit_operand_list_operand (hsa_op_operand_list *operand_list)
1154 {
1155 struct BrigOperandOperandList out;
1156 unsigned args = operand_list->m_offsets.length ();
1157
1158 for (unsigned i = 0; i < args; i++)
1159 gcc_assert (operand_list->m_offsets[i]);
1160
1161 out.base.byteCount = lendian16 (sizeof (out));
1162 out.base.kind = lendian16 (BRIG_KIND_OPERAND_OPERAND_LIST);
1163
1164 uint32_t byteCount = lendian32 (4 * args);
1165
1166 out.elements = lendian32 (brig_data.add (&byteCount, sizeof (byteCount)));
1167 brig_data.add (operand_list->m_offsets.address (), args * sizeof (uint32_t));
1168 brig_data.round_size_up (4);
1169 brig_operand.add (&out, sizeof (out));
1170 }
1171
1172 /* Emit all operands queued for writing. */
1173
1174 static void
1175 emit_queued_operands (void)
1176 {
1177 for (hsa_op_base *op = op_queue.first_op; op; op = op->m_next)
1178 {
1179 gcc_assert (op->m_brig_op_offset == brig_operand.total_size);
1180 if (hsa_op_immed *imm = dyn_cast <hsa_op_immed *> (op))
1181 emit_immediate_operand (imm);
1182 else if (hsa_op_reg *reg = dyn_cast <hsa_op_reg *> (op))
1183 emit_register_operand (reg);
1184 else if (hsa_op_address *addr = dyn_cast <hsa_op_address *> (op))
1185 emit_address_operand (addr);
1186 else if (hsa_op_code_ref *ref = dyn_cast <hsa_op_code_ref *> (op))
1187 emit_code_ref_operand (ref);
1188 else if (hsa_op_code_list *code_list = dyn_cast <hsa_op_code_list *> (op))
1189 emit_code_list_operand (code_list);
1190 else if (hsa_op_operand_list *l = dyn_cast <hsa_op_operand_list *> (op))
1191 emit_operand_list_operand (l);
1192 else
1193 gcc_unreachable ();
1194 }
1195 }
1196
1197 /* Emit directives describing the function that is used for
1198 a function declaration. */
1199
1200 static BrigDirectiveExecutable *
1201 emit_function_declaration (tree decl)
1202 {
1203 hsa_function_representation *f = hsa_generate_function_declaration (decl);
1204
1205 BrigDirectiveExecutable *e = emit_function_directives (f, true);
1206 emit_queued_operands ();
1207
1208 delete f;
1209
1210 return e;
1211 }
1212
1213 /* Emit directives describing the function that is used for
1214 an internal function declaration. */
1215
1216 static BrigDirectiveExecutable *
1217 emit_internal_fn_decl (hsa_internal_fn *fn)
1218 {
1219 hsa_function_representation *f = hsa_generate_internal_fn_decl (fn);
1220
1221 BrigDirectiveExecutable *e = emit_function_directives (f, true);
1222 emit_queued_operands ();
1223
1224 delete f;
1225
1226 return e;
1227 }
1228
1229 /* Enqueue all operands of INSN and return offset to BRIG data section
1230 to list of operand offsets. */
1231
1232 static unsigned
1233 emit_insn_operands (hsa_insn_basic *insn)
1234 {
1235 auto_vec<BrigOperandOffset32_t, HSA_BRIG_INT_STORAGE_OPERANDS>
1236 operand_offsets;
1237
1238 unsigned l = insn->operand_count ();
1239 operand_offsets.safe_grow (l);
1240
1241 for (unsigned i = 0; i < l; i++)
1242 operand_offsets[i] = lendian32 (enqueue_op (insn->get_op (i)));
1243
1244 /* We have N operands so use 4 * N for the byte_count. */
1245 uint32_t byte_count = lendian32 (4 * l);
1246
1247 unsigned offset = brig_data.add (&byte_count, sizeof (byte_count));
1248 brig_data.add (operand_offsets.address (),
1249 l * sizeof (BrigOperandOffset32_t));
1250
1251 brig_data.round_size_up (4);
1252
1253 return offset;
1254 }
1255
1256 /* Enqueue operand OP0, OP1, OP2 (if different from NULL) and return offset
1257 to BRIG data section to list of operand offsets. */
1258
1259 static unsigned
1260 emit_operands (hsa_op_base *op0, hsa_op_base *op1 = NULL,
1261 hsa_op_base *op2 = NULL)
1262 {
1263 auto_vec<BrigOperandOffset32_t, HSA_BRIG_INT_STORAGE_OPERANDS>
1264 operand_offsets;
1265
1266 gcc_checking_assert (op0 != NULL);
1267 operand_offsets.safe_push (enqueue_op (op0));
1268
1269 if (op1 != NULL)
1270 {
1271 operand_offsets.safe_push (enqueue_op (op1));
1272 if (op2 != NULL)
1273 operand_offsets.safe_push (enqueue_op (op2));
1274 }
1275
1276 unsigned l = operand_offsets.length ();
1277
1278 /* We have N operands so use 4 * N for the byte_count. */
1279 uint32_t byte_count = lendian32 (4 * l);
1280
1281 unsigned offset = brig_data.add (&byte_count, sizeof (byte_count));
1282 brig_data.add (operand_offsets.address (),
1283 l * sizeof (BrigOperandOffset32_t));
1284
1285 brig_data.round_size_up (4);
1286
1287 return offset;
1288 }
1289
1290 /* Emit an HSA memory instruction and all necessary directives, schedule
1291 necessary operands for writing. */
1292
1293 static void
1294 emit_memory_insn (hsa_insn_mem *mem)
1295 {
1296 struct BrigInstMem repr;
1297 gcc_checking_assert (mem->operand_count () == 2);
1298
1299 hsa_op_address *addr = as_a <hsa_op_address *> (mem->get_op (1));
1300
1301 /* This is necessary because of the erroneous typedef of
1302 BrigMemoryModifier8_t which introduces padding which may then contain
1303 random stuff (which we do not want so that we can test things don't
1304 change). */
1305 memset (&repr, 0, sizeof (repr));
1306 repr.base.base.byteCount = lendian16 (sizeof (repr));
1307 repr.base.base.kind = lendian16 (BRIG_KIND_INST_MEM);
1308 repr.base.opcode = lendian16 (mem->m_opcode);
1309 repr.base.type = lendian16 (mem->m_type);
1310 repr.base.operands = lendian32 (emit_insn_operands (mem));
1311
1312 if (addr->m_symbol)
1313 repr.segment = addr->m_symbol->m_segment;
1314 else
1315 repr.segment = BRIG_SEGMENT_FLAT;
1316 repr.modifier = 0;
1317 repr.equivClass = mem->m_equiv_class;
1318 repr.align = mem->m_align;
1319 if (mem->m_opcode == BRIG_OPCODE_LD)
1320 repr.width = BRIG_WIDTH_1;
1321 else
1322 repr.width = BRIG_WIDTH_NONE;
1323 memset (&repr.reserved, 0, sizeof (repr.reserved));
1324 brig_code.add (&repr, sizeof (repr));
1325 brig_insn_count++;
1326 }
1327
1328 /* Emit an HSA signal memory instruction and all necessary directives, schedule
1329 necessary operands for writing. */
1330
1331 static void
1332 emit_signal_insn (hsa_insn_signal *mem)
1333 {
1334 struct BrigInstSignal repr;
1335
1336 /* This is necessary because of the erroneous typedef of
1337 BrigMemoryModifier8_t which introduces padding which may then contain
1338 random stuff (which we do not want so that we can test things don't
1339 change). */
1340 memset (&repr, 0, sizeof (repr));
1341 repr.base.base.byteCount = lendian16 (sizeof (repr));
1342 repr.base.base.kind = lendian16 (BRIG_KIND_INST_SIGNAL);
1343 repr.base.opcode = lendian16 (mem->m_opcode);
1344 repr.base.type = lendian16 (mem->m_type);
1345 repr.base.operands = lendian32 (emit_insn_operands (mem));
1346
1347 repr.memoryOrder = mem->m_memoryorder;
1348 repr.signalOperation = mem->m_atomicop;
1349 repr.signalType = BRIG_TYPE_SIG64;
1350
1351 brig_code.add (&repr, sizeof (repr));
1352 brig_insn_count++;
1353 }
1354
1355 /* Emit an HSA atomic memory instruction and all necessary directives, schedule
1356 necessary operands for writing. */
1357
1358 static void
1359 emit_atomic_insn (hsa_insn_atomic *mem)
1360 {
1361 struct BrigInstAtomic repr;
1362
1363 /* Either operand[0] or operand[1] must be an address operand. */
1364 hsa_op_address *addr = NULL;
1365 if (is_a <hsa_op_address *> (mem->get_op (0)))
1366 addr = as_a <hsa_op_address *> (mem->get_op (0));
1367 else
1368 addr = as_a <hsa_op_address *> (mem->get_op (1));
1369
1370 /* This is necessary because of the erroneous typedef of
1371 BrigMemoryModifier8_t which introduces padding which may then contain
1372 random stuff (which we do not want so that we can test things don't
1373 change). */
1374 memset (&repr, 0, sizeof (repr));
1375 repr.base.base.byteCount = lendian16 (sizeof (repr));
1376 repr.base.base.kind = lendian16 (BRIG_KIND_INST_ATOMIC);
1377 repr.base.opcode = lendian16 (mem->m_opcode);
1378 repr.base.type = lendian16 (mem->m_type);
1379 repr.base.operands = lendian32 (emit_insn_operands (mem));
1380
1381 if (addr->m_symbol)
1382 repr.segment = addr->m_symbol->m_segment;
1383 else
1384 repr.segment = BRIG_SEGMENT_FLAT;
1385 repr.memoryOrder = mem->m_memoryorder;
1386 repr.memoryScope = mem->m_memoryscope;
1387 repr.atomicOperation = mem->m_atomicop;
1388
1389 brig_code.add (&repr, sizeof (repr));
1390 brig_insn_count++;
1391 }
1392
1393 /* Emit an HSA LDA instruction and all necessary directives, schedule
1394 necessary operands for writing. */
1395
1396 static void
1397 emit_addr_insn (hsa_insn_basic *insn)
1398 {
1399 struct BrigInstAddr repr;
1400
1401 hsa_op_address *addr = as_a <hsa_op_address *> (insn->get_op (1));
1402
1403 repr.base.base.byteCount = lendian16 (sizeof (repr));
1404 repr.base.base.kind = lendian16 (BRIG_KIND_INST_ADDR);
1405 repr.base.opcode = lendian16 (insn->m_opcode);
1406 repr.base.type = lendian16 (insn->m_type);
1407 repr.base.operands = lendian32 (emit_insn_operands (insn));
1408
1409 if (addr->m_symbol)
1410 repr.segment = addr->m_symbol->m_segment;
1411 else
1412 repr.segment = BRIG_SEGMENT_FLAT;
1413 memset (&repr.reserved, 0, sizeof (repr.reserved));
1414
1415 brig_code.add (&repr, sizeof (repr));
1416 brig_insn_count++;
1417 }
1418
1419 /* Emit an HSA segment conversion instruction and all necessary directives,
1420 schedule necessary operands for writing. */
1421
1422 static void
1423 emit_segment_insn (hsa_insn_seg *seg)
1424 {
1425 struct BrigInstSegCvt repr;
1426
1427 repr.base.base.byteCount = lendian16 (sizeof (repr));
1428 repr.base.base.kind = lendian16 (BRIG_KIND_INST_SEG_CVT);
1429 repr.base.opcode = lendian16 (seg->m_opcode);
1430 repr.base.type = lendian16 (seg->m_type);
1431 repr.base.operands = lendian32 (emit_insn_operands (seg));
1432 repr.sourceType = lendian16 (as_a <hsa_op_reg *> (seg->get_op (1))->m_type);
1433 repr.segment = seg->m_segment;
1434 repr.modifier = 0;
1435
1436 brig_code.add (&repr, sizeof (repr));
1437
1438 brig_insn_count++;
1439 }
1440
1441 /* Emit an HSA alloca instruction and all necessary directives,
1442 schedule necessary operands for writing. */
1443
1444 static void
1445 emit_alloca_insn (hsa_insn_alloca *alloca)
1446 {
1447 struct BrigInstMem repr;
1448 gcc_checking_assert (alloca->operand_count () == 2);
1449
1450 /* This is necessary because of the erroneous typedef of
1451 BrigMemoryModifier8_t which introduces padding which may then contain
1452 random stuff (which we do not want so that we can test things don't
1453 change). */
1454 memset (&repr, 0, sizeof (repr));
1455 repr.base.base.byteCount = lendian16 (sizeof (repr));
1456 repr.base.base.kind = lendian16 (BRIG_KIND_INST_MEM);
1457 repr.base.opcode = lendian16 (alloca->m_opcode);
1458 repr.base.type = lendian16 (alloca->m_type);
1459 repr.base.operands = lendian32 (emit_insn_operands (alloca));
1460 repr.segment = BRIG_SEGMENT_PRIVATE;
1461 repr.modifier = 0;
1462 repr.equivClass = 0;
1463 repr.align = alloca->m_align;
1464 repr.width = BRIG_WIDTH_NONE;
1465 memset (&repr.reserved, 0, sizeof (repr.reserved));
1466 brig_code.add (&repr, sizeof (repr));
1467 brig_insn_count++;
1468 }
1469
1470 /* Emit an HSA comparison instruction and all necessary directives,
1471 schedule necessary operands for writing. */
1472
1473 static void
1474 emit_cmp_insn (hsa_insn_cmp *cmp)
1475 {
1476 struct BrigInstCmp repr;
1477
1478 memset (&repr, 0, sizeof (repr));
1479 repr.base.base.byteCount = lendian16 (sizeof (repr));
1480 repr.base.base.kind = lendian16 (BRIG_KIND_INST_CMP);
1481 repr.base.opcode = lendian16 (cmp->m_opcode);
1482 repr.base.type = lendian16 (cmp->m_type);
1483 repr.base.operands = lendian32 (emit_insn_operands (cmp));
1484
1485 if (is_a <hsa_op_reg *> (cmp->get_op (1)))
1486 repr.sourceType
1487 = lendian16 (as_a <hsa_op_reg *> (cmp->get_op (1))->m_type);
1488 else
1489 repr.sourceType
1490 = lendian16 (as_a <hsa_op_immed *> (cmp->get_op (1))->m_type);
1491 repr.modifier = 0;
1492 repr.compare = cmp->m_compare;
1493 repr.pack = 0;
1494
1495 brig_code.add (&repr, sizeof (repr));
1496 brig_insn_count++;
1497 }
1498
1499 /* Emit an HSA branching instruction and all necessary directives, schedule
1500 necessary operands for writing. */
1501
1502 static void
1503 emit_branch_insn (hsa_insn_br *br)
1504 {
1505 struct BrigInstBr repr;
1506
1507 basic_block target = NULL;
1508 edge_iterator ei;
1509 edge e;
1510
1511 /* At the moment we only handle direct conditional jumps. */
1512 gcc_assert (br->m_opcode == BRIG_OPCODE_CBR);
1513 repr.base.base.byteCount = lendian16 (sizeof (repr));
1514 repr.base.base.kind = lendian16 (BRIG_KIND_INST_BR);
1515 repr.base.opcode = lendian16 (br->m_opcode);
1516 repr.width = BRIG_WIDTH_1;
1517 /* For Conditional jumps the type is always B1. */
1518 repr.base.type = lendian16 (BRIG_TYPE_B1);
1519
1520 FOR_EACH_EDGE (e, ei, br->m_bb->succs)
1521 if (e->flags & EDGE_TRUE_VALUE)
1522 {
1523 target = e->dest;
1524 break;
1525 }
1526 gcc_assert (target);
1527
1528 repr.base.operands
1529 = lendian32 (emit_operands (br->get_op (0),
1530 &hsa_bb_for_bb (target)->m_label_ref));
1531 memset (&repr.reserved, 0, sizeof (repr.reserved));
1532
1533 brig_code.add (&repr, sizeof (repr));
1534 brig_insn_count++;
1535 }
1536
1537 /* Emit an HSA unconditional jump branching instruction that points to
1538 a label REFERENCE. */
1539
1540 static void
1541 emit_unconditional_jump (hsa_op_code_ref *reference)
1542 {
1543 struct BrigInstBr repr;
1544
1545 repr.base.base.byteCount = lendian16 (sizeof (repr));
1546 repr.base.base.kind = lendian16 (BRIG_KIND_INST_BR);
1547 repr.base.opcode = lendian16 (BRIG_OPCODE_BR);
1548 repr.base.type = lendian16 (BRIG_TYPE_NONE);
1549 /* Direct branches to labels must be width(all). */
1550 repr.width = BRIG_WIDTH_ALL;
1551
1552 repr.base.operands = lendian32 (emit_operands (reference));
1553 memset (&repr.reserved, 0, sizeof (repr.reserved));
1554 brig_code.add (&repr, sizeof (repr));
1555 brig_insn_count++;
1556 }
1557
1558 /* Emit an HSA switch jump instruction that uses a jump table to
1559 jump to a destination label. */
1560
1561 static void
1562 emit_switch_insn (hsa_insn_sbr *sbr)
1563 {
1564 struct BrigInstBr repr;
1565
1566 gcc_assert (sbr->m_opcode == BRIG_OPCODE_SBR);
1567 repr.base.base.byteCount = lendian16 (sizeof (repr));
1568 repr.base.base.kind = lendian16 (BRIG_KIND_INST_BR);
1569 repr.base.opcode = lendian16 (sbr->m_opcode);
1570 repr.width = BRIG_WIDTH_1;
1571 /* For Conditional jumps the type is always B1. */
1572 hsa_op_reg *index = as_a <hsa_op_reg *> (sbr->get_op (0));
1573 repr.base.type = lendian16 (index->m_type);
1574 repr.base.operands
1575 = lendian32 (emit_operands (sbr->get_op (0), sbr->m_label_code_list));
1576 memset (&repr.reserved, 0, sizeof (repr.reserved));
1577
1578 brig_code.add (&repr, sizeof (repr));
1579 brig_insn_count++;
1580 }
1581
1582 /* Emit a HSA convert instruction and all necessary directives, schedule
1583 necessary operands for writing. */
1584
1585 static void
1586 emit_cvt_insn (hsa_insn_cvt *insn)
1587 {
1588 struct BrigInstCvt repr;
1589 BrigType16_t srctype;
1590
1591 repr.base.base.byteCount = lendian16 (sizeof (repr));
1592 repr.base.base.kind = lendian16 (BRIG_KIND_INST_CVT);
1593 repr.base.opcode = lendian16 (insn->m_opcode);
1594 repr.base.type = lendian16 (insn->m_type);
1595 repr.base.operands = lendian32 (emit_insn_operands (insn));
1596
1597 if (is_a <hsa_op_reg *> (insn->get_op (1)))
1598 srctype = as_a <hsa_op_reg *> (insn->get_op (1))->m_type;
1599 else
1600 srctype = as_a <hsa_op_immed *> (insn->get_op (1))->m_type;
1601 repr.sourceType = lendian16 (srctype);
1602 repr.modifier = 0;
1603 /* float to smaller float requires a rounding setting (we default
1604 to 'near'. */
1605 if (hsa_type_float_p (insn->m_type)
1606 && (!hsa_type_float_p (srctype)
1607 || ((insn->m_type & BRIG_TYPE_BASE_MASK)
1608 < (srctype & BRIG_TYPE_BASE_MASK))))
1609 repr.round = BRIG_ROUND_FLOAT_NEAR_EVEN;
1610 else if (hsa_type_integer_p (insn->m_type) &&
1611 hsa_type_float_p (srctype))
1612 repr.round = BRIG_ROUND_INTEGER_ZERO;
1613 else
1614 repr.round = BRIG_ROUND_NONE;
1615 brig_code.add (&repr, sizeof (repr));
1616 brig_insn_count++;
1617 }
1618
1619 /* Emit call instruction INSN, where this instruction must be closed
1620 within a call block instruction. */
1621
1622 static void
1623 emit_call_insn (hsa_insn_call *call)
1624 {
1625 struct BrigInstBr repr;
1626
1627 repr.base.base.byteCount = lendian16 (sizeof (repr));
1628 repr.base.base.kind = lendian16 (BRIG_KIND_INST_BR);
1629 repr.base.opcode = lendian16 (BRIG_OPCODE_CALL);
1630 repr.base.type = lendian16 (BRIG_TYPE_NONE);
1631
1632 repr.base.operands
1633 = lendian32 (emit_operands (call->m_result_code_list, &call->m_func,
1634 call->m_args_code_list));
1635
1636 /* Internal functions have not set m_called_function. */
1637 if (call->m_called_function)
1638 {
1639 function_linkage_pair pair (call->m_called_function,
1640 call->m_func.m_brig_op_offset);
1641 function_call_linkage.safe_push (pair);
1642 }
1643 else
1644 {
1645 hsa_internal_fn *slot
1646 = hsa_emitted_internal_decls->find (call->m_called_internal_fn);
1647 gcc_assert (slot);
1648 gcc_assert (slot->m_offset > 0);
1649 call->m_func.m_directive_offset = slot->m_offset;
1650 }
1651
1652 repr.width = BRIG_WIDTH_ALL;
1653 memset (&repr.reserved, 0, sizeof (repr.reserved));
1654
1655 brig_code.add (&repr, sizeof (repr));
1656 brig_insn_count++;
1657 }
1658
1659 /* Emit argument block directive. */
1660
1661 static void
1662 emit_arg_block_insn (hsa_insn_arg_block *insn)
1663 {
1664 switch (insn->m_kind)
1665 {
1666 case BRIG_KIND_DIRECTIVE_ARG_BLOCK_START:
1667 {
1668 struct BrigDirectiveArgBlock repr;
1669 repr.base.byteCount = lendian16 (sizeof (repr));
1670 repr.base.kind = lendian16 (insn->m_kind);
1671 brig_code.add (&repr, sizeof (repr));
1672
1673 for (unsigned i = 0; i < insn->m_call_insn->m_input_args.length (); i++)
1674 {
1675 insn->m_call_insn->m_args_code_list->m_offsets[i]
1676 = lendian32 (emit_directive_variable
1677 (insn->m_call_insn->m_input_args[i]));
1678 brig_insn_count++;
1679 }
1680
1681 if (insn->m_call_insn->m_output_arg)
1682 {
1683 insn->m_call_insn->m_result_code_list->m_offsets[0]
1684 = lendian32 (emit_directive_variable
1685 (insn->m_call_insn->m_output_arg));
1686 brig_insn_count++;
1687 }
1688
1689 break;
1690 }
1691 case BRIG_KIND_DIRECTIVE_ARG_BLOCK_END:
1692 {
1693 struct BrigDirectiveArgBlock repr;
1694 repr.base.byteCount = lendian16 (sizeof (repr));
1695 repr.base.kind = lendian16 (insn->m_kind);
1696 brig_code.add (&repr, sizeof (repr));
1697 break;
1698 }
1699 default:
1700 gcc_unreachable ();
1701 }
1702
1703 brig_insn_count++;
1704 }
1705
1706 /* Emit comment directive. */
1707
1708 static void
1709 emit_comment_insn (hsa_insn_comment *insn)
1710 {
1711 struct BrigDirectiveComment repr;
1712 memset (&repr, 0, sizeof (repr));
1713
1714 repr.base.byteCount = lendian16 (sizeof (repr));
1715 repr.base.kind = lendian16 (insn->m_opcode);
1716 repr.name = brig_emit_string (insn->m_comment, '\0', false);
1717 brig_code.add (&repr, sizeof (repr));
1718 }
1719
1720 /* Emit queue instruction INSN. */
1721
1722 static void
1723 emit_queue_insn (hsa_insn_queue *insn)
1724 {
1725 BrigInstQueue repr;
1726 memset (&repr, 0, sizeof (repr));
1727
1728 repr.base.base.byteCount = lendian16 (sizeof (repr));
1729 repr.base.base.kind = lendian16 (BRIG_KIND_INST_QUEUE);
1730 repr.base.opcode = lendian16 (insn->m_opcode);
1731 repr.base.type = lendian16 (insn->m_type);
1732 repr.segment = BRIG_SEGMENT_GLOBAL;
1733 repr.memoryOrder = BRIG_MEMORY_ORDER_SC_RELEASE;
1734 repr.base.operands = lendian32 (emit_insn_operands (insn));
1735 brig_data.round_size_up (4);
1736 brig_code.add (&repr, sizeof (repr));
1737
1738 brig_insn_count++;
1739 }
1740
1741 /* Emit source type instruction INSN. */
1742
1743 static void
1744 emit_srctype_insn (hsa_insn_srctype *insn)
1745 {
1746 /* We assume that BrigInstMod has a BrigInstBasic prefix. */
1747 struct BrigInstSourceType repr;
1748 unsigned operand_count = insn->operand_count ();
1749 gcc_checking_assert (operand_count >= 2);
1750
1751 memset (&repr, 0, sizeof (repr));
1752 repr.sourceType = lendian16 (insn->m_source_type);
1753 repr.base.base.byteCount = lendian16 (sizeof (repr));
1754 repr.base.base.kind = lendian16 (BRIG_KIND_INST_SOURCE_TYPE);
1755 repr.base.opcode = lendian16 (insn->m_opcode);
1756 repr.base.type = lendian16 (insn->m_type);
1757
1758 repr.base.operands = lendian32 (emit_insn_operands (insn));
1759 brig_code.add (&repr, sizeof (struct BrigInstSourceType));
1760 brig_insn_count++;
1761 }
1762
1763 /* Emit packed instruction INSN. */
1764
1765 static void
1766 emit_packed_insn (hsa_insn_packed *insn)
1767 {
1768 /* We assume that BrigInstMod has a BrigInstBasic prefix. */
1769 struct BrigInstSourceType repr;
1770 unsigned operand_count = insn->operand_count ();
1771 gcc_checking_assert (operand_count >= 2);
1772
1773 memset (&repr, 0, sizeof (repr));
1774 repr.sourceType = lendian16 (insn->m_source_type);
1775 repr.base.base.byteCount = lendian16 (sizeof (repr));
1776 repr.base.base.kind = lendian16 (BRIG_KIND_INST_SOURCE_TYPE);
1777 repr.base.opcode = lendian16 (insn->m_opcode);
1778 repr.base.type = lendian16 (insn->m_type);
1779
1780 if (insn->m_opcode == BRIG_OPCODE_COMBINE)
1781 {
1782 /* Create operand list for packed type. */
1783 for (unsigned i = 1; i < operand_count; i++)
1784 {
1785 gcc_checking_assert (insn->get_op (i));
1786 insn->m_operand_list->m_offsets[i - 1]
1787 = lendian32 (enqueue_op (insn->get_op (i)));
1788 }
1789
1790 repr.base.operands = lendian32 (emit_operands (insn->get_op (0),
1791 insn->m_operand_list));
1792 }
1793 else if (insn->m_opcode == BRIG_OPCODE_EXPAND)
1794 {
1795 /* Create operand list for packed type. */
1796 for (unsigned i = 0; i < operand_count - 1; i++)
1797 {
1798 gcc_checking_assert (insn->get_op (i));
1799 insn->m_operand_list->m_offsets[i]
1800 = lendian32 (enqueue_op (insn->get_op (i)));
1801 }
1802
1803 unsigned ops = emit_operands (insn->m_operand_list,
1804 insn->get_op (insn->operand_count () - 1));
1805 repr.base.operands = lendian32 (ops);
1806 }
1807
1808
1809 brig_code.add (&repr, sizeof (struct BrigInstSourceType));
1810 brig_insn_count++;
1811 }
1812
1813 /* Emit a basic HSA instruction and all necessary directives, schedule
1814 necessary operands for writing. */
1815
1816 static void
1817 emit_basic_insn (hsa_insn_basic *insn)
1818 {
1819 /* We assume that BrigInstMod has a BrigInstBasic prefix. */
1820 struct BrigInstMod repr;
1821 BrigType16_t type;
1822
1823 memset (&repr, 0, sizeof (repr));
1824 repr.base.base.byteCount = lendian16 (sizeof (BrigInstBasic));
1825 repr.base.base.kind = lendian16 (BRIG_KIND_INST_BASIC);
1826 repr.base.opcode = lendian16 (insn->m_opcode);
1827 switch (insn->m_opcode)
1828 {
1829 /* And the bit-logical operations need bit types and whine about
1830 arithmetic types :-/ */
1831 case BRIG_OPCODE_AND:
1832 case BRIG_OPCODE_OR:
1833 case BRIG_OPCODE_XOR:
1834 case BRIG_OPCODE_NOT:
1835 type = regtype_for_type (insn->m_type);
1836 break;
1837 default:
1838 type = insn->m_type;
1839 break;
1840 }
1841 repr.base.type = lendian16 (type);
1842 repr.base.operands = lendian32 (emit_insn_operands (insn));
1843
1844 if (hsa_type_packed_p (type))
1845 {
1846 if (hsa_type_float_p (type)
1847 && !hsa_opcode_floating_bit_insn_p (insn->m_opcode))
1848 repr.round = BRIG_ROUND_FLOAT_NEAR_EVEN;
1849 else
1850 repr.round = 0;
1851 /* We assume that destination and sources agree in packing layout. */
1852 if (insn->num_used_ops () >= 2)
1853 repr.pack = BRIG_PACK_PP;
1854 else
1855 repr.pack = BRIG_PACK_P;
1856 repr.reserved = 0;
1857 repr.base.base.byteCount = lendian16 (sizeof (BrigInstMod));
1858 repr.base.base.kind = lendian16 (BRIG_KIND_INST_MOD);
1859 brig_code.add (&repr, sizeof (struct BrigInstMod));
1860 }
1861 else
1862 brig_code.add (&repr, sizeof (struct BrigInstBasic));
1863 brig_insn_count++;
1864 }
1865
1866 /* Emit an HSA instruction and all necessary directives, schedule necessary
1867 operands for writing. */
1868
1869 static void
1870 emit_insn (hsa_insn_basic *insn)
1871 {
1872 gcc_assert (!is_a <hsa_insn_phi *> (insn));
1873
1874 insn->m_brig_offset = brig_code.total_size;
1875
1876 if (hsa_insn_signal *signal = dyn_cast <hsa_insn_signal *> (insn))
1877 emit_signal_insn (signal);
1878 else if (hsa_insn_atomic *atom = dyn_cast <hsa_insn_atomic *> (insn))
1879 emit_atomic_insn (atom);
1880 else if (hsa_insn_mem *mem = dyn_cast <hsa_insn_mem *> (insn))
1881 emit_memory_insn (mem);
1882 else if (insn->m_opcode == BRIG_OPCODE_LDA)
1883 emit_addr_insn (insn);
1884 else if (hsa_insn_seg *seg = dyn_cast <hsa_insn_seg *> (insn))
1885 emit_segment_insn (seg);
1886 else if (hsa_insn_cmp *cmp = dyn_cast <hsa_insn_cmp *> (insn))
1887 emit_cmp_insn (cmp);
1888 else if (hsa_insn_br *br = dyn_cast <hsa_insn_br *> (insn))
1889 emit_branch_insn (br);
1890 else if (hsa_insn_sbr *sbr = dyn_cast <hsa_insn_sbr *> (insn))
1891 {
1892 if (switch_instructions == NULL)
1893 switch_instructions = new vec <hsa_insn_sbr *> ();
1894
1895 switch_instructions->safe_push (sbr);
1896 emit_switch_insn (sbr);
1897 }
1898 else if (hsa_insn_arg_block *block = dyn_cast <hsa_insn_arg_block *> (insn))
1899 emit_arg_block_insn (block);
1900 else if (hsa_insn_call *call = dyn_cast <hsa_insn_call *> (insn))
1901 emit_call_insn (call);
1902 else if (hsa_insn_comment *comment = dyn_cast <hsa_insn_comment *> (insn))
1903 emit_comment_insn (comment);
1904 else if (hsa_insn_queue *queue = dyn_cast <hsa_insn_queue *> (insn))
1905 emit_queue_insn (queue);
1906 else if (hsa_insn_srctype *srctype = dyn_cast <hsa_insn_srctype *> (insn))
1907 emit_srctype_insn (srctype);
1908 else if (hsa_insn_packed *packed = dyn_cast <hsa_insn_packed *> (insn))
1909 emit_packed_insn (packed);
1910 else if (hsa_insn_cvt *cvt = dyn_cast <hsa_insn_cvt *> (insn))
1911 emit_cvt_insn (cvt);
1912 else if (hsa_insn_alloca *alloca = dyn_cast <hsa_insn_alloca *> (insn))
1913 emit_alloca_insn (alloca);
1914 else
1915 emit_basic_insn (insn);
1916 }
1917
1918 /* We have just finished emitting BB and are about to emit NEXT_BB if non-NULL,
1919 or we are about to finish emitting code, if it is NULL. If the fall through
1920 edge from BB does not lead to NEXT_BB, emit an unconditional jump. */
1921
1922 static void
1923 perhaps_emit_branch (basic_block bb, basic_block next_bb)
1924 {
1925 basic_block t_bb = NULL, ff = NULL;
1926
1927 edge_iterator ei;
1928 edge e;
1929
1930 /* If the last instruction of BB is a switch, ignore emission of all
1931 edges. */
1932 if (hsa_bb_for_bb (bb)->m_last_insn
1933 && is_a <hsa_insn_sbr *> (hsa_bb_for_bb (bb)->m_last_insn))
1934 return;
1935
1936 FOR_EACH_EDGE (e, ei, bb->succs)
1937 if (e->flags & EDGE_TRUE_VALUE)
1938 {
1939 gcc_assert (!t_bb);
1940 t_bb = e->dest;
1941 }
1942 else
1943 {
1944 gcc_assert (!ff);
1945 ff = e->dest;
1946 }
1947
1948 if (!ff || ff == next_bb || ff == EXIT_BLOCK_PTR_FOR_FN (cfun))
1949 return;
1950
1951 emit_unconditional_jump (&hsa_bb_for_bb (ff)->m_label_ref);
1952 }
1953
1954 /* Emit the a function with name NAME to the various brig sections. */
1955
1956 void
1957 hsa_brig_emit_function (void)
1958 {
1959 basic_block bb, prev_bb;
1960 hsa_insn_basic *insn;
1961 BrigDirectiveExecutable *ptr_to_fndir;
1962
1963 brig_init ();
1964
1965 brig_insn_count = 0;
1966 memset (&op_queue, 0, sizeof (op_queue));
1967 op_queue.projected_size = brig_operand.total_size;
1968
1969 if (!function_offsets)
1970 function_offsets = new hash_map<tree, BrigCodeOffset32_t> ();
1971
1972 if (!emitted_declarations)
1973 emitted_declarations = new hash_map <tree, BrigDirectiveExecutable *> ();
1974
1975 for (unsigned i = 0; i < hsa_cfun->m_called_functions.length (); i++)
1976 {
1977 tree called = hsa_cfun->m_called_functions[i];
1978
1979 /* If the function has no definition, emit a declaration. */
1980 if (!emitted_declarations->get (called))
1981 {
1982 BrigDirectiveExecutable *e = emit_function_declaration (called);
1983 emitted_declarations->put (called, e);
1984 }
1985 }
1986
1987 for (unsigned i = 0; i < hsa_cfun->m_called_internal_fns.length (); i++)
1988 {
1989 hsa_internal_fn *called = hsa_cfun->m_called_internal_fns[i];
1990 emit_internal_fn_decl (called);
1991 }
1992
1993 ptr_to_fndir = emit_function_directives (hsa_cfun, false);
1994 for (insn = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun))->m_first_insn;
1995 insn;
1996 insn = insn->m_next)
1997 emit_insn (insn);
1998 prev_bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
1999 FOR_EACH_BB_FN (bb, cfun)
2000 {
2001 perhaps_emit_branch (prev_bb, bb);
2002 emit_bb_label_directive (hsa_bb_for_bb (bb));
2003 for (insn = hsa_bb_for_bb (bb)->m_first_insn; insn; insn = insn->m_next)
2004 emit_insn (insn);
2005 prev_bb = bb;
2006 }
2007 perhaps_emit_branch (prev_bb, NULL);
2008 ptr_to_fndir->nextModuleEntry = brig_code.total_size;
2009
2010 /* Fill up label references for all sbr instructions. */
2011 if (switch_instructions)
2012 {
2013 for (unsigned i = 0; i < switch_instructions->length (); i++)
2014 {
2015 hsa_insn_sbr *sbr = (*switch_instructions)[i];
2016 for (unsigned j = 0; j < sbr->m_jump_table.length (); j++)
2017 {
2018 hsa_bb *hbb = hsa_bb_for_bb (sbr->m_jump_table[j]);
2019 sbr->m_label_code_list->m_offsets[j]
2020 = hbb->m_label_ref.m_directive_offset;
2021 }
2022 }
2023
2024 switch_instructions->release ();
2025 delete switch_instructions;
2026 switch_instructions = NULL;
2027 }
2028
2029 if (dump_file)
2030 {
2031 fprintf (dump_file, "------- After BRIG emission: -------\n");
2032 dump_hsa_cfun (dump_file);
2033 }
2034
2035 emit_queued_operands ();
2036 }
2037
2038 /* Emit all OMP symbols related to OMP. */
2039
2040 void
2041 hsa_brig_emit_omp_symbols (void)
2042 {
2043 brig_init ();
2044 emit_directive_variable (hsa_num_threads);
2045 }
2046
2047 /* Create and return __hsa_global_variables symbol that contains
2048 all informations consumed by libgomp to link global variables
2049 with their string names used by an HSA kernel. */
2050
2051 static tree
2052 hsa_output_global_variables ()
2053 {
2054 unsigned l = hsa_global_variable_symbols->elements ();
2055
2056 tree variable_info_type = make_node (RECORD_TYPE);
2057 tree id_f1 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2058 get_identifier ("name"), ptr_type_node);
2059 DECL_CHAIN (id_f1) = NULL_TREE;
2060 tree id_f2 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2061 get_identifier ("omp_data_size"),
2062 ptr_type_node);
2063 DECL_CHAIN (id_f2) = id_f1;
2064 finish_builtin_struct (variable_info_type, "__hsa_variable_info", id_f2,
2065 NULL_TREE);
2066
2067 tree int_num_of_global_vars;
2068 int_num_of_global_vars = build_int_cst (uint32_type_node, l);
2069 tree global_vars_num_index_type = build_index_type (int_num_of_global_vars);
2070 tree global_vars_array_type = build_array_type (variable_info_type,
2071 global_vars_num_index_type);
2072 TYPE_ARTIFICIAL (global_vars_array_type) = 1;
2073
2074 vec<constructor_elt, va_gc> *global_vars_vec = NULL;
2075
2076 for (hash_table <hsa_noop_symbol_hasher>::iterator it
2077 = hsa_global_variable_symbols->begin ();
2078 it != hsa_global_variable_symbols->end (); ++it)
2079 {
2080 unsigned len = strlen ((*it)->m_name);
2081 char *copy = XNEWVEC (char, len + 2);
2082 copy[0] = '&';
2083 memcpy (copy + 1, (*it)->m_name, len);
2084 copy[len + 1] = '\0';
2085 len++;
2086 hsa_sanitize_name (copy);
2087
2088 tree var_name = build_string (len, copy);
2089 TREE_TYPE (var_name)
2090 = build_array_type (char_type_node, build_index_type (size_int (len)));
2091 free (copy);
2092
2093 vec<constructor_elt, va_gc> *variable_info_vec = NULL;
2094 CONSTRUCTOR_APPEND_ELT (variable_info_vec, NULL_TREE,
2095 build1 (ADDR_EXPR,
2096 build_pointer_type (TREE_TYPE (var_name)),
2097 var_name));
2098 CONSTRUCTOR_APPEND_ELT (variable_info_vec, NULL_TREE,
2099 build_fold_addr_expr ((*it)->m_decl));
2100
2101 tree variable_info_ctor = build_constructor (variable_info_type,
2102 variable_info_vec);
2103
2104 CONSTRUCTOR_APPEND_ELT (global_vars_vec, NULL_TREE,
2105 variable_info_ctor);
2106 }
2107
2108 tree global_vars_ctor = build_constructor (global_vars_array_type,
2109 global_vars_vec);
2110
2111 char tmp_name[64];
2112 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "__hsa_global_variables", 1);
2113 tree global_vars_table = build_decl (UNKNOWN_LOCATION, VAR_DECL,
2114 get_identifier (tmp_name),
2115 global_vars_array_type);
2116 TREE_STATIC (global_vars_table) = 1;
2117 TREE_READONLY (global_vars_table) = 1;
2118 TREE_PUBLIC (global_vars_table) = 0;
2119 DECL_ARTIFICIAL (global_vars_table) = 1;
2120 DECL_IGNORED_P (global_vars_table) = 1;
2121 DECL_EXTERNAL (global_vars_table) = 0;
2122 TREE_CONSTANT (global_vars_table) = 1;
2123 DECL_INITIAL (global_vars_table) = global_vars_ctor;
2124 varpool_node::finalize_decl (global_vars_table);
2125
2126 return global_vars_table;
2127 }
2128
2129 /* Create __hsa_host_functions and __hsa_kernels that contain
2130 all informations consumed by libgomp to register all kernels
2131 in the BRIG binary. */
2132
2133 static void
2134 hsa_output_kernels (tree *host_func_table, tree *kernels)
2135 {
2136 unsigned map_count = hsa_get_number_decl_kernel_mappings ();
2137
2138 tree int_num_of_kernels;
2139 int_num_of_kernels = build_int_cst (uint32_type_node, map_count);
2140 tree kernel_num_index_type = build_index_type (int_num_of_kernels);
2141 tree host_functions_array_type = build_array_type (ptr_type_node,
2142 kernel_num_index_type);
2143 TYPE_ARTIFICIAL (host_functions_array_type) = 1;
2144
2145 vec<constructor_elt, va_gc> *host_functions_vec = NULL;
2146 for (unsigned i = 0; i < map_count; ++i)
2147 {
2148 tree decl = hsa_get_decl_kernel_mapping_decl (i);
2149 tree host_fn = build_fold_addr_expr (hsa_get_host_function (decl));
2150 CONSTRUCTOR_APPEND_ELT (host_functions_vec, NULL_TREE, host_fn);
2151 }
2152 tree host_functions_ctor = build_constructor (host_functions_array_type,
2153 host_functions_vec);
2154 char tmp_name[64];
2155 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "__hsa_host_functions", 1);
2156 tree hsa_host_func_table = build_decl (UNKNOWN_LOCATION, VAR_DECL,
2157 get_identifier (tmp_name),
2158 host_functions_array_type);
2159 TREE_STATIC (hsa_host_func_table) = 1;
2160 TREE_READONLY (hsa_host_func_table) = 1;
2161 TREE_PUBLIC (hsa_host_func_table) = 0;
2162 DECL_ARTIFICIAL (hsa_host_func_table) = 1;
2163 DECL_IGNORED_P (hsa_host_func_table) = 1;
2164 DECL_EXTERNAL (hsa_host_func_table) = 0;
2165 TREE_CONSTANT (hsa_host_func_table) = 1;
2166 DECL_INITIAL (hsa_host_func_table) = host_functions_ctor;
2167 varpool_node::finalize_decl (hsa_host_func_table);
2168 *host_func_table = hsa_host_func_table;
2169
2170 /* Following code emits list of kernel_info structures. */
2171
2172 tree kernel_info_type = make_node (RECORD_TYPE);
2173 tree id_f1 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2174 get_identifier ("name"), ptr_type_node);
2175 DECL_CHAIN (id_f1) = NULL_TREE;
2176 tree id_f2 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2177 get_identifier ("omp_data_size"),
2178 unsigned_type_node);
2179 DECL_CHAIN (id_f2) = id_f1;
2180 tree id_f3 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2181 get_identifier ("gridified_kernel_p"),
2182 boolean_type_node);
2183 DECL_CHAIN (id_f3) = id_f2;
2184 tree id_f4 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2185 get_identifier ("kernel_dependencies_count"),
2186 unsigned_type_node);
2187 DECL_CHAIN (id_f4) = id_f3;
2188 tree id_f5 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2189 get_identifier ("kernel_dependencies"),
2190 build_pointer_type (build_pointer_type
2191 (char_type_node)));
2192 DECL_CHAIN (id_f5) = id_f4;
2193 finish_builtin_struct (kernel_info_type, "__hsa_kernel_info", id_f5,
2194 NULL_TREE);
2195
2196 int_num_of_kernels = build_int_cstu (uint32_type_node, map_count);
2197 tree kernel_info_vector_type
2198 = build_array_type (kernel_info_type,
2199 build_index_type (int_num_of_kernels));
2200 TYPE_ARTIFICIAL (kernel_info_vector_type) = 1;
2201
2202 vec<constructor_elt, va_gc> *kernel_info_vector_vec = NULL;
2203 tree kernel_dependencies_vector_type = NULL;
2204
2205 for (unsigned i = 0; i < map_count; ++i)
2206 {
2207 tree kernel = hsa_get_decl_kernel_mapping_decl (i);
2208 char *name = hsa_get_decl_kernel_mapping_name (i);
2209 unsigned len = strlen (name);
2210 char *copy = XNEWVEC (char, len + 2);
2211 copy[0] = '&';
2212 memcpy (copy + 1, name, len);
2213 copy[len + 1] = '\0';
2214 len++;
2215
2216 tree kern_name = build_string (len, copy);
2217 TREE_TYPE (kern_name)
2218 = build_array_type (char_type_node, build_index_type (size_int (len)));
2219 free (copy);
2220
2221 unsigned omp_size = hsa_get_decl_kernel_mapping_omp_size (i);
2222 tree omp_data_size = build_int_cstu (unsigned_type_node, omp_size);
2223 bool gridified_kernel_p = hsa_get_decl_kernel_mapping_gridified (i);
2224 tree gridified_kernel_p_tree = build_int_cstu (boolean_type_node,
2225 gridified_kernel_p);
2226 unsigned count = 0;
2227
2228 kernel_dependencies_vector_type
2229 = build_array_type (build_pointer_type (char_type_node),
2230 build_index_type (size_int (0)));
2231
2232 vec<constructor_elt, va_gc> *kernel_dependencies_vec = NULL;
2233 if (hsa_decl_kernel_dependencies)
2234 {
2235 vec<const char *> **slot;
2236 slot = hsa_decl_kernel_dependencies->get (kernel);
2237 if (slot)
2238 {
2239 vec <const char *> *dependencies = *slot;
2240 count = dependencies->length ();
2241
2242 kernel_dependencies_vector_type
2243 = build_array_type (build_pointer_type (char_type_node),
2244 build_index_type (size_int (count)));
2245 TYPE_ARTIFICIAL (kernel_dependencies_vector_type) = 1;
2246
2247 for (unsigned j = 0; j < count; j++)
2248 {
2249 const char *d = (*dependencies)[j];
2250 len = strlen (d);
2251 tree dependency_name = build_string (len, d);
2252 TREE_TYPE (dependency_name)
2253 = build_array_type (char_type_node,
2254 build_index_type (size_int (len)));
2255
2256 CONSTRUCTOR_APPEND_ELT
2257 (kernel_dependencies_vec, NULL_TREE,
2258 build1 (ADDR_EXPR,
2259 build_pointer_type (TREE_TYPE (dependency_name)),
2260 dependency_name));
2261 }
2262 }
2263 }
2264
2265 tree dependencies_count = build_int_cstu (unsigned_type_node, count);
2266
2267 vec<constructor_elt, va_gc> *kernel_info_vec = NULL;
2268 CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE,
2269 build1 (ADDR_EXPR,
2270 build_pointer_type (TREE_TYPE
2271 (kern_name)),
2272 kern_name));
2273 CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE, omp_data_size);
2274 CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE,
2275 gridified_kernel_p_tree);
2276 CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE, dependencies_count);
2277
2278 if (count > 0)
2279 {
2280 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "__hsa_dependencies_list", i);
2281 tree dependencies_list = build_decl (UNKNOWN_LOCATION, VAR_DECL,
2282 get_identifier (tmp_name),
2283 kernel_dependencies_vector_type);
2284
2285 TREE_STATIC (dependencies_list) = 1;
2286 TREE_READONLY (dependencies_list) = 1;
2287 TREE_PUBLIC (dependencies_list) = 0;
2288 DECL_ARTIFICIAL (dependencies_list) = 1;
2289 DECL_IGNORED_P (dependencies_list) = 1;
2290 DECL_EXTERNAL (dependencies_list) = 0;
2291 TREE_CONSTANT (dependencies_list) = 1;
2292 DECL_INITIAL (dependencies_list)
2293 = build_constructor (kernel_dependencies_vector_type,
2294 kernel_dependencies_vec);
2295 varpool_node::finalize_decl (dependencies_list);
2296
2297 CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE,
2298 build1 (ADDR_EXPR,
2299 build_pointer_type
2300 (TREE_TYPE (dependencies_list)),
2301 dependencies_list));
2302 }
2303 else
2304 CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE, null_pointer_node);
2305
2306 tree kernel_info_ctor = build_constructor (kernel_info_type,
2307 kernel_info_vec);
2308
2309 CONSTRUCTOR_APPEND_ELT (kernel_info_vector_vec, NULL_TREE,
2310 kernel_info_ctor);
2311 }
2312
2313 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "__hsa_kernels", 1);
2314 tree hsa_kernels = build_decl (UNKNOWN_LOCATION, VAR_DECL,
2315 get_identifier (tmp_name),
2316 kernel_info_vector_type);
2317
2318 TREE_STATIC (hsa_kernels) = 1;
2319 TREE_READONLY (hsa_kernels) = 1;
2320 TREE_PUBLIC (hsa_kernels) = 0;
2321 DECL_ARTIFICIAL (hsa_kernels) = 1;
2322 DECL_IGNORED_P (hsa_kernels) = 1;
2323 DECL_EXTERNAL (hsa_kernels) = 0;
2324 TREE_CONSTANT (hsa_kernels) = 1;
2325 DECL_INITIAL (hsa_kernels) = build_constructor (kernel_info_vector_type,
2326 kernel_info_vector_vec);
2327 varpool_node::finalize_decl (hsa_kernels);
2328 *kernels = hsa_kernels;
2329 }
2330
2331 /* Create a static constructor that will register out brig stuff with
2332 libgomp. */
2333
2334 static void
2335 hsa_output_libgomp_mapping (tree brig_decl)
2336 {
2337 unsigned kernel_count = hsa_get_number_decl_kernel_mappings ();
2338 unsigned global_variable_count = hsa_global_variable_symbols->elements ();
2339
2340 tree kernels;
2341 tree host_func_table;
2342
2343 hsa_output_kernels (&host_func_table, &kernels);
2344 tree global_vars = hsa_output_global_variables ();
2345
2346 tree hsa_image_desc_type = make_node (RECORD_TYPE);
2347 tree id_f1 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2348 get_identifier ("brig_module"), ptr_type_node);
2349 DECL_CHAIN (id_f1) = NULL_TREE;
2350 tree id_f2 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2351 get_identifier ("kernel_count"),
2352 unsigned_type_node);
2353
2354 DECL_CHAIN (id_f2) = id_f1;
2355 tree id_f3 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2356 get_identifier ("hsa_kernel_infos"),
2357 ptr_type_node);
2358 DECL_CHAIN (id_f3) = id_f2;
2359 tree id_f4 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2360 get_identifier ("global_variable_count"),
2361 unsigned_type_node);
2362 DECL_CHAIN (id_f4) = id_f3;
2363 tree id_f5 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2364 get_identifier ("hsa_global_variable_infos"),
2365 ptr_type_node);
2366 DECL_CHAIN (id_f5) = id_f4;
2367 finish_builtin_struct (hsa_image_desc_type, "__hsa_image_desc", id_f5,
2368 NULL_TREE);
2369 TYPE_ARTIFICIAL (hsa_image_desc_type) = 1;
2370
2371 vec<constructor_elt, va_gc> *img_desc_vec = NULL;
2372 CONSTRUCTOR_APPEND_ELT (img_desc_vec, NULL_TREE,
2373 build_fold_addr_expr (brig_decl));
2374 CONSTRUCTOR_APPEND_ELT (img_desc_vec, NULL_TREE,
2375 build_int_cstu (unsigned_type_node, kernel_count));
2376 CONSTRUCTOR_APPEND_ELT (img_desc_vec, NULL_TREE,
2377 build1 (ADDR_EXPR,
2378 build_pointer_type (TREE_TYPE (kernels)),
2379 kernels));
2380 CONSTRUCTOR_APPEND_ELT (img_desc_vec, NULL_TREE,
2381 build_int_cstu (unsigned_type_node,
2382 global_variable_count));
2383 CONSTRUCTOR_APPEND_ELT (img_desc_vec, NULL_TREE,
2384 build1 (ADDR_EXPR,
2385 build_pointer_type (TREE_TYPE (global_vars)),
2386 global_vars));
2387
2388 tree img_desc_ctor = build_constructor (hsa_image_desc_type, img_desc_vec);
2389
2390 char tmp_name[64];
2391 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "__hsa_img_descriptor", 1);
2392 tree hsa_img_descriptor = build_decl (UNKNOWN_LOCATION, VAR_DECL,
2393 get_identifier (tmp_name),
2394 hsa_image_desc_type);
2395 TREE_STATIC (hsa_img_descriptor) = 1;
2396 TREE_READONLY (hsa_img_descriptor) = 1;
2397 TREE_PUBLIC (hsa_img_descriptor) = 0;
2398 DECL_ARTIFICIAL (hsa_img_descriptor) = 1;
2399 DECL_IGNORED_P (hsa_img_descriptor) = 1;
2400 DECL_EXTERNAL (hsa_img_descriptor) = 0;
2401 TREE_CONSTANT (hsa_img_descriptor) = 1;
2402 DECL_INITIAL (hsa_img_descriptor) = img_desc_ctor;
2403 varpool_node::finalize_decl (hsa_img_descriptor);
2404
2405 /* Construct the "host_table" libgomp expects. */
2406 tree index_type = build_index_type (build_int_cst (integer_type_node, 4));
2407 tree libgomp_host_table_type = build_array_type (ptr_type_node, index_type);
2408 TYPE_ARTIFICIAL (libgomp_host_table_type) = 1;
2409 vec<constructor_elt, va_gc> *libgomp_host_table_vec = NULL;
2410 tree host_func_table_addr = build_fold_addr_expr (host_func_table);
2411 CONSTRUCTOR_APPEND_ELT (libgomp_host_table_vec, NULL_TREE,
2412 host_func_table_addr);
2413 offset_int func_table_size
2414 = wi::to_offset (TYPE_SIZE_UNIT (ptr_type_node)) * kernel_count;
2415 CONSTRUCTOR_APPEND_ELT (libgomp_host_table_vec, NULL_TREE,
2416 fold_build2 (POINTER_PLUS_EXPR,
2417 TREE_TYPE (host_func_table_addr),
2418 host_func_table_addr,
2419 build_int_cst (size_type_node,
2420 func_table_size.to_uhwi
2421 ())));
2422 CONSTRUCTOR_APPEND_ELT (libgomp_host_table_vec, NULL_TREE, null_pointer_node);
2423 CONSTRUCTOR_APPEND_ELT (libgomp_host_table_vec, NULL_TREE, null_pointer_node);
2424 tree libgomp_host_table_ctor = build_constructor (libgomp_host_table_type,
2425 libgomp_host_table_vec);
2426 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "__hsa_libgomp_host_table", 1);
2427 tree hsa_libgomp_host_table = build_decl (UNKNOWN_LOCATION, VAR_DECL,
2428 get_identifier (tmp_name),
2429 libgomp_host_table_type);
2430
2431 TREE_STATIC (hsa_libgomp_host_table) = 1;
2432 TREE_READONLY (hsa_libgomp_host_table) = 1;
2433 TREE_PUBLIC (hsa_libgomp_host_table) = 0;
2434 DECL_ARTIFICIAL (hsa_libgomp_host_table) = 1;
2435 DECL_IGNORED_P (hsa_libgomp_host_table) = 1;
2436 DECL_EXTERNAL (hsa_libgomp_host_table) = 0;
2437 TREE_CONSTANT (hsa_libgomp_host_table) = 1;
2438 DECL_INITIAL (hsa_libgomp_host_table) = libgomp_host_table_ctor;
2439 varpool_node::finalize_decl (hsa_libgomp_host_table);
2440
2441 /* Generate an initializer with a call to the registration routine. */
2442
2443 tree offload_register
2444 = builtin_decl_explicit (BUILT_IN_GOMP_OFFLOAD_REGISTER);
2445 gcc_checking_assert (offload_register);
2446
2447 tree *hsa_ctor_stmts = hsa_get_ctor_statements ();
2448 append_to_statement_list
2449 (build_call_expr (offload_register, 4,
2450 build_int_cstu (unsigned_type_node,
2451 GOMP_VERSION_PACK (GOMP_VERSION,
2452 GOMP_VERSION_HSA)),
2453 build_fold_addr_expr (hsa_libgomp_host_table),
2454 build_int_cst (integer_type_node, GOMP_DEVICE_HSA),
2455 build_fold_addr_expr (hsa_img_descriptor)),
2456 hsa_ctor_stmts);
2457
2458 cgraph_build_static_cdtor ('I', *hsa_ctor_stmts, DEFAULT_INIT_PRIORITY);
2459
2460 tree offload_unregister
2461 = builtin_decl_explicit (BUILT_IN_GOMP_OFFLOAD_UNREGISTER);
2462 gcc_checking_assert (offload_unregister);
2463
2464 tree *hsa_dtor_stmts = hsa_get_dtor_statements ();
2465 append_to_statement_list
2466 (build_call_expr (offload_unregister, 4,
2467 build_int_cstu (unsigned_type_node,
2468 GOMP_VERSION_PACK (GOMP_VERSION,
2469 GOMP_VERSION_HSA)),
2470 build_fold_addr_expr (hsa_libgomp_host_table),
2471 build_int_cst (integer_type_node, GOMP_DEVICE_HSA),
2472 build_fold_addr_expr (hsa_img_descriptor)),
2473 hsa_dtor_stmts);
2474 cgraph_build_static_cdtor ('D', *hsa_dtor_stmts, DEFAULT_INIT_PRIORITY);
2475 }
2476
2477 /* Emit the brig module we have compiled to a section in the final assembly and
2478 also create a compile unit static constructor that will register the brig
2479 module with libgomp. */
2480
2481 void
2482 hsa_output_brig (void)
2483 {
2484 section *saved_section;
2485
2486 if (!brig_initialized)
2487 return;
2488
2489 for (unsigned i = 0; i < function_call_linkage.length (); i++)
2490 {
2491 function_linkage_pair p = function_call_linkage[i];
2492
2493 BrigCodeOffset32_t *func_offset = function_offsets->get (p.function_decl);
2494 gcc_assert (*func_offset);
2495 BrigOperandCodeRef *code_ref
2496 = (BrigOperandCodeRef *) (brig_operand.get_ptr_by_offset (p.offset));
2497 gcc_assert (code_ref->base.kind == BRIG_KIND_OPERAND_CODE_REF);
2498 code_ref->ref = lendian32 (*func_offset);
2499 }
2500
2501 /* Iterate all function declarations and if we meet a function that should
2502 have module linkage and we are unable to emit HSAIL for the function,
2503 then change the linkage to program linkage. Doing so, we will emit
2504 a valid BRIG image. */
2505 if (hsa_failed_functions != NULL && emitted_declarations != NULL)
2506 for (hash_map <tree, BrigDirectiveExecutable *>::iterator it
2507 = emitted_declarations->begin ();
2508 it != emitted_declarations->end ();
2509 ++it)
2510 {
2511 if (hsa_failed_functions->contains ((*it).first))
2512 (*it).second->linkage = BRIG_LINKAGE_PROGRAM;
2513 }
2514
2515 saved_section = in_section;
2516
2517 switch_to_section (get_section (BRIG_ELF_SECTION_NAME, SECTION_NOTYPE, NULL));
2518 char tmp_name[64];
2519 ASM_GENERATE_INTERNAL_LABEL (tmp_name, BRIG_LABEL_STRING, 1);
2520 ASM_OUTPUT_LABEL (asm_out_file, tmp_name);
2521 tree brig_id = get_identifier (tmp_name);
2522 tree brig_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, brig_id,
2523 char_type_node);
2524 SET_DECL_ASSEMBLER_NAME (brig_decl, brig_id);
2525 TREE_ADDRESSABLE (brig_decl) = 1;
2526 TREE_READONLY (brig_decl) = 1;
2527 DECL_ARTIFICIAL (brig_decl) = 1;
2528 DECL_IGNORED_P (brig_decl) = 1;
2529 TREE_STATIC (brig_decl) = 1;
2530 TREE_PUBLIC (brig_decl) = 0;
2531 TREE_USED (brig_decl) = 1;
2532 DECL_INITIAL (brig_decl) = brig_decl;
2533 TREE_ASM_WRITTEN (brig_decl) = 1;
2534
2535 BrigModuleHeader module_header;
2536 memcpy (&module_header.identification, "HSA BRIG",
2537 sizeof (module_header.identification));
2538 module_header.brigMajor = lendian32 (BRIG_VERSION_BRIG_MAJOR);
2539 module_header.brigMinor = lendian32 (BRIG_VERSION_BRIG_MINOR);
2540 uint64_t section_index[3];
2541
2542 int data_padding, code_padding, operand_padding;
2543 data_padding = HSA_SECTION_ALIGNMENT
2544 - brig_data.total_size % HSA_SECTION_ALIGNMENT;
2545 code_padding = HSA_SECTION_ALIGNMENT
2546 - brig_code.total_size % HSA_SECTION_ALIGNMENT;
2547 operand_padding = HSA_SECTION_ALIGNMENT
2548 - brig_operand.total_size % HSA_SECTION_ALIGNMENT;
2549
2550 uint64_t module_size = sizeof (module_header)
2551 + sizeof (section_index)
2552 + brig_data.total_size
2553 + data_padding
2554 + brig_code.total_size
2555 + code_padding
2556 + brig_operand.total_size
2557 + operand_padding;
2558 gcc_assert ((module_size % 16) == 0);
2559 module_header.byteCount = lendian64 (module_size);
2560 memset (&module_header.hash, 0, sizeof (module_header.hash));
2561 module_header.reserved = 0;
2562 module_header.sectionCount = lendian32 (3);
2563 module_header.sectionIndex = lendian64 (sizeof (module_header));
2564 assemble_string ((const char *) &module_header, sizeof (module_header));
2565 uint64_t off = sizeof (module_header) + sizeof (section_index);
2566 section_index[0] = lendian64 (off);
2567 off += brig_data.total_size + data_padding;
2568 section_index[1] = lendian64 (off);
2569 off += brig_code.total_size + code_padding;
2570 section_index[2] = lendian64 (off);
2571 assemble_string ((const char *) &section_index, sizeof (section_index));
2572
2573 char padding[HSA_SECTION_ALIGNMENT];
2574 memset (padding, 0, sizeof (padding));
2575
2576 brig_data.output ();
2577 assemble_string (padding, data_padding);
2578 brig_code.output ();
2579 assemble_string (padding, code_padding);
2580 brig_operand.output ();
2581 assemble_string (padding, operand_padding);
2582
2583 if (saved_section)
2584 switch_to_section (saved_section);
2585
2586 hsa_output_libgomp_mapping (brig_decl);
2587
2588 hsa_free_decl_kernel_mapping ();
2589 brig_release_data ();
2590 hsa_deinit_compilation_unit_data ();
2591
2592 delete emitted_declarations;
2593 emitted_declarations = NULL;
2594 delete function_offsets;
2595 function_offsets = NULL;
2596 }