From: cuz Date: Thu, 10 Oct 2002 21:15:24 +0000 (+0000) Subject: Allow initialization of local variables of compound type X-Git-Tag: V2.12.0~2174 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=83fb2c8ab4892e2ff0e3c700f99b9cf7ab19b3b3;p=cc65 Allow initialization of local variables of compound type git-svn-id: svn://svn.cc65.org/cc65/trunk@1458 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index cca466465..40dcd46ab 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -450,7 +450,7 @@ void g_leave (void) { /* How many bytes of locals do we have to drop? */ int k = -oursp; - + /* If we didn't have a variable argument list, don't call leave */ if (funcargs >= 0) { @@ -598,25 +598,25 @@ void g_getimmed (unsigned Flags, unsigned long Val, long Offs) break; case CF_LONG: - /* Split the value into 4 bytes */ - B1 = (unsigned char) (Val >> 0); - B2 = (unsigned char) (Val >> 8); - B3 = (unsigned char) (Val >> 16); - B4 = (unsigned char) (Val >> 24); - - /* Remember which bytes are done */ - Done = 0; - - /* Load the value */ - AddCodeLine ("ldx #$%02X", B2); - Done |= 0x02; - if (B2 == B3) { - AddCodeLine ("stx sreg"); - Done |= 0x04; - } - if (B2 == B4) { - AddCodeLine ("stx sreg+1"); - Done |= 0x08; + /* Split the value into 4 bytes */ + B1 = (unsigned char) (Val >> 0); + B2 = (unsigned char) (Val >> 8); + B3 = (unsigned char) (Val >> 16); + B4 = (unsigned char) (Val >> 24); + + /* Remember which bytes are done */ + Done = 0; + + /* Load the value */ + AddCodeLine ("ldx #$%02X", B2); + Done |= 0x02; + if (B2 == B3) { + AddCodeLine ("stx sreg"); + Done |= 0x04; + } + if (B2 == B4) { + AddCodeLine ("stx sreg+1"); + Done |= 0x08; } if ((Done & 0x04) == 0 && B1 != 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 */ /*****************************************************************************/ diff --git a/src/cc65/codegen.h b/src/cc65/codegen.h index 8d16c8948..37f5febb7 100644 --- a/src/cc65/codegen.h +++ b/src/cc65/codegen.h @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2001 Ullrich von Bassewitz */ +/* (C) 1998-2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ @@ -429,6 +429,12 @@ void g_defbytes (const void* bytes, unsigned count); void g_zerobytes (unsigned n); /* 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 */ + /*****************************************************************************/ diff --git a/src/cc65/locals.c b/src/cc65/locals.c index 4e50ea959..fbb054ea5 100644 --- a/src/cc65/locals.c +++ b/src/cc65/locals.c @@ -141,6 +141,10 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned Size, unsigned* SC) { unsigned Flags; 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 */ if (StaticLocals == 0) { @@ -151,27 +155,57 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned Size, unsigned* SC) ExprDesc lval; - /* Allocate previously reserved local space */ - F_AllocLocalSpace (CurrentFunc); - /* Skip the '=' */ NextToken (); - /* Setup the type flags for the assignment */ - Flags = (Size == 1)? CF_FORCECHAR : CF_NONE; + /* Special handling for compound types */ + 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 { - /* Expression is not constant and in the primary */ - assignadjust (Decl->Type, &lval); - } - /* Push the value */ - g_push (Flags | TypeOf (Decl->Type), lval.ConstVal); + /* Allocate previously reserved local space */ + 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 */ *SC |= SC_REF; @@ -209,23 +243,44 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned Size, unsigned* SC) /* Skip the '=' */ NextToken (); - /* Setup the type flags for the assignment */ - Flags = (Size == 1)? CF_FORCECHAR : CF_NONE; + if (IsCompound) { + + /* 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 { - /* 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); + /* 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; + /* 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 */ *SC |= SC_REF;