* 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;
optionalint ();
D->Type[0] = T_LONG;
D->Type[1] = T_END;
- break;
+ break;
case TOK_INT:
NextToken ();
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;
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 */
}
if (CurTok.Tok == TOK_COMMA) {
- NextToken ();
+ NextToken ();
} else {
break;
}
-static FuncDesc* ParseFuncDecl (void)
+static FuncDesc* ParseFuncDecl (const DeclSpec* Spec)
/* Parse the argument list of a function. */
{
unsigned Offs;
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;
+ }
}
}
-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 */
/* 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");
* - 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';
FuncDesc* F;
NextToken ();
/* Parse the function declaration */
- F = ParseFuncDecl ();
+ F = ParseFuncDecl (Spec);
*D->T++ = T_FUNC;
EncodePtr (D->T, F);
D->T += DECODE_SIZE;
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");
+ }
}
}
* 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 {
#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)
-const char* GetFuncName (const Function* F)
+const char* F_GetFuncName (const Function* F)
/* Return the name of the current function */
{
return F->FuncEntry->Name;
-unsigned GetParamCount (const Function* F)
+unsigned F_GetParamCount (const Function* F)
/* Return the parameter count for the current function */
{
return F->Desc->ParamCount;
-unsigned GetParamSize (const Function* F)
+unsigned F_GetParamSize (const Function* F)
/* Return the parameter size for the current function */
{
return F->Desc->ParamSize;
-type* GetReturnType (Function* F)
+type* F_GetReturnType (Function* F)
/* Get the return type for the function */
{
return F->ReturnType;
-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);
-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;
-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;
-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.
*/
{
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;
}
}
}
/* 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;
/* 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);
-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.
*/
ExprDesc lval;
/* Allocate previously reserved local space */
- AllocLocalSpace (CurrentFunc);
+ F_AllocLocalSpace (CurrentFunc);
/* Skip the '=' */
NextToken ();
/* Non-initialized local variable. Just keep track of
* the space needed.
*/
- SymData = ReserveLocalSpace (CurrentFunc, Size);
+ SymData = F_ReserveLocalSpace (CurrentFunc, Size);
}
} else {
}
/* 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.
}
/* Save the accumulator if needed */
- if (!HasVoidReturn (CurrentFunc) && HaveResult) {
+ if (!F_HasVoidReturn (CurrentFunc) && HaveResult) {
g_save (CF_CHAR | CF_FORCECHAR);
}
}
/* Restore the accumulator if needed */
- if (!HasVoidReturn (CurrentFunc) && HaveResult) {
+ if (!F_HasVoidReturn (CurrentFunc) && HaveResult) {
g_restore (CF_CHAR | CF_FORCECHAR);
}
}
} 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;
}
/* 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 */
NextToken ();
if (CurTok.Tok != TOK_SEMI) {
- if (HasVoidReturn (CurrentFunc)) {
+ if (F_HasVoidReturn (CurrentFunc)) {
Error ("Returning a value in function with return type 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));
}