X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fexpr.c;h=89e708e0d091539ff3b2e1c10c01314f737fb630;hb=b821c2c8ae74aca5346429344034f3c5200e5570;hp=692ba4d55f445e43cc4fb5c907e8a41a518c11bf;hpb=89f00263af86905d08d8f0c61e105521cbe190dc;p=cc65 diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 692ba4d55..89e708e0d 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -8,10 +8,10 @@ #include #include -#include /* common */ #include "check.h" +#include "debugflag.h" #include "xmalloc.h" /* cc65 */ @@ -31,8 +31,8 @@ #include "scanner.h" #include "stdfunc.h" #include "symtab.h" -#include "typecast.h" #include "typecmp.h" +#include "typeconv.h" #include "expr.h" @@ -87,6 +87,9 @@ static GenDesc GenOASGN = { TOK_OR_ASSIGN, GEN_NOPUSH, g_or }; +int hie0 (ExprDesc *lval); +/* Parse comma operator. */ + static int expr (int (*func) (ExprDesc*), ExprDesc *lval); /* Expression parser; func is either hie0 or hie1. */ @@ -192,94 +195,6 @@ static unsigned typeadjust (ExprDesc* lhs, ExprDesc* rhs, int NoPush) -unsigned assignadjust (type* lhst, ExprDesc* rhs) -/* Adjust the type of the right hand expression so that it can be assigned to - * the type on the left hand side. This function is used for assignment and - * for converting parameters in a function call. It returns the code generator - * flags for the operation. The type string of the right hand side will be - * set to the type of the left hand side. - */ -{ - /* Get the type of the right hand side. Treat function types as - * pointer-to-function - */ - type* rhst = rhs->Type; - if (IsTypeFunc (rhst)) { - rhst = PointerTo (rhst); - } - - /* After calling this function, rhs will have the type of the lhs */ - rhs->Type = lhst; - - /* First, do some type checking */ - if (IsTypeVoid (lhst) || IsTypeVoid (rhst)) { - /* If one of the sides are of type void, output a more apropriate - * error message. - */ - Error ("Illegal type"); - } else if (IsClassInt (lhst)) { - if (IsClassPtr (rhst)) { - /* Pointer -> int conversion */ - Warning ("Converting pointer to integer without a cast"); - } else if (!IsClassInt (rhst)) { - Error ("Incompatible types"); - } else { - /* Convert the rhs to the type of the lhs. */ - unsigned flags = TypeOf (rhst); - if (rhs->Flags == E_MCONST) { - flags |= CF_CONST; - } - return g_typecast (TypeOf (lhst), flags); - } - } else if (IsClassPtr (lhst)) { - if (IsClassPtr (rhst)) { - /* Pointer to pointer assignment is valid, if: - * - both point to the same types, or - * - the rhs pointer is a void pointer, or - * - the lhs pointer is a void pointer. - */ - if (!IsTypeVoid (Indirect (lhst)) && !IsTypeVoid (Indirect (rhst))) { - /* Compare the types */ - switch (TypeCmp (lhst, rhst)) { - - case TC_INCOMPATIBLE: - Error ("Incompatible pointer types"); - break; - - case TC_QUAL_DIFF: - Error ("Pointer types differ in type qualifiers"); - break; - - default: - /* Ok */ - break; - } - } - } else if (IsClassInt (rhst)) { - /* Int to pointer assignment is valid only for constant zero */ - if (rhs->Flags != E_MCONST || rhs->ConstVal != 0) { - Warning ("Converting integer to pointer without a cast"); - } - } else if (IsTypeFuncPtr (lhst) && IsTypeFunc(rhst)) { - /* Assignment of function to function pointer is allowed, provided - * that both functions have the same parameter list. - */ - if (TypeCmp (Indirect (lhst), rhst) < TC_EQUAL) { - Error ("Incompatible types"); - } - } else { - Error ("Incompatible types"); - } - } else { - Error ("Incompatible types"); - } - - /* Return an int value in all cases where the operands are not both ints */ - return CF_INT; -} - - - void DefineData (ExprDesc* Expr) /* Output a data definition for the given expression */ { @@ -362,7 +277,7 @@ static void LoadConstant (unsigned Flags, ExprDesc* Expr) -static int kcalc (int tok, long val1, long val2) +static int kcalc (token_t tok, long val1, long val2) /* Calculate an operation with left and right operand constant. */ { switch (tok) { @@ -437,7 +352,7 @@ static int istypeexpr (void) (NextTok.Tok == TOK_CONST) || (NextTok.Tok == TOK_IDENT && (Entry = FindSym (NextTok.Ident)) != 0 && - IsTypeDef (Entry))); + SymIsTypeDef (Entry))); } @@ -465,7 +380,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 */ @@ -498,7 +413,7 @@ void CheckBoolExpr (ExprDesc* lval) -void exprhs (unsigned flags, int k, ExprDesc *lval) +void exprhs (unsigned flags, int k, ExprDesc* lval) /* Put the result of an expression into the primary register */ { int f; @@ -580,8 +495,7 @@ static unsigned FunctionParamList (FuncDesc* Func) FrameSize = Func->ParamSize; if (FrameParams > 0 && (Func->Flags & FD_FASTCALL) != 0) { /* Last parameter is not pushed */ - const SymEntry* LastParam = Func->SymTab->SymTail; - FrameSize -= CheckedSizeOf (LastParam->Type); + FrameSize -= CheckedSizeOf (Func->LastParam->Type); --FrameParams; } @@ -653,8 +567,8 @@ static unsigned FunctionParamList (FuncDesc* Func) * convert the actual argument to the type needed. */ if (!Ellipsis) { - /* Promote the argument if needed */ - assignadjust (Param->Type, &lval); + /* Convert the argument to the parameter type if needed */ + TypeConversion (&lval, 0, Param->Type); /* If we have a prototype, chars may be pushed as chars */ Flags |= CF_FORCECHAR; @@ -858,7 +772,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 +829,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) { @@ -938,6 +852,11 @@ static int primary (ExprDesc* lval) lval->Flags = E_MLOCAL | E_TLOFFS; lval->ConstVal = Sym->V.Offs; } + } else if ((Sym->Flags & SC_REGISTER) == SC_REGISTER) { + /* Register variable, zero page based */ + lval->Flags = E_MGLOBAL | E_MCONST | E_TREGISTER; + lval->Name = Sym->V.R.RegOffs; + lval->ConstVal = 0; } else if ((Sym->Flags & SC_STATIC) == SC_STATIC) { /* Static variable */ if (Sym->Flags & (SC_EXTERN | SC_STORAGE)) { @@ -948,11 +867,6 @@ static int primary (ExprDesc* lval) lval->Name = Sym->V.Label; } lval->ConstVal = 0; - } else if ((Sym->Flags & SC_REGISTER) == SC_REGISTER) { - /* Register variable, zero page based */ - lval->Flags = E_MGLOBAL | E_MCONST | E_TREGISTER; - lval->Name = Sym->V.Offs; - lval->ConstVal = 0; } else { /* Local static variable */ lval->Flags = E_MGLOBAL | E_MCONST | E_TLLAB; @@ -1102,9 +1016,10 @@ static int arrayref (int k, ExprDesc* lval) RemoveCode (Mark1); /* Handle constant base array on stack. Be sure NOT to - * handle pointers the same way, this won't work. + * handle pointers the same way, and check for character literals + * (both won't work). */ - if (IsTypeArray (tptr1) && + if (IsTypeArray (tptr1) && lval->Flags != (E_MCONST | E_TLIT) && ((lval->Flags & ~E_MCTYPE) == E_MCONST || (lval->Flags & ~E_MCTYPE) == E_MLOCAL || (lval->Flags & E_MGLOBAL) != 0 || @@ -1232,7 +1147,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 +1156,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); + } } } } @@ -1607,29 +1522,37 @@ int hie10 (ExprDesc* lval) case TOK_BOOL_NOT: NextToken (); if (evalexpr (CF_NONE, hie10, lval) == 0) { - /* Constant expression */ - lval->ConstVal = !lval->ConstVal; + /* Constant expression */ + lval->ConstVal = !lval->ConstVal; } else { - g_bneg (TypeOf (lval->Type)); - lval->Test |= E_CC; /* bneg will set cc */ - lval->Flags = E_MEXPR; /* say it's an expr */ + g_bneg (TypeOf (lval->Type)); + lval->Test |= E_CC; /* bneg will set cc */ + lval->Flags = E_MEXPR; /* say it's an expr */ } return 0; /* expr not storable */ case TOK_STAR: NextToken (); if (evalexpr (CF_NONE, hie10, lval) != 0) { - /* Expression is not const, indirect value loaded into primary */ - lval->Flags = E_MEXPR; - lval->ConstVal = 0; /* Offset is zero now */ + /* Expression is not const, indirect value loaded into primary */ + lval->Flags = E_MEXPR; + lval->ConstVal = 0; /* Offset is zero now */ } - t = lval->Type; - if (IsClassPtr (t)) { - lval->Type = Indirect (t); - } else { - Error ("Illegal indirection"); - } - return 1; + /* If the expression is already a pointer to function, the + * additional dereferencing operator must be ignored. + */ + if (IsTypeFuncPtr (lval->Type)) { + /* Expression not storable */ + return 0; + } else { + if (IsClassPtr (lval->Type)) { + lval->Type = Indirect (lval->Type); + } else { + Error ("Illegal indirection"); + } + return 1; + } + break; case TOK_AND: NextToken (); @@ -1638,32 +1561,32 @@ int hie10 (ExprDesc* lval) * applied to functions, even if they're no lvalues. */ if (k == 0 && !IsTypeFunc (lval->Type)) { - /* Allow the & operator with an array */ - if (!IsTypeArray (lval->Type)) { - Error ("Illegal address"); - } + /* Allow the & operator with an array */ + if (!IsTypeArray (lval->Type)) { + Error ("Illegal address"); + } } else { - t = TypeAlloc (TypeLen (lval->Type) + 2); - t [0] = T_PTR; - TypeCpy (t + 1, lval->Type); - lval->Type = t; + t = TypeAlloc (TypeLen (lval->Type) + 2); + t [0] = T_PTR; + TypeCpy (t + 1, lval->Type); + lval->Type = t; } return 0; case TOK_SIZEOF: NextToken (); if (istypeexpr ()) { - type Type[MAXTYPELEN]; - NextToken (); - lval->ConstVal = CheckedSizeOf (ParseType (Type)); - ConsumeRParen (); + type Type[MAXTYPELEN]; + NextToken (); + lval->ConstVal = CheckedSizeOf (ParseType (Type)); + ConsumeRParen (); } else { - /* Remember the output queue pointer */ - CodeMark Mark = GetCodePos (); - hie10 (lval); + /* Remember the output queue pointer */ + CodeMark Mark = GetCodePos (); + hie10 (lval); lval->ConstVal = CheckedSizeOf (lval->Type); - /* Remove any generated code */ - RemoveCode (Mark); + /* Remove any generated code */ + RemoveCode (Mark); } lval->Flags = E_MCONST | E_TCONST; lval->Type = type_uint; @@ -1672,8 +1595,8 @@ int hie10 (ExprDesc* lval) default: if (istypeexpr ()) { - /* A cast */ - return TypeCast (lval); + /* A cast */ + return TypeCast (lval); } } @@ -1697,7 +1620,7 @@ int hie10 (ExprDesc* lval) static int hie_internal (const GenDesc** ops, /* List of generators */ ExprDesc* lval, /* parent expr's lval */ int (*hienext) (ExprDesc*), - int* UsedGen) /* next higher level */ + int* UsedGen) /* next higher level */ /* Helper function */ { int k; @@ -2023,53 +1946,53 @@ static void parseadd (int k, ExprDesc* lval) g_scale (CF_INT, CheckedPSizeOf (lhst)); /* Operate on pointers, result type is a pointer */ flags |= CF_PTR; - /* Generate the code for the add */ - if (lval->Flags == E_MCONST) { - /* Numeric constant */ - g_inc (flags, lval->ConstVal); - } else { - /* Constant address */ - g_addaddr_static (flags, lval->Name, lval->ConstVal); - } + /* Generate the code for the add */ + if (lval->Flags == E_MCONST) { + /* Numeric constant */ + g_inc (flags, lval->ConstVal); + } else { + /* Constant address */ + g_addaddr_static (flags, lval->Name, lval->ConstVal); + } } else if (IsClassInt (lhst) && IsClassPtr (rhst)) { /* Left is int, right is pointer, must scale lhs. */ - unsigned ScaleFactor = CheckedPSizeOf (rhst); + unsigned ScaleFactor = CheckedPSizeOf (rhst); /* Operate on pointers, result type is a pointer */ - flags |= CF_PTR; - lval->Type = lval2.Type; - - /* Since we do already have rhs in the primary, if lhs is - * not a numeric constant, and the scale factor is not one - * (no scaling), we must take the long way over the stack. - */ - if (lval->Flags == E_MCONST) { - /* Numeric constant, scale lhs */ - lval->ConstVal *= ScaleFactor; - /* Generate the code for the add */ - g_inc (flags, lval->ConstVal); - } else if (ScaleFactor == 1) { - /* Constant address but no need to scale */ - g_addaddr_static (flags, lval->Name, lval->ConstVal); - } else { - /* Constant address that must be scaled */ + flags |= CF_PTR; + lval->Type = lval2.Type; + + /* Since we do already have rhs in the primary, if lhs is + * not a numeric constant, and the scale factor is not one + * (no scaling), we must take the long way over the stack. + */ + if (lval->Flags == E_MCONST) { + /* Numeric constant, scale lhs */ + lval->ConstVal *= ScaleFactor; + /* Generate the code for the add */ + g_inc (flags, lval->ConstVal); + } else if (ScaleFactor == 1) { + /* Constant address but no need to scale */ + g_addaddr_static (flags, lval->Name, lval->ConstVal); + } else { + /* Constant address that must be scaled */ g_push (TypeOf (lval2.Type), 0); /* rhs --> stack */ - g_getimmed (flags, lval->Name, lval->ConstVal); - g_scale (CF_PTR, ScaleFactor); - g_add (CF_PTR, 0); - } + g_getimmed (flags, lval->Name, lval->ConstVal); + g_scale (CF_PTR, ScaleFactor); + g_add (CF_PTR, 0); + } } else if (IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer addition */ flags |= typeadjust (lval, &lval2, 1); - /* Generate the code for the add */ - if (lval->Flags == E_MCONST) { - /* Numeric constant */ - g_inc (flags, lval->ConstVal); - } else { - /* Constant address */ - g_addaddr_static (flags, lval->Name, lval->ConstVal); - } + /* Generate the code for the add */ + if (lval->Flags == E_MCONST) { + /* Numeric constant */ + g_inc (flags, lval->ConstVal); + } else { + /* Constant address */ + g_addaddr_static (flags, lval->Name, lval->ConstVal); + } } else { /* OOPS */ Error ("Invalid operands for binary operator `+'"); @@ -2145,8 +2068,16 @@ static void parseadd (int k, ExprDesc* lval) flags = CF_PTR; lval->Type = lval2.Type; } else if (IsClassInt (lhst) && IsClassInt (rhst)) { - /* Integer addition */ - flags = typeadjust (lval, &lval2, 0); + /* Integer addition. Note: Result is never constant. + * Problem here is that typeadjust does not know if the + * variable is an rvalue or lvalue, so if both operands + * are dereferenced constant numeric addresses, typeadjust + * thinks the operation works on constants. Removing + * CF_CONST here means handling the symptoms, however, the + * whole parser is such a mess that I fear to break anything + * when trying to apply another solution. + */ + flags = typeadjust (lval, &lval2, 0) & ~CF_CONST; } else { /* OOPS */ Error ("Invalid operands for binary operator `+'"); @@ -3006,9 +2937,7 @@ int hie1 (ExprDesc* lval) int hie0 (ExprDesc *lval) /* Parse comma operator. */ { - int k; - - k = hie1 (lval); + int k = hie1 (lval); while (CurTok.Tok == TOK_COMMA) { NextToken (); k = hie1 (lval); @@ -3069,7 +2998,7 @@ void expression1 (ExprDesc* lval) * the primary register */ { - memset (lval, 0, sizeof (*lval)); + InitExprDesc (lval); exprhs (CF_NONE, expr (hie1, lval), lval); } @@ -3078,7 +3007,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 +3016,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 +3029,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 +3063,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);