Allow __fastcall__ for C function. Contrary to the name, this is a size

optimization for C functions. The last parameter is not pushed onto the
stack by the caller but in the function entry code, so there is no speed
but a size gain.


git-svn-id: svn://svn.cc65.org/cc65/trunk@645 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz
2001-03-22 21:02:01 +00:00
parent 00706daa49
commit 4357bb4760
6 changed files with 80 additions and 39 deletions

View File

@@ -450,7 +450,7 @@ unsigned TypeOf (const type* T)
FuncDesc* F; FuncDesc* F;
switch (UnqualifiedType (T[0])) { switch (UnqualifiedType (T[0])) {
case T_SCHAR: case T_SCHAR:
return CF_CHAR; return CF_CHAR;
@@ -648,6 +648,17 @@ int IsFastCallFunc (const type* T)
int IsEllipsisFunc (const type* T)
/* Return true if this is a function type with variable parameter list */
{
FuncDesc* F;
CHECK (IsTypeFunc (T));
F = DecodePtr (T+1);
return (F->Flags & FD_ELLIPSIS) != 0;
}
int IsTypeFuncPtr (const type* T) int IsTypeFuncPtr (const type* T)
/* Return true if this is a function pointer */ /* Return true if this is a function pointer */
{ {
@@ -657,7 +668,7 @@ int IsTypeFuncPtr (const type* T)
type GetType (const type* T) type GetType (const type* T)
/* Get the raw type */ /* Get the raw type */
{ {
PRECONDITION (T[0] != T_END); PRECONDITION (T[0] != T_END);
return (T[0] & T_MASK_TYPE); return (T[0] & T_MASK_TYPE);

View File

@@ -283,6 +283,9 @@ int IsQualVolatile (const type* T) attribute ((const));
int IsFastCallFunc (const type* T) attribute ((const)); int IsFastCallFunc (const type* T) attribute ((const));
/* Return true if this is a function type with __fastcall__ calling conventions */ /* Return true if this is a function type with __fastcall__ calling conventions */
int IsEllipsisFunc (const type* T) attribute ((const));
/* Return true if this is a function type with variable parameter list */
int IsTypeFuncPtr (const type* T) attribute ((const)); int IsTypeFuncPtr (const type* T) attribute ((const));
/* Return true if this is a function pointer */ /* Return true if this is a function pointer */

View File

@@ -775,7 +775,9 @@ static void Decl (Declaration* D, unsigned Mode)
/* Set the fastcall flag */ /* Set the fastcall flag */
if (!IsTypeFunc (T)) { if (!IsTypeFunc (T)) {
Error ("__fastcall__ modifier applied to non function"); Error ("__fastcall__ modifier applied to non function");
} else { } else if (IsEllipsisFunc (T)) {
Error ("Cannot apply __fastcall__ to functions with variable parameter list");
} else {
FuncDesc* F = DecodePtr (T+1); FuncDesc* F = DecodePtr (T+1);
F->Flags |= FD_FASTCALL; F->Flags |= FD_FASTCALL;
} }

View File

@@ -34,6 +34,7 @@
/* common */ /* common */
#include "check.h"
#include "xmalloc.h" #include "xmalloc.h"
/* cc65 */ /* cc65 */
@@ -115,6 +116,14 @@ const char* GetFuncName (const Function* F)
unsigned GetParamCount (const Function* F)
/* Return the parameter count for the current function */
{
return F->Desc->ParamCount;
}
unsigned GetParamSize (const Function* F) unsigned GetParamSize (const Function* F)
/* Return the parameter size for the current function */ /* Return the parameter size for the current function */
{ {
@@ -213,11 +222,6 @@ void NewFunc (SymEntry* Func)
/* Function body now defined */ /* Function body now defined */
Func->Flags |= SC_DEF; Func->Flags |= SC_DEF;
/* C functions cannot currently have __fastcall__ calling conventions */
if (IsFastCallFunc (Func->Type)) {
Error ("__fastcall__ is not allowed for C functions");
}
/* Need a starting curly brace */ /* Need a starting curly brace */
if (curtok != TOK_LCURLY) { if (curtok != TOK_LCURLY) {
Error ("`{' expected"); Error ("`{' expected");
@@ -230,7 +234,25 @@ void NewFunc (SymEntry* Func)
g_usecode (); g_usecode ();
g_defgloblabel (Func->Name); g_defgloblabel (Func->Name);
/* If stack cehcking code is requested, emit a call to the helper routine */ /* If this is a fastcall function, push the last parameter onto the stack */
if (IsFastCallFunc (Func->Type) && D->ParamCount > 0 && (D->Flags & FD_ELLIPSIS) == 0) {
unsigned Flags;
/* Get a pointer to the last parameter entry */
SymEntry* LastParam = D->SymTab->SymTail;
/* Generate the push */
if (IsTypeFunc (LastParam->Type)) {
/* Pointer to function */
Flags = CF_PTR;
} else {
Flags = TypeOf (LastParam->Type) | CF_FORCECHAR;
}
g_push (Flags, 0);
}
/* If stack checking code is requested, emit a call to the helper routine */
if (CheckStack) { if (CheckStack) {
g_stackcheck (); g_stackcheck ();
} }

View File

@@ -34,6 +34,9 @@ extern Function* CurrentFunc;
const char* GetFuncName (const Function* F); const char* GetFuncName (const Function* F);
/* Return the name of the current function */ /* Return the name of the current function */
unsigned GetParamCount (const Function* F);
/* Return the parameter count for the current function */
unsigned GetParamSize (const Function* F); unsigned GetParamSize (const Function* F);
/* Return the parameter size for the current function */ /* Return the parameter size for the current function */

View File

@@ -6,7 +6,7 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000 Ullrich von Bassewitz */ /* (C) 2000-2001 Ullrich von Bassewitz */
/* Wacholderweg 14 */ /* Wacholderweg 14 */
/* D-70597 Stuttgart */ /* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */ /* EMail: uz@musoftware.de */
@@ -164,7 +164,7 @@ ExprNode* DoAsm (void)
if (CurTok.Tok != TOK_SCONST) { if (CurTok.Tok != TOK_SCONST) {
/* Print an error */ /* Print an error */
Error (ERR_STRLIT_EXPECTED); Error ("String literal expected");
/* To be on the safe side later, insert an empty asm string */ /* To be on the safe side later, insert an empty asm string */
AppendItem (N, xstrdup ("")); AppendItem (N, xstrdup (""));
@@ -238,7 +238,7 @@ static ExprNode* Primary (void)
*/ */
if (Preprocessing) { if (Preprocessing) {
/* Illegal expression in PP mode */ /* Illegal expression in PP mode */
Error (ERR_CPP_EXPR_EXPECTED); Error ("Preprocessor expression expected");
/* Skip the token for error recovery */ /* Skip the token for error recovery */
NextToken (); NextToken ();
@@ -266,11 +266,11 @@ static ExprNode* Primary (void)
/* Check for illegal symbol types */ /* Check for illegal symbol types */
if ((Sym->Flags & SC_LABEL) == SC_LABEL) { if ((Sym->Flags & SC_LABEL) == SC_LABEL) {
/* Cannot use labels in expressions */ /* Cannot use labels in expressions */
Error (ERR_SYMBOL_KIND); Error ("Cannot use a label in an expression");
return GetIntNode (0); return GetIntNode (0);
} else if (Sym->Flags & SC_TYPE) { } else if (Sym->Flags & SC_TYPE) {
/* Cannot use type symbols */ /* Cannot use type symbols */
Error (ERR_VAR_IDENT_EXPECTED); Error ("Cannot use a type in an expression");
/* Assume an int type to make lval valid */ /* Assume an int type to make lval valid */
return GetIntNode (0); return GetIntNode (0);
} }
@@ -307,7 +307,7 @@ static ExprNode* Primary (void)
if (CurTok.Tok == TOK_LPAREN) { if (CurTok.Tok == TOK_LPAREN) {
/* Warn about the use of a function without prototype */ /* Warn about the use of a function without prototype */
Warning (WARN_FUNC_WITHOUT_PROTO); Warning ("Function call without a prototype");
/* Declare a function returning int. For that purpose, prepare /* Declare a function returning int. For that purpose, prepare
* a function signature for a function having an empty param * a function signature for a function having an empty param
@@ -320,7 +320,7 @@ static ExprNode* Primary (void)
} else { } else {
/* Print an error about an undeclared variable */ /* Print an error about an undeclared variable */
Error (ERR_UNDEFINED_SYMBOL, Ident); Error ("Undefined symbiol: `%s'", Ident);
/* Undeclared Variable */ /* Undeclared Variable */
Sym = AddLocalSym (Ident, type_int, SC_AUTO | SC_REF, 0); Sym = AddLocalSym (Ident, type_int, SC_AUTO | SC_REF, 0);
@@ -370,7 +370,7 @@ static ExprNode* Primary (void)
} else { } else {
/* Illegal primary. */ /* Illegal primary. */
Error (ERR_EXPR_EXPECTED); Error ("Expression expected");
N = GetIntNode (0); N = GetIntNode (0);
} }
@@ -402,7 +402,7 @@ static ExprNode* DoArray (ExprNode* Left)
/* Right side must be some sort of integer */ /* Right side must be some sort of integer */
if (!IsClassInt (Right->Type)) { if (!IsClassInt (Right->Type)) {
/* Print an error */ /* Print an error */
Error (ERR_CANNOT_SUBSCRIPT); Error ("Invalid subscript");
/* To avoid problems later, create a new, legal subscript /* To avoid problems later, create a new, legal subscript
* expression * expression
*/ */
@@ -413,9 +413,9 @@ static ExprNode* DoArray (ExprNode* Left)
ExprNode* Tmp; ExprNode* Tmp;
/* Left side must be some sort of integer */ /* Left side must be some sort of integer */
if (!IsClassInt (Right->Type)) { if (!IsClassInt (Left->Type)) {
/* Print an error */ /* Print an error */
Error (ERR_CANNOT_SUBSCRIPT); Error ("Invalid subscript");
/* To avoid problems later, create a new, legal subscript /* To avoid problems later, create a new, legal subscript
* expression * expression
*/ */
@@ -431,7 +431,7 @@ static ExprNode* DoArray (ExprNode* Left)
/* Invalid array expression. Skip the closing bracket, then return /* Invalid array expression. Skip the closing bracket, then return
* an integer instead of the array expression to be safe later. * an integer instead of the array expression to be safe later.
*/ */
Error (ERR_CANNOT_SUBSCRIPT); Error ("Invalid subscript");
ConsumeRBrack (); ConsumeRBrack ();
return GetIntNode (0); return GetIntNode (0);
} }
@@ -473,7 +473,7 @@ static ExprNode* DoStruct (ExprNode* Left)
if (CurTok.Tok == TOK_PTR_REF) { if (CurTok.Tok == TOK_PTR_REF) {
NT = NT_STRUCTPTR_ACCESS; NT = NT_STRUCTPTR_ACCESS;
if (!IsTypePtr (StructType)) { if (!IsTypePtr (StructType)) {
Error (ERR_STRUCT_PTR_EXPECTED); Error ("Struct pointer expected");
return GetIntNode (0); return GetIntNode (0);
} }
StructType = Indirect (StructType); StructType = Indirect (StructType);
@@ -481,7 +481,7 @@ static ExprNode* DoStruct (ExprNode* Left)
NT = NT_STRUCT_ACCESS; NT = NT_STRUCT_ACCESS;
} }
if (!IsClassStruct (StructType)) { if (!IsClassStruct (StructType)) {
Error (ERR_STRUCT_EXPECTED); Error ("Struct expected");
return GetIntNode (0); return GetIntNode (0);
} }
@@ -489,7 +489,7 @@ static ExprNode* DoStruct (ExprNode* Left)
NextToken (); NextToken ();
if (CurTok.Tok != TOK_IDENT) { if (CurTok.Tok != TOK_IDENT) {
/* Print an error */ /* Print an error */
Error (ERR_IDENT_EXPECTED); Error ("Identifier expected");
/* Return an integer expression instead */ /* Return an integer expression instead */
return GetIntNode (0); return GetIntNode (0);
} }
@@ -500,7 +500,7 @@ static ExprNode* DoStruct (ExprNode* Left)
Field = FindStructField (StructType, Ident); Field = FindStructField (StructType, Ident);
if (Field == 0) { if (Field == 0) {
/* Struct field not found */ /* Struct field not found */
Error (ERR_STRUCT_FIELD_MISMATCH, Ident); Error ("Struct/union has no field named `%s'", Ident);
/* Return an integer expression instead */ /* Return an integer expression instead */
return GetIntNode (0); return GetIntNode (0);
} }
@@ -539,7 +539,7 @@ static ExprNode* DoFunctionCall (ExprNode* Left)
if (!IsTypeFunc (Left->Type) && !IsTypeFuncPtr (Left->Type)) { if (!IsTypeFunc (Left->Type) && !IsTypeFuncPtr (Left->Type)) {
/* Call to non function */ /* Call to non function */
Error (ERR_ILLEGAL_FUNC_CALL); Error ("Illegal function call");
/* Free the old tree */ /* Free the old tree */
FreeExprTree (Left); FreeExprTree (Left);
@@ -590,7 +590,7 @@ static ExprNode* DoFunctionCall (ExprNode* Left)
/* Too many arguments. Do we have an open param list? */ /* Too many arguments. Do we have an open param list? */
if ((Func->Flags & FD_ELLIPSIS) == 0) { if ((Func->Flags & FD_ELLIPSIS) == 0) {
/* End of param list reached, no ellipsis */ /* End of param list reached, no ellipsis */
Error (ERR_TOO_MANY_FUNC_ARGS); Error ("Too many function arguments");
} }
/* Assume an ellipsis even in case of errors to avoid an error /* Assume an ellipsis even in case of errors to avoid an error
* message for each other argument. * message for each other argument.
@@ -615,7 +615,7 @@ static ExprNode* DoFunctionCall (ExprNode* Left)
/* Check if we had enough parameters */ /* Check if we had enough parameters */
if (ParamCount < Func->ParamCount) { if (ParamCount < Func->ParamCount) {
Error (ERR_TOO_FEW_FUNC_ARGS); Error ("Too few function arguments");
} }
/* Return the function call node */ /* Return the function call node */
@@ -639,7 +639,7 @@ static ExprNode* DoPostIncDec (ExprNode* Left)
if (Left->LValue == 0) { if (Left->LValue == 0) {
/* Print a diagnostics */ /* Print a diagnostics */
Error (ERR_LVALUE_EXPECTED); Error ("lvalue expected");
/* It is safe to return the operand expression and probably better /* It is safe to return the operand expression and probably better
* than returning an int, since the operand expression already has * than returning an int, since the operand expression already has
@@ -721,7 +721,7 @@ static ExprNode* DoPreIncDec (void)
if (Op->LValue == 0) { if (Op->LValue == 0) {
/* Print a diagnostics */ /* Print a diagnostics */
Error (ERR_LVALUE_EXPECTED); Error ("lvalue expected");
/* It is safe to return the operand expression and probably better /* It is safe to return the operand expression and probably better
* than returning an int, since the operand expression already has * than returning an int, since the operand expression already has
@@ -758,7 +758,7 @@ static ExprNode* DoUnaryPlusMinus (void)
if (!IsClassInt (Op->Type) && !IsClassFloat (Op->Type)) { if (!IsClassInt (Op->Type) && !IsClassFloat (Op->Type)) {
/* Output diagnostic */ /* Output diagnostic */
Error (ERR_SYNTAX); Error ("Syntax error");
/* Free the errorneous node */ /* Free the errorneous node */
FreeExprTree (Op); FreeExprTree (Op);
@@ -817,7 +817,7 @@ static ExprNode* DoComplement (void)
if (!IsClassInt (Op->Type)) { if (!IsClassInt (Op->Type)) {
/* Display diagnostic */ /* Display diagnostic */
Error (ERR_OP_NOT_ALLOWED); Error ("Operation not allowed on this type");
/* Free the errorneous node */ /* Free the errorneous node */
FreeExprTree (Op); FreeExprTree (Op);
@@ -890,7 +890,7 @@ static ExprNode* DoAddress (void)
ExprNode* Root; ExprNode* Root;
/* Print diagnostics */ /* Print diagnostics */
Error (ERR_ILLEGAL_ADDRESS); Error ("Cannot take address of rvalue");
/* Free the problematic tree */ /* Free the problematic tree */
FreeExprTree (Op); FreeExprTree (Op);
@@ -924,7 +924,7 @@ static ExprNode* DoIndirect (void)
if (!IsClassPtr (Op->Type)) { if (!IsClassPtr (Op->Type)) {
/* Print diagnostics */ /* Print diagnostics */
Error (ERR_ILLEGAL_INDIRECT); Error ("Illegal indirection");
/* Free the problematic tree */ /* Free the problematic tree */
FreeExprTree (Op); FreeExprTree (Op);
@@ -1089,7 +1089,7 @@ static ExprNode* DoMul (ExprNode* Left)
/* Check the type of the left operand */ /* Check the type of the left operand */
if (!IsClassInt (Left->Type) && !IsClassFloat (Left->Type)) { if (!IsClassInt (Left->Type) && !IsClassFloat (Left->Type)) {
MError ("Invalid left operand to binary operator `*'"); Error ("Invalid left operand to binary operator `*'");
FreeExprTree (Left); FreeExprTree (Left);
Left = GetIntNode (0); Left = GetIntNode (0);
} }
@@ -1102,7 +1102,7 @@ static ExprNode* DoMul (ExprNode* Left)
/* Check the type of the right operand */ /* Check the type of the right operand */
if (!IsClassInt (Right->Type) && !IsClassFloat (Right->Type)) { if (!IsClassInt (Right->Type) && !IsClassFloat (Right->Type)) {
MError ("Invalid right operand to binary operator `*'"); Error ("Invalid right operand to binary operator `*'");
FreeExprTree (Right); FreeExprTree (Right);
Right = GetIntNode (0); Right = GetIntNode (0);
} }
@@ -1295,7 +1295,7 @@ static ExprNode* AndExpr (void)
if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) { if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
/* Print a diagnostic */ /* Print a diagnostic */
Error (ERR_OP_NOT_ALLOWED); Error ("Operation not allowed for these types");
/* Remove the unneeded nodes */ /* Remove the unneeded nodes */
FreeExprTree (Right); FreeExprTree (Right);
@@ -1358,7 +1358,7 @@ static ExprNode* XorExpr (void)
if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) { if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
/* Print a diagnostic */ /* Print a diagnostic */
Error (ERR_OP_NOT_ALLOWED); Error ("Operation not allowed for these types");
/* Remove the unneeded nodes */ /* Remove the unneeded nodes */
FreeExprTree (Right); FreeExprTree (Right);
@@ -1421,7 +1421,7 @@ static ExprNode* OrExpr (void)
if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) { if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
/* Print a diagnostic */ /* Print a diagnostic */
Error (ERR_OP_NOT_ALLOWED); Error ("Operation not allowed for these types");
/* Remove the unneeded nodes */ /* Remove the unneeded nodes */
FreeExprTree (Right); FreeExprTree (Right);