|
|
|
|
@@ -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);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|