#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
/* common */
#include "check.h"
+static int hie0 (ExprDesc *lval);
+/* Parse comma operator. */
+
static int expr (int (*func) (ExprDesc*), ExprDesc *lval);
/* Expression parser; func is either hie0 or hie1. */
}
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 */
* 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 */
*/
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;
/* 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) {
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 {
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);
+ }
}
}
}
-int hie0 (ExprDesc *lval)
+static int hie0 (ExprDesc *lval)
/* Parse comma operator. */
{
int k;
* the primary register
*/
{
- memset (lval, 0, sizeof (*lval));
+ InitExprDesc (lval);
exprhs (CF_NONE, expr (hie1, lval), 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);
}
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 */
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)) {
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);
#include "error.h"
#include "funcdesc.h"
#include "global.h"
+#include "litpool.h"
#include "scanner.h"
#include "stdfunc.h"
/* Push the argument */
g_push (Flags, Arg.ConstVal);
ParamSize += SizeOf (Arg2Type);
- }
+ }
ConsumeComma ();
/* Argument #3. Since memset is a fastcall function, we must load the
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 ();
}