]> git.sur5r.net Git - cc65/blob - src/cc65/datatype.c
POKEY: Add register #defines & internal kybd codes
[cc65] / src / cc65 / datatype.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                datatype.c                                 */
4 /*                                                                           */
5 /*               Type string handling for the cc65 C compiler                */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2015, Ullrich von Bassewitz                                      */
10 /*                Roemerstrasse 52                                           */
11 /*                D-70794 Filderstadt                                        */
12 /* EMail:         uz@cc65.org                                                */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <string.h>
37
38 /* common */
39 #include "addrsize.h"
40 #include "check.h"
41 #include "mmodel.h"
42 #include "xmalloc.h"
43
44 /* cc65 */
45 #include "codegen.h"
46 #include "datatype.h"
47 #include "error.h"
48 #include "fp.h"
49 #include "funcdesc.h"
50 #include "global.h"
51 #include "symtab.h"
52
53
54
55 /*****************************************************************************/
56 /*                                   Data                                    */
57 /*****************************************************************************/
58
59
60
61 /* Predefined type strings */
62 Type type_schar[]       = { TYPE(T_SCHAR),  TYPE(T_END) };
63 Type type_uchar[]       = { TYPE(T_UCHAR),  TYPE(T_END) };
64 Type type_int[]         = { TYPE(T_INT),    TYPE(T_END) };
65 Type type_uint[]        = { TYPE(T_UINT),   TYPE(T_END) };
66 Type type_long[]        = { TYPE(T_LONG),   TYPE(T_END) };
67 Type type_ulong[]       = { TYPE(T_ULONG),  TYPE(T_END) };
68 Type type_void[]        = { TYPE(T_VOID),   TYPE(T_END) };
69 Type type_size_t[]      = { TYPE(T_SIZE_T), TYPE(T_END) };
70 Type type_float[]       = { TYPE(T_FLOAT),  TYPE(T_END) };
71 Type type_double[]      = { TYPE(T_DOUBLE), TYPE(T_END) };
72
73
74
75 /*****************************************************************************/
76 /*                                   Code                                    */
77 /*****************************************************************************/
78
79
80
81 unsigned TypeLen (const Type* T)
82 /* Return the length of the type string */
83 {
84     const Type* Start = T;
85     while (T->C != T_END) {
86         ++T;
87     }
88     return T - Start;
89 }
90
91
92
93 Type* TypeCopy (Type* Dest, const Type* Src)
94 /* Copy a type string */
95 {
96     Type* Orig = Dest;
97     while (1) {
98         *Dest = *Src;
99         if (Src->C == T_END) {
100             break;
101         }
102         Src++;
103         Dest++;
104     }
105     return Orig;
106 }
107
108
109
110 Type* TypeDup (const Type* T)
111 /* Create a copy of the given type on the heap */
112 {
113     unsigned Len = (TypeLen (T) + 1) * sizeof (Type);
114     return memcpy (xmalloc (Len), T, Len);
115 }
116
117
118
119 Type* TypeAlloc (unsigned Len)
120 /* Allocate memory for a type string of length Len. Len *must* include the
121 ** trailing T_END.
122 */
123 {
124     return xmalloc (Len * sizeof (Type));
125 }
126
127
128
129 void TypeFree (Type* T)
130 /* Free a type string */
131 {
132     xfree (T);
133 }
134
135
136
137 int SignExtendChar (int C)
138 /* Do correct sign extension of a character */
139 {
140     if (IS_Get (&SignedChars) && (C & 0x80) != 0) {
141         return C | ~0xFF;
142     } else {
143         return C & 0xFF;
144     }
145 }
146
147
148
149 TypeCode GetDefaultChar (void)
150 /* Return the default char type (signed/unsigned) depending on the settings */
151 {
152     return IS_Get (&SignedChars)? T_SCHAR : T_UCHAR;
153 }
154
155
156
157 Type* GetCharArrayType (unsigned Len)
158 /* Return the type for a char array of the given length */
159 {
160     /* Allocate memory for the type string */
161     Type* T = TypeAlloc (3);    /* array/char/terminator */
162
163     /* Fill the type string */
164     T[0].C   = T_ARRAY;
165     T[0].A.L = Len;             /* Array length is in the L attribute */
166     T[1].C   = GetDefaultChar ();
167     T[2].C   = T_END;
168
169     /* Return the new type */
170     return T;
171 }
172
173
174
175 Type* GetImplicitFuncType (void)
176 /* Return a type string for an inplicitly declared function */
177 {
178     /* Get a new function descriptor */
179     FuncDesc* F = NewFuncDesc ();
180
181     /* Allocate memory for the type string */
182     Type* T = TypeAlloc (3);    /* func/returns int/terminator */
183
184     /* Prepare the function descriptor */
185     F->Flags  = FD_EMPTY | FD_VARIADIC;
186     F->SymTab = &EmptySymTab;
187     F->TagTab = &EmptySymTab;
188
189     /* Fill the type string */
190     T[0].C   = T_FUNC | CodeAddrSizeQualifier ();
191     T[0].A.P = F;
192     T[1].C   = T_INT;
193     T[2].C   = T_END;
194
195     /* Return the new type */
196     return T;
197 }
198
199
200
201 Type* PointerTo (const Type* T)
202 /* Return a type string that is "pointer to T". The type string is allocated
203 ** on the heap and may be freed after use.
204 */
205 {
206     /* Get the size of the type string including the terminator */
207     unsigned Size = TypeLen (T) + 1;
208
209     /* Allocate the new type string */
210     Type* P = TypeAlloc (Size + 1);
211
212     /* Create the return type... */
213     P[0].C = T_PTR | (T[0].C & T_QUAL_ADDRSIZE);
214     memcpy (P+1, T, Size * sizeof (Type));
215
216     /* ...and return it */
217     return P;
218 }
219
220
221
222 static TypeCode PrintTypeComp (FILE* F, TypeCode C, TypeCode Mask, const char* Name)
223 /* Check for a specific component of the type. If it is there, print the
224 ** name and remove it. Return the type with the component removed.
225 */
226 {
227     if ((C & Mask) == Mask) {
228         fprintf (F, "%s ", Name);
229         C &= ~Mask;
230     }
231     return C;
232 }
233
234
235
236 void PrintType (FILE* F, const Type* T)
237 /* Output translation of type array. */
238 {
239     /* Walk over the type string */
240     while (T->C != T_END) {
241
242         /* Get the type code */
243         TypeCode C = T->C;
244
245         /* Print any qualifiers */
246         C = PrintTypeComp (F, C, T_QUAL_CONST, "const");
247         C = PrintTypeComp (F, C, T_QUAL_VOLATILE, "volatile");
248         C = PrintTypeComp (F, C, T_QUAL_RESTRICT, "restrict");
249         C = PrintTypeComp (F, C, T_QUAL_NEAR, "__near__");
250         C = PrintTypeComp (F, C, T_QUAL_FAR, "__far__");
251         C = PrintTypeComp (F, C, T_QUAL_FASTCALL, "__fastcall__");
252         C = PrintTypeComp (F, C, T_QUAL_CDECL, "__cdecl__");
253
254         /* Signedness. Omit the signedness specifier for long and int */
255         if ((C & T_MASK_TYPE) != T_TYPE_INT && (C & T_MASK_TYPE) != T_TYPE_LONG) {
256             C = PrintTypeComp (F, C, T_SIGN_SIGNED, "signed");
257         }
258         C = PrintTypeComp (F, C, T_SIGN_UNSIGNED, "unsigned");
259
260         /* Now check the real type */
261         switch (C & T_MASK_TYPE) {
262             case T_TYPE_CHAR:
263                 fprintf (F, "char");
264                 break;
265             case T_TYPE_SHORT:
266                 fprintf (F, "short");
267                 break;
268             case T_TYPE_INT:
269                 fprintf (F, "int");
270                 break;
271             case T_TYPE_LONG:
272                 fprintf (F, "long");
273                 break;
274             case T_TYPE_LONGLONG:
275                 fprintf (F, "long long");
276                 break;
277             case T_TYPE_FLOAT:
278                 fprintf (F, "float");
279                 break;
280             case T_TYPE_DOUBLE:
281                 fprintf (F, "double");
282                 break;
283             case T_TYPE_VOID:
284                 fprintf (F, "void");
285                 break;
286             case T_TYPE_STRUCT:
287                 fprintf (F, "struct %s", ((SymEntry*) T->A.P)->Name);
288                 break;
289             case T_TYPE_UNION:
290                 fprintf (F, "union %s", ((SymEntry*) T->A.P)->Name);
291                 break;
292             case T_TYPE_ARRAY:
293                 /* Recursive call */
294                 PrintType (F, T + 1);
295                 if (T->A.L == UNSPECIFIED) {
296                     fprintf (F, " []");
297                 } else {
298                     fprintf (F, " [%ld]", T->A.L);
299                 }
300                 return;
301             case T_TYPE_PTR:
302                 /* Recursive call */
303                 PrintType (F, T + 1);
304                 fprintf (F, " *");
305                 return;
306             case T_TYPE_FUNC:
307                 fprintf (F, "function returning ");
308                 break;
309             default:
310                 fprintf (F, "unknown type: %04lX", T->C);
311         }
312
313         /* Next element */
314         ++T;
315     }
316 }
317
318
319
320 void PrintFuncSig (FILE* F, const char* Name, Type* T)
321 /* Print a function signature. */
322 {
323     /* Get the function descriptor */
324     const FuncDesc* D = GetFuncDesc (T);
325
326     /* Print a comment with the function signature */
327     PrintType (F, GetFuncReturn (T));
328     if (IsQualNear (T)) {
329         fprintf (F, " __near__");
330     }
331     if (IsQualFar (T)) {
332         fprintf (F, " __far__");
333     }
334     if (IsQualFastcall (T)) {
335         fprintf (F, " __fastcall__");
336     }
337     if (IsQualCDecl (T)) {
338         fprintf (F, " __cdecl__");
339     }
340     fprintf (F, " %s (", Name);
341
342     /* Parameters */
343     if (D->Flags & FD_VOID_PARAM) {
344         fprintf (F, "void");
345     } else {
346         unsigned I;
347         SymEntry* E = D->SymTab->SymHead;
348         for (I = 0; I < D->ParamCount; ++I) {
349             if (I > 0) {
350                 fprintf (F, ", ");
351             }
352             if (SymIsRegVar (E)) {
353                 fprintf (F, "register ");
354             }
355             PrintType (F, E->Type);
356             E = E->NextSym;
357         }
358     }
359
360     /* End of parameter list */
361     fprintf (F, ")");
362 }
363
364
365
366 void PrintRawType (FILE* F, const Type* T)
367 /* Print a type string in raw format (for debugging) */
368 {
369     while (T->C != T_END) {
370         fprintf (F, "%04lX ", T->C);
371         ++T;
372     }
373     fprintf (F, "\n");
374 }
375
376
377
378 int TypeHasAttr (const Type* T)
379 /* Return true if the given type has attribute data */
380 {
381     return IsClassStruct (T) || IsTypeArray (T) || IsClassFunc (T);
382 }
383
384
385
386 unsigned SizeOf (const Type* T)
387 /* Compute size of object represented by type array. */
388 {
389     switch (UnqualifiedType (T->C)) {
390
391         case T_VOID:
392             /* A void variable is a cc65 extension.
393             ** Get its size (in bytes).
394             */
395             return T->A.U;
396
397         /* Beware: There's a chance that this triggers problems in other parts
398            of the compiler. The solution is to fix the callers, because calling
399            SizeOf() with a function type as argument is bad. */
400         case T_FUNC:
401             return 0;   /* Size of function is unknown */
402
403         case T_SCHAR:
404         case T_UCHAR:
405             return SIZEOF_CHAR;
406
407         case T_SHORT:
408         case T_USHORT:
409             return SIZEOF_SHORT;
410
411         case T_INT:
412         case T_UINT:
413             return SIZEOF_INT;
414
415         case T_PTR:
416             return SIZEOF_PTR;
417
418         case T_LONG:
419         case T_ULONG:
420             return SIZEOF_LONG;
421
422         case T_LONGLONG:
423         case T_ULONGLONG:
424             return SIZEOF_LONGLONG;
425
426         case T_ENUM:
427             return SIZEOF_INT;
428
429         case T_FLOAT:
430             return SIZEOF_FLOAT;
431
432         case T_DOUBLE:
433             return SIZEOF_DOUBLE;
434
435         case T_STRUCT:
436         case T_UNION:
437             return ((SymEntry*) T->A.P)->V.S.Size;
438
439         case T_ARRAY:
440             if (T->A.L == UNSPECIFIED) {
441                 /* Array with unspecified size */
442                 return 0;
443             } else {
444                 return T->A.U * SizeOf (T + 1);
445             }
446
447         default:
448             Internal ("Unknown type in SizeOf: %04lX", T->C);
449             return 0;
450
451     }
452 }
453
454
455
456 unsigned PSizeOf (const Type* T)
457 /* Compute size of pointer object. */
458 {
459     /* We are expecting a pointer expression */
460     CHECK (IsClassPtr (T));
461
462     /* Skip the pointer or array token itself */
463     return SizeOf (T + 1);
464 }
465
466
467
468 unsigned CheckedSizeOf (const Type* T)
469 /* Return the size of a data type. If the size is zero, emit an error and
470 ** return some valid size instead (so the rest of the compiler doesn't have
471 ** to work with invalid sizes).
472 */
473 {
474     unsigned Size = SizeOf (T);
475     if (Size == 0) {
476         Error ("Size of data type is unknown");
477         Size = SIZEOF_CHAR;     /* Don't return zero */
478     }
479     return Size;
480 }
481
482
483
484 unsigned CheckedPSizeOf (const Type* T)
485 /* Return the size of a data type that is pointed to by a pointer. If the
486 ** size is zero, emit an error and return some valid size instead (so the
487 ** rest of the compiler doesn't have to work with invalid sizes).
488 */
489 {
490     unsigned Size = PSizeOf (T);
491     if (Size == 0) {
492         Error ("Size of data type is unknown");
493         Size = SIZEOF_CHAR;     /* Don't return zero */
494     }
495     return Size;
496 }
497
498
499
500 unsigned TypeOf (const Type* T)
501 /* Get the code generator base type of the object */
502 {
503     switch (UnqualifiedType (T->C)) {
504
505         case T_SCHAR:
506             return CF_CHAR;
507
508         case T_UCHAR:
509             return CF_CHAR | CF_UNSIGNED;
510
511         case T_SHORT:
512         case T_INT:
513         case T_ENUM:
514             return CF_INT;
515
516         case T_USHORT:
517         case T_UINT:
518         case T_PTR:
519         case T_ARRAY:
520             return CF_INT | CF_UNSIGNED;
521
522         case T_LONG:
523             return CF_LONG;
524
525         case T_ULONG:
526             return CF_LONG | CF_UNSIGNED;
527
528         case T_FLOAT:
529         case T_DOUBLE:
530             /* These two are identical in the backend */
531             return CF_FLOAT;
532
533         case T_FUNC:
534             return (((FuncDesc*) T->A.P)->Flags & FD_VARIADIC)? 0 : CF_FIXARGC;
535
536         case T_STRUCT:
537         case T_UNION:
538             /* Address of ... */
539             return CF_INT | CF_UNSIGNED;
540
541         default:
542             Error ("Illegal type %04lX", T->C);
543             return CF_INT;
544     }
545 }
546
547
548
549 Type* Indirect (Type* T)
550 /* Do one indirection for the given type, that is, return the type where the
551 ** given type points to.
552 */
553 {
554     /* We are expecting a pointer expression */
555     CHECK (IsClassPtr (T));
556
557     /* Skip the pointer or array token itself */
558     return T + 1;
559 }
560
561
562
563 Type* ArrayToPtr (Type* T)
564 /* Convert an array to a pointer to it's first element */
565 {
566     /* Return pointer to first element */
567     return PointerTo (GetElementType (T));
568 }
569
570
571
572 int IsVariadicFunc (const Type* T)
573 /* Return true if this is a function type or pointer to function type with
574 ** variable parameter list
575 */
576 {
577     FuncDesc* F = GetFuncDesc (T);
578     return (F->Flags & FD_VARIADIC) != 0;
579 }
580
581
582
583 FuncDesc* GetFuncDesc (const Type* T)
584 /* Get the FuncDesc pointer from a function or pointer-to-function type */
585 {
586     if (UnqualifiedType (T->C) == T_PTR) {
587         /* Pointer to function */
588         ++T;
589     }
590
591     /* Be sure it's a function type */
592     CHECK (IsClassFunc (T));
593
594     /* Get the function descriptor from the type attributes */
595     return T->A.P;
596 }
597
598
599
600 void SetFuncDesc (Type* T, FuncDesc* F)
601 /* Set the FuncDesc pointer in a function or pointer-to-function type */
602 {
603     if (UnqualifiedType (T->C) == T_PTR) {
604         /* Pointer to function */
605         ++T;
606     }
607
608     /* Be sure it's a function type */
609     CHECK (IsClassFunc (T));
610
611     /* Set the function descriptor */
612     T->A.P = F;
613 }
614
615
616
617 Type* GetFuncReturn (Type* T)
618 /* Return a pointer to the return type of a function or pointer-to-function type */
619 {
620     if (UnqualifiedType (T->C) == T_PTR) {
621         /* Pointer to function */
622         ++T;
623     }
624
625     /* Be sure it's a function type */
626     CHECK (IsClassFunc (T));
627
628     /* Return a pointer to the return type */
629     return T + 1;
630 }
631
632
633
634 long GetElementCount (const Type* T)
635 /* Get the element count of the array specified in T (which must be of
636 ** array type).
637 */
638 {
639     CHECK (IsTypeArray (T));
640     return T->A.L;
641 }
642
643
644
645 void SetElementCount (Type* T, long Count)
646 /* Set the element count of the array specified in T (which must be of
647 ** array type).
648 */
649 {
650     CHECK (IsTypeArray (T));
651     T->A.L = Count;
652 }
653
654
655
656 Type* GetElementType (Type* T)
657 /* Return the element type of the given array type. */
658 {
659     CHECK (IsTypeArray (T));
660     return T + 1;
661 }
662
663
664
665 Type* GetBaseElementType (Type* T)
666 /* Return the base element type of a given type. If T is not an array, this
667 ** will return. Otherwise it will return the base element type, which means
668 ** the element type that is not an array.
669 */
670 {
671     while (IsTypeArray (T)) {
672         ++T;
673     }
674     return T;
675 }
676
677
678
679 SymEntry* GetSymEntry (const Type* T)
680 /* Return a SymEntry pointer from a type */
681 {
682     /* Only structs or unions have a SymEntry attribute */
683     CHECK (IsClassStruct (T));
684
685     /* Return the attribute */
686     return T->A.P;
687 }
688
689
690
691 void SetSymEntry (Type* T, SymEntry* S)
692 /* Set the SymEntry pointer for a type */
693 {
694     /* Only structs or unions have a SymEntry attribute */
695     CHECK (IsClassStruct (T));
696
697     /* Set the attribute */
698     T->A.P = S;
699 }
700
701
702
703 Type* IntPromotion (Type* T)
704 /* Apply the integer promotions to T and return the result. The returned type
705 ** string may be T if there is no need to change it.
706 */
707 {
708     /* We must have an int to apply int promotions */
709     PRECONDITION (IsClassInt (T));
710
711     /* An integer can represent all values from either signed or unsigned char,
712     ** so convert chars to int and leave all other types alone.
713     */
714     if (IsTypeChar (T)) {
715         return type_int;
716     } else {
717         return T;
718     }
719 }
720
721
722
723 Type* PtrConversion (Type* T)
724 /* If the type is a function, convert it to pointer to function. If the
725 ** expression is an array, convert it to pointer to first element. Otherwise
726 ** return T.
727 */
728 {
729     if (IsTypeFunc (T)) {
730         return PointerTo (T);
731     } else if (IsTypeArray (T)) {
732         return ArrayToPtr (T);
733     } else {
734         return T;
735     }
736 }
737
738
739
740 TypeCode AddrSizeQualifier (unsigned AddrSize)
741 /* Return T_QUAL_NEAR or T_QUAL_FAR depending on the address size */
742 {
743     switch (AddrSize) {
744
745         case ADDR_SIZE_ABS:
746             return T_QUAL_NEAR;
747
748         case ADDR_SIZE_FAR:
749             return T_QUAL_FAR;
750
751         default:
752             Error ("Invalid address size");
753             return T_QUAL_NEAR;
754
755     }
756 }