File: m2-type-size.c

package info (click to toggle)
m2c 0.6-10
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 2,156 kB
  • ctags: 1,908
  • sloc: ansic: 18,136; sh: 1,561; makefile: 48
file content (284 lines) | stat: -rw-r--r-- 8,007 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
/* Functions for tunning on memory allocation of the used C translator.
   Copyright (C) 1993-1997 (see more details in file COPYING).

   This file is part of Modula-2 translator.  */

#include "m2-common.h"


#define MIN(a,b)  ((a)<(b) ? (a) : (b))

static void get_record_case_part_size_and_alignment ();

/* Round up V so that it will be multiple of D.  Return the result. */

static Tcard
round_up (v, d)
     register Tcard v;
     register int d;
{
  return (v % d == 0 ? v : v + (d - v % d));
}

/* Return span (number of the elements -1) of values of array index type
   INDEX_TYPE_PTR. */

Tcard
array_index_span (index_type_ptr)
     register ICN_pointer index_type_ptr;
{
  register ICN_pointer range_min_ptr, range_max_ptr;
  enum icode_node_mode mode;

  range_min_ptr = min_or_max (index_type_ptr, TRUE);
  range_max_ptr = min_or_max (index_type_ptr, FALSE);
  if (range_min_ptr != NULL && range_max_ptr != NULL)
    {
      mode = MODE (range_min_ptr);
      if (mode == ICNM_CARDINAL)
	return (CARDINAL_NODE (range_max_ptr)->cardinal_value
		- CARDINAL_NODE (range_min_ptr)->cardinal_value);
      else if (mode == ICNM_INTEGER)
	return (INTEGER_NODE (range_min_ptr)->integer_value < 0
		&& INTEGER_NODE (range_max_ptr)->integer_value > 0
		? ((Tcard) INTEGER_NODE (range_max_ptr)->integer_value
		   + (Tcard) - INTEGER_NODE (range_min_ptr)->integer_value)
		: (INTEGER_NODE (range_max_ptr)->integer_value
		   - INTEGER_NODE (range_min_ptr)->integer_value));
    }
  return 0;
}

/* The following function makes more precise size and alignment of type given
   as TYPE_PTR after standard method of size and alignment calculation.
   Input and output values are passed through parameters SIZE and ALIGN. */

static void
make_more_precise_size_and_align (type_ptr, size, align)
     register ICN_pointer type_ptr;
{
  register enum icode_node_mode mode;

  if (type_ptr == NULL)
    return;
  mode = MODE (type_ptr);
#ifdef MAKING_MORE_PRECISE_SIZE_BY_TYPE_MODE
  *size = MAKING_MORE_PRECISE_SIZE_BY_TYPE_MODE (*size, mode);
#endif

#ifdef MAKING_MORE_PRECISE_SIZE_BY_TYPE
  *size = MAKING_MORE_PRECISE_SIZE_BY_TYPE (*size, type_ptr);
#endif

#ifdef MAKING_MORE_PRECISE_ALIGN_BY_TYPE_MODE
  *align = MAKING_MORE_PRECISE_ALIGN_BY_TYPE_MODE (*align, mode);
#endif

#ifdef MAKING_MORE_PRECISE_ALIGN_BY_TYPE
  *align = MAKING_MORE_PRECISE_ALIGN_BY_TYPE (*align, type_ptr);
#endif

}

/* The following function processes current field list element (field or
   case part) given as CURRENT_ELEMENT_PTR and calculates current size and
   alignment of construction which contains this filed list. */

static ICN_pointer
process_field_or_case_part (current_element_ptr, current_size, current_align)
     register ICN_pointer current_element_ptr;
     register Tcard *current_size;
     register int *current_align;
{
  Tcard displacement;
  Tcard element_size;
  int element_align;
  ICN_pointer next_element_ptr;

  if (MODE (current_element_ptr) == ICNM_FIELD)
    {
      get_type_size_and_alignment
	(FIELD_NODE (current_element_ptr)->field_type, &element_size,
	 &element_align);
      next_element_ptr = FIELD_NODE (current_element_ptr)->next_field;
    }
  else
    {
      get_record_case_part_size_and_alignment (current_element_ptr,
					       &element_size, &element_align);
      next_element_ptr
	= RECORD_CASE_PART_NODE (current_element_ptr)
	->record_element_after_case_part;
    }
  displacement = round_up (*current_size, element_align);
  *current_size = (displacement) + element_size;
  if (*current_align < element_align)
    *current_align = element_align;
  return next_element_ptr;
}

/* The following function calculates size and alignment of case part
   (it is represented by union in C)given as CASE_PART_PTR and returns
   the results through parameters SIZE and ALIGN. */

