X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Flocals.c;h=024c1c5fc457344f559ced2e3da1964939c2b85b;hb=0614078198d69d3d891fe669e4703e8a60beddca;hp=626acaa6b0473b8a8a54761d598429c310c2480c;hpb=faf58a822060553358cc48bbf4e2d557bdd8e260;p=cc65 diff --git a/src/cc65/locals.c b/src/cc65/locals.c index 626acaa6b..024c1c5fc 100644 --- a/src/cc65/locals.c +++ b/src/cc65/locals.c @@ -1,12 +1,12 @@ /*****************************************************************************/ /* */ -/* locals.c */ +/* locals.c */ /* */ -/* Local variable handling for the cc65 C compiler */ +/* Local variable handling for the cc65 C compiler */ /* */ /* */ /* */ -/* (C) 2000-2009, Ullrich von Bassewitz */ +/* (C) 2000-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -52,11 +52,12 @@ #include "standard.h" #include "symtab.h" #include "typeconv.h" +#include "input.h" /*****************************************************************************/ -/* Code */ +/* Code */ /*****************************************************************************/ @@ -96,8 +97,8 @@ static void AllocStorage (unsigned Label, void (*UseSeg) (), unsigned Size) static void ParseRegisterDecl (Declaration* Decl, int Reg) /* Parse the declaration of a register variable. Reg is the offset of the - * variable in the register bank. - */ +** variable in the register bank. +*/ { SymEntry* Sym; @@ -112,9 +113,9 @@ static void ParseRegisterDecl (Declaration* Decl, int Reg) g_save_regvars (Reg, Size); /* Add the symbol to the symbol table. We do that now, because for register - * variables the current stack pointer is implicitly used as location for - * the save area. - */ + ** variables the current stack pointer is implicitly used as location for + ** the save area. + */ Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, Reg); /* Check for an optional initialization */ @@ -129,18 +130,18 @@ static void ParseRegisterDecl (Declaration* Decl, int Reg) if (IsCompound) { /* Switch to read only data and define a label for the - * initialization data. - */ + ** initialization data. + */ unsigned InitLabel = AllocLabel (g_userodata); /* Parse the initialization generating a memory image of the - * data in the RODATA segment. The function does return the size - * of the initialization data, which may be greater than the - * actual size of the type, if the type is a structure with a - * flexible array member that has been initialized. Since we must - * know the size of the data in advance for register variables, - * we cannot allow that here. - */ + ** data in the RODATA segment. The function does return the size + ** of the initialization data, which may be greater than the + ** actual size of the type, if the type is a structure with a + ** flexible array member that has been initialized. Since we must + ** know the size of the data in advance for register variables, + ** we cannot allow that here. + */ if (ParseInit (Sym->Type) != Size) { Error ("Cannot initialize flexible array members of storage class `register'"); } @@ -192,8 +193,8 @@ static void ParseAutoDecl (Declaration* Decl) if (IS_Get (&StaticLocals) == 0) { /* Add the symbol to the symbol table. The stack offset we use here - * may get corrected later. - */ + ** may get corrected later. + */ Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, F_GetStackPtr (CurrentFunc) - (int) Size); @@ -210,32 +211,32 @@ static void ParseAutoDecl (Declaration* Decl) if (IsCompound) { /* Switch to read only data and define a label for the - * initialization data. - */ + ** initialization data. + */ unsigned InitLabel = AllocLabel (g_userodata); /* Parse the initialization generating a memory image of the - * data in the RODATA segment. The function will return the - * actual size of the initialization data, which may be - * greater than the size of the variable if it is a struct - * that contains a flexible array member and we're not in - * ANSI mode. - */ + ** data in the RODATA segment. The function will return the + ** actual size of the initialization data, which may be + ** greater than the size of the variable if it is a struct + ** that contains a flexible array member and we're not in + ** ANSI mode. + */ Size = ParseInit (Sym->Type); /* Now reserve space for the variable on the stack and correct - * the offset in the symbol table entry. - */ + ** the offset in the symbol table entry. + */ Sym->V.Offs = F_ReserveLocalSpace (CurrentFunc, Size); /* Next, allocate the space on the stack. This means that the - * variable is now located at offset 0 from the current sp. - */ + ** variable is now located at offset 0 from the current sp. + */ F_AllocLocalSpace (CurrentFunc); /* Generate code to copy the initialization data into the - * variable space - */ + ** variable space + */ g_initauto (InitLabel, Size); } else { @@ -253,8 +254,8 @@ static void ParseAutoDecl (Declaration* Decl) TypeConversion (&Expr, Sym->Type); /* If the value is not const, load it into the primary. - * Otherwise pass the information to the code generator. - */ + ** Otherwise pass the information to the code generator. + */ if (ED_IsConstAbsInt (&Expr)) { Flags |= CF_CONST; } else { @@ -270,10 +271,18 @@ static void ParseAutoDecl (Declaration* Decl) /* Mark the variable as referenced */ Sym->Flags |= SC_REF; + /* Make note of auto variables initialized in current block. + ** We abuse the Collection somewhat by using it to store line + ** numbers. + */ + CollReplace (&CurrentFunc->LocalsBlockStack, + (void *)(size_t)GetCurrentLine (), + CollCount (&CurrentFunc->LocalsBlockStack) - 1); + } else { /* Non-initialized local variable. Just keep track of - * the space needed. - */ + ** the space needed. + */ F_ReserveLocalSpace (CurrentFunc, Size); } @@ -302,13 +311,13 @@ static void ParseAutoDecl (Declaration* Decl) if (IsCompound) { /* Switch to read only data and define a label for the - * initialization data. - */ + ** initialization data. + */ unsigned InitLabel = AllocLabel (g_userodata); /* Parse the initialization generating a memory image of the - * data in the RODATA segment. - */ + ** data in the RODATA segment. + */ Size = ParseInit (Sym->Type); /* Allocate space for the variable */ @@ -371,9 +380,9 @@ static void ParseStaticDecl (Declaration* Decl) if (CurTok.Tok == TOK_ASSIGN) { /* Initialization ahead, switch to data segment and define the label. - * For arrays, we need to check the elements of the array for - * constness, not the array itself. - */ + ** For arrays, we need to check the elements of the array for + ** constness, not the array itself. + */ if (IsQualConst (GetBaseElementType (Sym->Type))) { g_userodata (); } else { @@ -392,8 +401,11 @@ static void ParseStaticDecl (Declaration* Decl) } else { + /* Get the size of the variable */ + Size = SizeOf (Decl->Type); + /* Allocate a label and space for the variable in the BSS segment */ - AllocStorage (DataLabel, g_usebss, SizeOf (Sym->Type)); + AllocStorage (DataLabel, g_usebss, Size); } @@ -408,7 +420,7 @@ static void ParseStaticDecl (Declaration* Decl) static void ParseOneDecl (const DeclSpec* Spec) /* Parse one variable declaration */ { - Declaration Decl; /* Declaration data structure */ + Declaration Decl; /* Declaration data structure */ /* Read the declaration */ @@ -416,32 +428,32 @@ static void ParseOneDecl (const DeclSpec* Spec) /* Set the correct storage class for functions */ if ((Decl.StorageClass & SC_FUNC) == SC_FUNC) { - /* Function prototypes are always external */ - if ((Decl.StorageClass & SC_EXTERN) == 0) { - Warning ("Function must be extern"); - } - Decl.StorageClass |= SC_EXTERN; + /* Function prototypes are always external */ + if ((Decl.StorageClass & SC_EXTERN) == 0) { + Warning ("Function must be extern"); + } + Decl.StorageClass |= SC_EXTERN; } /* If we don't have a name, this was flagged as an error earlier. - * To avoid problems later, use an anonymous name here. - */ + ** To avoid problems later, use an anonymous name here. + */ if (Decl.Ident[0] == '\0') { - AnonName (Decl.Ident, "param"); + AnonName (Decl.Ident, "param"); } /* If the symbol is not marked as external, it will be defined now */ if ((Decl.StorageClass & SC_EXTERN) == 0) { - Decl.StorageClass |= SC_DEF; + Decl.StorageClass |= SC_DEF; } /* Handle anything that needs storage (no functions, no typdefs) */ if ((Decl.StorageClass & SC_FUNC) != SC_FUNC && - (Decl.StorageClass & SC_TYPEDEF) != SC_TYPEDEF) { + (Decl.StorageClass & SC_TYPEMASK) != SC_TYPEDEF) { /* If we have a register variable, try to allocate a register and - * convert the declaration to "auto" if this is not possible. - */ + ** convert the declaration to "auto" if this is not possible. + */ int Reg = 0; /* Initialize to avoid gcc complains */ if ((Decl.StorageClass & SC_REGISTER) != 0 && (Reg = F_AllocRegVar (CurrentFunc, Decl.Type)) < 0) { @@ -453,7 +465,7 @@ static void ParseOneDecl (const DeclSpec* Spec) if ((Decl.StorageClass & SC_REGISTER) == SC_REGISTER) { /* Register variable */ ParseRegisterDecl (&Decl, Reg); - } else if ((Decl.StorageClass & SC_AUTO) == SC_AUTO) { + } else if ((Decl.StorageClass & SC_AUTO) == SC_AUTO) { /* Auto variable */ ParseAutoDecl (&Decl); } else if ((Decl.StorageClass & SC_EXTERN) == SC_EXTERN) { @@ -463,10 +475,10 @@ static void ParseOneDecl (const DeclSpec* Spec) } /* Add the external symbol to the symbol table */ AddLocalSym (Decl.Ident, Decl.Type, Decl.StorageClass, 0); - } else if ((Decl.StorageClass & SC_STATIC) == SC_STATIC) { + } else if ((Decl.StorageClass & SC_STATIC) == SC_STATIC) { /* Static variable */ ParseStaticDecl (&Decl); - } else { + } else { Internal ("Invalid storage class in ParseOneDecl: %04X", Decl.StorageClass); } @@ -486,62 +498,67 @@ void DeclareLocals (void) /* Remember the current stack pointer */ int InitialStack = StackPtr; + /* A place to store info about potential initializations of auto variables */ + CollAppend (&CurrentFunc->LocalsBlockStack, 0); + /* Loop until we don't find any more variables */ while (1) { - /* Check variable declarations. We need to distinguish between a - * default int type and the end of variable declarations. So we - * will do the following: If there is no explicit storage class - * specifier *and* no explicit type given, *and* no type qualifiers - * have been read, it is assumed that we have reached the end of - * declarations. - */ - DeclSpec Spec; - ParseDeclSpec (&Spec, SC_AUTO, T_INT); - if ((Spec.Flags & DS_DEF_STORAGE) != 0 && /* No storage spec */ + /* Check variable declarations. We need to distinguish between a + ** default int type and the end of variable declarations. So we + ** will do the following: If there is no explicit storage class + ** specifier *and* no explicit type given, *and* no type qualifiers + ** have been read, it is assumed that we have reached the end of + ** declarations. + */ + DeclSpec Spec; + ParseDeclSpec (&Spec, SC_AUTO, T_INT); + if ((Spec.Flags & DS_DEF_STORAGE) != 0 && /* No storage spec */ (Spec.Flags & DS_DEF_TYPE) != 0 && /* No type given */ GetQualifier (Spec.Type) == T_QUAL_NONE) { /* No type qualifier */ - break; - } - - /* Accept type only declarations */ - if (CurTok.Tok == TOK_SEMI) { - /* Type declaration only */ - CheckEmptyDecl (&Spec); - NextToken (); - continue; - } - - /* Parse a comma separated variable list */ - while (1) { - - /* Parse one declaration */ - ParseOneDecl (&Spec); - - /* Check if there is more */ - if (CurTok.Tok == TOK_COMMA) { - /* More to come */ - NextToken (); - } else { - /* Done */ - break; - } - } - - /* A semicolon must follow */ - ConsumeSemi (); + break; + } + + /* Accept type only declarations */ + if (CurTok.Tok == TOK_SEMI) { + /* Type declaration only */ + CheckEmptyDecl (&Spec); + NextToken (); + continue; + } + + /* Parse a comma separated variable list */ + while (1) { + + /* Parse one declaration */ + ParseOneDecl (&Spec); + + /* Check if there is more */ + if (CurTok.Tok == TOK_COMMA) { + /* More to come */ + NextToken (); + } else { + /* Done */ + break; + } + } + + /* A semicolon must follow */ + ConsumeSemi (); } /* Be sure to allocate any reserved space for locals */ F_AllocLocalSpace (CurrentFunc); + /* No auto variables were inited. No new block on the stack then. */ + if (CollLast (&CurrentFunc->LocalsBlockStack) == NULL) { + CollPop (&CurrentFunc->LocalsBlockStack); + } + /* 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. + */ if (IS_Get (&CheckStack) && InitialStack != StackPtr) { - g_cstackcheck (); + g_cstackcheck (); } } - - -