annotate gcc/hsa-brig.c @ 144:8f4e72ab4e11

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