Completed the cc65 code that recognizes __CDECL__ as a calling convention qualifier.

This commit is contained in:
Greg King
2015-03-09 18:53:45 -04:00
parent f014800d3c
commit 6230b6a813
3 changed files with 54 additions and 33 deletions

View File

@@ -6,7 +6,7 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 1998-2012, Ullrich von Bassewitz */ /* (C) 1998-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
@@ -290,18 +290,18 @@ void PrintType (FILE* F, const Type* T)
fprintf (F, "union %s", ((SymEntry*) T->A.P)->Name); fprintf (F, "union %s", ((SymEntry*) T->A.P)->Name);
break; break;
case T_TYPE_ARRAY: case T_TYPE_ARRAY:
if (T->A.L == UNSPECIFIED) {
fprintf (F, "[] ");
} else {
fprintf (F, "[%ld] ", T->A.L);
}
/* Recursive call */ /* Recursive call */
PrintType (F, T + 1); PrintType (F, T + 1);
if (T->A.L == UNSPECIFIED) {
fprintf (F, "[]");
} else {
fprintf (F, "[%ld]", T->A.L);
}
return; return;
case T_TYPE_PTR: case T_TYPE_PTR:
fprintf (F, "* ");
/* Recursive call */ /* Recursive call */
PrintType (F, T + 1); PrintType (F, T + 1);
fprintf (F, "*");
return; return;
case T_TYPE_FUNC: case T_TYPE_FUNC:
fprintf (F, "function returning "); fprintf (F, "function returning ");

View File

