X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Flocals.c;h=710d05e33a34a7442bbaee93f432246fd2c08378;hb=112ae0e3db511ddd92e769c11328646ebe2a6240;hp=14f804e092f3ca3557995c844184444022828337;hpb=9fc71c5e93f7e8270dd6f8fc3810b7b731bf1259;p=cc65 diff --git a/src/cc65/locals.c b/src/cc65/locals.c index 14f804e09..710d05e33 100644 --- a/src/cc65/locals.c +++ b/src/cc65/locals.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2000-2004 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2000-2009, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -46,8 +46,10 @@ #include "expr.h" #include "function.h" #include "global.h" +#include "loadexpr.h" #include "locals.h" #include "stackptr.h" +#include "standard.h" #include "symtab.h" #include "typeconv.h" @@ -59,6 +61,41 @@ +static unsigned AllocLabel (void (*UseSeg) ()) +/* Switch to a segment, define a local label and return it */ +{ + unsigned Label; + + /* Switch to the segment */ + UseSeg (); + + /* Define the variable label */ + Label = GetLocalLabel (); + g_defdatalabel (Label); + + /* Return the label */ + return Label; +} + + + +static unsigned AllocStorage (void (*UseSeg) (), unsigned Size) +/* Reserve Size bytes of BSS storage prefixed by a local label. Return the + * label. + */ +{ + /* Switch to the segment and define the label */ + unsigned Label = AllocLabel (UseSeg); + + /* 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. @@ -87,12 +124,10 @@ static unsigned ParseRegisterDecl (Declaration* Decl, unsigned* SC, int Reg) /* Special handling for compound types */ if (IsCompound) { - /* Switch to read only data */ - g_userodata (); - - /* Define a label for the initialization data */ - InitLabel = GetLocalLabel (); - g_defdatalabel (InitLabel); + /* Switch to read only data and define a label for the + * initialization data. + */ + InitLabel = AllocLabel (g_userodata); /* Parse the initialization generating a memory image of the * data in the RODATA segment. The function does return the size @@ -118,7 +153,7 @@ static unsigned ParseRegisterDecl (Declaration* Decl, unsigned* SC, int Reg) TypeConversion (&Expr, Decl->Type); /* Load the value into the primary */ - ExprLoad (CF_NONE, &Expr); + LoadExpr (CF_NONE, &Expr); /* Store the value into the variable */ g_putstatic (CF_REGVAR | TypeOf (Decl->Type), Reg, 0); @@ -148,7 +183,6 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC) { unsigned Flags; unsigned SymData; - unsigned InitLabel; /* Determine if this is a compound variable */ int IsCompound = IsClassStruct (Decl->Type) || IsTypeArray (Decl->Type); @@ -170,12 +204,10 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC) /* Special handling for compound types */ if (IsCompound) { - /* Switch to read only data */ - g_userodata (); - - /* Define a label for the initialization data */ - InitLabel = GetLocalLabel (); - g_defdatalabel (InitLabel); + /* Switch to read only data and define a label for the + * 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 @@ -219,7 +251,7 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC) if (ED_IsConstAbsInt (&Expr)) { Flags |= CF_CONST; } else { - ExprLoad (CF_NONE, &Expr); + LoadExpr (CF_NONE, &Expr); ED_MakeRVal (&Expr); } @@ -246,16 +278,6 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC) /* Static local variables. */ *SC = (*SC & ~SC_AUTO) | SC_STATIC; - /* Put them into the BSS */ - g_usebss (); - - /* Define the variable label */ - SymData = GetLocalLabel (); - g_defdatalabel (SymData); - - /* Reserve space for the data */ - g_res (Size); - /* Allow assignments */ if (CurTok.Tok == TOK_ASSIGN) { @@ -266,23 +288,27 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC) if (IsCompound) { - /* Switch to read only data */ - g_userodata (); - - /* Define a label for the initialization data */ - InitLabel = GetLocalLabel (); - g_defdatalabel (InitLabel); + /* Switch to read only data and define a label for the + * initialization data. + */ + unsigned InitLabel = AllocLabel (g_userodata); /* Parse the initialization generating a memory image of the * data in the RODATA segment. */ - ParseInit (Decl->Type); + Size = ParseInit (Decl->Type); + + /* Allocate a label and space for the variable */ + SymData = AllocStorage (g_usebss, Size); /* Generate code to copy this data into the variable space */ g_initstatic (InitLabel, SymData, Size); } else { + /* Allocate a label and space for the variable */ + SymData = AllocStorage (g_usebss, Size); + /* Parse the expression */ hie1 (&Expr); @@ -290,7 +316,7 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC) TypeConversion (&Expr, Decl->Type); /* Load the value into the primary */ - ExprLoad (CF_NONE, &Expr); + LoadExpr (CF_NONE, &Expr); /* Store the value into the variable */ g_putstatic (TypeOf (Decl->Type), SymData, 0); @@ -298,6 +324,12 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC) /* Mark the variable as referenced */ *SC |= SC_REF; + + } else { + + /* No assignment - allocate a label and space for the variable */ + SymData = AllocStorage (g_usebss, Size); + } } @@ -318,49 +350,38 @@ static unsigned ParseStaticDecl (Declaration* Decl, unsigned* SC) */ { unsigned SymData; - - /* Get the size of the variable */ - unsigned Size = SizeOf (Decl->Type); + unsigned Size; /* Static data */ if (CurTok.Tok == TOK_ASSIGN) { - /* Initialization ahead, switch to data segment */ - if (IsQualConst (Decl->Type)) { - g_userodata (); + /* Initialization ahead, switch to data segment and define a label. + * For arrays, we need to check the elements of the array for + * constness, not the array itself. + */ + if (IsQualConst (Decl->Type) || + (IsTypeArray (Decl->Type) && IsQualConst (GetElementType (Decl->Type)))) { + SymData = AllocLabel (g_userodata); } else { - g_usedata (); + SymData = AllocLabel (g_usedata); } - /* Define the variable label */ - SymData = GetLocalLabel (); - g_defdatalabel (SymData); - /* Skip the '=' */ NextToken (); /* Allow initialization of static vars */ - ParseInit (Decl->Type); - - /* If the previous size has been unknown, it must be known now */ - if (Size == 0) { - Size = SizeOf (Decl->Type); - } + Size = ParseInit (Decl->Type); /* Mark the variable as referenced */ *SC |= SC_REF; } else { - /* Uninitialized data, use BSS segment */ - g_usebss (); - - /* Define the variable label */ - SymData = GetLocalLabel (); - g_defdatalabel (SymData); + /* Get the size of the variable */ + Size = SizeOf (Decl->Type); - /* Reserve space for the data */ - g_res (Size); + /* Allocate a label and space for the variable in the BSS segment */ + SymData = AllocStorage (g_usebss, Size); } @@ -378,25 +399,20 @@ static unsigned ParseStaticDecl (Declaration* Decl, unsigned* SC) static void ParseOneDecl (const DeclSpec* Spec) /* Parse one variable declaration */ { - unsigned SC; /* Storage class for symbol */ unsigned SymData = 0; /* Symbol data (offset, label name, ...) */ Declaration Decl; /* Declaration data structure */ - /* Remember the storage class for the new symbol */ - SC = Spec->StorageClass; - /* Read the declaration */ ParseDecl (Spec, &Decl, DM_NEED_IDENT); /* Set the correct storage class for functions */ - if (IsTypeFunc (Decl.Type)) { + if ((Decl.StorageClass & SC_FUNC) == SC_FUNC) { /* Function prototypes are always external */ - if ((SC & SC_EXTERN) == 0) { + if ((Decl.StorageClass & SC_EXTERN) == 0) { Warning ("Function must be extern"); } - SC |= SC_FUNC | SC_EXTERN; - + Decl.StorageClass |= SC_EXTERN; } /* If we don't have a name, this was flagged as an error earlier. @@ -407,39 +423,47 @@ static void ParseOneDecl (const DeclSpec* Spec) } /* Handle anything that needs storage (no functions, no typdefs) */ - if ((SC & SC_FUNC) != SC_FUNC && (SC & SC_TYPEDEF) != SC_TYPEDEF) { + if ((Decl.StorageClass & SC_FUNC) != SC_FUNC && + (Decl.StorageClass & SC_TYPEDEF) != SC_TYPEDEF) { /* If we have a register variable, try to allocate a register and * convert the declaration to "auto" if this is not possible. */ int Reg = 0; /* Initialize to avoid gcc complains */ - if ((SC & SC_REGISTER) != 0 && (Reg = F_AllocRegVar (CurrentFunc, Decl.Type)) < 0) { + if ((Decl.StorageClass & SC_REGISTER) != 0 && + (Reg = F_AllocRegVar (CurrentFunc, Decl.Type)) < 0) { /* No space for this register variable, convert to auto */ - SC = (SC & ~SC_REGISTER) | SC_AUTO; + Decl.StorageClass = (Decl.StorageClass & ~SC_REGISTER) | SC_AUTO; } /* Check the variable type */ - if ((SC & SC_REGISTER) == SC_REGISTER) { + if ((Decl.StorageClass & SC_REGISTER) == SC_REGISTER) { /* Register variable */ - SymData = ParseRegisterDecl (&Decl, &SC, Reg); - } else if ((SC & SC_AUTO) == SC_AUTO) { + SymData = ParseRegisterDecl (&Decl, &Decl.StorageClass, Reg); + } else if ((Decl.StorageClass & SC_AUTO) == SC_AUTO) { /* Auto variable */ - SymData = ParseAutoDecl (&Decl, &SC); - } else if ((SC & SC_STATIC) == SC_STATIC) { + SymData = ParseAutoDecl (&Decl, &Decl.StorageClass); + } 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; + } else if ((Decl.StorageClass & SC_STATIC) == SC_STATIC) { /* Static variable */ - SymData = ParseStaticDecl (&Decl, &SC); + SymData = ParseStaticDecl (&Decl, &Decl.StorageClass); } else { - Internal ("Invalid storage class in ParseOneDecl: %04X", SC); + Internal ("Invalid storage class in ParseOneDecl: %04X", Decl.StorageClass); } } /* If the symbol is not marked as external, it will be defined now */ - if ((SC & SC_EXTERN) == 0) { - SC |= SC_DEF; + if ((Decl.StorageClass & SC_EXTERN) == 0) { + Decl.StorageClass |= SC_DEF; } /* Add the symbol to the symbol table */ - AddLocalSym (Decl.Ident, Decl.Type, SC, SymData); + AddLocalSym (Decl.Ident, Decl.Type, Decl.StorageClass, SymData); } @@ -453,38 +477,38 @@ void DeclareLocals (void) /* 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 + /* 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); + */ + 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; - } + break; + } - /* Accept type only declarations */ - if (CurTok.Tok == TOK_SEMI) { - /* Type declaration only */ - CheckEmptyDecl (&Spec); - NextToken (); - continue; - } + /* 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); + /* Parse one declaration */ + ParseOneDecl (&Spec); - /* Check if there is more */ + /* Check if there is more */ if (CurTok.Tok == TOK_COMMA) { - /* More to come */ + /* More to come */ NextToken (); } else { /* Done */