]> git.sur5r.net Git - cc65/commitdiff
Rewrote code generation for the strlen standard function. Added code for
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Wed, 2 Jun 2004 21:33:35 +0000 (21:33 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Wed, 2 Jun 2004 21:33:35 +0000 (21:33 +0000)
other standard functions in several places.

git-svn-id: svn://svn.cc65.org/cc65/trunk@3069 b7a2c559-68d2-44c3-8de9-860c34a00d81

15 files changed:
src/cc65/codegen.c
src/cc65/codegen.h
src/cc65/expr.c
src/cc65/exprdesc.c
src/cc65/exprdesc.h
src/cc65/global.c
src/cc65/global.h
src/cc65/litpool.c
src/cc65/main.c
src/cc65/stdfunc.c
src/cc65/stdfunc.h
src/cc65/stdnames.c
src/cc65/stdnames.h
src/cc65/symentry.h
src/cc65/typeconv.c

index 278ecc9b4e4fad52a7a9d01b5eb9df7e96eb4a46..5b75a764f3baee61859db853cd3438d5c6d54a4f 100644 (file)
@@ -464,21 +464,22 @@ void g_leave (void)
 /* Function epilogue */
 {
     /* How many bytes of locals do we have to drop? */
-    int k = -StackPtr;
+    unsigned k = (unsigned) -StackPtr;
 
     /* If we didn't have a variable argument list, don't call leave */
     if (funcargs >= 0) {
 
-       /* Drop stackframe if needed */
+       /* Drop stackframe if needed. We can only drop 255 bytes at a time. */
        k += funcargs;
-               if (k > 0) {
-           if (k <= 8) {
-           AddCodeLine ("jsr incsp%d", k);
+               while (k > 0) {
+            unsigned ToDrop = (k > 255)? 255 : k;
+           if (ToDrop <= 8) {
+               AddCodeLine ("jsr incsp%d", k);
            } else {
-               CheckLocalOffs (k);
-               ldyconst (k);
-               AddCodeLine ("jsr addysp");
+               ldyconst (ToDrop);
+               AddCodeLine ("jsr addysp");
            }
+            k -= ToDrop;
        }
 
     } else {
@@ -488,6 +489,11 @@ void g_leave (void)
            AddCodeLine ("jsr leave");
        } else {
            /* We've a stack frame to drop */
+            while (k > 255) {
+                ldyconst (255);
+                AddCodeLine ("jsr addysp");
+                k -= 255;
+            }
            ldyconst (k);
            AddCodeLine ("jsr leavey");
        }
@@ -4279,53 +4285,3 @@ void g_asmcode (struct StrBuf* B)
 
 
 
-/*****************************************************************************/
-/*                         Inlined known functions                          */
-/*****************************************************************************/
-
-
-
-void g_strlen (unsigned flags, unsigned long val, long offs)
-/* Inline the strlen() function */
-{
-    /* We need a label in both cases */
-    unsigned label = GetLocalLabel ();
-
-    /* Two different encodings */
-    if (flags & CF_CONST) {
-
-       /* The address of the string is constant. Create the correct label name */
-       const char* lbuf = GetLabelName (flags, val, offs);
-
-       /* Generate the strlen code */
-       AddCodeLine ("ldy #$FF");
-       g_defcodelabel (label);
-       AddCodeLine ("iny");
-       AddCodeLine ("lda %s,y", lbuf);
-       AddCodeLine ("bne %s", LocalLabelName (label));
-               AddCodeLine ("tax");
-       AddCodeLine ("tya");
-
-    } else {
-
-               /* Address not constant but in primary */
-       if (CodeSizeFactor < 400) {
-           /* This is too much code, so call strlen instead of inlining */
-           AddCodeLine ("jsr _strlen");
-       } else {
-           /* Inline the function */
-           AddCodeLine ("sta ptr1");
-           AddCodeLine ("stx ptr1+1");
-           AddCodeLine ("ldy #$FF");
-           g_defcodelabel (label);
-           AddCodeLine ("iny");
-           AddCodeLine ("lda (ptr1),y");
-           AddCodeLine ("bne %s", LocalLabelName (label));
-                   AddCodeLine ("tax");
-           AddCodeLine ("tya");
-       }
-    }
-}
-
-
-
index e251029f63c1f534cca1536df11b62f80f83f8e7..58e0217ef1f56b4f4024123155a7f753f9aff5d0 100644 (file)
@@ -472,17 +472,6 @@ void g_asmcode (struct StrBuf* B);
 
 
 
-/*****************************************************************************/
-/*                         Inlined known functions                          */
-/*****************************************************************************/
-
-
-
-void g_strlen (unsigned flags, unsigned long val, long offs);
-/* Inline the strlen() function */
-
-
-
 /* End of codegen.h */
 #endif
 
index 51aee06627127b741cbfbdd37eb1d0b32f214f66..cc3fab011db0a9af2829dbed261cd37c9d298652 100644 (file)
@@ -455,13 +455,6 @@ void ExprLoad (unsigned Flags, ExprDesc* Expr)
             Expr->Test &= ~E_FORCETEST;
         }
     }
-
-#if 0
-    /* Regardless of the original contents, Expr is now an rvalue in the
-     * primary. ### Later...
-     */
-    ED_MakeRValExpr (Expr);
-#endif
 }
 
 
@@ -637,6 +630,7 @@ static void FunctionCall (ExprDesc* Expr)
 {
     FuncDesc*    Func;           /* Function descriptor */
     int           IsFuncPtr;      /* Flag */
+    int           StdFunc;        /* Standard function index */
     unsigned     ParamSize;      /* Number of parameter bytes */
     CodeMark     Mark = 0;       /* Initialize to keep gcc silent */
     int           PtrOffs = 0;    /* Offset of function pointer on stack */
@@ -682,11 +676,12 @@ static void FunctionCall (ExprDesc* Expr)
        }
 
     /* Check for known standard functions and inline them if requested */
-    } else if (IS_Get (&InlineStdFuncs) && IsStdFunc ((const char*) Expr->Name)) {
+    } else if (IS_Get (&InlineStdFuncs) &&
+               (StdFunc = FindStdFunc ((const char*) Expr->Name)) >= 0) {
 
        /* Inline this function */
-               HandleStdFunc (Func, Expr);
-               goto ExitPoint;
+               HandleStdFunc (StdFunc, Func, Expr);
+               return;
 
     }
 
