mirror of
https://github.com/cc65/cc65.git
synced 2024-12-22 12:30:41 +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:
parent
fc3d55d196
commit
a96da498f5
@ -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
|
||||
* 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);
|
||||
AsmErrorSkip ();
|
||||
return;
|
||||
|
@ -417,7 +417,7 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
|
||||
optionalint ();
|
||||
D->Type[0] = T_LONG;
|
||||
D->Type[1] = T_END;
|
||||
break;
|
||||
break;
|
||||
|
||||
case TOK_INT:
|
||||
NextToken ();
|
||||
@ -454,13 +454,13 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
|
||||
D->Type[1] = T_END;
|
||||
break;
|
||||
|
||||
case TOK_INT:
|
||||
case TOK_INT:
|
||||
NextToken ();
|
||||
/* FALL THROUGH */
|
||||
|
||||
default:
|
||||
D->Type[0] = T_UINT;
|
||||
D->Type[1] = T_END;
|
||||
D->Type[1] = T_END;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -497,7 +497,7 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
|
||||
if (SymIsLocal (Entry) && (Entry->Flags & SC_ENUM) == 0) {
|
||||
Error ("Symbol `%s' is already different kind", Entry->Name);
|
||||
}
|
||||
} else {
|
||||
} else {
|
||||
/* Insert entry into table ### */
|
||||
}
|
||||
/* Skip the identifier */
|
||||
@ -626,7 +626,7 @@ static void ParseOldStyleParamList (FuncDesc* F)
|
||||
}
|
||||
|
||||
if (CurTok.Tok == TOK_COMMA) {
|
||||
NextToken ();
|
||||
NextToken ();
|
||||
} else {
|
||||
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. */
|
||||
{
|
||||
unsigned Offs;
|
||||
@ -749,6 +749,14 @@ static FuncDesc* ParseFuncDecl (void)
|
||||
if (Sym == 0 || !IsTypeDef (Sym)) {
|
||||
/* Old style (K&R) function. Assume variable param list. */
|
||||
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. */
|
||||
{
|
||||
|
||||
if (CurTok.Tok == TOK_STAR) {
|
||||
type T = T_PTR;
|
||||
type T = T_PTR;
|
||||
NextToken ();
|
||||
/* Allow optional const or volatile qualifiers */
|
||||
T |= OptionalQualifiers (T_QUAL_NONE);
|
||||
Decl (D, Mode);
|
||||
/* Allow optional const or volatile qualifiers */
|
||||
T |= OptionalQualifiers (T_QUAL_NONE);
|
||||
Decl (Spec, D, Mode);
|
||||
*D->T++ = T;
|
||||
return;
|
||||
} else if (CurTok.Tok == TOK_LPAREN) {
|
||||
NextToken ();
|
||||
Decl (D, Mode);
|
||||
Decl (Spec, D, Mode);
|
||||
ConsumeRParen ();
|
||||
} else if (CurTok.Tok == TOK_FASTCALL) {
|
||||
/* Remember the current type pointer */
|
||||
@ -805,7 +813,7 @@ static void Decl (Declaration* D, unsigned Mode)
|
||||
/* Skip the fastcall token */
|
||||
NextToken ();
|
||||
/* Parse the function */
|
||||
Decl (D, Mode);
|
||||
Decl (Spec, D, Mode);
|
||||
/* Set the fastcall flag */
|
||||
if (!IsTypeFunc (T) && !IsTypeFuncPtr (T)) {
|
||||
Error ("__fastcall__ modifier applied to non function");
|
||||
@ -821,11 +829,11 @@ static void Decl (Declaration* D, unsigned Mode)
|
||||
* - Mode == DM_NEED_IDENT means:
|
||||
* we *must* have a type and a variable identifer.
|
||||
* - 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).
|
||||
* - Mode == DM_ACCEPT_IDENT means:
|
||||
* we *may* have an identifier. If there is an identifier,
|
||||
* it is read, but it is no error, if there is none.
|
||||
* we *may* have an identifier. If there is an identifier,
|
||||
* it is read, but it is no error, if there is none.
|
||||
*/
|
||||
if (Mode == DM_NO_IDENT) {
|
||||
D->Ident[0] = '\0';
|
||||
@ -847,7 +855,7 @@ static void Decl (Declaration* D, unsigned Mode)
|
||||
FuncDesc* F;
|
||||
NextToken ();
|
||||
/* Parse the function declaration */
|
||||
F = ParseFuncDecl ();
|
||||
F = ParseFuncDecl (Spec);
|
||||
*D->T++ = T_FUNC;
|
||||
EncodePtr (D->T, F);
|
||||
D->T += DECODE_SIZE;
|
||||
@ -907,18 +915,18 @@ void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
|
||||
InitDeclaration (D);
|
||||
|
||||
/* Get additional declarators and the identifier */
|
||||
Decl (D, Mode);
|
||||
Decl (Spec, D, Mode);
|
||||
|
||||
/* Add the base type. */
|
||||
TypeCpy (D->T, Spec->Type);
|
||||
|
||||
/* Check the size of the generated type */
|
||||
if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type) && SizeOf (D->Type) >= 0x10000) {
|
||||
if (D->Ident[0] != '\0') {
|
||||
Error ("Size of `%s' is invalid", D->Ident);
|
||||
} else {
|
||||
Error ("Invalid size");
|
||||
}
|
||||
if (D->Ident[0] != '\0') {
|
||||
Error ("Size of `%s' is invalid", D->Ident);
|
||||
} else {
|
||||
Error ("Invalid size");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -913,9 +913,9 @@ static int primary (ExprDesc* lval)
|
||||
* function, we have to add some address calculations, and the
|
||||
* 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 */
|
||||
g_leavariadic (Sym->V.Offs - GetParamSize (CurrentFunc));
|
||||
g_leavariadic (Sym->V.Offs - F_GetParamSize (CurrentFunc));
|
||||
lval->Flags = E_MEXPR;
|
||||
lval->ConstVal = 0;
|
||||
} else {
|
||||
|
@ -51,7 +51,8 @@
|
||||
#define FD_VARIADIC 0x0008U /* Function with variable param list */
|
||||
#define FD_FASTCALL 0x0010U /* __fastcall__ 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 */
|
||||
#define FD_IGNORE (FD_IMPLICIT | FD_UNNAMED_PARAMS)
|
||||
|
@ -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 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 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 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 */
|
||||
{
|
||||
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 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 (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 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 */
|
||||
{
|
||||
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
|
||||
* 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
|
||||
* nothing if there is no reserved local space.
|
||||
*/
|
||||
{
|
||||
if (F->Reserved > 0) {
|
||||
|
||||
/* Create space on the stack */
|
||||
g_space (F->Reserved);
|
||||
/* Create space on the stack */
|
||||
g_space (F->Reserved);
|
||||
|
||||
/* Correct the stack pointer */
|
||||
oursp -= F->Reserved;
|
||||
/* Correct the stack pointer */
|
||||
oursp -= F->Reserved;
|
||||
|
||||
/* Nothing more reserved */
|
||||
F->Reserved = 0;
|
||||
/* Nothing more reserved */
|
||||
F->Reserved = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,7 +292,7 @@ void NewFunc (SymEntry* Func)
|
||||
}
|
||||
|
||||
/* Generate function entry code if needed */
|
||||
g_enter (TypeOf (Func->Type), GetParamSize (CurrentFunc));
|
||||
g_enter (TypeOf (Func->Type), F_GetParamSize (CurrentFunc));
|
||||
|
||||
/* Setup the stack */
|
||||
oursp = 0;
|
||||
@ -305,16 +321,16 @@ void NewFunc (SymEntry* Func)
|
||||
/* If the function has a return type but no return statement, flag
|
||||
* a warning
|
||||
*/
|
||||
IsVoidFunc = HasVoidReturn (CurrentFunc);
|
||||
IsVoidFunc = F_HasVoidReturn (CurrentFunc);
|
||||
#if 0
|
||||
/* Does not work reliably */
|
||||
if (!IsVoidFunc && !HadReturn) {
|
||||
if (!F_IsVoidFunc && !HadReturn) {
|
||||
Warning ("Function `%s' should return a value", Func->Name);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Output the function exit code label */
|
||||
g_defcodelabel (GetRetLab (CurrentFunc));
|
||||
g_defcodelabel (F_GetRetLab (CurrentFunc));
|
||||
|
||||
/* Restore the register variables */
|
||||
RestoreRegVars (!IsVoidFunc);
|
||||
|
@ -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 */
|
||||
|
||||
unsigned GetParamCount (const Function* F);
|
||||
unsigned F_GetParamCount (const Function* F);
|
||||
/* 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 */
|
||||
|
||||
type* GetReturnType (Function* F);
|
||||
type* F_GetReturnType (Function* F);
|
||||
/* 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 */
|
||||
|
||||
int IsVariadic (const Function* F);
|
||||
int F_IsVariadic (const Function* F);
|
||||
/* 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 */
|
||||
|
||||
int GetTopLevelSP (const Function* F);
|
||||
int F_GetTopLevelSP (const Function* F);
|
||||
/* 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
|
||||
* offset.
|
||||
*/
|
||||
|
||||
void AllocLocalSpace (Function* F);
|
||||
void F_AllocLocalSpace (Function* F);
|
||||
/* Allocate any local space previously reserved. The function will do
|
||||
* nothing if there is no reserved local space.
|
||||
*/
|
||||
|
@ -184,7 +184,7 @@ static void ParseOneDecl (const DeclSpec* Spec)
|
||||
ExprDesc lval;
|
||||
|
||||
/* Allocate previously reserved local space */
|
||||
AllocLocalSpace (CurrentFunc);
|
||||
F_AllocLocalSpace (CurrentFunc);
|
||||
|
||||
/* Skip the '=' */
|
||||
NextToken ();
|
||||
@ -215,7 +215,7 @@ static void ParseOneDecl (const DeclSpec* Spec)
|
||||
/* Non-initialized local variable. Just keep track of
|
||||
* the space needed.
|
||||
*/
|
||||
SymData = ReserveLocalSpace (CurrentFunc, Size);
|
||||
SymData = F_ReserveLocalSpace (CurrentFunc, Size);
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -377,7 +377,7 @@ void DeclareLocals (void)
|
||||
}
|
||||
|
||||
/* 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
|
||||
* the stack checking routine if stack checks are enabled.
|
||||
@ -404,7 +404,7 @@ void RestoreRegVars (int HaveResult)
|
||||
}
|
||||
|
||||
/* Save the accumulator if needed */
|
||||
if (!HasVoidReturn (CurrentFunc) && HaveResult) {
|
||||
if (!F_HasVoidReturn (CurrentFunc) && HaveResult) {
|
||||
g_save (CF_CHAR | CF_FORCECHAR);
|
||||
}
|
||||
|
||||
@ -449,7 +449,7 @@ void RestoreRegVars (int HaveResult)
|
||||
}
|
||||
|
||||
/* Restore the accumulator if needed */
|
||||
if (!HasVoidReturn (CurrentFunc) && HaveResult) {
|
||||
if (!F_HasVoidReturn (CurrentFunc) && HaveResult) {
|
||||
g_restore (CF_CHAR | CF_FORCECHAR);
|
||||
}
|
||||
}
|
||||
|
@ -547,7 +547,7 @@ void NextToken (void)
|
||||
} else if (strcmp (token, "__func__") == 0) {
|
||||
/* __func__ is only defined in functions */
|
||||
if (CurrentFunc) {
|
||||
NextTok.IVal = AddLiteral (GetFuncName (CurrentFunc));
|
||||
NextTok.IVal = AddLiteral (F_GetFuncName (CurrentFunc));
|
||||
NextTok.Tok = TOK_SCONST;
|
||||
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.
|
||||
* This routine is used for error recovery.
|
||||
*/
|
||||
{
|
||||
{
|
||||
while (CurTok.Tok != TOK_CEOF) {
|
||||
|
||||
/* Check if the current token is in the token list */
|
||||
|
@ -242,7 +242,7 @@ static void ReturnStatement (void)
|
||||
|
||||
NextToken ();
|
||||
if (CurTok.Tok != TOK_SEMI) {
|
||||
if (HasVoidReturn (CurrentFunc)) {
|
||||
if (F_HasVoidReturn (CurrentFunc)) {
|
||||
Error ("Returning a value in function with return type void");
|
||||
}
|
||||
|
||||
@ -250,18 +250,18 @@ static void ReturnStatement (void)
|
||||
expression (&lval);
|
||||
|
||||
/* Convert the return value to the type of the function result */
|
||||
if (!HasVoidReturn (CurrentFunc)) {
|
||||
assignadjust (GetReturnType (CurrentFunc), &lval);
|
||||
if (!F_HasVoidReturn (CurrentFunc)) {
|
||||
assignadjust (F_GetReturnType (CurrentFunc), &lval);
|
||||
}
|
||||
} else if (!HasVoidReturn (CurrentFunc)) {
|
||||
Error ("Function `%s' must return a value", GetFuncName (CurrentFunc));
|
||||
} else if (!F_HasVoidReturn (CurrentFunc) && !F_HasOldStyleIntRet (CurrentFunc)) {
|
||||
Error ("Function `%s' must return a value", F_GetFuncName (CurrentFunc));
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
g_jump (GetRetLab (CurrentFunc));
|
||||
g_jump (F_GetRetLab (CurrentFunc));
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user