@@ -6,7 +6,7 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 1998-2012, Ullrich von Bassewitz */ /* (C) 1998-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
@@ -603,6 +603,16 @@ INLINE int IsQualCDecl (const Type* T)
# define IsQualCDecl(T) (((T)->C & T_QUAL_CDECL) != 0) # define IsQualCDecl(T) (((T)->C & T_QUAL_CDECL) != 0)
#endif #endif
#if defined(HAVE_INLINE)
INLINE int IsQualCConv (const Type* T)
/* Return true if the given type has a calling convention qualifier */
{
return (T->C & T_QUAL_CCONV) != 0;
}
#else
# define IsQualCConv(T) (((T)->C & T_QUAL_CCONV) != 0)
#endif
int IsVariadicFunc (const Type* T) attribute ((const)); int IsVariadicFunc (const Type* T) attribute ((const));
/* Return true if this is a function type or pointer to function type with /* Return true if this is a function type or pointer to function type with
** variable parameter list ** variable parameter list

View File

@@ -6,7 +6,7 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 1998-2013, Ullrich von Bassewitz */ /* (C) 1998-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
@@ -85,7 +85,7 @@ struct StructInitData {
static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers); static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers);
/* Parse a type specificier */ /* Parse a type specifier */
static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers); static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers);
/* Parse initialization of variables. Return the number of data bytes. */ /* Parse initialization of variables. Return the number of data bytes. */
@@ -336,17 +336,28 @@ static void FixQualifiers (Type* DataType)
while (T->C != T_END) { while (T->C != T_END) {
if (IsTypePtr (T)) { if (IsTypePtr (T)) {
/* Fastcall qualifier on the pointer? */ /* Calling convention qualifier on the pointer? */
if (IsQualFastcall (T)) { if (IsQualCConv (T)) {
/* Pointer to function which is not fastcall? */ /* Pull the convention off of the pointer */
if (IsTypeFunc (T+1) && !IsQualFastcall (T+1)) { Q = T[0].C & T_QUAL_CCONV;
/* Move the fastcall qualifier from the pointer to T[0].C &= ~T_QUAL_CCONV;
** the function. /* Pointer to a function which doesn't have an explicit convention? */
if (IsTypeFunc (T + 1)) {
if (IsQualCConv (T + 1)) {
if (T[1].C == Q) {
/* TODO: The end of Declarator() catches this error.
** Try to make it let the error be caught here, instead.
*/ */
T[0].C &= ~T_QUAL_FASTCALL; Warning ("Pointer duplicates function's calling convention");
T[1].C |= T_QUAL_FASTCALL;
} else { } else {
Error ("Invalid `_fastcall__' qualifier for pointer"); Error ("Mismatch between pointer's and function's calling conventions");
}
} else {
/* Move the qualifier from the pointer to the function. */
T[1].C |= Q;
}
} else {
Error ("Not pointer to a function; can't use a calling convention");
} }
} }
@@ -355,8 +366,8 @@ static void FixQualifiers (Type* DataType)
if (Q == T_QUAL_NONE) { if (Q == T_QUAL_NONE) {
/* No address size qualifiers specified */ /* No address size qualifiers specified */
if (IsTypeFunc (T+1)) { if (IsTypeFunc (T+1)) {
/* Pointer to function. Use the qualifier from the function /* Pointer to function. Use the qualifier from the function,
** or the default if the function don't has one. ** or the default if the function doesn't have one.
*/ */
Q = (T[1].C & T_QUAL_ADDRSIZE); Q = (T[1].C & T_QUAL_ADDRSIZE);
if (Q == T_QUAL_NONE) { if (Q == T_QUAL_NONE) {
@@ -368,7 +379,7 @@ static void FixQualifiers (Type* DataType)
T[0].C |= Q; T[0].C |= Q;
} else { } else {
/* We have address size qualifiers. If followed by a function, /* We have address size qualifiers. If followed by a function,
** apply these also to the function. ** apply them to the function also.
*/ */
if (IsTypeFunc (T+1)) { if (IsTypeFunc (T+1)) {
TypeCode FQ = (T[1].C & T_QUAL_ADDRSIZE); TypeCode FQ = (T[1].C & T_QUAL_ADDRSIZE);
@@ -489,7 +500,7 @@ static void ParseEnumDecl (void)
static int ParseFieldWidth (Declaration* Decl) static int ParseFieldWidth (Declaration* Decl)
/* Parse an optional field width. Returns -1 if no field width is speficied, /* Parse an optional field width. Returns -1 if no field width is specified,
** otherwise the width of the field. ** otherwise the width of the field.
*/ */
{ {
@@ -862,7 +873,7 @@ NextMember: if (CurTok.Tok != TOK_COMMA) {
static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers) static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
/* Parse a type specificier */ /* Parse a type specifier */
{ {
ident Ident; ident Ident;
SymEntry* Entry; SymEntry* Entry;
@@ -1376,13 +1387,13 @@ static FuncDesc* ParseFuncDecl (void)
static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode) static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
/* Recursively process declarators. Build a type array in reverse order. */ /* Recursively process declarators. Build a type array in reverse order. */
{ {
/* Read optional function or pointer qualifiers. These modify the /* Read optional function or pointer qualifiers. They modify the
** identifier or token to the right. For convenience, we allow the fastcall ** identifier or token to the right. For convenience, we allow a calling
** qualifier also for pointers here. If it is a pointer-to-function, the ** convention also for pointers here. If it's a pointer-to-function, the
** qualifier will later be transfered to the function itself. If it's a ** qualifier later will be transfered to the function itself. If it's a
** pointer to something else, it will be flagged as an error. ** pointer to something else, it will be flagged as an error.
*/ */
TypeCode Qualifiers = OptionalQualifiers (T_QUAL_ADDRSIZE | T_QUAL_FASTCALL); TypeCode Qualifiers = OptionalQualifiers (T_QUAL_ADDRSIZE | T_QUAL_CCONV);
/* Pointer to something */ /* Pointer to something */
if (CurTok.Tok == TOK_STAR) { if (CurTok.Tok == TOK_STAR) {
@@ -1390,10 +1401,10 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
/* Skip the star */ /* Skip the star */
NextToken (); NextToken ();
/* Allow const, restrict and volatile qualifiers */ /* Allow const, restrict, and volatile qualifiers */
Qualifiers |= OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE | T_QUAL_RESTRICT); Qualifiers |= OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE | T_QUAL_RESTRICT);
/* Parse the type, the pointer points to */ /* Parse the type that the pointer points to */
Declarator (Spec, D, Mode); Declarator (Spec, D, Mode);
/* Add the type */ /* Add the type */