From: cuz Date: Wed, 2 Jun 2004 21:33:35 +0000 (+0000) Subject: Rewrote code generation for the strlen standard function. Added code for X-Git-Tag: V2.12.0~763 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=6e34e386cb840daa2f6181e079ba486aa9681d59;p=cc65 Rewrote code generation for the strlen standard function. Added code for other standard functions in several places. git-svn-id: svn://svn.cc65.org/cc65/trunk@3069 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index 278ecc9b4..5b75a764f 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -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"); - } - } -} - - - diff --git a/src/cc65/codegen.h b/src/cc65/codegen.h index e251029f6..58e0217ef 100644 --- a/src/cc65/codegen.h +++ b/src/cc65/codegen.h @@ -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 diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 51aee0662..cc3fab011 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -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)) { diff --git a/src/cc65/exprdesc.c b/src/cc65/exprdesc.c index 585e137c8..14200a9e1 100644 --- a/src/cc65/exprdesc.c +++ b/src/cc65/exprdesc.c @@ -33,8 +33,13 @@ +/* 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. */ { diff --git a/src/cc65/exprdesc.h b/src/cc65/exprdesc.h index 2b4ca0132..49bcd2f5a 100644 --- a/src/cc65/exprdesc.h +++ b/src/cc65/exprdesc.h @@ -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. */ diff --git a/src/cc65/global.c b/src/cc65/global.c index abea777e8..2e862a894 100644 --- a/src/cc65/global.c +++ b/src/cc65/global.c @@ -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 */ diff --git a/src/cc65/global.h b/src/cc65/global.h index cc74c8df3..93032dae8 100644 --- a/src/cc65/global.h +++ b/src/cc65/global.h @@ -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 */ diff --git a/src/cc65/litpool.c b/src/cc65/litpool.c index e5bc9b737..e026db0d4 100644 --- a/src/cc65/litpool.c +++ b/src/cc65/litpool.c @@ -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); } diff --git a/src/cc65/main.c b/src/cc65/main.c index 980a086d7..bb8864698 100644 --- a/src/cc65/main.c +++ b/src/cc65/main.c @@ -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; diff --git a/src/cc65/stdfunc.c b/src/cc65/stdfunc.c index 5e31221ea..9fa237c6e 100644 --- a/src/cc65/stdfunc.c +++ b/src/cc65/stdfunc.c @@ -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); diff --git a/src/cc65/stdfunc.h b/src/cc65/stdfunc.h index 809dc617b..33094ecee 100644 --- a/src/cc65/stdfunc.h +++ b/src/cc65/stdfunc.h @@ -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 */ @@ -50,12 +50,12 @@ -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. */ diff --git a/src/cc65/stdnames.c b/src/cc65/stdnames.c index 78254448e..eb17d871b 100644 --- a/src/cc65/stdnames.c +++ b/src/cc65/stdnames.c @@ -43,9 +43,10 @@ +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" */ diff --git a/src/cc65/stdnames.h b/src/cc65/stdnames.h index b140c45bb..cd67a8f2a 100644 --- a/src/cc65/stdnames.h +++ b/src/cc65/stdnames.h @@ -43,10 +43,11 @@ /*****************************************************************************/ - + +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" */ diff --git a/src/cc65/symentry.h b/src/cc65/symentry.h index 530fc9ce1..ca925572c 100644 --- a/src/cc65/symentry.h +++ b/src/cc65/symentry.h @@ -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 */ diff --git a/src/cc65/typeconv.c b/src/cc65/typeconv.c index 34498259a..cdd1aa2f5 100644 --- a/src/cc65/typeconv.c +++ b/src/cc65/typeconv.c @@ -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;