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