]> git.sur5r.net Git - cc65/commitdiff
Allow initialization of local variables of compound type
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 10 Oct 2002 21:15:24 +0000 (21:15 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 10 Oct 2002 21:15:24 +0000 (21:15 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@1458 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/codegen.c
src/cc65/codegen.h
src/cc65/locals.c

index cca466465ca88332b0b7aa2f33eb45ad5cf6adfa..40dcd46ab3a48b63f8e390835d233d0fb7727d0c 100644 (file)
@@ -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                              */
 /*****************************************************************************/
index 8d16c8948ba93395731142bf8908f1530fbcbfc9..37f5febb7616d69a3d3ad0ce60c8b6f81e5ca6e3 100644 (file)
@@ -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 */
+
 
 
 /*****************************************************************************/
index 4e50ea959f3c00f63321960bdc35d02bb0239508..fbb054ea5002d1f872f5f1c08564e6fb1f2af29f 100644 (file)
@@ -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;