]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/brig/brigfrontend/brig-variable-handler.cc
update-copyright.py: Add libhsail-rt to self.default_dirs and call self.add_dir on it.
[thirdparty/gcc.git] / gcc / brig / brigfrontend / brig-variable-handler.cc
1 /* brig-variable-handler.cc -- brig variable directive handling
2 Copyright (C) 2016-2017 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 #include "brig-code-entry-handler.h"
23
24 #include "stringpool.h"
25 #include "errors.h"
26 #include "brig-machine.h"
27 #include "brig-util.h"
28 #include "print-tree.h"
29 #include "diagnostic-core.h"
30
31 tree
32 brig_directive_variable_handler::build_variable
33 (const BrigDirectiveVariable *brigVar, tree_code var_decltype)
34 {
35 std::string var_name = m_parent.get_mangled_name (brigVar);
36
37 bool is_definition = brigVar->modifier & BRIG_VARIABLE_DEFINITION;
38
39 tree name_identifier = get_identifier (var_name.c_str ());
40
41 tree var_decl;
42 tree t;
43 if (brigVar->type & BRIG_TYPE_ARRAY)
44 {
45 tree element_type
46 = gccbrig_tree_type_for_hsa_type (brigVar->type & ~BRIG_TYPE_ARRAY);
47 uint64_t element_count = gccbrig_to_uint64_t (brigVar->dim);
48 if (is_definition && element_count == 0)
49 fatal_error (UNKNOWN_LOCATION, "Array definition with zero elements.");
50 if (var_decltype == PARM_DECL)
51 t = build_pointer_type (element_type);
52 else
53 t = build_array_type_nelts (element_type, element_count);
54 }
55 else
56 {
57 t = gccbrig_tree_type_for_hsa_type (brigVar->type);
58 }
59
60 size_t alignment = get_brig_var_alignment (brigVar);
61
62 if (brigVar->segment == BRIG_SEGMENT_READONLY
63 || brigVar->segment == BRIG_SEGMENT_KERNARG
64 || (brigVar->modifier & BRIG_VARIABLE_CONST))
65 TYPE_READONLY (t) = 1;
66
67 TYPE_ADDR_SPACE (t) = gccbrig_get_target_addr_space_id (brigVar->segment);
68
69 var_decl = build_decl (UNKNOWN_LOCATION, var_decltype, name_identifier, t);
70
71 SET_DECL_ALIGN (var_decl, alignment * BITS_PER_UNIT);
72
73 /* Force the HSA alignments. */
74 DECL_USER_ALIGN (var_decl) = 1;
75
76 TREE_USED (var_decl) = 1;
77
78 TREE_PUBLIC (var_decl) = 1;
79 if (is_definition)
80 DECL_EXTERNAL (var_decl) = 0;
81 else
82 DECL_EXTERNAL (var_decl) = 1; /* The definition is elsewhere. */
83
84 if (brigVar->init != 0)
85 {
86 gcc_assert (brigVar->segment == BRIG_SEGMENT_READONLY
87 || brigVar->segment == BRIG_SEGMENT_GLOBAL);
88
89 const BrigBase *cst_operand_data
90 = m_parent.get_brig_operand_entry (brigVar->init);
91
92 tree initializer = NULL_TREE;
93 if (cst_operand_data->kind == BRIG_KIND_OPERAND_CONSTANT_BYTES)
94 initializer = get_tree_cst_for_hsa_operand
95 ((const BrigOperandConstantBytes *) cst_operand_data, t);
96 else
97 error ("variable initializers of type %x not implemented",
98 cst_operand_data->kind);
99 gcc_assert (initializer != NULL_TREE);
100 DECL_INITIAL (var_decl) = initializer;
101 }
102
103 if (var_decltype == PARM_DECL)
104 {
105 DECL_ARG_TYPE (var_decl) = TREE_TYPE (var_decl);
106 DECL_EXTERNAL (var_decl) = 0;
107 TREE_PUBLIC (var_decl) = 0;
108 }
109
110 TREE_ADDRESSABLE (var_decl) = 1;
111
112 TREE_USED (var_decl) = 1;
113 DECL_NONLOCAL (var_decl) = 1;
114 DECL_ARTIFICIAL (var_decl) = 0;
115
116 return var_decl;
117 }
118
119 size_t
120 brig_directive_variable_handler::operator () (const BrigBase *base)
121 {
122 const BrigDirectiveVariable *brigVar = (const BrigDirectiveVariable *) base;
123
124 bool is_definition = brigVar->modifier & BRIG_VARIABLE_DEFINITION;
125
126 size_t var_size;
127 tree var_type;
128 if (brigVar->type & BRIG_TYPE_ARRAY)
129 {
130 tree element_type
131 = gccbrig_tree_type_for_hsa_type (brigVar->type & ~BRIG_TYPE_ARRAY);
132 uint64_t element_count = gccbrig_to_uint64_t (brigVar->dim);
133 if (is_definition && element_count == 0)
134 fatal_error (UNKNOWN_LOCATION, "Array definition with zero elements.");
135 var_type = build_array_type_nelts (element_type, element_count);
136 size_t element_size = tree_to_uhwi (TYPE_SIZE (element_type));
137 var_size = element_size * element_count / 8;
138 }
139 else
140 {
141 var_type = gccbrig_tree_type_for_hsa_type (brigVar->type);
142 var_size = tree_to_uhwi (TYPE_SIZE (var_type)) / 8;
143 }
144
145 size_t alignment = get_brig_var_alignment (brigVar);
146
147 if (m_parent.m_cf != NULL)
148 m_parent.m_cf->m_function_scope_vars.insert (base);
149
150 std::string var_name = m_parent.get_mangled_name (brigVar);
151 if (brigVar->segment == BRIG_SEGMENT_KERNARG)
152 {
153 /* Do not create a real variable, but only a table of
154 offsets to the kernarg segment buffer passed as the
155 single argument by the kernel launcher for later
156 reference. Ignore kernel declarations. */
157 if (m_parent.m_cf != NULL && m_parent.m_cf->m_func_decl != NULL_TREE)
158 m_parent.m_cf->append_kernel_arg (brigVar, var_size, alignment);
159 return base->byteCount;
160 }
161 else if (brigVar->segment == BRIG_SEGMENT_GROUP)
162 {
163 /* Handle group region variables similarly as kernargs:
164 assign offsets to the group region on the fly when
165 a new module scope or function scope group variable is
166 introduced. These offsets will be then added to the
167 group_base hidden pointer passed to the kernel in order to
168 get the flat address. */
169 if (!m_parent.has_group_variable (var_name))
170 m_parent.append_group_variable (var_name, var_size, alignment);
171 return base->byteCount;
172 }
173 else if (brigVar->segment == BRIG_SEGMENT_PRIVATE
174 || brigVar->segment == BRIG_SEGMENT_SPILL)
175 {
176 /* Private variables are handled like group variables,
177 except that their offsets are multiplied by the work-item
178 flat id, when accessed. */
179 if (!m_parent.has_private_variable (var_name))
180 m_parent.append_private_variable (var_name, var_size, alignment);
181 return base->byteCount;
182 }
183 else if (brigVar->segment == BRIG_SEGMENT_GLOBAL
184 || brigVar->segment == BRIG_SEGMENT_READONLY)
185 {
186 tree def = is_definition ? NULL_TREE :
187 m_parent.global_variable (var_name);
188
189 if (!is_definition && def != NULL_TREE)
190 {
191 /* We have a definition already for this declaration.
192 Use the definition instead of the declaration. */
193 }
194 else if (gccbrig_might_be_host_defined_var_p (brigVar))
195 {
196 tree var_decl = build_variable (brigVar);
197 m_parent.add_host_def_var_ptr (var_name, var_decl);
198 }
199 else
200 {
201 tree var_decl = build_variable (brigVar);
202 /* Make all global variables program scope for now
203 so we can get their address from the Runtime API. */
204 DECL_CONTEXT (var_decl) = NULL_TREE;
205 TREE_STATIC (var_decl) = 1;
206 m_parent.add_global_variable (var_name, var_decl);
207 }
208 }
209 else if (brigVar->segment == BRIG_SEGMENT_ARG)
210 {
211
212 if (m_parent.m_cf->m_generating_arg_block)
213 {
214 tree var_decl = build_variable (brigVar);
215 tree bind_expr = m_parent.m_cf->m_current_bind_expr;
216
217 DECL_CONTEXT (var_decl) = m_parent.m_cf->m_func_decl;
218 DECL_CHAIN (var_decl) = BIND_EXPR_VARS (bind_expr);
219 BIND_EXPR_VARS (bind_expr) = var_decl;
220 TREE_PUBLIC (var_decl) = 0;
221
222 m_parent.m_cf->add_arg_variable (brigVar, var_decl);
223 }
224 else
225 {
226 /* Must be an incoming function argument which has
227 been parsed in brig-function-handler.cc. No
228 need to generate anything here. */
229 }
230 }
231 else
232 gcc_unreachable ();
233
234 return base->byteCount;
235 }
236
237 /* Returns the alignment for the given BRIG variable. In case the variable
238 explicitly defines alignment and its larger than the natural alignment,
239 returns it instead of the natural one. */
240
241 size_t
242 brig_directive_variable_handler::get_brig_var_alignment
243 (const BrigDirectiveVariable *brigVar)
244 {
245
246 size_t defined_alignment
247 = brigVar->align == BRIG_ALIGNMENT_NONE ? 0 : 1 << (brigVar->align - 1);
248 size_t natural_alignment;
249 if (brigVar->type & BRIG_TYPE_ARRAY)
250 {
251 tree element_type
252 = gccbrig_tree_type_for_hsa_type (brigVar->type & ~BRIG_TYPE_ARRAY);
253 size_t element_size = tree_to_uhwi (TYPE_SIZE (element_type));
254 natural_alignment = element_size / BITS_PER_UNIT;
255 }
256 else
257 {
258 tree t = gccbrig_tree_type_for_hsa_type (brigVar->type);
259 natural_alignment = tree_to_uhwi (TYPE_SIZE (t)) / BITS_PER_UNIT;
260 }
261
262 return natural_alignment > defined_alignment
263 ? natural_alignment : defined_alignment;
264 }