From: uz Date: Sun, 22 Apr 2012 18:08:45 +0000 (+0000) Subject: Fixed an error when parsing local variables: Variables must be inserted into X-Git-Tag: V2.14~419 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=faf58a822060553358cc48bbf4e2d557bdd8e260;p=cc65 Fixed an error when parsing local variables: Variables must be inserted into the symbol table *before* the optional initializer is parsed, because they might be referenced in the intializer. git-svn-id: svn://svn.cc65.org/cc65/trunk@5648 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/src/cc65/function.c b/src/cc65/function.c index 7c9e52cbb..5681b2a8b 100644 --- a/src/cc65/function.c +++ b/src/cc65/function.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 2000-2011, Ullrich von Bassewitz */ +/* (C) 2000-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -237,6 +237,16 @@ int F_ReserveLocalSpace (Function* F, unsigned Size) +int F_GetStackPtr (const Function* F) +/* Return the current stack pointer including reserved (but not allocated) + * space on the stack. + */ +{ + return StackPtr - F->Reserved; +} + + + void F_AllocLocalSpace (Function* F) /* Allocate any local space previously reserved. The function will do * nothing if there is no reserved local space. @@ -361,7 +371,7 @@ static void F_RestoreRegVars (Function* F) static void F_EmitDebugInfo (void) /* Emit debug infos for the current function */ -{ +{ if (DebugInfo) { /* Get the current fuction */ const SymEntry* Sym = CurrentFunc->FuncEntry; diff --git a/src/cc65/function.h b/src/cc65/function.h index 36dcb0528..87f61268d 100644 --- a/src/cc65/function.h +++ b/src/cc65/function.h @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2009, Ullrich von Bassewitz */ +/* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -102,6 +102,11 @@ int F_ReserveLocalSpace (Function* F, unsigned Size); * offset. */ +int F_GetStackPtr (const Function* F); +/* Return the current stack pointer including reserved (but not allocated) + * space on the stack. + */ + void F_AllocLocalSpace (Function* F); /* Allocate any local space previously reserved. The function will do * nothing if there is no reserved local space. diff --git a/src/cc65/locals.c b/src/cc65/locals.c index 3e1002add..626acaa6b 100644 --- a/src/cc65/locals.c +++ b/src/cc65/locals.c @@ -79,29 +79,27 @@ static unsigned AllocLabel (void (*UseSeg) ()) -static unsigned AllocStorage (void (*UseSeg) (), unsigned Size) -/* Reserve Size bytes of BSS storage prefixed by a local label. Return the - * label. - */ +static void AllocStorage (unsigned Label, void (*UseSeg) (), unsigned Size) +/* Reserve Size bytes of BSS storage prefixed by a local label. */ { - /* Switch to the segment and define the label */ - unsigned Label = AllocLabel (UseSeg); + /* Switch to the segment */ + UseSeg (); + + /* Define the variable label */ + g_defdatalabel (Label); /* Reserve space for the data */ g_res (Size); - - /* Return the label */ - return Label; } -static unsigned ParseRegisterDecl (Declaration* Decl, unsigned* SC, int Reg) -/* Parse the declaration of a register variable. The function returns the - * symbol data, which is the offset of the variable in the register bank. +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. */ { - unsigned InitLabel; + SymEntry* Sym; /* Determine if this is a compound variable */ int IsCompound = IsClassStruct (Decl->Type) || IsTypeArray (Decl->Type); @@ -113,6 +111,12 @@ static unsigned ParseRegisterDecl (Declaration* Decl, unsigned* SC, int Reg) F_AllocLocalSpace (CurrentFunc); 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. + */ + Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, Reg); + /* Check for an optional initialization */ if (CurTok.Tok == TOK_ASSIGN) { @@ -127,7 +131,7 @@ static unsigned ParseRegisterDecl (Declaration* Decl, unsigned* SC, int Reg) /* Switch to read only data and define a label for the * initialization data. */ - InitLabel = AllocLabel (g_userodata); + 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 @@ -137,7 +141,7 @@ static unsigned ParseRegisterDecl (Declaration* Decl, unsigned* SC, int Reg) * know the size of the data in advance for register variables, * we cannot allow that here. */ - if (ParseInit (Decl->Type) != Size) { + if (ParseInit (Sym->Type) != Size) { Error ("Cannot initialize flexible array members of storage class `register'"); } @@ -150,39 +154,33 @@ static unsigned ParseRegisterDecl (Declaration* Decl, unsigned* SC, int Reg) hie1 (&Expr); /* Convert it to the target type */ - TypeConversion (&Expr, Decl->Type); + TypeConversion (&Expr, Sym->Type); /* Load the value into the primary */ LoadExpr (CF_NONE, &Expr); /* Store the value into the variable */ - g_putstatic (CF_REGVAR | TypeOf (Decl->Type), Reg, 0); + g_putstatic (CF_REGVAR | TypeOf (Sym->Type), Reg, 0); } /* Mark the variable as referenced */ - *SC |= SC_REF; + Sym->Flags |= SC_REF; } /* Cannot allocate a variable of zero size */ if (Size == 0) { Error ("Variable `%s' has unknown size", Decl->Ident); } - - /* Return the symbol data */ - return Reg; } -static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC) -/* Parse the declaration of an auto variable. The function returns the symbol - * data, which is the offset for variables on the stack, and the label for - * static variables. - */ +static void ParseAutoDecl (Declaration* Decl) +/* Parse the declaration of an auto variable. */ { - unsigned Flags; - unsigned SymData; + unsigned Flags; + SymEntry* Sym; /* Determine if this is a compound variable */ int IsCompound = IsClassStruct (Decl->Type) || IsTypeArray (Decl->Type); @@ -193,6 +191,13 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC) /* Check if this is a variable on the stack or in static memory */ if (IS_Get (&StaticLocals) == 0) { + /* Add the symbol to the symbol table. The stack offset we use here + * may get corrected later. + */ + Sym = AddLocalSym (Decl->Ident, Decl->Type, + Decl->StorageClass, + F_GetStackPtr (CurrentFunc) - (int) Size); + /* Check for an optional initialization */ if (CurTok.Tok == TOK_ASSIGN) { @@ -216,10 +221,12 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC) * that contains a flexible array member and we're not in * ANSI mode. */ - Size = ParseInit (Decl->Type); + Size = ParseInit (Sym->Type); - /* Now reserve space for the variable on the stack */ - SymData = F_ReserveLocalSpace (CurrentFunc, Size); + /* Now reserve space for the variable on the stack and correct + * 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. @@ -243,7 +250,7 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC) hie1 (&Expr); /* Convert it to the target type */ - TypeConversion (&Expr, Decl->Type); + TypeConversion (&Expr, Sym->Type); /* If the value is not const, load it into the primary. * Otherwise pass the information to the code generator. @@ -256,27 +263,33 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC) } /* Push the value */ - g_push (Flags | TypeOf (Decl->Type), Expr.IVal); + g_push (Flags | TypeOf (Sym->Type), Expr.IVal); } /* Mark the variable as referenced */ - *SC |= SC_REF; - - /* Variable is located at the current SP */ - SymData = StackPtr; + Sym->Flags |= SC_REF; } else { /* Non-initialized local variable. Just keep track of * the space needed. */ - SymData = F_ReserveLocalSpace (CurrentFunc, Size); + F_ReserveLocalSpace (CurrentFunc, Size); } } else { + unsigned DataLabel; + + /* Static local variables. */ - *SC = (*SC & ~SC_AUTO) | SC_STATIC; + Decl->StorageClass = (Decl->StorageClass & ~SC_AUTO) | SC_STATIC; + + /* Generate a label, but don't define it */ + DataLabel = GetLocalLabel (); + + /* Add the symbol to the symbol table. */ + Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, DataLabel); /* Allow assignments */ if (CurTok.Tok == TOK_ASSIGN) { @@ -296,39 +309,39 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC) /* Parse the initialization generating a memory image of the * data in the RODATA segment. */ - Size = ParseInit (Decl->Type); + Size = ParseInit (Sym->Type); - /* Allocate a label and space for the variable */ - SymData = AllocStorage (g_usebss, Size); + /* Allocate space for the variable */ + AllocStorage (DataLabel, g_usebss, Size); /* Generate code to copy this data into the variable space */ - g_initstatic (InitLabel, SymData, Size); + g_initstatic (InitLabel, DataLabel, Size); } else { - /* Allocate a label and space for the variable */ - SymData = AllocStorage (g_usebss, Size); + /* Allocate space for the variable */ + AllocStorage (DataLabel, g_usebss, Size); /* Parse the expression */ hie1 (&Expr); /* Convert it to the target type */ - TypeConversion (&Expr, Decl->Type); + TypeConversion (&Expr, Sym->Type); /* Load the value into the primary */ LoadExpr (CF_NONE, &Expr); /* Store the value into the variable */ - g_putstatic (TypeOf (Decl->Type), SymData, 0); + g_putstatic (TypeOf (Sym->Type), DataLabel, 0); } /* Mark the variable as referenced */ - *SC |= SC_REF; + Sym->Flags |= SC_REF; } else { /* No assignment - allocate a label and space for the variable */ - SymData = AllocStorage (g_usebss, Size); + AllocStorage (DataLabel, g_usebss, Size); } } @@ -337,50 +350,50 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC) if (Size == 0) { Error ("Variable `%s' has unknown size", Decl->Ident); } - - /* Return the symbol data */ - return SymData; } -static unsigned ParseStaticDecl (Declaration* Decl, unsigned* SC) -/* Parse the declaration of a static variable. The function returns the symbol - * data, which is the asm label of the variable. - */ +static void ParseStaticDecl (Declaration* Decl) +/* Parse the declaration of a static variable. */ { - unsigned SymData; unsigned Size; + /* Generate a label, but don't define it */ + unsigned DataLabel = GetLocalLabel (); + + /* Add the symbol to the symbol table. */ + SymEntry* Sym = AddLocalSym (Decl->Ident, Decl->Type, + Decl->StorageClass, + DataLabel); + /* Static data */ if (CurTok.Tok == TOK_ASSIGN) { - /* Initialization ahead, switch to data segment and define a label. + /* 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. */ - if (IsQualConst (GetBaseElementType (Decl->Type))) { - SymData = AllocLabel (g_userodata); + if (IsQualConst (GetBaseElementType (Sym->Type))) { + g_userodata (); } else { - SymData = AllocLabel (g_usedata); + g_usedata (); } + g_defdatalabel (DataLabel); /* Skip the '=' */ NextToken (); /* Allow initialization of static vars */ - Size = ParseInit (Decl->Type); + Size = ParseInit (Sym->Type); /* Mark the variable as referenced */ - *SC |= SC_REF; + Sym->Flags |= SC_REF; } else { - /* Get the size of the variable */ - Size = SizeOf (Decl->Type); - /* Allocate a label and space for the variable in the BSS segment */ - SymData = AllocStorage (g_usebss, Size); + AllocStorage (DataLabel, g_usebss, SizeOf (Sym->Type)); } @@ -388,9 +401,6 @@ static unsigned ParseStaticDecl (Declaration* Decl, unsigned* SC) if (Size == 0) { Error ("Variable `%s' has unknown size", Decl->Ident); } - - /* Return the symbol data */ - return SymData; } @@ -398,7 +408,6 @@ static unsigned ParseStaticDecl (Declaration* Decl, unsigned* SC) static void ParseOneDecl (const DeclSpec* Spec) /* Parse one variable declaration */ { - unsigned SymData = 0; /* Symbol data (offset, label name, ...) */ Declaration Decl; /* Declaration data structure */ @@ -421,6 +430,11 @@ static void ParseOneDecl (const DeclSpec* Spec) 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; + } + /* Handle anything that needs storage (no functions, no typdefs) */ if ((Decl.StorageClass & SC_FUNC) != SC_FUNC && (Decl.StorageClass & SC_TYPEDEF) != SC_TYPEDEF) { @@ -438,31 +452,30 @@ static void ParseOneDecl (const DeclSpec* Spec) /* Check the variable type */ if ((Decl.StorageClass & SC_REGISTER) == SC_REGISTER) { /* Register variable */ - SymData = ParseRegisterDecl (&Decl, &Decl.StorageClass, Reg); + ParseRegisterDecl (&Decl, Reg); } else if ((Decl.StorageClass & SC_AUTO) == SC_AUTO) { /* Auto variable */ - SymData = ParseAutoDecl (&Decl, &Decl.StorageClass); + ParseAutoDecl (&Decl); } else if ((Decl.StorageClass & SC_EXTERN) == SC_EXTERN) { /* External identifier - may not get initialized */ if (CurTok.Tok == TOK_ASSIGN) { Error ("Cannot initialize externals"); } - SymData = 0; + /* Add the external symbol to the symbol table */ + AddLocalSym (Decl.Ident, Decl.Type, Decl.StorageClass, 0); } else if ((Decl.StorageClass & SC_STATIC) == SC_STATIC) { /* Static variable */ - SymData = ParseStaticDecl (&Decl, &Decl.StorageClass); + ParseStaticDecl (&Decl); } else { Internal ("Invalid storage class in ParseOneDecl: %04X", Decl.StorageClass); } - } - /* If the symbol is not marked as external, it will be defined now */ - if ((Decl.StorageClass & SC_EXTERN) == 0) { - Decl.StorageClass |= SC_DEF; - } + } else { - /* Add the symbol to the symbol table */ - AddLocalSym (Decl.Ident, Decl.Type, Decl.StorageClass, SymData); + /* Add the symbol to the symbol table */ + AddLocalSym (Decl.Ident, Decl.Type, Decl.StorageClass, 0); + + } } diff --git a/src/cc65/make/gcc.mak b/src/cc65/make/gcc.mak index 76b0f08a9..aa7d9f20e 100644 --- a/src/cc65/make/gcc.mak +++ b/src/cc65/make/gcc.mak @@ -19,7 +19,7 @@ CC65_INC = \"/usr/lib/cc65/include/\" # CC = gcc -CFLAGS = -O2 -g -Wall -W -std=c89 +CFLAGS = -g -Wall -W -std=c89 override CFLAGS += -I$(COMMON) override CFLAGS += -DCC65_INC=$(CC65_INC) EBIND = emxbind