From 02c26efdd3abe12b8376420567836b639883a143 Mon Sep 17 00:00:00 2001 From: cuz Date: Tue, 16 Jul 2002 11:01:51 +0000 Subject: [PATCH] Replace calls to memset with _bzero if the fill value is zero and -Oi in effect. git-svn-id: svn://svn.cc65.org/cc65/trunk@1359 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/expr.c | 4 +- src/cc65/stdfunc.c | 115 +++++++++++++++++++++++++++++++++++++++++---- src/cc65/stdfunc.h | 15 +++--- 3 files changed, 116 insertions(+), 18 deletions(-) diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 0f4a6a657..dfebf8adc 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -244,7 +244,7 @@ unsigned assignadjust (type* lhst, ExprDesc* rhs) case TC_INCOMPATIBLE: Error ("Incompatible pointer types"); break; - + case TC_QUAL_DIFF: Error ("Pointer types differ in type qualifiers"); break; @@ -756,7 +756,7 @@ static void FunctionCall (int k, ExprDesc* lval) } else if (InlineStdFuncs && IsStdFunc ((const char*) lval->Name)) { /* Inline this function */ - HandleStdFunc (lval); + HandleStdFunc (Func, lval); return; } diff --git a/src/cc65/stdfunc.c b/src/cc65/stdfunc.c index ff554a393..6d1c18440 100644 --- a/src/cc65/stdfunc.c +++ b/src/cc65/stdfunc.c @@ -37,11 +37,13 @@ #include /* common */ +#include "attrib.h" #include "check.h" /* cc65 */ #include "codegen.h" #include "error.h" +#include "funcdesc.h" #include "global.h" #include "scanner.h" #include "stdfunc.h" @@ -49,17 +51,18 @@ /*****************************************************************************/ -/* Function forwards */ +/* Function forwards */ /*****************************************************************************/ -static void StdFunc_strlen (ExprDesc*); +static void StdFunc_memset (FuncDesc*, ExprDesc*); +static void StdFunc_strlen (FuncDesc*, ExprDesc*); /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ @@ -69,8 +72,9 @@ static void StdFunc_strlen (ExprDesc*); */ static struct StdFuncDesc { const char* Name; - void (*Handler) (ExprDesc*); + void (*Handler) (FuncDesc*, ExprDesc*); } StdFuncs [] = { + { "memset", StdFunc_memset }, { "strlen", StdFunc_strlen }, }; @@ -101,13 +105,106 @@ static struct StdFuncDesc* FindFunc (const char* Name) +static unsigned ParseArg (type* Type, ExprDesc* pval) +/* Parse one argument but do not push it onto the stack. Return the code + * generator flags needed to do the actual push. + */ +{ + unsigned CFlags; + unsigned Flags; + + /* Do some optimization: If we have a constant value to push, + * use a special function that may optimize. + */ + CFlags = CF_NONE; + if (CheckedSizeOf (Type) == 1) { + CFlags = CF_FORCECHAR; + } + Flags = CF_NONE; + if (evalexpr (CFlags, hie1, pval) == 0) { + /* A constant value */ + Flags |= CF_CONST; + } + + /* Promote the argument if needed */ + assignadjust (Type, pval); + + /* We have a prototype, so chars may be pushed as chars */ + Flags |= CF_FORCECHAR; + + /* Use the type of the argument for the push */ + return (Flags | TypeOf (pval->Type)); +} + + + /*****************************************************************************/ /* Handle known functions */ /*****************************************************************************/ -static void StdFunc_strlen (ExprDesc* lval attribute ((unused))) +static void StdFunc_memset (FuncDesc* F attribute ((unused)), + ExprDesc* lval attribute ((unused))) +/* Handle the memset function */ +{ + /* Argument types */ + static type Arg1Type[] = { T_PTR, T_VOID, T_END }; /* void* */ + static type Arg2Type[] = { T_INT, T_END }; /* int */ + static type Arg3Type[] = { T_UINT, T_END }; /* size_t */ + + unsigned Flags; + ExprDesc Arg; + int MemSet = 1; /* Use real memset if true */ + unsigned ParamSize = 0; + + + /* Check the prototype of the function against what we know about it, so + * we can detect errors. + */ + /* ### */ + + /* Argument #1 */ + Flags = ParseArg (Arg1Type, &Arg); + g_push (Flags, Arg.ConstVal); + ParamSize += SizeOf (Arg1Type); + ConsumeComma (); + + /* Argument #2. This argument is special in that we will call another + * function if it is a constant zero. + */ + Flags = ParseArg (Arg2Type, &Arg); + if ((Flags & CF_CONST) != 0 && Arg.ConstVal == 0) { + /* Don't call memset, call bzero instead */ + MemSet = 0; + } else { + /* Push the argument */ + g_push (Flags, Arg.ConstVal); + ParamSize += SizeOf (Arg2Type); + } + ConsumeComma (); + + /* Argument #3. Since memset is a fastcall function, we must load the + * arg into the primary if it is not already there. This parameter is + * also ignored for the calculation of the parameter size, since it is + * not passed via the stack. + */ + Flags = ParseArg (Arg3Type, &Arg); + if (Flags & CF_CONST) { + exprhs (CF_FORCECHAR, 0, &Arg); + } + + /* Emit the actual function call */ + g_call (CF_NONE, MemSet? "memset" : "_bzero", ParamSize); + + /* We expect the closing brace */ + ConsumeRParen (); +} + + + +static void StdFunc_strlen (FuncDesc* F attribute ((unused)), + ExprDesc* lval attribute ((unused))) /* Handle the strlen function */ { ExprDesc pval; @@ -169,15 +266,15 @@ int IsStdFunc (const char* Name) -void HandleStdFunc (ExprDesc* lval) +void HandleStdFunc (FuncDesc* F, ExprDesc* lval) /* Generate code for a known standard function. */ { /* Get a pointer to the table entry */ - struct StdFuncDesc* F = FindFunc ((const char*) lval->Name); - CHECK (F != 0); + struct StdFuncDesc* D = FindFunc ((const char*) lval->Name); + CHECK (D != 0); /* Call the handler function */ - F->Handler (lval); + D->Handler (F, lval); } diff --git a/src/cc65/stdfunc.h b/src/cc65/stdfunc.h index 19bc06c0c..809dc617b 100644 --- a/src/cc65/stdfunc.h +++ b/src/cc65/stdfunc.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* (C) 1998-2002 Ullrich von Bassewitz */ +/* Wacholderweg 14 */ +/* D-70597 Stuttgart */ +/* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -38,13 +38,14 @@ -#include "symtab.h" +/* cc65 */ #include "expr.h" +#include "symtab.h" /*****************************************************************************/ -/* Code */ +/* Code */ /*****************************************************************************/ @@ -54,7 +55,7 @@ int IsStdFunc (const char* Name); * called in a special way. */ -void HandleStdFunc (ExprDesc* lval); +void HandleStdFunc (struct FuncDesc* F, ExprDesc* lval); /* Generate code for a known standard function. */ -- 2.39.5