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