From daf8e0d1e61af355cbf7139ff7af0478251dfbab Mon Sep 17 00:00:00 2001 From: cuz Date: Tue, 29 Jun 2004 20:26:27 +0000 Subject: [PATCH] Added license information preproc.h git-svn-id: svn://svn.cc65.org/cc65/trunk@3135 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/datatype.c | 21 +++++ src/cc65/datatype.h | 6 ++ src/cc65/expr.c | 206 +++++++++++++++++++++++++++++++++++++++----- src/cc65/expr.h | 9 +- src/cc65/exprdesc.c | 12 +-- src/cc65/exprdesc.h | 10 ++- src/cc65/preproc.c | 9 +- src/cc65/preproc.h | 39 +++++++-- src/cc65/typeconv.c | 68 +++++++++------ 9 files changed, 307 insertions(+), 73 deletions(-) diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index c35bb241b..93746b4df 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -57,6 +57,7 @@ /* Predefined type strings */ +type type_schar[] = { T_SCHAR, T_END }; type type_uchar[] = { T_UCHAR, T_END }; type type_int[] = { T_INT, T_END }; type type_uint[] = { T_UINT, T_END }; @@ -777,3 +778,23 @@ type* GetElementType (type* T) +type* IntPromotion (type* T) +/* Apply the integer promotions to T and return the result. The returned type + * string may be T if there is no need to change it. + */ +{ + /* We must have an int to apply int promotions */ + PRECONDITION (IsClassInt (T)); + + /* An integer can represent all values from either signed or unsigned char, + * so convert chars to int and leave all other types alone. + */ + if (IsTypeChar (T)) { + return type_int; + } else { + return T; + } +} + + + diff --git a/src/cc65/datatype.h b/src/cc65/datatype.h index 180654133..cf7849042 100644 --- a/src/cc65/datatype.h +++ b/src/cc65/datatype.h @@ -161,6 +161,7 @@ typedef unsigned short type; #define SIZEOF_PTR 2 /* Predefined type strings */ +extern type type_schar[]; extern type type_uchar[]; extern type type_int[]; extern type type_uint[]; @@ -490,6 +491,11 @@ long GetElementCount (const type* T); type* GetElementType (type* T); /* Return the element type of the given array type. */ +type* IntPromotion (type* T); +/* Apply the integer promotions to T and return the result. The returned type + * string may be T if there is no need to change it. + */ + /* End of datatype.h */ diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 6cff40326..6cd41138b 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -68,17 +68,6 @@ static GenDesc GenOASGN = { TOK_OR_ASSIGN, GEN_NOPUSH, g_or }; -/*****************************************************************************/ -/* Function forwards */ -/*****************************************************************************/ - - - -void hie0 (ExprDesc *lval); -/* Parse comma operator. */ - - - /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ @@ -97,7 +86,7 @@ static unsigned GlobalModeFlags (unsigned Flags) } } - + void ExprWithCheck (void (*Func) (ExprDesc*), ExprDesc *Expr) /* Call an expression function with checks. */ @@ -2277,7 +2266,7 @@ static void parsesub (ExprDesc* Expr) -static void hie8 (ExprDesc* Expr) +void hie8 (ExprDesc* Expr) /* Process + and - binary operators. */ { hie9 (Expr); @@ -2293,16 +2282,191 @@ static void hie8 (ExprDesc* Expr) static void hie7 (ExprDesc* Expr) -/* Parse << and >>. */ +/* Parse the << and >> operators. */ { - static const GenDesc hie7_ops [] = { - { TOK_SHL, GEN_NOPUSH, g_asl }, - { TOK_SHR, GEN_NOPUSH, g_asr }, - { TOK_INVALID, 0, 0 } - }; - int UsedGen; + ExprDesc Expr2; + CodeMark Mark1; + CodeMark Mark2; + token_t Tok; /* The operator token */ + unsigned ltype, rtype, flags; + int rconst; /* Operand is a constant */ + + + /* Evaluate the lhs */ + ExprWithCheck (hie8, Expr); + + while (CurTok.Tok == TOK_SHL || CurTok.Tok == TOK_SHR) { + + /* All operators that call this function expect an int on the lhs */ + if (!IsClassInt (Expr->Type)) { + Error ("Integer expression expected"); + ED_MakeConstAbsInt (Expr, 1); + } - hie_internal (hie7_ops, Expr, hie8, &UsedGen); + /* Remember the operator token, then skip it */ + Tok = CurTok.Tok; + NextToken (); + + /* Get the lhs on stack */ + Mark1 = GetCodePos (); + ltype = TypeOf (Expr->Type); + if (ED_IsConstAbs (Expr)) { + /* Constant value */ + Mark2 = GetCodePos (); + g_push (ltype | CF_CONST, Expr->IVal); + } else { + /* Value not constant */ + LoadExpr (CF_NONE, Expr); + Mark2 = GetCodePos (); + g_push (ltype, 0); + } + + /* Get the right hand side */ + ExprWithCheck (hie8, &Expr2); + + /* Check the type of the rhs */ + if (!IsClassInt (Expr2.Type)) { + Error ("Integer expression expected"); + ED_MakeConstAbsInt (&Expr2, 1); + } + + /* Check for a constant right side expression */ + rconst = ED_IsConstAbs (&Expr2); + if (!rconst) { + + /* Not constant, load into the primary */ + LoadExpr (CF_NONE, &Expr2); + + } else { + + /* If the right hand side is constant, we can check a lot of + * things: + */ + + /* If the shift count is zero, nothing happens */ + if (Expr2.IVal == 0) { + + /* Result is already in Expr, remove the generated code */ + RemoveCode (Mark1); + pop (ltype); + + /* Done */ + goto Next; + } + + /* If the left hand side is a constant, the result is constant */ + if (ED_IsConstAbs (Expr)) { + + /* Evaluate the result */ + Expr->IVal = kcalc (Tok, Expr->IVal, Expr2.IVal); + + /* Both operands are constant, remove the generated code */ + RemoveCode (Mark1); + pop (ltype); + + /* Done */ + goto Next; + } + + /* If we're shifting to the left, and the shift count is larger + * or equal than the bit count of the integer type, the result + * is zero. + */ + if (Tok == TOK_SHL && Expr2.IVal >= (long) SizeOf (Expr->Type) * 8) { + + /* Set the result */ + ED_MakeConstAbs (Expr, 0, Expr->Type); + + /* Result is zero, remove the generated code */ + RemoveCode (Mark1); + pop (ltype); + + /* Done */ + goto Next; + } + + /* If we're shifting an integer or unsigned to the right, the + * lhs has a const address, and the shift count is larger than 8, + * we can load just the high byte as a char with the correct + * signedness, and reduce the shift count by 8. If the remaining + * shift count is zero, we're done. + */ + if (Tok == TOK_SHR && + IsTypeInt (Expr->Type) && + ED_IsLVal (Expr) && + (ED_IsLocConst (Expr) || ED_IsLocStack (Expr)) && + Expr2.IVal >= 8) { + + type* OldType; + + /* Increase the address by one and decrease the shift count */ + ++Expr->IVal; + Expr2.IVal -= 8; + + /* Replace the type of the expression temporarily by the + * corresponding char type. + */ + OldType = Expr->Type; + if (IsSignUnsigned (Expr->Type)) { + Expr->Type = type_uchar; + } else { + Expr->Type = type_schar; + } + + /* Remove the generated load code */ + RemoveCode (Mark1); + pop (ltype); + + /* Generate again code for the load */ + LoadExpr (CF_NONE, Expr); + + /* Reset the type */ + Expr->Type = OldType; + + /* If the shift count is now zero, we're done */ + if (Expr2.IVal == 0) { + /* Be sure to mark the value as in the primary */ + goto Loaded; + } + + /* Otherwise generate code to push the value */ + Mark2 = GetCodePos (); + g_push (ltype, 0); + } + + } + + /* If the right hand side is a constant, remove the push of the + * primary register. + */ + rtype = TypeOf (Expr2.Type); + flags = 0; + if (rconst) { + flags |= CF_CONST; + rtype |= CF_CONST; + RemoveCode (Mark2); + pop (ltype); + ltype |= CF_REG; /* Value is in register */ + } + + /* Determine the type of the operation result. */ + flags |= g_typeadjust (ltype, rtype); + + /* Generate code */ + switch (Tok) { + case TOK_SHL: g_asl (flags, Expr2.IVal); break; + case TOK_SHR: g_asr (flags, Expr2.IVal); break; + default: break; + } + +Loaded: + /* We have a rvalue in the primary now */ + ED_MakeRValExpr (Expr); + +Next: + /* Get the type of the result */ + Expr->Type = promoteint (Expr->Type, Expr2.Type); + } } diff --git a/src/cc65/expr.h b/src/cc65/expr.h index 9f5668977..e166dd5ee 100644 --- a/src/cc65/expr.h +++ b/src/cc65/expr.h @@ -39,9 +39,6 @@ void Store (ExprDesc* Expr, const type* StoreType); * is NULL, use lval->Type instead. */ -void hie0 (ExprDesc* Expr); -/* Parse comma operator. */ - int evalexpr (unsigned flags, void (*Func) (ExprDesc*), ExprDesc* Expr); /* Will evaluate an expression via the given function. If the result is a * constant, 0 is returned and the value is put in the lval struct. If the @@ -76,9 +73,15 @@ void ConstAbsIntExpr (void (*Func) (ExprDesc*), ExprDesc* Expr); void hie10 (ExprDesc* lval); /* Handle ++, --, !, unary - etc. */ +void hie8 (ExprDesc* Expr); +/* Process + and - binary operators. */ + void hie1 (ExprDesc* lval); /* Parse first level of expression hierarchy. */ +void hie0 (ExprDesc* Expr); +/* Parse comma operator. */ + void DefineData (ExprDesc* lval); /* Output a data definition for the given expression */ diff --git a/src/cc65/exprdesc.c b/src/cc65/exprdesc.c index 9b9a0a6fb..4de2a6adf 100644 --- a/src/cc65/exprdesc.c +++ b/src/cc65/exprdesc.c @@ -192,7 +192,7 @@ ExprDesc* ED_MakeLValExpr (ExprDesc* Expr) Expr->Flags |= (E_LOC_EXPR | E_RTYPE_LVAL); Expr->Name = 0; Expr->IVal = 0; /* No offset */ - Expr->FVal = 0.0; + Expr->FVal = 0.0; return Expr; } @@ -209,16 +209,6 @@ int ED_IsConst (const ExprDesc* Expr) -int ED_IsConstAbs (const ExprDesc* Expr) -/* Return true if the expression denotes a constant absolute value. This can be - * a numeric constant, cast to any type. - */ -{ - return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL); -} - - - int ED_IsConstAbsInt (const ExprDesc* Expr) /* Return true if the expression is a constant (numeric) integer. */ { diff --git a/src/cc65/exprdesc.h b/src/cc65/exprdesc.h index 97f87b162..7b945666c 100644 --- a/src/cc65/exprdesc.h +++ b/src/cc65/exprdesc.h @@ -307,10 +307,18 @@ int ED_IsConst (const ExprDesc* Expr); * similar. */ -int ED_IsConstAbs (const ExprDesc* Expr); +#if defined(HAVE_INLINE) +INLINE int ED_IsConstAbs (const ExprDesc* Expr) /* Return true if the expression denotes a constant absolute value. This can be * a numeric constant, cast to any type. */ +{ + return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL); +} +#else +# define ED_IsConstAbs(E) \ + (((E)->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL)) +#endif int ED_IsConstAbsInt (const ExprDesc* Expr); /* Return true if the expression is a constant (numeric) integer. */ diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index e22727d65..282322085 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -1,6 +1,9 @@ - -/* C pre-processor functions */ - +/* + * C pre-processor functions. + * Portions of this code are copyright (C) 1989 John R. Dunning. + * See copyleft.jrd for license information. + */ + #include #include #include diff --git a/src/cc65/preproc.h b/src/cc65/preproc.h index b6fc559cf..286d309d1 100644 --- a/src/cc65/preproc.h +++ b/src/cc65/preproc.h @@ -1,8 +1,35 @@ -/* - * preproc.h - * - * Ullrich von Bassewitz, 07.06.1998 - */ +/*****************************************************************************/ +/* */ +/* preproc.h */ +/* */ +/* C preprocessor */ +/* */ +/* */ +/* */ +/* (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 */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ @@ -17,7 +44,7 @@ -/* Set when the pp calls expr() recursively */ +/* Set when the preprocessor calls ConstExpr() recursively */ extern unsigned char Preprocessing; diff --git a/src/cc65/typeconv.c b/src/cc65/typeconv.c index 3b30461c7..cf3c9a3ef 100644 --- a/src/cc65/typeconv.c +++ b/src/cc65/typeconv.c @@ -195,6 +195,12 @@ void TypeConversion (ExprDesc* Expr, type* NewType) Error ("Illegal type"); } + /* If both types are equal, no conversion is needed */ + if (TypeCmp (Expr->Type, NewType) >= TC_EQUAL) { + /* We're already done */ + return; + } + /* Check for conversion problems */ if (IsClassInt (NewType)) { @@ -202,10 +208,16 @@ void TypeConversion (ExprDesc* Expr, type* NewType) if (IsClassPtr (Expr->Type)) { /* Pointer -> int conversion */ Warning ("Converting pointer to integer without a cast"); - } else if (!IsClassInt (Expr->Type)) { + } else if (!IsClassInt (Expr->Type) && !IsClassFloat (Expr->Type)) { Error ("Incompatible types"); } + } else if (IsClassFloat (NewType)) { + + if (!IsClassFloat (Expr->Type) && !IsClassInt (Expr->Type)) { + Error ("Incompatible types"); + } + } else if (IsClassPtr (NewType)) { /* Handle conversions to pointer type */ @@ -213,40 +225,40 @@ void TypeConversion (ExprDesc* Expr, type* NewType) /* 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. + * - the lhs pointer is a void pointer. */ - if (!IsTypeVoid (Indirect (NewType)) && !IsTypeVoid (Indirect (Expr->Type))) { - /* Compare the types */ - switch (TypeCmp (NewType, Expr->Type)) { - - case TC_INCOMPATIBLE: - Error ("Incompatible pointer types"); - break; - - case TC_QUAL_DIFF: - Error ("Pointer types differ in type qualifiers"); - break; - - default: - /* Ok */ - break; - } - } + if (!IsTypeVoid (Indirect (NewType)) && !IsTypeVoid (Indirect (Expr->Type))) { + /* Compare the types */ + switch (TypeCmp (NewType, Expr->Type)) { + + 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 (Expr->Type)) { /* Int to pointer assignment is valid only for constant zero */ if (!ED_IsConstAbsInt (Expr) || Expr->IVal != 0) { Warning ("Converting integer to pointer without a cast"); } - } else if (IsTypeFuncPtr (NewType) && IsTypeFunc(Expr->Type)) { - /* Assignment of function to function pointer is allowed, provided - * that both functions have the same parameter list. - */ - if (TypeCmp (Indirect (NewType), Expr->Type) < TC_EQUAL) { - Error ("Incompatible types"); - } + } else if (IsTypeFuncPtr (NewType) && IsTypeFunc(Expr->Type)) { + /* Assignment of function to function pointer is allowed, provided + * that both functions have the same parameter list. + */ + if (TypeCmp (Indirect (NewType), Expr->Type) < TC_EQUAL) { + Error ("Incompatible types"); + } } else { - Error ("Incompatible types"); - } + Error ("Incompatible types"); + } } else { -- 2.39.5