1 /*
2 * Handle initialisation
3 */
4
5 #include "ccdefs.h"
6
7 static void output_double_string_load(double value);
8 static int init(Type *type, int dump);
9 static int agg_init(Type *type, int isflexible);
10
11
12 /*
13 * initialise global object
14 */
initials(const char * dropname,Type * type)15 int initials(const char *dropname, Type *type)
16 {
17 int desize = 0;
18 gltptr = 0;
19 glblab = getlabel();
20
21 // We can only use rodata_compile (i.e. ROM if double string isn't enabled)
22 if ( (type->isconst && !c_double_strings) ||
23 ( (ispointer(type) || type->kind == KIND_ARRAY) &&
24 (type->ptr->isconst || ((ispointer(type->ptr) || type->ptr->kind == KIND_ARRAY) && type->ptr->ptr->isconst) ) ) ) {
25 gen_switch_section(get_section_name(type->namespace,c_rodata_section));
26 } else {
27 gen_switch_section(get_section_name(type->namespace,c_data_section));
28 }
29 prefix();
30 outname(dropname, YES);
31 col();
32 nl();
33
34 if (cmatch('{')) {
35 if ( type->kind == KIND_STRUCT || ( type->kind == KIND_PTR && type->ptr->kind == KIND_STRUCT)) {
36 if ( type->kind == KIND_PTR ) {
37 point();
38 }
39 desize = str_init(type->kind == KIND_STRUCT ? type->tag : type->ptr);
40 } else {
41 // Aggregate initialiser
42 desize = agg_init(type, 0);
43 }
44 needchar('}');
45 } else {
46 // Initialise a single one
47 desize = init(type, 1);
48 }
49
50 gen_switch_section(c_code_section);
51 return (desize);
52 }
53
add_bitfield(Type * bitfield,int * value)54 static void add_bitfield(Type *bitfield, int *value)
55 {
56 Kind valtype;
57 double cvalue;
58
59 if (constexpr(&cvalue, &valtype, 0)) {
60 int ival = ((int)cvalue & (( 1 << bitfield->bit_size) - 1)) << bitfield->bit_offset;
61 check_assign_range(bitfield, cvalue);
62 *value |= ival;
63 } else {
64 errorfmt("Expected a constant value for bitfield assignment", 1);
65 }
66 }
67
68 /*
69 * initialise structure (also called by init())
70 *
71 * Pads out to the size of the structure
72 */
str_init(Type * tag)73 int str_init(Type *tag)
74 {
75 int sz = 0;
76 Type *ptr;
77 int i;
78 int last_offset = -1;
79 int num_fields = tag->isstruct ? array_len(tag->fields) : 1;
80 int bitfield_value = 0;
81 int had_bitfield = 0;
82
83 for ( i = 0; i < num_fields; i++ ) {
84 ptr = array_get_byindex(tag->fields,i);
85
86 if ( rcmatch('}')) {
87 break;
88 }
89 if ( i != 0 ) needchar(',');
90
91
92 if ( ptr->offset == last_offset ) {
93 add_bitfield(ptr, &bitfield_value);
94 had_bitfield += ptr->bit_size;
95 continue;
96 } else if ( had_bitfield ) {
97 sz = ptr->offset;
98 // We've finished a byte/word of bitfield, we should dump it
99 outfmt("\t%s\t0x%x\n", had_bitfield <= 8 ? "defb" : "defw", bitfield_value);
100 had_bitfield = 0;
101 bitfield_value = 0;
102 }
103
104 if ( ptr->bit_size ) {
105 sz = ptr->offset;
106 last_offset = ptr->offset;
107 had_bitfield = ptr->bit_size;
108 add_bitfield(ptr, &bitfield_value);
109 continue;
110 }
111
112 last_offset = ptr->offset;
113
114 sz += ptr->size == -1 ? 0 : ptr->size;
115 if ( ptr->kind == KIND_STRUCT ) {
116 needchar('{');
117 str_init(ptr->tag);
118 needchar('}');
119 } else if ( ( ptr->kind == KIND_ARRAY && ptr->ptr->kind != KIND_CHAR ) ) {
120 needchar('{');
121 agg_init(ptr, ptr->size == -1 && i == num_fields - 1);
122 needchar('}');
123 } else if ( ptr->kind == KIND_ARRAY && ptr->ptr->kind == KIND_CHAR ) {
124 if ( rcmatch('{')) {
125 needchar('{');
126 agg_init(ptr,0);
127 needchar('}');
128 } else {
129 init(ptr,1);
130 }
131 } else {
132 init(ptr,1);
133 }
134 }
135 swallow(",");
136
137 // And output
138 if ( had_bitfield ) {
139 // We've finished a struct initialisation with a bitfield
140 outfmt("\t%s\t0x%x\n", had_bitfield <= 8 ? "defb" : "defw", bitfield_value);
141 sz += ((had_bitfield-1) / 8) + 1;
142 }
143
144 // Pad out the union
145 if ( sz < tag->size) {
146 defstorage();
147 outdec(tag->size - sz);
148 nl();
149 }
150 return tag->size;
151 }
152
153
154 /*
155 * initialise aggregate
156 */
agg_init(Type * type,int isflexible)157 int agg_init(Type *type, int isflexible)
158 {
159 int done = 0;
160 int dim = type->len;
161 int size = 0;
162
163 while (dim) {
164 if ( type->kind == KIND_ARRAY && type->ptr->kind == KIND_STRUCT ) {
165 /* array of struct */
166 if ( done == 0 ) {
167 needchar('{');
168 } else if ( cmatch('{') == 0 ) {
169 break;
170 }
171 size += str_init(type->ptr->tag);
172 dim--;
173 needchar('}');
174 } else if ( type->ptr && type->ptr->kind == KIND_ARRAY) {
175 if ( type->ptr->ptr->kind != KIND_CHAR ) {
176 needchar('{');
177 size += agg_init(type->ptr, isflexible);
178 needchar('}');
179 } else {
180 char needbrace = 0;
181 if ( cmatch('{') )
182 needbrace = 1;
183 if ( rcmatch('"') )
184 size += init(type->ptr,1);
185 else
186 size += agg_init(type->ptr, isflexible);
187 if ( needbrace ) needchar('}');
188 }
189 } else {
190 char needbrace = 0;
191 if ( cmatch('{') )
192 needbrace = 1;
193 if ( type->kind == KIND_ARRAY && type->ptr->kind == KIND_CHAR && rcmatch('"')) {
194 size += init(type,1);
195 } else {
196 size += init(type->ptr,1);
197 }
198 if ( needbrace ) needchar('}');
199 }
200 done++;
201 if (cmatch(',') == 0)
202 break;
203 blanks();
204 }
205 if ( type->len != -1 ) {
206 size += dumpzero(1, type->size - size);
207 } else if ( !isflexible ) {
208 type->size = size;
209 type->len = size / type->ptr->size;
210 }
211 return size;
212 }
213
214 /*
215 * evaluate one initialiser
216 *
217 * if dump is TRUE, dump literal immediately
218 * save character string in litq to dump later
219 * this is used for structures and arrays of pointers to char, so that the
220 * struct or array is built immediately and the char strings are dumped later
221 */
init(Type * type,int dump)222 static int init(Type *type, int dump)
223 {
224 double value;
225 Kind valtype;
226 int sz = 0; /* number of chars in queue */
227
228 if ((sz = qstr(&value)) != -1) {
229 sz++;
230 if ( type->kind == KIND_ARRAY ) {
231 /* Dump the literals where they are, padding out as appropriate */
232 if (type->len != -1 && sz > type->len) {
233 /* Ooops, initialised to long a string! */
234 warningfmt("overlong-initialization","Initialisation too long, truncating!");
235 sz = type->len;
236 gltptr = sz;
237 *(glbq + sz - 1) = '\0'; /* Terminate string */
238 }
239 dumplits(type->ptr->kind == KIND_CHAR ? 0 : type->ptr->size, NO, gltptr, glblab, glbq);
240 gltptr = 0;
241 if ( type->len != -1 ) {
242 dumpzero(type->size/ type->len, type->len - sz);
243 return type->size;
244 }
245 type->size = sz;
246 type->len = sz;
247 return sz;
248 } else {
249 int32_t ivalue = value;
250 /* Store the literals in the queue! */
251 storeq(sz, glbq, &ivalue);
252 gltptr = 0;
253 defword();
254 printlabel(litlab);
255 outbyte('+');
256 outdec(ivalue);
257 nl();
258 return 2;
259 }
260 } else {
261 /* djm, catch label names in structures (for (*name)() initialisation */
262 char sname[NAMESIZE];
263 SYMBOL *ptr;
264 int gotref = cmatch('&');
265 if (symname(sname) && strcmp(sname, "sizeof") != 0) { /* We have got something.. */
266 if ((ptr = findglb(sname))) {
267 Type *ptype = ptr->ctype;
268
269 /* Actually found sommat..very good! */
270 if ( ispointer(type)|| type->kind == KIND_ARRAY ) {
271 int offset = 0;
272
273 if ( rcmatch('[')) {
274 if ( gotref == 0 ) {
275 errorfmt("Initialiser element is not a compile-time constant",1);
276 }
277 while ( rcmatch('[')) {
278 if ( ispointer(ptype) || ptype->kind == KIND_ARRAY) {
279 double val;
280 Kind valtype;
281 needchar('[');
282 constexpr(&val, &valtype, 1);
283 needchar(']');
284 offset += ( ptype->size / ptype->len) * val;
285 ptype = ptype->ptr;
286 } else {
287 errorfmt("Cannot subscript a non-pointer", 1);
288 break;
289 }
290 }
291 } else if ( cmatch('+') ) {
292 if ( constexpr(&value, &valtype, 1) ) {
293 offset = value;
294 }
295 } else if ( cmatch('-') ) {
296 if ( constexpr(&value, &valtype, 1) ) {
297 offset = value * -1;
298 }
299 }
300 defword();
301 outname(ptr->name, dopref(ptr));
302 outfmt(" + %d",offset);
303 nl();
304 if ( type->isfar ) {
305 defbyte(); outdec(0); nl();
306 }
307 } else if (ptr->type == KIND_ENUM) {
308 value = ptr->size;
309 goto constdecl;
310 } else {
311 errorfmt("Dodgy declaration (not pointer)", 0);
312 junk();
313 }
314 } else {
315 errorfmt("Unknown symbol: %s", 1, sname);
316 junk();
317 }
318 } else if (rcmatch('}')) {
319 #if 0
320 dumpzero(size,*dim);
321 #endif
322 return 0;
323 } else if (constexpr(&value, &valtype, 1)) {
324 constdecl:
325 check_assign_range(type, value);
326 if (dump) {
327 /* struct member or array of pointer to char */
328 if ( type->kind == KIND_DOUBLE ) {
329 unsigned char fa[MAX_MANTISSA_SIZE+1];
330 int i;
331 /* It was a float, lets parse the float and then dump it */
332 if ( c_double_strings ) {
333 output_double_string_load(value);
334 } else {
335 dofloat(c_maths_mode,value, fa);
336 defbyte();
337 for ( i = 0; i < c_fp_size; i++ ) {
338 if ( i ) outbyte(',');
339 outdec(fa[i]);
340 }
341 }
342 } else if (type->kind == KIND_FLOAT16) {
343 unsigned char fa[MAX_MANTISSA_SIZE+1];
344 dofloat(MATHS_IEEE16, value, fa);
345 defword();
346 outdec(fa[1] << 8 | fa[0]);
347 } else if (type->kind == KIND_LONGLONG ){
348 uint32_t val = (uint32_t)((int64_t)value & 0xffffffff);
349 /* there appears to be a bug in z80asm regarding defq */
350 defbyte();
351 outdec(((uint32_t)val % 65536UL) % 256);
352 outbyte(',');
353 outdec(((uint32_t)val % 65536UL) / 256);
354 outbyte(',');
355 outdec(((uint32_t)val / 65536UL) % 256);
356 outbyte(',');
357 outdec(((uint32_t)val / 65536UL) / 256);
358 nl();
359 val = (uint32_t)(((int64_t)value >> 32) & 0xffffffff);
360 defbyte();
361 outdec(((uint32_t)val % 65536UL) % 256);
362 outbyte(',');
363 outdec(((uint32_t)val % 65536UL) / 256);
364 outbyte(',');
365 outdec(((uint32_t)val / 65536UL) % 256);
366 outbyte(',');
367 outdec(((uint32_t)val / 65536UL) / 256);
368 } else if (type->kind == KIND_LONG ){
369 uint32_t val = (int32_t)(int64_t)value;
370 /* there appears to be a bug in z80asm regarding defq */
371 defbyte();
372 outdec(((uint32_t)val % 65536UL) % 256);
373 outbyte(',');
374 outdec(((uint32_t)val % 65536UL) / 256);
375 outbyte(',');
376 outdec(((uint32_t)val / 65536UL) % 256);
377 outbyte(',');
378 outdec(((uint32_t)val / 65536UL) / 256);
379 } else if (type->kind == KIND_CPTR) {
380 uint32_t val = (int32_t)(int64_t)value;
381 defbyte();
382 outdec(((uint32_t)val % 65536UL) % 256);
383 outbyte(',');
384 outdec(((uint32_t)val % 65536UL) / 256);
385 outbyte(',');
386 outdec(((uint32_t)val / 65536UL) % 256);
387 } else {
388 if (type->kind == KIND_CHAR )
389 defbyte();
390 else
391 defword();
392 outdec(value);
393 }
394 nl();
395 /* Dump out a train of zeros as appropriate */
396 // if (ident == ID_ARRAY && more == 0) {
397 // dumpzero(size, (dim) - 1);
398 // }
399
400 } else {
401 if ( type->kind == KIND_DOUBLE ) {
402 unsigned char fa[6];
403 int i;
404
405 /* It was a float, lets parse the float and then dump it */
406 if ( c_double_strings ) {
407 output_double_string_load(value);
408 } else {
409 dofloat(c_maths_mode,value, fa);
410 for ( i = 0; i < c_fp_size; i++ ) {
411 stowlit(fa[i], 1);
412 }
413 }
414 } else {
415 stowlit(value, type->size);
416 }
417 }
418 } else {
419 return 0; // Nothing parsed
420 }
421 }
422 return type->size;
423 }
424
425
output_double_string_load(double value)426 static void output_double_string_load(double value)
427 {
428 int dumplocation = getlabel();
429 LVALUE lval;
430
431 lval.val_type = KIND_DOUBLE;
432
433 postlabel(dumplocation);
434 defstorage(); outdec(6); nl();
435
436 gen_switch_section(c_init_section);
437 lval.const_val = value;
438 lval.val_type = KIND_DOUBLE;
439 lval.ltype = type_double;
440 load_constant(&lval);
441 immedlit(dumplocation,0); nl();
442 callrts("dstore");
443 gen_switch_section(c_data_section);
444 }
445