mirror of
https://github.com/cc65/cc65.git
synced 2024-06-26 05:29:30 +00:00
Moved the fascall and near/far flags from the function desriptor into the
type. Started to add general handling of address size flags in types. git-svn-id: svn://svn.cc65.org/cc65/trunk@3891 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
f1e0de512a
commit
cc36f8a93a
|
@ -340,14 +340,15 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg)
|
||||||
/* Did we find it in the top level table? */
|
/* Did we find it in the top level table? */
|
||||||
if (E && IsTypeFunc (E->Type)) {
|
if (E && IsTypeFunc (E->Type)) {
|
||||||
|
|
||||||
|
FuncDesc* D = E->V.F.Func;
|
||||||
|
|
||||||
/* A function may use the A or A/X registers if it is a fastcall
|
/* A function may use the A or A/X registers if it is a fastcall
|
||||||
* function. If it is not a fastcall function but a variadic one,
|
* function. If it is not a fastcall function but a variadic one,
|
||||||
* it will use the Y register (the parameter size is passed here).
|
* it will use the Y register (the parameter size is passed here).
|
||||||
* In all other cases, no registers are used. However, we assume
|
* In all other cases, no registers are used. However, we assume
|
||||||
* that any function will destroy all registers.
|
* that any function will destroy all registers.
|
||||||
*/
|
*/
|
||||||
FuncDesc* D = E->V.F.Func;
|
if (IsQualFastcall (E->Type) && D->ParamCount > 0) {
|
||||||
if ((D->Flags & FD_FASTCALL) != 0 && D->ParamCount > 0) {
|
|
||||||
/* Will use registers depending on the last param */
|
/* Will use registers depending on the last param */
|
||||||
unsigned LastParamSize = CheckedSizeOf (D->LastParam->Type);
|
unsigned LastParamSize = CheckedSizeOf (D->LastParam->Type);
|
||||||
if (LastParamSize == 1) {
|
if (LastParamSize == 1) {
|
||||||
|
|
|
@ -1241,12 +1241,11 @@ void CS_OutputPrologue (const CodeSeg* S, FILE* F)
|
||||||
*/
|
*/
|
||||||
if (Func) {
|
if (Func) {
|
||||||
/* Get the function descriptor */
|
/* Get the function descriptor */
|
||||||
const FuncDesc* D = GetFuncDesc (Func->Type);
|
|
||||||
CS_PrintFunctionHeader (S, F);
|
CS_PrintFunctionHeader (S, F);
|
||||||
fprintf (F, ".segment\t\"%s\"\n\n.proc\t_%s", S->SegName, Func->Name);
|
fprintf (F, ".segment\t\"%s\"\n\n.proc\t_%s", S->SegName, Func->Name);
|
||||||
if (D->Flags & FD_NEAR) {
|
if (IsQualNear (Func->Type)) {
|
||||||
fputs (": near", F);
|
fputs (": near", F);
|
||||||
} else if (D->Flags & FD_FAR) {
|
} else if (IsQualFar (Func->Type)) {
|
||||||
fputs (": far", F);
|
fputs (": far", F);
|
||||||
}
|
}
|
||||||
fputs ("\n\n", F);
|
fputs ("\n\n", F);
|
||||||
|
|
|
@ -36,7 +36,9 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
|
#include "addrsize.h"
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
#include "mmodel.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
|
@ -208,7 +210,7 @@ Type* PointerTo (const Type* T)
|
||||||
Type* P = TypeAlloc (Size + 1);
|
Type* P = TypeAlloc (Size + 1);
|
||||||
|
|
||||||
/* Create the return type... */
|
/* Create the return type... */
|
||||||
P[0].C = T_PTR;
|
P[0].C = T_PTR | (T[0].C & T_QUAL_ADDRSIZE);
|
||||||
memcpy (P+1, T, Size * sizeof (Type));
|
memcpy (P+1, T, Size * sizeof (Type));
|
||||||
|
|
||||||
/* ...and return it */
|
/* ...and return it */
|
||||||
|
@ -240,69 +242,72 @@ void PrintType (FILE* F, const Type* T)
|
||||||
/* Get the type code */
|
/* Get the type code */
|
||||||
TypeCode C = T->C;
|
TypeCode C = T->C;
|
||||||
|
|
||||||
/* Print any qualifiers */
|
/* Print any qualifiers */
|
||||||
C = PrintTypeComp (F, C, T_QUAL_CONST, "const");
|
C = PrintTypeComp (F, C, T_QUAL_CONST, "const");
|
||||||
C = PrintTypeComp (F, C, T_QUAL_VOLATILE, "volatile");
|
C = PrintTypeComp (F, C, T_QUAL_VOLATILE, "volatile");
|
||||||
C = PrintTypeComp (F, C, T_QUAL_RESTRICT, "restrict");
|
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__");
|
||||||
|
|
||||||
/* Signedness. Omit the signedness specifier for long and int */
|
/* Signedness. Omit the signedness specifier for long and int */
|
||||||
if ((C & T_MASK_TYPE) != T_TYPE_INT && (C & T_MASK_TYPE) != T_TYPE_LONG) {
|
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_SIGNED, "signed");
|
||||||
}
|
}
|
||||||
C = PrintTypeComp (F, C, T_SIGN_UNSIGNED, "unsigned");
|
C = PrintTypeComp (F, C, T_SIGN_UNSIGNED, "unsigned");
|
||||||
|
|
||||||
/* Now check the real type */
|
/* Now check the real type */
|
||||||
switch (C & T_MASK_TYPE) {
|
switch (C & T_MASK_TYPE) {
|
||||||
case T_TYPE_CHAR:
|
case T_TYPE_CHAR:
|
||||||
fprintf (F, "char");
|
fprintf (F, "char");
|
||||||
break;
|
break;
|
||||||
case T_TYPE_SHORT:
|
case T_TYPE_SHORT:
|
||||||
fprintf (F, "short");
|
fprintf (F, "short");
|
||||||
break;
|
break;
|
||||||
case T_TYPE_INT:
|
case T_TYPE_INT:
|
||||||
fprintf (F, "int");
|
fprintf (F, "int");
|
||||||
break;
|
break;
|
||||||
case T_TYPE_LONG:
|
case T_TYPE_LONG:
|
||||||
fprintf (F, "long");
|
fprintf (F, "long");
|
||||||
break;
|
break;
|
||||||
case T_TYPE_LONGLONG:
|
case T_TYPE_LONGLONG:
|
||||||
fprintf (F, "long long");
|
fprintf (F, "long long");
|
||||||
break;
|
break;
|
||||||
case T_TYPE_FLOAT:
|
case T_TYPE_FLOAT:
|
||||||
fprintf (F, "float");
|
fprintf (F, "float");
|
||||||
break;
|
break;
|
||||||
case T_TYPE_DOUBLE:
|
case T_TYPE_DOUBLE:
|
||||||
fprintf (F, "double");
|
fprintf (F, "double");
|
||||||
break;
|
break;
|
||||||
case T_TYPE_VOID:
|
case T_TYPE_VOID:
|
||||||
fprintf (F, "void");
|
fprintf (F, "void");
|
||||||
break;
|
break;
|
||||||
case T_TYPE_STRUCT:
|
case T_TYPE_STRUCT:
|
||||||
fprintf (F, "struct %s", ((SymEntry*) T->A.P)->Name);
|
fprintf (F, "struct %s", ((SymEntry*) T->A.P)->Name);
|
||||||
break;
|
break;
|
||||||
case T_TYPE_UNION:
|
case T_TYPE_UNION:
|
||||||
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:
|
||||||
/* Recursive call */
|
/* Recursive call */
|
||||||
PrintType (F, T + 1);
|
PrintType (F, T + 1);
|
||||||
if (T->A.L == UNSPECIFIED) {
|
if (T->A.L == UNSPECIFIED) {
|
||||||
fprintf (F, "[]");
|
fprintf (F, "[]");
|
||||||
} else {
|
} else {
|
||||||
fprintf (F, "[%ld]", T->A.L);
|
fprintf (F, "[%ld]", T->A.L);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case T_TYPE_PTR:
|
case T_TYPE_PTR:
|
||||||
/* Recursive call */
|
/* Recursive call */
|
||||||
PrintType (F, T + 1);
|
PrintType (F, T + 1);
|
||||||
fprintf (F, "*");
|
fprintf (F, "*");
|
||||||
return;
|
return;
|
||||||
case T_TYPE_FUNC:
|
case T_TYPE_FUNC:
|
||||||
fprintf (F, "function returning ");
|
fprintf (F, "function returning ");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf (F, "unknown type: %04lX", T->C);
|
fprintf (F, "unknown type: %04lX", T->C);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Next element */
|
/* Next element */
|
||||||
++T;
|
++T;
|
||||||
|
@ -319,33 +324,33 @@ void PrintFuncSig (FILE* F, const char* Name, Type* T)
|
||||||
|
|
||||||
/* Print a comment with the function signature */
|
/* Print a comment with the function signature */
|
||||||
PrintType (F, GetFuncReturn (T));
|
PrintType (F, GetFuncReturn (T));
|
||||||
if (D->Flags & FD_NEAR) {
|
if (IsQualNear (T)) {
|
||||||
fprintf (F, " __near__");
|
fprintf (F, " __near__");
|
||||||
}
|
}
|
||||||
if (D->Flags & FD_FAR) {
|
if (IsQualFar (T)) {
|
||||||
fprintf (F, " __far__");
|
fprintf (F, " __far__");
|
||||||
}
|
}
|
||||||
if (D->Flags & FD_FASTCALL) {
|
if (IsQualFastcall (T)) {
|
||||||
fprintf (F, " __fastcall__");
|
fprintf (F, " __fastcall__");
|
||||||
}
|
}
|
||||||
fprintf (F, " %s (", Name);
|
fprintf (F, " %s (", Name);
|
||||||
|
|
||||||
/* Parameters */
|
/* Parameters */
|
||||||
if (D->Flags & FD_VOID_PARAM) {
|
if (D->Flags & FD_VOID_PARAM) {
|
||||||
fprintf (F, "void");
|
fprintf (F, "void");
|
||||||
} else {
|
} else {
|
||||||
unsigned I;
|
unsigned I;
|
||||||
SymEntry* E = D->SymTab->SymHead;
|
SymEntry* E = D->SymTab->SymHead;
|
||||||
for (I = 0; I < D->ParamCount; ++I) {
|
for (I = 0; I < D->ParamCount; ++I) {
|
||||||
if (I > 0) {
|
if (I > 0) {
|
||||||
fprintf (F, ", ");
|
fprintf (F, ", ");
|
||||||
}
|
}
|
||||||
if (SymIsRegVar (E)) {
|
if (SymIsRegVar (E)) {
|
||||||
fprintf (F, "register ");
|
fprintf (F, "register ");
|
||||||
}
|
}
|
||||||
PrintType (F, E->Type);
|
PrintType (F, E->Type);
|
||||||
E = E->NextSym;
|
E = E->NextSym;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* End of parameter list */
|
/* End of parameter list */
|
||||||
|
@ -555,31 +560,6 @@ Type* ArrayToPtr (const Type* T)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TypeCode GetQualifier (const Type* T)
|
|
||||||
/* Get the qualifier from the given type string */
|
|
||||||
{
|
|
||||||
/* If this is an array, look at the element type, otherwise look at the
|
|
||||||
* type itself.
|
|
||||||
*/
|
|
||||||
if (IsTypeArray (T)) {
|
|
||||||
++T;
|
|
||||||
}
|
|
||||||
return (T->C & T_MASK_QUAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int IsFastCallFunc (const Type* T)
|
|
||||||
/* Return true if this is a function type or pointer to function with
|
|
||||||
* __fastcall__ calling conventions
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
FuncDesc* F = GetFuncDesc (T);
|
|
||||||
return (F->Flags & FD_FASTCALL) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int IsVariadicFunc (const Type* T)
|
int IsVariadicFunc (const Type* T)
|
||||||
/* 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
|
||||||
|
@ -723,10 +703,8 @@ Type* PtrConversion (Type* T)
|
||||||
* return T.
|
* return T.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
if (IsTypeFunc (T)) {
|
if (IsTypeFunc (T) || IsTypeArray (T)) {
|
||||||
return PointerTo (T);
|
return PointerTo (T);
|
||||||
} else if (IsTypeArray (T)) {
|
|
||||||
return ArrayToPtr (T);
|
|
||||||
} else {
|
} else {
|
||||||
return T;
|
return T;
|
||||||
}
|
}
|
||||||
|
@ -734,4 +712,27 @@ Type* PtrConversion (Type* T)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TypeCode CodeAddrSizeQualifier (void)
|
||||||
|
/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the code address size */
|
||||||
|
{
|
||||||
|
if (CodeAddrSize == ADDR_SIZE_FAR) {
|
||||||
|
return T_QUAL_FAR;
|
||||||
|
} else {
|
||||||
|
return T_QUAL_NEAR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TypeCode DataAddrSizeQualifier (void)
|
||||||
|
/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the data address size */
|
||||||
|
{
|
||||||
|
if (DataAddrSize == ADDR_SIZE_FAR) {
|
||||||
|
return T_QUAL_FAR;
|
||||||
|
} else {
|
||||||
|
return T_QUAL_NEAR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -58,54 +58,58 @@
|
||||||
|
|
||||||
/* Basic data types */
|
/* Basic data types */
|
||||||
enum {
|
enum {
|
||||||
T_END = 0x0000,
|
T_END = 0x000000,
|
||||||
|
|
||||||
/* Basic types */
|
/* Basic types */
|
||||||
T_TYPE_NONE = 0x0000,
|
T_TYPE_NONE = 0x000000,
|
||||||
T_TYPE_CHAR = 0x0001,
|
T_TYPE_CHAR = 0x000001,
|
||||||
T_TYPE_SHORT = 0x0002,
|
T_TYPE_SHORT = 0x000002,
|
||||||
T_TYPE_INT = 0x0003,
|
T_TYPE_INT = 0x000003,
|
||||||
T_TYPE_LONG = 0x0004,
|
T_TYPE_LONG = 0x000004,
|
||||||
T_TYPE_LONGLONG = 0x0005,
|
T_TYPE_LONGLONG = 0x000005,
|
||||||
T_TYPE_ENUM = 0x0006,
|
T_TYPE_ENUM = 0x000006,
|
||||||
T_TYPE_FLOAT = 0x0007,
|
T_TYPE_FLOAT = 0x000007,
|
||||||
T_TYPE_DOUBLE = 0x0008,
|
T_TYPE_DOUBLE = 0x000008,
|
||||||
T_TYPE_VOID = 0x0009,
|
T_TYPE_VOID = 0x000009,
|
||||||
T_TYPE_STRUCT = 0x000A,
|
T_TYPE_STRUCT = 0x00000A,
|
||||||
T_TYPE_UNION = 0x000B,
|
T_TYPE_UNION = 0x00000B,
|
||||||
T_TYPE_ARRAY = 0x000C,
|
T_TYPE_ARRAY = 0x00000C,
|
||||||
T_TYPE_PTR = 0x000D,
|
T_TYPE_PTR = 0x00000D,
|
||||||
T_TYPE_FUNC = 0x000E,
|
T_TYPE_FUNC = 0x00000E,
|
||||||
T_MASK_TYPE = 0x001F,
|
T_MASK_TYPE = 0x00000F,
|
||||||
|
|
||||||
/* Type classes */
|
/* Type classes */
|
||||||
T_CLASS_NONE = 0x0000,
|
T_CLASS_NONE = 0x000000,
|
||||||
T_CLASS_INT = 0x0020,
|
T_CLASS_INT = 0x000010,
|
||||||
T_CLASS_FLOAT = 0x0040,
|
T_CLASS_FLOAT = 0x000020,
|
||||||
T_CLASS_PTR = 0x0060,
|
T_CLASS_PTR = 0x000030,
|
||||||
T_CLASS_STRUCT = 0x0080,
|
T_CLASS_STRUCT = 0x000040,
|
||||||
T_CLASS_FUNC = 0x00A0,
|
T_CLASS_FUNC = 0x000050,
|
||||||
T_MASK_CLASS = 0x00E0,
|
T_MASK_CLASS = 0x000070,
|
||||||
|
|
||||||
/* Type signedness */
|
/* Type signedness */
|
||||||
T_SIGN_NONE = 0x0000,
|
T_SIGN_NONE = 0x000000,
|
||||||
T_SIGN_UNSIGNED = 0x0100,
|
T_SIGN_UNSIGNED = 0x000080,
|
||||||
T_SIGN_SIGNED = 0x0200,
|
T_SIGN_SIGNED = 0x000100,
|
||||||
T_MASK_SIGN = 0x0300,
|
T_MASK_SIGN = 0x000180,
|
||||||
|
|
||||||
/* Type size modifiers */
|
/* Type size modifiers */
|
||||||
T_SIZE_NONE = 0x0000,
|
T_SIZE_NONE = 0x000000,
|
||||||
T_SIZE_SHORT = 0x0400,
|
T_SIZE_SHORT = 0x000200,
|
||||||
T_SIZE_LONG = 0x0800,
|
T_SIZE_LONG = 0x000400,
|
||||||
T_SIZE_LONGLONG = 0x0C00,
|
T_SIZE_LONGLONG = 0x000600,
|
||||||
T_MASK_SIZE = 0x0C00,
|
T_MASK_SIZE = 0x000600,
|
||||||
|
|
||||||
/* Type qualifiers */
|
/* Type qualifiers */
|
||||||
T_QUAL_NONE = 0x0000,
|
T_QUAL_NONE = 0x000000,
|
||||||
T_QUAL_CONST = 0x1000,
|
T_QUAL_CONST = 0x000800,
|
||||||
T_QUAL_VOLATILE = 0x2000,
|
T_QUAL_VOLATILE = 0x001000,
|
||||||
T_QUAL_RESTRICT = 0x4000,
|
T_QUAL_RESTRICT = 0x002000,
|
||||||
T_MASK_QUAL = 0x7000,
|
T_QUAL_NEAR = 0x004000,
|
||||||
|
T_QUAL_FAR = 0x008000,
|
||||||
|
T_QUAL_ADDRSIZE = T_QUAL_NEAR | T_QUAL_FAR,
|
||||||
|
T_QUAL_FASTCALL = 0x010000,
|
||||||
|
T_MASK_QUAL = 0x01F800,
|
||||||
|
|
||||||
/* Types */
|
/* Types */
|
||||||
T_CHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE,
|
T_CHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE,
|
||||||
|
@ -506,43 +510,75 @@ INLINE int IsSignSigned (const Type* T)
|
||||||
# define IsSignSigned(T) (GetSignedness (T) == T_SIGN_SIGNED)
|
# define IsSignSigned(T) (GetSignedness (T) == T_SIGN_SIGNED)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TypeCode GetQualifier (const Type* T) attribute ((const));
|
#if defined(HAVE_INLINE)
|
||||||
|
INLINE TypeCode GetQualifier (const Type* T)
|
||||||
/* Get the qualifier from the given type string */
|
/* Get the qualifier from the given type string */
|
||||||
|
{
|
||||||
|
return (T->C & T_MASK_QUAL);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define GetQualifier(T) ((T)->C & T_MASK_QUAL)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_INLINE)
|
#if defined(HAVE_INLINE)
|
||||||
INLINE int IsQualConst (const Type* T)
|
INLINE int IsQualConst (const Type* T)
|
||||||
/* Return true if the given type has a const memory image */
|
/* Return true if the given type has a const memory image */
|
||||||
{
|
{
|
||||||
return (GetQualifier (T) & T_QUAL_CONST) != 0;
|
return (T->C & T_QUAL_CONST) != 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
# define IsQualConst(T) ((GetQualifier (T) & T_QUAL_CONST) != 0)
|
# define IsQualConst(T) ((T->C & T_QUAL_CONST) != 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_INLINE)
|
#if defined(HAVE_INLINE)
|
||||||
INLINE int IsQualVolatile (const Type* T)
|
INLINE int IsQualVolatile (const Type* T)
|
||||||
/* Return true if the given type has a volatile type qualifier */
|
/* Return true if the given type has a volatile type qualifier */
|
||||||
{
|
{
|
||||||
return (GetQualifier (T) & T_QUAL_VOLATILE) != 0;
|
return (T->C & T_QUAL_VOLATILE) != 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
# define IsQualVolatile(T) ((GetQualifier (T) & T_QUAL_VOLATILE) != 0)
|
# define IsQualVolatile(T) (T->C & T_QUAL_VOLATILE) != 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_INLINE)
|
#if defined(HAVE_INLINE)
|
||||||
INLINE int IsQualRestrict (const Type* T)
|
INLINE int IsQualRestrict (const Type* T)
|
||||||
/* Return true if the given type has a restrict qualifier */
|
/* Return true if the given type has a restrict qualifier */
|
||||||
{
|
{
|
||||||
return (GetQualifier (T) & T_QUAL_RESTRICT) != 0;
|
return (T->C & T_QUAL_RESTRICT) != 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
# define IsQualRestrict(T) ((GetQualifier (T) & T_QUAL_RESTRICT) != 0)
|
# define IsQualRestrict(T) (T->C & T_QUAL_RESTRICT) != 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int IsFastCallFunc (const Type* T) attribute ((const));
|
#if defined(HAVE_INLINE)
|
||||||
/* Return true if this is a function type or pointer to function with
|
INLINE int IsQualNear (const Type* T)
|
||||||
* __fastcall__ calling conventions
|
/* Return true if the given type has a near qualifier */
|
||||||
*/
|
{
|
||||||
|
return (T->C & T_QUAL_NEAR) != 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define IsQualNear(T) (T->C & T_QUAL_NEAR) != 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_INLINE)
|
||||||
|
INLINE int IsQualFar (const Type* T)
|
||||||
|
/* Return true if the given type has a far qualifier */
|
||||||
|
{
|
||||||
|
return (T->C & T_QUAL_FAR) != 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define IsQualFar(T) (T->C & T_QUAL_FAR) != 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_INLINE)
|
||||||
|
INLINE int IsQualFastcall (const Type* T)
|
||||||
|
/* Return true if the given type has a fastcall qualifier */
|
||||||
|
{
|
||||||
|
return (T->C & T_QUAL_FASTCALL) != 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define IsQualFastcall(T) (T->C & T_QUAL_FASTCALL) != 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
|
||||||
|
@ -598,6 +634,12 @@ Type* PtrConversion (Type* T);
|
||||||
* return T.
|
* return T.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
TypeCode CodeAddrSizeQualifier (void);
|
||||||
|
/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the code address size */
|
||||||
|
|
||||||
|
TypeCode DataAddrSizeQualifier (void);
|
||||||
|
/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the data address size */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* End of datatype.h */
|
/* End of datatype.h */
|
||||||
|
|
|
@ -77,41 +77,94 @@ static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers);
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* internal functions */
|
/* internal functions */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static TypeCode OptionalQualifiers (TypeCode Q)
|
static void DuplicateQualifier (const char* Name)
|
||||||
|
/* Print an error message */
|
||||||
|
{
|
||||||
|
Warning ("Duplicate qualifier: `%s'", Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static TypeCode OptionalQualifiers (TypeCode Q, TypeCode Allowed)
|
||||||
/* Read type qualifiers if we have any */
|
/* Read type qualifiers if we have any */
|
||||||
{
|
{
|
||||||
while (TokIsTypeQual (&CurTok)) {
|
while (1) {
|
||||||
|
|
||||||
switch (CurTok.Tok) {
|
switch (CurTok.Tok) {
|
||||||
|
|
||||||
case TOK_CONST:
|
case TOK_CONST:
|
||||||
if (Q & T_QUAL_CONST) {
|
if (Allowed & T_QUAL_CONST) {
|
||||||
Error ("Duplicate qualifier: `const'");
|
if (Q & T_QUAL_CONST) {
|
||||||
}
|
DuplicateQualifier ("const");
|
||||||
Q |= T_QUAL_CONST;
|
}
|
||||||
break;
|
Q |= T_QUAL_CONST;
|
||||||
|
} else {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case TOK_VOLATILE:
|
case TOK_VOLATILE:
|
||||||
if (Q & T_QUAL_VOLATILE) {
|
if (Allowed & T_QUAL_VOLATILE) {
|
||||||
Error ("Duplicate qualifier: `volatile'");
|
if (Q & T_QUAL_VOLATILE) {
|
||||||
}
|
DuplicateQualifier ("volatile");
|
||||||
Q |= T_QUAL_VOLATILE;
|
}
|
||||||
break;
|
Q |= T_QUAL_VOLATILE;
|
||||||
|
} else {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case TOK_RESTRICT:
|
case TOK_RESTRICT:
|
||||||
if (Q & T_QUAL_RESTRICT) {
|
if (Allowed & T_QUAL_RESTRICT) {
|
||||||
Error ("Duplicate qualifier: `restrict'");
|
if (Q & T_QUAL_RESTRICT) {
|
||||||
|
DuplicateQualifier ("restrict");
|
||||||
|
}
|
||||||
|
Q |= T_QUAL_RESTRICT;
|
||||||
|
} else {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TOK_NEAR:
|
||||||
|
if (Allowed & T_QUAL_NEAR) {
|
||||||
|
if (Q & T_QUAL_NEAR) {
|
||||||
|
DuplicateQualifier ("near");
|
||||||
|
}
|
||||||
|
Q |= T_QUAL_NEAR;
|
||||||
|
} else {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TOK_FAR:
|
||||||
|
if (Allowed & T_QUAL_FAR) {
|
||||||
|
if (Q & T_QUAL_FAR) {
|
||||||
|
DuplicateQualifier ("far");
|
||||||
|
}
|
||||||
|
Q |= T_QUAL_FAR;
|
||||||
|
} else {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TOK_FASTCALL:
|
||||||
|
if (Allowed & T_QUAL_FASTCALL) {
|
||||||
|
if (Q & T_QUAL_FASTCALL) {
|
||||||
|
DuplicateQualifier ("fastcall");
|
||||||
|
}
|
||||||
|
Q |= T_QUAL_FASTCALL;
|
||||||
|
} else {
|
||||||
|
goto Done;
|
||||||
}
|
}
|
||||||
Q |= T_QUAL_RESTRICT;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Internal ("Unexpected type qualifier token: %d", CurTok.Tok);
|
goto Done;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +172,7 @@ static TypeCode OptionalQualifiers (TypeCode Q)
|
||||||
NextToken ();
|
NextToken ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Done:
|
||||||
/* Return the qualifiers read */
|
/* Return the qualifiers read */
|
||||||
return Q;
|
return Q;
|
||||||
}
|
}
|
||||||
|
@ -190,35 +244,18 @@ static void AddTypeToDeclaration (Declaration* D, TypeCode T)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void AddFuncTypeToDeclaration (Declaration* D, FuncDesc* F)
|
static void FixQualifiers (Type* DataType)
|
||||||
/* Add a function type plus function descriptor to the type of a declaration */
|
/* Apply several fixes to qualifiers */
|
||||||
{
|
{
|
||||||
NeedTypeSpace (D, 1);
|
Type* T;
|
||||||
D->Type[D->Index].C = T_FUNC;
|
TypeCode Q;
|
||||||
SetFuncDesc (D->Type + D->Index, F);
|
|
||||||
++D->Index;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Using typedefs, it is possible to generate declarations that have
|
||||||
|
* type qualifiers attached to an array, not the element type. Go and
|
||||||
static void AddArrayToDeclaration (Declaration* D, long Size)
|
* fix these here.
|
||||||
/* Add an array type plus size to the type of a declaration */
|
*/
|
||||||
{
|
T = DataType;
|
||||||
NeedTypeSpace (D, 1);
|
Q = T_QUAL_NONE;
|
||||||
D->Type[D->Index].C = T_ARRAY;
|
|
||||||
D->Type[D->Index].A.L = Size;
|
|
||||||
++D->Index;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void FixArrayQualifiers (Type* T)
|
|
||||||
/* Using typedefs, it is possible to generate declarations that have
|
|
||||||
* type qualifiers attached to an array, not the element type. Go and
|
|
||||||
* fix these here.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
TypeCode Q = T_QUAL_NONE;
|
|
||||||
while (T->C != T_END) {
|
while (T->C != T_END) {
|
||||||
if (IsTypeArray (T)) {
|
if (IsTypeArray (T)) {
|
||||||
/* Extract any type qualifiers */
|
/* Extract any type qualifiers */
|
||||||
|
@ -231,9 +268,69 @@ static void FixArrayQualifiers (Type* T)
|
||||||
}
|
}
|
||||||
++T;
|
++T;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Q must be empty now */
|
/* Q must be empty now */
|
||||||
CHECK (Q == T_QUAL_NONE);
|
CHECK (Q == T_QUAL_NONE);
|
||||||
|
|
||||||
|
/* Do some fixes on pointers and functions. */
|
||||||
|
T = DataType;
|
||||||
|
while (T->C != T_END) {
|
||||||
|
if (IsTypePtr (T)) {
|
||||||
|
|
||||||
|
/* Fastcall qualifier on the pointer? */
|
||||||
|
if (IsQualFastcall (T)) {
|
||||||
|
/* Pointer to function which is not fastcall? */
|
||||||
|
if (IsTypeFunc (T+1) && !IsQualFastcall (T+1)) {
|
||||||
|
/* Move the fastcall qualifier from the pointer to
|
||||||
|
* the function.
|
||||||
|
*/
|
||||||
|
T[0].C &= ~T_QUAL_FASTCALL;
|
||||||
|
T[1].C |= T_QUAL_FASTCALL;
|
||||||
|
} else {
|
||||||
|
Error ("Invalid `_fastcall__' qualifier for pointer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Apply the default far and near qualifiers if none are given */
|
||||||
|
Q = (T[0].C & T_QUAL_ADDRSIZE);
|
||||||
|
if (Q == T_QUAL_NONE) {
|
||||||
|
/* No address size qualifiers specified */
|
||||||
|
if (IsTypeFunc (T+1)) {
|
||||||
|
/* Pointer to function. Use the qualifier from the function
|
||||||
|
* or the default if the function don't has one.
|
||||||
|
*/
|
||||||
|
Q = (T[1].C & T_QUAL_ADDRSIZE);
|
||||||
|
if (Q == T_QUAL_NONE) {
|
||||||
|
Q = CodeAddrSizeQualifier ();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Q = DataAddrSizeQualifier ();
|
||||||
|
}
|
||||||
|
T[0].C |= Q;
|
||||||
|
} else {
|
||||||
|
/* We have address size qualifiers. If followed by a function,
|
||||||
|
* apply these also to the function.
|
||||||
|
*/
|
||||||
|
if (IsTypeFunc (T+1)) {
|
||||||
|
TypeCode FQ = (T[1].C & T_QUAL_ADDRSIZE);
|
||||||
|
if (FQ == T_QUAL_NONE) {
|
||||||
|
T[1].C |= Q;
|
||||||
|
} else if (FQ != Q) {
|
||||||
|
Error ("Address size qualifier mismatch");
|
||||||
|
T[1].C = (T[1].C & ~T_QUAL_ADDRSIZE) | Q;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (IsTypeFunc (T)) {
|
||||||
|
|
||||||
|
/* Apply the default far and near qualifiers if none are given */
|
||||||
|
if ((T[0].C & T_QUAL_ADDRSIZE) == 0) {
|
||||||
|
T[0].C |= CodeAddrSizeQualifier ();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
++T;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -458,7 +555,7 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
|
||||||
D->Flags &= ~DS_DEF_TYPE;
|
D->Flags &= ~DS_DEF_TYPE;
|
||||||
|
|
||||||
/* Read type qualifiers if we have any */
|
/* Read type qualifiers if we have any */
|
||||||
Qualifiers = OptionalQualifiers (Qualifiers);
|
Qualifiers = OptionalQualifiers (Qualifiers, T_QUAL_CONST | T_QUAL_VOLATILE);
|
||||||
|
|
||||||
/* Look at the data type */
|
/* Look at the data type */
|
||||||
switch (CurTok.Tok) {
|
switch (CurTok.Tok) {
|
||||||
|
@ -666,7 +763,7 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* There may also be qualifiers *after* the initial type */
|
/* There may also be qualifiers *after* the initial type */
|
||||||
D->Type[0].C |= OptionalQualifiers (Qualifiers);
|
D->Type[0].C |= OptionalQualifiers (Qualifiers, T_QUAL_CONST | T_QUAL_VOLATILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -924,13 +1021,6 @@ static FuncDesc* ParseFuncDecl (void)
|
||||||
Sym = Sym->PrevSym;
|
Sym = Sym->PrevSym;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add the default address size for the function */
|
|
||||||
if (CodeAddrSize == ADDR_SIZE_FAR) {
|
|
||||||
F->Flags |= FD_FAR;
|
|
||||||
} else {
|
|
||||||
F->Flags |= FD_NEAR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Leave the lexical level remembering the symbol tables */
|
/* Leave the lexical level remembering the symbol tables */
|
||||||
RememberFunctionLevel (F);
|
RememberFunctionLevel (F);
|
||||||
|
|
||||||
|
@ -940,111 +1030,48 @@ static FuncDesc* ParseFuncDecl (void)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static unsigned FunctionModifierFlags (void)
|
|
||||||
/* Parse __fastcall__, __near__ and __far__ and return the matching FD_ flags */
|
|
||||||
{
|
|
||||||
/* Read the flags */
|
|
||||||
unsigned Flags = FD_NONE;
|
|
||||||
while (CurTok.Tok == TOK_FASTCALL || CurTok.Tok == TOK_NEAR || CurTok.Tok == TOK_FAR) {
|
|
||||||
|
|
||||||
/* Get the flag bit for the next token */
|
|
||||||
unsigned F = FD_NONE;
|
|
||||||
switch (CurTok.Tok) {
|
|
||||||
case TOK_FASTCALL: F = FD_FASTCALL; break;
|
|
||||||
case TOK_NEAR: F = FD_NEAR; break;
|
|
||||||
case TOK_FAR: F = FD_FAR; break;
|
|
||||||
default: Internal ("Unexpected token: %d", CurTok.Tok);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remember the flag for this modifier */
|
|
||||||
if (Flags & F) {
|
|
||||||
Error ("Duplicate modifier");
|
|
||||||
}
|
|
||||||
Flags |= F;
|
|
||||||
|
|
||||||
/* Skip the token */
|
|
||||||
NextToken ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sanity check */
|
|
||||||
if ((Flags & (FD_NEAR | FD_FAR)) == (FD_NEAR | FD_FAR)) {
|
|
||||||
Error ("Cannot specify both, `__near__' and `__far__' modifiers");
|
|
||||||
Flags &= ~(FD_NEAR | FD_FAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the flags read */
|
|
||||||
return Flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void ApplyFunctionModifiers (Type* T, unsigned Flags)
|
|
||||||
/* Apply a set of function modifier flags to a function */
|
|
||||||
{
|
|
||||||
/* Get the function descriptor */
|
|
||||||
FuncDesc* F = GetFuncDesc (T);
|
|
||||||
|
|
||||||
/* Special check for __fastcall__ */
|
|
||||||
if ((Flags & FD_FASTCALL) != 0 && IsVariadicFunc (T)) {
|
|
||||||
Error ("Cannot apply `__fastcall__' to functions with "
|
|
||||||
"variable parameter list");
|
|
||||||
Flags &= ~FD_FASTCALL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove the default function address size modifiers */
|
|
||||||
F->Flags &= ~(FD_NEAR | FD_FAR);
|
|
||||||
|
|
||||||
/* Add the new modifers */
|
|
||||||
F->Flags |= Flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
|
static void Decl (const DeclSpec* Spec, Declaration* D, unsigned 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
|
||||||
|
* identifier or token to the right. For convenience, we allow the fastcall
|
||||||
|
* qualifier also for pointers here. If it is a pointer-to-function, the
|
||||||
|
* qualifier will later be transfered to the function itself. If it's a
|
||||||
|
* pointer to something else, it will be flagged as an error.
|
||||||
|
*/
|
||||||
|
TypeCode Qualifiers =
|
||||||
|
OptionalQualifiers (T_QUAL_NONE, T_QUAL_ADDRSIZE | T_QUAL_FASTCALL);
|
||||||
|
|
||||||
|
/* We cannot have more than one address size far qualifier */
|
||||||
|
switch (Qualifiers & T_QUAL_ADDRSIZE) {
|
||||||
|
|
||||||
|
case T_QUAL_NONE:
|
||||||
|
case T_QUAL_NEAR:
|
||||||
|
case T_QUAL_FAR:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Error ("Cannot specify more than one address size qualifier");
|
||||||
|
Qualifiers &= ~T_QUAL_ADDRSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Pointer to something */
|
/* Pointer to something */
|
||||||
if (CurTok.Tok == TOK_STAR) {
|
if (CurTok.Tok == TOK_STAR) {
|
||||||
|
|
||||||
TypeCode C;
|
|
||||||
|
|
||||||
/* Skip the star */
|
/* Skip the star */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
/* Allow optional const or volatile qualifiers */
|
/* Allow optional pointer qualifiers */
|
||||||
C = T_PTR | OptionalQualifiers (T_QUAL_NONE);
|
Qualifiers = OptionalQualifiers (Qualifiers, T_QUAL_CONST | T_QUAL_VOLATILE);
|
||||||
|
|
||||||
/* Parse the type, the pointer points to */
|
/* Parse the type, the pointer points to */
|
||||||
Decl (Spec, D, Mode);
|
Decl (Spec, D, Mode);
|
||||||
|
|
||||||
/* Add the type */
|
/* Add the type */
|
||||||
AddTypeToDeclaration (D, C);
|
AddTypeToDeclaration (D, T_PTR | Qualifiers);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Function modifiers */
|
|
||||||
if (CurTok.Tok == TOK_FASTCALL || CurTok.Tok == TOK_NEAR || CurTok.Tok == TOK_FAR) {
|
|
||||||
|
|
||||||
/* Remember the current type pointer */
|
|
||||||
Type* T = D->Type + D->Index;
|
|
||||||
|
|
||||||
/* Read the flags */
|
|
||||||
unsigned Flags = FunctionModifierFlags ();
|
|
||||||
|
|
||||||
/* Parse the function */
|
|
||||||
Decl (Spec, D, Mode);
|
|
||||||
|
|
||||||
/* Check that we have a function */
|
|
||||||
if (!IsTypeFunc (T) && !IsTypeFuncPtr (T)) {
|
|
||||||
Error ("Function modifier applied to non function");
|
|
||||||
} else {
|
|
||||||
ApplyFunctionModifiers (T, Flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Done */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CurTok.Tok == TOK_LPAREN) {
|
if (CurTok.Tok == TOK_LPAREN) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
Decl (Spec, D, Mode);
|
Decl (Spec, D, Mode);
|
||||||
|
@ -1078,17 +1105,41 @@ static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
|
||||||
|
|
||||||
/* Function declaration */
|
/* Function declaration */
|
||||||
FuncDesc* F;
|
FuncDesc* F;
|
||||||
|
|
||||||
|
/* Skip the opening paren */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
/* Parse the function declaration */
|
/* Parse the function declaration */
|
||||||
F = ParseFuncDecl ();
|
F = ParseFuncDecl ();
|
||||||
|
|
||||||
|
/* We cannot specify fastcall for variadic functions */
|
||||||
|
if ((F->Flags & FD_VARIADIC) && (Qualifiers & T_QUAL_FASTCALL)) {
|
||||||
|
Error ("Variadic functions cannot be `__fastcall'");
|
||||||
|
Qualifiers &= ~T_QUAL_FASTCALL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Add the function type. Be sure to bounds check the type buffer */
|
/* Add the function type. Be sure to bounds check the type buffer */
|
||||||
AddFuncTypeToDeclaration (D, F);
|
NeedTypeSpace (D, 1);
|
||||||
|
D->Type[D->Index].C = T_FUNC | Qualifiers;
|
||||||
|
D->Type[D->Index].A.P = F;
|
||||||
|
++D->Index;
|
||||||
|
|
||||||
|
/* Qualifiers now used */
|
||||||
|
Qualifiers = T_QUAL_NONE;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* Array declaration */
|
/* Array declaration. */
|
||||||
long Size = UNSPECIFIED;
|
long Size = UNSPECIFIED;
|
||||||
|
|
||||||
|
/* We cannot have any qualifiers for an array */
|
||||||
|
if (Qualifiers != T_QUAL_NONE) {
|
||||||
|
Error ("Invalid qualifiers for array");
|
||||||
|
Qualifiers = T_QUAL_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip the left bracket */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
/* Read the size if it is given */
|
/* Read the size if it is given */
|
||||||
if (CurTok.Tok != TOK_RBRACK) {
|
if (CurTok.Tok != TOK_RBRACK) {
|
||||||
ExprDesc Expr;
|
ExprDesc Expr;
|
||||||
|
@ -1103,12 +1154,28 @@ static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
|
||||||
}
|
}
|
||||||
Size = Expr.IVal;
|
Size = Expr.IVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Skip the right bracket */
|
||||||
ConsumeRBrack ();
|
ConsumeRBrack ();
|
||||||
|
|
||||||
/* Add the array type with the size */
|
/* Add the array type with the size to the type */
|
||||||
AddArrayToDeclaration (D, Size);
|
NeedTypeSpace (D, 1);
|
||||||
|
D->Type[D->Index].C = T_ARRAY;
|
||||||
|
D->Type[D->Index].A.L = Size;
|
||||||
|
++D->Index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we have remaining qualifiers, flag them as invalid */
|
||||||
|
if (Qualifiers & T_QUAL_NEAR) {
|
||||||
|
Error ("Invalid `__near__' qualifier");
|
||||||
|
}
|
||||||
|
if (Qualifiers & T_QUAL_FAR) {
|
||||||
|
Error ("Invalid `__far__' qualifier");
|
||||||
|
}
|
||||||
|
if (Qualifiers & T_QUAL_FASTCALL) {
|
||||||
|
Error ("Invalid `__fastcall__' qualifier");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1157,8 +1224,8 @@ void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
|
||||||
/* Use the storage class from the declspec */
|
/* Use the storage class from the declspec */
|
||||||
D->StorageClass = Spec->StorageClass;
|
D->StorageClass = Spec->StorageClass;
|
||||||
|
|
||||||
/* Fix any type qualifiers attached to an array type */
|
/* Do several fixes on qualifiers */
|
||||||
FixArrayQualifiers (D->Type);
|
FixQualifiers (D->Type);
|
||||||
|
|
||||||
/* If we have a function, add a special storage class */
|
/* If we have a function, add a special storage class */
|
||||||
if (IsTypeFunc (D->Type)) {
|
if (IsTypeFunc (D->Type)) {
|
||||||
|
@ -1243,7 +1310,7 @@ void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, long DefType)
|
||||||
InitDeclSpec (D);
|
InitDeclSpec (D);
|
||||||
|
|
||||||
/* There may be qualifiers *before* the storage class specifier */
|
/* There may be qualifiers *before* the storage class specifier */
|
||||||
Qualifiers = OptionalQualifiers (T_QUAL_NONE);
|
Qualifiers = OptionalQualifiers (T_QUAL_NONE, T_QUAL_CONST | T_QUAL_VOLATILE);
|
||||||
|
|
||||||
/* Now get the storage class specifier for this declaration */
|
/* Now get the storage class specifier for this declaration */
|
||||||
ParseStorageClass (D, DefStorage);
|
ParseStorageClass (D, DefStorage);
|
||||||
|
|
|
@ -242,12 +242,12 @@ void PushAddr (const ExprDesc* Expr)
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* code */
|
/* code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static unsigned FunctionParamList (FuncDesc* Func)
|
static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall)
|
||||||
/* Parse a function parameter list and pass the parameters to the called
|
/* Parse a function parameter list and pass the parameters to the called
|
||||||
* function. Depending on several criteria this may be done by just pushing
|
* function. Depending on several criteria this may be done by just pushing
|
||||||
* each parameter separately, or creating the parameter frame once and then
|
* each parameter separately, or creating the parameter frame once and then
|
||||||
|
@ -284,7 +284,7 @@ static unsigned FunctionParamList (FuncDesc* Func)
|
||||||
/* Calculate the number and size of the parameters */
|
/* Calculate the number and size of the parameters */
|
||||||
FrameParams = Func->ParamCount;
|
FrameParams = Func->ParamCount;
|
||||||
FrameSize = Func->ParamSize;
|
FrameSize = Func->ParamSize;
|
||||||
if (FrameParams > 0 && (Func->Flags & FD_FASTCALL) != 0) {
|
if (FrameParams > 0 && IsFastcall) {
|
||||||
/* Last parameter is not pushed */
|
/* Last parameter is not pushed */
|
||||||
FrameSize -= CheckedSizeOf (Func->LastParam->Type);
|
FrameSize -= CheckedSizeOf (Func->LastParam->Type);
|
||||||
--FrameParams;
|
--FrameParams;
|
||||||
|
@ -371,7 +371,7 @@ static unsigned FunctionParamList (FuncDesc* Func)
|
||||||
Flags |= TypeOf (Expr.Type);
|
Flags |= TypeOf (Expr.Type);
|
||||||
|
|
||||||
/* If this is a fastcall function, don't push the last argument */
|
/* If this is a fastcall function, don't push the last argument */
|
||||||
if (ParamCount != Func->ParamCount || (Func->Flags & FD_FASTCALL) == 0) {
|
if (ParamCount != Func->ParamCount || !IsFastcall) {
|
||||||
unsigned ArgSize = sizeofarg (Flags);
|
unsigned ArgSize = sizeofarg (Flags);
|
||||||
if (FrameSize > 0) {
|
if (FrameSize > 0) {
|
||||||
/* We have the space already allocated, store in the frame.
|
/* We have the space already allocated, store in the frame.
|
||||||
|
@ -430,7 +430,7 @@ static void FunctionCall (ExprDesc* Expr)
|
||||||
unsigned ParamSize; /* Number of parameter bytes */
|
unsigned ParamSize; /* Number of parameter bytes */
|
||||||
CodeMark Mark;
|
CodeMark Mark;
|
||||||
int PtrOffs = 0; /* Offset of function pointer on stack */
|
int PtrOffs = 0; /* Offset of function pointer on stack */
|
||||||
int IsFastCall = 0; /* True if it's a fast call function */
|
int IsFastcall = 0; /* True if it's a fast call function */
|
||||||
int PtrOnStack = 0; /* True if a pointer copy is on stack */
|
int PtrOnStack = 0; /* True if a pointer copy is on stack */
|
||||||
|
|
||||||
/* Skip the left paren */
|
/* Skip the left paren */
|
||||||
|
@ -444,7 +444,7 @@ static void FunctionCall (ExprDesc* Expr)
|
||||||
if (IsFuncPtr) {
|
if (IsFuncPtr) {
|
||||||
|
|
||||||
/* Check wether it's a fastcall function that has parameters */
|
/* Check wether it's a fastcall function that has parameters */
|
||||||
IsFastCall = IsFastCallFunc (Expr->Type + 1) && (Func->ParamCount > 0);
|
IsFastcall = IsQualFastcall (Expr->Type + 1) && (Func->ParamCount > 0);
|
||||||
|
|
||||||
/* Things may be difficult, depending on where the function pointer
|
/* Things may be difficult, depending on where the function pointer
|
||||||
* resides. If the function pointer is an expression of some sort
|
* resides. If the function pointer is an expression of some sort
|
||||||
|
@ -454,7 +454,7 @@ static void FunctionCall (ExprDesc* Expr)
|
||||||
* For fastcall functions we do also need to place a copy of the
|
* For fastcall functions we do also need to place a copy of the
|
||||||
* pointer on stack, since we cannot use a/x.
|
* pointer on stack, since we cannot use a/x.
|
||||||
*/
|
*/
|
||||||
PtrOnStack = IsFastCall || !ED_IsConst (Expr);
|
PtrOnStack = IsFastcall || !ED_IsConst (Expr);
|
||||||
if (PtrOnStack) {
|
if (PtrOnStack) {
|
||||||
|
|
||||||
/* Not a global or local variable, or a fastcall function. Load
|
/* Not a global or local variable, or a fastcall function. Load
|
||||||
|
@ -471,18 +471,23 @@ static void FunctionCall (ExprDesc* Expr)
|
||||||
PtrOffs = StackPtr;
|
PtrOffs = StackPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for known standard functions and inline them */
|
} else {
|
||||||
} else if (Expr->Name != 0) {
|
/* Check for known standard functions and inline them */
|
||||||
int StdFunc = FindStdFunc ((const char*) Expr->Name);
|
if (Expr->Name != 0) {
|
||||||
if (StdFunc >= 0) {
|
int StdFunc = FindStdFunc ((const char*) Expr->Name);
|
||||||
/* Inline this function */
|
if (StdFunc >= 0) {
|
||||||
HandleStdFunc (StdFunc, Func, Expr);
|
/* Inline this function */
|
||||||
return;
|
HandleStdFunc (StdFunc, Func, Expr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we didn't inline the function, get fastcall info */
|
||||||
|
IsFastcall = IsQualFastcall (Expr->Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse the parameter list */
|
/* Parse the parameter list */
|
||||||
ParamSize = FunctionParamList (Func);
|
ParamSize = FunctionParamList (Func, IsFastcall);
|
||||||
|
|
||||||
/* We need the closing paren here */
|
/* We need the closing paren here */
|
||||||
ConsumeRParen ();
|
ConsumeRParen ();
|
||||||
|
@ -493,7 +498,7 @@ static void FunctionCall (ExprDesc* Expr)
|
||||||
/* If the function is not a fastcall function, load the pointer to
|
/* If the function is not a fastcall function, load the pointer to
|
||||||
* the function into the primary.
|
* the function into the primary.
|
||||||
*/
|
*/
|
||||||
if (!IsFastCall) {
|
if (!IsFastcall) {
|
||||||
|
|
||||||
/* Not a fastcall function - we may use the primary */
|
/* Not a fastcall function - we may use the primary */
|
||||||
if (PtrOnStack) {
|
if (PtrOnStack) {
|
||||||
|
@ -1290,7 +1295,7 @@ static void PreInc (ExprDesc* Expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Result is an expression, no reference */
|
/* Result is an expression, no reference */
|
||||||
ED_MakeRValExpr (Expr);
|
ED_MakeRValExpr (Expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1367,7 +1372,7 @@ static void PreDec (ExprDesc* Expr)
|
||||||
|
|
||||||
/* Result is an expression, no reference */
|
/* Result is an expression, no reference */
|
||||||
ED_MakeRValExpr (Expr);
|
ED_MakeRValExpr (Expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -49,12 +49,9 @@
|
||||||
#define FD_EMPTY 0x0001U /* Function with empty param list */
|
#define FD_EMPTY 0x0001U /* Function with empty param list */
|
||||||
#define FD_VOID_PARAM 0x0002U /* Function with a void param list */
|
#define FD_VOID_PARAM 0x0002U /* Function with a void param list */
|
||||||
#define FD_VARIADIC 0x0004U /* Function with variable param list */
|
#define FD_VARIADIC 0x0004U /* Function with variable param list */
|
||||||
#define FD_FASTCALL 0x0010U /* __fastcall__ function */
|
#define FD_OLDSTYLE 0x0010U /* Old style (K&R) function */
|
||||||
#define FD_FAR 0x0020U /* __far__ function */
|
#define FD_OLDSTYLE_INTRET 0x0020U /* K&R func has implicit int return */
|
||||||
#define FD_NEAR 0x0040U /* __near__ function */
|
#define FD_UNNAMED_PARAMS 0x0040U /* Function has unnamed params */
|
||||||
#define FD_OLDSTYLE 0x0100U /* Old style (K&R) function */
|
|
||||||
#define FD_OLDSTYLE_INTRET 0x0200U /* K&R func has implicit int return */
|
|
||||||
#define FD_UNNAMED_PARAMS 0x0400U /* Function has unnamed params */
|
|
||||||
|
|
||||||
/* Bits that must be ignored when comparing funcs */
|
/* Bits that must be ignored when comparing funcs */
|
||||||
#define FD_IGNORE (FD_OLDSTYLE | FD_OLDSTYLE_INTRET | FD_UNNAMED_PARAMS)
|
#define FD_IGNORE (FD_OLDSTYLE | FD_OLDSTYLE_INTRET | FD_UNNAMED_PARAMS)
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 2000-2006 Ullrich von Bassewitz */
|
/* (C) 2000-2008 Ullrich von Bassewitz */
|
||||||
/* Römerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
|
@ -370,7 +370,7 @@ void NewFunc (SymEntry* Func)
|
||||||
/* Special handling for main() */
|
/* Special handling for main() */
|
||||||
if (strcmp (Func->Name, "main") == 0) {
|
if (strcmp (Func->Name, "main") == 0) {
|
||||||
/* Main cannot be a fastcall function */
|
/* Main cannot be a fastcall function */
|
||||||
if (IsFastCallFunc (Func->Type)) {
|
if (IsQualFastcall (Func->Type)) {
|
||||||
Error ("`main' cannot be declared as __fastcall__");
|
Error ("`main' cannot be declared as __fastcall__");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,7 +391,7 @@ void NewFunc (SymEntry* Func)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this is a fastcall function, push the last parameter onto the stack */
|
/* If this is a fastcall function, push the last parameter onto the stack */
|
||||||
if (IsFastCallFunc (Func->Type) && D->ParamCount > 0) {
|
if (IsQualFastcall (Func->Type) && D->ParamCount > 0) {
|
||||||
|
|
||||||
unsigned Flags;
|
unsigned Flags;
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ static void SetResult (typecmp_t* Result, typecmp_t Val)
|
||||||
/* Set a new result value if it is less than the existing one */
|
/* Set a new result value if it is less than the existing one */
|
||||||
{
|
{
|
||||||
if (Val < *Result) {
|
if (Val < *Result) {
|
||||||
|
/* printf ("SetResult = %d\n", Val); */
|
||||||
*Result = Val;
|
*Result = Val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,13 +247,14 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
||||||
}
|
}
|
||||||
if (LeftQual != RightQual) {
|
if (LeftQual != RightQual) {
|
||||||
/* On the first indirection level, different qualifiers mean
|
/* On the first indirection level, different qualifiers mean
|
||||||
* that the types are still compatible. On the second level,
|
* that the types are still compatible. On the second level,
|
||||||
* this is a (maybe minor) error, so we create a special
|
* this is a (maybe minor) error, so we create a special
|
||||||
* return code, since a qualifier is dropped from a pointer.
|
* return code, since a qualifier is dropped from a pointer.
|
||||||
* Starting from the next level, the types are incompatible
|
* Starting from the next level, the types are incompatible
|
||||||
* if the qualifiers differ.
|
* if the qualifiers differ.
|
||||||
*/
|
*/
|
||||||
switch (Indirections) {
|
/* printf ("Ind = %d %06X != %06X\n", Indirections, LeftQual, RightQual); */
|
||||||
|
switch (Indirections) {
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
SetResult (Result, TC_STRICT_COMPATIBLE);
|
SetResult (Result, TC_STRICT_COMPATIBLE);
|
||||||
|
|
|
@ -168,11 +168,6 @@ void TypeConversion (ExprDesc* Expr, Type* NewType)
|
||||||
* impossible.
|
* impossible.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
/* Get the type of the right hand side. Treat function types as
|
|
||||||
* pointer-to-function
|
|
||||||
*/
|
|
||||||
Expr->Type = PtrConversion (Expr->Type);
|
|
||||||
|
|
||||||
/* First, do some type checking */
|
/* First, do some type checking */
|
||||||
if (IsTypeVoid (NewType) || IsTypeVoid (Expr->Type)) {
|
if (IsTypeVoid (NewType) || IsTypeVoid (Expr->Type)) {
|
||||||
/* If one of the sides are of type void, output a more apropriate
|
/* If one of the sides are of type void, output a more apropriate
|
||||||
|
@ -192,7 +187,10 @@ void TypeConversion (ExprDesc* Expr, Type* NewType)
|
||||||
|
|
||||||
/* Handle conversions to int type */
|
/* Handle conversions to int type */
|
||||||
if (IsClassPtr (Expr->Type)) {
|
if (IsClassPtr (Expr->Type)) {
|
||||||
/* Pointer -> int conversion */
|
/* Pointer -> int conversion. Convert array to pointer */
|
||||||
|
if (IsTypeArray (Expr->Type)) {
|
||||||
|
Expr->Type = ArrayToPtr (Expr->Type);
|
||||||
|
}
|
||||||
Warning ("Converting pointer to integer without a cast");
|
Warning ("Converting pointer to integer without a cast");
|
||||||
} else if (!IsClassInt (Expr->Type) && !IsClassFloat (Expr->Type)) {
|
} else if (!IsClassInt (Expr->Type) && !IsClassFloat (Expr->Type)) {
|
||||||
Error ("Incompatible types");
|
Error ("Incompatible types");
|
||||||
|
@ -207,7 +205,13 @@ void TypeConversion (ExprDesc* Expr, Type* NewType)
|
||||||
} else if (IsClassPtr (NewType)) {
|
} else if (IsClassPtr (NewType)) {
|
||||||
|
|
||||||
/* Handle conversions to pointer type */
|
/* Handle conversions to pointer type */
|
||||||
if (IsClassPtr (Expr->Type)) {
|
if (IsClassPtr (Expr->Type)) {
|
||||||
|
|
||||||
|
/* Convert array to pointer */
|
||||||
|
if (IsTypeArray (Expr->Type)) {
|
||||||
|
Expr->Type = ArrayToPtr (Expr->Type);
|
||||||
|
}
|
||||||
|
|
||||||
/* Pointer to pointer assignment is valid, if:
|
/* Pointer to pointer assignment is valid, if:
|
||||||
* - both point to the same types, or
|
* - both point to the same types, or
|
||||||
* - the rhs pointer is a void pointer, or
|
* - the rhs pointer is a void pointer, or
|
||||||
|
@ -230,16 +234,20 @@ void TypeConversion (ExprDesc* Expr, Type* NewType)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (IsClassInt (Expr->Type)) {
|
} else if (IsClassInt (Expr->Type)) {
|
||||||
/* Int to pointer assignment is valid only for constant zero */
|
/* Int to pointer assignment is valid only for constant zero */
|
||||||
if (!ED_IsConstAbsInt (Expr) || Expr->IVal != 0) {
|
if (!ED_IsConstAbsInt (Expr) || Expr->IVal != 0) {
|
||||||
Warning ("Converting integer to pointer without a cast");
|
Warning ("Converting integer to pointer without a cast");
|
||||||
}
|
}
|
||||||
} else if (IsTypeFuncPtr (NewType) && IsTypeFunc(Expr->Type)) {
|
} else if (IsTypeFuncPtr (NewType) && IsTypeFunc(Expr->Type)) {
|
||||||
|
/* Function -> Function pointer. First convert rhs to pointer */
|
||||||
|
Expr->Type = PointerTo (Expr->Type);
|
||||||
|
|
||||||
/* Assignment of function to function pointer is allowed, provided
|
/* Assignment of function to function pointer is allowed, provided
|
||||||
* that both functions have the same parameter list.
|
* that both functions have the same parameter list.
|
||||||
*/
|
*/
|
||||||
if (TypeCmp (Indirect (NewType), Expr->Type) < TC_EQUAL) {
|
if (TypeCmp (NewType, Expr->Type) < TC_EQUAL) {
|
||||||
Error ("Incompatible types");
|
Error ("Incompatible types");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user