LCOV - code coverage report
Current view: top level - gcc - hsa-brig.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 4 1410 0.3 %
Date: 2020-04-04 11:58:09 Functions: 1 60 1.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

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

Generated by: LCOV version 1.0

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto --enable-host-shared. GCC test suite is run with the built compiler.