1/* brig-code-entry-handler.h -- a gccbrig base class
2   Copyright (C) 2016-2020 Free Software Foundation, Inc.
3   Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
4   for General Processor Tech.
5
6   This file is part of GCC.
7
8   GCC is free software; you can redistribute it and/or modify it under
9   the terms of the GNU General Public License as published by the Free
10   Software Foundation; either version 3, or (at your option) any later
11   version.
12
13   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14   WARRANTY; without even the implied warranty of MERCHANTABILITY or
15   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16   for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with GCC; see the file COPYING3.  If not see
20   <http://www.gnu.org/licenses/>.  */
21
22#ifndef GCC_BRIG_CODE_ENTRY_HANDLER_H
23#define GCC_BRIG_CODE_ENTRY_HANDLER_H
24
25#include "brig-to-generic.h"
26
27#include <map>
28#include <vector>
29
30class tree_element_unary_visitor;
31
32/* An interface to organize the different types of element handlers
33   for the code section.  */
34
35class brig_code_entry_handler : public brig_entry_handler
36{
37public:
38  brig_code_entry_handler (brig_to_generic &parent);
39
40  /* Handles the brig_code data at the given pointer and adds it to the
41     currently built tree.  Returns the number of consumed bytes.  */
42
43  virtual size_t operator () (const BrigBase *base) = 0;
44
45  void append_statement (tree stmt);
46
47protected:
48
49  tree get_tree_expr_type_for_hsa_type (BrigType16_t brig_type) const;
50  tree get_tree_cst_for_hsa_operand (const BrigOperandConstantBytes *brigConst,
51				     tree type) const;
52  tree get_comparison_result_type (tree source_type);
53
54  tree build_code_ref (const BrigBase &ref);
55
56  tree build_tree_operand (const BrigInstBase &brig_inst,
57			   const BrigBase &operand,
58			   tree operand_type = NULL_TREE,
59			   bool is_input = false);
60
61  tree build_address_operand (const BrigInstBase &brig_inst,
62			      const BrigOperandAddress &addr_operand);
63
64  tree build_tree_operand_from_brig (const BrigInstBase *brig_inst,
65				     tree operand_type, size_t operand_index);
66
67  tree build_tree_cst_element (BrigType16_t element_type,
68			       const unsigned char *next_data) const;
69
70  bool needs_workitem_context_data (BrigOpcode16_t brig_opcode) const;
71
72  tree add_temp_var (std::string name, tree expr);
73
74  tree build_f2h_conversion (tree source);
75  tree build_h2f_conversion (tree source);
76
77  tree_stl_vec build_operands (const BrigInstBase &brig_inst);
78  void analyze_operands (const BrigInstBase &brig_inst);
79  tree build_output_assignment (const BrigInstBase &brig_inst, tree output,
80				tree inst_expr);
81
82  tree apply_to_all_elements (tree_element_unary_visitor &visitor,
83			      tree operand);
84
85  HOST_WIDE_INT int_constant_value (tree node);
86
87  tree extend_int (tree input, tree dest_type, tree src_type);
88
89private:
90
91  tree_stl_vec build_or_analyze_operands (const BrigInstBase &brig_inst,
92					  bool analyze);
93};
94
95/* Implement the Visitor software pattern for performing various actions on
96   elements of vector operands.  This enables separating the vector element
97   traversal/extraction/packing code from whatever different actions are
98   performed to each element.  */
99
100class tree_element_unary_visitor
101{
102public:
103  tree operator () (brig_code_entry_handler &handler, tree operand);
104
105  /* Performs an action to a single element, which can have originally
106     been a vector element or a scalar.  */
107
108  virtual tree visit_element (brig_code_entry_handler &handler, tree operand)
109    = 0;
110};
111
112class tree_element_binary_visitor
113{
114public:
115  tree operator () (brig_code_entry_handler &handler, tree operand0,
116		   tree operand1);
117
118  /* Performs an action to a pair of elements, which can have originally
119     been a vector element or a scalar.  */
120
121  virtual tree visit_element (brig_code_entry_handler &handler, tree operand0,
122			      tree operand1)
123    = 0;
124};
125
126/* Visitor for flushing float elements to zero.  */
127
128class flush_to_zero : public tree_element_unary_visitor
129{
130public:
131  flush_to_zero (bool fp16) : m_fp16 (fp16)
132  {
133  }
134
135  virtual tree visit_element (brig_code_entry_handler &caller, tree operand);
136
137private:
138
139  /* True if the value should be flushed according to fp16 limits.  */
140
141  bool m_fp16;
142};
143
144/* Visitor for converting F16 elements to F32.  */
145
146class half_to_float : public tree_element_unary_visitor
147{
148public:
149  virtual tree visit_element (brig_code_entry_handler &caller, tree operand);
150};
151
152/* Visitor for converting F32 elements to F16.  */
153
154class float_to_half : public tree_element_unary_visitor
155{
156public:
157  virtual tree visit_element (brig_code_entry_handler &caller, tree operand);
158};
159
160/* A base class for instruction types that support floating point
161   modifiers.
162
163   operator () delegates to subclasses (template method pattern) in
164   type specific parts.  */
165
166class brig_inst_mod_handler : public brig_code_entry_handler
167{
168public:
169  brig_inst_mod_handler (brig_to_generic &parent)
170    : brig_code_entry_handler (parent)
171  {
172  }
173
174  virtual size_t generate (const BrigBase *base);
175  virtual const BrigAluModifier8_t *modifier (const BrigBase *base) const;
176  virtual const BrigRound8_t *round (const BrigBase *base) const;
177
178  size_t operator () (const BrigBase *base);
179};
180
181class brig_directive_function_handler : public brig_code_entry_handler
182{
183public:
184  brig_directive_function_handler (brig_to_generic &parent)
185    : brig_code_entry_handler (parent)
186  {
187  }
188  size_t operator () (const BrigBase *base);
189};
190
191class brig_directive_control_handler : public brig_code_entry_handler
192{
193public:
194  brig_directive_control_handler (brig_to_generic &parent)
195    : brig_code_entry_handler (parent)
196  {
197  }
198
199  size_t operator () (const BrigBase *base);
200};
201
202class brig_directive_variable_handler : public brig_code_entry_handler
203{
204public:
205  brig_directive_variable_handler (brig_to_generic &parent)
206    : brig_code_entry_handler (parent)
207  {
208  }
209
210  size_t operator () (const BrigBase *base);
211
212  tree build_variable (const BrigDirectiveVariable *brigVar,
213		       tree_code var_decltype = VAR_DECL);
214
215  size_t get_brig_var_alignment (const BrigDirectiveVariable *brigVar);
216};
217
218class brig_directive_fbarrier_handler : public brig_code_entry_handler
219{
220public:
221  brig_directive_fbarrier_handler (brig_to_generic &parent)
222    : brig_code_entry_handler (parent)
223  {
224  }
225
226  size_t operator () (const BrigBase *base);
227};
228
229class brig_directive_label_handler : public brig_code_entry_handler
230{
231public:
232  brig_directive_label_handler (brig_to_generic &parent)
233    : brig_code_entry_handler (parent)
234  {
235  }
236
237  size_t operator () (const BrigBase *base);
238};
239
240class brig_directive_comment_handler : public brig_code_entry_handler
241{
242public:
243  brig_directive_comment_handler (brig_to_generic &parent)
244    : brig_code_entry_handler (parent)
245  {
246  }
247
248  size_t operator () (const BrigBase *base);
249};
250
251class brig_directive_arg_block_handler : public brig_code_entry_handler
252{
253public:
254  brig_directive_arg_block_handler (brig_to_generic &parent)
255    : brig_code_entry_handler (parent)
256  {
257  }
258
259  size_t operator () (const BrigBase *base);
260};
261
262class brig_basic_inst_handler : public brig_code_entry_handler
263{
264public:
265  brig_basic_inst_handler (brig_to_generic &parent);
266
267  size_t operator () (const BrigBase *base);
268
269private:
270  tree build_lower_element_broadcast (tree vec_operand);
271
272  bool must_be_scalarized (const BrigInstBase *brig_inst,
273			   tree instr_type) const;
274
275  tree build_inst_expr (BrigOpcode16_t brig_opcode, BrigType16_t brig_type,
276			 tree arith_type, tree_stl_vec &operands);
277
278  tree build_shuffle (tree arith_type, tree_stl_vec &operands);
279  tree build_unpack (tree_stl_vec &operands);
280  tree build_pack (tree_stl_vec &operands);
281
282  tree build_unpack_lo_or_hi (BrigOpcode16_t brig_opcode, tree arith_type,
283			      tree_stl_vec &operands);
284};
285
286class brig_cvt_inst_handler : public brig_inst_mod_handler
287{
288public:
289  brig_cvt_inst_handler (brig_to_generic &parent)
290    : brig_inst_mod_handler (parent)
291  {
292  }
293
294  virtual size_t generate (const BrigBase *base);
295  virtual const BrigAluModifier8_t *modifier (const BrigBase *base) const;
296  virtual const BrigRound8_t *round (const BrigBase *base) const;
297};
298
299class brig_branch_inst_handler : public brig_code_entry_handler
300{
301public:
302  brig_branch_inst_handler (brig_to_generic &parent)
303    : brig_code_entry_handler (parent)
304  {
305  }
306
307  size_t operator () (const BrigBase *base);
308};
309
310class brig_mem_inst_handler : public brig_code_entry_handler
311{
312public:
313  brig_mem_inst_handler (brig_to_generic &parent)
314    : brig_code_entry_handler (parent)
315  {
316  }
317
318  size_t operator () (const BrigBase *base);
319
320private:
321  tree build_mem_access (const BrigInstBase *brig_inst, tree addr, tree data);
322};
323
324class brig_copy_move_inst_handler : public brig_code_entry_handler
325{
326public:
327  brig_copy_move_inst_handler (brig_to_generic &parent)
328    : brig_code_entry_handler (parent)
329  {
330  }
331
332  size_t operator () (const BrigBase *base);
333
334private:
335  size_t handle_lda (const BrigInstBase *base);
336};
337
338class brig_atomic_inst_handler : public brig_code_entry_handler
339{
340private:
341  typedef std::map<std::string, tree> atomic_builtins_map;
342
343public:
344  brig_atomic_inst_handler (brig_to_generic &parent);
345
346  size_t operator () (const BrigBase *base);
347
348protected:
349  size_t generate_tree (const BrigInstBase &inst,
350			BrigAtomicOperation8_t atomic_opcode);
351};
352
353class brig_signal_inst_handler : public brig_atomic_inst_handler
354{
355public:
356  brig_signal_inst_handler (brig_to_generic &parent)
357    : brig_atomic_inst_handler (parent)
358  {
359  }
360  size_t operator () (const BrigBase *base);
361};
362
363class brig_cmp_inst_handler : public brig_code_entry_handler
364{
365public:
366  brig_cmp_inst_handler (brig_to_generic &parent)
367    : brig_code_entry_handler (parent)
368  {
369  }
370
371  size_t operator () (const BrigBase *base);
372};
373
374class brig_seg_inst_handler : public brig_code_entry_handler
375{
376public:
377  brig_seg_inst_handler (brig_to_generic &parent);
378
379  size_t operator () (const BrigBase *base);
380};
381
382class brig_lane_inst_handler : public brig_code_entry_handler
383{
384public:
385  brig_lane_inst_handler (brig_to_generic &parent);
386
387  size_t operator () (const BrigBase *base);
388};
389
390class brig_queue_inst_handler : public brig_code_entry_handler
391{
392public:
393  brig_queue_inst_handler (brig_to_generic &parent);
394
395  size_t operator () (const BrigBase *base);
396};
397
398class brig_directive_module_handler : public brig_code_entry_handler
399{
400public:
401  brig_directive_module_handler (brig_to_generic &parent)
402    : brig_code_entry_handler (parent)
403  {
404  }
405
406  size_t operator () (const BrigBase *base);
407};
408
409
410#endif
411