1 /* brig-to-generic.h -- brig to gcc generic conversion
2    Copyright (C) 2016-2018 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 BRIG_TO_GENERIC_H
23 #define BRIG_TO_GENERIC_H
24 
25 #include <string>
26 #include <map>
27 #include <vector>
28 
29 #include "config.h"
30 #include "system.h"
31 #include "ansidecl.h"
32 #include "coretypes.h"
33 #include "opts.h"
34 #include "tree.h"
35 #include "tree-iterator.h"
36 #include "hsa-brig-format.h"
37 #include "brig-function.h"
38 
39 struct reg_decl_index_entry;
40 
41 /* Converts an HSAIL BRIG input to GENERIC.  This class holds global state
42    for the translation process.  Handling of the smaller pieces of BRIG data
43    is delegated to various handler classes declared in
44    brig-code-entry-handlers.h.  */
45 
46 class brig_to_generic
47 {
48 public:
49   typedef std::map<const BrigDirectiveVariable *, tree> variable_index;
50 
51 private:
52   typedef std::map<std::string, size_t> var_offset_table;
53   typedef std::map<const BrigBase *, std::string> name_index;
54 
55 public:
56   brig_to_generic ();
57 
58   void analyze (const char *brig_blob);
59   void parse (const char *brig_blob);
60 
61   void write_globals ();
62 
63   std::string get_string (size_t entry_offset) const;
64 
65   const BrigData *get_brig_data_entry (size_t entry_offset) const;
66   const BrigBase *get_brig_operand_entry (size_t entry_offset) const;
67   const BrigBase *get_brig_code_entry (size_t entry_offset) const;
68 
69   void append_global (tree g);
70 
71   tree function_decl (const std::string &name);
72   void add_function_decl (const std::string &name, tree func_decl);
73 
74   tree global_variable (const std::string &name) const;
75   void add_global_variable (const std::string &name, tree var_decl);
76   void add_host_def_var_ptr (const std::string &name, tree var_decl);
77 
78   void start_function (tree f);
79   void finish_function ();
80 
81   void append_private_variable (const std::string &name, size_t size,
82 				size_t alignment);
83 
84   size_t
85   private_variable_segment_offset (const std::string &name) const;
86 
87   bool
88   has_private_variable (const std::string &name) const;
89 
90   size_t private_variable_size (const std::string &name) const;
91 
92   template <typename T>
93     std::string
94     get_mangled_name_tmpl (const T *brigVar) const;
95 
get_mangled_name(const BrigDirectiveFbarrier * fbar)96   std::string get_mangled_name (const BrigDirectiveFbarrier *fbar) const
97     { return get_mangled_name_tmpl (fbar); }
get_mangled_name(const BrigDirectiveVariable * var)98   std::string get_mangled_name (const BrigDirectiveVariable *var) const
99     { return get_mangled_name_tmpl (var); }
100   std::string get_mangled_name (const BrigDirectiveExecutable *func) const;
101 
102   size_t private_segment_size () const;
103 
104   brig_function *get_finished_function (tree func_decl);
105 
106   void add_group_variable (const std::string &name, size_t size,
107 			   size_t alignment, bool function_scope);
108 
109   void add_reg_used_as_type (const BrigOperandRegister &brig_reg,
110 			     tree operand_type);
111 
112   static tree s_fp16_type;
113   static tree s_fp32_type;
114   static tree s_fp64_type;
115 
116   /* The default rounding mode that should be used for float instructions.
117      This can be set in each BRIG module header.  */
118   BrigRound8_t m_default_float_rounding_mode;
119 
120   /* The currently built function.  */
121   brig_function *m_cf;
122 
123   /* Stores the module and function scope group variable offsets.  */
124   group_variable_offset_index m_module_group_variables;
125 
126   /* The name of the currently handled BRIG module.  */
127   std::string m_module_name;
128 
129   /* Set to true if the compilation is in 'analyze' phase.  */
130   bool m_analyzing;
131 
132   /* Accumulates the total group segment usage.  */
133   size_t m_total_group_segment_usage;
134 
135   /* Statistics about register uses per function.  */
136   std::map<std::string, regs_use_index> m_fn_regs_use_index;
137 
138 private:
139 
140   void find_brig_sections ();
141   /* The BRIG blob and its different sections of the file currently being
142      parsed.  */
143   const char *m_brig;
144   const char *m_data;
145   size_t m_data_size;
146   const char *m_operand;
147   size_t m_operand_size;
148   const char *m_code;
149   size_t m_code_size;
150 
151   tree m_globals;
152 
153   label_index m_global_variables;
154 
155   /* The size of each private variable, including the alignment padding.  */
156   std::map<std::string, size_t> m_private_data_sizes;
157 
158   /* And private.  */
159   size_t m_next_private_offset;
160   var_offset_table m_private_offsets;
161 
162   /* Name index for declared functions.  */
163   label_index m_function_index;
164 
165   /* Stores all processed kernels in order.  */
166   std::vector<brig_function *> m_kernels;
167 
168   /* Stores all already processed functions from the translation unit
169      for some interprocedural analysis.  */
170   std::map<std::string, brig_function *> m_finished_functions;
171 
172   /* The original dump file.  */
173   FILE *m_dump_file;
174 
175   /* The original dump file flags.  */
176   dump_flags_t m_dump_flags;
177 };
178 
179 /* Produce a "mangled name" for the given brig variable.  The mangling is used
180    to make unique global symbol names for module and function scope variables.
181    The templated version is suitable for most of the variable types.  Functions
182    and kernels (BrigDirectiveExecutable) are handled with a specialized
183    get_mangled_name() version.  */
184 
185 template <typename T>
186 std::string
get_mangled_name_tmpl(const T * brigVar)187 brig_to_generic::get_mangled_name_tmpl (const T *brigVar) const
188 {
189   std::string var_name = get_string (brigVar->name).substr (1);
190 
191   /* Mangle the variable name using the function name and the module name
192      in case of a function scope variable.  */
193   if (m_cf != NULL
194       && m_cf->has_function_scope_var (&brigVar->base))
195     var_name = m_cf->m_name + "." + var_name;
196 
197   if (brigVar->linkage == BRIG_LINKAGE_MODULE)
198     var_name = "gccbrig." + m_module_name + "." + var_name;
199   return var_name;
200 }
201 
202 /* An interface to organize the different types of BRIG element handlers.  */
203 
204 class brig_entry_handler
205 {
206 public:
brig_entry_handler(brig_to_generic & parent)207   brig_entry_handler (brig_to_generic &parent) : m_parent (parent)
208   {
209   }
210 
211   /* Handles the brig_code data at the given pointer and adds it to the
212      currently built tree.  Returns the number of consumed bytes;  */
213   virtual size_t operator () (const BrigBase *base) = 0;
214 
215 protected:
216   brig_to_generic &m_parent;
217 };
218 
219 tree call_builtin (tree pdecl, int nargs, tree rettype, ...);
220 
221 tree build_resize_convert_view (tree destination_type, tree source);
222 tree build_reinterpret_to_uint (tree source);
223 
224 tree build_stmt (enum tree_code code, ...);
225 
226 tree get_unsigned_int_type (tree type);
227 
228 tree get_scalar_unsigned_int_type (tree type);
229 
230 void dump_function (FILE *dump_file, brig_function *f);
231 
232 #endif
233