/*****************************************************************************/
/* */
-/* datatype.c */
+/* datatype.c */
/* */
-/* Type string handling for the cc65 C compiler */
+/* Type string handling for the cc65 C compiler */
/* */
/* */
/* */
-/* (C) 1998-2008 Ullrich von Bassewitz */
-/* Roemerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 1998-2015, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
{
const Type* Start = T;
while (T->C != T_END) {
- ++T;
+ ++T;
}
return T - Start;
}
{
Type* Orig = Dest;
while (1) {
- *Dest = *Src;
+ *Dest = *Src;
if (Src->C == T_END) {
break;
}
- Src++;
+ Src++;
Dest++;
}
return Orig;
Type* TypeAlloc (unsigned Len)
/* Allocate memory for a type string of length Len. Len *must* include the
- * trailing T_END.
- */
+** trailing T_END.
+*/
{
return xmalloc (Len * sizeof (Type));
}
/* Do correct sign extension of a character */
{
if (IS_Get (&SignedChars) && (C & 0x80) != 0) {
- return C | ~0xFF;
+ return C | ~0xFF;
} else {
- return C & 0xFF;
+ return C & 0xFF;
}
}
Type* PointerTo (const Type* T)
/* Return a type string that is "pointer to T". The type string is allocated
- * on the heap and may be freed after use.
- */
+** on the heap and may be freed after use.
+*/
{
/* Get the size of the type string including the terminator */
unsigned Size = TypeLen (T) + 1;
/* Allocate the new type string */
- Type* P = TypeAlloc (Size + 1);
+ Type* P = TypeAlloc (Size + 1);
/* Create the return type... */
P[0].C = T_PTR | (T[0].C & T_QUAL_ADDRSIZE);
static TypeCode PrintTypeComp (FILE* F, TypeCode C, TypeCode Mask, const char* Name)
/* Check for a specific component of the type. If it is there, print the
- * name and remove it. Return the type with the component removed.
- */
+** name and remove it. Return the type with the component removed.
+*/
{
if ((C & Mask) == Mask) {
- fprintf (F, "%s ", Name);
- C &= ~Mask;
+ fprintf (F, "%s ", Name);
+ C &= ~Mask;
}
return C;
}
/* Get the type code */
TypeCode C = T->C;
- /* Print any qualifiers */
- C = PrintTypeComp (F, C, T_QUAL_CONST, "const");
- C = PrintTypeComp (F, C, T_QUAL_VOLATILE, "volatile");
+ /* Print any qualifiers */
+ C = PrintTypeComp (F, C, T_QUAL_CONST, "const");
+ C = PrintTypeComp (F, C, T_QUAL_VOLATILE, "volatile");
C = PrintTypeComp (F, C, T_QUAL_RESTRICT, "restrict");
C = PrintTypeComp (F, C, T_QUAL_NEAR, "__near__");
C = PrintTypeComp (F, C, T_QUAL_FAR, "__far__");
C = PrintTypeComp (F, C, T_QUAL_FASTCALL, "__fastcall__");
+ C = PrintTypeComp (F, C, T_QUAL_CDECL, "__cdecl__");
- /* Signedness. Omit the signedness specifier for long and int */
- if ((C & T_MASK_TYPE) != T_TYPE_INT && (C & T_MASK_TYPE) != T_TYPE_LONG) {
- C = PrintTypeComp (F, C, T_SIGN_SIGNED, "signed");
- }
- C = PrintTypeComp (F, C, T_SIGN_UNSIGNED, "unsigned");
-
- /* Now check the real type */
- switch (C & T_MASK_TYPE) {
- case T_TYPE_CHAR:
- fprintf (F, "char");
- break;
- case T_TYPE_SHORT:
- fprintf (F, "short");
- break;
- case T_TYPE_INT:
- fprintf (F, "int");
- break;
- case T_TYPE_LONG:
- fprintf (F, "long");
- break;
- case T_TYPE_LONGLONG:
- fprintf (F, "long long");
- break;
- case T_TYPE_FLOAT:
- fprintf (F, "float");
- break;
- case T_TYPE_DOUBLE:
- fprintf (F, "double");
- break;
- case T_TYPE_VOID:
- fprintf (F, "void");
- break;
- case T_TYPE_STRUCT:
- fprintf (F, "struct %s", ((SymEntry*) T->A.P)->Name);
- break;
- case T_TYPE_UNION:
- fprintf (F, "union %s", ((SymEntry*) T->A.P)->Name);
- break;
- case T_TYPE_ARRAY:
- /* Recursive call */
- PrintType (F, T + 1);
- if (T->A.L == UNSPECIFIED) {
- fprintf (F, "[]");
- } else {
- fprintf (F, "[%ld]", T->A.L);
- }
- return;
- case T_TYPE_PTR:
- /* Recursive call */
- PrintType (F, T + 1);
- fprintf (F, "*");
- return;
- case T_TYPE_FUNC:
- fprintf (F, "function returning ");
- break;
- default:
- fprintf (F, "unknown type: %04lX", T->C);
- }
+ /* Signedness. Omit the signedness specifier for long and int */
+ if ((C & T_MASK_TYPE) != T_TYPE_INT && (C & T_MASK_TYPE) != T_TYPE_LONG) {
+ C = PrintTypeComp (F, C, T_SIGN_SIGNED, "signed");
+ }
+ C = PrintTypeComp (F, C, T_SIGN_UNSIGNED, "unsigned");
+
+ /* Now check the real type */
+ switch (C & T_MASK_TYPE) {
+ case T_TYPE_CHAR:
+ fprintf (F, "char");
+ break;
+ case T_TYPE_SHORT:
+ fprintf (F, "short");
+ break;
+ case T_TYPE_INT:
+ fprintf (F, "int");
+ break;
+ case T_TYPE_LONG:
+ fprintf (F, "long");
+ break;
+ case T_TYPE_LONGLONG:
+ fprintf (F, "long long");
+ break;
+ case T_TYPE_FLOAT:
+ fprintf (F, "float");
+ break;
+ case T_TYPE_DOUBLE:
+ fprintf (F, "double");
+ break;
+ case T_TYPE_VOID:
+ fprintf (F, "void");
+ break;
+ case T_TYPE_STRUCT:
+ fprintf (F, "struct %s", ((SymEntry*) T->A.P)->Name);
+ break;
+ case T_TYPE_UNION:
+ fprintf (F, "union %s", ((SymEntry*) T->A.P)->Name);
+ break;
+ case T_TYPE_ARRAY:
+ /* Recursive call */
+ PrintType (F, T + 1);
+ if (T->A.L == UNSPECIFIED) {
+ fprintf (F, " []");
+ } else {
+ fprintf (F, " [%ld]", T->A.L);
+ }
+ return;
+ case T_TYPE_PTR:
+ /* Recursive call */
+ PrintType (F, T + 1);
+ fprintf (F, " *");
+ return;
+ case T_TYPE_FUNC:
+ fprintf (F, "function returning ");
+ break;
+ default:
+ fprintf (F, "unknown type: %04lX", T->C);
+ }
/* Next element */
++T;
fprintf (F, " __far__");
}
if (IsQualFastcall (T)) {
- fprintf (F, " __fastcall__");
+ fprintf (F, " __fastcall__");
+ }
+ if (IsQualCDecl (T)) {
+ fprintf (F, " __cdecl__");
}
fprintf (F, " %s (", Name);
/* Parameters */
if (D->Flags & FD_VOID_PARAM) {
- fprintf (F, "void");
+ fprintf (F, "void");
} else {
- unsigned I;
- SymEntry* E = D->SymTab->SymHead;
- for (I = 0; I < D->ParamCount; ++I) {
- if (I > 0) {
- fprintf (F, ", ");
- }
+ unsigned I;
+ SymEntry* E = D->SymTab->SymHead;
+ for (I = 0; I < D->ParamCount; ++I) {
+ if (I > 0) {
+ fprintf (F, ", ");
+ }
if (SymIsRegVar (E)) {
fprintf (F, "register ");
}
- PrintType (F, E->Type);
- E = E->NextSym;
- }
+ PrintType (F, E->Type);
+ E = E->NextSym;
+ }
}
/* End of parameter list */
/* Print a type string in raw format (for debugging) */
{
while (T->C != T_END) {
- fprintf (F, "%04lX ", T->C);
+ fprintf (F, "%04lX ", T->C);
++T;
}
fprintf (F, "\n");
{
switch (UnqualifiedType (T->C)) {
- case T_VOID:
- return 0; /* Assume voids have size zero */
+ case T_VOID:
+ /* A void variable is a cc65 extension.
+ ** Get its size (in bytes).
+ */
+ return T->A.U;
+
+ /* Beware: There's a chance that this triggers problems in other parts
+ of the compiler. The solution is to fix the callers, because calling
+ SizeOf() with a function type as argument is bad. */
+ case T_FUNC:
+ return 0; /* Size of function is unknown */
- case T_SCHAR:
- case T_UCHAR:
- return SIZEOF_CHAR;
+ case T_SCHAR:
+ case T_UCHAR:
+ return SIZEOF_CHAR;
- case T_SHORT:
- case T_USHORT:
+ case T_SHORT:
+ case T_USHORT:
return SIZEOF_SHORT;
- case T_INT:
- case T_UINT:
+ case T_INT:
+ case T_UINT:
return SIZEOF_INT;
- case T_PTR:
- case T_FUNC: /* Maybe pointer to function */
- return SIZEOF_PTR;
+ case T_PTR:
+ return SIZEOF_PTR;
case T_LONG:
- case T_ULONG:
- return SIZEOF_LONG;
+ case T_ULONG:
+ return SIZEOF_LONG;
- case T_LONGLONG:
- case T_ULONGLONG:
- return SIZEOF_LONGLONG;
+ case T_LONGLONG:
+ case T_ULONGLONG:
+ return SIZEOF_LONGLONG;
case T_ENUM:
- return SIZEOF_INT;
+ return SIZEOF_INT;
- case T_FLOAT:
+ case T_FLOAT:
return SIZEOF_FLOAT;
- case T_DOUBLE:
- return SIZEOF_DOUBLE;
+ case T_DOUBLE:
+ return SIZEOF_DOUBLE;
- case T_STRUCT:
- case T_UNION:
+ case T_STRUCT:
+ case T_UNION:
return ((SymEntry*) T->A.P)->V.S.Size;
- case T_ARRAY:
+ case T_ARRAY:
if (T->A.L == UNSPECIFIED) {
/* Array with unspecified size */
return 0;
} else {
- return T->A.L * SizeOf (T + 1);
+ return T->A.U * SizeOf (T + 1);
}
- default:
- Internal ("Unknown type in SizeOf: %04lX", T->C);
- return 0;
+ default:
+ Internal ("Unknown type in SizeOf: %04lX", T->C);
+ return 0;
}
}
unsigned CheckedSizeOf (const Type* T)
/* Return the size of a data type. If the size is zero, emit an error and
- * return some valid size instead (so the rest of the compiler doesn't have
- * to work with invalid sizes).
- */
+** return some valid size instead (so the rest of the compiler doesn't have
+** to work with invalid sizes).
+*/
{
unsigned Size = SizeOf (T);
if (Size == 0) {
unsigned CheckedPSizeOf (const Type* T)
/* Return the size of a data type that is pointed to by a pointer. If the
- * size is zero, emit an error and return some valid size instead (so the
- * rest of the compiler doesn't have to work with invalid sizes).
- */
+** size is zero, emit an error and return some valid size instead (so the
+** rest of the compiler doesn't have to work with invalid sizes).
+*/
{
unsigned Size = PSizeOf (T);
if (Size == 0) {
{
switch (UnqualifiedType (T->C)) {
- case T_SCHAR:
- return CF_CHAR;
+ case T_SCHAR:
+ return CF_CHAR;
- case T_UCHAR:
- return CF_CHAR | CF_UNSIGNED;
+ case T_UCHAR:
+ return CF_CHAR | CF_UNSIGNED;
- case T_SHORT:
- case T_INT:
+ case T_SHORT:
+ case T_INT:
case T_ENUM:
- return CF_INT;
+ return CF_INT;
- case T_USHORT:
- case T_UINT:
- case T_PTR:
- case T_ARRAY:
- return CF_INT | CF_UNSIGNED;
+ case T_USHORT:
+ case T_UINT:
+ case T_PTR:
+ case T_ARRAY:
+ return CF_INT | CF_UNSIGNED;
case T_LONG:
- return CF_LONG;
+ return CF_LONG;
- case T_ULONG:
- return CF_LONG | CF_UNSIGNED;
+ case T_ULONG:
+ return CF_LONG | CF_UNSIGNED;
case T_FLOAT:
case T_DOUBLE:
return CF_FLOAT;
case T_FUNC:
- return (((FuncDesc*) T->A.P)->Flags & FD_VARIADIC)? 0 : CF_FIXARGC;
+ return (((FuncDesc*) T->A.P)->Flags & FD_VARIADIC)? 0 : CF_FIXARGC;
case T_STRUCT:
case T_UNION:
- /* Address of ... */
- return CF_INT | CF_UNSIGNED;
+ /* Address of ... */
+ return CF_INT | CF_UNSIGNED;
- default:
- Error ("Illegal type %04lX", T->C);
- return CF_INT;
+ default:
+ Error ("Illegal type %04lX", T->C);
+ return CF_INT;
}
}
Type* Indirect (Type* T)
/* Do one indirection for the given type, that is, return the type where the
- * given type points to.
- */
+** given type points to.
+*/
{
/* We are expecting a pointer expression */
CHECK (IsClassPtr (T));
int IsVariadicFunc (const Type* T)
/* Return true if this is a function type or pointer to function type with
- * variable parameter list
- */
+** variable parameter list
+*/
{
FuncDesc* F = GetFuncDesc (T);
return (F->Flags & FD_VARIADIC) != 0;
/* Get the FuncDesc pointer from a function or pointer-to-function type */
{
if (UnqualifiedType (T->C) == T_PTR) {
- /* Pointer to function */
- ++T;
+ /* Pointer to function */
+ ++T;
}
/* Be sure it's a function type */
/* Set the FuncDesc pointer in a function or pointer-to-function type */
{
if (UnqualifiedType (T->C) == T_PTR) {
- /* Pointer to function */
- ++T;
+ /* Pointer to function */
+ ++T;
}
/* Be sure it's a function type */
/* Return a pointer to the return type of a function or pointer-to-function type */
{
if (UnqualifiedType (T->C) == T_PTR) {
- /* Pointer to function */
- ++T;
+ /* Pointer to function */
+ ++T;
}
/* Be sure it's a function type */
long GetElementCount (const Type* T)
/* Get the element count of the array specified in T (which must be of
- * array type).
- */
+** array type).
+*/
{
CHECK (IsTypeArray (T));
return T->A.L;
void SetElementCount (Type* T, long Count)
/* Set the element count of the array specified in T (which must be of
- * array type).
- */
+** array type).
+*/
{
CHECK (IsTypeArray (T));
T->A.L = Count;
+Type* GetBaseElementType (Type* T)
+/* Return the base element type of a given type. If T is not an array, this
+** will return. Otherwise it will return the base element type, which means
+** the element type that is not an array.
+*/
+{
+ while (IsTypeArray (T)) {
+ ++T;
+ }
+ return T;
+}
+
+
+
SymEntry* GetSymEntry (const Type* T)
/* Return a SymEntry pointer from a type */
{
Type* IntPromotion (Type* T)
/* Apply the integer promotions to T and return the result. The returned type
- * string may be T if there is no need to change it.
- */
+** string may be T if there is no need to change it.
+*/
{
/* We must have an int to apply int promotions */
PRECONDITION (IsClassInt (T));
/* An integer can represent all values from either signed or unsigned char,
- * so convert chars to int and leave all other types alone.
- */
+ ** so convert chars to int and leave all other types alone.
+ */
if (IsTypeChar (T)) {
return type_int;
} else {
Type* PtrConversion (Type* T)
/* If the type is a function, convert it to pointer to function. If the
- * expression is an array, convert it to pointer to first element. Otherwise
- * return T.
- */
+** expression is an array, convert it to pointer to first element. Otherwise
+** return T.
+*/
{
if (IsTypeFunc (T)) {
- return PointerTo (T);
+ return PointerTo (T);
} else if (IsTypeArray (T)) {
return ArrayToPtr (T);
} else {
}
}
-
-
-