xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/fortran/target-memory.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1627f7eb2Smrg /* Simulate storage of variables into target memory.
2*4c3eb207Smrg    Copyright (C) 2007-2020 Free Software Foundation, Inc.
3627f7eb2Smrg    Contributed by Paul Thomas and Brooks Moses
4627f7eb2Smrg 
5627f7eb2Smrg This file is part of GCC.
6627f7eb2Smrg 
7627f7eb2Smrg GCC is free software; you can redistribute it and/or modify it under
8627f7eb2Smrg the terms of the GNU General Public License as published by the Free
9627f7eb2Smrg Software Foundation; either version 3, or (at your option) any later
10627f7eb2Smrg version.
11627f7eb2Smrg 
12627f7eb2Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13627f7eb2Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
14627f7eb2Smrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15627f7eb2Smrg for more details.
16627f7eb2Smrg 
17627f7eb2Smrg You should have received a copy of the GNU General Public License
18627f7eb2Smrg along with GCC; see the file COPYING3.  If not see
19627f7eb2Smrg <http://www.gnu.org/licenses/>.  */
20627f7eb2Smrg 
21627f7eb2Smrg #include "config.h"
22627f7eb2Smrg #include "system.h"
23627f7eb2Smrg #include "coretypes.h"
24627f7eb2Smrg #include "tree.h"
25627f7eb2Smrg #include "gfortran.h"
26627f7eb2Smrg #include "trans.h"
27627f7eb2Smrg #include "fold-const.h"
28627f7eb2Smrg #include "stor-layout.h"
29627f7eb2Smrg #include "arith.h"
30627f7eb2Smrg #include "constructor.h"
31627f7eb2Smrg #include "trans-const.h"
32627f7eb2Smrg #include "trans-types.h"
33627f7eb2Smrg #include "target-memory.h"
34627f7eb2Smrg 
35627f7eb2Smrg /* --------------------------------------------------------------- */
36627f7eb2Smrg /* Calculate the size of an expression.  */
37627f7eb2Smrg 
38627f7eb2Smrg 
39627f7eb2Smrg static size_t
size_integer(int kind)40627f7eb2Smrg size_integer (int kind)
41627f7eb2Smrg {
42627f7eb2Smrg   return GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (gfc_get_int_type (kind)));
43627f7eb2Smrg }
44627f7eb2Smrg 
45627f7eb2Smrg 
46627f7eb2Smrg static size_t
size_float(int kind)47627f7eb2Smrg size_float (int kind)
48627f7eb2Smrg {
49627f7eb2Smrg   return GET_MODE_SIZE (SCALAR_FLOAT_TYPE_MODE (gfc_get_real_type (kind)));
50627f7eb2Smrg }
51627f7eb2Smrg 
52627f7eb2Smrg 
53627f7eb2Smrg static size_t
size_complex(int kind)54627f7eb2Smrg size_complex (int kind)
55627f7eb2Smrg {
56627f7eb2Smrg   return 2 * size_float (kind);
57627f7eb2Smrg }
58627f7eb2Smrg 
59627f7eb2Smrg 
60627f7eb2Smrg static size_t
size_logical(int kind)61627f7eb2Smrg size_logical (int kind)
62627f7eb2Smrg {
63627f7eb2Smrg   return GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (gfc_get_logical_type (kind)));
64627f7eb2Smrg }
65627f7eb2Smrg 
66627f7eb2Smrg 
67627f7eb2Smrg static size_t
size_character(gfc_charlen_t length,int kind)68627f7eb2Smrg size_character (gfc_charlen_t length, int kind)
69627f7eb2Smrg {
70627f7eb2Smrg   int i = gfc_validate_kind (BT_CHARACTER, kind, false);
71627f7eb2Smrg   return length * gfc_character_kinds[i].bit_size / 8;
72627f7eb2Smrg }
73627f7eb2Smrg 
74627f7eb2Smrg 
75627f7eb2Smrg /* Return the size of a single element of the given expression.
76627f7eb2Smrg    Equivalent to gfc_target_expr_size for scalars.  */
77627f7eb2Smrg 
78627f7eb2Smrg bool
gfc_element_size(gfc_expr * e,size_t * siz)79627f7eb2Smrg gfc_element_size (gfc_expr *e, size_t *siz)
80627f7eb2Smrg {
81627f7eb2Smrg   tree type;
82627f7eb2Smrg 
83627f7eb2Smrg   switch (e->ts.type)
84627f7eb2Smrg     {
85627f7eb2Smrg     case BT_INTEGER:
86627f7eb2Smrg       *siz = size_integer (e->ts.kind);
87627f7eb2Smrg       return true;
88627f7eb2Smrg     case BT_REAL:
89627f7eb2Smrg       *siz = size_float (e->ts.kind);
90627f7eb2Smrg       return true;
91627f7eb2Smrg     case BT_COMPLEX:
92627f7eb2Smrg       *siz = size_complex (e->ts.kind);
93627f7eb2Smrg       return true;
94627f7eb2Smrg     case BT_LOGICAL:
95627f7eb2Smrg       *siz = size_logical (e->ts.kind);
96627f7eb2Smrg       return true;
97627f7eb2Smrg     case BT_CHARACTER:
98627f7eb2Smrg       if (e->expr_type == EXPR_CONSTANT)
99627f7eb2Smrg 	*siz = size_character (e->value.character.length, e->ts.kind);
100627f7eb2Smrg       else if (e->ts.u.cl != NULL && e->ts.u.cl->length != NULL
101627f7eb2Smrg 	       && e->ts.u.cl->length->expr_type == EXPR_CONSTANT
102627f7eb2Smrg 	       && e->ts.u.cl->length->ts.type == BT_INTEGER)
103627f7eb2Smrg 	{
104627f7eb2Smrg 	  HOST_WIDE_INT length;
105627f7eb2Smrg 
106627f7eb2Smrg 	  gfc_extract_hwi (e->ts.u.cl->length, &length);
107627f7eb2Smrg 	  *siz = size_character (length, e->ts.kind);
108627f7eb2Smrg 	}
109627f7eb2Smrg       else
110627f7eb2Smrg 	{
111627f7eb2Smrg 	  *siz = 0;
112627f7eb2Smrg 	  return false;
113627f7eb2Smrg 	}
114627f7eb2Smrg       return true;
115627f7eb2Smrg 
116627f7eb2Smrg     case BT_HOLLERITH:
117627f7eb2Smrg       *siz = e->representation.length;
118627f7eb2Smrg       return true;
119627f7eb2Smrg     case BT_DERIVED:
120627f7eb2Smrg     case BT_CLASS:
121627f7eb2Smrg     case BT_VOID:
122627f7eb2Smrg     case BT_ASSUMED:
123627f7eb2Smrg     case BT_PROCEDURE:
124627f7eb2Smrg       {
125627f7eb2Smrg 	/* Determine type size without clobbering the typespec for ISO C
126627f7eb2Smrg 	   binding types.  */
127627f7eb2Smrg 	gfc_typespec ts;
128627f7eb2Smrg 	HOST_WIDE_INT size;
129627f7eb2Smrg 	ts = e->ts;
130627f7eb2Smrg 	type = gfc_typenode_for_spec (&ts);
131627f7eb2Smrg 	size = int_size_in_bytes (type);
132627f7eb2Smrg 	gcc_assert (size >= 0);
133627f7eb2Smrg 	*siz = size;
134627f7eb2Smrg       }
135627f7eb2Smrg       return true;
136627f7eb2Smrg     default:
137627f7eb2Smrg       gfc_internal_error ("Invalid expression in gfc_element_size.");
138627f7eb2Smrg       *siz = 0;
139627f7eb2Smrg       return false;
140627f7eb2Smrg     }
141627f7eb2Smrg   return true;
142627f7eb2Smrg }
143627f7eb2Smrg 
144627f7eb2Smrg 
145627f7eb2Smrg /* Return the size of an expression in its target representation.  */
146627f7eb2Smrg 
147627f7eb2Smrg bool
gfc_target_expr_size(gfc_expr * e,size_t * size)148627f7eb2Smrg gfc_target_expr_size (gfc_expr *e, size_t *size)
149627f7eb2Smrg {
150627f7eb2Smrg   mpz_t tmp;
151627f7eb2Smrg   size_t asz, el_size;
152627f7eb2Smrg 
153627f7eb2Smrg   gcc_assert (e != NULL);
154627f7eb2Smrg 
155627f7eb2Smrg   *size = 0;
156627f7eb2Smrg   if (e->rank)
157627f7eb2Smrg     {
158627f7eb2Smrg       if (gfc_array_size (e, &tmp))
159627f7eb2Smrg 	asz = mpz_get_ui (tmp);
160627f7eb2Smrg       else
161627f7eb2Smrg 	return false;
162627f7eb2Smrg     }
163627f7eb2Smrg   else
164627f7eb2Smrg     asz = 1;
165627f7eb2Smrg 
166627f7eb2Smrg   if (!gfc_element_size (e, &el_size))
167627f7eb2Smrg     return false;
168627f7eb2Smrg   *size = asz * el_size;
169627f7eb2Smrg   return true;
170627f7eb2Smrg }
171627f7eb2Smrg 
172627f7eb2Smrg 
173627f7eb2Smrg /* The encode_* functions export a value into a buffer, and
174627f7eb2Smrg    return the number of bytes of the buffer that have been
175627f7eb2Smrg    used.  */
176627f7eb2Smrg 
177627f7eb2Smrg static unsigned HOST_WIDE_INT
encode_array(gfc_expr * expr,unsigned char * buffer,size_t buffer_size)178627f7eb2Smrg encode_array (gfc_expr *expr, unsigned char *buffer, size_t buffer_size)
179627f7eb2Smrg {
180627f7eb2Smrg   mpz_t array_size;
181627f7eb2Smrg   int i;
182627f7eb2Smrg   int ptr = 0;
183627f7eb2Smrg 
184627f7eb2Smrg   gfc_constructor_base ctor = expr->value.constructor;
185627f7eb2Smrg 
186627f7eb2Smrg   gfc_array_size (expr, &array_size);
187627f7eb2Smrg   for (i = 0; i < (int)mpz_get_ui (array_size); i++)
188627f7eb2Smrg     {
189627f7eb2Smrg       ptr += gfc_target_encode_expr (gfc_constructor_lookup_expr (ctor, i),
190627f7eb2Smrg 				     &buffer[ptr], buffer_size - ptr);
191627f7eb2Smrg     }
192627f7eb2Smrg 
193627f7eb2Smrg   mpz_clear (array_size);
194627f7eb2Smrg   return ptr;
195627f7eb2Smrg }
196627f7eb2Smrg 
197627f7eb2Smrg 
198627f7eb2Smrg static int
encode_integer(int kind,mpz_t integer,unsigned char * buffer,size_t buffer_size)199627f7eb2Smrg encode_integer (int kind, mpz_t integer, unsigned char *buffer,
200627f7eb2Smrg 		size_t buffer_size)
201627f7eb2Smrg {
202627f7eb2Smrg   return native_encode_expr (gfc_conv_mpz_to_tree (integer, kind),
203627f7eb2Smrg 			     buffer, buffer_size);
204627f7eb2Smrg }
205627f7eb2Smrg 
206627f7eb2Smrg 
207627f7eb2Smrg static int
encode_float(int kind,mpfr_t real,unsigned char * buffer,size_t buffer_size)208627f7eb2Smrg encode_float (int kind, mpfr_t real, unsigned char *buffer, size_t buffer_size)
209627f7eb2Smrg {
210627f7eb2Smrg   return native_encode_expr (gfc_conv_mpfr_to_tree (real, kind, 0), buffer,
211627f7eb2Smrg 			     buffer_size);
212627f7eb2Smrg }
213627f7eb2Smrg 
214627f7eb2Smrg 
215627f7eb2Smrg static int
encode_complex(int kind,mpc_t cmplx,unsigned char * buffer,size_t buffer_size)216627f7eb2Smrg encode_complex (int kind, mpc_t cmplx,
217627f7eb2Smrg 		unsigned char *buffer, size_t buffer_size)
218627f7eb2Smrg {
219627f7eb2Smrg   int size;
220627f7eb2Smrg   size = encode_float (kind, mpc_realref (cmplx), &buffer[0], buffer_size);
221627f7eb2Smrg   size += encode_float (kind, mpc_imagref (cmplx),
222627f7eb2Smrg 			&buffer[size], buffer_size - size);
223627f7eb2Smrg   return size;
224627f7eb2Smrg }
225627f7eb2Smrg 
226627f7eb2Smrg 
227627f7eb2Smrg static int
encode_logical(int kind,int logical,unsigned char * buffer,size_t buffer_size)228627f7eb2Smrg encode_logical (int kind, int logical, unsigned char *buffer, size_t buffer_size)
229627f7eb2Smrg {
230627f7eb2Smrg   return native_encode_expr (build_int_cst (gfc_get_logical_type (kind),
231627f7eb2Smrg 					    logical),
232627f7eb2Smrg 			     buffer, buffer_size);
233627f7eb2Smrg }
234627f7eb2Smrg 
235627f7eb2Smrg 
236627f7eb2Smrg size_t
gfc_encode_character(int kind,size_t length,const gfc_char_t * string,unsigned char * buffer,size_t buffer_size)237627f7eb2Smrg gfc_encode_character (int kind, size_t length, const gfc_char_t *string,
238627f7eb2Smrg 		      unsigned char *buffer, size_t buffer_size)
239627f7eb2Smrg {
240627f7eb2Smrg   size_t elsize = size_character (1, kind);
241627f7eb2Smrg   tree type = gfc_get_char_type (kind);
242627f7eb2Smrg 
243627f7eb2Smrg   gcc_assert (buffer_size >= size_character (length, kind));
244627f7eb2Smrg 
245627f7eb2Smrg   for (size_t i = 0; i < length; i++)
246627f7eb2Smrg     native_encode_expr (build_int_cst (type, string[i]), &buffer[i*elsize],
247627f7eb2Smrg 			elsize);
248627f7eb2Smrg 
249627f7eb2Smrg   return length;
250627f7eb2Smrg }
251627f7eb2Smrg 
252627f7eb2Smrg 
253627f7eb2Smrg static unsigned HOST_WIDE_INT
encode_derived(gfc_expr * source,unsigned char * buffer,size_t buffer_size)254627f7eb2Smrg encode_derived (gfc_expr *source, unsigned char *buffer, size_t buffer_size)
255627f7eb2Smrg {
256627f7eb2Smrg   gfc_constructor *c;
257627f7eb2Smrg   gfc_component *cmp;
258627f7eb2Smrg   int ptr;
259627f7eb2Smrg   tree type;
260627f7eb2Smrg   HOST_WIDE_INT size;
261627f7eb2Smrg 
262627f7eb2Smrg   type = gfc_typenode_for_spec (&source->ts);
263627f7eb2Smrg 
264627f7eb2Smrg   for (c = gfc_constructor_first (source->value.constructor),
265627f7eb2Smrg        cmp = source->ts.u.derived->components;
266627f7eb2Smrg        c;
267627f7eb2Smrg        c = gfc_constructor_next (c), cmp = cmp->next)
268627f7eb2Smrg     {
269627f7eb2Smrg       gcc_assert (cmp);
270627f7eb2Smrg       if (!c->expr)
271627f7eb2Smrg 	continue;
272627f7eb2Smrg       ptr = TREE_INT_CST_LOW(DECL_FIELD_OFFSET(cmp->backend_decl))
273627f7eb2Smrg 	    + TREE_INT_CST_LOW(DECL_FIELD_BIT_OFFSET(cmp->backend_decl))/8;
274627f7eb2Smrg 
275627f7eb2Smrg       if (c->expr->expr_type == EXPR_NULL)
276627f7eb2Smrg 	{
277627f7eb2Smrg 	  size = int_size_in_bytes (TREE_TYPE (cmp->backend_decl));
278627f7eb2Smrg 	  gcc_assert (size >= 0);
279627f7eb2Smrg 	  memset (&buffer[ptr], 0, size);
280627f7eb2Smrg 	}
281627f7eb2Smrg       else
282627f7eb2Smrg 	gfc_target_encode_expr (c->expr, &buffer[ptr],
283627f7eb2Smrg 				buffer_size - ptr);
284627f7eb2Smrg     }
285627f7eb2Smrg 
286627f7eb2Smrg   size = int_size_in_bytes (type);
287627f7eb2Smrg   gcc_assert (size >= 0);
288627f7eb2Smrg   return size;
289627f7eb2Smrg }
290627f7eb2Smrg 
291627f7eb2Smrg 
292627f7eb2Smrg /* Write a constant expression in binary form to a buffer.  */
293627f7eb2Smrg unsigned HOST_WIDE_INT
gfc_target_encode_expr(gfc_expr * source,unsigned char * buffer,size_t buffer_size)294627f7eb2Smrg gfc_target_encode_expr (gfc_expr *source, unsigned char *buffer,
295627f7eb2Smrg 			size_t buffer_size)
296627f7eb2Smrg {
297627f7eb2Smrg   if (source == NULL)
298627f7eb2Smrg     return 0;
299627f7eb2Smrg 
300627f7eb2Smrg   if (source->expr_type == EXPR_ARRAY)
301627f7eb2Smrg     return encode_array (source, buffer, buffer_size);
302627f7eb2Smrg 
303627f7eb2Smrg   gcc_assert (source->expr_type == EXPR_CONSTANT
304627f7eb2Smrg 	      || source->expr_type == EXPR_STRUCTURE
305627f7eb2Smrg 	      || source->expr_type == EXPR_SUBSTRING);
306627f7eb2Smrg 
307627f7eb2Smrg   /* If we already have a target-memory representation, we use that rather
308627f7eb2Smrg      than recreating one.  */
309627f7eb2Smrg   if (source->representation.string)
310627f7eb2Smrg     {
311627f7eb2Smrg       memcpy (buffer, source->representation.string,
312627f7eb2Smrg 	      source->representation.length);
313627f7eb2Smrg       return source->representation.length;
314627f7eb2Smrg     }
315627f7eb2Smrg 
316627f7eb2Smrg   switch (source->ts.type)
317627f7eb2Smrg     {
318627f7eb2Smrg     case BT_INTEGER:
319627f7eb2Smrg       return encode_integer (source->ts.kind, source->value.integer, buffer,
320627f7eb2Smrg 			     buffer_size);
321627f7eb2Smrg     case BT_REAL:
322627f7eb2Smrg       return encode_float (source->ts.kind, source->value.real, buffer,
323627f7eb2Smrg 			   buffer_size);
324627f7eb2Smrg     case BT_COMPLEX:
325627f7eb2Smrg       return encode_complex (source->ts.kind, source->value.complex,
326627f7eb2Smrg 			     buffer, buffer_size);
327627f7eb2Smrg     case BT_LOGICAL:
328627f7eb2Smrg       return encode_logical (source->ts.kind, source->value.logical, buffer,
329627f7eb2Smrg 			     buffer_size);
330627f7eb2Smrg     case BT_CHARACTER:
331627f7eb2Smrg       if (source->expr_type == EXPR_CONSTANT || source->ref == NULL)
332627f7eb2Smrg 	return gfc_encode_character (source->ts.kind,
333627f7eb2Smrg 				     source->value.character.length,
334627f7eb2Smrg 				     source->value.character.string,
335627f7eb2Smrg 				     buffer, buffer_size);
336627f7eb2Smrg       else
337627f7eb2Smrg 	{
338627f7eb2Smrg 	  HOST_WIDE_INT start, end;
339627f7eb2Smrg 
340627f7eb2Smrg 	  gcc_assert (source->expr_type == EXPR_SUBSTRING);
341627f7eb2Smrg 	  gfc_extract_hwi (source->ref->u.ss.start, &start);
342627f7eb2Smrg 	  gfc_extract_hwi (source->ref->u.ss.end, &end);
343627f7eb2Smrg 	  return gfc_encode_character (source->ts.kind, MAX(end - start + 1, 0),
344627f7eb2Smrg 				       &source->value.character.string[start-1],
345627f7eb2Smrg 				       buffer, buffer_size);
346627f7eb2Smrg 	}
347627f7eb2Smrg 
348627f7eb2Smrg     case BT_DERIVED:
349627f7eb2Smrg       if (source->ts.u.derived->ts.f90_type == BT_VOID)
350627f7eb2Smrg 	{
351627f7eb2Smrg 	  gfc_constructor *c;
352627f7eb2Smrg 	  gcc_assert (source->expr_type == EXPR_STRUCTURE);
353627f7eb2Smrg 	  c = gfc_constructor_first (source->value.constructor);
354627f7eb2Smrg 	  gcc_assert (c->expr->expr_type == EXPR_CONSTANT
355627f7eb2Smrg 		      && c->expr->ts.type == BT_INTEGER);
356627f7eb2Smrg 	  return encode_integer (gfc_index_integer_kind, c->expr->value.integer,
357627f7eb2Smrg 				 buffer, buffer_size);
358627f7eb2Smrg 	}
359627f7eb2Smrg 
360627f7eb2Smrg       return encode_derived (source, buffer, buffer_size);
361627f7eb2Smrg     default:
362627f7eb2Smrg       gfc_internal_error ("Invalid expression in gfc_target_encode_expr.");
363627f7eb2Smrg       return 0;
364627f7eb2Smrg     }
365627f7eb2Smrg }
366627f7eb2Smrg 
367627f7eb2Smrg 
368627f7eb2Smrg static size_t
interpret_array(unsigned char * buffer,size_t buffer_size,gfc_expr * result)369627f7eb2Smrg interpret_array (unsigned char *buffer, size_t buffer_size, gfc_expr *result)
370627f7eb2Smrg {
371627f7eb2Smrg   gfc_constructor_base base = NULL;
372627f7eb2Smrg   size_t array_size = 1;
373627f7eb2Smrg   size_t ptr = 0;
374627f7eb2Smrg 
375627f7eb2Smrg   /* Calculate array size from its shape and rank.  */
376627f7eb2Smrg   gcc_assert (result->rank > 0 && result->shape);
377627f7eb2Smrg 
378627f7eb2Smrg   for (int i = 0; i < result->rank; i++)
379627f7eb2Smrg     array_size *= mpz_get_ui (result->shape[i]);
380627f7eb2Smrg 
381627f7eb2Smrg   /* Iterate over array elements, producing constructors.  */
382627f7eb2Smrg   for (size_t i = 0; i < array_size; i++)
383627f7eb2Smrg     {
384627f7eb2Smrg       gfc_expr *e = gfc_get_constant_expr (result->ts.type, result->ts.kind,
385627f7eb2Smrg 					   &result->where);
386627f7eb2Smrg       e->ts = result->ts;
387627f7eb2Smrg 
388627f7eb2Smrg       if (e->ts.type == BT_CHARACTER)
389627f7eb2Smrg 	e->value.character.length = result->value.character.length;
390627f7eb2Smrg 
391627f7eb2Smrg       gfc_constructor_append_expr (&base, e, &result->where);
392627f7eb2Smrg 
393627f7eb2Smrg       ptr += gfc_target_interpret_expr (&buffer[ptr], buffer_size - ptr, e,
394627f7eb2Smrg 					true);
395627f7eb2Smrg     }
396627f7eb2Smrg 
397627f7eb2Smrg   result->value.constructor = base;
398627f7eb2Smrg   return ptr;
399627f7eb2Smrg }
400627f7eb2Smrg 
401627f7eb2Smrg 
402627f7eb2Smrg int
gfc_interpret_integer(int kind,unsigned char * buffer,size_t buffer_size,mpz_t integer)403627f7eb2Smrg gfc_interpret_integer (int kind, unsigned char *buffer, size_t buffer_size,
404627f7eb2Smrg 		   mpz_t integer)
405627f7eb2Smrg {
406627f7eb2Smrg   mpz_init (integer);
407627f7eb2Smrg   gfc_conv_tree_to_mpz (integer,
408627f7eb2Smrg 			native_interpret_expr (gfc_get_int_type (kind),
409627f7eb2Smrg 					       buffer, buffer_size));
410627f7eb2Smrg   return size_integer (kind);
411627f7eb2Smrg }
412627f7eb2Smrg 
413627f7eb2Smrg 
414627f7eb2Smrg int
gfc_interpret_float(int kind,unsigned char * buffer,size_t buffer_size,mpfr_t real)415627f7eb2Smrg gfc_interpret_float (int kind, unsigned char *buffer, size_t buffer_size,
416627f7eb2Smrg 		     mpfr_t real)
417627f7eb2Smrg {
418627f7eb2Smrg   gfc_set_model_kind (kind);
419627f7eb2Smrg   mpfr_init (real);
420627f7eb2Smrg   gfc_conv_tree_to_mpfr (real,
421627f7eb2Smrg 			 native_interpret_expr (gfc_get_real_type (kind),
422627f7eb2Smrg 						buffer, buffer_size));
423627f7eb2Smrg 
424627f7eb2Smrg   return size_float (kind);
425627f7eb2Smrg }
426627f7eb2Smrg 
427627f7eb2Smrg 
428627f7eb2Smrg int
gfc_interpret_complex(int kind,unsigned char * buffer,size_t buffer_size,mpc_t complex)429627f7eb2Smrg gfc_interpret_complex (int kind, unsigned char *buffer, size_t buffer_size,
430627f7eb2Smrg 		       mpc_t complex)
431627f7eb2Smrg {
432627f7eb2Smrg   int size;
433627f7eb2Smrg   size = gfc_interpret_float (kind, &buffer[0], buffer_size,
434627f7eb2Smrg 			      mpc_realref (complex));
435627f7eb2Smrg   size += gfc_interpret_float (kind, &buffer[size], buffer_size - size,
436627f7eb2Smrg 			       mpc_imagref (complex));
437627f7eb2Smrg   return size;
438627f7eb2Smrg }
439627f7eb2Smrg 
440627f7eb2Smrg 
441627f7eb2Smrg int
gfc_interpret_logical(int kind,unsigned char * buffer,size_t buffer_size,int * logical)442627f7eb2Smrg gfc_interpret_logical (int kind, unsigned char *buffer, size_t buffer_size,
443627f7eb2Smrg 		   int *logical)
444627f7eb2Smrg {
445627f7eb2Smrg   tree t = native_interpret_expr (gfc_get_logical_type (kind), buffer,
446627f7eb2Smrg 				  buffer_size);
447627f7eb2Smrg   *logical = wi::to_wide (t) == 0 ? 0 : 1;
448627f7eb2Smrg   return size_logical (kind);
449627f7eb2Smrg }
450627f7eb2Smrg 
451627f7eb2Smrg 
452627f7eb2Smrg size_t
gfc_interpret_character(unsigned char * buffer,size_t buffer_size,gfc_expr * result)453627f7eb2Smrg gfc_interpret_character (unsigned char *buffer, size_t buffer_size,
454627f7eb2Smrg 			 gfc_expr *result)
455627f7eb2Smrg {
456627f7eb2Smrg   if (result->ts.u.cl && result->ts.u.cl->length)
457627f7eb2Smrg     result->value.character.length =
458627f7eb2Smrg       gfc_mpz_get_hwi (result->ts.u.cl->length->value.integer);
459627f7eb2Smrg 
460627f7eb2Smrg   gcc_assert (buffer_size >= size_character (result->value.character.length,
461627f7eb2Smrg 					     result->ts.kind));
462627f7eb2Smrg   result->value.character.string =
463627f7eb2Smrg     gfc_get_wide_string (result->value.character.length + 1);
464627f7eb2Smrg 
465627f7eb2Smrg   if (result->ts.kind == gfc_default_character_kind)
466627f7eb2Smrg     for (size_t i = 0; i < (size_t) result->value.character.length; i++)
467627f7eb2Smrg       result->value.character.string[i] = (gfc_char_t) buffer[i];
468627f7eb2Smrg   else
469627f7eb2Smrg     {
470627f7eb2Smrg       mpz_t integer;
471627f7eb2Smrg       size_t bytes = size_character (1, result->ts.kind);
472627f7eb2Smrg       mpz_init (integer);
473627f7eb2Smrg       gcc_assert (bytes <= sizeof (unsigned long));
474627f7eb2Smrg 
475627f7eb2Smrg       for (size_t i = 0; i < (size_t) result->value.character.length; i++)
476627f7eb2Smrg 	{
477627f7eb2Smrg 	  gfc_conv_tree_to_mpz (integer,
478627f7eb2Smrg 	    native_interpret_expr (gfc_get_char_type (result->ts.kind),
479627f7eb2Smrg 				   &buffer[bytes*i], buffer_size-bytes*i));
480627f7eb2Smrg 	  result->value.character.string[i]
481627f7eb2Smrg 	    = (gfc_char_t) mpz_get_ui (integer);
482627f7eb2Smrg 	}
483627f7eb2Smrg 
484627f7eb2Smrg       mpz_clear (integer);
485627f7eb2Smrg     }
486627f7eb2Smrg 
487627f7eb2Smrg   result->value.character.string[result->value.character.length] = '\0';
488627f7eb2Smrg 
489*4c3eb207Smrg   return size_character (result->value.character.length, result->ts.kind);
490627f7eb2Smrg }
491627f7eb2Smrg 
492627f7eb2Smrg 
493627f7eb2Smrg int
gfc_interpret_derived(unsigned char * buffer,size_t buffer_size,gfc_expr * result)494627f7eb2Smrg gfc_interpret_derived (unsigned char *buffer, size_t buffer_size, gfc_expr *result)
495627f7eb2Smrg {
496627f7eb2Smrg   gfc_component *cmp;
497627f7eb2Smrg   int ptr;
498627f7eb2Smrg   tree type;
499627f7eb2Smrg 
500627f7eb2Smrg   /* The attributes of the derived type need to be bolted to the floor.  */
501627f7eb2Smrg   result->expr_type = EXPR_STRUCTURE;
502627f7eb2Smrg 
503627f7eb2Smrg   cmp = result->ts.u.derived->components;
504627f7eb2Smrg 
505627f7eb2Smrg   if (result->ts.u.derived->from_intmod == INTMOD_ISO_C_BINDING
506627f7eb2Smrg       && (result->ts.u.derived->intmod_sym_id == ISOCBINDING_PTR
507627f7eb2Smrg 	  || result->ts.u.derived->intmod_sym_id == ISOCBINDING_FUNPTR))
508627f7eb2Smrg     {
509627f7eb2Smrg       gfc_constructor *c;
510627f7eb2Smrg       gfc_expr *e;
511627f7eb2Smrg       /* Needed as gfc_typenode_for_spec as gfc_typenode_for_spec
512627f7eb2Smrg 	 sets this to BT_INTEGER.  */
513627f7eb2Smrg       result->ts.type = BT_DERIVED;
514627f7eb2Smrg       e = gfc_get_constant_expr (cmp->ts.type, cmp->ts.kind, &result->where);
515627f7eb2Smrg       c = gfc_constructor_append_expr (&result->value.constructor, e, NULL);
516627f7eb2Smrg       c->n.component = cmp;
517627f7eb2Smrg       gfc_target_interpret_expr (buffer, buffer_size, e, true);
518627f7eb2Smrg       e->ts.is_iso_c = 1;
519627f7eb2Smrg       return int_size_in_bytes (ptr_type_node);
520627f7eb2Smrg     }
521627f7eb2Smrg 
522627f7eb2Smrg   type = gfc_typenode_for_spec (&result->ts);
523627f7eb2Smrg 
524627f7eb2Smrg   /* Run through the derived type components.  */
525627f7eb2Smrg   for (;cmp; cmp = cmp->next)
526627f7eb2Smrg     {
527627f7eb2Smrg       gfc_constructor *c;
528627f7eb2Smrg       gfc_expr *e = gfc_get_constant_expr (cmp->ts.type, cmp->ts.kind,
529627f7eb2Smrg 					   &result->where);
530627f7eb2Smrg       e->ts = cmp->ts;
531627f7eb2Smrg 
532627f7eb2Smrg       /* Copy shape, if needed.  */
533627f7eb2Smrg       if (cmp->as && cmp->as->rank)
534627f7eb2Smrg 	{
535627f7eb2Smrg 	  int n;
536627f7eb2Smrg 
537*4c3eb207Smrg 	  if (cmp->as->type != AS_EXPLICIT)
538*4c3eb207Smrg 	    return 0;
539*4c3eb207Smrg 
540627f7eb2Smrg 	  e->expr_type = EXPR_ARRAY;
541627f7eb2Smrg 	  e->rank = cmp->as->rank;
542627f7eb2Smrg 
543627f7eb2Smrg 	  e->shape = gfc_get_shape (e->rank);
544627f7eb2Smrg 	  for (n = 0; n < e->rank; n++)
545627f7eb2Smrg 	     {
546627f7eb2Smrg 	       mpz_init_set_ui (e->shape[n], 1);
547627f7eb2Smrg 	       mpz_add (e->shape[n], e->shape[n],
548627f7eb2Smrg 			cmp->as->upper[n]->value.integer);
549627f7eb2Smrg 	       mpz_sub (e->shape[n], e->shape[n],
550627f7eb2Smrg 			cmp->as->lower[n]->value.integer);
551627f7eb2Smrg 	     }
552627f7eb2Smrg 	}
553627f7eb2Smrg 
554627f7eb2Smrg       c = gfc_constructor_append_expr (&result->value.constructor, e, NULL);
555627f7eb2Smrg 
556627f7eb2Smrg       /* The constructor points to the component.  */
557627f7eb2Smrg       c->n.component = cmp;
558627f7eb2Smrg 
559627f7eb2Smrg       /* Calculate the offset, which consists of the FIELD_OFFSET in
560627f7eb2Smrg 	 bytes, which appears in multiples of DECL_OFFSET_ALIGN-bit-sized,
561627f7eb2Smrg 	 and additional bits of FIELD_BIT_OFFSET. The code assumes that all
562627f7eb2Smrg 	 sizes of the components are multiples of BITS_PER_UNIT,
563627f7eb2Smrg 	 i.e. there are, e.g., no bit fields.  */
564627f7eb2Smrg 
565627f7eb2Smrg       gcc_assert (cmp->backend_decl);
566627f7eb2Smrg       ptr = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (cmp->backend_decl));
567627f7eb2Smrg       gcc_assert (ptr % 8 == 0);
568627f7eb2Smrg       ptr = ptr/8 + TREE_INT_CST_LOW (DECL_FIELD_OFFSET (cmp->backend_decl));
569627f7eb2Smrg 
570627f7eb2Smrg       gcc_assert (e->ts.type != BT_VOID || cmp->attr.caf_token);
571627f7eb2Smrg       gfc_target_interpret_expr (&buffer[ptr], buffer_size - ptr, e, true);
572627f7eb2Smrg     }
573627f7eb2Smrg 
574627f7eb2Smrg   return int_size_in_bytes (type);
575627f7eb2Smrg }
576627f7eb2Smrg 
577627f7eb2Smrg 
578627f7eb2Smrg /* Read a binary buffer to a constant expression.  */
579627f7eb2Smrg size_t
gfc_target_interpret_expr(unsigned char * buffer,size_t buffer_size,gfc_expr * result,bool convert_widechar)580627f7eb2Smrg gfc_target_interpret_expr (unsigned char *buffer, size_t buffer_size,
581627f7eb2Smrg 			   gfc_expr *result, bool convert_widechar)
582627f7eb2Smrg {
583627f7eb2Smrg   if (result->expr_type == EXPR_ARRAY)
584627f7eb2Smrg     return interpret_array (buffer, buffer_size, result);
585627f7eb2Smrg 
586627f7eb2Smrg   switch (result->ts.type)
587627f7eb2Smrg     {
588627f7eb2Smrg     case BT_INTEGER:
589627f7eb2Smrg       result->representation.length =
590627f7eb2Smrg         gfc_interpret_integer (result->ts.kind, buffer, buffer_size,
591627f7eb2Smrg 			       result->value.integer);
592627f7eb2Smrg       break;
593627f7eb2Smrg 
594627f7eb2Smrg     case BT_REAL:
595627f7eb2Smrg       result->representation.length =
596627f7eb2Smrg         gfc_interpret_float (result->ts.kind, buffer, buffer_size,
597627f7eb2Smrg     			     result->value.real);
598627f7eb2Smrg       break;
599627f7eb2Smrg 
600627f7eb2Smrg     case BT_COMPLEX:
601627f7eb2Smrg       result->representation.length =
602627f7eb2Smrg         gfc_interpret_complex (result->ts.kind, buffer, buffer_size,
603627f7eb2Smrg 			       result->value.complex);
604627f7eb2Smrg       break;
605627f7eb2Smrg 
606627f7eb2Smrg     case BT_LOGICAL:
607627f7eb2Smrg       result->representation.length =
608627f7eb2Smrg         gfc_interpret_logical (result->ts.kind, buffer, buffer_size,
609627f7eb2Smrg 			       &result->value.logical);
610627f7eb2Smrg       break;
611627f7eb2Smrg 
612627f7eb2Smrg     case BT_CHARACTER:
613627f7eb2Smrg       result->representation.length =
614627f7eb2Smrg         gfc_interpret_character (buffer, buffer_size, result);
615627f7eb2Smrg       break;
616627f7eb2Smrg 
617627f7eb2Smrg     case BT_CLASS:
618627f7eb2Smrg       result->ts = CLASS_DATA (result)->ts;
619627f7eb2Smrg       /* Fall through.  */
620627f7eb2Smrg     case BT_DERIVED:
621627f7eb2Smrg       result->representation.length =
622627f7eb2Smrg         gfc_interpret_derived (buffer, buffer_size, result);
623627f7eb2Smrg       gcc_assert (result->representation.length >= 0);
624627f7eb2Smrg       break;
625627f7eb2Smrg 
626627f7eb2Smrg     case BT_VOID:
627627f7eb2Smrg       /* This deals with caf_tokens.  */
628627f7eb2Smrg       result->representation.length =
629627f7eb2Smrg         gfc_interpret_integer (result->ts.kind, buffer, buffer_size,
630627f7eb2Smrg 			       result->value.integer);
631627f7eb2Smrg       break;
632627f7eb2Smrg 
633627f7eb2Smrg     default:
634627f7eb2Smrg       gfc_internal_error ("Invalid expression in gfc_target_interpret_expr.");
635627f7eb2Smrg       break;
636627f7eb2Smrg     }
637627f7eb2Smrg 
638627f7eb2Smrg   if (result->ts.type == BT_CHARACTER && convert_widechar)
639627f7eb2Smrg     result->representation.string
640627f7eb2Smrg       = gfc_widechar_to_char (result->value.character.string,
641627f7eb2Smrg 			      result->value.character.length);
642627f7eb2Smrg   else
643627f7eb2Smrg     {
644627f7eb2Smrg       result->representation.string =
645627f7eb2Smrg         XCNEWVEC (char, result->representation.length + 1);
646627f7eb2Smrg       memcpy (result->representation.string, buffer,
647627f7eb2Smrg 	      result->representation.length);
648627f7eb2Smrg       result->representation.string[result->representation.length] = '\0';
649627f7eb2Smrg     }
650627f7eb2Smrg 
651627f7eb2Smrg   return result->representation.length;
652627f7eb2Smrg }
653627f7eb2Smrg 
654627f7eb2Smrg 
655627f7eb2Smrg /* --------------------------------------------------------------- */
656627f7eb2Smrg /* Two functions used by trans-common.c to write overlapping
657627f7eb2Smrg    equivalence initializers to a buffer.  This is added to the union
658627f7eb2Smrg    and the original initializers freed.  */
659627f7eb2Smrg 
660627f7eb2Smrg 
661627f7eb2Smrg /* Writes the values of a constant expression to a char buffer. If another
662627f7eb2Smrg    unequal initializer has already been written to the buffer, this is an
663627f7eb2Smrg    error.  */
664627f7eb2Smrg 
665627f7eb2Smrg static size_t
expr_to_char(gfc_expr * e,locus * loc,unsigned char * data,unsigned char * chk,size_t len)666627f7eb2Smrg expr_to_char (gfc_expr *e, locus *loc,
667627f7eb2Smrg 	      unsigned char *data, unsigned char *chk, size_t len)
668627f7eb2Smrg {
669627f7eb2Smrg   int i;
670627f7eb2Smrg   int ptr;
671627f7eb2Smrg   gfc_constructor *c;
672627f7eb2Smrg   gfc_component *cmp;
673627f7eb2Smrg   unsigned char *buffer;
674627f7eb2Smrg 
675627f7eb2Smrg   if (e == NULL)
676627f7eb2Smrg     return 0;
677627f7eb2Smrg 
678627f7eb2Smrg   /* Take a derived type, one component at a time, using the offsets from the backend
679627f7eb2Smrg      declaration.  */
680627f7eb2Smrg   if (e->ts.type == BT_DERIVED)
681627f7eb2Smrg     {
682627f7eb2Smrg       for (c = gfc_constructor_first (e->value.constructor),
683627f7eb2Smrg 	   cmp = e->ts.u.derived->components;
684627f7eb2Smrg 	   c; c = gfc_constructor_next (c), cmp = cmp->next)
685627f7eb2Smrg 	{
686627f7eb2Smrg 	  gcc_assert (cmp && cmp->backend_decl);
687627f7eb2Smrg 	  if (!c->expr)
688627f7eb2Smrg 	    continue;
689627f7eb2Smrg 	  ptr = TREE_INT_CST_LOW(DECL_FIELD_OFFSET(cmp->backend_decl))
690627f7eb2Smrg 	    + TREE_INT_CST_LOW(DECL_FIELD_BIT_OFFSET(cmp->backend_decl))/8;
691627f7eb2Smrg 	  expr_to_char (c->expr, loc, &data[ptr], &chk[ptr], len);
692627f7eb2Smrg 	}
693627f7eb2Smrg       return len;
694627f7eb2Smrg     }
695627f7eb2Smrg 
696627f7eb2Smrg   /* Otherwise, use the target-memory machinery to write a bitwise image, appropriate
697627f7eb2Smrg      to the target, in a buffer and check off the initialized part of the buffer.  */
698627f7eb2Smrg   gfc_target_expr_size (e, &len);
699627f7eb2Smrg   buffer = (unsigned char*)alloca (len);
700627f7eb2Smrg   len = gfc_target_encode_expr (e, buffer, len);
701627f7eb2Smrg 
702627f7eb2Smrg   for (i = 0; i < (int)len; i++)
703627f7eb2Smrg     {
704627f7eb2Smrg       if (chk[i] && (buffer[i] != data[i]))
705627f7eb2Smrg 	{
706627f7eb2Smrg 	  if (loc)
707627f7eb2Smrg 	    gfc_error ("Overlapping unequal initializers in EQUIVALENCE "
708627f7eb2Smrg 			"at %L", loc);
709627f7eb2Smrg 	  else
710627f7eb2Smrg 	    gfc_error ("Overlapping unequal initializers in EQUIVALENCE "
711627f7eb2Smrg 			"at %C");
712627f7eb2Smrg 	  return 0;
713627f7eb2Smrg 	}
714627f7eb2Smrg       chk[i] = 0xFF;
715627f7eb2Smrg     }
716627f7eb2Smrg 
717627f7eb2Smrg   memcpy (data, buffer, len);
718627f7eb2Smrg   return len;
719627f7eb2Smrg }
720627f7eb2Smrg 
721627f7eb2Smrg 
722627f7eb2Smrg /* Writes the values from the equivalence initializers to a char* array
723627f7eb2Smrg    that will be written to the constructor to make the initializer for
724627f7eb2Smrg    the union declaration.  */
725627f7eb2Smrg 
726627f7eb2Smrg size_t
gfc_merge_initializers(gfc_typespec ts,gfc_expr * e,locus * loc,unsigned char * data,unsigned char * chk,size_t length)727627f7eb2Smrg gfc_merge_initializers (gfc_typespec ts, gfc_expr *e, locus *loc,
728627f7eb2Smrg 			unsigned char *data,
729627f7eb2Smrg 			unsigned char *chk, size_t length)
730627f7eb2Smrg {
731627f7eb2Smrg   size_t len = 0;
732627f7eb2Smrg   gfc_constructor * c;
733627f7eb2Smrg 
734627f7eb2Smrg   switch (e->expr_type)
735627f7eb2Smrg     {
736627f7eb2Smrg     case EXPR_CONSTANT:
737627f7eb2Smrg     case EXPR_STRUCTURE:
738627f7eb2Smrg       len = expr_to_char (e, loc, &data[0], &chk[0], length);
739627f7eb2Smrg       break;
740627f7eb2Smrg 
741627f7eb2Smrg     case EXPR_ARRAY:
742627f7eb2Smrg       for (c = gfc_constructor_first (e->value.constructor);
743627f7eb2Smrg 	   c; c = gfc_constructor_next (c))
744627f7eb2Smrg 	{
745627f7eb2Smrg 	  size_t elt_size;
746627f7eb2Smrg 
747627f7eb2Smrg 	  gfc_target_expr_size (c->expr, &elt_size);
748627f7eb2Smrg 
749627f7eb2Smrg 	  if (mpz_cmp_si (c->offset, 0) != 0)
750627f7eb2Smrg 	    len = elt_size * (size_t)mpz_get_si (c->offset);
751627f7eb2Smrg 
752627f7eb2Smrg 	  len = len + gfc_merge_initializers (ts, c->expr, loc, &data[len],
753627f7eb2Smrg 					      &chk[len], length - len);
754627f7eb2Smrg 	}
755627f7eb2Smrg       break;
756627f7eb2Smrg 
757627f7eb2Smrg     default:
758627f7eb2Smrg       return 0;
759627f7eb2Smrg     }
760627f7eb2Smrg 
761627f7eb2Smrg   return len;
762627f7eb2Smrg }
763627f7eb2Smrg 
764627f7eb2Smrg 
765627f7eb2Smrg /* Transfer the bitpattern of a (integer) BOZ to real or complex variables.
766627f7eb2Smrg    When successful, no BOZ or nothing to do, true is returned.  */
767627f7eb2Smrg 
768627f7eb2Smrg bool
gfc_convert_boz(gfc_expr * expr,gfc_typespec * ts)769627f7eb2Smrg gfc_convert_boz (gfc_expr *expr, gfc_typespec *ts)
770627f7eb2Smrg {
771627f7eb2Smrg   size_t buffer_size, boz_bit_size, ts_bit_size;
772627f7eb2Smrg   int index;
773627f7eb2Smrg   unsigned char *buffer;
774627f7eb2Smrg 
775*4c3eb207Smrg   if (expr->ts.type != BT_INTEGER)
776627f7eb2Smrg     return true;
777627f7eb2Smrg 
778627f7eb2Smrg   /* Don't convert BOZ to logical, character, derived etc.  */
779*4c3eb207Smrg   gcc_assert (ts->type == BT_REAL);
780*4c3eb207Smrg 
781627f7eb2Smrg   buffer_size = size_float (ts->kind);
782627f7eb2Smrg   ts_bit_size = buffer_size * 8;
783627f7eb2Smrg 
784627f7eb2Smrg   /* Convert BOZ to the smallest possible integer kind.  */
785627f7eb2Smrg   boz_bit_size = mpz_sizeinbase (expr->value.integer, 2);
786627f7eb2Smrg 
787*4c3eb207Smrg   gcc_assert (boz_bit_size <= ts_bit_size);
788627f7eb2Smrg 
789627f7eb2Smrg   for (index = 0; gfc_integer_kinds[index].kind != 0; ++index)
790627f7eb2Smrg     if ((unsigned) gfc_integer_kinds[index].bit_size >= ts_bit_size)
791627f7eb2Smrg       break;
792627f7eb2Smrg 
793627f7eb2Smrg   expr->ts.kind = gfc_integer_kinds[index].kind;
794627f7eb2Smrg   buffer_size = MAX (buffer_size, size_integer (expr->ts.kind));
795627f7eb2Smrg 
796627f7eb2Smrg   buffer = (unsigned char*)alloca (buffer_size);
797627f7eb2Smrg   encode_integer (expr->ts.kind, expr->value.integer, buffer, buffer_size);
798627f7eb2Smrg   mpz_clear (expr->value.integer);
799627f7eb2Smrg 
800627f7eb2Smrg   mpfr_init (expr->value.real);
801627f7eb2Smrg   gfc_interpret_float (ts->kind, buffer, buffer_size, expr->value.real);
802*4c3eb207Smrg 
803627f7eb2Smrg   expr->ts.type = ts->type;
804627f7eb2Smrg   expr->ts.kind = ts->kind;
805627f7eb2Smrg 
806627f7eb2Smrg   return true;
807627f7eb2Smrg }
808