1 /*****************************************************************************/
5 /* Type string handling for the cc65 C compiler */
9 /* (C) 1998-2015, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
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. */
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: */
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 */
32 /*****************************************************************************/
55 /*****************************************************************************/
57 /*****************************************************************************/
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) };
75 /*****************************************************************************/
77 /*****************************************************************************/
81 unsigned TypeLen (const Type* T)
82 /* Return the length of the type string */
84 const Type* Start = T;
85 while (T->C != T_END) {
93 Type* TypeCopy (Type* Dest, const Type* Src)
94 /* Copy a type string */
99 if (Src->C == T_END) {
110 Type* TypeDup (const Type* T)
111 /* Create a copy of the given type on the heap */
113 unsigned Len = (TypeLen (T) + 1) * sizeof (Type);
114 return memcpy (xmalloc (Len), T, Len);
119 Type* TypeAlloc (unsigned Len)
120 /* Allocate memory for a type string of length Len. Len *must* include the
124 return xmalloc (Len * sizeof (Type));
129 void TypeFree (Type* T)
130 /* Free a type string */
137 int SignExtendChar (int C)
138 /* Do correct sign extension of a character */
140 if (IS_Get (&SignedChars) && (C & 0x80) != 0) {
149 TypeCode GetDefaultChar (void)
150 /* Return the default char type (signed/unsigned) depending on the settings */
152 return IS_Get (&SignedChars)? T_SCHAR : T_UCHAR;
157 Type* GetCharArrayType (unsigned Len)
158 /* Return the type for a char array of the given length */
160 /* Allocate memory for the type string */
161 Type* T = TypeAlloc (3); /* array/char/terminator */
163 /* Fill the type string */
165 T[0].A.L = Len; /* Array length is in the L attribute */
166 T[1].C = GetDefaultChar ();
169 /* Return the new type */
175 Type* GetImplicitFuncType (void)
176 /* Return a type string for an inplicitly declared function */
178 /* Get a new function descriptor */
179 FuncDesc* F = NewFuncDesc ();
181 /* Allocate memory for the type string */
182 Type* T = TypeAlloc (3); /* func/returns int/terminator */
184 /* Prepare the function descriptor */
185 F->Flags = FD_EMPTY | FD_VARIADIC;
186 F->SymTab = &EmptySymTab;
187 F->TagTab = &EmptySymTab;
189 /* Fill the type string */
190 T[0].C = T_FUNC | CodeAddrSizeQualifier ();
195 /* Return the new type */
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.
206 /* Get the size of the type string including the terminator */
207 unsigned Size = TypeLen (T) + 1;
209 /* Allocate the new type string */
210 Type* P = TypeAlloc (Size + 1);
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));
216 /* ...and return it */
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.
227 if ((C & Mask) == Mask) {
228 fprintf (F, "%s ", Name);
236 void PrintType (FILE* F, const Type* T)
237 /* Output translation of type array. */
239 /* Walk over the type string */
240 while (T->C != T_END) {
242 /* Get the type code */
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__");
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");
258 C = PrintTypeComp (F, C, T_SIGN_UNSIGNED, "unsigned");
260 /* Now check the real type */
261 switch (C & T_MASK_TYPE) {
266 fprintf (F, "short");
274 case T_TYPE_LONGLONG:
275 fprintf (F, "long long");
278 fprintf (F, "float");
281 fprintf (F, "double");
287 fprintf (F, "struct %s", ((SymEntry*) T->A.P)->Name);
290 fprintf (F, "union %s", ((SymEntry*) T->A.P)->Name);
294 PrintType (F, T + 1);
295 if (T->A.L == UNSPECIFIED) {
298 fprintf (F, " [%ld]", T->A.L);
303 PrintType (F, T + 1);
307 fprintf (F, "function returning ");
310 fprintf (F, "unknown type: %04lX", T->C);
320 void PrintFuncSig (FILE* F, const char* Name, Type* T)
321 /* Print a function signature. */
323 /* Get the function descriptor */
324 const FuncDesc* D = GetFuncDesc (T);
326 /* Print a comment with the function signature */
327 PrintType (F, GetFuncReturn (T));
328 if (IsQualNear (T)) {
329 fprintf (F, " __near__");
332 fprintf (F, " __far__");
334 if (IsQualFastcall (T)) {
335 fprintf (F, " __fastcall__");
337 if (IsQualCDecl (T)) {
338 fprintf (F, " __cdecl__");
340 fprintf (F, " %s (", Name);
343 if (D->Flags & FD_VOID_PARAM) {
347 SymEntry* E = D->SymTab->SymHead;
348 for (I = 0; I < D->ParamCount; ++I) {
352 if (SymIsRegVar (E)) {
353 fprintf (F, "register ");
355 PrintType (F, E->Type);
360 /* End of parameter list */
366 void PrintRawType (FILE* F, const Type* T)
367 /* Print a type string in raw format (for debugging) */
369 while (T->C != T_END) {
370 fprintf (F, "%04lX ", T->C);
378 int TypeHasAttr (const Type* T)
379 /* Return true if the given type has attribute data */
381 return IsClassStruct (T) || IsTypeArray (T) || IsClassFunc (T);
386 unsigned SizeOf (const Type* T)
387 /* Compute size of object represented by type array. */
389 switch (UnqualifiedType (T->C)) {
392 /* A void variable is a cc65 extension.
393 ** Get its size (in bytes).
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. */
401 return 0; /* Size of function is unknown */
424 return SIZEOF_LONGLONG;
433 return SIZEOF_DOUBLE;
437 return ((SymEntry*) T->A.P)->V.S.Size;
440 if (T->A.L == UNSPECIFIED) {
441 /* Array with unspecified size */
444 return T->A.U * SizeOf (T + 1);
448 Internal ("Unknown type in SizeOf: %04lX", T->C);
456 unsigned PSizeOf (const Type* T)
457 /* Compute size of pointer object. */
459 /* We are expecting a pointer expression */
460 CHECK (IsClassPtr (T));
462 /* Skip the pointer or array token itself */
463 return SizeOf (T + 1);
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).
474 unsigned Size = SizeOf (T);
476 Error ("Size of data type is unknown");
477 Size = SIZEOF_CHAR; /* Don't return zero */
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).
490 unsigned Size = PSizeOf (T);
492 Error ("Size of data type is unknown");
493 Size = SIZEOF_CHAR; /* Don't return zero */
500 unsigned TypeOf (const Type* T)
501 /* Get the code generator base type of the object */
503 switch (UnqualifiedType (T->C)) {
509 return CF_CHAR | CF_UNSIGNED;
520 return CF_INT | CF_UNSIGNED;
526 return CF_LONG | CF_UNSIGNED;
530 /* These two are identical in the backend */
534 return (((FuncDesc*) T->A.P)->Flags & FD_VARIADIC)? 0 : CF_FIXARGC;
539 return CF_INT | CF_UNSIGNED;
542 Error ("Illegal type %04lX", T->C);
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.
554 /* We are expecting a pointer expression */
555 CHECK (IsClassPtr (T));
557 /* Skip the pointer or array token itself */
563 Type* ArrayToPtr (Type* T)
564 /* Convert an array to a pointer to it's first element */
566 /* Return pointer to first element */
567 return PointerTo (GetElementType (T));
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
577 FuncDesc* F = GetFuncDesc (T);
578 return (F->Flags & FD_VARIADIC) != 0;
583 FuncDesc* GetFuncDesc (const Type* T)
584 /* Get the FuncDesc pointer from a function or pointer-to-function type */
586 if (UnqualifiedType (T->C) == T_PTR) {
587 /* Pointer to function */
591 /* Be sure it's a function type */
592 CHECK (IsClassFunc (T));
594 /* Get the function descriptor from the type attributes */
600 void SetFuncDesc (Type* T, FuncDesc* F)
601 /* Set the FuncDesc pointer in a function or pointer-to-function type */
603 if (UnqualifiedType (T->C) == T_PTR) {
604 /* Pointer to function */
608 /* Be sure it's a function type */
609 CHECK (IsClassFunc (T));
611 /* Set the function descriptor */
617 Type* GetFuncReturn (Type* T)
618 /* Return a pointer to the return type of a function or pointer-to-function type */
620 if (UnqualifiedType (T->C) == T_PTR) {
621 /* Pointer to function */
625 /* Be sure it's a function type */
626 CHECK (IsClassFunc (T));
628 /* Return a pointer to the return type */
634 long GetElementCount (const Type* T)
635 /* Get the element count of the array specified in T (which must be of
639 CHECK (IsTypeArray (T));
645 void SetElementCount (Type* T, long Count)
646 /* Set the element count of the array specified in T (which must be of
650 CHECK (IsTypeArray (T));
656 Type* GetElementType (Type* T)
657 /* Return the element type of the given array type. */
659 CHECK (IsTypeArray (T));
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.
671 while (IsTypeArray (T)) {
679 SymEntry* GetSymEntry (const Type* T)
680 /* Return a SymEntry pointer from a type */
682 /* Only structs or unions have a SymEntry attribute */
683 CHECK (IsClassStruct (T));
685 /* Return the attribute */
691 void SetSymEntry (Type* T, SymEntry* S)
692 /* Set the SymEntry pointer for a type */
694 /* Only structs or unions have a SymEntry attribute */
695 CHECK (IsClassStruct (T));
697 /* Set the attribute */
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.
708 /* We must have an int to apply int promotions */
709 PRECONDITION (IsClassInt (T));
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.
714 if (IsTypeChar (T)) {
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
729 if (IsTypeFunc (T)) {
730 return PointerTo (T);
731 } else if (IsTypeArray (T)) {
732 return ArrayToPtr (T);
740 TypeCode AddrSizeQualifier (unsigned AddrSize)
741 /* Return T_QUAL_NEAR or T_QUAL_FAR depending on the address size */
752 Error ("Invalid address size");