@@ -712,7 +707,7 @@ static void FunctionCall (ExprDesc* Expr)
                 */
                if (ParamSize == 0) {
                    RemoveCode (Mark);
-                   pop (CF_PTR);
+                   pop (CF_PTR);
                    PtrOnStack = 0;
                } else {
                    /* Load from the saved copy */
@@ -752,7 +747,6 @@ static void FunctionCall (ExprDesc* Expr)
 
     }
 
-ExitPoint:
     /* The function result is an rvalue in the primary register */
     ED_MakeRValExpr (Expr);
     Expr->Type = GetFuncReturn (Expr->Type);
@@ -1110,7 +1104,7 @@ static void ArrayRef (ExprDesc* Expr)
             * portion of the index (which is in (e)ax, so there's no further
             * action required).
             */
-           g_scale (CF_INT | CF_UNSIGNED, CheckedSizeOf (ElementType));
+           g_scale (CF_INT, CheckedSizeOf (ElementType));
 
                } else {
 
@@ -1144,7 +1138,7 @@ static void ArrayRef (ExprDesc* Expr)
                    /* The array base address is on stack and the subscript is in the
              * primary. Add both.
              */
-           g_add (CF_INT | CF_UNSIGNED, 0);
+           g_add (CF_INT, 0);
 
        } else {
 
@@ -1182,7 +1176,7 @@ static void ArrayRef (ExprDesc* Expr)
            } else {
                if (ED_IsLocAbs (Expr)) {
                    /* Constant numeric address. Just add it */
-                   g_inc (CF_INT | CF_UNSIGNED, Expr->Val);
+                   g_inc (CF_INT, Expr->Val);
                } else if (ED_IsLocStack (Expr)) {
                    /* Base address is a local variable address */
                    if (IsTypeArray (Expr->Type)) {
index 585e137c804ee58d8c0192f23136ee995b378646..14200a9e1953a7d2a572d35eb821fe5782be02cf 100644 (file)
 
 
 
+/* common */
+#include "xsprintf.h"
+
 /* cc65 */
+#include "asmlabel.h"
 #include "datatype.h"
+#include "error.h"
 #include "symentry.h"
 #include "exprdesc.h"
 
@@ -60,6 +65,64 @@ ExprDesc* ED_Init (ExprDesc* Expr)
 
 
 
+const char* ED_GetLabelName (const ExprDesc* Expr, long Offs)
+/* Return the assembler label name of the given expression. Beware: This
+ * function may use a static buffer, so the name may get "lost" on the second
+ * call to the function.
+ */
+{
+    static char Buf[256];
+
+    /* Expr may have it's own offset, adjust Offs accordingly */
+    Offs += Expr->Val;
+
+    /* Generate a label depending on the location */
+    switch (ED_GetLoc (Expr)) {
+
+        case E_LOC_ABS:
+            /* Absolute: numeric address or const */
+           xsprintf (Buf, sizeof (Buf), "$%04X", (int)(Offs & 0xFFFF));
+            break;
+
+        case E_LOC_GLOBAL:
+        case E_LOC_STATIC:
+            /* Global or static variable */
+           if (Offs) {
+               xsprintf (Buf, sizeof (Buf), "%s%+ld",
+                          SymGetAsmName (Expr->Sym), Offs);
+           } else {
+               xsprintf (Buf, sizeof (Buf), "%s",
+                          SymGetAsmName (Expr->Sym));
+           }
+            break;
+
+        case E_LOC_REGISTER:
+            /* Register variable */
+           xsprintf (Buf, sizeof (Buf), "regbank+%u",
+                      (unsigned)(Offs & 0xFFFFU));
+            break;
+
+        case E_LOC_LITERAL:
+            /* Literal in the literal pool */
+           if (Offs) {
+               xsprintf (Buf, sizeof (Buf), "%s%+ld",
+                          LocalLabelName (Expr->Name), Offs);
+           } else {
+                       xsprintf (Buf, sizeof (Buf), "%s",
+                          LocalLabelName (Expr->Name));
+           }
+            break;
+
+        default:
+            Internal ("Invalid location in ED_GetLabelName: 0x%04X", ED_GetLoc (Expr));
+    }
+
+    /* Return a pointer to the static buffer */
+    return Buf;
+}
+
+
+
 ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, type* Type)
 /* Make Expr an absolute const with the given value and type. */
 {
index 2b4ca0132f706c0ef45957086b37c2ecef94fb4c..49bcd2f5a35b3257a9eadc38da416fd69eae86a9 100644 (file)
@@ -123,6 +123,16 @@ INLINE int ED_IsLocAbs (const ExprDesc* Expr)
 #  define ED_IsLocAbs(Expr)     (((Expr)->Flags & E_MASK_LOC) == E_LOC_ABS)
 #endif
 
+#if defined(HAVE_INLINE)
+INLINE int ED_IsLocRegister (const ExprDesc* Expr)
+/* Return true if the expression is located in a register */
+{
+    return (Expr->Flags & E_MASK_LOC) == E_LOC_REGISTER;
+}
+#else
+#  define ED_IsLocRegister(Expr)    (((Expr)->Flags & E_MASK_LOC) == E_LOC_REGISTER)
+#endif
+
 #if defined(HAVE_INLINE)
 INLINE int ED_IsLocStack (const ExprDesc* Expr)
 /* Return true if the expression is located on the stack */
@@ -133,6 +143,16 @@ INLINE int ED_IsLocStack (const ExprDesc* Expr)
 #  define ED_IsLocStack(Expr)     (((Expr)->Flags & E_MASK_LOC) == E_LOC_STACK)
 #endif
 
+#if defined(HAVE_INLINE)
+INLINE int ED_IsLocPrimary (const ExprDesc* Expr)
+/* Return true if the expression is an expression in the register pseudo variable */
+{
+    return (Expr->Flags & E_MASK_LOC) == E_LOC_PRIMARY;
+}
+#else
+#  define ED_IsLocExpr(Expr)     (((Expr)->Flags & E_MASK_LOC) == E_LOC_PRIMARY)
+#endif
+
 #if defined(HAVE_INLINE)
 INLINE int ED_IsLocExpr (const ExprDesc* Expr)
 /* Return true if the expression is an expression in the primary */
@@ -143,6 +163,16 @@ INLINE int ED_IsLocExpr (const ExprDesc* Expr)
 #  define ED_IsLocExpr(Expr)     (((Expr)->Flags & E_MASK_LOC) == E_LOC_EXPR)
 #endif
 
+#if defined(HAVE_INLINE)
+INLINE int ED_IsLocLiteral (const ExprDesc* Expr)
+/* Return true if the expression is a string from the literal pool */
+{
+    return (Expr->Flags & E_MASK_LOC) == E_LOC_LITERAL;
+}
+#else
+#  define ED_IsLocLiteral(Expr)   (((Expr)->Flags & E_MASK_LOC) == E_LOC_LITERAL)
+#endif
+
 #if defined(HAVE_INLINE)
 INLINE int ED_IsLocConst (const ExprDesc* Expr)
 /* Return true if the expression is a constant location of some sort */
@@ -193,6 +223,12 @@ INLINE void ED_MakeRVal (ExprDesc* Expr)
 #  define ED_MakeRVal(Expr)       do { (Expr)->Flags &= ~E_RTYPE_LVAL; } while (0)
 #endif
 
+const char* ED_GetLabelName (const ExprDesc* Expr, long Offs);
+/* Return the assembler label name of the given expression. Beware: This
+ * function may use a static buffer, so the name may get "lost" on the second
+ * call to the function.
+ */
+
 ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, type* Type);
 /* Make Expr an absolute const with the given value and type. */
 
index abea777e8618b5943c05a52daa7fa8d9e24ef3f8..2e862a894f6adfff63f8bd1d3ff5554ee140c30f 100644 (file)
@@ -47,7 +47,6 @@ unsigned char AddSource               = 0;    /* Add source lines as comments */
 unsigned char DebugInfo                = 0;    /* Add debug info to the obj */
 unsigned char CreateDep                = 0;    /* Create a dependency file */
 unsigned char ANSI             = 0;    /* Strict ANSI flag */
-unsigned char WriteableStrings = 0;    /* Literal strings are r/w */
 unsigned char NoWarn           = 0;    /* Suppress warnings */
 unsigned char Optimize         = 0;    /* Optimize flag */
 unsigned long OptDisable       = 0;    /* Optimizer passes to disable */
@@ -56,6 +55,7 @@ unsigned      CodeSizeFactor  = 100;  /* Size factor for generated code */
 unsigned      RegisterSpace     = 6;    /* Space available for register vars */
 
 /* Stackable options */
+IntStack WritableStrings    = INTSTACK(0);  /* Literal strings are r/w */
 IntStack InlineStdFuncs     = INTSTACK(0);  /* Inline some known functions */
 IntStack EnableRegVars      = INTSTACK(0);  /* Enable register variables */
 IntStack AllowRegVarAddr    = INTSTACK(0);  /* Allow taking addresses of register vars */
index cc74c8df36423a514be06b8afd1972b630411b25..93032dae8480e2e6d60fc91e1cffee2fd617f3f2 100644 (file)
@@ -53,7 +53,6 @@ extern unsigned char  AddSource;              /* Add source lines as comments */
 extern unsigned char   DebugInfo;              /* Add debug info to the obj */
 extern unsigned char   CreateDep;              /* Create a dependency file */
 extern unsigned char   ANSI;                   /* Strict ANSI flag */
-extern unsigned char   WriteableStrings;       /* Literal strings are r/w */
 extern unsigned char   NoWarn;                 /* Suppress warnings */
 extern unsigned char   Optimize;               /* Optimize flag */
 extern unsigned long   OptDisable;             /* Optimizer passes to disable */
@@ -62,6 +61,7 @@ extern unsigned               CodeSizeFactor;         /* Size factor for generated code */
 extern unsigned         RegisterSpace;          /* Space available for register vars */
 
 /* Stackable options */
+extern IntStack         WritableStrings;       /* Literal strings are r/w */
 extern IntStack         InlineStdFuncs;                /* Inline some known functions */
 extern IntStack         EnableRegVars;         /* Enable register variables */
 extern IntStack         AllowRegVarAddr;       /* Allow taking addresses of register vars */
index e5bc9b737a29ca5bb652a02d6379a76057ac2315..e026db0d49af72c85687d75068e9ef46c7bfa785 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998     Ullrich von Bassewitz                                        */
-/*              Wacholderweg 14                                              */
-/*              D-70597 Stuttgart                                            */
-/* EMail:       uz@musoftware.de                                             */
+/* (C) 1998-2004 Ullrich von Bassewitz                                        */
+/*               RömerstraĂŸe 52                                              */
+/*               D-70794 Filderstadt                                         */
+/* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -93,7 +93,7 @@ void DumpLiteralPool (void)
     }
 
     /* Switch to the data segment */
-    if (WriteableStrings) {
+    if (IS_Get (&WritableStrings)) {
        g_usedata ();
     } else {
                g_userodata ();
@@ -168,7 +168,7 @@ void GetLiteralStrBuf (StrBuf* Target, unsigned Offs)
 /* Copy the string starting at Offs and lasting to the end of the buffer
  * into Target.
  */
-{                                        
+{
     CHECK (Offs <= SB_GetLen (&LiteralPool));
     SB_Slice (Target, &LiteralPool, Offs, SB_GetLen (&LiteralPool) - Offs);
 }
index 980a086d7f93460bbaebead30a18b231c11cbe3e..bb8864698f5ed7c7c21d245ef35fbcae47d7e6f8 100644 (file)
@@ -127,7 +127,8 @@ static void Usage (void)
                     "  --static-locals\tMake local variables static\n"
                     "  --target sys\t\tSet the target system\n"
                     "  --verbose\t\tIncrease verbosity\n"
-                    "  --version\t\tPrint the compiler version number\n",
+                    "  --version\t\tPrint the compiler version number\n"
+             "  --writable-strings\tMake string literals writable\n",
             ProgName);
 }
 
@@ -660,6 +661,15 @@ static void OptVersion (const char* Opt attribute ((unused)),
 
 
 
+static void OptWritableStrings (const char* Opt attribute ((unused)),
+                               const char* Arg attribute ((unused)))
+/* Make string literals writable */
+{
+    IS_Set (&WritableStrings, 1);
+}
+
+
+
 int main (int argc, char* argv[])
 {
     /* Program long options */
@@ -691,6 +701,7 @@ int main (int argc, char* argv[])
        { "--target",           1,      OptTarget               },
        { "--verbose",          0,      OptVerbose              },
        { "--version",          0,      OptVersion              },
+               { "--writable-strings", 0,      OptWritableStrings      },
     };
 
     unsigned I;
index 5e31221ea7f70ce4f4e0de78d6926269a454141f..9fa237c6e39ac6153858878bb92e2114c5bb8e38 100644 (file)
@@ -41,6 +41,7 @@
 #include "check.h"
 
 /* cc65 */
+#include "asmlabel.h"
 #include "codegen.h"
 #include "error.h"
 #include "funcdesc.h"
@@ -54,7 +55,7 @@
 
 
 /*****************************************************************************/
-/*                            Function forwards                             */
+/*                            Function forwards                             */
 /*****************************************************************************/
 
 
@@ -65,7 +66,7 @@ static void StdFunc_strlen (FuncDesc*, ExprDesc*);
 
 
 /*****************************************************************************/
-/*                                  Data                                    */
+/*                                  Data                                    */
 /*****************************************************************************/
 
 
@@ -75,13 +76,14 @@ static void StdFunc_strlen (FuncDesc*, ExprDesc*);
  */
 static struct StdFuncDesc {
     const char*                Name;
-    void               (*Handler) (FuncDesc*, ExprDesc*);
-} StdFuncs [] = {
+    void               (*Handler) (FuncDesc*, ExprDesc*);
+} StdFuncs[] = {
     {          "memset",       StdFunc_memset          },
     {          "strlen",       StdFunc_strlen          },
 
 };
-#define FUNC_COUNT     (sizeof (StdFuncs) / sizeof (StdFuncs [0]))
+#define FUNC_COUNT     (sizeof (StdFuncs) / sizeof (StdFuncs[0]))
+
 
 
 /*****************************************************************************/
@@ -98,16 +100,6 @@ static int CmpFunc (const void* Key, const void* Elem)
 
 
 
-static struct StdFuncDesc* FindFunc (const char* Name)
-/* Find a function with the given name. Return a pointer to the descriptor if
- * found, return NULL otherwise.
- */
-{
-    return bsearch (Name, StdFuncs, FUNC_COUNT, sizeof (StdFuncs [0]), CmpFunc);
-}
-
-
-
 static unsigned ParseArg (type* Type, ExprDesc* Arg)
 /* Parse one argument but do not push it onto the stack. Return the code
  * generator flags needed to do the actual push.
@@ -146,8 +138,7 @@ static unsigned ParseArg (type* Type, ExprDesc* Arg)
 
 
 
-static void StdFunc_memset (FuncDesc* F attribute ((unused)),
-                            ExprDesc* lval attribute ((unused)))
+static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
 /* Handle the memset function */
 {
     /* Argument types */
@@ -198,91 +189,123 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)),
 
     /* We expect the closing brace */
     ConsumeRParen ();
+
+    /* The function result is an rvalue in the primary register */
+    ED_MakeRValExpr (Expr);
+    Expr->Type = GetFuncReturn (Expr->Type);
 }
 
 
 
-static void StdFunc_strlen (FuncDesc* F attribute ((unused)),
-                            ExprDesc* lval attribute ((unused)))
+static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
 /* Handle the strlen function */
 {
-    static type   ParamType[] = { T_PTR, T_SCHAR, T_END };
-    ExprDesc      Param;
-    unsigned      CodeFlags;
-    unsigned long ParamName;
+    static type ArgType[] = { T_PTR, T_SCHAR, T_END };
+    ExprDesc    Arg;
+    unsigned    L;
+
 
     /* Setup the argument type string */
-    ParamType[1] = GetDefaultChar () | T_QUAL_CONST;
+    ArgType[1] = GetDefaultChar () | T_QUAL_CONST;
 
-    /* Fetch the parameter and convert it to the type needed */
-    hie1 (&Param);
-    TypeConversion (&Param, ParamType);
+    /* Evaluate the parameter */
+    hie1 (&Arg);
+
+    /* We can generate special code for several locations */
+    if (ED_IsLocConst (&Arg) && IsTypeArray (Arg.Type)) {
+
+        /* Do type conversion */
+        TypeConversion (&Arg, ArgType);
+
+        /* If the expression is a literal, and if string literals are read
+         * only, we can calculate the length of the string and remove it
+         * from the literal pool. Otherwise we have to calculate the length
+         * at runtime.
+         */
+        if (ED_IsLocLiteral (&Arg) && IS_Get (&WritableStrings)) {
+
+            /* Constant string literal */
+            ED_MakeConstAbs (Expr, strlen (GetLiteral (Arg.Val)), type_size_t);
+            ResetLiteralPoolOffs (Arg.Val);
+
+        } else {
+
+            /* Generate the strlen code */
+            L = GetLocalLabel ();
+            AddCodeLine ("ldy #$FF");
+            g_defcodelabel (L);
+            AddCodeLine ("iny");
+            AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg, 0));
+            AddCodeLine ("bne %s", LocalLabelName (L));
+            AddCodeLine ("tax");
+            AddCodeLine ("tya");
+
+            /* The function result is an rvalue in the primary register */
+            ED_MakeRValExpr (Expr);
+            Expr->Type = type_size_t;
 
-    /* Check if the parameter is a constant array of some type, or a numeric
-     * address cast to a pointer.
-     */
-    CodeFlags = 0;
-    ParamName = Param.Name;
-    if ((ED_IsLocConst (&Param) && IsTypeArray (Param.Type)) ||
-        (ED_IsLocAbs (&Param) && IsTypePtr (Param.Type))) {
-
-        /* Check which type of constant it is */
-        switch (ED_GetLoc (&Param)) {
-
-            case E_LOC_ABS:
-                /* Numerical address */
-                CodeFlags |= CF_CONST | CF_ABSOLUTE;
-                break;
-
-            case E_LOC_GLOBAL:
-                /* Global label */
-                CodeFlags |= CF_CONST | CF_EXTERNAL;
-                break;
-
-            case E_LOC_STATIC:
-                /* Local symbol */
-                CodeFlags |= CF_CONST | CF_STATIC;
-                break;
-
-            case E_LOC_REGISTER:
-                /* Register variable */
-                CodeFlags |= CF_CONST | CF_REGVAR;
-                break;
-
-            case E_LOC_LITERAL:
-                /* A literal of some kind. If string literals are read only,
-                 * we can calculate the length of the string and remove it
-                 * from the literal pool. Otherwise we have to calculate the
-                 * length at runtime.
-                 */
-                if (!WriteableStrings) {
-                    /* String literals are const */
-                    ExprDesc Length;
-                    ED_MakeConstAbsInt (&Length, strlen (GetLiteral (Param.Val)));
-                    ResetLiteralPoolOffs (Param.Val);
-                    ExprLoad (CF_NONE, &Length);
-                    goto ExitPoint;
-                } else {
-                    CodeFlags |= CF_CONST | CF_STATIC;
-                    ParamName = LiteralPoolLabel;
-                }
-                break;
-
-            default:
-                Internal ("Unknown constant type: %04X", Param.Flags);
         }
 
+    } else if (ED_IsLocStack (&Arg) && StackPtr >= -255 && IsTypeArray (Arg.Type)) {
+
+        /* Calculate the true stack offset */
+        unsigned Offs = (unsigned) (Arg.Val - StackPtr);
+
+        /* Do type conversion */
+        TypeConversion (&Arg, ArgType);
+
+        /* Generate the strlen code */
+        L = GetLocalLabel ();
+        AddCodeLine ("ldx #$FF");
+        AddCodeLine ("ldy #$%02X", (unsigned char) (Offs-1));
+        g_defcodelabel (L);
+        AddCodeLine ("inx");
+        AddCodeLine ("iny");
+        AddCodeLine ("lda (sp),y");
+        AddCodeLine ("bne %s", LocalLabelName (L));
+        AddCodeLine ("txa");
+        AddCodeLine ("ldx #$00");
+
+        /* The function result is an rvalue in the primary register */
+        ED_MakeRValExpr (Expr);
+        Expr->Type = type_size_t;
+
+    } else if (ED_IsLocRegister (&Arg) && ED_IsLVal (&Arg) && IsTypePtr (Arg.Type)) {
+
+        /* Do type conversion */
+        TypeConversion (&Arg, ArgType);
+
+        /* Generate the strlen code */
+        L = GetLocalLabel ();
+        AddCodeLine ("ldy #$FF");
+        g_defcodelabel (L);
+        AddCodeLine ("iny");
+        AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg, 0));
+        AddCodeLine ("bne %s", LocalLabelName (L));
+        AddCodeLine ("tax");
+        AddCodeLine ("tya");
+
+        /* The function result is an rvalue in the primary register */
+        ED_MakeRValExpr (Expr);
+        Expr->Type = type_size_t;
+
     } else {
 
-       /* Not an array with a constant address. Load parameter into primary */
-       ExprLoad (CF_NONE, &Param);
+        /* Do type conversion */
+        TypeConversion (&Arg, ArgType);
 
-    }
+        /* Load the expression into the primary */
+        ExprLoad (CF_NONE, &Arg);
+
+        /* Call the strlen function */
+        AddCodeLine ("jsr _%s", Func_strlen);
 
-    /* Generate the strlen code */
-    g_strlen (CodeFlags, ParamName, Param.Val);
+        /* The function result is an rvalue in the primary register */
+        ED_MakeRValExpr (Expr);
+        Expr->Type = type_size_t;
+
+    }
 
