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"
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 bool function_scope
= m_parent
.m_cf
!= NULL
;
150 m_parent
.m_cf
->m_function_scope_vars
.insert (base
);
152 std::string var_name
= m_parent
.get_mangled_name (brigVar
);
153 if (brigVar
->segment
== BRIG_SEGMENT_GROUP
)
155 /* Non-kernel scope group variables have been added at the
157 m_parent
.add_group_variable (var_name
, var_size
, alignment
,
159 return base
->byteCount
;
162 /* During analyze, handle only (module scope) group variables. */
163 if (m_parent
.m_analyzing
)
164 return base
->byteCount
;
166 if (brigVar
->segment
== BRIG_SEGMENT_KERNARG
)
168 /* Do not create a real variable, but only a table of
169 offsets to the kernarg segment buffer passed as the
170 single argument by the kernel launcher for later
171 reference. Ignore kernel declarations. */
172 if (m_parent
.m_cf
!= NULL
&& m_parent
.m_cf
->m_func_decl
!= NULL_TREE
)
173 m_parent
.m_cf
->append_kernel_arg (brigVar
, var_size
, alignment
);
174 return base
->byteCount
;
176 else if (brigVar
->segment
== BRIG_SEGMENT_PRIVATE
177 || brigVar
->segment
== BRIG_SEGMENT_SPILL
)
179 /* Private variables are handled like group variables,
180 except that their offsets are multiplied by the work-item
181 flat id, when accessed. */
182 if (!m_parent
.has_private_variable (var_name
))
183 m_parent
.append_private_variable (var_name
, var_size
, alignment
);
184 return base
->byteCount
;
186 else if (brigVar
->segment
== BRIG_SEGMENT_GLOBAL
187 || brigVar
->segment
== BRIG_SEGMENT_READONLY
)
189 tree def
= is_definition
? NULL_TREE
:
190 m_parent
.global_variable (var_name
);
192 if (!is_definition
&& def
!= NULL_TREE
)
194 /* We have a definition already for this declaration.
195 Use the definition instead of the declaration. */
197 else if (gccbrig_might_be_host_defined_var_p (brigVar
))
199 tree var_decl
= build_variable (brigVar
);
200 m_parent
.add_host_def_var_ptr (var_name
, var_decl
);
204 tree var_decl
= build_variable (brigVar
);
205 /* Make all global variables program scope for now
206 so we can get their address from the Runtime API. */
207 DECL_CONTEXT (var_decl
) = NULL_TREE
;
208 TREE_STATIC (var_decl
) = 1;
209 m_parent
.add_global_variable (var_name
, var_decl
);
212 else if (brigVar
->segment
== BRIG_SEGMENT_ARG
)
215 if (m_parent
.m_cf
->m_generating_arg_block
)
217 tree var_decl
= build_variable (brigVar
);
218 tree bind_expr
= m_parent
.m_cf
->m_current_bind_expr
;
220 DECL_CONTEXT (var_decl
) = m_parent
.m_cf
->m_func_decl
;
221 DECL_CHAIN (var_decl
) = BIND_EXPR_VARS (bind_expr
);
222 BIND_EXPR_VARS (bind_expr
) = var_decl
;
223 TREE_PUBLIC (var_decl
) = 0;
225 m_parent
.m_cf
->add_arg_variable (brigVar
, var_decl
);
229 /* Must be an incoming function argument which has
230 been parsed in brig-function-handler.cc. No
231 need to generate anything here. */
237 return base
->byteCount
;
240 /* Returns the alignment for the given BRIG variable. In case the variable
241 explicitly defines alignment and its larger than the natural alignment,
242 returns it instead of the natural one. */
245 brig_directive_variable_handler::get_brig_var_alignment
246 (const BrigDirectiveVariable
*brigVar
)
249 size_t defined_alignment
250 = brigVar
->align
== BRIG_ALIGNMENT_NONE
? 0 : 1 << (brigVar
->align
- 1);
251 size_t natural_alignment
;
252 if (brigVar
->type
& BRIG_TYPE_ARRAY
)
255 = gccbrig_tree_type_for_hsa_type (brigVar
->type
& ~BRIG_TYPE_ARRAY
);
256 size_t element_size
= tree_to_uhwi (TYPE_SIZE (element_type
));
257 natural_alignment
= element_size
/ BITS_PER_UNIT
;
261 tree t
= gccbrig_tree_type_for_hsa_type (brigVar
->type
);
262 natural_alignment
= tree_to_uhwi (TYPE_SIZE (t
)) / BITS_PER_UNIT
;
265 return natural_alignment
> defined_alignment
266 ? natural_alignment
: defined_alignment
;