1 /* brig-variable-handler.cc -- brig variable directive handling
2 Copyright (C) 2016-2018 Free Software Foundation, Inc.
3 Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
4 for General Processor Tech.
6 This file is part of GCC.
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
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
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/>. */
22 #include "brig-code-entry-handler.h"
24 #include "stringpool.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"
33 brig_directive_variable_handler::build_variable
34 (const BrigDirectiveVariable
*brigVar
, tree_code var_decltype
)
36 std::string var_name
= m_parent
.get_mangled_name (brigVar
);
38 bool is_definition
= brigVar
->modifier
& BRIG_VARIABLE_DEFINITION
;
40 tree name_identifier
= get_identifier (var_name
.c_str ());
44 if (brigVar
->type
& BRIG_TYPE_ARRAY
)
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
);
54 t
= build_array_type_nelts (element_type
, element_count
);
58 t
= gccbrig_tree_type_for_hsa_type (brigVar
->type
);
61 size_t alignment
= get_brig_var_alignment (brigVar
);
63 if (brigVar
->segment
== BRIG_SEGMENT_READONLY
64 || brigVar
->segment
== BRIG_SEGMENT_KERNARG
65 || (brigVar
->modifier
& BRIG_VARIABLE_CONST
))
66 TYPE_READONLY (t
) = 1;
68 TYPE_ADDR_SPACE (t
) = gccbrig_get_target_addr_space_id (brigVar
->segment
);
70 var_decl
= build_decl (UNKNOWN_LOCATION
, var_decltype
, name_identifier
, t
);
72 SET_DECL_ALIGN (var_decl
, alignment
* BITS_PER_UNIT
);
74 /* Force the HSA alignments. */
75 DECL_USER_ALIGN (var_decl
) = 1;
77 TREE_USED (var_decl
) = 1;
79 TREE_PUBLIC (var_decl
) = 1;
81 DECL_EXTERNAL (var_decl
) = 0;
83 DECL_EXTERNAL (var_decl
) = 1; /* The definition is elsewhere. */
85 if (brigVar
->init
!= 0)
87 gcc_assert (brigVar
->segment
== BRIG_SEGMENT_READONLY
88 || brigVar
->segment
== BRIG_SEGMENT_GLOBAL
);
90 const BrigBase
*cst_operand_data
91 = m_parent
.get_brig_operand_entry (brigVar
->init
);
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
);
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
;
104 if (var_decltype
== PARM_DECL
)
106 DECL_ARG_TYPE (var_decl
) = TREE_TYPE (var_decl
);
107 DECL_EXTERNAL (var_decl
) = 0;
108 TREE_PUBLIC (var_decl
) = 0;
111 TREE_ADDRESSABLE (var_decl
) = 1;
113 TREE_USED (var_decl
) = 1;
114 DECL_NONLOCAL (var_decl
) = 1;
115 DECL_ARTIFICIAL (var_decl
) = 0;
121 brig_directive_variable_handler::operator () (const BrigBase
*base
)
123 const BrigDirectiveVariable
*brigVar
= (const BrigDirectiveVariable
*) base
;
125 bool is_definition
= brigVar
->modifier
& BRIG_VARIABLE_DEFINITION
;
129 if (brigVar
->type
& BRIG_TYPE_ARRAY
)
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;
142 var_type
= gccbrig_tree_type_for_hsa_type (brigVar
->type
);
143 var_size
= tree_to_uhwi (TYPE_SIZE (var_type
)) / 8;
146 size_t alignment
= get_brig_var_alignment (brigVar
);
148 bool function_scope
= m_parent
.m_cf
!= NULL
;
151 m_parent
.m_cf
->m_function_scope_vars
.insert (base
);
153 std::string var_name
= m_parent
.get_mangled_name (brigVar
);
154 if (brigVar
->segment
== BRIG_SEGMENT_GROUP
)
156 /* Non-kernel scope group variables have been added at the
158 m_parent
.add_group_variable (var_name
, var_size
, alignment
,
160 return base
->byteCount
;
163 /* During analyze, handle only (module scope) group variables. */
164 if (m_parent
.m_analyzing
)
165 return base
->byteCount
;
167 if (brigVar
->segment
== BRIG_SEGMENT_KERNARG
)
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
;
177 else if (brigVar
->segment
== BRIG_SEGMENT_PRIVATE
178 || brigVar
->segment
== BRIG_SEGMENT_SPILL
)
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
;
187 else if (brigVar
->segment
== BRIG_SEGMENT_GLOBAL
188 || brigVar
->segment
== BRIG_SEGMENT_READONLY
)
190 tree def
= is_definition
? NULL_TREE
:
191 m_parent
.global_variable (var_name
);
193 if (!is_definition
&& def
!= NULL_TREE
)
195 /* We have a definition already for this declaration.
196 Use the definition instead of the declaration. */
198 else if (gccbrig_might_be_host_defined_var_p (brigVar
))
200 tree var_decl
= build_variable (brigVar
);
201 m_parent
.add_host_def_var_ptr (var_name
, var_decl
);
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
);
215 else if (brigVar
->segment
== BRIG_SEGMENT_ARG
)
218 if (m_parent
.m_cf
->m_generating_arg_block
)
220 tree var_decl
= build_variable (brigVar
);
221 tree bind_expr
= m_parent
.m_cf
->m_current_bind_expr
;
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;
228 m_parent
.m_cf
->add_arg_variable (brigVar
, var_decl
);
232 /* Must be an incoming function argument which has
233 been parsed in brig-function-handler.cc. No
234 need to generate anything here. */
240 return base
->byteCount
;
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. */
248 brig_directive_variable_handler::get_brig_var_alignment
249 (const BrigDirectiveVariable
*brigVar
)
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
)
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
;
264 tree t
= gccbrig_tree_type_for_hsa_type (brigVar
->type
);
265 natural_alignment
= tree_to_uhwi (TYPE_SIZE (t
)) / BITS_PER_UNIT
;
268 return natural_alignment
> defined_alignment
269 ? natural_alignment
: defined_alignment
;