Allow initialization of local variables of compound type
git-svn-id: svn://svn.cc65.org/cc65/trunk@1458 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -450,7 +450,7 @@ void g_leave (void)
|
|||||||
{
|
{
|
||||||
/* How many bytes of locals do we have to drop? */
|
/* How many bytes of locals do we have to drop? */
|
||||||
int k = -oursp;
|
int k = -oursp;
|
||||||
|
|
||||||
/* If we didn't have a variable argument list, don't call leave */
|
/* If we didn't have a variable argument list, don't call leave */
|
||||||
if (funcargs >= 0) {
|
if (funcargs >= 0) {
|
||||||
|
|
||||||
@@ -598,25 +598,25 @@ void g_getimmed (unsigned Flags, unsigned long Val, long Offs)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CF_LONG:
|
case CF_LONG:
|
||||||
/* Split the value into 4 bytes */
|
/* Split the value into 4 bytes */
|
||||||
B1 = (unsigned char) (Val >> 0);
|
B1 = (unsigned char) (Val >> 0);
|
||||||
B2 = (unsigned char) (Val >> 8);
|
B2 = (unsigned char) (Val >> 8);
|
||||||
B3 = (unsigned char) (Val >> 16);
|
B3 = (unsigned char) (Val >> 16);
|
||||||
B4 = (unsigned char) (Val >> 24);
|
B4 = (unsigned char) (Val >> 24);
|
||||||
|
|
||||||
/* Remember which bytes are done */
|
/* Remember which bytes are done */
|
||||||
Done = 0;
|
Done = 0;
|
||||||
|
|
||||||
/* Load the value */
|
/* Load the value */
|
||||||
AddCodeLine ("ldx #$%02X", B2);
|
AddCodeLine ("ldx #$%02X", B2);
|
||||||
Done |= 0x02;
|
Done |= 0x02;
|
||||||
if (B2 == B3) {
|
if (B2 == B3) {
|
||||||
AddCodeLine ("stx sreg");
|
AddCodeLine ("stx sreg");
|
||||||
Done |= 0x04;
|
Done |= 0x04;
|
||||||
}
|
}
|
||||||
if (B2 == B4) {
|
if (B2 == B4) {
|
||||||
AddCodeLine ("stx sreg+1");
|
AddCodeLine ("stx sreg+1");
|
||||||
Done |= 0x08;
|
Done |= 0x08;
|
||||||
}
|
}
|
||||||
if ((Done & 0x04) == 0 && B1 != B3) {
|
if ((Done & 0x04) == 0 && B1 != B3) {
|
||||||
AddCodeLine ("lda #$%02X", B3);
|
AddCodeLine ("lda #$%02X", B3);
|
||||||
@@ -3913,6 +3913,65 @@ void g_zerobytes (unsigned n)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void g_initauto (unsigned Label, unsigned Size)
|
||||||
|
/* Initialize a local variable at stack offset zero from static data */
|
||||||
|
{
|
||||||
|
unsigned CodeLabel = GetLocalLabel ();
|
||||||
|
|
||||||
|
CheckLocalOffs (Size);
|
||||||
|
if (Size <= 128) {
|
||||||
|
ldyconst (Size-1);
|
||||||
|
g_defcodelabel (CodeLabel);
|
||||||
|
AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, Label, 0));
|
||||||
|
AddCodeLine ("sta (sp),y");
|
||||||
|
AddCodeLine ("dey");
|
||||||
|
AddCodeLine ("bpl %s", LocalLabelName (CodeLabel));
|
||||||
|
} else if (Size <= 256) {
|
||||||
|
ldyconst (0);
|
||||||
|
g_defcodelabel (CodeLabel);
|
||||||
|
AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, Label, 0));
|
||||||
|
AddCodeLine ("sta (sp),y");
|
||||||
|
AddCodeLine ("iny");
|
||||||
|
AddCodeLine ("cpy #$%02X", (unsigned char) Size);
|
||||||
|
AddCodeLine ("bne %s", LocalLabelName (CodeLabel));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void g_initstatic (unsigned InitLabel, unsigned VarLabel, unsigned Size)
|
||||||
|
/* Initialize a static local variable from static initialization data */
|
||||||
|
{
|
||||||
|
if (Size <= 128) {
|
||||||
|
unsigned CodeLabel = GetLocalLabel ();
|
||||||
|
ldyconst (Size-1);
|
||||||
|
g_defcodelabel (CodeLabel);
|
||||||
|
AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, InitLabel, 0));
|
||||||
|
AddCodeLine ("sta %s,y", GetLabelName (CF_STATIC, VarLabel, 0));
|
||||||
|
AddCodeLine ("dey");
|
||||||
|
AddCodeLine ("bpl %s", LocalLabelName (CodeLabel));
|
||||||
|
} else if (Size <= 256) {
|
||||||
|
unsigned CodeLabel = GetLocalLabel ();
|
||||||
|
ldyconst (0);
|
||||||
|
g_defcodelabel (CodeLabel);
|
||||||
|
AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, InitLabel, 0));
|
||||||
|
AddCodeLine ("sta %s,y", GetLabelName (CF_STATIC, VarLabel, 0));
|
||||||
|
AddCodeLine ("iny");
|
||||||
|
AddCodeLine ("cpy #$%02X", (unsigned char) Size);
|
||||||
|
AddCodeLine ("bne %s", LocalLabelName (CodeLabel));
|
||||||
|
} else {
|
||||||
|
/* Use the easy way here: memcpy */
|
||||||
|
g_getimmed (CF_STATIC, VarLabel, 0);
|
||||||
|
AddCodeLine ("jsr pushax");
|
||||||
|
g_getimmed (CF_STATIC, InitLabel, 0);
|
||||||
|
AddCodeLine ("jsr pushax");
|
||||||
|
g_getimmed (CF_INT | CF_UNSIGNED | CF_CONST, Size, 0);
|
||||||
|
AddCodeLine ("jsr %s", GetLabelName (CF_EXTERNAL, (unsigned long) "memcpy", 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Switch statement */
|
/* Switch statement */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2001 Ullrich von Bassewitz */
|
/* (C) 1998-2002 Ullrich von Bassewitz */
|
||||||
/* Wacholderweg 14 */
|
/* Wacholderweg 14 */
|
||||||
/* D-70597 Stuttgart */
|
/* D-70597 Stuttgart */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
@@ -429,6 +429,12 @@ void g_defbytes (const void* bytes, unsigned count);
|
|||||||
void g_zerobytes (unsigned n);
|
void g_zerobytes (unsigned n);
|
||||||
/* Output n bytes of data initialized with zero */
|
/* Output n bytes of data initialized with zero */
|
||||||
|
|
||||||
|
void g_initauto (unsigned Label, unsigned Size);
|
||||||
|
/* Initialize a local variable at stack offset zero from static data */
|
||||||
|
|
||||||
|
void g_initstatic (unsigned InitLabel, unsigned VarLabel, unsigned Size);
|
||||||
|
/* Initialize a static local variable from static initialization data */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|||||||
@@ -141,6 +141,10 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned Size, unsigned* SC)
|
|||||||
{
|
{
|
||||||
unsigned Flags;
|
unsigned Flags;
|
||||||
unsigned SymData;
|
unsigned SymData;
|
||||||
|
unsigned InitLabel;
|
||||||
|
|
||||||
|
/* Determine if this is a compound variable */
|
||||||
|
int IsCompound = IsClassStruct (Decl->Type) || IsTypeArray (Decl->Type);
|
||||||
|
|
||||||
/* Check if this is a variable on the stack or in static memory */
|
/* Check if this is a variable on the stack or in static memory */
|
||||||
if (StaticLocals == 0) {
|
if (StaticLocals == 0) {
|
||||||
@@ -151,27 +155,57 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned Size, unsigned* SC)
|
|||||||
|
|
||||||
ExprDesc lval;
|
ExprDesc lval;
|
||||||
|
|
||||||
/* Allocate previously reserved local space */
|
|
||||||
F_AllocLocalSpace (CurrentFunc);
|
|
||||||
|
|
||||||
/* Skip the '=' */
|
/* Skip the '=' */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
/* Setup the type flags for the assignment */
|
/* Special handling for compound types */
|
||||||
Flags = (Size == 1)? CF_FORCECHAR : CF_NONE;
|
if (IsCompound) {
|
||||||
|
|
||||||
|
/* First reserve space for the variable */
|
||||||
|
SymData = 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.
|
||||||
|
*/
|
||||||
|
F_AllocLocalSpace (CurrentFunc);
|
||||||
|
|
||||||
|
/* Switch to read only data */
|
||||||
|
g_userodata ();
|
||||||
|
|
||||||
|
/* Define a label for the initialization data */
|
||||||
|
InitLabel = GetLocalLabel ();
|
||||||
|
g_defdatalabel (InitLabel);
|
||||||
|
|
||||||
|
/* Parse the initialization generating a memory image of the
|
||||||
|
* data in the RODATA segment.
|
||||||
|
*/
|
||||||
|
ParseInit (Decl->Type);
|
||||||
|
|
||||||
|
/* Generate code to copy this data into the variable space */
|
||||||
|
g_initauto (InitLabel, Size);
|
||||||
|
|
||||||
/* Get the expression into the primary */
|
|
||||||
if (evalexpr (Flags, hie1, &lval) == 0) {
|
|
||||||
/* Constant expression. Adjust the types */
|
|
||||||
assignadjust (Decl->Type, &lval);
|
|
||||||
Flags |= CF_CONST;
|
|
||||||
} else {
|
} else {
|
||||||
/* Expression is not constant and in the primary */
|
|
||||||
assignadjust (Decl->Type, &lval);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Push the value */
|
/* Allocate previously reserved local space */
|
||||||
g_push (Flags | TypeOf (Decl->Type), lval.ConstVal);
|
F_AllocLocalSpace (CurrentFunc);
|
||||||
|
|
||||||
|
/* Setup the type flags for the assignment */
|
||||||
|
Flags = (Size == 1)? CF_FORCECHAR : CF_NONE;
|
||||||
|
|
||||||
|
/* Get the expression into the primary */
|
||||||
|
if (evalexpr (Flags, hie1, &lval) == 0) {
|
||||||
|
/* Constant expression. Adjust the types */
|
||||||
|
assignadjust (Decl->Type, &lval);
|
||||||
|
Flags |= CF_CONST;
|
||||||
|
} else {
|
||||||
|
/* Expression is not constant and in the primary */
|
||||||
|
assignadjust (Decl->Type, &lval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Push the value */
|
||||||
|
g_push (Flags | TypeOf (Decl->Type), lval.ConstVal);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Mark the variable as referenced */
|
/* Mark the variable as referenced */
|
||||||
*SC |= SC_REF;
|
*SC |= SC_REF;
|
||||||
@@ -209,23 +243,44 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned Size, unsigned* SC)
|
|||||||
/* Skip the '=' */
|
/* Skip the '=' */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
/* Setup the type flags for the assignment */
|
if (IsCompound) {
|
||||||
Flags = (Size == 1)? CF_FORCECHAR : CF_NONE;
|
|
||||||
|
/* Switch to read only data */
|
||||||
|
g_userodata ();
|
||||||
|
|
||||||
|
/* Define a label for the initialization data */
|
||||||
|
InitLabel = GetLocalLabel ();
|
||||||
|
g_defdatalabel (InitLabel);
|
||||||
|
|
||||||
|
/* Parse the initialization generating a memory image of the
|
||||||
|
* data in the RODATA segment.
|
||||||
|
*/
|
||||||
|
ParseInit (Decl->Type);
|
||||||
|
|
||||||
|
/* Generate code to copy this data into the variable space */
|
||||||
|
g_initstatic (InitLabel, SymData, Size);
|
||||||
|
|
||||||
/* Get the expression into the primary */
|
|
||||||
if (evalexpr (Flags, hie1, &lval) == 0) {
|
|
||||||
/* Constant expression. Adjust the types */
|
|
||||||
assignadjust (Decl->Type, &lval);
|
|
||||||
Flags |= CF_CONST;
|
|
||||||
/* Load it into the primary */
|
|
||||||
exprhs (Flags, 0, &lval);
|
|
||||||
} else {
|
} else {
|
||||||
/* Expression is not constant and in the primary */
|
|
||||||
assignadjust (Decl->Type, &lval);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Store the value into the variable */
|
/* Setup the type flags for the assignment */
|
||||||
g_putstatic (Flags | TypeOf (Decl->Type), SymData, 0);
|
Flags = (Size == 1)? CF_FORCECHAR : CF_NONE;
|
||||||
|
|
||||||
|
/* Get the expression into the primary */
|
||||||
|
if (evalexpr (Flags, hie1, &lval) == 0) {
|
||||||
|
/* Constant expression. Adjust the types */
|
||||||
|
assignadjust (Decl->Type, &lval);
|
||||||
|
Flags |= CF_CONST;
|
||||||
|
/* Load it into the primary */
|
||||||
|
exprhs (Flags, 0, &lval);
|
||||||
|
} else {
|
||||||
|
/* Expression is not constant and in the primary */
|
||||||
|
assignadjust (Decl->Type, &lval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store the value into the variable */
|
||||||
|
g_putstatic (Flags | TypeOf (Decl->Type), SymData, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Mark the variable as referenced */
|
/* Mark the variable as referenced */
|
||||||
*SC |= SC_REF;
|
*SC |= SC_REF;
|
||||||
|
|||||||
Reference in New Issue
Block a user