2016-01-26 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / gcc / hsa-brig.c
blobcfbac581a30b3d1f6632f99bd49455250ce26029
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>.
6 This file is part of GCC.
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.
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.
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/>. */
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"
49 /* Convert VAL to little endian form, if necessary. */
51 static uint16_t
52 lendian16 (uint16_t val)
54 #if GCC_VERSION >= 4006
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
72 /* Convert VAL to little endian form, if necessary. */
74 static uint32_t
75 lendian32 (uint32_t val)
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
96 /* Convert VAL to little endian form, if necessary. */
98 static uint64_t
99 lendian64 (uint64_t val)
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
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"
132 #define BRIG_CHUNK_MAX_SIZE (64 * 1024)
134 /* Required HSA section alignment. */
136 #define HSA_SECTION_ALIGNMENT 16
138 /* Chunks of BRIG binary data. */
140 struct hsa_brig_data_chunk
142 /* Size of the data already stored into a chunk. */
143 unsigned size;
145 /* Pointer to the data. */
146 char *data;
149 /* Structure representing a BRIG section, holding and writing its data. */
151 class hsa_brig_section
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;
163 /* Buffers of binary data, each containing BRIG_CHUNK_MAX_SIZE bytes. */
164 vec <struct hsa_brig_data_chunk> chunks;
166 /* More convenient access to the last chunk from the vector above. */
167 struct hsa_brig_data_chunk *cur_chunk;
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);
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;
182 /* Mapping between emitted HSA functions and their offset in code segment. */
183 static hash_map<tree, BrigCodeOffset32_t> *function_offsets;
185 /* Hash map of emitted function declarations. */
186 static hash_map <tree, BrigDirectiveExecutable *> *emitted_declarations;
188 /* Hash table of emitted internal function declaration offsets. */
189 hash_table <hsa_internal_fn_hasher> *hsa_emitted_internal_decls;
191 /* List of sbr instructions. */
192 static vec <hsa_insn_sbr *> *switch_instructions;
194 struct function_linkage_pair
196 function_linkage_pair (tree decl, unsigned int off)
197 : function_decl (decl), offset (off) {}
199 /* Declaration of called function. */
200 tree function_decl;
202 /* Offset in operand section. */
203 unsigned int offset;
206 /* Vector of function calls where we need to resolve function offsets. */
207 static auto_vec <function_linkage_pair> function_call_linkage;
209 /* Add a new chunk, allocate data for it and initialize it. */
211 void
212 hsa_brig_section::allocate_new_chunk ()
214 struct hsa_brig_data_chunk new_chunk;
216 new_chunk.data = XCNEWVEC (char, BRIG_CHUNK_MAX_SIZE);
217 new_chunk.size = 0;
218 cur_chunk = chunks.safe_push (new_chunk);
221 /* Initialize the brig section. */
223 void
224 hsa_brig_section::init (const char *name)
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;
239 /* Free all data in the section. */
241 void
242 hsa_brig_section::release ()
244 for (unsigned i = 0; i < chunks.length (); i++)
245 free (chunks[i].data);
246 chunks.release ();
247 cur_chunk = NULL;
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. */
253 void
254 hsa_brig_section::output ()
256 struct BrigSectionHeader section_header;
257 char padding[8];
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);
272 /* Add to the stream LEN bytes of opaque binary DATA. Return the offset at
273 which it was stored. */
275 unsigned
276 hsa_brig_section::add (const void *data, unsigned len)
278 unsigned offset = total_size;
280 gcc_assert (len <= BRIG_CHUNK_MAX_SIZE);
281 if (cur_chunk->size > (BRIG_CHUNK_MAX_SIZE - len))
282 allocate_new_chunk ();
284 memcpy (cur_chunk->data + cur_chunk->size, data, len);
285 cur_chunk->size += len;
286 total_size += len;
288 return offset;
291 /* Add padding to section so that its size is divisible by FACTOR. */
293 void
294 hsa_brig_section::round_size_up (int factor)
296 unsigned padding, res = total_size % factor;
298 if (res == 0)
299 return;
301 padding = factor - res;
302 total_size += padding;
303 if (cur_chunk->size > (BRIG_CHUNK_MAX_SIZE - padding))
305 padding -= BRIG_CHUNK_MAX_SIZE - cur_chunk->size;
306 cur_chunk->size = BRIG_CHUNK_MAX_SIZE;
307 allocate_new_chunk ();
310 cur_chunk->size += padding;
313 /* Return pointer to data by global OFFSET in the section. */
315 void *
316 hsa_brig_section::get_ptr_by_offset (unsigned int offset)
318 gcc_assert (offset < total_size);
319 offset -= header_byte_delta;
321 unsigned i;
322 for (i = 0; offset >= chunks[i].size; i++)
323 offset -= chunks[i].size;
325 return chunks[i].data + offset;
328 /* BRIG string data hashing. */
330 struct brig_string_slot
332 const char *s;
333 char prefix;
334 int len;
335 uint32_t offset;
338 /* Hash table helpers. */
340 struct brig_string_slot_hasher : pointer_hash <brig_string_slot>
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);
347 /* Returns a hash code for DS. Adapted from libiberty's htab_hash_string
348 to support strings that may not end in '\0'. */
350 inline hashval_t
351 brig_string_slot_hasher::hash (const value_type ds)
353 hashval_t r = ds->len;
354 int i;
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;
362 /* Returns nonzero if DS1 and DS2 are equal. */
364 inline bool
365 brig_string_slot_hasher::equal (const value_type ds1, const compare_type ds2)
367 if (ds1->len == ds2->len)
368 return ds1->prefix == ds2->prefix
369 && memcmp (ds1->s, ds2->s, ds1->len) == 0;
371 return 0;
374 /* Deallocate memory for DS upon its removal. */
376 inline void
377 brig_string_slot_hasher::remove (value_type ds)
379 free (const_cast<char *> (ds->s));
380 free (ds);
383 /* Hash for strings we output in order not to duplicate them needlessly. */
385 static hash_table<brig_string_slot_hasher> *brig_string_htab;
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. */
391 static unsigned
392 brig_emit_string (const char *str, char prefix = 0, bool sanitize = true)
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;
401 str2 = xstrdup (str);
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;
410 slot = brig_string_htab->find_slot (&s_slot, INSERT);
411 if (*slot == NULL)
413 brig_string_slot *new_slot = XCNEW (brig_string_slot);
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);
421 brig_data.add (str2, slen);
422 brig_data.round_size_up (4);
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;
432 else
434 offset = (*slot)->offset;
435 free (str2);
438 return offset;
441 /* Linked list of queued operands. */
443 static struct operand_queue
445 /* First from the chain of queued operands. */
446 hsa_op_base *first_op, *last_op;
448 /* The offset at which the next operand will be enqueued. */
449 unsigned projected_size;
451 } op_queue;
453 /* Unless already initialized, initialize infrastructure to produce BRIG. */
455 static void
456 brig_init (void)
458 brig_insn_count = 0;
460 if (brig_initialized)
461 return;
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;
469 struct BrigDirectiveModule moddir;
470 memset (&moddir, 0, sizeof (moddir));
471 moddir.base.byteCount = lendian16 (sizeof (moddir));
473 char *modname;
474 if (main_input_filename && *main_input_filename != '\0')
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';
486 /* As in LTO mode, we have to emit a different module names. */
487 if (flag_ltrans)
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;
500 hsa_sanitize_name (modname);
501 moddir.name = brig_emit_string (modname);
502 free (modname);
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));
518 /* Free all BRIG data. */
520 static void
521 brig_release_data (void)
523 delete brig_string_htab;
524 brig_data.release ();
525 brig_code.release ();
526 brig_operand.release ();
528 brig_initialized = 0;
531 /* Enqueue operation OP. Return the offset at which it will be stored. */
533 static unsigned int
534 enqueue_op (hsa_op_base *op)
536 unsigned ret;
538 if (op->m_brig_op_offset)
539 return op->m_brig_op_offset;
541 ret = op_queue.projected_size;
542 op->m_brig_op_offset = op_queue.projected_size;
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;
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;
568 /* Emit directive describing a symbol if it has not been emitted already.
569 Return the offset of the directive. */
571 static unsigned
572 emit_directive_variable (struct hsa_symbol *symbol)
574 struct BrigDirectiveVariable dirvar;
575 unsigned name_offset;
576 static unsigned res_name_offset;
578 if (symbol->m_directive_offset)
579 return symbol->m_directive_offset;
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;
586 char prefix = symbol->m_global_scope_p ? '&' : '%';
588 if (symbol->m_decl && TREE_CODE (symbol->m_decl) == RESULT_DECL)
590 if (res_name_offset == 0)
591 res_name_offset = brig_emit_string (symbol->m_name, '%');
592 name_offset = res_name_offset;
594 else if (symbol->m_name)
595 name_offset = brig_emit_string (symbol->m_name, prefix);
596 else
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);
604 dirvar.name = lendian32 (name_offset);
605 dirvar.init = 0;
606 dirvar.type = lendian16 (symbol->m_type);
607 dirvar.segment = symbol->m_segment;
608 /* TODO: Once we are able to access global variables, we must copy their
609 alignment. */
610 dirvar.align = MAX (hsa_natural_alignment (dirvar.type),
611 (BrigAlignment8_t) BRIG_ALIGNMENT_4);
612 dirvar.linkage = symbol->m_linkage;
613 dirvar.dim.lo = symbol->m_dim;
614 dirvar.dim.hi = symbol->m_dim >> 32;
616 /* Global variables are just declared and linked via HSA runtime. */
617 if (symbol->m_linkage != BRIG_ALLOCATION_PROGRAM)
618 dirvar.modifier |= BRIG_VARIABLE_DEFINITION;
619 dirvar.reserved = 0;
621 if (symbol->m_cst_value)
623 dirvar.modifier |= BRIG_VARIABLE_CONST;
624 dirvar.init = lendian32 (enqueue_op (symbol->m_cst_value));
627 symbol->m_directive_offset = brig_code.add (&dirvar, sizeof (dirvar));
628 return symbol->m_directive_offset;
631 /* Emit directives describing either a function declaration or
632 definition F. */
634 static BrigDirectiveExecutable *
635 emit_function_directives (hsa_function_representation *f, bool is_declaration)
637 struct BrigDirectiveExecutable fndir;
638 unsigned name_offset, inarg_off, scoped_off, next_toplev_off;
639 int count = 0;
640 BrigDirectiveExecutable *ptr_to_fndir;
641 hsa_symbol *sym;
643 if (!f->m_declaration_p)
644 for (int i = 0; f->m_global_symbols.iterate (i, &sym); i++)
646 emit_directive_variable (sym);
647 brig_insn_count++;
650 name_offset = brig_emit_string (f->m_name, '&');
651 inarg_off = brig_code.total_size + sizeof (fndir)
652 + (f->m_output_arg ? sizeof (struct BrigDirectiveVariable) : 0);
653 scoped_off = inarg_off
654 + f->m_input_args.length () * sizeof (struct BrigDirectiveVariable);
656 if (!f->m_declaration_p)
658 count += f->m_spill_symbols.length ();
659 count += f->m_private_variables.length ();
662 next_toplev_off = scoped_off + count * sizeof (struct BrigDirectiveVariable);
664 memset (&fndir, 0, sizeof (fndir));
665 fndir.base.byteCount = lendian16 (sizeof (fndir));
666 fndir.base.kind = lendian16 (f->m_kern_p ? BRIG_KIND_DIRECTIVE_KERNEL
667 : BRIG_KIND_DIRECTIVE_FUNCTION);
668 fndir.name = lendian32 (name_offset);
669 fndir.inArgCount = lendian16 (f->m_input_args.length ());
670 fndir.outArgCount = lendian16 (f->m_output_arg ? 1 : 0);
671 fndir.firstInArg = lendian32 (inarg_off);
672 fndir.firstCodeBlockEntry = lendian32 (scoped_off);
673 fndir.nextModuleEntry = lendian32 (next_toplev_off);
674 fndir.linkage = f->get_linkage ();
675 if (!f->m_declaration_p)
676 fndir.modifier |= BRIG_EXECUTABLE_DEFINITION;
677 memset (&fndir.reserved, 0, sizeof (fndir.reserved));
679 /* Once we put a definition of function_offsets, we should not overwrite
680 it with a declaration of the function. */
681 if (f->m_internal_fn == NULL)
683 if (!function_offsets->get (f->m_decl) || !is_declaration)
684 function_offsets->put (f->m_decl, brig_code.total_size);
686 else
688 /* Internal function. */
689 hsa_internal_fn **slot
690 = hsa_emitted_internal_decls->find_slot (f->m_internal_fn, INSERT);
691 hsa_internal_fn *int_fn = new hsa_internal_fn (f->m_internal_fn);
692 int_fn->m_offset = brig_code.total_size;
693 *slot = int_fn;
696 brig_code.add (&fndir, sizeof (fndir));
697 /* terrible hack: we need to set instCount after we emit all
698 insns, but we need to emit directive in order, and we emit directives
699 during insn emitting. So we need to emit the FUNCTION directive
700 early, then the insns, and then we need to set instCount, so remember
701 a pointer to it, in some horrible way. cur_chunk.data+size points
702 directly to after fndir here. */
703 ptr_to_fndir
704 = (BrigDirectiveExecutable *)(brig_code.cur_chunk->data
705 + brig_code.cur_chunk->size
706 - sizeof (fndir));
708 if (f->m_output_arg)
709 emit_directive_variable (f->m_output_arg);
710 for (unsigned i = 0; i < f->m_input_args.length (); i++)
711 emit_directive_variable (f->m_input_args[i]);
713 if (!f->m_declaration_p)
715 for (int i = 0; f->m_spill_symbols.iterate (i, &sym); i++)
717 emit_directive_variable (sym);
718 brig_insn_count++;
720 for (unsigned i = 0; i < f->m_private_variables.length (); i++)
722 emit_directive_variable (f->m_private_variables[i]);
723 brig_insn_count++;
727 return ptr_to_fndir;
730 /* Emit a label directive for the given HBB. We assume it is about to start on
731 the current offset in the code section. */
733 static void
734 emit_bb_label_directive (hsa_bb *hbb)
736 struct BrigDirectiveLabel lbldir;
738 lbldir.base.byteCount = lendian16 (sizeof (lbldir));
739 lbldir.base.kind = lendian16 (BRIG_KIND_DIRECTIVE_LABEL);
740 char buf[32];
741 snprintf (buf, 32, "BB_%u_%i", DECL_UID (current_function_decl),
742 hbb->m_index);
743 lbldir.name = lendian32 (brig_emit_string (buf, '@'));
745 hbb->m_label_ref.m_directive_offset = brig_code.add (&lbldir,
746 sizeof (lbldir));
747 brig_insn_count++;
750 /* Map a normal HSAIL type to the type of the equivalent BRIG operand
751 holding such, for constants and registers. */
753 static BrigType16_t
754 regtype_for_type (BrigType16_t t)
756 switch (t)
758 case BRIG_TYPE_B1:
759 return BRIG_TYPE_B1;
761 case BRIG_TYPE_U8:
762 case BRIG_TYPE_U16:
763 case BRIG_TYPE_U32:
764 case BRIG_TYPE_S8:
765 case BRIG_TYPE_S16:
766 case BRIG_TYPE_S32:
767 case BRIG_TYPE_B8:
768 case BRIG_TYPE_B16:
769 case BRIG_TYPE_B32:
770 case BRIG_TYPE_F16:
771 case BRIG_TYPE_F32:
772 case BRIG_TYPE_U8X4:
773 case BRIG_TYPE_U16X2:
774 case BRIG_TYPE_S8X4:
775 case BRIG_TYPE_S16X2:
776 case BRIG_TYPE_F16X2:
777 return BRIG_TYPE_B32;
779 case BRIG_TYPE_U64:
780 case BRIG_TYPE_S64:
781 case BRIG_TYPE_F64:
782 case BRIG_TYPE_B64:
783 case BRIG_TYPE_U8X8:
784 case BRIG_TYPE_U16X4:
785 case BRIG_TYPE_U32X2:
786 case BRIG_TYPE_S8X8:
787 case BRIG_TYPE_S16X4:
788 case BRIG_TYPE_S32X2:
789 case BRIG_TYPE_F16X4:
790 case BRIG_TYPE_F32X2:
791 return BRIG_TYPE_B64;
793 case BRIG_TYPE_B128:
794 case BRIG_TYPE_U8X16:
795 case BRIG_TYPE_U16X8:
796 case BRIG_TYPE_U32X4:
797 case BRIG_TYPE_U64X2:
798 case BRIG_TYPE_S8X16:
799 case BRIG_TYPE_S16X8:
800 case BRIG_TYPE_S32X4:
801 case BRIG_TYPE_S64X2:
802 case BRIG_TYPE_F16X8:
803 case BRIG_TYPE_F32X4:
804 case BRIG_TYPE_F64X2:
805 return BRIG_TYPE_B128;
807 default:
808 gcc_unreachable ();
812 /* Return the length of the BRIG type TYPE that is going to be streamed out as
813 an immediate constant (so it must not be B1). */
815 unsigned
816 hsa_get_imm_brig_type_len (BrigType16_t type)
818 BrigType16_t base_type = type & BRIG_TYPE_BASE_MASK;
819 BrigType16_t pack_type = type & BRIG_TYPE_PACK_MASK;
821 switch (pack_type)
823 case BRIG_TYPE_PACK_NONE:
824 break;
825 case BRIG_TYPE_PACK_32:
826 return 4;
827 case BRIG_TYPE_PACK_64:
828 return 8;
829 case BRIG_TYPE_PACK_128:
830 return 16;
831 default:
832 gcc_unreachable ();
835 switch (base_type)
837 case BRIG_TYPE_U8:
838 case BRIG_TYPE_S8:
839 case BRIG_TYPE_B8:
840 return 1;
841 case BRIG_TYPE_U16:
842 case BRIG_TYPE_S16:
843 case BRIG_TYPE_F16:
844 case BRIG_TYPE_B16:
845 return 2;
846 case BRIG_TYPE_U32:
847 case BRIG_TYPE_S32:
848 case BRIG_TYPE_F32:
849 case BRIG_TYPE_B32:
850 return 4;
851 case BRIG_TYPE_U64:
852 case BRIG_TYPE_S64:
853 case BRIG_TYPE_F64:
854 case BRIG_TYPE_B64:
855 return 8;
856 case BRIG_TYPE_B128:
857 return 16;
858 default:
859 gcc_unreachable ();
863 /* Emit one scalar VALUE to the buffer DATA intended for BRIG emission.
864 If NEED_LEN is not equal to zero, shrink or extend the value
865 to NEED_LEN bytes. Return how many bytes were written. */
867 static int
868 emit_immediate_scalar_to_buffer (tree value, char *data, unsigned need_len)
870 union hsa_bytes bytes;
872 memset (&bytes, 0, sizeof (bytes));
873 tree type = TREE_TYPE (value);
874 gcc_checking_assert (TREE_CODE (type) != VECTOR_TYPE);
876 unsigned data_len = tree_to_uhwi (TYPE_SIZE (type)) / BITS_PER_UNIT;
877 if (INTEGRAL_TYPE_P (type)
878 || (POINTER_TYPE_P (type) && TREE_CODE (value) == INTEGER_CST))
879 switch (data_len)
881 case 1:
882 bytes.b8 = (uint8_t) TREE_INT_CST_LOW (value);
883 break;
884 case 2:
885 bytes.b16 = (uint16_t) TREE_INT_CST_LOW (value);
886 break;
887 case 4:
888 bytes.b32 = (uint32_t) TREE_INT_CST_LOW (value);
889 break;
890 case 8:
891 bytes.b64 = (uint64_t) TREE_INT_CST_LOW (value);
892 break;
893 default:
894 gcc_unreachable ();
896 else if (SCALAR_FLOAT_TYPE_P (type))
898 if (data_len == 2)
900 sorry ("Support for HSA does not implement immediate 16 bit FPU "
901 "operands");
902 return 2;
904 unsigned int_len = GET_MODE_SIZE (TYPE_MODE (type));
905 /* There are always 32 bits in each long, no matter the size of
906 the hosts long. */
907 long tmp[6];
909 real_to_target (tmp, TREE_REAL_CST_PTR (value), TYPE_MODE (type));
911 if (int_len == 4)
912 bytes.b32 = (uint32_t) tmp[0];
913 else
915 bytes.b64 = (uint64_t)(uint32_t) tmp[1];
916 bytes.b64 <<= 32;
917 bytes.b64 |= (uint32_t) tmp[0];
920 else
921 gcc_unreachable ();
923 int len;
924 if (need_len == 0)
925 len = data_len;
926 else
927 len = need_len;
929 memcpy (data, &bytes, len);
930 return len;
933 void
934 hsa_op_immed::emit_to_buffer (tree value)
936 unsigned total_len = m_brig_repr_size;
938 /* As we can have a constructor with fewer elements, fill the memory
939 with zeros. */
940 m_brig_repr = XCNEWVEC (char, total_len);
941 char *p = m_brig_repr;
943 if (TREE_CODE (value) == VECTOR_CST)
945 int i, num = VECTOR_CST_NELTS (value);
946 for (i = 0; i < num; i++)
948 unsigned actual;
949 actual
950 = emit_immediate_scalar_to_buffer (VECTOR_CST_ELT (value, i), p, 0);
951 total_len -= actual;
952 p += actual;
954 /* Vectors should have the exact size. */
955 gcc_assert (total_len == 0);
957 else if (TREE_CODE (value) == STRING_CST)
958 memcpy (m_brig_repr, TREE_STRING_POINTER (value),
959 TREE_STRING_LENGTH (value));
960 else if (TREE_CODE (value) == COMPLEX_CST)
962 gcc_assert (total_len % 2 == 0);
963 unsigned actual;
964 actual
965 = emit_immediate_scalar_to_buffer (TREE_REALPART (value), p,
966 total_len / 2);
968 gcc_assert (actual == total_len / 2);
969 p += actual;
971 actual
972 = emit_immediate_scalar_to_buffer (TREE_IMAGPART (value), p,
973 total_len / 2);
974 gcc_assert (actual == total_len / 2);
976 else if (TREE_CODE (value) == CONSTRUCTOR)
978 unsigned len = vec_safe_length (CONSTRUCTOR_ELTS (value));
979 for (unsigned i = 0; i < len; i++)
981 tree v = CONSTRUCTOR_ELT (value, i)->value;
982 unsigned actual = emit_immediate_scalar_to_buffer (v, p, 0);
983 total_len -= actual;
984 p += actual;
987 else
988 emit_immediate_scalar_to_buffer (value, p, total_len);
991 /* Emit an immediate BRIG operand IMM. The BRIG type of the immediate might
992 have been massaged to comply with various HSA/BRIG type requirements, so the
993 only important aspect of that is the length (because HSAIL might expect
994 smaller constants or become bit-data). The data should be represented
995 according to what is in the tree representation. */
997 static void
998 emit_immediate_operand (hsa_op_immed *imm)
1000 struct BrigOperandConstantBytes out;
1002 memset (&out, 0, sizeof (out));
1003 out.base.byteCount = lendian16 (sizeof (out));
1004 out.base.kind = lendian16 (BRIG_KIND_OPERAND_CONSTANT_BYTES);
1005 uint32_t byteCount = lendian32 (imm->m_brig_repr_size);
1006 out.type = lendian16 (imm->m_type);
1007 out.bytes = lendian32 (brig_data.add (&byteCount, sizeof (byteCount)));
1008 brig_operand.add (&out, sizeof (out));
1009 brig_data.add (imm->m_brig_repr, imm->m_brig_repr_size);
1010 brig_data.round_size_up (4);
1013 /* Emit a register BRIG operand REG. */
1015 static void
1016 emit_register_operand (hsa_op_reg *reg)
1018 struct BrigOperandRegister out;
1020 out.base.byteCount = lendian16 (sizeof (out));
1021 out.base.kind = lendian16 (BRIG_KIND_OPERAND_REGISTER);
1022 out.regNum = lendian32 (reg->m_hard_num);
1024 switch (regtype_for_type (reg->m_type))
1026 case BRIG_TYPE_B32:
1027 out.regKind = BRIG_REGISTER_KIND_SINGLE;
1028 break;
1029 case BRIG_TYPE_B64:
1030 out.regKind = BRIG_REGISTER_KIND_DOUBLE;
1031 break;
1032 case BRIG_TYPE_B128:
1033 out.regKind = BRIG_REGISTER_KIND_QUAD;
1034 break;
1035 case BRIG_TYPE_B1:
1036 out.regKind = BRIG_REGISTER_KIND_CONTROL;
1037 break;
1038 default:
1039 gcc_unreachable ();
1042 brig_operand.add (&out, sizeof (out));
1045 /* Emit an address BRIG operand ADDR. */
1047 static void
1048 emit_address_operand (hsa_op_address *addr)
1050 struct BrigOperandAddress out;
1052 out.base.byteCount = lendian16 (sizeof (out));
1053 out.base.kind = lendian16 (BRIG_KIND_OPERAND_ADDRESS);
1054 out.symbol = addr->m_symbol
1055 ? lendian32 (emit_directive_variable (addr->m_symbol)) : 0;
1056 out.reg = addr->m_reg ? lendian32 (enqueue_op (addr->m_reg)) : 0;
1058 if (sizeof (addr->m_imm_offset) == 8)
1060 out.offset.lo = lendian32 (addr->m_imm_offset);
1061 out.offset.hi = lendian32 (addr->m_imm_offset >> 32);
1063 else
1065 gcc_assert (sizeof (addr->m_imm_offset) == 4);
1066 out.offset.lo = lendian32 (addr->m_imm_offset);
1067 out.offset.hi = 0;
1070 brig_operand.add (&out, sizeof (out));
1073 /* Emit a code reference operand REF. */
1075 static void
1076 emit_code_ref_operand (hsa_op_code_ref *ref)
1078 struct BrigOperandCodeRef out;
1080 out.base.byteCount = lendian16 (sizeof (out));
1081 out.base.kind = lendian16 (BRIG_KIND_OPERAND_CODE_REF);
1082 out.ref = lendian32 (ref->m_directive_offset);
1083 brig_operand.add (&out, sizeof (out));
1086 /* Emit a code list operand CODE_LIST. */
1088 static void
1089 emit_code_list_operand (hsa_op_code_list *code_list)
1091 struct BrigOperandCodeList out;
1092 unsigned args = code_list->m_offsets.length ();
1094 for (unsigned i = 0; i < args; i++)
1095 gcc_assert (code_list->m_offsets[i]);
1097 out.base.byteCount = lendian16 (sizeof (out));
1098 out.base.kind = lendian16 (BRIG_KIND_OPERAND_CODE_LIST);
1100 uint32_t byteCount = lendian32 (4 * args);
1102 out.elements = lendian32 (brig_data.add (&byteCount, sizeof (byteCount)));
1103 brig_data.add (code_list->m_offsets.address (), args * sizeof (uint32_t));
1104 brig_data.round_size_up (4);
1105 brig_operand.add (&out, sizeof (out));
1108 /* Emit an operand list operand OPERAND_LIST. */
1110 static void
1111 emit_operand_list_operand (hsa_op_operand_list *operand_list)
1113 struct BrigOperandOperandList out;
1114 unsigned args = operand_list->m_offsets.length ();
1116 for (unsigned i = 0; i < args; i++)
1117 gcc_assert (operand_list->m_offsets[i]);
1119 out.base.byteCount = lendian16 (sizeof (out));
1120 out.base.kind = lendian16 (BRIG_KIND_OPERAND_OPERAND_LIST);
1122 uint32_t byteCount = lendian32 (4 * args);
1124 out.elements = lendian32 (brig_data.add (&byteCount, sizeof (byteCount)));
1125 brig_data.add (operand_list->m_offsets.address (), args * sizeof (uint32_t));
1126 brig_data.round_size_up (4);
1127 brig_operand.add (&out, sizeof (out));
1130 /* Emit all operands queued for writing. */
1132 static void
1133 emit_queued_operands (void)
1135 for (hsa_op_base *op = op_queue.first_op; op; op = op->m_next)
1137 gcc_assert (op->m_brig_op_offset == brig_operand.total_size);
1138 if (hsa_op_immed *imm = dyn_cast <hsa_op_immed *> (op))
1139 emit_immediate_operand (imm);
1140 else if (hsa_op_reg *reg = dyn_cast <hsa_op_reg *> (op))
1141 emit_register_operand (reg);
1142 else if (hsa_op_address *addr = dyn_cast <hsa_op_address *> (op))
1143 emit_address_operand (addr);
1144 else if (hsa_op_code_ref *ref = dyn_cast <hsa_op_code_ref *> (op))
1145 emit_code_ref_operand (ref);
1146 else if (hsa_op_code_list *code_list = dyn_cast <hsa_op_code_list *> (op))
1147 emit_code_list_operand (code_list);
1148 else if (hsa_op_operand_list *l = dyn_cast <hsa_op_operand_list *> (op))
1149 emit_operand_list_operand (l);
1150 else
1151 gcc_unreachable ();
1155 /* Emit directives describing the function that is used for
1156 a function declaration. */
1158 static BrigDirectiveExecutable *
1159 emit_function_declaration (tree decl)
1161 hsa_function_representation *f = hsa_generate_function_declaration (decl);
1163 BrigDirectiveExecutable *e = emit_function_directives (f, true);
1164 emit_queued_operands ();
1166 delete f;
1168 return e;
1171 /* Emit directives describing the function that is used for
1172 an internal function declaration. */
1174 static BrigDirectiveExecutable *
1175 emit_internal_fn_decl (hsa_internal_fn *fn)
1177 hsa_function_representation *f = hsa_generate_internal_fn_decl (fn);
1179 BrigDirectiveExecutable *e = emit_function_directives (f, true);
1180 emit_queued_operands ();
1182 delete f;
1184 return e;
1187 /* Enqueue all operands of INSN and return offset to BRIG data section
1188 to list of operand offsets. */
1190 static unsigned
1191 emit_insn_operands (hsa_insn_basic *insn)
1193 auto_vec<BrigOperandOffset32_t, HSA_BRIG_INT_STORAGE_OPERANDS>
1194 operand_offsets;
1196 unsigned l = insn->operand_count ();
1197 operand_offsets.safe_grow (l);
1199 for (unsigned i = 0; i < l; i++)
1200 operand_offsets[i] = lendian32 (enqueue_op (insn->get_op (i)));
1202 /* We have N operands so use 4 * N for the byte_count. */
1203 uint32_t byte_count = lendian32 (4 * l);
1205 unsigned offset = brig_data.add (&byte_count, sizeof (byte_count));
1206 brig_data.add (operand_offsets.address (),
1207 l * sizeof (BrigOperandOffset32_t));
1209 brig_data.round_size_up (4);
1211 return offset;
1214 /* Enqueue operand OP0, OP1, OP2 (if different from NULL) and return offset
1215 to BRIG data section to list of operand offsets. */
1217 static unsigned
1218 emit_operands (hsa_op_base *op0, hsa_op_base *op1 = NULL,
1219 hsa_op_base *op2 = NULL)
1221 auto_vec<BrigOperandOffset32_t, HSA_BRIG_INT_STORAGE_OPERANDS>
1222 operand_offsets;
1224 gcc_checking_assert (op0 != NULL);
1225 operand_offsets.safe_push (enqueue_op (op0));
1227 if (op1 != NULL)
1229 operand_offsets.safe_push (enqueue_op (op1));
1230 if (op2 != NULL)
1231 operand_offsets.safe_push (enqueue_op (op2));
1234 unsigned l = operand_offsets.length ();
1236 /* We have N operands so use 4 * N for the byte_count. */
1237 uint32_t byte_count = lendian32 (4 * l);
1239 unsigned offset = brig_data.add (&byte_count, sizeof (byte_count));
1240 brig_data.add (operand_offsets.address (),
1241 l * sizeof (BrigOperandOffset32_t));
1243 brig_data.round_size_up (4);
1245 return offset;
1248 /* Emit an HSA memory instruction and all necessary directives, schedule
1249 necessary operands for writing. */
1251 static void
1252 emit_memory_insn (hsa_insn_mem *mem)
1254 struct BrigInstMem repr;
1255 gcc_checking_assert (mem->operand_count () == 2);
1257 hsa_op_address *addr = as_a <hsa_op_address *> (mem->get_op (1));
1259 /* This is necessary because of the erroneous typedef of
1260 BrigMemoryModifier8_t which introduces padding which may then contain
1261 random stuff (which we do not want so that we can test things don't
1262 change). */
1263 memset (&repr, 0, sizeof (repr));
1264 repr.base.base.byteCount = lendian16 (sizeof (repr));
1265 repr.base.base.kind = lendian16 (BRIG_KIND_INST_MEM);
1266 repr.base.opcode = lendian16 (mem->m_opcode);
1267 repr.base.type = lendian16 (mem->m_type);
1268 repr.base.operands = lendian32 (emit_insn_operands (mem));
1270 if (addr->m_symbol)
1271 repr.segment = addr->m_symbol->m_segment;
1272 else
1273 repr.segment = BRIG_SEGMENT_FLAT;
1274 repr.modifier = 0;
1275 repr.equivClass = mem->m_equiv_class;
1276 repr.align = mem->m_align;
1277 if (mem->m_opcode == BRIG_OPCODE_LD)
1278 repr.width = BRIG_WIDTH_1;
1279 else
1280 repr.width = BRIG_WIDTH_NONE;
1281 memset (&repr.reserved, 0, sizeof (repr.reserved));
1282 brig_code.add (&repr, sizeof (repr));
1283 brig_insn_count++;
1286 /* Emit an HSA signal memory instruction and all necessary directives, schedule
1287 necessary operands for writing. */
1289 static void
1290 emit_signal_insn (hsa_insn_signal *mem)
1292 struct BrigInstSignal repr;
1294 /* This is necessary because of the erroneous typedef of
1295 BrigMemoryModifier8_t which introduces padding which may then contain
1296 random stuff (which we do not want so that we can test things don't
1297 change). */
1298 memset (&repr, 0, sizeof (repr));
1299 repr.base.base.byteCount = lendian16 (sizeof (repr));
1300 repr.base.base.kind = lendian16 (BRIG_KIND_INST_SIGNAL);
1301 repr.base.opcode = lendian16 (mem->m_opcode);
1302 repr.base.type = lendian16 (mem->m_type);
1303 repr.base.operands = lendian32 (emit_insn_operands (mem));
1305 repr.memoryOrder = mem->m_memoryorder;
1306 repr.signalOperation = mem->m_atomicop;
1307 repr.signalType = BRIG_TYPE_SIG64;
1309 brig_code.add (&repr, sizeof (repr));
1310 brig_insn_count++;
1313 /* Emit an HSA atomic memory instruction and all necessary directives, schedule
1314 necessary operands for writing. */
1316 static void
1317 emit_atomic_insn (hsa_insn_atomic *mem)
1319 struct BrigInstAtomic repr;
1321 /* Either operand[0] or operand[1] must be an address operand. */
1322 hsa_op_address *addr = NULL;
1323 if (is_a <hsa_op_address *> (mem->get_op (0)))
1324 addr = as_a <hsa_op_address *> (mem->get_op (0));
1325 else
1326 addr = as_a <hsa_op_address *> (mem->get_op (1));
1328 /* This is necessary because of the erroneous typedef of
1329 BrigMemoryModifier8_t which introduces padding which may then contain
1330 random stuff (which we do not want so that we can test things don't
1331 change). */
1332 memset (&repr, 0, sizeof (repr));
1333 repr.base.base.byteCount = lendian16 (sizeof (repr));
1334 repr.base.base.kind = lendian16 (BRIG_KIND_INST_ATOMIC);
1335 repr.base.opcode = lendian16 (mem->m_opcode);
1336 repr.base.type = lendian16 (mem->m_type);
1337 repr.base.operands = lendian32 (emit_insn_operands (mem));
1339 if (addr->m_symbol)
1340 repr.segment = addr->m_symbol->m_segment;
1341 else
1342 repr.segment = BRIG_SEGMENT_FLAT;
1343 repr.memoryOrder = mem->m_memoryorder;
1344 repr.memoryScope = mem->m_memoryscope;
1345 repr.atomicOperation = mem->m_atomicop;
1347 brig_code.add (&repr, sizeof (repr));
1348 brig_insn_count++;
1351 /* Emit an HSA LDA instruction and all necessary directives, schedule
1352 necessary operands for writing. */
1354 static void
1355 emit_addr_insn (hsa_insn_basic *insn)
1357 struct BrigInstAddr repr;
1359 hsa_op_address *addr = as_a <hsa_op_address *> (insn->get_op (1));
1361 repr.base.base.byteCount = lendian16 (sizeof (repr));
1362 repr.base.base.kind = lendian16 (BRIG_KIND_INST_ADDR);
1363 repr.base.opcode = lendian16 (insn->m_opcode);
1364 repr.base.type = lendian16 (insn->m_type);
1365 repr.base.operands = lendian32 (emit_insn_operands (insn));
1367 if (addr->m_symbol)
1368 repr.segment = addr->m_symbol->m_segment;
1369 else
1370 repr.segment = BRIG_SEGMENT_FLAT;
1371 memset (&repr.reserved, 0, sizeof (repr.reserved));
1373 brig_code.add (&repr, sizeof (repr));
1374 brig_insn_count++;
1377 /* Emit an HSA segment conversion instruction and all necessary directives,
1378 schedule necessary operands for writing. */
1380 static void
1381 emit_segment_insn (hsa_insn_seg *seg)
1383 struct BrigInstSegCvt repr;
1385 repr.base.base.byteCount = lendian16 (sizeof (repr));
1386 repr.base.base.kind = lendian16 (BRIG_KIND_INST_SEG_CVT);
1387 repr.base.opcode = lendian16 (seg->m_opcode);
1388 repr.base.type = lendian16 (seg->m_type);
1389 repr.base.operands = lendian32 (emit_insn_operands (seg));
1390 repr.sourceType = lendian16 (as_a <hsa_op_reg *> (seg->get_op (1))->m_type);
1391 repr.segment = seg->m_segment;
1392 repr.modifier = 0;
1394 brig_code.add (&repr, sizeof (repr));
1396 brig_insn_count++;
1399 /* Emit an HSA alloca instruction and all necessary directives,
1400 schedule necessary operands for writing. */
1402 static void
1403 emit_alloca_insn (hsa_insn_alloca *alloca)
1405 struct BrigInstMem repr;
1406 gcc_checking_assert (alloca->operand_count () == 2);
1408 /* This is necessary because of the erroneous typedef of
1409 BrigMemoryModifier8_t which introduces padding which may then contain
1410 random stuff (which we do not want so that we can test things don't
1411 change). */
1412 memset (&repr, 0, sizeof (repr));
1413 repr.base.base.byteCount = lendian16 (sizeof (repr));
1414 repr.base.base.kind = lendian16 (BRIG_KIND_INST_MEM);
1415 repr.base.opcode = lendian16 (alloca->m_opcode);
1416 repr.base.type = lendian16 (alloca->m_type);
1417 repr.base.operands = lendian32 (emit_insn_operands (alloca));
1418 repr.segment = BRIG_SEGMENT_PRIVATE;
1419 repr.modifier = 0;
1420 repr.equivClass = 0;
1421 repr.align = alloca->m_align;
1422 repr.width = BRIG_WIDTH_NONE;
1423 memset (&repr.reserved, 0, sizeof (repr.reserved));
1424 brig_code.add (&repr, sizeof (repr));
1425 brig_insn_count++;
1428 /* Emit an HSA comparison instruction and all necessary directives,
1429 schedule necessary operands for writing. */
1431 static void
1432 emit_cmp_insn (hsa_insn_cmp *cmp)
1434 struct BrigInstCmp repr;
1436 memset (&repr, 0, sizeof (repr));
1437 repr.base.base.byteCount = lendian16 (sizeof (repr));
1438 repr.base.base.kind = lendian16 (BRIG_KIND_INST_CMP);
1439 repr.base.opcode = lendian16 (cmp->m_opcode);
1440 repr.base.type = lendian16 (cmp->m_type);
1441 repr.base.operands = lendian32 (emit_insn_operands (cmp));
1443 if (is_a <hsa_op_reg *> (cmp->get_op (1)))
1444 repr.sourceType
1445 = lendian16 (as_a <hsa_op_reg *> (cmp->get_op (1))->m_type);
1446 else
1447 repr.sourceType
1448 = lendian16 (as_a <hsa_op_immed *> (cmp->get_op (1))->m_type);
1449 repr.modifier = 0;
1450 repr.compare = cmp->m_compare;
1451 repr.pack = 0;
1453 brig_code.add (&repr, sizeof (repr));
1454 brig_insn_count++;
1457 /* Emit an HSA branching instruction and all necessary directives, schedule
1458 necessary operands for writing. */
1460 static void
1461 emit_branch_insn (hsa_insn_br *br)
1463 struct BrigInstBr repr;
1465 basic_block target = NULL;
1466 edge_iterator ei;
1467 edge e;
1469 /* At the moment we only handle direct conditional jumps. */
1470 gcc_assert (br->m_opcode == BRIG_OPCODE_CBR);
1471 repr.base.base.byteCount = lendian16 (sizeof (repr));
1472 repr.base.base.kind = lendian16 (BRIG_KIND_INST_BR);
1473 repr.base.opcode = lendian16 (br->m_opcode);
1474 repr.width = BRIG_WIDTH_1;
1475 /* For Conditional jumps the type is always B1. */
1476 repr.base.type = lendian16 (BRIG_TYPE_B1);
1478 FOR_EACH_EDGE (e, ei, br->m_bb->succs)
1479 if (e->flags & EDGE_TRUE_VALUE)
1481 target = e->dest;
1482 break;
1484 gcc_assert (target);
1486 repr.base.operands
1487 = lendian32 (emit_operands (br->get_op (0),
1488 &hsa_bb_for_bb (target)->m_label_ref));
1489 memset (&repr.reserved, 0, sizeof (repr.reserved));
1491 brig_code.add (&repr, sizeof (repr));
1492 brig_insn_count++;
1495 /* Emit an HSA unconditional jump branching instruction that points to
1496 a label REFERENCE. */
1498 static void
1499 emit_unconditional_jump (hsa_op_code_ref *reference)
1501 struct BrigInstBr repr;
1503 repr.base.base.byteCount = lendian16 (sizeof (repr));
1504 repr.base.base.kind = lendian16 (BRIG_KIND_INST_BR);
1505 repr.base.opcode = lendian16 (BRIG_OPCODE_BR);
1506 repr.base.type = lendian16 (BRIG_TYPE_NONE);
1507 /* Direct branches to labels must be width(all). */
1508 repr.width = BRIG_WIDTH_ALL;
1510 repr.base.operands = lendian32 (emit_operands (reference));
1511 memset (&repr.reserved, 0, sizeof (repr.reserved));
1512 brig_code.add (&repr, sizeof (repr));
1513 brig_insn_count++;
1516 /* Emit an HSA switch jump instruction that uses a jump table to
1517 jump to a destination label. */
1519 static void
1520 emit_switch_insn (hsa_insn_sbr *sbr)
1522 struct BrigInstBr repr;
1524 gcc_assert (sbr->m_opcode == BRIG_OPCODE_SBR);
1525 repr.base.base.byteCount = lendian16 (sizeof (repr));
1526 repr.base.base.kind = lendian16 (BRIG_KIND_INST_BR);
1527 repr.base.opcode = lendian16 (sbr->m_opcode);
1528 repr.width = BRIG_WIDTH_1;
1529 /* For Conditional jumps the type is always B1. */
1530 hsa_op_reg *index = as_a <hsa_op_reg *> (sbr->get_op (0));
1531 repr.base.type = lendian16 (index->m_type);
1532 repr.base.operands
1533 = lendian32 (emit_operands (sbr->get_op (0), sbr->m_label_code_list));
1534 memset (&repr.reserved, 0, sizeof (repr.reserved));
1536 brig_code.add (&repr, sizeof (repr));
1537 brig_insn_count++;
1539 /* Emit jump to default label. */
1540 hsa_bb *hbb = hsa_bb_for_bb (sbr->m_default_bb);
1541 emit_unconditional_jump (&hbb->m_label_ref);
1544 /* Emit a HSA convert instruction and all necessary directives, schedule
1545 necessary operands for writing. */
1547 static void
1548 emit_cvt_insn (hsa_insn_cvt *insn)
1550 struct BrigInstCvt repr;
1551 BrigType16_t srctype;
1553 repr.base.base.byteCount = lendian16 (sizeof (repr));
1554 repr.base.base.kind = lendian16 (BRIG_KIND_INST_CVT);
1555 repr.base.opcode = lendian16 (insn->m_opcode);
1556 repr.base.type = lendian16 (insn->m_type);
1557 repr.base.operands = lendian32 (emit_insn_operands (insn));
1559 if (is_a <hsa_op_reg *> (insn->get_op (1)))
1560 srctype = as_a <hsa_op_reg *> (insn->get_op (1))->m_type;
1561 else
1562 srctype = as_a <hsa_op_immed *> (insn->get_op (1))->m_type;
1563 repr.sourceType = lendian16 (srctype);
1564 repr.modifier = 0;
1565 /* float to smaller float requires a rounding setting (we default
1566 to 'near'. */
1567 if (hsa_type_float_p (insn->m_type)
1568 && (!hsa_type_float_p (srctype)
1569 || ((insn->m_type & BRIG_TYPE_BASE_MASK)
1570 < (srctype & BRIG_TYPE_BASE_MASK))))
1571 repr.round = BRIG_ROUND_FLOAT_NEAR_EVEN;
1572 else if (hsa_type_integer_p (insn->m_type) &&
1573 hsa_type_float_p (srctype))
1574 repr.round = BRIG_ROUND_INTEGER_ZERO;
1575 else
1576 repr.round = BRIG_ROUND_NONE;
1577 brig_code.add (&repr, sizeof (repr));
1578 brig_insn_count++;
1581 /* Emit call instruction INSN, where this instruction must be closed
1582 within a call block instruction. */
1584 static void
1585 emit_call_insn (hsa_insn_call *call)
1587 struct BrigInstBr repr;
1589 repr.base.base.byteCount = lendian16 (sizeof (repr));
1590 repr.base.base.kind = lendian16 (BRIG_KIND_INST_BR);
1591 repr.base.opcode = lendian16 (BRIG_OPCODE_CALL);
1592 repr.base.type = lendian16 (BRIG_TYPE_NONE);
1594 repr.base.operands
1595 = lendian32 (emit_operands (call->m_result_code_list, &call->m_func,
1596 call->m_args_code_list));
1598 /* Internal functions have not set m_called_function. */
1599 if (call->m_called_function)
1601 function_linkage_pair pair (call->m_called_function,
1602 call->m_func.m_brig_op_offset);
1603 function_call_linkage.safe_push (pair);
1605 else
1607 hsa_internal_fn *slot
1608 = hsa_emitted_internal_decls->find (call->m_called_internal_fn);
1609 gcc_assert (slot);
1610 gcc_assert (slot->m_offset > 0);
1611 call->m_func.m_directive_offset = slot->m_offset;
1614 repr.width = BRIG_WIDTH_ALL;
1615 memset (&repr.reserved, 0, sizeof (repr.reserved));
1617 brig_code.add (&repr, sizeof (repr));
1618 brig_insn_count++;
1621 /* Emit argument block directive. */
1623 static void
1624 emit_arg_block_insn (hsa_insn_arg_block *insn)
1626 switch (insn->m_kind)
1628 case BRIG_KIND_DIRECTIVE_ARG_BLOCK_START:
1630 struct BrigDirectiveArgBlock repr;
1631 repr.base.byteCount = lendian16 (sizeof (repr));
1632 repr.base.kind = lendian16 (insn->m_kind);
1633 brig_code.add (&repr, sizeof (repr));
1635 for (unsigned i = 0; i < insn->m_call_insn->m_input_args.length (); i++)
1637 insn->m_call_insn->m_args_code_list->m_offsets[i]
1638 = lendian32 (emit_directive_variable
1639 (insn->m_call_insn->m_input_args[i]));
1640 brig_insn_count++;
1643 if (insn->m_call_insn->m_output_arg)
1645 insn->m_call_insn->m_result_code_list->m_offsets[0]
1646 = lendian32 (emit_directive_variable
1647 (insn->m_call_insn->m_output_arg));
1648 brig_insn_count++;
1651 break;
1653 case BRIG_KIND_DIRECTIVE_ARG_BLOCK_END:
1655 struct BrigDirectiveArgBlock repr;
1656 repr.base.byteCount = lendian16 (sizeof (repr));
1657 repr.base.kind = lendian16 (insn->m_kind);
1658 brig_code.add (&repr, sizeof (repr));
1659 break;
1661 default:
1662 gcc_unreachable ();
1665 brig_insn_count++;
1668 /* Emit comment directive. */
1670 static void
1671 emit_comment_insn (hsa_insn_comment *insn)
1673 struct BrigDirectiveComment repr;
1674 memset (&repr, 0, sizeof (repr));
1676 repr.base.byteCount = lendian16 (sizeof (repr));
1677 repr.base.kind = lendian16 (insn->m_opcode);
1678 repr.name = brig_emit_string (insn->m_comment, '\0', false);
1679 brig_code.add (&repr, sizeof (repr));
1682 /* Emit queue instruction INSN. */
1684 static void
1685 emit_queue_insn (hsa_insn_queue *insn)
1687 BrigInstQueue repr;
1688 memset (&repr, 0, sizeof (repr));
1690 repr.base.base.byteCount = lendian16 (sizeof (repr));
1691 repr.base.base.kind = lendian16 (BRIG_KIND_INST_QUEUE);
1692 repr.base.opcode = lendian16 (insn->m_opcode);
1693 repr.base.type = lendian16 (insn->m_type);
1694 repr.segment = BRIG_SEGMENT_GLOBAL;
1695 repr.memoryOrder = BRIG_MEMORY_ORDER_SC_RELEASE;
1696 repr.base.operands = lendian32 (emit_insn_operands (insn));
1697 brig_data.round_size_up (4);
1698 brig_code.add (&repr, sizeof (repr));
1700 brig_insn_count++;
1703 /* Emit source type instruction INSN. */
1705 static void
1706 emit_srctype_insn (hsa_insn_srctype *insn)
1708 /* We assume that BrigInstMod has a BrigInstBasic prefix. */
1709 struct BrigInstSourceType repr;
1710 unsigned operand_count = insn->operand_count ();
1711 gcc_checking_assert (operand_count >= 2);
1713 memset (&repr, 0, sizeof (repr));
1714 repr.sourceType = lendian16 (insn->m_source_type);
1715 repr.base.base.byteCount = lendian16 (sizeof (repr));
1716 repr.base.base.kind = lendian16 (BRIG_KIND_INST_SOURCE_TYPE);
1717 repr.base.opcode = lendian16 (insn->m_opcode);
1718 repr.base.type = lendian16 (insn->m_type);
1720 repr.base.operands = lendian32 (emit_insn_operands (insn));
1721 brig_code.add (&repr, sizeof (struct BrigInstSourceType));
1722 brig_insn_count++;
1725 /* Emit packed instruction INSN. */
1727 static void
1728 emit_packed_insn (hsa_insn_packed *insn)
1730 /* We assume that BrigInstMod has a BrigInstBasic prefix. */
1731 struct BrigInstSourceType repr;
1732 unsigned operand_count = insn->operand_count ();
1733 gcc_checking_assert (operand_count >= 2);
1735 memset (&repr, 0, sizeof (repr));
1736 repr.sourceType = lendian16 (insn->m_source_type);
1737 repr.base.base.byteCount = lendian16 (sizeof (repr));
1738 repr.base.base.kind = lendian16 (BRIG_KIND_INST_SOURCE_TYPE);
1739 repr.base.opcode = lendian16 (insn->m_opcode);
1740 repr.base.type = lendian16 (insn->m_type);
1742 if (insn->m_opcode == BRIG_OPCODE_COMBINE)
1744 /* Create operand list for packed type. */
1745 for (unsigned i = 1; i < operand_count; i++)
1747 gcc_checking_assert (insn->get_op (i));
1748 insn->m_operand_list->m_offsets[i - 1]
1749 = lendian32 (enqueue_op (insn->get_op (i)));
1752 repr.base.operands = lendian32 (emit_operands (insn->get_op (0),
1753 insn->m_operand_list));
1755 else if (insn->m_opcode == BRIG_OPCODE_EXPAND)
1757 /* Create operand list for packed type. */
1758 for (unsigned i = 0; i < operand_count - 1; i++)
1760 gcc_checking_assert (insn->get_op (i));
1761 insn->m_operand_list->m_offsets[i]
1762 = lendian32 (enqueue_op (insn->get_op (i)));
1765 unsigned ops = emit_operands (insn->m_operand_list,
1766 insn->get_op (insn->operand_count () - 1));
1767 repr.base.operands = lendian32 (ops);
1771 brig_code.add (&repr, sizeof (struct BrigInstSourceType));
1772 brig_insn_count++;
1775 /* Emit a basic HSA instruction and all necessary directives, schedule
1776 necessary operands for writing. */
1778 static void
1779 emit_basic_insn (hsa_insn_basic *insn)
1781 /* We assume that BrigInstMod has a BrigInstBasic prefix. */
1782 struct BrigInstMod repr;
1783 BrigType16_t type;
1785 memset (&repr, 0, sizeof (repr));
1786 repr.base.base.byteCount = lendian16 (sizeof (BrigInstBasic));
1787 repr.base.base.kind = lendian16 (BRIG_KIND_INST_BASIC);
1788 repr.base.opcode = lendian16 (insn->m_opcode);
1789 switch (insn->m_opcode)
1791 /* And the bit-logical operations need bit types and whine about
1792 arithmetic types :-/ */
1793 case BRIG_OPCODE_AND:
1794 case BRIG_OPCODE_OR:
1795 case BRIG_OPCODE_XOR:
1796 case BRIG_OPCODE_NOT:
1797 type = regtype_for_type (insn->m_type);
1798 break;
1799 default:
1800 type = insn->m_type;
1801 break;
1803 repr.base.type = lendian16 (type);
1804 repr.base.operands = lendian32 (emit_insn_operands (insn));
1806 if ((type & BRIG_TYPE_PACK_MASK) != BRIG_TYPE_PACK_NONE)
1808 if (hsa_type_float_p (type)
1809 && !hsa_opcode_floating_bit_insn_p (insn->m_opcode))
1810 repr.round = BRIG_ROUND_FLOAT_NEAR_EVEN;
1811 else
1812 repr.round = 0;
1813 /* We assume that destination and sources agree in packing layout. */
1814 if (insn->num_used_ops () >= 2)
1815 repr.pack = BRIG_PACK_PP;
1816 else
1817 repr.pack = BRIG_PACK_P;
1818 repr.reserved = 0;
1819 repr.base.base.byteCount = lendian16 (sizeof (BrigInstMod));
1820 repr.base.base.kind = lendian16 (BRIG_KIND_INST_MOD);
1821 brig_code.add (&repr, sizeof (struct BrigInstMod));
1823 else
1824 brig_code.add (&repr, sizeof (struct BrigInstBasic));
1825 brig_insn_count++;
1828 /* Emit an HSA instruction and all necessary directives, schedule necessary
1829 operands for writing. */
1831 static void
1832 emit_insn (hsa_insn_basic *insn)
1834 gcc_assert (!is_a <hsa_insn_phi *> (insn));
1836 insn->m_brig_offset = brig_code.total_size;
1838 if (hsa_insn_signal *signal = dyn_cast <hsa_insn_signal *> (insn))
1839 emit_signal_insn (signal);
1840 else if (hsa_insn_atomic *atom = dyn_cast <hsa_insn_atomic *> (insn))
1841 emit_atomic_insn (atom);
1842 else if (hsa_insn_mem *mem = dyn_cast <hsa_insn_mem *> (insn))
1843 emit_memory_insn (mem);
1844 else if (insn->m_opcode == BRIG_OPCODE_LDA)
1845 emit_addr_insn (insn);
1846 else if (hsa_insn_seg *seg = dyn_cast <hsa_insn_seg *> (insn))
1847 emit_segment_insn (seg);
1848 else if (hsa_insn_cmp *cmp = dyn_cast <hsa_insn_cmp *> (insn))
1849 emit_cmp_insn (cmp);
1850 else if (hsa_insn_br *br = dyn_cast <hsa_insn_br *> (insn))
1851 emit_branch_insn (br);
1852 else if (hsa_insn_sbr *sbr = dyn_cast <hsa_insn_sbr *> (insn))
1854 if (switch_instructions == NULL)
1855 switch_instructions = new vec <hsa_insn_sbr *> ();
1857 switch_instructions->safe_push (sbr);
1858 emit_switch_insn (sbr);
1860 else if (hsa_insn_arg_block *block = dyn_cast <hsa_insn_arg_block *> (insn))
1861 emit_arg_block_insn (block);
1862 else if (hsa_insn_call *call = dyn_cast <hsa_insn_call *> (insn))
1863 emit_call_insn (call);
1864 else if (hsa_insn_comment *comment = dyn_cast <hsa_insn_comment *> (insn))
1865 emit_comment_insn (comment);
1866 else if (hsa_insn_queue *queue = dyn_cast <hsa_insn_queue *> (insn))
1867 emit_queue_insn (queue);
1868 else if (hsa_insn_srctype *srctype = dyn_cast <hsa_insn_srctype *> (insn))
1869 emit_srctype_insn (srctype);
1870 else if (hsa_insn_packed *packed = dyn_cast <hsa_insn_packed *> (insn))
1871 emit_packed_insn (packed);
1872 else if (hsa_insn_cvt *cvt = dyn_cast <hsa_insn_cvt *> (insn))
1873 emit_cvt_insn (cvt);
1874 else if (hsa_insn_alloca *alloca = dyn_cast <hsa_insn_alloca *> (insn))
1875 emit_alloca_insn (alloca);
1876 else
1877 emit_basic_insn (insn);
1880 /* We have just finished emitting BB and are about to emit NEXT_BB if non-NULL,
1881 or we are about to finish emitting code, if it is NULL. If the fall through
1882 edge from BB does not lead to NEXT_BB, emit an unconditional jump. */
1884 static void
1885 perhaps_emit_branch (basic_block bb, basic_block next_bb)
1887 basic_block t_bb = NULL, ff = NULL;
1889 edge_iterator ei;
1890 edge e;
1892 /* If the last instruction of BB is a switch, ignore emission of all
1893 edges. */
1894 if (hsa_bb_for_bb (bb)->m_last_insn
1895 && is_a <hsa_insn_sbr *> (hsa_bb_for_bb (bb)->m_last_insn))
1896 return;
1898 FOR_EACH_EDGE (e, ei, bb->succs)
1899 if (e->flags & EDGE_TRUE_VALUE)
1901 gcc_assert (!t_bb);
1902 t_bb = e->dest;
1904 else
1906 gcc_assert (!ff);
1907 ff = e->dest;
1910 if (!ff || ff == next_bb || ff == EXIT_BLOCK_PTR_FOR_FN (cfun))
1911 return;
1913 emit_unconditional_jump (&hsa_bb_for_bb (ff)->m_label_ref);
1916 /* Emit the a function with name NAME to the various brig sections. */
1918 void
1919 hsa_brig_emit_function (void)
1921 basic_block bb, prev_bb;
1922 hsa_insn_basic *insn;
1923 BrigDirectiveExecutable *ptr_to_fndir;
1925 brig_init ();
1927 brig_insn_count = 0;
1928 memset (&op_queue, 0, sizeof (op_queue));
1929 op_queue.projected_size = brig_operand.total_size;
1931 if (!function_offsets)
1932 function_offsets = new hash_map<tree, BrigCodeOffset32_t> ();
1934 if (!emitted_declarations)
1935 emitted_declarations = new hash_map <tree, BrigDirectiveExecutable *> ();
1937 for (unsigned i = 0; i < hsa_cfun->m_called_functions.length (); i++)
1939 tree called = hsa_cfun->m_called_functions[i];
1941 /* If the function has no definition, emit a declaration. */
1942 if (!emitted_declarations->get (called))
1944 BrigDirectiveExecutable *e = emit_function_declaration (called);
1945 emitted_declarations->put (called, e);
1949 for (unsigned i = 0; i < hsa_cfun->m_called_internal_fns.length (); i++)
1951 hsa_internal_fn *called = hsa_cfun->m_called_internal_fns[i];
1952 emit_internal_fn_decl (called);
1955 ptr_to_fndir = emit_function_directives (hsa_cfun, false);
1956 for (insn = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun))->m_first_insn;
1957 insn;
1958 insn = insn->m_next)
1959 emit_insn (insn);
1960 prev_bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
1961 FOR_EACH_BB_FN (bb, cfun)
1963 perhaps_emit_branch (prev_bb, bb);
1964 emit_bb_label_directive (hsa_bb_for_bb (bb));
1965 for (insn = hsa_bb_for_bb (bb)->m_first_insn; insn; insn = insn->m_next)
1966 emit_insn (insn);
1967 prev_bb = bb;
1969 perhaps_emit_branch (prev_bb, NULL);
1970 ptr_to_fndir->nextModuleEntry = brig_code.total_size;
1972 /* Fill up label references for all sbr instructions. */
1973 if (switch_instructions)
1975 for (unsigned i = 0; i < switch_instructions->length (); i++)
1977 hsa_insn_sbr *sbr = (*switch_instructions)[i];
1978 for (unsigned j = 0; j < sbr->m_jump_table.length (); j++)
1980 hsa_bb *hbb = hsa_bb_for_bb (sbr->m_jump_table[j]);
1981 sbr->m_label_code_list->m_offsets[j]
1982 = hbb->m_label_ref.m_directive_offset;
1986 switch_instructions->release ();
1987 delete switch_instructions;
1988 switch_instructions = NULL;
1991 if (dump_file)
1993 fprintf (dump_file, "------- After BRIG emission: -------\n");
1994 dump_hsa_cfun (dump_file);
1997 emit_queued_operands ();
2000 /* Emit all OMP symbols related to OMP. */
2002 void
2003 hsa_brig_emit_omp_symbols (void)
2005 brig_init ();
2006 emit_directive_variable (hsa_num_threads);
2009 static GTY(()) tree hsa_cdtor_statements[2];
2011 /* Create and return __hsa_global_variables symbol that contains
2012 all informations consumed by libgomp to link global variables
2013 with their string names used by an HSA kernel. */
2015 static tree
2016 hsa_output_global_variables ()
2018 unsigned l = hsa_global_variable_symbols->elements ();
2020 tree variable_info_type = make_node (RECORD_TYPE);
2021 tree id_f1 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2022 get_identifier ("name"), ptr_type_node);
2023 DECL_CHAIN (id_f1) = NULL_TREE;
2024 tree id_f2 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2025 get_identifier ("omp_data_size"),
2026 ptr_type_node);
2027 DECL_CHAIN (id_f2) = id_f1;
2028 finish_builtin_struct (variable_info_type, "__hsa_variable_info", id_f2,
2029 NULL_TREE);
2031 tree int_num_of_global_vars;
2032 int_num_of_global_vars = build_int_cst (uint32_type_node, l);
2033 tree global_vars_num_index_type = build_index_type (int_num_of_global_vars);
2034 tree global_vars_array_type = build_array_type (variable_info_type,
2035 global_vars_num_index_type);
2036 TYPE_ARTIFICIAL (global_vars_array_type) = 1;
2038 vec<constructor_elt, va_gc> *global_vars_vec = NULL;
2040 for (hash_table <hsa_noop_symbol_hasher>::iterator it
2041 = hsa_global_variable_symbols->begin ();
2042 it != hsa_global_variable_symbols->end (); ++it)
2044 unsigned len = strlen ((*it)->m_name);
2045 char *copy = XNEWVEC (char, len + 2);
2046 copy[0] = '&';
2047 memcpy (copy + 1, (*it)->m_name, len);
2048 copy[len + 1] = '\0';
2049 len++;
2050 hsa_sanitize_name (copy);
2052 tree var_name = build_string (len, copy);
2053 TREE_TYPE (var_name)
2054 = build_array_type (char_type_node, build_index_type (size_int (len)));
2055 free (copy);
2057 vec<constructor_elt, va_gc> *variable_info_vec = NULL;
2058 CONSTRUCTOR_APPEND_ELT (variable_info_vec, NULL_TREE,
2059 build1 (ADDR_EXPR,
2060 build_pointer_type (TREE_TYPE (var_name)),
2061 var_name));
2062 CONSTRUCTOR_APPEND_ELT (variable_info_vec, NULL_TREE,
2063 build_fold_addr_expr ((*it)->m_decl));
2065 tree variable_info_ctor = build_constructor (variable_info_type,
2066 variable_info_vec);
2068 CONSTRUCTOR_APPEND_ELT (global_vars_vec, NULL_TREE,
2069 variable_info_ctor);
2072 tree global_vars_ctor = build_constructor (global_vars_array_type,
2073 global_vars_vec);
2075 char tmp_name[64];
2076 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "__hsa_global_variables", 1);
2077 tree global_vars_table = build_decl (UNKNOWN_LOCATION, VAR_DECL,
2078 get_identifier (tmp_name),
2079 global_vars_array_type);
2080 TREE_STATIC (global_vars_table) = 1;
2081 TREE_READONLY (global_vars_table) = 1;
2082 TREE_PUBLIC (global_vars_table) = 0;
2083 DECL_ARTIFICIAL (global_vars_table) = 1;
2084 DECL_IGNORED_P (global_vars_table) = 1;
2085 DECL_EXTERNAL (global_vars_table) = 0;
2086 TREE_CONSTANT (global_vars_table) = 1;
2087 DECL_INITIAL (global_vars_table) = global_vars_ctor;
2088 varpool_node::finalize_decl (global_vars_table);
2090 return global_vars_table;
2093 /* Create __hsa_host_functions and __hsa_kernels that contain
2094 all informations consumed by libgomp to register all kernels
2095 in the BRIG binary. */
2097 static void
2098 hsa_output_kernels (tree *host_func_table, tree *kernels)
2100 unsigned map_count = hsa_get_number_decl_kernel_mappings ();
2102 tree int_num_of_kernels;
2103 int_num_of_kernels = build_int_cst (uint32_type_node, map_count);
2104 tree kernel_num_index_type = build_index_type (int_num_of_kernels);
2105 tree host_functions_array_type = build_array_type (ptr_type_node,
2106 kernel_num_index_type);
2107 TYPE_ARTIFICIAL (host_functions_array_type) = 1;
2109 vec<constructor_elt, va_gc> *host_functions_vec = NULL;
2110 for (unsigned i = 0; i < map_count; ++i)
2112 tree decl = hsa_get_decl_kernel_mapping_decl (i);
2113 tree host_fn = build_fold_addr_expr (hsa_get_host_function (decl));
2114 CONSTRUCTOR_APPEND_ELT (host_functions_vec, NULL_TREE, host_fn);
2116 tree host_functions_ctor = build_constructor (host_functions_array_type,
2117 host_functions_vec);
2118 char tmp_name[64];
2119 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "__hsa_host_functions", 1);
2120 tree hsa_host_func_table = build_decl (UNKNOWN_LOCATION, VAR_DECL,
2121 get_identifier (tmp_name),
2122 host_functions_array_type);
2123 TREE_STATIC (hsa_host_func_table) = 1;
2124 TREE_READONLY (hsa_host_func_table) = 1;
2125 TREE_PUBLIC (hsa_host_func_table) = 0;
2126 DECL_ARTIFICIAL (hsa_host_func_table) = 1;
2127 DECL_IGNORED_P (hsa_host_func_table) = 1;
2128 DECL_EXTERNAL (hsa_host_func_table) = 0;
2129 TREE_CONSTANT (hsa_host_func_table) = 1;
2130 DECL_INITIAL (hsa_host_func_table) = host_functions_ctor;
2131 varpool_node::finalize_decl (hsa_host_func_table);
2132 *host_func_table = hsa_host_func_table;
2134 /* Following code emits list of kernel_info structures. */
2136 tree kernel_info_type = make_node (RECORD_TYPE);
2137 tree id_f1 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2138 get_identifier ("name"), ptr_type_node);
2139 DECL_CHAIN (id_f1) = NULL_TREE;
2140 tree id_f2 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2141 get_identifier ("omp_data_size"),
2142 unsigned_type_node);
2143 DECL_CHAIN (id_f2) = id_f1;
2144 tree id_f3 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2145 get_identifier ("gridified_kernel_p"),
2146 boolean_type_node);
2147 DECL_CHAIN (id_f3) = id_f2;
2148 tree id_f4 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2149 get_identifier ("kernel_dependencies_count"),
2150 unsigned_type_node);
2151 DECL_CHAIN (id_f4) = id_f3;
2152 tree id_f5 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2153 get_identifier ("kernel_dependencies"),
2154 build_pointer_type (build_pointer_type
2155 (char_type_node)));
2156 DECL_CHAIN (id_f5) = id_f4;
2157 finish_builtin_struct (kernel_info_type, "__hsa_kernel_info", id_f5,
2158 NULL_TREE);
2160 int_num_of_kernels = build_int_cstu (uint32_type_node, map_count);
2161 tree kernel_info_vector_type
2162 = build_array_type (kernel_info_type,
2163 build_index_type (int_num_of_kernels));
2164 TYPE_ARTIFICIAL (kernel_info_vector_type) = 1;
2166 vec<constructor_elt, va_gc> *kernel_info_vector_vec = NULL;
2167 tree kernel_dependencies_vector_type = NULL;
2169 for (unsigned i = 0; i < map_count; ++i)
2171 tree kernel = hsa_get_decl_kernel_mapping_decl (i);
2172 char *name = hsa_get_decl_kernel_mapping_name (i);
2173 unsigned len = strlen (name);
2174 char *copy = XNEWVEC (char, len + 2);
2175 copy[0] = '&';
2176 memcpy (copy + 1, name, len);
2177 copy[len + 1] = '\0';
2178 len++;
2180 tree kern_name = build_string (len, copy);
2181 TREE_TYPE (kern_name)
2182 = build_array_type (char_type_node, build_index_type (size_int (len)));
2183 free (copy);
2185 unsigned omp_size = hsa_get_decl_kernel_mapping_omp_size (i);
2186 tree omp_data_size = build_int_cstu (unsigned_type_node, omp_size);
2187 bool gridified_kernel_p = hsa_get_decl_kernel_mapping_gridified (i);
2188 tree gridified_kernel_p_tree = build_int_cstu (boolean_type_node,
2189 gridified_kernel_p);
2190 unsigned count = 0;
2192 kernel_dependencies_vector_type
2193 = build_array_type (build_pointer_type (char_type_node),
2194 build_index_type (size_int (0)));
2196 vec<constructor_elt, va_gc> *kernel_dependencies_vec = NULL;
2197 if (hsa_decl_kernel_dependencies)
2199 vec<const char *> **slot;
2200 slot = hsa_decl_kernel_dependencies->get (kernel);
2201 if (slot)
2203 vec <const char *> *dependencies = *slot;
2204 count = dependencies->length ();
2206 kernel_dependencies_vector_type
2207 = build_array_type (build_pointer_type (char_type_node),
2208 build_index_type (size_int (count)));
2209 TYPE_ARTIFICIAL (kernel_dependencies_vector_type) = 1;
2211 for (unsigned j = 0; j < count; j++)
2213 const char *d = (*dependencies)[j];
2214 len = strlen (d);
2215 tree dependency_name = build_string (len, d);
2216 TREE_TYPE (dependency_name)
2217 = build_array_type (char_type_node,
2218 build_index_type (size_int (len)));
2220 CONSTRUCTOR_APPEND_ELT
2221 (kernel_dependencies_vec, NULL_TREE,
2222 build1 (ADDR_EXPR,
2223 build_pointer_type (TREE_TYPE (dependency_name)),
2224 dependency_name));
2229 tree dependencies_count = build_int_cstu (unsigned_type_node, count);
2231 vec<constructor_elt, va_gc> *kernel_info_vec = NULL;
2232 CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE,
2233 build1 (ADDR_EXPR,
2234 build_pointer_type (TREE_TYPE
2235 (kern_name)),
2236 kern_name));
2237 CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE, omp_data_size);
2238 CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE,
2239 gridified_kernel_p_tree);
2240 CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE, dependencies_count);
2242 if (count > 0)
2244 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "__hsa_dependencies_list", i);
2245 tree dependencies_list = build_decl (UNKNOWN_LOCATION, VAR_DECL,
2246 get_identifier (tmp_name),
2247 kernel_dependencies_vector_type);
2249 TREE_STATIC (dependencies_list) = 1;
2250 TREE_READONLY (dependencies_list) = 1;
2251 TREE_PUBLIC (dependencies_list) = 0;
2252 DECL_ARTIFICIAL (dependencies_list) = 1;
2253 DECL_IGNORED_P (dependencies_list) = 1;
2254 DECL_EXTERNAL (dependencies_list) = 0;
2255 TREE_CONSTANT (dependencies_list) = 1;
2256 DECL_INITIAL (dependencies_list)
2257 = build_constructor (kernel_dependencies_vector_type,
2258 kernel_dependencies_vec);
2259 varpool_node::finalize_decl (dependencies_list);
2261 CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE,
2262 build1 (ADDR_EXPR,
2263 build_pointer_type
2264 (TREE_TYPE (dependencies_list)),
2265 dependencies_list));
2267 else
2268 CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE, null_pointer_node);
2270 tree kernel_info_ctor = build_constructor (kernel_info_type,
2271 kernel_info_vec);
2273 CONSTRUCTOR_APPEND_ELT (kernel_info_vector_vec, NULL_TREE,
2274 kernel_info_ctor);
2277 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "__hsa_kernels", 1);
2278 tree hsa_kernels = build_decl (UNKNOWN_LOCATION, VAR_DECL,
2279 get_identifier (tmp_name),
2280 kernel_info_vector_type);
2282 TREE_STATIC (hsa_kernels) = 1;
2283 TREE_READONLY (hsa_kernels) = 1;
2284 TREE_PUBLIC (hsa_kernels) = 0;
2285 DECL_ARTIFICIAL (hsa_kernels) = 1;
2286 DECL_IGNORED_P (hsa_kernels) = 1;
2287 DECL_EXTERNAL (hsa_kernels) = 0;
2288 TREE_CONSTANT (hsa_kernels) = 1;
2289 DECL_INITIAL (hsa_kernels) = build_constructor (kernel_info_vector_type,
2290 kernel_info_vector_vec);
2291 varpool_node::finalize_decl (hsa_kernels);
2292 *kernels = hsa_kernels;
2295 /* Create a static constructor that will register out brig stuff with
2296 libgomp. */
2298 static void
2299 hsa_output_libgomp_mapping (tree brig_decl)
2301 unsigned kernel_count = hsa_get_number_decl_kernel_mappings ();
2302 unsigned global_variable_count = hsa_global_variable_symbols->elements ();
2304 tree kernels;
2305 tree host_func_table;
2307 hsa_output_kernels (&host_func_table, &kernels);
2308 tree global_vars = hsa_output_global_variables ();
2310 tree hsa_image_desc_type = make_node (RECORD_TYPE);
2311 tree id_f1 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2312 get_identifier ("brig_module"), ptr_type_node);
2313 DECL_CHAIN (id_f1) = NULL_TREE;
2314 tree id_f2 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2315 get_identifier ("kernel_count"),
2316 unsigned_type_node);
2318 DECL_CHAIN (id_f2) = id_f1;
2319 tree id_f3 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2320 get_identifier ("hsa_kernel_infos"),
2321 ptr_type_node);
2322 DECL_CHAIN (id_f3) = id_f2;
2323 tree id_f4 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2324 get_identifier ("global_variable_count"),
2325 unsigned_type_node);
2326 DECL_CHAIN (id_f4) = id_f3;
2327 tree id_f5 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2328 get_identifier ("hsa_global_variable_infos"),
2329 ptr_type_node);
2330 DECL_CHAIN (id_f5) = id_f4;
2331 finish_builtin_struct (hsa_image_desc_type, "__hsa_image_desc", id_f5,
2332 NULL_TREE);
2333 TYPE_ARTIFICIAL (hsa_image_desc_type) = 1;
2335 vec<constructor_elt, va_gc> *img_desc_vec = NULL;
2336 CONSTRUCTOR_APPEND_ELT (img_desc_vec, NULL_TREE,
2337 build_fold_addr_expr (brig_decl));
2338 CONSTRUCTOR_APPEND_ELT (img_desc_vec, NULL_TREE,
2339 build_int_cstu (unsigned_type_node, kernel_count));
2340 CONSTRUCTOR_APPEND_ELT (img_desc_vec, NULL_TREE,
2341 build1 (ADDR_EXPR,
2342 build_pointer_type (TREE_TYPE (kernels)),
2343 kernels));
2344 CONSTRUCTOR_APPEND_ELT (img_desc_vec, NULL_TREE,
2345 build_int_cstu (unsigned_type_node,
2346 global_variable_count));
2347 CONSTRUCTOR_APPEND_ELT (img_desc_vec, NULL_TREE,
2348 build1 (ADDR_EXPR,
2349 build_pointer_type (TREE_TYPE (global_vars)),
2350 global_vars));
2352 tree img_desc_ctor = build_constructor (hsa_image_desc_type, img_desc_vec);
2354 char tmp_name[64];
2355 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "__hsa_img_descriptor", 1);
2356 tree hsa_img_descriptor = build_decl (UNKNOWN_LOCATION, VAR_DECL,
2357 get_identifier (tmp_name),
2358 hsa_image_desc_type);
2359 TREE_STATIC (hsa_img_descriptor) = 1;
2360 TREE_READONLY (hsa_img_descriptor) = 1;
2361 TREE_PUBLIC (hsa_img_descriptor) = 0;
2362 DECL_ARTIFICIAL (hsa_img_descriptor) = 1;
2363 DECL_IGNORED_P (hsa_img_descriptor) = 1;
2364 DECL_EXTERNAL (hsa_img_descriptor) = 0;
2365 TREE_CONSTANT (hsa_img_descriptor) = 1;
2366 DECL_INITIAL (hsa_img_descriptor) = img_desc_ctor;
2367 varpool_node::finalize_decl (hsa_img_descriptor);
2369 /* Construct the "host_table" libgomp expects. */
2370 tree index_type = build_index_type (build_int_cst (integer_type_node, 4));
2371 tree libgomp_host_table_type = build_array_type (ptr_type_node, index_type);
2372 TYPE_ARTIFICIAL (libgomp_host_table_type) = 1;
2373 vec<constructor_elt, va_gc> *libgomp_host_table_vec = NULL;
2374 tree host_func_table_addr = build_fold_addr_expr (host_func_table);
2375 CONSTRUCTOR_APPEND_ELT (libgomp_host_table_vec, NULL_TREE,
2376 host_func_table_addr);
2377 offset_int func_table_size
2378 = wi::to_offset (TYPE_SIZE_UNIT (ptr_type_node)) * kernel_count;
2379 CONSTRUCTOR_APPEND_ELT (libgomp_host_table_vec, NULL_TREE,
2380 fold_build2 (POINTER_PLUS_EXPR,
2381 TREE_TYPE (host_func_table_addr),
2382 host_func_table_addr,
2383 build_int_cst (size_type_node,
2384 func_table_size.to_uhwi
2385 ())));
2386 CONSTRUCTOR_APPEND_ELT (libgomp_host_table_vec, NULL_TREE, null_pointer_node);
2387 CONSTRUCTOR_APPEND_ELT (libgomp_host_table_vec, NULL_TREE, null_pointer_node);
2388 tree libgomp_host_table_ctor = build_constructor (libgomp_host_table_type,
2389 libgomp_host_table_vec);
2390 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "__hsa_libgomp_host_table", 1);
2391 tree hsa_libgomp_host_table = build_decl (UNKNOWN_LOCATION, VAR_DECL,
2392 get_identifier (tmp_name),
2393 libgomp_host_table_type);
2395 TREE_STATIC (hsa_libgomp_host_table) = 1;
2396 TREE_READONLY (hsa_libgomp_host_table) = 1;
2397 TREE_PUBLIC (hsa_libgomp_host_table) = 0;
2398 DECL_ARTIFICIAL (hsa_libgomp_host_table) = 1;
2399 DECL_IGNORED_P (hsa_libgomp_host_table) = 1;
2400 DECL_EXTERNAL (hsa_libgomp_host_table) = 0;
2401 TREE_CONSTANT (hsa_libgomp_host_table) = 1;
2402 DECL_INITIAL (hsa_libgomp_host_table) = libgomp_host_table_ctor;
2403 varpool_node::finalize_decl (hsa_libgomp_host_table);
2405 /* Generate an initializer with a call to the registration routine. */
2407 tree offload_register
2408 = builtin_decl_explicit (BUILT_IN_GOMP_OFFLOAD_REGISTER);
2409 gcc_checking_assert (offload_register);
2411 append_to_statement_list
2412 (build_call_expr (offload_register, 4,
2413 build_int_cstu (unsigned_type_node,
2414 GOMP_VERSION_PACK (GOMP_VERSION,
2415 GOMP_VERSION_HSA)),
2416 build_fold_addr_expr (hsa_libgomp_host_table),
2417 build_int_cst (integer_type_node, GOMP_DEVICE_HSA),
2418 build_fold_addr_expr (hsa_img_descriptor)),
2419 &hsa_cdtor_statements[0]);
2421 cgraph_build_static_cdtor ('I', hsa_cdtor_statements[0],
2422 DEFAULT_INIT_PRIORITY);
2424 tree offload_unregister
2425 = builtin_decl_explicit (BUILT_IN_GOMP_OFFLOAD_UNREGISTER);
2426 gcc_checking_assert (offload_unregister);
2428 append_to_statement_list
2429 (build_call_expr (offload_unregister, 4,
2430 build_int_cstu (unsigned_type_node,
2431 GOMP_VERSION_PACK (GOMP_VERSION,
2432 GOMP_VERSION_HSA)),
2433 build_fold_addr_expr (hsa_libgomp_host_table),
2434 build_int_cst (integer_type_node, GOMP_DEVICE_HSA),
2435 build_fold_addr_expr (hsa_img_descriptor)),
2436 &hsa_cdtor_statements[1]);
2437 cgraph_build_static_cdtor ('D', hsa_cdtor_statements[1],
2438 DEFAULT_INIT_PRIORITY);
2441 /* Emit the brig module we have compiled to a section in the final assembly and
2442 also create a compile unit static constructor that will register the brig
2443 module with libgomp. */
2445 void
2446 hsa_output_brig (void)
2448 section *saved_section;
2450 if (!brig_initialized)
2451 return;
2453 for (unsigned i = 0; i < function_call_linkage.length (); i++)
2455 function_linkage_pair p = function_call_linkage[i];
2457 BrigCodeOffset32_t *func_offset = function_offsets->get (p.function_decl);
2458 gcc_assert (*func_offset);
2459 BrigOperandCodeRef *code_ref
2460 = (BrigOperandCodeRef *) (brig_operand.get_ptr_by_offset (p.offset));
2461 gcc_assert (code_ref->base.kind == BRIG_KIND_OPERAND_CODE_REF);
2462 code_ref->ref = lendian32 (*func_offset);
2465 /* Iterate all function declarations and if we meet a function that should
2466 have module linkage and we are unable to emit HSAIL for the function,
2467 then change the linkage to program linkage. Doing so, we will emit
2468 a valid BRIG image. */
2469 if (hsa_failed_functions != NULL && emitted_declarations != NULL)
2470 for (hash_map <tree, BrigDirectiveExecutable *>::iterator it
2471 = emitted_declarations->begin ();
2472 it != emitted_declarations->end ();
2473 ++it)
2475 if (hsa_failed_functions->contains ((*it).first))
2476 (*it).second->linkage = BRIG_LINKAGE_PROGRAM;
2479 saved_section = in_section;
2481 switch_to_section (get_section (BRIG_ELF_SECTION_NAME, SECTION_NOTYPE, NULL));
2482 char tmp_name[64];
2483 ASM_GENERATE_INTERNAL_LABEL (tmp_name, BRIG_LABEL_STRING, 1);
2484 ASM_OUTPUT_LABEL (asm_out_file, tmp_name);
2485 tree brig_id = get_identifier (tmp_name);
2486 tree brig_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, brig_id,
2487 char_type_node);
2488 SET_DECL_ASSEMBLER_NAME (brig_decl, brig_id);
2489 TREE_ADDRESSABLE (brig_decl) = 1;
2490 TREE_READONLY (brig_decl) = 1;
2491 DECL_ARTIFICIAL (brig_decl) = 1;
2492 DECL_IGNORED_P (brig_decl) = 1;
2493 TREE_STATIC (brig_decl) = 1;
2494 TREE_PUBLIC (brig_decl) = 0;
2495 TREE_USED (brig_decl) = 1;
2496 DECL_INITIAL (brig_decl) = brig_decl;
2497 TREE_ASM_WRITTEN (brig_decl) = 1;
2499 BrigModuleHeader module_header;
2500 memcpy (&module_header.identification, "HSA BRIG",
2501 sizeof (module_header.identification));
2502 module_header.brigMajor = lendian32 (BRIG_VERSION_BRIG_MAJOR);
2503 module_header.brigMinor = lendian32 (BRIG_VERSION_BRIG_MINOR);
2504 uint64_t section_index[3];
2506 int data_padding, code_padding, operand_padding;
2507 data_padding = HSA_SECTION_ALIGNMENT
2508 - brig_data.total_size % HSA_SECTION_ALIGNMENT;
2509 code_padding = HSA_SECTION_ALIGNMENT
2510 - brig_code.total_size % HSA_SECTION_ALIGNMENT;
2511 operand_padding = HSA_SECTION_ALIGNMENT
2512 - brig_operand.total_size % HSA_SECTION_ALIGNMENT;
2514 uint64_t module_size = sizeof (module_header)
2515 + sizeof (section_index)
2516 + brig_data.total_size
2517 + data_padding
2518 + brig_code.total_size
2519 + code_padding
2520 + brig_operand.total_size
2521 + operand_padding;
2522 gcc_assert ((module_size % 16) == 0);
2523 module_header.byteCount = lendian64 (module_size);
2524 memset (&module_header.hash, 0, sizeof (module_header.hash));
2525 module_header.reserved = 0;
2526 module_header.sectionCount = lendian32 (3);
2527 module_header.sectionIndex = lendian64 (sizeof (module_header));
2528 assemble_string ((const char *) &module_header, sizeof (module_header));
2529 uint64_t off = sizeof (module_header) + sizeof (section_index);
2530 section_index[0] = lendian64 (off);
2531 off += brig_data.total_size + data_padding;
2532 section_index[1] = lendian64 (off);
2533 off += brig_code.total_size + code_padding;
2534 section_index[2] = lendian64 (off);
2535 assemble_string ((const char *) &section_index, sizeof (section_index));
2537 char padding[HSA_SECTION_ALIGNMENT];
2538 memset (padding, 0, sizeof (padding));
2540 brig_data.output ();
2541 assemble_string (padding, data_padding);
2542 brig_code.output ();
2543 assemble_string (padding, code_padding);
2544 brig_operand.output ();
2545 assemble_string (padding, operand_padding);
2547 if (saved_section)
2548 switch_to_section (saved_section);
2550 hsa_output_libgomp_mapping (brig_decl);
2552 hsa_free_decl_kernel_mapping ();
2553 brig_release_data ();
2554 hsa_deinit_compilation_unit_data ();
2556 delete emitted_declarations;
2557 emitted_declarations = NULL;
2558 delete function_offsets;
2559 function_offsets = NULL;