1
0
mirror of https://github.com/cc65/cc65.git synced 2025-01-10 03:30:05 +00:00

Renamed the functions working with "struct Function".

Fixed a problem with K&R functions: In a function with no return type
specified, the compiler did not allow a simple "return" statement. However,
there was no "void" type at that time, so it was not possible to specify
something else. The solution is to allow omission of a return value in a
K&R function with an implicit int type. Other types or an explicit int is
still checked.


git-svn-id: svn://svn.cc65.org/cc65/trunk@1302 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2002-06-12 12:12:04 +00:00
parent fc3d55d196
commit a96da498f5
9 changed files with 103 additions and 72 deletions

View File

@ -254,7 +254,7 @@ static void ParseLVarArg (StrBuf* T, unsigned Arg)
* don't have a fixed stack offset, so check it and bail out with an error * don't have a fixed stack offset, so check it and bail out with an error
* if this is the case. * if this is the case.
*/ */
if ((Sym->Flags & SC_PARAM) == SC_PARAM && IsVariadic (CurrentFunc)) { if ((Sym->Flags & SC_PARAM) == SC_PARAM && F_IsVariadic (CurrentFunc)) {
Error ("Argument %u has no fixed stack offset", Arg); Error ("Argument %u has no fixed stack offset", Arg);
AsmErrorSkip (); AsmErrorSkip ();
return; return;

View File

@ -417,7 +417,7 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
optionalint (); optionalint ();
D->Type[0] = T_LONG; D->Type[0] = T_LONG;
D->Type[1] = T_END; D->Type[1] = T_END;
break; break;
case TOK_INT: case TOK_INT:
NextToken (); NextToken ();
@ -454,13 +454,13 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
D->Type[1] = T_END; D->Type[1] = T_END;
break; break;
case TOK_INT: case TOK_INT:
NextToken (); NextToken ();
/* FALL THROUGH */ /* FALL THROUGH */
default: default:
D->Type[0] = T_UINT; D->Type[0] = T_UINT;
D->Type[1] = T_END; D->Type[1] = T_END;
break; break;
} }
break; break;
@ -497,7 +497,7 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
if (SymIsLocal (Entry) && (Entry->Flags & SC_ENUM) == 0) { if (SymIsLocal (Entry) && (Entry->Flags & SC_ENUM) == 0) {
Error ("Symbol `%s' is already different kind", Entry->Name); Error ("Symbol `%s' is already different kind", Entry->Name);
} }
} else { } else {
/* Insert entry into table ### */ /* Insert entry into table ### */
} }
/* Skip the identifier */ /* Skip the identifier */
@ -626,7 +626,7 @@ static void ParseOldStyleParamList (FuncDesc* F)
} }
if (CurTok.Tok == TOK_COMMA) { if (CurTok.Tok == TOK_COMMA) {
NextToken (); NextToken ();
} else { } else {
break; break;
} }
@ -720,7 +720,7 @@ static void ParseAnsiParamList (FuncDesc* F)
static FuncDesc* ParseFuncDecl (void) static FuncDesc* ParseFuncDecl (const DeclSpec* Spec)
/* Parse the argument list of a function. */ /* Parse the argument list of a function. */
{ {
unsigned Offs; unsigned Offs;
@ -749,6 +749,14 @@ static FuncDesc* ParseFuncDecl (void)
if (Sym == 0 || !IsTypeDef (Sym)) { if (Sym == 0 || !IsTypeDef (Sym)) {
/* Old style (K&R) function. Assume variable param list. */ /* Old style (K&R) function. Assume variable param list. */
F->Flags |= (FD_OLDSTYLE | FD_VARIADIC); F->Flags |= (FD_OLDSTYLE | FD_VARIADIC);
/* Check for an implicit int return in the K&R function */
if ((Spec->Flags & DS_DEF_TYPE) != 0 &&
Spec->Type[0] == T_INT &&
Spec->Type[1] == T_END) {
/* Function has an implicit int return */
F->Flags |= FD_OLDSTYLE_INTRET;
}
} }
} }
@ -783,21 +791,21 @@ static FuncDesc* ParseFuncDecl (void)
static void Decl (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. */
{ {
if (CurTok.Tok == TOK_STAR) { if (CurTok.Tok == TOK_STAR) {
type T = T_PTR; type T = T_PTR;
NextToken (); NextToken ();
/* Allow optional const or volatile qualifiers */ /* Allow optional const or volatile qualifiers */
T |= OptionalQualifiers (T_QUAL_NONE); T |= OptionalQualifiers (T_QUAL_NONE);
Decl (D, Mode); Decl (Spec, D, Mode);
*D->T++ = T; *D->T++ = T;
return; return;
} else if (CurTok.Tok == TOK_LPAREN) { } else if (CurTok.Tok == TOK_LPAREN) {
NextToken (); NextToken ();
Decl (D, Mode); Decl (Spec, D, Mode);
ConsumeRParen (); ConsumeRParen ();
} else if (CurTok.Tok == TOK_FASTCALL) { } else if (CurTok.Tok == TOK_FASTCALL) {
/* Remember the current type pointer */ /* Remember the current type pointer */
@ -805,7 +813,7 @@ static void Decl (Declaration* D, unsigned Mode)
/* Skip the fastcall token */ /* Skip the fastcall token */
NextToken (); NextToken ();
/* Parse the function */ /* Parse the function */
Decl (D, Mode); Decl (Spec, D, Mode);
/* Set the fastcall flag */ /* Set the fastcall flag */
if (!IsTypeFunc (T) && !IsTypeFuncPtr (T)) { if (!IsTypeFunc (T) && !IsTypeFuncPtr (T)) {
Error ("__fastcall__ modifier applied to non function"); Error ("__fastcall__ modifier applied to non function");
@ -821,11 +829,11 @@ static void Decl (Declaration* D, unsigned Mode)
* - Mode == DM_NEED_IDENT means: * - Mode == DM_NEED_IDENT means:
* we *must* have a type and a variable identifer. * we *must* have a type and a variable identifer.
* - Mode == DM_NO_IDENT means: * - Mode == DM_NO_IDENT means:
* we must have a type but no variable identifer * we must have a type but no variable identifer
* (if there is one, it's not read). * (if there is one, it's not read).
* - Mode == DM_ACCEPT_IDENT means: * - Mode == DM_ACCEPT_IDENT means:
* we *may* have an identifier. If there is an identifier, * we *may* have an identifier. If there is an identifier,
* it is read, but it is no error, if there is none. * it is read, but it is no error, if there is none.
*/ */
if (Mode == DM_NO_IDENT) { if (Mode == DM_NO_IDENT) {
D->Ident[0] = '\0'; D->Ident[0] = '\0';
@ -847,7 +855,7 @@ static void Decl (Declaration* D, unsigned Mode)
FuncDesc* F; FuncDesc* F;
NextToken (); NextToken ();
/* Parse the function declaration */ /* Parse the function declaration */
F = ParseFuncDecl (); F = ParseFuncDecl (Spec);
*D->T++ = T_FUNC; *D->T++ = T_FUNC;
EncodePtr (D->T, F); EncodePtr (D->T, F);
D->T += DECODE_SIZE; D->T += DECODE_SIZE;
@ -907,18 +915,18 @@ void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
InitDeclaration (D); InitDeclaration (D);
/* Get additional declarators and the identifier */ /* Get additional declarators and the identifier */
Decl (D, Mode); Decl (Spec, D, Mode);
/* Add the base type. */ /* Add the base type. */
TypeCpy (D->T, Spec->Type); TypeCpy (D->T, Spec->Type);
/* Check the size of the generated type */ /* Check the size of the generated type */
if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type) && SizeOf (D->Type) >= 0x10000) { if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type) && SizeOf (D->Type) >= 0x10000) {
if (D->Ident[0] != '\0') { if (D->Ident[0] != '\0') {
Error ("Size of `%s' is invalid", D->Ident); Error ("Size of `%s' is invalid", D->Ident);
} else { } else {
Error ("Invalid size"); Error ("Invalid size");
} }
} }
} }

View File

@ -913,9 +913,9 @@ static int primary (ExprDesc* lval)
* function, we have to add some address calculations, and the * function, we have to add some address calculations, and the
* address is not const. * address is not const.
*/ */
if ((Sym->Flags & SC_PARAM) == SC_PARAM && IsVariadic (CurrentFunc)) { if ((Sym->Flags & SC_PARAM) == SC_PARAM && F_IsVariadic (CurrentFunc)) {
/* Variadic parameter */ /* Variadic parameter */
g_leavariadic (Sym->V.Offs - GetParamSize (CurrentFunc)); g_leavariadic (Sym->V.Offs - F_GetParamSize (CurrentFunc));
lval->Flags = E_MEXPR; lval->Flags = E_MEXPR;
lval->ConstVal = 0; lval->ConstVal = 0;
} else { } else {

View File

@ -51,7 +51,8 @@
#define FD_VARIADIC 0x0008U /* Function with variable param list */ #define FD_VARIADIC 0x0008U /* Function with variable param list */
#define FD_FASTCALL 0x0010U /* __fastcall__ function */ #define FD_FASTCALL 0x0010U /* __fastcall__ function */
#define FD_OLDSTYLE 0x0020U /* Old style (K&R) function */ #define FD_OLDSTYLE 0x0020U /* Old style (K&R) function */
#define FD_UNNAMED_PARAMS 0x0040U /* Function has unnamed params */ #define FD_OLDSTYLE_INTRET 0x0040U /* K&R func has implicit int return */
#define FD_UNNAMED_PARAMS 0x0080U /* Function has unnamed params */
/* Bits that must be ignored when comparing funcs */ /* Bits that must be ignored when comparing funcs */
#define FD_IGNORE (FD_IMPLICIT | FD_UNNAMED_PARAMS) #define FD_IGNORE (FD_IMPLICIT | FD_UNNAMED_PARAMS)

View File

@ -109,7 +109,7 @@ static void FreeFunction (Function* F)
const char* GetFuncName (const Function* F) const char* F_GetFuncName (const Function* F)
/* Return the name of the current function */ /* Return the name of the current function */
{ {
return F->FuncEntry->Name; return F->FuncEntry->Name;
@ -117,7 +117,7 @@ const char* GetFuncName (const Function* F)
unsigned GetParamCount (const Function* F) unsigned F_GetParamCount (const Function* F)
/* Return the parameter count for the current function */ /* Return the parameter count for the current function */
{ {
return F->Desc->ParamCount; return F->Desc->ParamCount;
@ -125,7 +125,7 @@ unsigned GetParamCount (const Function* F)
unsigned GetParamSize (const Function* F) unsigned F_GetParamSize (const Function* F)
/* Return the parameter size for the current function */ /* Return the parameter size for the current function */
{ {
return F->Desc->ParamSize; return F->Desc->ParamSize;
@ -133,7 +133,7 @@ unsigned GetParamSize (const Function* F)
type* GetReturnType (Function* F) type* F_GetReturnType (Function* F)
/* Get the return type for the function */ /* Get the return type for the function */
{ {
return F->ReturnType; return F->ReturnType;
@ -141,7 +141,7 @@ type* GetReturnType (Function* F)
int HasVoidReturn (const Function* F) int F_HasVoidReturn (const Function* F)
/* Return true if the function does not have a return value */ /* Return true if the function does not have a return value */
{ {
return IsTypeVoid (F->ReturnType); return IsTypeVoid (F->ReturnType);
@ -149,15 +149,31 @@ int HasVoidReturn (const Function* F)
int IsVariadic (const Function* F) int F_IsVariadic (const Function* F)
/* Return true if this is a variadic function */ /* Return true if this is a variadic function */
{ {
return (F->Desc->Flags & FD_VARIADIC) != 0; return (F->Desc->Flags & FD_OLDSTYLE) != 0;
} }
unsigned GetRetLab (const Function* F) int F_IsOldStyle (const Function* F)
/* Return true if this is an old style (K&R) function */
{
return (F->Desc->Flags & FD_OLDSTYLE) != 0;
}
int F_HasOldStyleIntRet (const Function* F)
/* Return true if this is an old style (K&R) function with an implicit int return */
{
return (F->Desc->Flags & FD_OLDSTYLE_INTRET) != 0;
}
unsigned F_GetRetLab (const Function* F)
/* Return the return jump label */ /* Return the return jump label */
{ {
return F->RetLab; return F->RetLab;
@ -165,7 +181,7 @@ unsigned GetRetLab (const Function* F)
int GetTopLevelSP (const Function* F) int F_GetTopLevelSP (const Function* F)
/* Get the value of the stack pointer on function top level */ /* Get the value of the stack pointer on function top level */
{ {
return F->TopLevelSP; return F->TopLevelSP;
@ -173,7 +189,7 @@ int GetTopLevelSP (const Function* F)
int ReserveLocalSpace (Function* F, unsigned Size) int F_ReserveLocalSpace (Function* F, unsigned Size)
/* Reserve (but don't allocate) the given local space and return the stack /* Reserve (but don't allocate) the given local space and return the stack
* offset. * offset.
*/ */
@ -184,21 +200,21 @@ int ReserveLocalSpace (Function* F, unsigned Size)
void AllocLocalSpace (Function* F) void F_AllocLocalSpace (Function* F)
/* Allocate any local space previously reserved. The function will do /* Allocate any local space previously reserved. The function will do
* nothing if there is no reserved local space. * nothing if there is no reserved local space.
*/ */
{ {
if (F->Reserved > 0) { if (F->Reserved > 0) {
/* Create space on the stack */ /* Create space on the stack */
g_space (F->Reserved); g_space (F->Reserved);
/* Correct the stack pointer */ /* Correct the stack pointer */
oursp -= F->Reserved; oursp -= F->Reserved;
/* Nothing more reserved */ /* Nothing more reserved */
F->Reserved = 0; F->Reserved = 0;
} }
} }
@ -276,7 +292,7 @@ void NewFunc (SymEntry* Func)
} }
/* Generate function entry code if needed */ /* Generate function entry code if needed */
g_enter (TypeOf (Func->Type), GetParamSize (CurrentFunc)); g_enter (TypeOf (Func->Type), F_GetParamSize (CurrentFunc));
/* Setup the stack */ /* Setup the stack */
oursp = 0; oursp = 0;
@ -305,16 +321,16 @@ void NewFunc (SymEntry* Func)
/* If the function has a return type but no return statement, flag /* If the function has a return type but no return statement, flag
* a warning * a warning
*/ */
IsVoidFunc = HasVoidReturn (CurrentFunc); IsVoidFunc = F_HasVoidReturn (CurrentFunc);
#if 0 #if 0
/* Does not work reliably */ /* Does not work reliably */
if (!IsVoidFunc && !HadReturn) { if (!F_IsVoidFunc && !HadReturn) {
Warning ("Function `%s' should return a value", Func->Name); Warning ("Function `%s' should return a value", Func->Name);
} }
#endif #endif
/* Output the function exit code label */ /* Output the function exit code label */
g_defcodelabel (GetRetLab (CurrentFunc)); g_defcodelabel (F_GetRetLab (CurrentFunc));
/* Restore the register variables */ /* Restore the register variables */
RestoreRegVars (!IsVoidFunc); RestoreRegVars (!IsVoidFunc);

View File

@ -58,36 +58,42 @@ extern Function* CurrentFunc;
const char* GetFuncName (const Function* F); const char* F_GetFuncName (const Function* F);
/* Return the name of the current function */ /* Return the name of the current function */
unsigned GetParamCount (const Function* F); unsigned F_GetParamCount (const Function* F);
/* Return the parameter count for the current function */ /* Return the parameter count for the current function */
unsigned GetParamSize (const Function* F); unsigned F_GetParamSize (const Function* F);
/* Return the parameter size for the current function */ /* Return the parameter size for the current function */
type* GetReturnType (Function* F); type* F_GetReturnType (Function* F);
/* Get the return type for the function */ /* Get the return type for the function */
int HasVoidReturn (const Function* F); int F_HasVoidReturn (const Function* F);
/* Return true if the function does not have a return value */ /* Return true if the function does not have a return value */
int IsVariadic (const Function* F); int F_IsVariadic (const Function* F);
/* Return true if this is a variadic function */ /* Return true if this is a variadic function */
unsigned GetRetLab (const Function* F); int F_IsOldStyle (const Function* F);
/* Return true if this is an old style (K&R) function */
int F_HasOldStyleIntRet (const Function* F);
/* Return true if this is an old style (K&R) function with an implicit int return */
unsigned F_GetRetLab (const Function* F);
/* Return the return jump label */ /* Return the return jump label */
int GetTopLevelSP (const Function* F); int F_GetTopLevelSP (const Function* F);
/* Get the value of the stack pointer on function top level */ /* Get the value of the stack pointer on function top level */
int ReserveLocalSpace (Function* F, unsigned Size); int F_ReserveLocalSpace (Function* F, unsigned Size);
/* Reserve (but don't allocate) the given local space and return the stack /* Reserve (but don't allocate) the given local space and return the stack
* offset. * offset.
*/ */
void AllocLocalSpace (Function* F); void F_AllocLocalSpace (Function* F);
/* Allocate any local space previously reserved. The function will do /* Allocate any local space previously reserved. The function will do
* nothing if there is no reserved local space. * nothing if there is no reserved local space.
*/ */

View File

@ -184,7 +184,7 @@ static void ParseOneDecl (const DeclSpec* Spec)
ExprDesc lval; ExprDesc lval;
/* Allocate previously reserved local space */ /* Allocate previously reserved local space */
AllocLocalSpace (CurrentFunc); F_AllocLocalSpace (CurrentFunc);
/* Skip the '=' */ /* Skip the '=' */
NextToken (); NextToken ();
@ -215,7 +215,7 @@ static void ParseOneDecl (const DeclSpec* Spec)
/* Non-initialized local variable. Just keep track of /* Non-initialized local variable. Just keep track of
* the space needed. * the space needed.
*/ */
SymData = ReserveLocalSpace (CurrentFunc, Size); SymData = F_ReserveLocalSpace (CurrentFunc, Size);
} }
} else { } else {
@ -377,7 +377,7 @@ void DeclareLocals (void)
} }
/* Be sure to allocate any reserved space for locals */ /* Be sure to allocate any reserved space for locals */
AllocLocalSpace (CurrentFunc); F_AllocLocalSpace (CurrentFunc);
/* In case we've allocated local variables in this block, emit a call to /* In case we've allocated local variables in this block, emit a call to
* the stack checking routine if stack checks are enabled. * the stack checking routine if stack checks are enabled.
@ -404,7 +404,7 @@ void RestoreRegVars (int HaveResult)
} }
/* Save the accumulator if needed */ /* Save the accumulator if needed */
if (!HasVoidReturn (CurrentFunc) && HaveResult) { if (!F_HasVoidReturn (CurrentFunc) && HaveResult) {
g_save (CF_CHAR | CF_FORCECHAR); g_save (CF_CHAR | CF_FORCECHAR);
} }
@ -449,7 +449,7 @@ void RestoreRegVars (int HaveResult)
} }
/* Restore the accumulator if needed */ /* Restore the accumulator if needed */
if (!HasVoidReturn (CurrentFunc) && HaveResult) { if (!F_HasVoidReturn (CurrentFunc) && HaveResult) {
g_restore (CF_CHAR | CF_FORCECHAR); g_restore (CF_CHAR | CF_FORCECHAR);
} }
} }

View File

@ -547,7 +547,7 @@ void NextToken (void)
} else if (strcmp (token, "__func__") == 0) { } else if (strcmp (token, "__func__") == 0) {
/* __func__ is only defined in functions */ /* __func__ is only defined in functions */
if (CurrentFunc) { if (CurrentFunc) {
NextTok.IVal = AddLiteral (GetFuncName (CurrentFunc)); NextTok.IVal = AddLiteral (F_GetFuncName (CurrentFunc));
NextTok.Tok = TOK_SCONST; NextTok.Tok = TOK_SCONST;
return; return;
} }
@ -805,7 +805,7 @@ void SkipTokens (const token_t* TokenList, unsigned TokenCount)
/* Skip tokens until we reach TOK_CEOF or a token in the given token list. /* Skip tokens until we reach TOK_CEOF or a token in the given token list.
* This routine is used for error recovery. * This routine is used for error recovery.
*/ */
{ {
while (CurTok.Tok != TOK_CEOF) { while (CurTok.Tok != TOK_CEOF) {
/* Check if the current token is in the token list */ /* Check if the current token is in the token list */

View File

@ -242,7 +242,7 @@ static void ReturnStatement (void)
NextToken (); NextToken ();
if (CurTok.Tok != TOK_SEMI) { if (CurTok.Tok != TOK_SEMI) {
if (HasVoidReturn (CurrentFunc)) { if (F_HasVoidReturn (CurrentFunc)) {
Error ("Returning a value in function with return type void"); Error ("Returning a value in function with return type void");
} }
@ -250,18 +250,18 @@ static void ReturnStatement (void)
expression (&lval); expression (&lval);
/* Convert the return value to the type of the function result */ /* Convert the return value to the type of the function result */
if (!HasVoidReturn (CurrentFunc)) { if (!F_HasVoidReturn (CurrentFunc)) {
assignadjust (GetReturnType (CurrentFunc), &lval); assignadjust (F_GetReturnType (CurrentFunc), &lval);
} }
} else if (!HasVoidReturn (CurrentFunc)) { } else if (!F_HasVoidReturn (CurrentFunc) && !F_HasOldStyleIntRet (CurrentFunc)) {
Error ("Function `%s' must return a value", GetFuncName (CurrentFunc)); Error ("Function `%s' must return a value", F_GetFuncName (CurrentFunc));
} }
/* Cleanup the stack in case we're inside a block with locals */ /* Cleanup the stack in case we're inside a block with locals */
g_space (oursp - GetTopLevelSP (CurrentFunc)); g_space (oursp - F_GetTopLevelSP (CurrentFunc));
/* Output a jump to the function exit code */ /* Output a jump to the function exit code */
g_jump (GetRetLab (CurrentFunc)); g_jump (F_GetRetLab (CurrentFunc));
} }