-ExitPoint:
     /* We expect the closing brace */
     ConsumeRParen ();
 }
@@ -295,23 +318,33 @@ ExitPoint:
 
 
 
-int IsStdFunc (const char* Name)
+int FindStdFunc (const char* Name)
 /* Determine if the given function is a known standard function that may be
- * called in a special way.
+ * called in a special way. If so, return the index, otherwise return -1.
  */
 {
     /* Look into the table for known names */
-    return FindFunc (Name) != 0;
+    struct StdFuncDesc* D =
+        bsearch (Name, StdFuncs, FUNC_COUNT, sizeof (StdFuncs[0]), CmpFunc);
+
+    /* Return the function index or -1 */
+    if (D == 0) {
+        return -1;
+    } else {
+        return D - StdFuncs;
+    }
 }
 
 
 
-void HandleStdFunc (FuncDesc* F, ExprDesc* lval)
+void HandleStdFunc (int Index, FuncDesc* F, ExprDesc* lval)
 /* Generate code for a known standard function. */
 {
+    struct StdFuncDesc* D;
+
     /* Get a pointer to the table entry */
-    struct StdFuncDesc* D = FindFunc ((const char*) lval->Name);
-    CHECK (D != 0);
+    CHECK (Index >= 0 && Index < (int)FUNC_COUNT);
+    D = StdFuncs + Index;
 
     /* Call the handler function */
     D->Handler (F, lval);
index 809dc617bfb8cead95f9d8ed60b6a85ba87c79f1..33094eceeb8d370574a53eddd02def9ad941075c 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2002 Ullrich von Bassewitz                                       */
-/*               Wacholderweg 14                                             */
-/*               D-70597 Stuttgart                                           */
-/* EMail:        uz@musoftware.de                                            */
+/* (C) 1998-2004 Ullrich von Bassewitz                                       */
+/*               Römerstrasse 52                                             */
+/*               D-70794 Filderstadt                                         */
+/* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
 
 
 
-int IsStdFunc (const char* Name);
+int FindStdFunc (const char* Name);
 /* Determine if the given function is a known standard function that may be
- * called in a special way.
+ * called in a special way. If so, return the index, otherwise return -1.
  */
 
-void HandleStdFunc (struct FuncDesc* F, ExprDesc* lval);
+void HandleStdFunc (int Index, struct FuncDesc* F, ExprDesc* lval);
 /* Generate code for a known standard function. */
 
 
index 78254448e80a2d5fbfc930ad9ad3e9e3b5169f37..eb17d871b0819bbfd951bab4386c5f7d03f7c6cd 100644 (file)
 
 
 
+const char Func__bzero[]        = "_bzero";     /* Asm name of "_bzero" */
 const char Func_memcpy[]        = "memcpy";     /* Asm name of "memcpy" */
 const char Func_memset[]        = "memset";     /* Asm name of "memset" */
-const char Func__bzero[]        = "_bzero";     /* Asm name of "_bzero */
+const char Func_strlen[]        = "strlen";     /* Asm name of "strlen" */
 
 
 
index b140c45bb36ec811cae9b712714d9983dd477041..cd67a8f2aa6f4ae7bdef25249a04cac286a4fbc5 100644 (file)
 /*****************************************************************************/
 
 
-                                                          
+
+extern const char Func__bzero[];        /* Asm name of "_bzero" */
 extern const char Func_memcpy[];        /* Asm name of "memcpy" */
 extern const char Func_memset[];        /* Asm name of "memset" */
-extern const char Func__bzero[];        /* Asm name of "_bzero */
+extern const char Func_strlen[];        /* Asm name of "strlen" */
 
 
 
index 530fc9ce1a8ec42e3c4f72ace19b131d17ef6c0a..ca925572c14192308dccfc43aa0d3523938d918e 100644 (file)
@@ -197,6 +197,16 @@ INLINE int SymIsRegVar (const SymEntry* Sym)
 #  define SymIsRegVar(Sym)      (((Sym)->Flags & (SC_REGISTER|SC_TYPE)) == SC_REGISTER)
 #endif
 
+#if defined(HAVE_INLINE)
+INLINE const char* SymGetAsmName (const SymEntry* Sym)
+/* Return the assembler label name for the symbol (beware: may be NULL!) */
+{
+    return Sym->AsmName;
+}
+#else
+#  define SymGetAsmName(Sym)      ((Sym)->AsmName)
+#endif
+
 void CvtRegVarToAuto (SymEntry* Sym);
 /* Convert a register variable to an auto variable */
 
index 34498259a21d8458257d0a53cd8e8dd17c13923f..cdd1aa2f5a622fbc00cb85a76ef01e374df5d350 100644 (file)
@@ -68,7 +68,7 @@ static void DoPtrConversions (ExprDesc* Expr)
 
 
 
-static void DoConversion (ExprDesc* Expr, type* NewType)
+static void DoConversion (ExprDesc* Expr, const type* NewType)
 /* Emit code to convert the given expression to a new type. */
 {
     type*    OldType;