1 /* Producing binary form of HSA BRIG from our internal representation.
2 Copyright (C) 2013 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
22 #include "coretypes.h"
26 #include "stor-layout.h"
30 #include "basic-block.h"
32 #include "gimple-pretty-print.h"
33 #include "diagnostic-core.h"
35 #define BRIG_SECTION_DATA_NAME "hsa_data"
36 #define BRIG_SECTION_CODE_NAME "hsa_code"
37 #define BRIG_SECTION_OPERAND_NAME "hsa_operand"
39 #define BRIG_CHUNK_MAX_SIZE (64 * 1024)
41 /* FIXME: The code below uses endian.h routines to convert numbers to
42 little-endian. I suspect this only works on glibc platforms, so we might
43 need an alternative solutin later. */
45 /* Chunks of BRIG binary data. */
47 struct hsa_brig_data_chunk
49 /* Size of the data already stored into a chunk. */
52 /* Pointer to the data. */
56 /* Structure represeting a BRIC section, holding and writing its data. */
58 class hsa_brig_section
61 /* Section name that will be output to the BRIG. */
62 const char *section_name
;
63 /* Size in bytes of all data stored in the section. */
64 unsigned total_size
, header_byte_count
;
66 /* Buffers of binary data, each containing BRIG_CHUNK_MAX_SIZE bytes. */
67 vec
<struct hsa_brig_data_chunk
> chunks
;
69 /* More convenient access to the last chunk from the vector above. */
70 struct hsa_brig_data_chunk
*cur_chunk
;
72 void allocate_new_chunk ();
73 void init (const char *name
);
76 unsigned add (const void *data
, unsigned len
);
77 void round_size_up (int factor
);
80 static struct hsa_brig_section brig_data
, brig_code
, brig_operand
;
81 static uint32_t brig_insn_count
;
82 static bool brig_initialized
= false;
84 /* Add a new chunk, allocate data for it and initialize it. */
87 hsa_brig_section::allocate_new_chunk ()
89 struct hsa_brig_data_chunk new_chunk
;
91 new_chunk
.data
= XCNEWVEC (char, BRIG_CHUNK_MAX_SIZE
);
93 cur_chunk
= chunks
.safe_push (new_chunk
);
96 /* Initialize the brig section. */
99 hsa_brig_section::init (const char *name
)
101 struct BrigSectionHeader sample
;
104 total_size
= sizeof(sample
.byteCount
) + sizeof(sample
.headerByteCount
)
105 + sizeof(sample
.nameLength
);
106 /* Add strlen + null termination to the section size*/
107 total_size
= total_size
+ strlen(section_name
) + 1;
109 allocate_new_chunk ();
111 header_byte_count
= total_size
;
114 /* Free all data in the section. */
117 hsa_brig_section::release ()
119 for (unsigned i
= 0; i
< chunks
.length (); i
++)
120 free (chunks
[i
].data
);
125 /* Write the section to the output file to a section with the name given at
126 initialization. Switches the output section and does not restore it. */
129 hsa_brig_section::output ()
131 struct BrigSectionHeader section_header
;
133 switch_to_section (get_section (section_name
, SECTION_NOTYPE
, NULL
));
135 section_header
.byteCount
= htole32 (total_size
);
136 section_header
.nameLength
= htole32 (strlen(section_name
));
137 section_header
.headerByteCount
= htole32 (header_byte_count
);
138 assemble_string ((const char*) §ion_header
, 12);
139 assemble_string (section_name
, (section_header
.nameLength
+ 1));
140 for (unsigned i
= 0; i
< chunks
.length (); i
++)
141 assemble_string (chunks
[i
].data
, chunks
[i
].size
);
144 /* Add to the stream LEN bytes of opaque binary DATA. Return the offset at
145 which it was stored. */
148 hsa_brig_section::add (const void *data
, unsigned len
)
150 unsigned offset
= total_size
;
152 gcc_assert (len
<= BRIG_CHUNK_MAX_SIZE
);
153 if (cur_chunk
->size
> (BRIG_CHUNK_MAX_SIZE
- len
))
154 allocate_new_chunk ();
156 memcpy (cur_chunk
->data
+ cur_chunk
->size
, data
, len
);
157 cur_chunk
->size
+= len
;
163 /* Add padding to section so that its size is divisble by FACTOR. */
166 hsa_brig_section::round_size_up (int factor
)
168 unsigned padding
, res
= total_size
% factor
;
173 padding
= factor
- res
;
174 total_size
+= padding
;
175 if (cur_chunk
->size
> (BRIG_CHUNK_MAX_SIZE
- padding
))
177 padding
-= BRIG_CHUNK_MAX_SIZE
- cur_chunk
->size
;
178 cur_chunk
->size
= BRIG_CHUNK_MAX_SIZE
;
179 allocate_new_chunk ();
182 cur_chunk
->size
+= padding
;
185 /* BRIG string data hashing. */
187 struct brig_string_slot
195 /* Hashtable helpers. */
197 struct brig_string_slot_hasher
199 typedef brig_string_slot value_type
;
200 typedef brig_string_slot compare_type
;
201 static inline hashval_t
hash (const value_type
*);
202 static inline bool equal (const value_type
*, const compare_type
*);
203 static inline void remove (value_type
*);
206 /* Returns a hash code for DS. Adapted from libiberty's htab_hash_string
207 to support strings that may not end in '\0'. */
210 brig_string_slot_hasher::hash (const value_type
*ds
)
212 hashval_t r
= ds
->len
;
215 for (i
= 0; i
< ds
->len
; i
++)
216 r
= r
* 67 + (unsigned)ds
->s
[i
] - 113;
217 r
= r
* 67 + (unsigned)ds
->prefix
- 113;
221 /* Returns nonzero if DS1 and DS2 are equal. */
224 brig_string_slot_hasher::equal (const value_type
*ds1
, const compare_type
*ds2
)
226 if (ds1
->len
== ds2
->len
)
227 return ds1
->prefix
== ds2
->prefix
&& memcmp (ds1
->s
, ds2
->s
, ds1
->len
) == 0;
233 brig_string_slot_hasher::remove (value_type
*ds
)
235 free (const_cast<char*> (ds
->s
));
238 static hash_table
<brig_string_slot_hasher
> *brig_string_htab
;
241 sanitize_hsa_name (char *p
)
248 /* Emit a null terminated string STR to the data section and return its
249 offset in it. If PREFIX is non-zero, output it just before STR too. */
252 brig_emit_string (const char *str
, char prefix
= 0)
254 unsigned slen
= strlen (str
);
255 unsigned offset
, len
= slen
+ (prefix
? 1 : 0);
256 uint32_t hdr_len
= htole32 (len
);
257 brig_string_slot s_slot
;
258 brig_string_slot
**slot
;
261 /* XXX Sanitize the names without all the strdup. */
262 str2
= xstrdup (str
);
263 sanitize_hsa_name (str2
);
266 s_slot
.prefix
= prefix
;
269 slot
= brig_string_htab
->find_slot (&s_slot
, INSERT
);
272 brig_string_slot
*new_slot
= XCNEW (brig_string_slot
);
274 /* In theory we should fill in BrigData but that would mean copying
275 the string to a buffer for no reason, so we just emaulate it. */
276 offset
= brig_data
.add (&hdr_len
, sizeof (hdr_len
));
278 brig_data
.add (&prefix
, 1);
280 brig_data
.add (str2
, slen
);
281 brig_data
.round_size_up (4);
283 /* XXX could use the string we just copied into brig_string->cur_chunk */
285 new_slot
->len
= slen
;
286 new_slot
->prefix
= prefix
;
287 new_slot
->offset
= offset
;
292 offset
= (*slot
)->offset
;
299 /* Linked list of queued operands. */
301 static struct operand_queue
303 /* First from the chain of queued operands. */
304 hsa_op_base
*first_op
, *last_op
;
306 /* The offset at which the next operand will be enqueued. */
307 unsigned projected_size
;
311 /* Unless already initialized, initialzie infrastructure to produce BRIG. */
316 struct BrigDirectiveVersion verdir
;
319 if (brig_initialized
)
322 brig_string_htab
= new hash_table
<brig_string_slot_hasher
> (37);
323 brig_data
.init (BRIG_SECTION_DATA_NAME
);
324 brig_code
.init (BRIG_SECTION_CODE_NAME
);
325 brig_operand
.init (BRIG_SECTION_OPERAND_NAME
);
327 verdir
.base
.byteCount
= htole16 (sizeof (verdir
));
328 verdir
.base
.kind
= htole16 (BRIG_KIND_DIRECTIVE_VERSION
);
329 verdir
.hsailMajor
= htole32 (BRIG_VERSION_HSAIL_MAJOR
) ;
330 verdir
.hsailMinor
= htole32 (BRIG_VERSION_HSAIL_MINOR
);
331 verdir
.brigMajor
= htole32 (BRIG_VERSION_BRIG_MAJOR
);
332 verdir
.brigMinor
= htole32 (BRIG_VERSION_BRIG_MINOR
);
333 verdir
.profile
= hsa_full_profile_p () ? BRIG_PROFILE_FULL
: BRIG_PROFILE_BASE
;
334 if (hsa_machine_large_p ())
335 verdir
.machineModel
= BRIG_MACHINE_LARGE
;
337 verdir
.machineModel
= BRIG_MACHINE_SMALL
;
339 brig_code
.add (&verdir
, sizeof (verdir
));
340 brig_initialized
= true;
343 /* Free all BRIG data. */
346 brig_release_data (void)
348 delete brig_string_htab
;
349 brig_data
.release ();
350 brig_code
.release ();
351 brig_operand
.release ();
353 brig_initialized
= 0;
356 /* Find the alignment base on the type. */
358 static BrigAlignment8_t
359 get_alignment (BrigType16_t type
)
361 BrigType16_t bit_type
;
362 bit_type
= bittype_for_type (type
) ;
364 if (bit_type
== BRIG_TYPE_B1
)
365 return BRIG_ALIGNMENT_1
;
366 if (bit_type
== BRIG_TYPE_B8
)
367 return BRIG_ALIGNMENT_1
;
368 if (bit_type
== BRIG_TYPE_B16
)
369 return BRIG_ALIGNMENT_2
;
370 if (bit_type
== BRIG_TYPE_B32
)
371 return BRIG_ALIGNMENT_4
;
372 if (bit_type
== BRIG_TYPE_B64
)
373 return BRIG_ALIGNMENT_8
;
374 if (bit_type
== BRIG_TYPE_B128
)
375 return BRIG_ALIGNMENT_16
;
379 /* Emit directive describing a symbol if it has not been emitted already.
380 Return the offset of the directive. */
383 emit_directive_variable (struct hsa_symbol
*symbol
)
385 struct BrigDirectiveVariable dirvar
;
386 unsigned name_offset
;
387 static unsigned res_name_offset
;
391 return symbol
->offset
;
393 dirvar
.base
.byteCount
= htole16 (sizeof (dirvar
));
394 dirvar
.base
.kind
= htole16 (BRIG_KIND_DIRECTIVE_VARIABLE
);
395 dirvar
.allocation
= BRIG_ALLOCATION_AUTOMATIC
;
397 if (symbol
->decl
&& is_global_var (symbol
->decl
))
400 dirvar
.allocation
= BRIG_ALLOCATION_PROGRAM
;
401 if (TREE_CODE (symbol
->decl
) == VAR_DECL
)
402 warning (0, "referring to global symbol %q+D by name from HSA code won't work", symbol
->decl
);
407 if (symbol
->decl
&& TREE_CODE (symbol
->decl
) == RESULT_DECL
)
409 if (res_name_offset
== 0)
410 res_name_offset
= brig_emit_string (symbol
->name
, '%');
411 name_offset
= res_name_offset
;
412 dirvar
.allocation
= BRIG_ALLOCATION_NONE
;
414 else if (symbol
->name
)
415 name_offset
= brig_emit_string (symbol
->name
, prefix
);
419 sprintf (buf
, "__%s_%i", hsa_seg_name (symbol
->segment
),
420 symbol
->name_number
);
421 name_offset
= brig_emit_string (buf
, prefix
);
424 dirvar
.name
= htole32 (name_offset
);
426 dirvar
.type
= htole16 (symbol
->type
);
427 dirvar
.segment
= symbol
->segment
;
428 dirvar
.align
= get_alignment (dirvar
.type
);
429 dirvar
.linkage
= BRIG_LINKAGE_FUNCTION
;
430 dirvar
.dim
.lo
= htole32 (symbol
->dimLo
);
431 dirvar
.dim
.hi
= htole32 (symbol
->dimHi
);
432 dirvar
.modifier
= BRIG_SYMBOL_DEFINITION
;
435 symbol
->offset
= brig_code
.add (&dirvar
, sizeof (dirvar
));
436 return symbol
->offset
;
439 /* Emit directives describing the function, for example its input and output
440 arguments, local variables etc. */
442 static BrigDirectiveExecutable
*
443 emit_function_directives (void)
445 struct BrigDirectiveExecutable fndir
;
446 unsigned name_offset
, inarg_off
, scoped_off
, next_toplev_off
;
448 BrigDirectiveExecutable
*ptr_to_fndir
;
451 name_offset
= brig_emit_string (hsa_cfun
.name
, '&');
452 inarg_off
= brig_code
.total_size
+ sizeof(fndir
)
453 + (hsa_cfun
.output_arg
? sizeof (struct BrigDirectiveVariable
) : 0);
454 scoped_off
= inarg_off
455 + hsa_cfun
.input_args_count
* sizeof (struct BrigDirectiveVariable
);
456 for (hash_table
<hsa_noop_symbol_hasher
>::iterator iter
457 = hsa_cfun
.local_symbols
->begin ();
458 iter
!= hsa_cfun
.local_symbols
->end ();
460 if (TREE_CODE ((*iter
)->decl
) == VAR_DECL
)
462 count
+= hsa_cfun
.spill_symbols
.length();
464 next_toplev_off
= scoped_off
+ count
* sizeof (struct BrigDirectiveVariable
);
466 fndir
.base
.byteCount
= htole16 (sizeof (fndir
));
467 fndir
.base
.kind
= htole16 (BRIG_KIND_DIRECTIVE_KERNEL
);
468 fndir
.name
= htole32 (name_offset
);
469 fndir
.inArgCount
= htole16 (hsa_cfun
.input_args_count
);
470 fndir
.outArgCount
= htole16 (hsa_cfun
.output_arg
? 1 : 0);
471 fndir
.firstInArg
= htole32 (inarg_off
);
472 fndir
.firstCodeBlockEntry
= htole32 (scoped_off
);
473 fndir
.nextModuleEntry
= htole32 (next_toplev_off
);
474 fndir
.linkage
= BRIG_LINKAGE_PROGRAM
;
475 fndir
.codeBlockEntryCount
= htole32 (0);
476 fndir
.modifier
= BRIG_EXECUTABLE_DEFINITION
;
477 memset (&fndir
.reserved
, 0, sizeof (fndir
.reserved
));
479 brig_code
.add (&fndir
, sizeof (fndir
));
480 /* XXX terrible hack: we need to set instCount after we emit all
481 insns, but we need to emit directive in order, and we emit directives
482 during insn emitting. So we need to emit the FUNCTION directive
483 early, then the insns, and then we need to set instCount, so remember
484 a pointer to it, in some horrible way. cur_chunk.data+size points
485 directly to after fndir here. */
487 = (BrigDirectiveExecutable
*)(brig_code
.cur_chunk
->data
488 + brig_code
.cur_chunk
->size
491 if (hsa_cfun
.output_arg
)
492 emit_directive_variable(hsa_cfun
.output_arg
);
493 for (int i
= 0; i
< hsa_cfun
.input_args_count
; i
++)
494 emit_directive_variable(&hsa_cfun
.input_args
[i
]);
495 for (hash_table
<hsa_noop_symbol_hasher
>::iterator iter
496 = hsa_cfun
.local_symbols
->begin ();
497 iter
!= hsa_cfun
.local_symbols
->end ();
499 emit_directive_variable(*iter
);
500 for (int i
= 0; hsa_cfun
.spill_symbols
.iterate (i
, &sym
); i
++)
502 emit_directive_variable (sym
);
508 /* Emit a label directive for the given HBB. We assume it is about to start on
509 the current offset in the code section. */
512 emit_bb_label_directive (hsa_bb
*hbb
)
514 struct BrigDirectiveLabel lbldir
;
517 lbldir
.base
.byteCount
= htole16 (sizeof (lbldir
));
518 lbldir
.base
.kind
= htole16 (BRIG_KIND_DIRECTIVE_LABEL
);
519 sprintf (buf
, "BB_%u_%i", DECL_UID (current_function_decl
), hbb
->index
);
520 lbldir
.name
= htole32 (brig_emit_string (buf
, '@'));
522 hbb
->label_ref
.directive_offset
= brig_code
.add (&lbldir
, sizeof (lbldir
));
527 bittype_for_type (BrigType16_t t
)
543 return BRIG_TYPE_B16
;
550 case BRIG_TYPE_U16X2
:
552 case BRIG_TYPE_S16X2
:
553 case BRIG_TYPE_F16X2
:
554 return BRIG_TYPE_B32
;
561 case BRIG_TYPE_U16X4
:
562 case BRIG_TYPE_U32X2
:
564 case BRIG_TYPE_S16X4
:
565 case BRIG_TYPE_S32X2
:
566 case BRIG_TYPE_F16X4
:
567 case BRIG_TYPE_F32X2
:
569 return BRIG_TYPE_B64
;
572 case BRIG_TYPE_U8X16
:
573 case BRIG_TYPE_U16X8
:
574 case BRIG_TYPE_U32X4
:
575 case BRIG_TYPE_U64X2
:
576 case BRIG_TYPE_S8X16
:
577 case BRIG_TYPE_S16X8
:
578 case BRIG_TYPE_S32X4
:
579 case BRIG_TYPE_S64X2
:
580 case BRIG_TYPE_F16X8
:
581 case BRIG_TYPE_F32X4
:
582 case BRIG_TYPE_F64X2
:
583 return BRIG_TYPE_B128
;
586 gcc_assert (seen_error ());
591 /* Map a normal HSAIL type to the type of the equivalent BRIG operand
592 holding such, for constants and registers. */
595 regtype_for_type (BrigType16_t t
)
614 case BRIG_TYPE_U16X2
:
616 case BRIG_TYPE_S16X2
:
617 case BRIG_TYPE_F16X2
:
618 return BRIG_TYPE_B32
;
625 case BRIG_TYPE_U16X4
:
626 case BRIG_TYPE_U32X2
:
628 case BRIG_TYPE_S16X4
:
629 case BRIG_TYPE_S32X2
:
630 case BRIG_TYPE_F16X4
:
631 case BRIG_TYPE_F32X2
:
633 return BRIG_TYPE_B64
;
636 case BRIG_TYPE_U8X16
:
637 case BRIG_TYPE_U16X8
:
638 case BRIG_TYPE_U32X4
:
639 case BRIG_TYPE_U64X2
:
640 case BRIG_TYPE_S8X16
:
641 case BRIG_TYPE_S16X8
:
642 case BRIG_TYPE_S32X4
:
643 case BRIG_TYPE_S64X2
:
644 case BRIG_TYPE_F16X8
:
645 case BRIG_TYPE_F32X4
:
646 case BRIG_TYPE_F64X2
:
647 return BRIG_TYPE_B128
;
654 /* Enqueue operation OP. Return the offset at which it will be stored. */
657 enqueue_op (hsa_op_base
*op
)
664 ret
= op_queue
.projected_size
;
665 op
->offset
= op_queue
.projected_size
;
667 if (!op_queue
.first_op
)
668 op_queue
.first_op
= op
;
670 op_queue
.last_op
->next
= op
;
671 op_queue
.last_op
= op
;
673 if (is_a
<hsa_op_immed
*> (op
))
674 op_queue
.projected_size
+= sizeof (struct BrigOperandData
);
675 else if (is_a
<hsa_op_reg
*> (op
))
676 op_queue
.projected_size
+= sizeof (struct BrigOperandReg
);
677 else if (is_a
<hsa_op_address
*> (op
))
679 op_queue
.projected_size
+= sizeof (struct BrigOperandAddress
);
681 else if (is_a
<hsa_op_label
*> (op
))
682 op_queue
.projected_size
+= sizeof (struct BrigOperandCodeRef
);
688 /* Emit an immediate BRIG operand IMM. */
691 emit_immediate_operand (hsa_op_immed
*imm
)
693 struct BrigOperandData out
;
710 bytes
.b8
= (uint8_t) TREE_INT_CST_LOW (imm
->value
);
714 bytes
.b16
= (uint16_t) TREE_INT_CST_LOW (imm
->value
);
719 sorry ("Support for HSA does not implement immediate 16 bit FPU "
726 bytes
.b32
= (uint32_t) TREE_INT_CST_LOW (imm
->value
);
732 bytes
.b64
= (uint64_t) int_cst_value (imm
->value
);
739 tree expr
= imm
->value
;
740 tree type
= TREE_TYPE (expr
);
742 len
= GET_MODE_SIZE (TYPE_MODE (type
));
744 /* There are always 32 bits in each long, no matter the size of
748 gcc_assert (len
== 4 || len
== 8);
750 real_to_target (tmp
, TREE_REAL_CST_PTR (expr
), TYPE_MODE (type
));
753 bytes
.b32
= (uint32_t) tmp
[0];
756 bytes
.b64
= (uint64_t)(uint32_t) tmp
[1];
758 bytes
.b64
|= (uint32_t) tmp
[0];
766 case BRIG_TYPE_U16X2
:
767 case BRIG_TYPE_S16X2
:
768 case BRIG_TYPE_F16X2
:
770 sorry ("Support for HSA does not implement immediate 32bit "
771 "vector operands. ");
776 case BRIG_TYPE_U16X4
:
777 case BRIG_TYPE_S16X4
:
778 case BRIG_TYPE_F16X4
:
779 case BRIG_TYPE_U32X2
:
780 case BRIG_TYPE_S32X2
:
781 case BRIG_TYPE_F32X2
:
783 sorry ("Support for HSA does not implement immediate 32bit "
784 "vector operands. ");
791 out
.base
.byteCount
= htole16 (sizeof (out
));
792 out
.base
.kind
= htole16 (BRIG_KIND_OPERAND_DATA
);
795 out
.data
= brig_data
.add (&byteCount
, sizeof (byteCount
));
796 brig_data
.add (&bytes
, len
);
798 brig_operand
.add (&out
, sizeof(out
));
799 brig_data
.round_size_up (4);
802 /* Emit a register BRIG operand REG. */
805 emit_register_operand (hsa_op_reg
*reg
)
807 struct BrigOperandReg out
;
809 out
.base
.byteCount
= htole16 (sizeof (out
));
810 out
.base
.kind
= htole16 (BRIG_KIND_OPERAND_REG
);
811 out
.regNum
= htole32 (reg
->hard_num
);
813 if (BRIG_TYPE_B32
== regtype_for_type (reg
->type
))
814 out
.regKind
= BRIG_REGISTER_SINGLE
;
815 else if (BRIG_TYPE_B64
== regtype_for_type (reg
->type
))
816 out
.regKind
= BRIG_REGISTER_DOUBLE
;
817 else if (BRIG_TYPE_B128
== regtype_for_type (reg
->type
))
818 out
.regKind
= BRIG_REGISTER_QUAD
;
819 else if (BRIG_TYPE_B1
== regtype_for_type (reg
->type
))
820 out
.regKind
= BRIG_REGISTER_CONTROL
;
824 brig_operand
.add (&out
, sizeof (out
));
827 /* Emit an address BRIG operand ADDR. */
830 emit_address_operand (hsa_op_address
*addr
)
832 struct BrigOperandAddress out
;
834 out
.base
.byteCount
= htole16 (sizeof (out
));
835 out
.base
.kind
= htole16 (BRIG_KIND_OPERAND_ADDRESS
);
836 out
.symbol
= addr
->symbol
837 ? htole32 (emit_directive_variable (addr
->symbol
)) : 0;
838 out
.reg
= addr
->reg
? htole32 (enqueue_op (addr
->reg
)) : 0;
840 /* FIXME: This is very clumsy. */
841 if (sizeof (addr
->imm_offset
) == 8)
843 out
.offset
.lo
= htole32 ((uint32_t)addr
->imm_offset
);
844 out
.offset
.hi
= htole32 (((long long) addr
->imm_offset
) >> 32);
848 out
.offset
.lo
= htole32 (addr
->imm_offset
);
852 brig_operand
.add (&out
, sizeof (out
));
855 /* Emit a label BRIG operand LABEL. */
858 emit_label_operand (hsa_op_label
*lbl
)
860 struct BrigOperandCodeRef out
;
862 gcc_assert (lbl
->directive_offset
);
863 out
.base
.byteCount
= htole16 (sizeof (out
));
864 out
.base
.kind
= htole16 (BRIG_KIND_OPERAND_CODE_REF
);
865 out
.ref
= htole32 (lbl
->directive_offset
);
866 brig_operand
.add (&out
, sizeof (out
));
869 /* Emit all operands queued for writing. */
872 emit_queued_operands (void)
874 for (hsa_op_base
*op
= op_queue
.first_op
; op
; op
= op
->next
)
876 gcc_assert (op
->offset
== brig_operand
.total_size
);
877 if (hsa_op_immed
*imm
= dyn_cast
<hsa_op_immed
*> (op
))
878 emit_immediate_operand (imm
);
879 else if (hsa_op_reg
*reg
= dyn_cast
<hsa_op_reg
*> (op
))
880 emit_register_operand (reg
);
881 else if (hsa_op_address
*addr
= dyn_cast
<hsa_op_address
*> (op
))
882 emit_address_operand (addr
);
883 else if (hsa_op_label
*lbl
= dyn_cast
<hsa_op_label
*> (op
))
884 emit_label_operand (lbl
);
890 /* Emit an HSA memory instruction and all necessary directives, schedule
891 necessary operands for writing . */
894 emit_memory_insn (hsa_insn_mem
*mem
)
896 struct BrigInstMem repr
;
897 BrigOperandOffset32_t operand_offsets
[2];
900 hsa_op_address
*addr
= as_a
<hsa_op_address
*> (mem
->operands
[1]);
902 /* This is necessary because of the errorneous typedef of
903 BrigMemoryModifier8_t which introduces padding which may then contain
904 random stuff (which we do not want so that we can test things don't
906 memset (&repr
, 0, sizeof (repr
));
907 repr
.base
.base
.byteCount
= htole16 (sizeof (repr
));
908 repr
.base
.base
.kind
= htole16 (BRIG_KIND_INST_MEM
);
909 repr
.base
.opcode
= htole16 (mem
->opcode
);
910 repr
.base
.type
= htole16 (mem
->type
);
912 operand_offsets
[0] = htole32 (enqueue_op (mem
->operands
[0]));
913 operand_offsets
[1] = htole32 (enqueue_op (mem
->operands
[1]));
914 /* We have two operands so use 4 * 2 for the byteCount */
915 byteCount
= htole32 (4 * 2);
917 repr
.base
.operands
= htole32 (brig_data
.add (&byteCount
, sizeof (byteCount
)));
918 brig_data
.add (&operand_offsets
, sizeof (operand_offsets
));
919 brig_data
.round_size_up (4);
922 repr
.segment
= addr
->symbol
->segment
;
924 repr
.segment
= BRIG_SEGMENT_FLAT
;
926 repr
.equivClass
= mem
->equiv_class
;
927 repr
.align
= BRIG_ALIGNMENT_1
;
928 if (mem
->opcode
== BRIG_OPCODE_LD
)
929 repr
.width
= BRIG_WIDTH_1
;
931 repr
.width
= BRIG_WIDTH_NONE
;
932 memset (&repr
.reserved
, 0, sizeof (repr
.reserved
));
933 brig_code
.add (&repr
, sizeof (repr
));
937 /* Emit an HSA memory instruction and all necessary directives, schedule
938 necessary operands for writing . */
941 emit_atomic_insn (hsa_insn_atomic
*mem
)
943 struct BrigInstAtomic repr
;
944 BrigOperandOffset32_t operand_offsets
[4];
947 hsa_op_address
*addr
= as_a
<hsa_op_address
*> (mem
->operands
[1]);
949 /* This is necessary because of the errorneous typedef of
950 BrigMemoryModifier8_t which introduces padding which may then contain
951 random stuff (which we do not want so that we can test things don't
953 memset (&repr
, 0, sizeof (repr
));
954 repr
.base
.base
.byteCount
= htole16 (sizeof (repr
));
955 repr
.base
.base
.kind
= htole16 (BRIG_KIND_INST_ATOMIC
);
956 repr
.base
.opcode
= htole16 (mem
->opcode
);
957 repr
.base
.type
= htole16 (mem
->type
);
959 operand_offsets
[0] = htole32 (enqueue_op (mem
->operands
[0]));
960 operand_offsets
[1] = htole32 (enqueue_op (mem
->operands
[1]));
961 operand_offsets
[2] = htole32 (enqueue_op (mem
->operands
[2]));
962 operand_offsets
[3] = htole32 (enqueue_op (mem
->operands
[3]));
964 /* We have 4 operands so use 4 * 4 for the byteCount */
965 byteCount
= htole32 (4 * 4);
967 repr
.base
.operands
= htole32 (brig_data
.add (&byteCount
, sizeof (byteCount
)));
968 brig_data
.add (&operand_offsets
, sizeof (operand_offsets
));
969 brig_data
.round_size_up (4);
972 repr
.segment
= addr
->symbol
->segment
;
974 repr
.segment
= BRIG_SEGMENT_FLAT
;
975 repr
.memoryOrder
= mem
->memoryorder
;
976 repr
.memoryScope
= mem
->memoryscope
;
977 repr
.atomicOperation
= mem
->atomicop
;
979 brig_code
.add (&repr
, sizeof (repr
));
983 /* Emit an HSA LDA instruction and all necessary directives, schedule
984 necessary operands for writing . */
987 emit_addr_insn (hsa_insn_addr
*insn
)
989 struct BrigInstAddr repr
;
990 BrigOperandOffset32_t operand_offsets
[2];
993 hsa_op_address
*addr
= as_a
<hsa_op_address
*> (insn
->operands
[1]);
995 repr
.base
.base
.byteCount
= htole16 (sizeof (repr
));
996 repr
.base
.base
.kind
= htole16 (BRIG_KIND_INST_ADDR
);
997 repr
.base
.opcode
= htole16 (insn
->opcode
);
998 repr
.base
.type
= htole16 (insn
->type
);
1000 operand_offsets
[0] = htole32 (enqueue_op (insn
->operands
[0]));
1001 operand_offsets
[1] = htole32 (enqueue_op (insn
->operands
[1]));
1003 /* We have two operands so use 4 * 2 for the byteCount */
1004 byteCount
= htole32 (4 * 2);
1006 repr
.base
.operands
= htole32 (brig_data
.add (&byteCount
, sizeof (byteCount
)));
1007 brig_data
.add (&operand_offsets
, sizeof (operand_offsets
));
1008 brig_data
.round_size_up (4);
1011 repr
.segment
= addr
->symbol
->segment
;
1013 repr
.segment
= BRIG_SEGMENT_FLAT
;
1014 memset (&repr
.reserved
, 0, sizeof (repr
.reserved
));
1016 brig_code
.add (&repr
, sizeof (repr
));
1020 /* Emit an HSA segment conversion instruction and all necessary directives,
1021 schedule necessary operands for writing . */
1024 emit_segment_insn (hsa_insn_seg
*seg
)
1026 struct BrigInstSeg repr
;
1027 BrigOperandOffset32_t operand_offsets
[2];
1030 repr
.base
.base
.byteCount
= htole16 (sizeof (repr
));
1031 repr
.base
.base
.kind
= htole16 (BRIG_KIND_INST_SEG
);
1032 repr
.base
.opcode
= htole16 (seg
->opcode
);
1033 repr
.base
.type
= htole16 (seg
->type
);
1035 operand_offsets
[0] = htole32 (enqueue_op (seg
->operands
[0]));
1036 operand_offsets
[1] = htole32 (enqueue_op (seg
->operands
[1]));
1038 /* We have two operands so use 4 * 2 for the byteCount */
1039 byteCount
= htole32 (4 * 2);
1041 repr
.base
.operands
= htole32 (brig_data
.add (&byteCount
, sizeof (byteCount
)));
1042 brig_data
.add (&operand_offsets
, sizeof (operand_offsets
));
1043 brig_data
.round_size_up (4);
1045 repr
.segment
= seg
->segment
;
1046 memset (&repr
.reserved
, 0, sizeof (repr
.reserved
));
1048 brig_code
.add (&repr
, sizeof (repr
));
1053 /* Emit an HSA comparison instruction and all necessary directives,
1054 schedule necessary operands for writing . */
1057 emit_cmp_insn (hsa_insn_cmp
*cmp
)
1059 struct BrigInstCmp repr
;
1060 BrigOperandOffset32_t operand_offsets
[3];
1063 repr
.base
.base
.byteCount
= htole16 (sizeof (repr
));
1064 repr
.base
.base
.kind
= htole16 (BRIG_KIND_INST_CMP
);
1065 repr
.base
.opcode
= htole16 (cmp
->opcode
);
1066 repr
.base
.type
= htole16 (cmp
->type
);
1068 operand_offsets
[0] = htole32 (enqueue_op (cmp
->operands
[0]));
1069 operand_offsets
[1] = htole32 (enqueue_op (cmp
->operands
[1]));
1070 operand_offsets
[2] = htole32 (enqueue_op (cmp
->operands
[2]));
1071 /* We have three operands so use 4 * 3 for the byteCount */
1072 byteCount
= htole32 (4 * 3);
1074 repr
.base
.operands
= htole32 (brig_data
.add (&byteCount
, sizeof (byteCount
)));
1075 brig_data
.add (&operand_offsets
, sizeof (operand_offsets
));
1076 brig_data
.round_size_up (4);
1078 if (is_a
<hsa_op_reg
*> (cmp
->operands
[1]))
1079 repr
.sourceType
= htole16 (as_a
<hsa_op_reg
*> (cmp
->operands
[1])->type
);
1081 repr
.sourceType
= htole16 (as_a
<hsa_op_immed
*> (cmp
->operands
[1])->type
);
1083 repr
.compare
= cmp
->compare
;
1087 brig_code
.add (&repr
, sizeof (repr
));
1091 /* Emit an HSA branching instruction and all necessary directives, schedule
1092 necessary operands for writing . */
1095 emit_branch_insn (hsa_insn_br
*br
)
1097 struct BrigInstBr repr
;
1098 BrigOperandOffset32_t operand_offsets
[2];
1101 basic_block target
= NULL
;
1105 /* At the moment we only handle direct conditional jumps. */
1106 gcc_assert (br
->opcode
== BRIG_OPCODE_CBR
1107 && !br
->operands
[2]);
1108 repr
.base
.base
.byteCount
= htole16 (sizeof (repr
));
1109 repr
.base
.base
.kind
= htole16 (BRIG_KIND_INST_BR
);
1110 repr
.base
.opcode
= htole16 (br
->opcode
);
1111 repr
.width
= BRIG_WIDTH_1
;
1112 /* For Conditional jumps the type is always B1 */
1113 repr
.base
.type
= htole16 (BRIG_TYPE_B1
);
1115 operand_offsets
[0] = htole32 (enqueue_op (br
->operands
[0]));
1117 FOR_EACH_EDGE (e
, ei
, br
->bb
->succs
)
1118 if (e
->flags
& EDGE_TRUE_VALUE
)
1123 gcc_assert (target
);
1124 operand_offsets
[1] = htole32 (enqueue_op
1125 (&hsa_bb_for_bb (target
)->label_ref
));
1127 /* We have 2 operands so use 4 * 2 for the byteCount */
1128 byteCount
= htole32 (4 * 2);
1129 repr
.base
.operands
= htole32 (brig_data
.add (&byteCount
, sizeof (byteCount
)));
1130 brig_data
.add (&operand_offsets
, sizeof (operand_offsets
));
1131 brig_data
.round_size_up (4);
1132 repr
.width
= BRIG_WIDTH_1
;
1133 memset (&repr
.reserved
, 0, sizeof (repr
.reserved
));
1135 brig_code
.add (&repr
, sizeof (repr
));
1140 float_type_p (BrigType16_t t
)
1142 switch (t
& BRIG_TYPE_BASE_MASK
)
1153 /* Emit a HSA convert instruction and all necessary directives, schedule
1154 necessary operands for writing. */
1157 emit_cvt_insn (hsa_insn_basic
*insn
)
1159 struct BrigInstCvt repr
;
1160 BrigType16_t srctype
;
1161 BrigOperandOffset32_t operand_offsets
[1];
1162 uint32_t byteCount
, operand_count
=0;
1164 repr
.base
.base
.byteCount
= htole16 (sizeof (repr
));
1165 repr
.base
.base
.kind
= htole16 (BRIG_KIND_INST_CVT
);
1166 repr
.base
.opcode
= htole16 (insn
->opcode
);
1167 repr
.base
.type
= htole16 (insn
->type
);
1169 for (int i
= 0; i
< HSA_OPERANDS_PER_INSN
; i
++)
1170 if (insn
->operands
[i
])
1172 operand_offsets
[i
] = htole32 (enqueue_op (insn
->operands
[i
]));
1173 operand_count
= operand_count
+ 1;
1176 operand_offsets
[i
] = 0;
1178 byteCount
= htole32 (4 * operand_count
) ;
1179 repr
.base
.operands
= htole32 (brig_data
.add (&byteCount
, sizeof (byteCount
)));
1180 brig_data
.add (&operand_offsets
,
1181 operand_count
* sizeof (BrigOperandOffset32_t
));
1183 if (is_a
<hsa_op_reg
*> (insn
->operands
[1]))
1184 srctype
= as_a
<hsa_op_reg
*> (insn
->operands
[1])->type
;
1186 srctype
= as_a
<hsa_op_immed
*> (insn
->operands
[1])->type
;
1187 repr
.sourceType
= htole16 (srctype
);
1189 /* float to smaller float requires a rounding setting (we default
1191 if (float_type_p (insn
->type
) && float_type_p (srctype
)
1192 && (insn
->type
& BRIG_TYPE_BASE_MASK
) < (srctype
& BRIG_TYPE_BASE_MASK
))
1193 repr
.modifier
= BRIG_ROUND_FLOAT_NEAR_EVEN
;
1197 brig_code
.add (&repr
, sizeof (repr
));
1201 /* Emit a basic HSA instruction and all necessary directives, schedule
1202 necessary operands for writing . */
1205 emit_basic_insn (hsa_insn_basic
*insn
)
1207 /* We assume that BrigInstMod has a BrigInstBasic prefix. */
1208 struct BrigInstMod repr
;
1210 BrigOperandOffset32_t operand_offsets
[HSA_OPERANDS_PER_INSN
];
1211 uint32_t byteCount
, operand_count
= 0;
1213 if (insn
->opcode
== BRIG_OPCODE_CVT
)
1215 emit_cvt_insn (insn
);
1219 repr
.base
.base
.byteCount
= htole16 (sizeof (BrigInstBasic
));
1220 repr
.base
.base
.kind
= htole16 (BRIG_KIND_INST_BASIC
);
1221 repr
.base
.opcode
= htole16 (insn
->opcode
);
1222 switch (insn
->opcode
)
1224 /* XXX The spec says mov can take all types. But the LLVM based
1225 simulator cries about "Mov_s32" not being defined. */
1226 case BRIG_OPCODE_MOV
:
1227 /* And the bit-logical operations need bit types and whine about
1228 arithmetic types :-/ */
1229 case BRIG_OPCODE_AND
:
1230 case BRIG_OPCODE_OR
:
1231 case BRIG_OPCODE_XOR
:
1232 case BRIG_OPCODE_NOT
:
1233 type
= regtype_for_type (insn
->type
);
1239 repr
.base
.type
= htole16 (type
);
1241 for (int i
= 0; i
< HSA_OPERANDS_PER_INSN
; i
++)
1242 if (insn
->operands
[i
])
1244 operand_offsets
[i
] = htole32 (enqueue_op (insn
->operands
[i
]));
1245 operand_count
= operand_count
+ 1;
1248 operand_offsets
[i
] = 0;
1250 byteCount
= htole32 (4 * operand_count
) ;
1251 repr
.base
.operands
= htole32 (brig_data
.add (&byteCount
, sizeof (byteCount
)));
1252 brig_data
.add (&operand_offsets
,
1253 operand_count
* sizeof (BrigOperandOffset32_t
));
1254 brig_data
.round_size_up (4);
1256 if ((type
& BRIG_TYPE_PACK_MASK
) != BRIG_TYPE_PACK_NONE
)
1258 if (float_type_p (type
))
1259 repr
.modifier
= BRIG_ROUND_FLOAT_NEAR_EVEN
;
1262 /* We assume that destination and sources agree in packing
1264 if (insn
->operands
[2])
1265 repr
.pack
= BRIG_PACK_PP
;
1267 repr
.pack
= BRIG_PACK_P
;
1269 repr
.base
.base
.byteCount
= htole16 (sizeof (BrigInstMod
));
1270 repr
.base
.base
.kind
= htole16 (BRIG_KIND_INST_MOD
);
1271 brig_code
.add (&repr
, sizeof (struct BrigInstMod
));
1274 brig_code
.add (&repr
, sizeof (struct BrigInstBasic
));
1278 /* Emit an HSA instruction and all necessary directives, schedule necessary
1279 operands for writing . */
1282 emit_insn (hsa_insn_basic
*insn
)
1284 gcc_assert (!is_a
<hsa_insn_phi
*> (insn
));
1285 if (hsa_insn_atomic
*atom
= dyn_cast
<hsa_insn_atomic
*> (insn
))
1287 emit_atomic_insn (atom
);
1290 if (hsa_insn_mem
*mem
= dyn_cast
<hsa_insn_mem
*> (insn
))
1292 emit_memory_insn (mem
);
1295 if (hsa_insn_addr
*addr
= dyn_cast
<hsa_insn_addr
*> (insn
))
1297 emit_addr_insn (addr
);
1300 if (hsa_insn_seg
*seg
= dyn_cast
<hsa_insn_seg
*> (insn
))
1302 emit_segment_insn (seg
);
1305 if (hsa_insn_cmp
*cmp
= dyn_cast
<hsa_insn_cmp
*> (insn
))
1307 emit_cmp_insn (cmp
);
1310 if (hsa_insn_br
*br
= dyn_cast
<hsa_insn_br
*> (insn
))
1312 emit_branch_insn (br
);
1315 emit_basic_insn (insn
);
1318 /* We have just finished emitting BB and are about to emit NEXT_BB if non-NULL,
1319 or we are about to finish emiting code, if it is NULL. If the fall through
1320 edge from BB does not lead to NEXT_BB, emit an unconditional jump. */
1323 perhaps_emit_branch (basic_block bb
, basic_block next_bb
)
1325 basic_block t_bb
= NULL
, ff
= NULL
;
1326 struct BrigInstBr repr
;
1327 BrigOperandOffset32_t operand_offsets
[1];
1333 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1334 if (e
->flags
& EDGE_TRUE_VALUE
)
1346 || ff
== EXIT_BLOCK_PTR_FOR_FN (cfun
))
1349 repr
.base
.base
.byteCount
= htole16 (sizeof (repr
));
1350 repr
.base
.base
.kind
= htole16 (BRIG_KIND_INST_BR
);
1351 repr
.base
.opcode
= htole16 (BRIG_OPCODE_BR
);
1352 repr
.base
.type
= htole16 (BRIG_TYPE_NONE
);
1353 /* Direct branches to labels must be width(all). */
1354 repr
.width
= BRIG_WIDTH_ALL
;
1356 operand_offsets
[0] = htole32 (enqueue_op (&hsa_bb_for_bb (ff
)->label_ref
));
1357 /* We have 1 operand so use 4 * 1 for the byteCount */
1358 byteCount
= htole32 (4 * 1);
1359 repr
.base
.operands
= htole32 (brig_data
.add (&byteCount
, sizeof (byteCount
)));
1360 brig_data
.add (&operand_offsets
, sizeof (operand_offsets
));
1361 brig_data
.round_size_up (4);
1362 memset (&repr
.reserved
, 0, sizeof (repr
.reserved
));
1363 brig_code
.add (&repr
, sizeof (repr
));
1367 /* Emit the a function with name NAME to the various brig sections. */
1370 hsa_brig_emit_function (void)
1372 basic_block bb
, prev_bb
;
1373 hsa_insn_basic
*insn
;
1374 BrigDirectiveExecutable
*ptr_to_fndir
;
1378 brig_insn_count
= 0;
1379 memset (&op_queue
, 0, sizeof (op_queue
));
1380 op_queue
.projected_size
= brig_operand
.total_size
;
1382 ptr_to_fndir
= emit_function_directives ();
1383 for (insn
= hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun
))->first_insn
;
1387 prev_bb
= ENTRY_BLOCK_PTR_FOR_FN (cfun
);
1388 FOR_EACH_BB_FN (bb
, cfun
)
1390 perhaps_emit_branch (prev_bb
, bb
);
1391 emit_bb_label_directive (hsa_bb_for_bb (bb
));
1392 for (insn
= hsa_bb_for_bb (bb
)->first_insn
; insn
; insn
= insn
->next
)
1396 perhaps_emit_branch (prev_bb
, NULL
);
1397 ptr_to_fndir
->codeBlockEntryCount
= brig_insn_count
;
1398 ptr_to_fndir
->nextModuleEntry
= brig_code
.total_size
;
1400 emit_queued_operands ();
1404 hsa_output_brig (void)
1406 section
*saved_section
;
1408 if (!brig_initialized
)
1411 saved_section
= in_section
;
1413 brig_data
.output ();
1414 brig_code
.output ();
1415 brig_operand
.output ();
1418 switch_to_section (saved_section
);
1420 brig_release_data ();
1421 hsa_deinit_compilation_unit_data ();