mirror of
https://github.com/cc65/cc65.git
synced 2025-01-14 00:32:08 +00:00
Fixed the inlined strlen function
git-svn-id: svn://svn.cc65.org/cc65/trunk@1738 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
e84a1c068b
commit
4e2110a7a9
@ -8,7 +8,6 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* common */
|
||||
#include "check.h"
|
||||
@ -87,6 +86,9 @@ static GenDesc GenOASGN = { TOK_OR_ASSIGN, GEN_NOPUSH, g_or };
|
||||
|
||||
|
||||
|
||||
static int hie0 (ExprDesc *lval);
|
||||
/* Parse comma operator. */
|
||||
|
||||
static int expr (int (*func) (ExprDesc*), ExprDesc *lval);
|
||||
/* Expression parser; func is either hie0 or hie1. */
|
||||
|
||||
@ -183,7 +185,7 @@ static unsigned typeadjust (ExprDesc* lhs, ExprDesc* rhs, int NoPush)
|
||||
}
|
||||
flags = g_typeadjust (ltype, rtype);
|
||||
|
||||
/* Set the type of the result */
|
||||
/* Set the type of the result */
|
||||
lhs->Type = promoteint (lhst, rhst);
|
||||
|
||||
/* Return the code generator flags */
|
||||
@ -465,7 +467,7 @@ void ConstSubExpr (int (*F) (ExprDesc*), ExprDesc* Expr)
|
||||
* from this input error.
|
||||
*/
|
||||
{
|
||||
memset (Expr, 0, sizeof (*Expr));
|
||||
InitExprDesc (Expr);
|
||||
if (F (Expr) != 0 || Expr->Flags != E_MCONST) {
|
||||
Error ("Constant expression expected");
|
||||
/* To avoid any compiler errors, make the expression a valid const */
|
||||
@ -858,7 +860,7 @@ static int primary (ExprDesc* lval)
|
||||
*/
|
||||
if (CurTok.Tok == TOK_LPAREN) {
|
||||
NextToken ();
|
||||
memset (lval, 0, sizeof (*lval)); /* Remove any attributes */
|
||||
InitExprDesc (lval); /* Remove any attributes */
|
||||
k = hie0 (lval);
|
||||
ConsumeRParen ();
|
||||
return k;
|
||||
@ -915,7 +917,7 @@ static int primary (ExprDesc* lval)
|
||||
/* Check for legal symbol types */
|
||||
if ((Sym->Flags & SC_CONST) == SC_CONST) {
|
||||
/* Enum or some other numeric constant */
|
||||
lval->Flags = E_MCONST;
|
||||
lval->Flags = E_MCONST | E_TCONST;
|
||||
lval->ConstVal = Sym->V.ConstVal;
|
||||
return 0;
|
||||
} else if ((Sym->Flags & SC_FUNC) == SC_FUNC) {
|
||||
@ -1232,7 +1234,7 @@ static int arrayref (int k, ExprDesc* lval)
|
||||
if (rflags == E_MLOCAL) {
|
||||
g_addlocal (flags, lval2.ConstVal);
|
||||
} else {
|
||||
flags |= GlobalModeFlags (lval2.Flags);
|
||||
flags |= GlobalModeFlags (lval2.Flags);
|
||||
g_addstatic (flags, lval2.Name, lval2.ConstVal);
|
||||
}
|
||||
} else {
|
||||
@ -1241,20 +1243,20 @@ static int arrayref (int k, ExprDesc* lval)
|
||||
g_inc (CF_INT | CF_UNSIGNED, lval->ConstVal);
|
||||
} else if (lflags == E_MLOCAL) {
|
||||
/* Base address is a local variable address */
|
||||
if (IsTypeArray (tptr1)) {
|
||||
if (IsTypeArray (tptr1)) {
|
||||
g_addaddr_local (CF_INT, lval->ConstVal);
|
||||
} else {
|
||||
} else {
|
||||
g_addlocal (CF_PTR, lval->ConstVal);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Base address is a static variable address */
|
||||
unsigned flags = CF_INT;
|
||||
flags |= GlobalModeFlags (lval->Flags);
|
||||
if (IsTypeArray (tptr1)) {
|
||||
flags |= GlobalModeFlags (lval->Flags);
|
||||
if (IsTypeArray (tptr1)) {
|
||||
g_addaddr_static (flags, lval->Name, lval->ConstVal);
|
||||
} else {
|
||||
g_addstatic (flags, lval->Name, lval->ConstVal);
|
||||
}
|
||||
} else {
|
||||
g_addstatic (flags, lval->Name, lval->ConstVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3003,7 +3005,7 @@ int hie1 (ExprDesc* lval)
|
||||
|
||||
|
||||
|
||||
int hie0 (ExprDesc *lval)
|
||||
static int hie0 (ExprDesc *lval)
|
||||
/* Parse comma operator. */
|
||||
{
|
||||
int k;
|
||||
@ -3069,7 +3071,7 @@ void expression1 (ExprDesc* lval)
|
||||
* the primary register
|
||||
*/
|
||||
{
|
||||
memset (lval, 0, sizeof (*lval));
|
||||
InitExprDesc (lval);
|
||||
exprhs (CF_NONE, expr (hie1, lval), lval);
|
||||
}
|
||||
|
||||
@ -3078,7 +3080,7 @@ void expression1 (ExprDesc* lval)
|
||||
void expression (ExprDesc* lval)
|
||||
/* Evaluate an expression and put it into the primary register */
|
||||
{
|
||||
memset (lval, 0, sizeof (*lval));
|
||||
InitExprDesc (lval);
|
||||
exprhs (CF_NONE, expr (hie0, lval), lval);
|
||||
}
|
||||
|
||||
@ -3087,7 +3089,7 @@ void expression (ExprDesc* lval)
|
||||
void ConstExpr (ExprDesc* lval)
|
||||
/* Get a constant value */
|
||||
{
|
||||
memset (lval, 0, sizeof (*lval));
|
||||
InitExprDesc (lval);
|
||||
if (expr (hie1, lval) != 0 || (lval->Flags & E_MCONST) == 0) {
|
||||
Error ("Constant expression expected");
|
||||
/* To avoid any compiler errors, make the expression a valid const */
|
||||
@ -3100,7 +3102,7 @@ void ConstExpr (ExprDesc* lval)
|
||||
void ConstIntExpr (ExprDesc* Val)
|
||||
/* Get a constant int value */
|
||||
{
|
||||
memset (Val, 0, sizeof (*Val));
|
||||
InitExprDesc (Val);
|
||||
if (expr (hie1, Val) != 0 ||
|
||||
(Val->Flags & E_MCONST) == 0 ||
|
||||
!IsClassInt (Val->Type)) {
|
||||
@ -3134,8 +3136,7 @@ void Test (unsigned Label, int Invert)
|
||||
ExprDesc lval;
|
||||
|
||||
/* Evaluate the expression */
|
||||
memset (&lval, 0, sizeof (lval));
|
||||
k = expr (hie0, &lval);
|
||||
k = expr (hie0, InitExprDesc (&lval));
|
||||
|
||||
/* Check for a boolean expression */
|
||||
CheckBoolExpr (&lval);
|
||||
|
@ -88,9 +88,6 @@ int hie10 (ExprDesc* lval);
|
||||
int hie1 (ExprDesc* lval);
|
||||
/* Parse first level of expression hierarchy. */
|
||||
|
||||
int hie0 (ExprDesc* lval);
|
||||
/* Parse comma operator (highest level of expression hierarchy) */
|
||||
|
||||
void DefineData (ExprDesc* lval);
|
||||
/* Output a data definition for the given expression */
|
||||
|
||||
|
@ -38,13 +38,18 @@
|
||||
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* common */
|
||||
#include "inline.h"
|
||||
|
||||
/* cc65 */
|
||||
#include "datatype.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
@ -83,11 +88,21 @@ struct ExprDesc {
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE ExprDesc* InitExprDesc (ExprDesc* Expr)
|
||||
/* Initialize an ExprDesc */
|
||||
{
|
||||
return memset (Expr, 0, sizeof (*Expr));
|
||||
}
|
||||
#else
|
||||
# define InitExprDesc(E) memset ((E), 0, sizeof (*(E)))
|
||||
#endif
|
||||
|
||||
void MakeConstIntExpr (ExprDesc* Expr, long Value);
|
||||
/* Make Expr a constant integer expression with the given value */
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "error.h"
|
||||
#include "funcdesc.h"
|
||||
#include "global.h"
|
||||
#include "litpool.h"
|
||||
#include "scanner.h"
|
||||
#include "stdfunc.h"
|
||||
|
||||
@ -181,7 +182,7 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)),
|
||||
/* Push the argument */
|
||||
g_push (Flags, Arg.ConstVal);
|
||||
ParamSize += SizeOf (Arg2Type);
|
||||
}
|
||||
}
|
||||
ConsumeComma ();
|
||||
|
||||
/* Argument #3. Since memset is a fastcall function, we must load the
|
||||
@ -207,42 +208,86 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)),
|
||||
ExprDesc* lval attribute ((unused)))
|
||||
/* Handle the strlen function */
|
||||
{
|
||||
ExprDesc pval;
|
||||
static type ArgType[] = { T_PTR, T_SCHAR, T_END };
|
||||
static type ParamType[] = { T_PTR, T_SCHAR, T_END };
|
||||
|
||||
ExprDesc Param;
|
||||
unsigned CodeFlags;
|
||||
unsigned long ParamName;
|
||||
|
||||
/* Fetch the parameter */
|
||||
int k = hie1 (&pval);
|
||||
|
||||
/* Check if the parameter is a const address */
|
||||
unsigned flags = 0;
|
||||
unsigned pflags = pval.Flags & ~E_MCTYPE;
|
||||
if (pflags == E_MCONST) {
|
||||
/* Constant numeric address */
|
||||
flags |= CF_CONST | CF_ABSOLUTE;
|
||||
} else if (k == 0 && ((pflags & E_MGLOBAL) != 0 || pval.Flags == E_MEOFFS)) {
|
||||
/* Global array with or without offset */
|
||||
flags |= CF_CONST;
|
||||
if (pval.Flags & E_TGLAB) {
|
||||
/* External linkage */
|
||||
flags |= CF_EXTERNAL;
|
||||
} else {
|
||||
flags |= CF_STATIC;
|
||||
}
|
||||
} else {
|
||||
/* Not const, load parameter into primary */
|
||||
exprhs (CF_NONE, k, &pval);
|
||||
}
|
||||
int k = hie1 (InitExprDesc (&Param));
|
||||
|
||||
/* Setup the argument type string */
|
||||
ArgType[1] = GetDefaultChar () | T_QUAL_CONST;
|
||||
ParamType[1] = GetDefaultChar () | T_QUAL_CONST;
|
||||
|
||||
/* Convert the parameter type to the type needed, check for mismatches */
|
||||
assignadjust (ArgType, &pval);
|
||||
assignadjust (ParamType, &Param);
|
||||
|
||||
/* 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 ((IsTypeArray (Param.Type) && (Param.Flags & E_MCONST) != 0) ||
|
||||
(IsTypePtr (Param.Type) && Param.Flags == (E_MCONST | E_TCONST))) {
|
||||
|
||||
/* Check which type of constant it is */
|
||||
switch (Param.Flags & E_MCTYPE) {
|
||||
|
||||
case E_TCONST:
|
||||
/* Numerical address */
|
||||
CodeFlags |= CF_CONST | CF_ABSOLUTE;
|
||||
break;
|
||||
|
||||
case E_TREGISTER:
|
||||
/* Register variable */
|
||||
CodeFlags |= CF_CONST | CF_REGVAR;
|
||||
break;
|
||||
|
||||
case E_TGLAB:
|
||||
/* Global label */
|
||||
CodeFlags |= CF_CONST | CF_EXTERNAL;
|
||||
break;
|
||||
|
||||
case E_TLLAB:
|
||||
/* Local symbol */
|
||||
CodeFlags |= CF_CONST | CF_STATIC;
|
||||
break;
|
||||
|
||||
case E_TLIT:
|
||||
/* 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;
|
||||
MakeConstIntExpr (&Length, strlen (GetLiteral (Param.ConstVal)));
|
||||
ResetLiteralPoolOffs (Param.ConstVal);
|
||||
exprhs (CF_NONE, 0, &Length);
|
||||
goto ExitPoint;
|
||||
} else {
|
||||
CodeFlags |= CF_CONST | CF_STATIC;
|
||||
ParamName = LiteralPoolLabel;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Internal ("Unknown constant type: %04X", Param.Flags);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Not an array with a constant address. Load parameter into primary */
|
||||
exprhs (CF_NONE, k, &Param);
|
||||
|
||||
}
|
||||
|
||||
/* Generate the strlen code */
|
||||
g_strlen (flags, pval.Name, pval.ConstVal);
|
||||
g_strlen (CodeFlags, ParamName, Param.ConstVal);
|
||||
|
||||
ExitPoint:
|
||||
/* We expect the closing brace */
|
||||
ConsumeRParen ();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user