static void
get_record_case_part_size_and_alignment (case_part_ptr, size, align)
     register ICN_pointer case_part_ptr;
     register Tcard *size;
     register int *align;
{
  ICN_pointer list_element_ptr, case_variant_ptr;
  Tcard variant_size;
  int variant_align;

  *size = 0;
  *align = 0;
  for (case_variant_ptr = (RECORD_CASE_PART_NODE (case_part_ptr)
			   ->record_case_variant_list);
       MODE (case_variant_ptr) == ICNM_RECORD_CASE_VARIANT;
       case_variant_ptr = (RECORD_CASE_VARIANT_NODE (case_variant_ptr)
			   ->next_case_variant))
    {
      variant_size = 0;
      variant_align = 0;
      for (list_element_ptr = (RECORD_CASE_VARIANT_NODE (case_variant_ptr)
			       ->case_variant_elements);
	   MODE (list_element_ptr) == ICNM_RECORD_CASE_PART
	   || MODE (list_element_ptr) == ICNM_FIELD;)
	list_element_ptr
	  = process_field_or_case_part (list_element_ptr,
					&variant_size, &variant_align);
      if (*size < variant_size)
	*size = variant_size;
      if (*align < variant_align)
	*align = variant_align;
    }
  make_more_precise_size_and_align (case_part_ptr, size, align);
}

/* Table of sizes of all Modula-2 basic type (except for string types).
   See order of basic types in file m2-icode.h. */

static char basic_type_size_table[] =
{				/*BTM_SHORT_CARDINAL - BTM_LONG_CARDINAL_OR_INTEGER*/
#ifdef MODULA_SHORT_IS_IMPLEMENTED_BY_C_CHAR
  sizeof (unsigned char),
#else
  sizeof (unsigned short),
#endif

  sizeof (unsigned int),

#ifdef MODULA_LONG_IS_IMPLEMENTED_BY_C_LONG
  sizeof (unsigned long),
#else
  sizeof (unsigned int),
#endif

#ifdef MODULA_SHORT_IS_IMPLEMENTED_BY_C_CHAR
  sizeof (char),
#else
  sizeof (short),
#endif

  sizeof (int),

#ifdef MODULA_LONG_IS_IMPLEMENTED_BY_C_LONG
  sizeof (long),
#else
  sizeof (int),
#endif

  sizeof (float), sizeof (float), sizeof (double),

#ifdef MODULA_CHAR_IS_IMPLEMENTED_BY_C_UNSIGNED_CHAR
  sizeof (unsigned char),
#else
  sizeof (char),
#endif

  BYTE_SIZE, sizeof (int), sizeof (int),

#ifdef MODULA_SHORT_IS_IMPLEMENTED_BY_C_CHAR
  sizeof (char),
#else
  sizeof (short),
#endif

  sizeof (int),

#ifdef MODULA_LONG_IS_IMPLEMENTED_BY_C_LONG
  sizeof (long),
#else
  sizeof (int)
#endif

};


/* The following function calculates size and alignment of type definition
   TYPE_PTR and returns the results through parameters SIZE and ALIGN. */

void
get_type_size_and_alignment (type_ptr, size, align)
     register ICN_pointer type_ptr;
     register Tcard *size;
     register int *align;
{
  enum icode_node_mode mode;
  int size_table_index;

  *size = 0;
  *align = 0;
  type_ptr = through_range_type (type_ptr);
  if (type_ptr != NULL)
    {
      mode = MODE (type_ptr);
      if (it_is_string_type (type_ptr))
	{
	  *size = (string_length_from_its_type (type_ptr)
		   * (Tcard) basic_type_size_table[(int) BTM_CHAR]);
	  *align = MIN (MAX_ALIGNMENT, basic_type_size_table[(int) BTM_CHAR]);
	}
      else
	{
	  if (mode == ICNM_SET_TYPE)
	    {
	      *size = SET_SIZE;
	      *align = MIN (MAX_ALIGNMENT, *size);
	    }
	  else if (mode == ICNM_ARRAY_TYPE)
	    {
	      get_type_size_and_alignment (ARRAY_TYPE_NODE (type_ptr)->base_type,
					   size, align);
	      *size *= (array_index_span
			(ARRAY_TYPE_NODE (type_ptr)->array_index_type)
			+ 1);
	    }
	  else if (mode == ICNM_RECORD)
	    {
	      for (type_ptr = RECORD_NODE (type_ptr)->record_element_list;
		   MODE (type_ptr) == ICNM_RECORD_CASE_PART
		   || MODE (type_ptr) == ICNM_FIELD;)
		type_ptr = process_field_or_case_part (type_ptr, size, align);
	      *size = round_up (*size, *align);
	    }
	  else if (mode == ICNM_ENUMERATION_TYPE)
	    get_type_size_and_alignment
	      (type_of_cardinal_value
	       (CARDINAL_NODE (min_or_max (type_ptr, FALSE))->cardinal_value),
	       size, align);
	  else
	    {
	      if (mode == ICNM_BASIC_TYPE)
		size_table_index = (int) BASIC_TYPE_NODE (type_ptr)->basic_type;
	      else
		/*ICNM_POINTER_TYPE, ICNM_QUALIFIED_EXPORT, ICNM_PROCEDURE_TYPE*/
		size_table_index = (int) BTM_NIL;
	      *size = basic_type_size_table[size_table_index];
	      *align = MIN (MAX_ALIGNMENT, *size);
	    }
	}
      make_more_precise_size_and_align (type_ptr, size, align);
    }
}