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.
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"
32 brig_directive_variable_handler::build_variable
33 (const BrigDirectiveVariable
*brigVar
, tree_code var_decltype
)
35 std::string var_name
= m_parent
.get_mangled_name (brigVar
);
37 bool is_definition
= brigVar
->modifier
& BRIG_VARIABLE_DEFINITION
;
39 tree name_identifier
= get_identifier (var_name
.c_str ());
43 if (brigVar
->type
& BRIG_TYPE_ARRAY
)
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
);
53 t
= build_array_type_nelts (element_type
, element_count
);
57 t
= gccbrig_tree_type_for_hsa_type (brigVar
->type
);
60 size_t alignment
= get_brig_var_alignment (brigVar
);
62 if (brigVar
->segment
== BRIG_SEGMENT_READONLY
63 || brigVar
->segment
== BRIG_SEGMENT_KERNARG
64 || (brigVar
->modifier
& BRIG_VARIABLE_CONST
))
65 TYPE_READONLY (t
) = 1;
67 TYPE_ADDR_SPACE (t
) = gccbrig_get_target_addr_space_id (brigVar
->segment
);
69 var_decl
= build_decl (UNKNOWN_LOCATION
, var_decltype
, name_identifier
, t
);
71 SET_DECL_ALIGN (var_decl
, alignment
* BITS_PER_UNIT
);
73 /* Force the HSA alignments. */
74 DECL_USER_ALIGN (var_decl
) = 1;
76 TREE_USED (var_decl
) = 1;
78 TREE_PUBLIC (var_decl
) = 1;
80 DECL_EXTERNAL (var_decl
) = 0;
82 DECL_EXTERNAL (var_decl
) = 1; /* The definition is elsewhere. */
84 if (brigVar
->init
!= 0)
86 gcc_assert (brigVar
->segment
== BRIG_SEGMENT_READONLY
87 || brigVar
->segment
== BRIG_SEGMENT_GLOBAL
);
89 const BrigBase
*cst_operand_data
90 = m_parent
.get_brig_operand_entry (brigVar
->init
);
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
);
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
;
103 if (var_decltype
== PARM_DECL
)
105 DECL_ARG_TYPE (var_decl
) = TREE_TYPE (var_decl
);
106 DECL_EXTERNAL (var_decl
) = 0;
107 TREE_PUBLIC (var_decl
) = 0;
110 TREE_ADDRESSABLE (var_decl
) = 1;
112 TREE_USED (var_decl
) = 1;
113 DECL_NONLOCAL (var_decl
) = 1;
114 DECL_ARTIFICIAL (var_decl
) = 0;
120 brig_directive_variable_handler::operator () (const BrigBase
*base
)
122 const BrigDirectiveVariable
*brigVar
= (const BrigDirectiveVariable
*) base
;
124 bool is_definition
= brigVar
->modifier
& BRIG_VARIABLE_DEFINITION
;
128 if (brigVar
->type
& BRIG_TYPE_ARRAY
)
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;
141 var_type
= gccbrig_tree_type_for_hsa_type (brigVar
->type
);
142 var_size
= tree_to_uhwi (TYPE_SIZE (var_type
)) / 8;
145 size_t alignment
= get_brig_var_alignment (brigVar
);
147 if (m_parent
.m_cf
!= NULL
)
148 m_parent
.m_cf
->m_function_scope_vars
.insert (base
);
150 std::string var_name
= m_parent
.get_mangled_name (brigVar
);
151 if (brigVar
->segment
== BRIG_SEGMENT_KERNARG
)
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
;
161 else if (brigVar
->segment
== BRIG_SEGMENT_GROUP
)
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
;
173 else if (brigVar
->segment
== BRIG_SEGMENT_PRIVATE
174 || brigVar
->segment
== BRIG_SEGMENT_SPILL
)
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
;
183 else if (brigVar
->segment
== BRIG_SEGMENT_GLOBAL
184 || brigVar
->segment
== BRIG_SEGMENT_READONLY
)
186 tree def
= is_definition
? NULL_TREE
:
187 m_parent
.global_variable (var_name
);
189 if (!is_definition
&& def
!= NULL_TREE
)
191 /* We have a definition already for this declaration.
192 Use the definition instead of the declaration. */
194 else if (gccbrig_might_be_host_defined_var_p (brigVar
))
196 tree var_decl
= build_variable (brigVar
);
197 m_parent
.add_host_def_var_ptr (var_name
, var_decl
);
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
);
209 else if (brigVar
->segment
== BRIG_SEGMENT_ARG
)
212 if (m_parent
.m_cf
->m_generating_arg_block
)
214 tree var_decl
= build_variable (brigVar
);
215 tree bind_expr
= m_parent
.m_cf
->m_current_bind_expr
;
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;
222 m_parent
.m_cf
->add_arg_variable (brigVar
, var_decl
);
226 /* Must be an incoming function argument which has
227 been parsed in brig-function-handler.cc. No
228 need to generate anything here. */
234 return base
->byteCount
;
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. */
242 brig_directive_variable_handler::get_brig_var_alignment
243 (const BrigDirectiveVariable
*brigVar
)
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
)
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
;
258 tree t
= gccbrig_tree_type_for_hsa_type (brigVar
->type
);
259 natural_alignment
= tree_to_uhwi (TYPE_SIZE (t
)) / BITS_PER_UNIT
;
262 return natural_alignment
> defined_alignment
263 ? natural_alignment
: defined_alignment
;