X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fexpr.c;h=7563645ff0e9bf6e28da7a8c12bcd6fb049ff06e;hb=74074a20b2ab6e7ed7f2b9b3b42a8facdf0b88d9;hp=b4704009604a470d37f4d16dac8977e472ec4306;hpb=40d01eb4cece210f6336d786ae0acb7f26c448c4;p=cc65 diff --git a/src/cc65/expr.c b/src/cc65/expr.c index b47040096..7563645ff 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -1,7 +1,8 @@ /* expr.c - * - * Ullrich von Bassewitz, 21.06.1998 - */ +** +** 1998-06-21, Ullrich von Bassewitz +** 2015-06-26, Greg King +*/ @@ -31,6 +32,7 @@ #include "scanner.h" #include "shiftexpr.h" #include "stackptr.h" +#include "standard.h" #include "stdfunc.h" #include "symtab.h" #include "typecmp.h" @@ -40,50 +42,56 @@ /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ /* Generator attributes */ -#define GEN_NOPUSH 0x01 /* Don't push lhs */ +#define GEN_NOPUSH 0x01 /* Don't push lhs */ +#define GEN_COMM 0x02 /* Operator is commutative */ /* Map a generator function and its attributes to a token */ typedef struct { - token_t Tok; /* Token to map to */ - unsigned Flags; /* Flags for generator function */ - void (*Func) (unsigned, unsigned long); /* Generator func */ + token_t Tok; /* Token to map to */ + unsigned Flags; /* Flags for generator function */ + void (*Func) (unsigned, unsigned long); /* Generator func */ } GenDesc; /* Descriptors for the operations */ -static GenDesc GenPASGN = { TOK_PLUS_ASSIGN, GEN_NOPUSH, g_add }; +static GenDesc GenPASGN = { TOK_PLUS_ASSIGN, GEN_NOPUSH, g_add }; static GenDesc GenSASGN = { TOK_MINUS_ASSIGN, GEN_NOPUSH, g_sub }; -static GenDesc GenMASGN = { TOK_MUL_ASSIGN, GEN_NOPUSH, g_mul }; -static GenDesc GenDASGN = { TOK_DIV_ASSIGN, GEN_NOPUSH, g_div }; -static GenDesc GenMOASGN = { TOK_MOD_ASSIGN, GEN_NOPUSH, g_mod }; -static GenDesc GenSLASGN = { TOK_SHL_ASSIGN, GEN_NOPUSH, g_asl }; -static GenDesc GenSRASGN = { TOK_SHR_ASSIGN, GEN_NOPUSH, g_asr }; -static GenDesc GenAASGN = { TOK_AND_ASSIGN, GEN_NOPUSH, g_and }; -static GenDesc GenXOASGN = { TOK_XOR_ASSIGN, GEN_NOPUSH, g_xor }; -static GenDesc GenOASGN = { TOK_OR_ASSIGN, GEN_NOPUSH, g_or }; +static GenDesc GenMASGN = { TOK_MUL_ASSIGN, GEN_NOPUSH, g_mul }; +static GenDesc GenDASGN = { TOK_DIV_ASSIGN, GEN_NOPUSH, g_div }; +static GenDesc GenMOASGN = { TOK_MOD_ASSIGN, GEN_NOPUSH, g_mod }; +static GenDesc GenSLASGN = { TOK_SHL_ASSIGN, GEN_NOPUSH, g_asl }; +static GenDesc GenSRASGN = { TOK_SHR_ASSIGN, GEN_NOPUSH, g_asr }; +static GenDesc GenAASGN = { TOK_AND_ASSIGN, GEN_NOPUSH, g_and }; +static GenDesc GenXOASGN = { TOK_XOR_ASSIGN, GEN_NOPUSH, g_xor }; +static GenDesc GenOASGN = { TOK_OR_ASSIGN, GEN_NOPUSH, g_or }; /*****************************************************************************/ -/* Helper functions */ +/* Helper functions */ /*****************************************************************************/ -static unsigned GlobalModeFlags (unsigned Flags) -/* Return the addressing mode flags for the variable with the given flags */ +static unsigned GlobalModeFlags (const ExprDesc* Expr) +/* Return the addressing mode flags for the given expression */ { - switch (Flags & E_MASK_LOC) { + switch (ED_GetLoc (Expr)) { + case E_LOC_ABS: return CF_ABSOLUTE; case E_LOC_GLOBAL: return CF_EXTERNAL; case E_LOC_STATIC: return CF_STATIC; case E_LOC_REGISTER: return CF_REGVAR; + case E_LOC_STACK: return CF_NONE; + case E_LOC_PRIMARY: return CF_NONE; + case E_LOC_EXPR: return CF_NONE; + case E_LOC_LITERAL: return CF_STATIC; /* Same as static */ default: - Internal ("GlobalModeFlags: Invalid flags value: %u", Flags); + Internal ("GlobalModeFlags: Invalid location flags value: 0x%04X", Expr->Flags); /* NOTREACHED */ return 0; } @@ -91,7 +99,7 @@ static unsigned GlobalModeFlags (unsigned Flags) -void ExprWithCheck (void (*Func) (ExprDesc*), ExprDesc *Expr) +void ExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr) /* Call an expression function with checks. */ { /* Remember the stack pointer */ @@ -100,41 +108,56 @@ void ExprWithCheck (void (*Func) (ExprDesc*), ExprDesc *Expr) /* Call the expression function */ (*Func) (Expr); - /* Do some checks if code generation is still constistent */ + /* Do some checks to see if code generation is still consistent */ if (StackPtr != OldSP) { - if (Debug) { - fprintf (stderr, - "Code generation messed up!\n" - "StackPtr is %d, should be %d", - StackPtr, OldSP); - } else { - Internal ("StackPtr is %d, should be %d\n", StackPtr, OldSP); - } + if (Debug) { + Error ("Code generation messed up: " + "StackPtr is %d, should be %d", + StackPtr, OldSP); + } else { + Internal ("Code generation messed up: " + "StackPtr is %d, should be %d", + StackPtr, OldSP); + } } } -static type* promoteint (type* lhst, type* rhst) +void MarkedExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr) +/* Call an expression function with checks and record start and end of the +** generated code. +*/ +{ + CodeMark Start, End; + GetCodePos (&Start); + ExprWithCheck (Func, Expr); + GetCodePos (&End); + ED_SetCodeRange (Expr, &Start, &End); +} + + + +static Type* promoteint (Type* lhst, Type* rhst) /* In an expression with two ints, return the type of the result */ { /* Rules for integer types: - * - If one of the values is a long, the result is long. - * - If one of the values is unsigned, the result is also unsigned. - * - Otherwise the result is an int. - */ + ** - If one of the values is a long, the result is long. + ** - If one of the values is unsigned, the result is also unsigned. + ** - Otherwise the result is an int. + */ if (IsTypeLong (lhst) || IsTypeLong (rhst)) { - if (IsSignUnsigned (lhst) || IsSignUnsigned (rhst)) { - return type_ulong; - } else { - return type_long; - } + if (IsSignUnsigned (lhst) || IsSignUnsigned (rhst)) { + return type_ulong; + } else { + return type_long; + } } else { - if (IsSignUnsigned (lhst) || IsSignUnsigned (rhst)) { - return type_uint; - } else { - return type_int; - } + if (IsSignUnsigned (lhst) || IsSignUnsigned (rhst)) { + return type_uint; + } else { + return type_int; + } } } @@ -142,33 +165,33 @@ static type* promoteint (type* lhst, type* rhst) static unsigned typeadjust (ExprDesc* lhs, ExprDesc* rhs, int NoPush) /* Adjust the two values for a binary operation. lhs is expected on stack or - * to be constant, rhs is expected to be in the primary register or constant. - * The function will put the type of the result into lhs and return the - * code generator flags for the operation. - * If NoPush is given, it is assumed that the operation does not expect the lhs - * to be on stack, and that lhs is in a register instead. - * Beware: The function does only accept int types. - */ +** to be constant, rhs is expected to be in the primary register or constant. +** The function will put the type of the result into lhs and return the +** code generator flags for the operation. +** If NoPush is given, it is assumed that the operation does not expect the lhs +** to be on stack, and that lhs is in a register instead. +** Beware: The function does only accept int types. +*/ { unsigned ltype, rtype; unsigned flags; /* Get the type strings */ - type* lhst = lhs->Type; - type* rhst = rhs->Type; + Type* lhst = lhs->Type; + Type* rhst = rhs->Type; /* Generate type adjustment code if needed */ ltype = TypeOf (lhst); if (ED_IsLocAbs (lhs)) { - ltype |= CF_CONST; + ltype |= CF_CONST; } if (NoPush) { - /* Value is in primary register*/ - ltype |= CF_REG; + /* Value is in primary register*/ + ltype |= CF_REG; } rtype = TypeOf (rhst); if (ED_IsLocAbs (rhs)) { - rtype |= CF_CONST; + rtype |= CF_CONST; } flags = g_typeadjust (ltype, rtype); @@ -181,58 +204,14 @@ static unsigned typeadjust (ExprDesc* lhs, ExprDesc* rhs, int NoPush) -static int kcalc (token_t tok, long val1, long val2) -/* Calculate an operation with left and right operand constant. */ -{ - switch (tok) { - case TOK_EQ: - return (val1 == val2); - case TOK_NE: - return (val1 != val2); - case TOK_LT: - return (val1 < val2); - case TOK_LE: - return (val1 <= val2); - case TOK_GE: - return (val1 >= val2); - case TOK_GT: - return (val1 > val2); - case TOK_OR: - return (val1 | val2); - case TOK_XOR: - return (val1 ^ val2); - case TOK_AND: - return (val1 & val2); - case TOK_STAR: - return (val1 * val2); - case TOK_DIV: - if (val2 == 0) { - Error ("Division by zero"); - return 0x7FFFFFFF; - } - return (val1 / val2); - case TOK_MOD: - if (val2 == 0) { - Error ("Modulo operation with zero"); - return 0; - } - return (val1 % val2); - default: - Internal ("kcalc: got token 0x%X\n", tok); - return 0; - } -} - - - static const GenDesc* FindGen (token_t Tok, const GenDesc* Table) /* Find a token in a generator table */ { while (Table->Tok != TOK_INVALID) { - if (Table->Tok == Tok) { - return Table; - } - ++Table; + if (Table->Tok == Tok) { + return Table; + } + ++Table; } return 0; } @@ -241,163 +220,175 @@ static const GenDesc* FindGen (token_t Tok, const GenDesc* Table) static int TypeSpecAhead (void) /* Return true if some sort of type is waiting (helper for cast and sizeof() - * in hie10). - */ +** in hie10). +*/ { SymEntry* Entry; /* There's a type waiting if: - * - * We have an opening paren, and - * a. the next token is a type, or - * b. the next token is a type qualifier, or - * c. the next token is a typedef'd type - */ + ** + ** We have an opening paren, and + ** a. the next token is a type, or + ** b. the next token is a type qualifier, or + ** c. the next token is a typedef'd type + */ return CurTok.Tok == TOK_LPAREN && ( - TokIsType (&NextTok) || + TokIsType (&NextTok) || TokIsTypeQual (&NextTok) || - (NextTok.Tok == TOK_IDENT && - (Entry = FindSym (NextTok.Ident)) != 0 && - SymIsTypeDef (Entry))); + (NextTok.Tok == TOK_IDENT && + (Entry = FindSym (NextTok.Ident)) != 0 && + SymIsTypeDef (Entry))); } void PushAddr (const ExprDesc* Expr) /* If the expression contains an address that was somehow evaluated, - * push this address on the stack. This is a helper function for all - * sorts of implicit or explicit assignment functions where the lvalue - * must be saved if it's not constant, before evaluating the rhs. - */ +** push this address on the stack. This is a helper function for all +** sorts of implicit or explicit assignment functions where the lvalue +** must be saved if it's not constant, before evaluating the rhs. +*/ { /* Get the address on stack if needed */ if (ED_IsLocExpr (Expr)) { - /* Push the address (always a pointer) */ - g_push (CF_PTR, 0); + /* Push the address (always a pointer) */ + g_push (CF_PTR, 0); + } +} + + + +static void WarnConstCompareResult (void) +/* If the result of a comparison is constant, this is suspicious when not in +** preprocessor mode. +*/ +{ + if (!Preprocessing && IS_Get (&WarnConstComparison) != 0) { + Warning ("Result of comparison is constant"); } } /*****************************************************************************/ -/* code */ +/* code */ /*****************************************************************************/ -static unsigned FunctionParamList (FuncDesc* Func) +static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall) /* Parse a function parameter list and pass the parameters to the called - * function. Depending on several criteria this may be done by just pushing - * each parameter separately, or creating the parameter frame once and then - * storing into this frame. - * The function returns the size of the parameters pushed. - */ +** function. Depending on several criteria this may be done by just pushing +** each parameter separately, or creating the parameter frame once and then +** storing into this frame. +** The function returns the size of the parameters pushed. +*/ { ExprDesc Expr; /* Initialize variables */ - SymEntry* Param = 0; /* Keep gcc silent */ - unsigned ParamSize = 0; /* Size of parameters pushed */ - unsigned ParamCount = 0; /* Number of parameters pushed */ - unsigned FrameSize = 0; /* Size of parameter frame */ - unsigned FrameParams = 0; /* Number of params in frame */ - int FrameOffs = 0; /* Offset into parameter frame */ - int Ellipsis = 0; /* Function is variadic */ + SymEntry* Param = 0; /* Keep gcc silent */ + unsigned ParamSize = 0; /* Size of parameters pushed */ + unsigned ParamCount = 0; /* Number of parameters pushed */ + unsigned FrameSize = 0; /* Size of parameter frame */ + unsigned FrameParams = 0; /* Number of params in frame */ + int FrameOffs = 0; /* Offset into parameter frame */ + int Ellipsis = 0; /* Function is variadic */ /* As an optimization, we may allocate the complete parameter frame at - * once instead of pushing each parameter as it comes. We may do that, - * if... - * - * - optimizations that increase code size are enabled (allocating the - * stack frame at once gives usually larger code). - * - we have more than one parameter to push (don't count the last param - * for __fastcall__ functions). - * - * The FrameSize variable will contain a value > 0 if storing into a frame - * (instead of pushing) is enabled. - * - */ + ** once instead of pushing each parameter as it comes. We may do that, + ** if... + ** + ** - optimizations that increase code size are enabled (allocating the + ** stack frame at once gives usually larger code). + ** - we have more than one parameter to push (don't count the last param + ** for __fastcall__ functions). + ** + ** The FrameSize variable will contain a value > 0 if storing into a frame + ** (instead of pushing) is enabled. + ** + */ if (IS_Get (&CodeSizeFactor) >= 200) { - /* Calculate the number and size of the parameters */ - FrameParams = Func->ParamCount; - FrameSize = Func->ParamSize; - if (FrameParams > 0 && (Func->Flags & FD_FASTCALL) != 0) { - /* Last parameter is not pushed */ - FrameSize -= CheckedSizeOf (Func->LastParam->Type); - --FrameParams; - } - - /* Do we have more than one parameter in the frame? */ - if (FrameParams > 1) { - /* Okeydokey, setup the frame */ - FrameOffs = StackPtr; - g_space (FrameSize); - StackPtr -= FrameSize; - } else { - /* Don't use a preallocated frame */ - FrameSize = 0; - } + /* Calculate the number and size of the parameters */ + FrameParams = Func->ParamCount; + FrameSize = Func->ParamSize; + if (FrameParams > 0 && IsFastcall) { + /* Last parameter is not pushed */ + FrameSize -= CheckedSizeOf (Func->LastParam->Type); + --FrameParams; + } + + /* Do we have more than one parameter in the frame? */ + if (FrameParams > 1) { + /* Okeydokey, setup the frame */ + FrameOffs = StackPtr; + g_space (FrameSize); + StackPtr -= FrameSize; + } else { + /* Don't use a preallocated frame */ + FrameSize = 0; + } } /* Parse the actual parameter list */ while (CurTok.Tok != TOK_RPAREN) { - unsigned Flags; - - /* Count arguments */ - ++ParamCount; - - /* Fetch the pointer to the next argument, check for too many args */ - if (ParamCount <= Func->ParamCount) { - /* Beware: If there are parameters with identical names, they - * cannot go into the same symbol table, which means that in this - * case of errorneous input, the number of nodes in the symbol - * table and ParamCount are NOT equal. We have to handle this case - * below to avoid segmentation violations. Since we know that this - * problem can only occur if there is more than one parameter, - * we will just use the last one. - */ - if (ParamCount == 1) { - /* First argument */ - Param = Func->SymTab->SymHead; - } else if (Param->NextSym != 0) { - /* Next argument */ - Param = Param->NextSym; - CHECK ((Param->Flags & SC_PARAM) != 0); - } - } else if (!Ellipsis) { - /* Too many arguments. Do we have an open param list? */ - if ((Func->Flags & FD_VARIADIC) == 0) { - /* End of param list reached, no ellipsis */ - Error ("Too many arguments in function call"); - } - /* Assume an ellipsis even in case of errors to avoid an error - * message for each other argument. - */ - Ellipsis = 1; - } + unsigned Flags; + + /* Count arguments */ + ++ParamCount; + + /* Fetch the pointer to the next argument, check for too many args */ + if (ParamCount <= Func->ParamCount) { + /* Beware: If there are parameters with identical names, they + ** cannot go into the same symbol table, which means that in this + ** case of errorneous input, the number of nodes in the symbol + ** table and ParamCount are NOT equal. We have to handle this case + ** below to avoid segmentation violations. Since we know that this + ** problem can only occur if there is more than one parameter, + ** we will just use the last one. + */ + if (ParamCount == 1) { + /* First argument */ + Param = Func->SymTab->SymHead; + } else if (Param->NextSym != 0) { + /* Next argument */ + Param = Param->NextSym; + CHECK ((Param->Flags & SC_PARAM) != 0); + } + } else if (!Ellipsis) { + /* Too many arguments. Do we have an open param list? */ + if ((Func->Flags & FD_VARIADIC) == 0) { + /* End of param list reached, no ellipsis */ + Error ("Too many arguments in function call"); + } + /* Assume an ellipsis even in case of errors to avoid an error + ** message for each other argument. + */ + Ellipsis = 1; + } /* Evaluate the parameter expression */ hie1 (&Expr); - /* If we don't have an argument spec, accept anything, otherwise - * convert the actual argument to the type needed. - */ + /* If we don't have an argument spec, accept anything, otherwise + ** convert the actual argument to the type needed. + */ Flags = CF_NONE; - if (!Ellipsis) { + if (!Ellipsis) { - /* Convert the argument to the parameter type if needed */ + /* Convert the argument to the parameter type if needed */ TypeConversion (&Expr, Param->Type); - /* If we have a prototype, chars may be pushed as chars */ - Flags |= CF_FORCECHAR; + /* If we have a prototype, chars may be pushed as chars */ + Flags |= CF_FORCECHAR; - } else { + } else { /* No prototype available. Convert array to "pointer to first - * element", and function to "pointer to function". - */ + ** element", and function to "pointer to function". + */ Expr.Type = PtrConversion (Expr.Type); } @@ -405,56 +396,56 @@ static unsigned FunctionParamList (FuncDesc* Func) /* Load the value into the primary if it is not already there */ LoadExpr (Flags, &Expr); - /* Use the type of the argument for the push */ - Flags |= TypeOf (Expr.Type); - - /* If this is a fastcall function, don't push the last argument */ - if (ParamCount != Func->ParamCount || (Func->Flags & FD_FASTCALL) == 0) { - unsigned ArgSize = sizeofarg (Flags); - if (FrameSize > 0) { - /* We have the space already allocated, store in the frame. - * Because of invalid type conversions (that have produced an - * error before), we can end up here with a non aligned stack - * frame. Since no output will be generated anyway, handle - * these cases gracefully instead of doing a CHECK. - */ + /* Use the type of the argument for the push */ + Flags |= TypeOf (Expr.Type); + + /* If this is a fastcall function, don't push the last argument */ + if (ParamCount != Func->ParamCount || !IsFastcall) { + unsigned ArgSize = sizeofarg (Flags); + if (FrameSize > 0) { + /* We have the space already allocated, store in the frame. + ** Because of invalid type conversions (that have produced an + ** error before), we can end up here with a non-aligned stack + ** frame. Since no output will be generated anyway, handle + ** these cases gracefully instead of doing a CHECK. + */ if (FrameSize >= ArgSize) { FrameSize -= ArgSize; } else { FrameSize = 0; } - FrameOffs -= ArgSize; - /* Store */ - g_putlocal (Flags | CF_NOKEEP, FrameOffs, Expr.IVal); - } else { - /* Push the argument */ - g_push (Flags, Expr.IVal); - } + FrameOffs -= ArgSize; + /* Store */ + g_putlocal (Flags | CF_NOKEEP, FrameOffs, Expr.IVal); + } else { + /* Push the argument */ + g_push (Flags, Expr.IVal); + } - /* Calculate total parameter size */ - ParamSize += ArgSize; - } + /* Calculate total parameter size */ + ParamSize += ArgSize; + } - /* Check for end of argument list */ - if (CurTok.Tok != TOK_COMMA) { - break; - } - NextToken (); + /* Check for end of argument list */ + if (CurTok.Tok != TOK_COMMA) { + break; + } + NextToken (); } /* Check if we had enough parameters */ if (ParamCount < Func->ParamCount) { - Error ("Too few arguments in function call"); + Error ("Too few arguments in function call"); } /* The function returns the size of all parameters pushed onto the stack. - * However, if there are parameters missing (which is an error and was - * flagged by the compiler) AND a stack frame was preallocated above, - * we would loose track of the stackpointer and generate an internal error - * later. So we correct the value by the parameters that should have been - * pushed to avoid an internal compiler error. Since an error was - * generated before, no code will be output anyway. - */ + ** However, if there are parameters missing (which is an error and was + ** flagged by the compiler) AND a stack frame was preallocated above, + ** we would loose track of the stackpointer and generate an internal error + ** later. So we correct the value by the parameters that should have been + ** pushed to avoid an internal compiler error. Since an error was + ** generated before, no code will be output anyway. + */ return ParamSize + FrameSize; } @@ -463,12 +454,12 @@ static unsigned FunctionParamList (FuncDesc* Func) static void FunctionCall (ExprDesc* Expr) /* Perform a function call. */ { - FuncDesc* Func; /* Function descriptor */ + FuncDesc* Func; /* Function descriptor */ int IsFuncPtr; /* Flag */ - unsigned ParamSize; /* Number of parameter bytes */ - CodeMark Mark; + unsigned ParamSize; /* Number of parameter bytes */ + CodeMark Mark; int PtrOffs = 0; /* Offset of function pointer on stack */ - int IsFastCall = 0; /* True if it's a fast call function */ + int IsFastcall = 0; /* True if it's a fast-call function */ int PtrOnStack = 0; /* True if a pointer copy is on stack */ /* Skip the left paren */ @@ -480,47 +471,63 @@ static void FunctionCall (ExprDesc* Expr) /* Handle function pointers transparently */ IsFuncPtr = IsTypeFuncPtr (Expr->Type); if (IsFuncPtr) { + /* Check whether it's a fastcall function that has parameters */ + IsFastcall = (Func->Flags & FD_VARIADIC) == 0 && Func->ParamCount > 0 && + (AutoCDecl ? + IsQualFastcall (Expr->Type + 1) : + !IsQualCDecl (Expr->Type + 1)); + + /* Things may be difficult, depending on where the function pointer + ** resides. If the function pointer is an expression of some sort + ** (not a local or global variable), we have to evaluate this + ** expression now and save the result for later. Since calls to + ** function pointers may be nested, we must save it onto the stack. + ** For fastcall functions we do also need to place a copy of the + ** pointer on stack, since we cannot use a/x. + */ + PtrOnStack = IsFastcall || !ED_IsConst (Expr); + if (PtrOnStack) { + + /* Not a global or local variable, or a fastcall function. Load + ** the pointer into the primary and mark it as an expression. + */ + LoadExpr (CF_NONE, Expr); + ED_MakeRValExpr (Expr); + + /* Remember the code position */ + GetCodePos (&Mark); + + /* Push the pointer onto the stack and remember the offset */ + g_push (CF_PTR, 0); + PtrOffs = StackPtr; + } - /* Check wether it's a fastcall function that has parameters */ - IsFastCall = IsFastCallFunc (Expr->Type + 1) && (Func->ParamCount > 0); - - /* Things may be difficult, depending on where the function pointer - * resides. If the function pointer is an expression of some sort - * (not a local or global variable), we have to evaluate this - * expression now and save the result for later. Since calls to - * function pointers may be nested, we must save it onto the stack. - * For fastcall functions we do also need to place a copy of the - * pointer on stack, since we cannot use a/x. - */ - PtrOnStack = IsFastCall || !ED_IsConst (Expr); - if (PtrOnStack) { - - /* Not a global or local variable, or a fastcall function. Load - * the pointer into the primary and mark it as an expression. - */ - LoadExpr (CF_NONE, Expr); - ED_MakeRValExpr (Expr); - - /* Remember the code position */ - GetCodePos (&Mark); - - /* Push the pointer onto the stack and remember the offset */ - g_push (CF_PTR, 0); - PtrOffs = StackPtr; - } - - /* Check for known standard functions and inline them */ - } else if (Expr->Name != 0) { - int StdFunc = FindStdFunc ((const char*) Expr->Name); - if (StdFunc >= 0) { - /* Inline this function */ - HandleStdFunc (StdFunc, Func, Expr); - return; + } else { + /* Check function attributes */ + if (Expr->Sym && SymHasAttr (Expr->Sym, atNoReturn)) { + /* For now, handle as if a return statement was encountered */ + F_ReturnFound (CurrentFunc); } + + /* Check for known standard functions and inline them */ + if (Expr->Name != 0) { + int StdFunc = FindStdFunc ((const char*) Expr->Name); + if (StdFunc >= 0) { + /* Inline this function */ + HandleStdFunc (StdFunc, Func, Expr); + return; + } + } + + /* If we didn't inline the function, get fastcall info */ + IsFastcall = (Func->Flags & FD_VARIADIC) == 0 && + (AutoCDecl ? + IsQualFastcall (Expr->Type) : + !IsQualCDecl (Expr->Type)); } /* Parse the parameter list */ - ParamSize = FunctionParamList (Func); + ParamSize = FunctionParamList (Func, IsFastcall); /* We need the closing paren here */ ConsumeRParen (); @@ -528,55 +535,55 @@ static void FunctionCall (ExprDesc* Expr) /* Special handling for function pointers */ if (IsFuncPtr) { - /* If the function is not a fastcall function, load the pointer to - * the function into the primary. - */ - if (!IsFastCall) { - - /* Not a fastcall function - we may use the primary */ - if (PtrOnStack) { - /* If we have no parameters, the pointer is still in the - * primary. Remove the code to push it and correct the - * stack pointer. - */ - if (ParamSize == 0) { - RemoveCode (&Mark); - PtrOnStack = 0; - } else { - /* Load from the saved copy */ - g_getlocal (CF_PTR, PtrOffs); - } - } else { - /* Load from original location */ - LoadExpr (CF_NONE, Expr); - } - - /* Call the function */ - g_callind (TypeOf (Expr->Type+1), ParamSize, PtrOffs); - - } else { - - /* Fastcall function. We cannot use the primary for the function - * pointer and must therefore use an offset to the stack location. - * Since fastcall functions may never be variadic, we can use the - * index register for this purpose. - */ - g_callind (CF_LOCAL, ParamSize, PtrOffs); - } - - /* If we have a pointer on stack, remove it */ - if (PtrOnStack) { - g_space (- (int) sizeofarg (CF_PTR)); - pop (CF_PTR); - } - - /* Skip T_PTR */ - ++Expr->Type; + /* If the function is not a fastcall function, load the pointer to + ** the function into the primary. + */ + if (!IsFastcall) { + + /* Not a fastcall function - we may use the primary */ + if (PtrOnStack) { + /* If we have no parameters, the pointer is still in the + ** primary. Remove the code to push it and correct the + ** stack pointer. + */ + if (ParamSize == 0) { + RemoveCode (&Mark); + PtrOnStack = 0; + } else { + /* Load from the saved copy */ + g_getlocal (CF_PTR, PtrOffs); + } + } else { + /* Load from original location */ + LoadExpr (CF_NONE, Expr); + } + + /* Call the function */ + g_callind (TypeOf (Expr->Type+1), ParamSize, PtrOffs); + + } else { + + /* Fastcall function. We cannot use the primary for the function + ** pointer and must therefore use an offset to the stack location. + ** Since fastcall functions may never be variadic, we can use the + ** index register for this purpose. + */ + g_callind (CF_LOCAL, ParamSize, PtrOffs); + } + + /* If we have a pointer on stack, remove it */ + if (PtrOnStack) { + g_drop (SIZEOF_PTR); + pop (CF_PTR); + } + + /* Skip T_PTR */ + ++Expr->Type; } else { - /* Normal function */ - g_call (TypeOf (Expr->Type), (const char*) Expr->Name, ParamSize); + /* Normal function */ + g_call (TypeOf (Expr->Type), (const char*) Expr->Name, ParamSize); } @@ -597,11 +604,11 @@ static void Primary (ExprDesc* E) /* Character and integer constants. */ if (CurTok.Tok == TOK_ICONST || CurTok.Tok == TOK_CCONST) { - E->IVal = CurTok.IVal; - E->Flags = E_LOC_ABS | E_RTYPE_RVAL; - E->Type = CurTok.Type; - NextToken (); - return; + E->IVal = CurTok.IVal; + E->Flags = E_LOC_ABS | E_RTYPE_RVAL; + E->Type = CurTok.Type; + NextToken (); + return; } /* Floating point constant */ @@ -614,31 +621,32 @@ static void Primary (ExprDesc* E) } /* Process parenthesized subexpression by calling the whole parser - * recursively. - */ + ** recursively. + */ if (CurTok.Tok == TOK_LPAREN) { - NextToken (); + NextToken (); hie0 (E); - ConsumeRParen (); - return; + ConsumeRParen (); + return; } /* If we run into an identifier in preprocessing mode, we assume that this - * is an undefined macro and replace it by a constant value of zero. - */ + ** is an undefined macro and replace it by a constant value of zero. + */ if (Preprocessing && CurTok.Tok == TOK_IDENT) { + NextToken (); ED_MakeConstAbsInt (E, 0); return; } /* All others may only be used if the expression evaluation is not called - * recursively by the preprocessor. - */ + ** recursively by the preprocessor. + */ if (Preprocessing) { - /* Illegal expression in PP mode */ - Error ("Preprocessor expression expected"); - ED_MakeConstAbsInt (E, 1); - return; + /* Illegal expression in PP mode */ + Error ("Preprocessor expression expected"); + ED_MakeConstAbsInt (E, 1); + return; } switch (CurTok.Tok) { @@ -681,9 +689,9 @@ static void Primary (ExprDesc* E) E->Name = (unsigned long) Sym->Name; } else if ((Sym->Flags & SC_AUTO) == SC_AUTO) { /* Local variable. If this is a parameter for a variadic - * function, we have to add some address calculations, and the - * address is not const. - */ + ** function, we have to add some address calculations, and the + ** address is not const. + */ if ((Sym->Flags & SC_PARAM) == SC_PARAM && F_IsVariadic (CurrentFunc)) { /* Variadic parameter */ g_leavariadic (Sym->V.Offs - F_GetParamSize (CurrentFunc)); @@ -713,11 +721,11 @@ static void Primary (ExprDesc* E) } /* We've made all variables lvalues above. However, this is - * not always correct: An array is actually the address of its - * first element, which is a rvalue, and a function is a - * rvalue, too, because we cannot store anything in a function. - * So fix the flags depending on the type. - */ + ** not always correct: An array is actually the address of its + ** first element, which is a rvalue, and a function is a + ** rvalue, too, because we cannot store anything in a function. + ** So fix the flags depending on the type. + */ if (IsTypeArray (E->Type) || IsTypeFunc (E->Type)) { ED_MakeRVal (E); } @@ -731,11 +739,17 @@ static void Primary (ExprDesc* E) /* IDENT is either an auto-declared function or an undefined variable. */ if (CurTok.Tok == TOK_LPAREN) { - /* Declare a function returning int. For that purpose, prepare a - * function signature for a function having an empty param list - * and returning int. - */ - Warning ("Function call without a prototype"); + /* C99 doesn't allow calls to undefined functions, so + ** generate an error and otherwise a warning. Declare a + ** function returning int. For that purpose, prepare a + ** function signature for a function having an empty param + ** list and returning int. + */ + if (IS_Get (&Standard) >= STD_C99) { + Error ("Call to undefined function `%s'", Ident); + } else { + Warning ("Call to undefined function `%s'", Ident); + } Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_EXTERN | SC_REF | SC_FUNC); E->Type = Sym->Type; E->Flags = E_LOC_GLOBAL | E_RTYPE_RVAL; @@ -752,11 +766,13 @@ static void Primary (ExprDesc* E) break; case TOK_SCONST: + case TOK_WCSCONST: /* String literal */ - E->Type = GetCharArrayType (GetLiteralPoolOffs () - CurTok.IVal); + E->LVal = UseLiteral (CurTok.SVal); + E->Type = GetCharArrayType (GetLiteralSize (CurTok.SVal)); E->Flags = E_LOC_LITERAL | E_RTYPE_RVAL; - E->IVal = CurTok.IVal; - E->Name = LiteralPoolLabel; + E->IVal = 0; + E->Name = GetLiteralLabel (CurTok.SVal); NextToken (); break; @@ -789,8 +805,11 @@ static void Primary (ExprDesc* E) break; default: - /* Illegal primary. */ + /* Illegal primary. Be sure to skip the token to avoid endless + ** error loops. + */ Error ("Expression expected"); + NextToken (); ED_MakeConstAbsInt (E, 1); break; } @@ -799,14 +818,15 @@ static void Primary (ExprDesc* E) static void ArrayRef (ExprDesc* Expr) -/* Handle an array reference */ +/* Handle an array reference. This function needs a rewrite. */ { int ConstBaseAddr; - ExprDesc SubScript; + ExprDesc Subscript; CodeMark Mark1; CodeMark Mark2; - type* ElementType; - type* tptr1; + TypeCode Qualifiers; + Type* ElementType; + Type* tptr1; /* Skip the bracket */ @@ -816,227 +836,251 @@ static void ArrayRef (ExprDesc* Expr) tptr1 = Expr->Type; /* We can apply a special treatment for arrays that have a const base - * address. This is true for most arrays and will produce a lot better - * code. Check if this is a const base address. - */ - ConstBaseAddr = (ED_IsLocConst (Expr) || ED_IsLocStack (Expr)); + ** address. This is true for most arrays and will produce a lot better + ** code. Check if this is a const base address. + */ + ConstBaseAddr = ED_IsRVal (Expr) && + (ED_IsLocConst (Expr) || ED_IsLocStack (Expr)); /* If we have a constant base, we delay the address fetch */ GetCodePos (&Mark1); if (!ConstBaseAddr) { - /* Get a pointer to the array into the primary */ - LoadExpr (CF_NONE, Expr); + /* Get a pointer to the array into the primary */ + LoadExpr (CF_NONE, Expr); - /* Get the array pointer on stack. Do not push more than 16 - * bit, even if this value is greater, since we cannot handle - * other than 16bit stuff when doing indexing. - */ - GetCodePos (&Mark2); - g_push (CF_PTR, 0); + /* Get the array pointer on stack. Do not push more than 16 + ** bit, even if this value is greater, since we cannot handle + ** other than 16bit stuff when doing indexing. + */ + GetCodePos (&Mark2); + g_push (CF_PTR, 0); } /* TOS now contains ptr to array elements. Get the subscript. */ - ExprWithCheck (hie0, &SubScript); + MarkedExprWithCheck (hie0, &Subscript); /* Check the types of array and subscript. We can either have a - * pointer/array to the left, in which case the subscript must be of an - * integer type, or we have an integer to the left, in which case the - * subscript must be a pointer/array. - * Since we do the necessary checking here, we can rely later on the - * correct types. - */ + ** pointer/array to the left, in which case the subscript must be of an + ** integer type, or we have an integer to the left, in which case the + ** subscript must be a pointer/array. + ** Since we do the necessary checking here, we can rely later on the + ** correct types. + */ + Qualifiers = T_QUAL_NONE; if (IsClassPtr (Expr->Type)) { - if (!IsClassInt (SubScript.Type)) { + if (!IsClassInt (Subscript.Type)) { Error ("Array subscript is not an integer"); /* To avoid any compiler errors, make the expression a valid int */ - ED_MakeConstAbsInt (&SubScript, 0); + ED_MakeConstAbsInt (&Subscript, 0); + } + if (IsTypeArray (Expr->Type)) { + Qualifiers = GetQualifier (Expr->Type); } ElementType = Indirect (Expr->Type); } else if (IsClassInt (Expr->Type)) { - if (!IsClassPtr (SubScript.Type)) { + if (!IsClassPtr (Subscript.Type)) { Error ("Subscripted value is neither array nor pointer"); /* To avoid compiler errors, make the subscript a char[] at - * address 0. - */ - ED_MakeConstAbs (&SubScript, 0, GetCharArrayType (1)); + ** address 0. + */ + ED_MakeConstAbs (&Subscript, 0, GetCharArrayType (1)); + } else if (IsTypeArray (Subscript.Type)) { + Qualifiers = GetQualifier (Subscript.Type); } - ElementType = Indirect (SubScript.Type); + ElementType = Indirect (Subscript.Type); } else { Error ("Cannot subscript"); /* To avoid compiler errors, fake both the array and the subscript, so - * we can just proceed. - */ + ** we can just proceed. + */ ED_MakeConstAbs (Expr, 0, GetCharArrayType (1)); - ED_MakeConstAbsInt (&SubScript, 0); + ED_MakeConstAbsInt (&Subscript, 0); ElementType = Indirect (Expr->Type); } + /* The element type has the combined qualifiers from itself and the array, + ** it is a member of (if any). + */ + if (GetQualifier (ElementType) != (GetQualifier (ElementType) | Qualifiers)) { + ElementType = TypeDup (ElementType); + ElementType->C |= Qualifiers; + } + + /* If the subscript is a bit-field, load it and make it an rvalue */ + if (ED_IsBitField (&Subscript)) { + LoadExpr (CF_NONE, &Subscript); + ED_MakeRValExpr (&Subscript); + } + /* Check if the subscript is constant absolute value */ - if (ED_IsConstAbs (&SubScript)) { - - /* The array subscript is a numeric constant. If we had pushed the - * array base address onto the stack before, we can remove this value, - * since we can generate expression+offset. - */ - if (!ConstBaseAddr) { - RemoveCode (&Mark2); - } else { - /* Get an array pointer into the primary */ - LoadExpr (CF_NONE, Expr); - } - - if (IsClassPtr (Expr->Type)) { - - /* Lhs is pointer/array. Scale the subscript value according to - * the element size. - */ - SubScript.IVal *= CheckedSizeOf (ElementType); + if (ED_IsConstAbs (&Subscript) && ED_CodeRangeIsEmpty (&Subscript)) { + + /* The array subscript is a numeric constant. If we had pushed the + ** array base address onto the stack before, we can remove this value, + ** since we can generate expression+offset. + */ + if (!ConstBaseAddr) { + RemoveCode (&Mark2); + } else { + /* Get an array pointer into the primary */ + LoadExpr (CF_NONE, Expr); + } + + if (IsClassPtr (Expr->Type)) { + + /* Lhs is pointer/array. Scale the subscript value according to + ** the element size. + */ + Subscript.IVal *= CheckedSizeOf (ElementType); /* Remove the address load code */ RemoveCode (&Mark1); /* In case of an array, we can adjust the offset of the expression - * already in Expr. If the base address was a constant, we can even - * remove the code that loaded the address into the primary. - */ + ** already in Expr. If the base address was a constant, we can even + ** remove the code that loaded the address into the primary. + */ if (IsTypeArray (Expr->Type)) { /* Adjust the offset */ - Expr->IVal += SubScript.IVal; + Expr->IVal += Subscript.IVal; } else { /* It's a pointer, so we do have to load it into the primary - * first (if it's not already there). - */ - if (ConstBaseAddr) { + ** first (if it's not already there). + */ + if (ConstBaseAddr || ED_IsLVal (Expr)) { LoadExpr (CF_NONE, Expr); ED_MakeRValExpr (Expr); } /* Use the offset */ - Expr->IVal = SubScript.IVal; + Expr->IVal = Subscript.IVal; } - } else { + } else { - /* Scale the rhs value according to the element type */ - g_scale (TypeOf (tptr1), CheckedSizeOf (ElementType)); + /* Scale the rhs value according to the element type */ + g_scale (TypeOf (tptr1), CheckedSizeOf (ElementType)); /* Add the subscript. Since arrays are indexed by integers, - * we will ignore the true type of the subscript here and - * use always an int. #### Use offset but beware of LoadExpr! - */ - g_inc (CF_INT | CF_CONST, SubScript.IVal); + ** we will ignore the true type of the subscript here and + ** use always an int. #### Use offset but beware of LoadExpr! + */ + g_inc (CF_INT | CF_CONST, Subscript.IVal); - } + } } else { - /* Array subscript is not constant. Load it into the primary */ - GetCodePos (&Mark2); - LoadExpr (CF_NONE, &SubScript); + /* Array subscript is not constant. Load it into the primary */ + GetCodePos (&Mark2); + LoadExpr (CF_NONE, &Subscript); /* Do scaling */ - if (IsClassPtr (Expr->Type)) { - - /* Indexing is based on unsigneds, so we will just use the integer - * portion of the index (which is in (e)ax, so there's no further - * action required). - */ - g_scale (CF_INT, CheckedSizeOf (ElementType)); - - } else { - - /* Get the int value on top. If we come here, we're sure, both - * values are 16 bit (the first one was truncated if necessary - * and the second one is a pointer). Note: If ConstBaseAddr is - * true, we don't have a value on stack, so to "swap" both, just - * push the subscript. - */ - if (ConstBaseAddr) { - g_push (CF_INT, 0); - LoadExpr (CF_NONE, Expr); - ConstBaseAddr = 0; - } else { - g_swap (CF_INT); - } - - /* Scale it */ - g_scale (TypeOf (tptr1), CheckedSizeOf (ElementType)); - - } - - /* The offset is now in the primary register. It we didn't have a - * constant base address for the lhs, the lhs address is already - * on stack, and we must add the offset. If the base address was - * constant, we call special functions to add the address to the - * offset value. - */ - if (!ConstBaseAddr) { - - /* The array base address is on stack and the subscript is in the - * primary. Add both. - */ - g_add (CF_INT, 0); - - } else { + if (IsClassPtr (Expr->Type)) { + + /* Indexing is based on unsigneds, so we will just use the integer + ** portion of the index (which is in (e)ax, so there's no further + ** action required). + */ + g_scale (CF_INT, CheckedSizeOf (ElementType)); + + } else { + + /* Get the int value on top. If we come here, we're sure, both + ** values are 16 bit (the first one was truncated if necessary + ** and the second one is a pointer). Note: If ConstBaseAddr is + ** true, we don't have a value on stack, so to "swap" both, just + ** push the subscript. + */ + if (ConstBaseAddr) { + g_push (CF_INT, 0); + LoadExpr (CF_NONE, Expr); + ConstBaseAddr = 0; + } else { + g_swap (CF_INT); + } + + /* Scale it */ + g_scale (TypeOf (tptr1), CheckedSizeOf (ElementType)); + + } + + /* The offset is now in the primary register. It we didn't have a + ** constant base address for the lhs, the lhs address is already + ** on stack, and we must add the offset. If the base address was + ** constant, we call special functions to add the address to the + ** offset value. + */ + if (!ConstBaseAddr) { + + /* The array base address is on stack and the subscript is in the + ** primary. Add both. + */ + g_add (CF_INT, 0); + + } else { /* The subscript is in the primary, and the array base address is - * in Expr. If the subscript has itself a constant address, it is - * often a better idea to reverse again the order of the - * evaluation. This will generate better code if the subscript is - * a byte sized variable. But beware: This is only possible if the - * subscript was not scaled, that is, if this was a byte array - * or pointer. - */ - if ((ED_IsLocConst (&SubScript) || ED_IsLocStack (&SubScript)) && + ** in Expr. If the subscript has itself a constant address, it is + ** often a better idea to reverse again the order of the + ** evaluation. This will generate better code if the subscript is + ** a byte sized variable. But beware: This is only possible if the + ** subscript was not scaled, that is, if this was a byte array + ** or pointer. + */ + if ((ED_IsLocConst (&Subscript) || ED_IsLocStack (&Subscript)) && CheckedSizeOf (ElementType) == SIZEOF_CHAR) { unsigned Flags; - /* Reverse the order of evaluation */ - if (CheckedSizeOf (SubScript.Type) == SIZEOF_CHAR) { + /* Reverse the order of evaluation */ + if (CheckedSizeOf (Subscript.Type) == SIZEOF_CHAR) { Flags = CF_CHAR; } else { Flags = CF_INT; } - RemoveCode (&Mark2); - - /* Get a pointer to the array into the primary. */ - LoadExpr (CF_NONE, Expr); - - /* Add the variable */ - if (ED_IsLocStack (&SubScript)) { - g_addlocal (Flags, SubScript.IVal); - } else { - Flags |= GlobalModeFlags (SubScript.Flags); - g_addstatic (Flags, SubScript.Name, SubScript.IVal); - } - } else { - if (ED_IsLocAbs (Expr)) { - /* Constant numeric address. Just add it */ - g_inc (CF_INT, Expr->IVal); - } else if (ED_IsLocStack (Expr)) { - /* Base address is a local variable address */ - if (IsTypeArray (Expr->Type)) { - g_addaddr_local (CF_INT, Expr->IVal); - } else { - g_addlocal (CF_PTR, Expr->IVal); - } - } else { - /* Base address is a static variable address */ - unsigned Flags = CF_INT | GlobalModeFlags (Expr->Flags); - if (IsTypeArray (Expr->Type)) { - g_addaddr_static (Flags, Expr->Name, Expr->IVal); - } else { - g_addstatic (Flags, Expr->Name, Expr->IVal); - } - } - } - - - } + RemoveCode (&Mark2); + + /* Get a pointer to the array into the primary. */ + LoadExpr (CF_NONE, Expr); + + /* Add the variable */ + if (ED_IsLocStack (&Subscript)) { + g_addlocal (Flags, Subscript.IVal); + } else { + Flags |= GlobalModeFlags (&Subscript); + g_addstatic (Flags, Subscript.Name, Subscript.IVal); + } + } else { + + if (ED_IsLocAbs (Expr)) { + /* Constant numeric address. Just add it */ + g_inc (CF_INT, Expr->IVal); + } else if (ED_IsLocStack (Expr)) { + /* Base address is a local variable address */ + if (IsTypeArray (Expr->Type)) { + g_addaddr_local (CF_INT, Expr->IVal); + } else { + g_addlocal (CF_PTR, Expr->IVal); + } + } else { + /* Base address is a static variable address */ + unsigned Flags = CF_INT | GlobalModeFlags (Expr); + if (ED_IsRVal (Expr)) { + /* Add the address of the location */ + g_addaddr_static (Flags, Expr->Name, Expr->IVal); + } else { + /* Add the contents of the location */ + g_addstatic (Flags, Expr->Name, Expr->IVal); + } + } + } + + + } /* The result is an expression in the primary */ ED_MakeRValExpr (Expr); @@ -1047,10 +1091,10 @@ static void ArrayRef (ExprDesc* Expr) Expr->Type = ElementType; /* An array element is actually a variable. So the rules for variables - * with respect to the reference type apply: If it's an array, it is - * a rvalue, otherwise it's an lvalue. (A function would also be a rvalue, - * but an array cannot contain functions). - */ + ** with respect to the reference type apply: If it's an array, it is + ** a rvalue, otherwise it's an lvalue. (A function would also be a rvalue, + ** but an array cannot contain functions). + */ if (IsTypeArray (Expr->Type)) { ED_MakeRVal (Expr); } else { @@ -1068,12 +1112,15 @@ static void StructRef (ExprDesc* Expr) { ident Ident; SymEntry* Field; + Type* FinalType; + TypeCode Q; /* Skip the token and check for an identifier */ NextToken (); if (CurTok.Tok != TOK_IDENT) { - Error ("Identifier expected"); - Expr->Type = type_int; + Error ("Identifier expected"); + /* Make the expression an integer at address zero */ + ED_MakeConstAbs (Expr, 0, type_int); return; } @@ -1082,14 +1129,15 @@ static void StructRef (ExprDesc* Expr) NextToken (); Field = FindStructField (Expr->Type, Ident); if (Field == 0) { - Error ("Struct/union has no field named `%s'", Ident); - Expr->Type = type_int; - return; + Error ("Struct/union has no field named `%s'", Ident); + /* Make the expression an integer at address zero */ + ED_MakeConstAbs (Expr, 0, type_int); + return; } /* If we have a struct pointer that is an lvalue and not already in the - * primary, load it now. - */ + ** primary, load it now. + */ if (ED_IsLVal (Expr) && IsTypePtr (Expr->Type)) { /* Load into the primary */ @@ -1099,22 +1147,88 @@ static void StructRef (ExprDesc* Expr) ED_MakeLValExpr (Expr); } - /* Set the struct field offset */ - Expr->IVal += Field->V.Offs; + /* The type is the type of the field plus any qualifiers from the struct */ + if (IsClassStruct (Expr->Type)) { + Q = GetQualifier (Expr->Type); + } else { + Q = GetQualifier (Indirect (Expr->Type)); + } + if (GetQualifier (Field->Type) == (GetQualifier (Field->Type) | Q)) { + FinalType = Field->Type; + } else { + FinalType = TypeDup (Field->Type); + FinalType->C |= Q; + } - /* The type is now the type of the field */ - Expr->Type = Field->Type; + /* A struct is usually an lvalue. If not, it is a struct in the primary + ** register. + */ + if (ED_IsRVal (Expr) && ED_IsLocExpr (Expr) && !IsTypePtr (Expr->Type)) { + + unsigned Flags = 0; + unsigned BitOffs; + + /* Get the size of the type */ + unsigned Size = SizeOf (Expr->Type); + + /* Safety check */ + CHECK (Field->V.Offs + Size <= SIZEOF_LONG); + + /* The type of the operation depends on the type of the struct */ + switch (Size) { + case 1: Flags = CF_CHAR | CF_UNSIGNED | CF_CONST; break; + case 2: Flags = CF_INT | CF_UNSIGNED | CF_CONST; break; + case 3: /* FALLTHROUGH */ + case 4: Flags = CF_LONG | CF_UNSIGNED | CF_CONST; break; + default: Internal ("Invalid struct size: %u", Size); break; + } + + /* Generate a shift to get the field in the proper position in the + ** primary. For bit fields, mask the value. + */ + BitOffs = Field->V.Offs * CHAR_BITS; + if (SymIsBitField (Field)) { + BitOffs += Field->V.B.BitOffs; + g_asr (Flags, BitOffs); + /* Mask the value. This is unnecessary if the shift executed above + ** moved only zeroes into the value. + */ + if (BitOffs + Field->V.B.BitWidth != Size * CHAR_BITS) { + g_and (CF_INT | CF_UNSIGNED | CF_CONST, + (0x0001U << Field->V.B.BitWidth) - 1U); + } + } else { + g_asr (Flags, BitOffs); + } + + /* Use the new type */ + Expr->Type = FinalType; - /* An struct member is actually a variable. So the rules for variables - * with respect to the reference type apply: If it's an array, it is - * a rvalue, otherwise it's an lvalue. (A function would also be a rvalue, - * but a struct field cannot be a function). - */ - if (IsTypeArray (Expr->Type)) { - ED_MakeRVal (Expr); } else { - ED_MakeLVal (Expr); + + /* Set the struct field offset */ + Expr->IVal += Field->V.Offs; + + /* Use the new type */ + Expr->Type = FinalType; + + /* An struct member is actually a variable. So the rules for variables + ** with respect to the reference type apply: If it's an array, it is + ** a rvalue, otherwise it's an lvalue. (A function would also be a rvalue, + ** but a struct field cannot be a function). + */ + if (IsTypeArray (Expr->Type)) { + ED_MakeRVal (Expr); + } else { + ED_MakeLVal (Expr); + } + + /* Make the expression a bit field if necessary */ + if (SymIsBitField (Field)) { + ED_MakeBitField (Expr, Field->V.B.BitOffs, Field->V.B.BitWidth); + } } + } @@ -1122,6 +1236,9 @@ static void StructRef (ExprDesc* Expr) static void hie11 (ExprDesc *Expr) /* Handle compound types (structs and arrays) */ { + /* Name value used in invalid function calls */ + static const char IllegalFunc[] = "illegal_function_call"; + /* Evaluate the lhs */ Primary (Expr); @@ -1142,11 +1259,11 @@ static void hie11 (ExprDesc *Expr) /* Not a function */ Error ("Illegal function call"); /* Force the type to be a implicitly defined function, one - * returning an int and taking any number of arguments. - * Since we don't have a name, place it at absolute address - * zero. - */ + ** returning an int and taking any number of arguments. + ** Since we don't have a name, invent one. + */ ED_MakeConstAbs (Expr, 0, GetImplicitFuncType ()); + Expr->Name = (long) IllegalFunc; } /* Call the function */ FunctionCall (Expr); @@ -1179,11 +1296,11 @@ static void hie11 (ExprDesc *Expr) -void Store (ExprDesc* Expr, const type* StoreType) +void Store (ExprDesc* Expr, const Type* StoreType) /* Store the primary register into the location denoted by Expr. If StoreType - * is given, use this type when storing instead of Expr->Type. If StoreType - * is NULL, use Expr->Type instead. - */ +** is given, use this type when storing instead of Expr->Type. If StoreType +** is NULL, use Expr->Type instead. +*/ { unsigned Flags; @@ -1193,30 +1310,30 @@ void Store (ExprDesc* Expr, const type* StoreType) } /* Prepare the code generator flags */ - Flags = TypeOf (StoreType); + Flags = TypeOf (StoreType) | GlobalModeFlags (Expr); /* Do the store depending on the location */ switch (ED_GetLoc (Expr)) { case E_LOC_ABS: /* Absolute: numeric address or const */ - g_putstatic (Flags | CF_ABSOLUTE, Expr->IVal, 0); + g_putstatic (Flags, Expr->IVal, 0); break; case E_LOC_GLOBAL: /* Global variable */ - g_putstatic (Flags | CF_EXTERNAL, Expr->Name, Expr->IVal); + g_putstatic (Flags, Expr->Name, Expr->IVal); break; case E_LOC_STATIC: case E_LOC_LITERAL: /* Static variable or literal in the literal pool */ - g_putstatic (Flags | CF_STATIC, Expr->Name, Expr->IVal); + g_putstatic (Flags, Expr->Name, Expr->IVal); break; case E_LOC_REGISTER: /* Register variable */ - g_putstatic (Flags | CF_REGVAR, Expr->Name, Expr->IVal); + g_putstatic (Flags, Expr->Name, Expr->IVal); break; case E_LOC_STACK: @@ -1226,7 +1343,6 @@ void Store (ExprDesc* Expr, const type* StoreType) case E_LOC_PRIMARY: /* The primary register (value is already there) */ - /* ### Do we need a test here if the flag is set? */ break; case E_LOC_EXPR: @@ -1256,12 +1372,17 @@ static void PreInc (ExprDesc* Expr) /* Evaluate the expression and check that it is an lvalue */ hie10 (Expr); if (!ED_IsLVal (Expr)) { - Error ("Invalid lvalue"); - return; + Error ("Invalid lvalue"); + return; + } + + /* We cannot modify const values */ + if (IsQualConst (Expr->Type)) { + Error ("Increment of read-only variable"); } /* Get the data type */ - Flags = TypeOf (Expr->Type) | CF_FORCECHAR | CF_CONST; + Flags = TypeOf (Expr->Type) | GlobalModeFlags (Expr) | CF_FORCECHAR | CF_CONST; /* Get the increment value in bytes */ Val = IsTypePtr (Expr->Type)? CheckedPSizeOf (Expr->Type) : 1; @@ -1271,23 +1392,23 @@ static void PreInc (ExprDesc* Expr) case E_LOC_ABS: /* Absolute: numeric address or const */ - g_addeqstatic (Flags | CF_ABSOLUTE, Expr->IVal, 0, Val); + g_addeqstatic (Flags, Expr->IVal, 0, Val); break; case E_LOC_GLOBAL: /* Global variable */ - g_addeqstatic (Flags | CF_EXTERNAL, Expr->Name, Expr->IVal, Val); + g_addeqstatic (Flags, Expr->Name, Expr->IVal, Val); break; case E_LOC_STATIC: case E_LOC_LITERAL: /* Static variable or literal in the literal pool */ - g_addeqstatic (Flags | CF_STATIC, Expr->Name, Expr->IVal, Val); + g_addeqstatic (Flags, Expr->Name, Expr->IVal, Val); break; case E_LOC_REGISTER: /* Register variable */ - g_addeqstatic (Flags | CF_REGVAR, Expr->Name, Expr->IVal, Val); + g_addeqstatic (Flags, Expr->Name, Expr->IVal, Val); break; case E_LOC_STACK: @@ -1327,12 +1448,17 @@ static void PreDec (ExprDesc* Expr) /* Evaluate the expression and check that it is an lvalue */ hie10 (Expr); if (!ED_IsLVal (Expr)) { - Error ("Invalid lvalue"); - return; + Error ("Invalid lvalue"); + return; + } + + /* We cannot modify const values */ + if (IsQualConst (Expr->Type)) { + Error ("Decrement of read-only variable"); } /* Get the data type */ - Flags = TypeOf (Expr->Type) | CF_FORCECHAR | CF_CONST; + Flags = TypeOf (Expr->Type) | GlobalModeFlags (Expr) | CF_FORCECHAR | CF_CONST; /* Get the increment value in bytes */ Val = IsTypePtr (Expr->Type)? CheckedPSizeOf (Expr->Type) : 1; @@ -1342,23 +1468,23 @@ static void PreDec (ExprDesc* Expr) case E_LOC_ABS: /* Absolute: numeric address or const */ - g_subeqstatic (Flags | CF_ABSOLUTE, Expr->IVal, 0, Val); + g_subeqstatic (Flags, Expr->IVal, 0, Val); break; case E_LOC_GLOBAL: /* Global variable */ - g_subeqstatic (Flags | CF_EXTERNAL, Expr->Name, Expr->IVal, Val); + g_subeqstatic (Flags, Expr->Name, Expr->IVal, Val); break; case E_LOC_STATIC: case E_LOC_LITERAL: /* Static variable or literal in the literal pool */ - g_subeqstatic (Flags | CF_STATIC, Expr->Name, Expr->IVal, Val); + g_subeqstatic (Flags, Expr->Name, Expr->IVal, Val); break; case E_LOC_REGISTER: /* Register variable */ - g_subeqstatic (Flags | CF_REGVAR, Expr->Name, Expr->IVal, Val); + g_subeqstatic (Flags, Expr->Name, Expr->IVal, Val); break; case E_LOC_STACK: @@ -1386,8 +1512,8 @@ static void PreDec (ExprDesc* Expr) -static void PostIncDec (ExprDesc* Expr, void (*inc) (unsigned, unsigned long)) -/* Handle i-- and i++ */ +static void PostInc (ExprDesc* Expr) +/* Handle the postincrement operator */ { unsigned Flags; @@ -1395,8 +1521,13 @@ static void PostIncDec (ExprDesc* Expr, void (*inc) (unsigned, unsigned long)) /* The expression to increment must be an lvalue */ if (!ED_IsLVal (Expr)) { - Error ("Invalid lvalue"); - return; + Error ("Invalid lvalue"); + return; + } + + /* We cannot modify const values */ + if (IsQualConst (Expr->Type)) { + Error ("Increment of read-only variable"); } /* Get the data type */ @@ -1411,9 +1542,56 @@ static void PostIncDec (ExprDesc* Expr, void (*inc) (unsigned, unsigned long)) /* If we have a pointer expression, increment by the size of the type */ if (IsTypePtr (Expr->Type)) { - inc (Flags | CF_CONST | CF_FORCECHAR, CheckedSizeOf (Expr->Type + 1)); + g_inc (Flags | CF_CONST | CF_FORCECHAR, CheckedSizeOf (Expr->Type + 1)); } else { - inc (Flags | CF_CONST | CF_FORCECHAR, 1); + g_inc (Flags | CF_CONST | CF_FORCECHAR, 1); + } + + /* Store the result back */ + Store (Expr, 0); + + /* Restore the original value in the primary register */ + g_restore (Flags | CF_FORCECHAR); + + /* The result is always an expression, no reference */ + ED_MakeRValExpr (Expr); +} + + + +static void PostDec (ExprDesc* Expr) +/* Handle the postdecrement operator */ +{ + unsigned Flags; + + NextToken (); + + /* The expression to increment must be an lvalue */ + if (!ED_IsLVal (Expr)) { + Error ("Invalid lvalue"); + return; + } + + /* We cannot modify const values */ + if (IsQualConst (Expr->Type)) { + Error ("Decrement of read-only variable"); + } + + /* Get the data type */ + Flags = TypeOf (Expr->Type); + + /* Push the address if needed */ + PushAddr (Expr); + + /* Fetch the value and save it (since it's the result of the expression) */ + LoadExpr (CF_NONE, Expr); + g_save (Flags | CF_FORCECHAR); + + /* If we have a pointer expression, increment by the size of the type */ + if (IsTypePtr (Expr->Type)) { + g_dec (Flags | CF_CONST | CF_FORCECHAR, CheckedSizeOf (Expr->Type + 1)); + } else { + g_dec (Flags | CF_CONST | CF_FORCECHAR, 1); } /* Store the result back */ @@ -1448,27 +1626,27 @@ static void UnaryOp (ExprDesc* Expr) /* Check for a constant expression */ if (ED_IsConstAbs (Expr)) { - /* Value is constant */ - switch (Tok) { - case TOK_MINUS: Expr->IVal = -Expr->IVal; break; - case TOK_PLUS: break; - case TOK_COMP: Expr->IVal = ~Expr->IVal; break; - default: Internal ("Unexpected token: %d", Tok); - } + /* Value is constant */ + switch (Tok) { + case TOK_MINUS: Expr->IVal = -Expr->IVal; break; + case TOK_PLUS: break; + case TOK_COMP: Expr->IVal = ~Expr->IVal; break; + default: Internal ("Unexpected token: %d", Tok); + } } else { - /* Value is not constant */ - LoadExpr (CF_NONE, Expr); + /* Value is not constant */ + LoadExpr (CF_NONE, Expr); - /* Get the type of the expression */ - Flags = TypeOf (Expr->Type); + /* Get the type of the expression */ + Flags = TypeOf (Expr->Type); - /* Handle the operation */ - switch (Tok) { - case TOK_MINUS: g_neg (Flags); break; - case TOK_PLUS: break; - case TOK_COMP: g_com (Flags); break; - default: Internal ("Unexpected token: %d", Tok); - } + /* Handle the operation */ + switch (Tok) { + case TOK_MINUS: g_neg (Flags); break; + case TOK_PLUS: break; + case TOK_COMP: g_com (Flags); break; + default: Internal ("Unexpected token: %d", Tok); + } /* The result is a rvalue in the primary */ ED_MakeRValExpr (Expr); @@ -1484,46 +1662,49 @@ void hie10 (ExprDesc* Expr) switch (CurTok.Tok) { - case TOK_INC: - PreInc (Expr); - break; - - case TOK_DEC: - PreDec (Expr); - break; - - case TOK_PLUS: - case TOK_MINUS: - case TOK_COMP: - UnaryOp (Expr); - break; - - case TOK_BOOL_NOT: - NextToken (); - if (evalexpr (CF_NONE, hie10, Expr) == 0) { - /* Constant expression */ - Expr->IVal = !Expr->IVal; - } else { - g_bneg (TypeOf (Expr->Type)); + case TOK_INC: + PreInc (Expr); + break; + + case TOK_DEC: + PreDec (Expr); + break; + + case TOK_PLUS: + case TOK_MINUS: + case TOK_COMP: + UnaryOp (Expr); + break; + + case TOK_BOOL_NOT: + NextToken (); + if (evalexpr (CF_NONE, hie10, Expr) == 0) { + /* Constant expression */ + Expr->IVal = !Expr->IVal; + } else { + g_bneg (TypeOf (Expr->Type)); ED_MakeRValExpr (Expr); - ED_TestDone (Expr); /* bneg will set cc */ - } - break; + ED_TestDone (Expr); /* bneg will set cc */ + } + break; - case TOK_STAR: - NextToken (); + case TOK_STAR: + NextToken (); ExprWithCheck (hie10, Expr); if (ED_IsLVal (Expr) || !(ED_IsLocConst (Expr) || ED_IsLocStack (Expr))) { /* Not a const, load it into the primary and make it a - * calculated value. - */ + ** calculated value. + */ LoadExpr (CF_NONE, Expr); ED_MakeRValExpr (Expr); } /* If the expression is already a pointer to function, the - * additional dereferencing operator must be ignored. - */ - if (IsTypeFuncPtr (Expr->Type)) { + ** additional dereferencing operator must be ignored. A function + ** itself is represented as "pointer to function", so any number + ** of dereference operators is legal, since the result will + ** always be converted to "pointer to function". + */ + if (IsTypeFuncPtr (Expr->Type) || IsTypeFunc (Expr->Type)) { /* Expression not storable */ ED_MakeRVal (Expr); } else { @@ -1532,63 +1713,79 @@ void hie10 (ExprDesc* Expr) } else { Error ("Illegal indirection"); } - ED_MakeLVal (Expr); + /* If the expression points to an array, then don't convert the + ** address -- it already is the location of the first element. + */ + if (!IsTypeArray (Expr->Type)) { + /* The * operator yields an lvalue */ + ED_MakeLVal (Expr); + } } break; - case TOK_AND: - NextToken (); - ExprWithCheck (hie10, Expr); - /* The & operator may be applied to any lvalue, and it may be - * applied to functions, even if they're no lvalues. - */ - if (ED_IsRVal (Expr) && !IsTypeFunc (Expr->Type)) { - /* Allow the & operator with an array */ - if (!IsTypeArray (Expr->Type)) { - Error ("Illegal address"); - } - } else { + case TOK_AND: + NextToken (); + ExprWithCheck (hie10, Expr); + /* The & operator may be applied to any lvalue, and it may be + ** applied to functions, even if they're no lvalues. + */ + if (ED_IsRVal (Expr) && !IsTypeFunc (Expr->Type) && !IsTypeArray (Expr->Type)) { + Error ("Illegal address"); + } else { + if (ED_IsBitField (Expr)) { + Error ("Cannot take address of bit-field"); + /* Do it anyway, just to avoid further warnings */ + Expr->Flags &= ~E_BITFIELD; + } Expr->Type = PointerTo (Expr->Type); + /* The & operator yields an rvalue */ ED_MakeRVal (Expr); - } - break; - - case TOK_SIZEOF: - NextToken (); - if (TypeSpecAhead ()) { - type Type[MAXTYPELEN]; - NextToken (); - Size = CheckedSizeOf (ParseType (Type)); - ConsumeRParen (); - } else { - /* Remember the output queue pointer */ - CodeMark Mark; + } + break; + + case TOK_SIZEOF: + NextToken (); + if (TypeSpecAhead ()) { + Type T[MAXTYPELEN]; + NextToken (); + Size = CheckedSizeOf (ParseType (T)); + ConsumeRParen (); + } else { + /* Remember the output queue pointer */ + CodeMark Mark; GetCodePos (&Mark); - hie10 (Expr); - Size = CheckedSizeOf (Expr->Type); - /* Remove any generated code */ - RemoveCode (&Mark); - } + hie10 (Expr); + /* If the expression is a literal string, release it, so it + ** won't be output as data if not used elsewhere. + */ + if (ED_IsLocLiteral (Expr)) { + ReleaseLiteral (Expr->LVal); + } + /* Calculate the size */ + Size = CheckedSizeOf (Expr->Type); + /* Remove any generated code */ + RemoveCode (&Mark); + } ED_MakeConstAbs (Expr, Size, type_size_t); - ED_MarkAsUntested (Expr); - break; + ED_MarkAsUntested (Expr); + break; - default: - if (TypeSpecAhead ()) { + default: + if (TypeSpecAhead ()) { - /* A typecast */ - TypeCast (Expr); + /* A typecast */ + TypeCast (Expr); - } else { + } else { /* An expression */ hie11 (Expr); /* Handle post increment */ - if (CurTok.Tok == TOK_INC) { - PostIncDec (Expr, g_inc); - } else if (CurTok.Tok == TOK_DEC) { - PostIncDec (Expr, g_dec); + switch (CurTok.Tok) { + case TOK_INC: PostInc (Expr); break; + case TOK_DEC: PostDec (Expr); break; + default: break; } } @@ -1599,224 +1796,540 @@ void hie10 (ExprDesc* Expr) static void hie_internal (const GenDesc* Ops, /* List of generators */ - ExprDesc* Expr, - void (*hienext) (ExprDesc*), - int* UsedGen) + ExprDesc* Expr, + void (*hienext) (ExprDesc*), + int* UsedGen) /* Helper function */ { ExprDesc Expr2; CodeMark Mark1; CodeMark Mark2; const GenDesc* Gen; - token_t Tok; /* The operator token */ + token_t Tok; /* The operator token */ unsigned ltype, type; - int rconst; /* Operand is a constant */ + int lconst; /* Left operand is a constant */ + int rconst; /* Right operand is a constant */ - hienext (Expr); + ExprWithCheck (hienext, Expr); *UsedGen = 0; while ((Gen = FindGen (CurTok.Tok, Ops)) != 0) { - /* Tell the caller that we handled it's ops */ - *UsedGen = 1; - - /* All operators that call this function expect an int on the lhs */ - if (!IsClassInt (Expr->Type)) { - Error ("Integer expression expected"); - } - - /* Remember the operator token, then skip it */ - Tok = CurTok.Tok; - NextToken (); - - /* Get the lhs on stack */ - GetCodePos (&Mark1); - ltype = TypeOf (Expr->Type); - if (ED_IsConstAbs (Expr)) { - /* Constant value */ - GetCodePos (&Mark2); - g_push (ltype | CF_CONST, Expr->IVal); - } else { - /* Value not constant */ - LoadExpr (CF_NONE, Expr); - GetCodePos (&Mark2); - g_push (ltype, 0); - } - - /* Get the right hand side */ - rconst = (evalexpr (CF_NONE, hienext, &Expr2) == 0); - - /* Check the type of the rhs */ - if (!IsClassInt (Expr2.Type)) { - Error ("Integer expression expected"); - } - - /* Check for const operands */ - if (ED_IsConstAbs (Expr) && rconst) { - - /* Both operands are constant, remove the generated code */ - RemoveCode (&Mark1); - - /* Evaluate the result */ - Expr->IVal = kcalc (Tok, Expr->IVal, Expr2.IVal); - - /* Get the type of the result */ - Expr->Type = promoteint (Expr->Type, Expr2.Type); - - } else { - - /* If the right hand side is constant, and the generator function - * expects the lhs in the primary, remove the push of the primary - * now. - */ - unsigned rtype = TypeOf (Expr2.Type); - type = 0; - if (rconst) { - /* Second value is constant - check for div */ - type |= CF_CONST; - rtype |= CF_CONST; - if (Tok == TOK_DIV && Expr2.IVal == 0) { - Error ("Division by zero"); - } else if (Tok == TOK_MOD && Expr2.IVal == 0) { - Error ("Modulo operation with zero"); - } - if ((Gen->Flags & GEN_NOPUSH) != 0) { - RemoveCode (&Mark2); - ltype |= CF_REG; /* Value is in register */ - } - } - - /* Determine the type of the operation result. */ - type |= g_typeadjust (ltype, rtype); - Expr->Type = promoteint (Expr->Type, Expr2.Type); - - /* Generate code */ - Gen->Func (type, Expr2.IVal); + /* Tell the caller that we handled it's ops */ + *UsedGen = 1; + + /* All operators that call this function expect an int on the lhs */ + if (!IsClassInt (Expr->Type)) { + Error ("Integer expression expected"); + /* To avoid further errors, make Expr a valid int expression */ + ED_MakeConstAbsInt (Expr, 1); + } + + /* Remember the operator token, then skip it */ + Tok = CurTok.Tok; + NextToken (); + + /* Get the lhs on stack */ + GetCodePos (&Mark1); + ltype = TypeOf (Expr->Type); + lconst = ED_IsConstAbs (Expr); + if (lconst) { + /* Constant value */ + GetCodePos (&Mark2); + /* If the operator is commutative, don't push the left side, if + ** it's a constant, since we will exchange both operands. + */ + if ((Gen->Flags & GEN_COMM) == 0) { + g_push (ltype | CF_CONST, Expr->IVal); + } + } else { + /* Value not constant */ + LoadExpr (CF_NONE, Expr); + GetCodePos (&Mark2); + g_push (ltype, 0); + } + + /* Get the right hand side */ + MarkedExprWithCheck (hienext, &Expr2); + + /* Check for a constant expression */ + rconst = (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)); + if (!rconst) { + /* Not constant, load into the primary */ + LoadExpr (CF_NONE, &Expr2); + } + + /* Check the type of the rhs */ + if (!IsClassInt (Expr2.Type)) { + Error ("Integer expression expected"); + } + + /* Check for const operands */ + if (lconst && rconst) { + + /* Both operands are constant, remove the generated code */ + RemoveCode (&Mark1); + + /* Get the type of the result */ + Expr->Type = promoteint (Expr->Type, Expr2.Type); + + /* Handle the op differently for signed and unsigned types */ + if (IsSignSigned (Expr->Type)) { + + /* Evaluate the result for signed operands */ + signed long Val1 = Expr->IVal; + signed long Val2 = Expr2.IVal; + switch (Tok) { + case TOK_OR: + Expr->IVal = (Val1 | Val2); + break; + case TOK_XOR: + Expr->IVal = (Val1 ^ Val2); + break; + case TOK_AND: + Expr->IVal = (Val1 & Val2); + break; + case TOK_STAR: + Expr->IVal = (Val1 * Val2); + break; + case TOK_DIV: + if (Val2 == 0) { + Error ("Division by zero"); + Expr->IVal = 0x7FFFFFFF; + } else { + Expr->IVal = (Val1 / Val2); + } + break; + case TOK_MOD: + if (Val2 == 0) { + Error ("Modulo operation with zero"); + Expr->IVal = 0; + } else { + Expr->IVal = (Val1 % Val2); + } + break; + default: + Internal ("hie_internal: got token 0x%X\n", Tok); + } + } else { + + /* Evaluate the result for unsigned operands */ + unsigned long Val1 = Expr->IVal; + unsigned long Val2 = Expr2.IVal; + switch (Tok) { + case TOK_OR: + Expr->IVal = (Val1 | Val2); + break; + case TOK_XOR: + Expr->IVal = (Val1 ^ Val2); + break; + case TOK_AND: + Expr->IVal = (Val1 & Val2); + break; + case TOK_STAR: + Expr->IVal = (Val1 * Val2); + break; + case TOK_DIV: + if (Val2 == 0) { + Error ("Division by zero"); + Expr->IVal = 0xFFFFFFFF; + } else { + Expr->IVal = (Val1 / Val2); + } + break; + case TOK_MOD: + if (Val2 == 0) { + Error ("Modulo operation with zero"); + Expr->IVal = 0; + } else { + Expr->IVal = (Val1 % Val2); + } + break; + default: + Internal ("hie_internal: got token 0x%X\n", Tok); + } + } + + } else if (lconst && (Gen->Flags & GEN_COMM) && !rconst) { + + /* The left side is constant, the right side is not, and the + ** operator allows swapping the operands. We haven't pushed the + ** left side onto the stack in this case, and will reverse the + ** operation because this allows for better code. + */ + unsigned rtype = ltype | CF_CONST; + ltype = TypeOf (Expr2.Type); /* Expr2 is now left */ + type = CF_CONST; + if ((Gen->Flags & GEN_NOPUSH) == 0) { + g_push (ltype, 0); + } else { + ltype |= CF_REG; /* Value is in register */ + } + + /* Determine the type of the operation result. */ + type |= g_typeadjust (ltype, rtype); + Expr->Type = promoteint (Expr->Type, Expr2.Type); + + /* Generate code */ + Gen->Func (type, Expr->IVal); + + /* We have a rvalue in the primary now */ + ED_MakeRValExpr (Expr); + + } else { + + /* If the right hand side is constant, and the generator function + ** expects the lhs in the primary, remove the push of the primary + ** now. + */ + unsigned rtype = TypeOf (Expr2.Type); + type = 0; + if (rconst) { + /* Second value is constant - check for div */ + type |= CF_CONST; + rtype |= CF_CONST; + if (Tok == TOK_DIV && Expr2.IVal == 0) { + Error ("Division by zero"); + } else if (Tok == TOK_MOD && Expr2.IVal == 0) { + Error ("Modulo operation with zero"); + } + if ((Gen->Flags & GEN_NOPUSH) != 0) { + RemoveCode (&Mark2); + ltype |= CF_REG; /* Value is in register */ + } + } + + /* Determine the type of the operation result. */ + type |= g_typeadjust (ltype, rtype); + Expr->Type = promoteint (Expr->Type, Expr2.Type); + + /* Generate code */ + Gen->Func (type, Expr2.IVal); /* We have a rvalue in the primary now */ - ED_MakeRValExpr (Expr); - } + ED_MakeRValExpr (Expr); + } } } static void hie_compare (const GenDesc* Ops, /* List of generators */ - ExprDesc* Expr, - void (*hienext) (ExprDesc*)) + ExprDesc* Expr, + void (*hienext) (ExprDesc*)) /* Helper function for the compare operators */ { ExprDesc Expr2; + CodeMark Mark0; CodeMark Mark1; CodeMark Mark2; const GenDesc* Gen; - token_t tok; /* The operator token */ + token_t Tok; /* The operator token */ unsigned ltype; - int rconst; /* Operand is a constant */ + int rconst; /* Operand is a constant */ - hienext (Expr); + GetCodePos (&Mark0); + ExprWithCheck (hienext, Expr); while ((Gen = FindGen (CurTok.Tok, Ops)) != 0) { - /* Remember the operator token, then skip it */ - tok = CurTok.Tok; - NextToken (); - - /* Get the lhs on stack */ - GetCodePos (&Mark1); - ltype = TypeOf (Expr->Type); - if (ED_IsConstAbs (Expr)) { - /* Constant value */ - GetCodePos (&Mark2); - g_push (ltype | CF_CONST, Expr->IVal); - } else { - /* Value not constant */ - LoadExpr (CF_NONE, Expr); - GetCodePos (&Mark2); - g_push (ltype, 0); - } - - /* Get the right hand side */ - rconst = (evalexpr (CF_NONE, hienext, &Expr2) == 0); - - /* Make sure, the types are compatible */ - if (IsClassInt (Expr->Type)) { - if (!IsClassInt (Expr2.Type) && !(IsClassPtr(Expr2.Type) && ED_IsNullPtr(Expr))) { - Error ("Incompatible types"); - } - } else if (IsClassPtr (Expr->Type)) { - if (IsClassPtr (Expr2.Type)) { - /* Both pointers are allowed in comparison if they point to - * the same type, or if one of them is a void pointer. - */ - type* left = Indirect (Expr->Type); - type* right = Indirect (Expr2.Type); - if (TypeCmp (left, right) < TC_EQUAL && *left != T_VOID && *right != T_VOID) { - /* Incomatible pointers */ - Error ("Incompatible types"); - } - } else if (!ED_IsNullPtr (&Expr2)) { - Error ("Incompatible types"); - } - } - - /* Check for const operands */ - if (ED_IsConstAbs (Expr) && rconst) { - - /* Both operands are constant, remove the generated code */ - RemoveCode (&Mark1); - - /* Evaluate the result */ - Expr->IVal = kcalc (tok, Expr->IVal, Expr2.IVal); - - } else { - - /* If the right hand side is constant, and the generator function - * expects the lhs in the primary, remove the push of the primary - * now. - */ - unsigned flags = 0; - if (rconst) { - flags |= CF_CONST; - if ((Gen->Flags & GEN_NOPUSH) != 0) { - RemoveCode (&Mark2); - ltype |= CF_REG; /* Value is in register */ - } - } - - /* Determine the type of the operation result. If the left - * operand is of type char and the right is a constant, or - * if both operands are of type char, we will encode the - * operation as char operation. Otherwise the default - * promotions are used. - */ - if (IsTypeChar (Expr->Type) && (IsTypeChar (Expr2.Type) || rconst)) { - flags |= CF_CHAR; - if (IsSignUnsigned (Expr->Type) || IsSignUnsigned (Expr2.Type)) { - flags |= CF_UNSIGNED; - } - if (rconst) { - flags |= CF_FORCECHAR; - } - } else { - unsigned rtype = TypeOf (Expr2.Type) | (flags & CF_CONST); - flags |= g_typeadjust (ltype, rtype); - } - - /* Generate code */ - Gen->Func (flags, Expr2.IVal); + /* Remember the generator function */ + void (*GenFunc) (unsigned, unsigned long) = Gen->Func; + + /* Remember the operator token, then skip it */ + Tok = CurTok.Tok; + NextToken (); + + /* Get the lhs on stack */ + GetCodePos (&Mark1); + ltype = TypeOf (Expr->Type); + if (ED_IsConstAbs (Expr)) { + /* Constant value */ + GetCodePos (&Mark2); + g_push (ltype | CF_CONST, Expr->IVal); + } else { + /* Value not constant */ + LoadExpr (CF_NONE, Expr); + GetCodePos (&Mark2); + g_push (ltype, 0); + } + + /* Get the right hand side */ + MarkedExprWithCheck (hienext, &Expr2); + + /* Check for a constant expression */ + rconst = (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)); + if (!rconst) { + /* Not constant, load into the primary */ + LoadExpr (CF_NONE, &Expr2); + } + + /* Make sure, the types are compatible */ + if (IsClassInt (Expr->Type)) { + if (!IsClassInt (Expr2.Type) && !(IsClassPtr(Expr2.Type) && ED_IsNullPtr(Expr))) { + Error ("Incompatible types"); + } + } else if (IsClassPtr (Expr->Type)) { + if (IsClassPtr (Expr2.Type)) { + /* Both pointers are allowed in comparison if they point to + ** the same type, or if one of them is a void pointer. + */ + Type* left = Indirect (Expr->Type); + Type* right = Indirect (Expr2.Type); + if (TypeCmp (left, right) < TC_EQUAL && left->C != T_VOID && right->C != T_VOID) { + /* Incomatible pointers */ + Error ("Incompatible types"); + } + } else if (!ED_IsNullPtr (&Expr2)) { + Error ("Incompatible types"); + } + } + + /* Check for const operands */ + if (ED_IsConstAbs (Expr) && rconst) { + + /* If the result is constant, this is suspicious when not in + ** preprocessor mode. + */ + WarnConstCompareResult (); + + /* Both operands are constant, remove the generated code */ + RemoveCode (&Mark1); + + /* Determine if this is a signed or unsigned compare */ + if (IsClassInt (Expr->Type) && IsSignSigned (Expr->Type) && + IsClassInt (Expr2.Type) && IsSignSigned (Expr2.Type)) { + + /* Evaluate the result for signed operands */ + signed long Val1 = Expr->IVal; + signed long Val2 = Expr2.IVal; + switch (Tok) { + case TOK_EQ: Expr->IVal = (Val1 == Val2); break; + case TOK_NE: Expr->IVal = (Val1 != Val2); break; + case TOK_LT: Expr->IVal = (Val1 < Val2); break; + case TOK_LE: Expr->IVal = (Val1 <= Val2); break; + case TOK_GE: Expr->IVal = (Val1 >= Val2); break; + case TOK_GT: Expr->IVal = (Val1 > Val2); break; + default: Internal ("hie_compare: got token 0x%X\n", Tok); + } + + } else { + + /* Evaluate the result for unsigned operands */ + unsigned long Val1 = Expr->IVal; + unsigned long Val2 = Expr2.IVal; + switch (Tok) { + case TOK_EQ: Expr->IVal = (Val1 == Val2); break; + case TOK_NE: Expr->IVal = (Val1 != Val2); break; + case TOK_LT: Expr->IVal = (Val1 < Val2); break; + case TOK_LE: Expr->IVal = (Val1 <= Val2); break; + case TOK_GE: Expr->IVal = (Val1 >= Val2); break; + case TOK_GT: Expr->IVal = (Val1 > Val2); break; + default: Internal ("hie_compare: got token 0x%X\n", Tok); + } + } + + } else { + + /* Determine the signedness of the operands */ + int LeftSigned = IsSignSigned (Expr->Type); + int RightSigned = IsSignSigned (Expr2.Type); + + /* If the right hand side is constant, and the generator function + ** expects the lhs in the primary, remove the push of the primary + ** now. + */ + unsigned flags = 0; + if (rconst) { + flags |= CF_CONST; + if ((Gen->Flags & GEN_NOPUSH) != 0) { + RemoveCode (&Mark2); + ltype |= CF_REG; /* Value is in register */ + } + } + + /* Determine the type of the operation. */ + if (IsTypeChar (Expr->Type) && rconst) { + + /* Left side is unsigned char, right side is constant. + ** Determine the minimum and maximum values + */ + int LeftMin, LeftMax; + if (LeftSigned) { + LeftMin = -128; + LeftMax = 127; + } else { + LeftMin = 0; + LeftMax = 255; + } + /* An integer value is always represented as a signed in the + ** ExprDesc structure. This may lead to false results below, + ** if it is actually unsigned, but interpreted as signed + ** because of the representation. Fortunately, in this case, + ** the actual value doesn't matter, since it's always greater + ** than what can be represented in a char. So correct the + ** value accordingly. + */ + if (!RightSigned && Expr2.IVal < 0) { + /* Correct the value so it is an unsigned. It will then + ** anyway match one of the cases below. + */ + Expr2.IVal = LeftMax + 1; + } + + /* Comparing a char against a constant may have a constant + ** result. Please note: It is not possible to remove the code + ** for the compare alltogether, because it may have side + ** effects. + */ + switch (Tok) { + + case TOK_EQ: + if (Expr2.IVal < LeftMin || Expr2.IVal > LeftMax) { + ED_MakeConstAbsInt (Expr, 0); + WarnConstCompareResult (); + goto Done; + } + break; + + case TOK_NE: + if (Expr2.IVal < LeftMin || Expr2.IVal > LeftMax) { + ED_MakeConstAbsInt (Expr, 1); + WarnConstCompareResult (); + goto Done; + } + break; + + case TOK_LT: + if (Expr2.IVal <= LeftMin || Expr2.IVal > LeftMax) { + ED_MakeConstAbsInt (Expr, Expr2.IVal > LeftMax); + WarnConstCompareResult (); + goto Done; + } + break; + + case TOK_LE: + if (Expr2.IVal < LeftMin || Expr2.IVal >= LeftMax) { + ED_MakeConstAbsInt (Expr, Expr2.IVal >= LeftMax); + WarnConstCompareResult (); + goto Done; + } + break; + + case TOK_GE: + if (Expr2.IVal <= LeftMin || Expr2.IVal > LeftMax) { + ED_MakeConstAbsInt (Expr, Expr2.IVal <= LeftMin); + WarnConstCompareResult (); + goto Done; + } + break; + + case TOK_GT: + if (Expr2.IVal < LeftMin || Expr2.IVal >= LeftMax) { + ED_MakeConstAbsInt (Expr, Expr2.IVal < LeftMin); + WarnConstCompareResult (); + goto Done; + } + break; + + default: + Internal ("hie_compare: got token 0x%X\n", Tok); + } + + /* If the result is not already constant (as evaluated in the + ** switch above), we can execute the operation as a char op, + ** since the right side constant is in a valid range. + */ + flags |= (CF_CHAR | CF_FORCECHAR); + if (!LeftSigned) { + flags |= CF_UNSIGNED; + } + + } else if (IsTypeChar (Expr->Type) && IsTypeChar (Expr2.Type) && + GetSignedness (Expr->Type) == GetSignedness (Expr2.Type)) { + + /* Both are chars with the same signedness. We can encode the + ** operation as a char operation. + */ + flags |= CF_CHAR; + if (rconst) { + flags |= CF_FORCECHAR; + } + if (!LeftSigned) { + flags |= CF_UNSIGNED; + } + } else { + unsigned rtype = TypeOf (Expr2.Type) | (flags & CF_CONST); + flags |= g_typeadjust (ltype, rtype); + } + + /* If the left side is an unsigned and the right is a constant, + ** we may be able to change the compares to something more + ** effective. + */ + if (!LeftSigned && rconst) { + + switch (Tok) { + + case TOK_LT: + if (Expr2.IVal == 1) { + /* An unsigned compare to one means that the value + ** must be zero. + */ + GenFunc = g_eq; + Expr2.IVal = 0; + } + break; + + case TOK_LE: + if (Expr2.IVal == 0) { + /* An unsigned compare to zero means that the value + ** must be zero. + */ + GenFunc = g_eq; + } + break; + + case TOK_GE: + if (Expr2.IVal == 1) { + /* An unsigned compare to one means that the value + ** must not be zero. + */ + GenFunc = g_ne; + Expr2.IVal = 0; + } + break; + + case TOK_GT: + if (Expr2.IVal == 0) { + /* An unsigned compare to zero means that the value + ** must not be zero. + */ + GenFunc = g_ne; + } + break; + + default: + break; + + } + + } + + /* Generate code */ + GenFunc (flags, Expr2.IVal); /* The result is an rvalue in the primary */ - ED_MakeRValExpr (Expr); - } + ED_MakeRValExpr (Expr); + } - /* Result type is always int */ - Expr->Type = type_int; + /* Result type is always int */ + Expr->Type = type_int; - /* Condition codes are set */ - ED_TestDone (Expr); +Done: /* Condition codes are set */ + ED_TestDone (Expr); } } @@ -1826,10 +2339,10 @@ static void hie9 (ExprDesc *Expr) /* Process * and / operators. */ { static const GenDesc hie9_ops[] = { - { TOK_STAR, GEN_NOPUSH, g_mul }, - { TOK_DIV, GEN_NOPUSH, g_div }, - { TOK_MOD, GEN_NOPUSH, g_mod }, - { TOK_INVALID, 0, 0 } + { TOK_STAR, GEN_NOPUSH | GEN_COMM, g_mul }, + { TOK_DIV, GEN_NOPUSH, g_div }, + { TOK_MOD, GEN_NOPUSH, g_mod }, + { TOK_INVALID, 0, 0 } }; int UsedGen; @@ -1840,15 +2353,15 @@ static void hie9 (ExprDesc *Expr) static void parseadd (ExprDesc* Expr) /* Parse an expression with the binary plus operator. Expr contains the - * unprocessed left hand side of the expression and will contain the - * result of the expression on return. - */ +** unprocessed left hand side of the expression and will contain the +** result of the expression on return. +*/ { ExprDesc Expr2; - unsigned flags; /* Operation flags */ - CodeMark Mark; /* Remember code position */ - type* lhst; /* Type of left hand side */ - type* rhst; /* Type of right hand side */ + unsigned flags; /* Operation flags */ + CodeMark Mark; /* Remember code position */ + Type* lhst; /* Type of left hand side */ + Type* rhst; /* Type of right hand side */ /* Skip the PLUS token */ @@ -1861,196 +2374,205 @@ static void parseadd (ExprDesc* Expr) /* Check for constness on both sides */ if (ED_IsConst (Expr)) { - /* The left hand side is a constant of some sort. Good. Get rhs */ - hie9 (&Expr2); - if (ED_IsConstAbs (&Expr2)) { - - /* Right hand side is a constant numeric value. Get the rhs type */ - rhst = Expr2.Type; - - /* Both expressions are constants. Check for pointer arithmetic */ - if (IsClassPtr (lhst) && IsClassInt (rhst)) { - /* Left is pointer, right is int, must scale rhs */ - Expr->IVal += Expr2.IVal * CheckedPSizeOf (lhst); - /* Result type is a pointer */ - } else if (IsClassInt (lhst) && IsClassPtr (rhst)) { - /* Left is int, right is pointer, must scale lhs */ - Expr->IVal = Expr->IVal * CheckedPSizeOf (rhst) + Expr2.IVal; - /* Result type is a pointer */ - Expr->Type = Expr2.Type; - } else if (IsClassInt (lhst) && IsClassInt (rhst)) { - /* Integer addition */ - Expr->IVal += Expr2.IVal; - typeadjust (Expr, &Expr2, 1); - } else { - /* OOPS */ - Error ("Invalid operands for binary operator `+'"); - } - - } else { - - /* lhs is a constant and rhs is not constant. Load rhs into - * the primary. - */ - LoadExpr (CF_NONE, &Expr2); - - /* Beware: The check above (for lhs) lets not only pass numeric - * constants, but also constant addresses (labels), maybe even - * with an offset. We have to check for that here. - */ - - /* First, get the rhs type. */ - rhst = Expr2.Type; - - /* Setup flags */ - if (ED_IsLocAbs (Expr)) { - /* A numerical constant */ - flags |= CF_CONST; - } else { - /* Constant address label */ - flags |= GlobalModeFlags (Expr->Flags) | CF_CONSTADDR; - } - - /* Check for pointer arithmetic */ - if (IsClassPtr (lhst) && IsClassInt (rhst)) { - /* Left is pointer, right is int, must scale rhs */ - g_scale (CF_INT, CheckedPSizeOf (lhst)); - /* Operate on pointers, result type is a pointer */ - flags |= CF_PTR; - /* Generate the code for the add */ - if (ED_GetLoc (Expr) == E_LOC_ABS) { - /* Numeric constant */ - g_inc (flags, Expr->IVal); - } else { - /* Constant address */ - g_addaddr_static (flags, Expr->Name, Expr->IVal); - } - } else if (IsClassInt (lhst) && IsClassPtr (rhst)) { - - /* Left is int, right is pointer, must scale lhs. */ - unsigned ScaleFactor = CheckedPSizeOf (rhst); - - /* Operate on pointers, result type is a pointer */ - flags |= CF_PTR; - Expr->Type = Expr2.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 (ED_IsLocAbs (Expr)) { - /* Numeric constant, scale lhs */ - Expr->IVal *= ScaleFactor; - /* Generate the code for the add */ - g_inc (flags, Expr->IVal); - } else if (ScaleFactor == 1) { - /* Constant address but no need to scale */ - g_addaddr_static (flags, Expr->Name, Expr->IVal); - } else { - /* Constant address that must be scaled */ - g_push (TypeOf (Expr2.Type), 0); /* rhs --> stack */ - g_getimmed (flags, Expr->Name, Expr->IVal); - g_scale (CF_PTR, ScaleFactor); - g_add (CF_PTR, 0); - } - } else if (IsClassInt (lhst) && IsClassInt (rhst)) { - /* Integer addition */ - flags |= typeadjust (Expr, &Expr2, 1); - /* Generate the code for the add */ - if (ED_IsLocAbs (Expr)) { - /* Numeric constant */ - g_inc (flags, Expr->IVal); - } else { - /* Constant address */ - g_addaddr_static (flags, Expr->Name, Expr->IVal); - } - } else { - /* OOPS */ - Error ("Invalid operands for binary operator `+'"); - } - - /* Result is a rvalue in primary register */ - ED_MakeRValExpr (Expr); - } + /* The left hand side is a constant of some sort. Good. Get rhs */ + ExprWithCheck (hie9, &Expr2); + if (ED_IsConstAbs (&Expr2)) { + + /* Right hand side is a constant numeric value. Get the rhs type */ + rhst = Expr2.Type; + + /* Both expressions are constants. Check for pointer arithmetic */ + if (IsClassPtr (lhst) && IsClassInt (rhst)) { + /* Left is pointer, right is int, must scale rhs */ + Expr->IVal += Expr2.IVal * CheckedPSizeOf (lhst); + /* Result type is a pointer */ + } else if (IsClassInt (lhst) && IsClassPtr (rhst)) { + /* Left is int, right is pointer, must scale lhs */ + Expr->IVal = Expr->IVal * CheckedPSizeOf (rhst) + Expr2.IVal; + /* Result type is a pointer */ + Expr->Type = Expr2.Type; + } else if (IsClassInt (lhst) && IsClassInt (rhst)) { + /* Integer addition */ + Expr->IVal += Expr2.IVal; + typeadjust (Expr, &Expr2, 1); + } else { + /* OOPS */ + Error ("Invalid operands for binary operator `+'"); + } + + } else { + + /* lhs is a constant and rhs is not constant. Load rhs into + ** the primary. + */ + LoadExpr (CF_NONE, &Expr2); + + /* Beware: The check above (for lhs) lets not only pass numeric + ** constants, but also constant addresses (labels), maybe even + ** with an offset. We have to check for that here. + */ + + /* First, get the rhs type. */ + rhst = Expr2.Type; + + /* Setup flags */ + if (ED_IsLocAbs (Expr)) { + /* A numerical constant */ + flags |= CF_CONST; + } else { + /* Constant address label */ + flags |= GlobalModeFlags (Expr) | CF_CONSTADDR; + } + + /* Check for pointer arithmetic */ + if (IsClassPtr (lhst) && IsClassInt (rhst)) { + /* Left is pointer, right is int, must scale rhs */ + g_scale (CF_INT, CheckedPSizeOf (lhst)); + /* Operate on pointers, result type is a pointer */ + flags |= CF_PTR; + /* Generate the code for the add */ + if (ED_GetLoc (Expr) == E_LOC_ABS) { + /* Numeric constant */ + g_inc (flags, Expr->IVal); + } else { + /* Constant address */ + g_addaddr_static (flags, Expr->Name, Expr->IVal); + } + } else if (IsClassInt (lhst) && IsClassPtr (rhst)) { + + /* Left is int, right is pointer, must scale lhs. */ + unsigned ScaleFactor = CheckedPSizeOf (rhst); + + /* Operate on pointers, result type is a pointer */ + flags |= CF_PTR; + Expr->Type = Expr2.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 (ED_IsLocAbs (Expr)) { + /* Numeric constant, scale lhs */ + Expr->IVal *= ScaleFactor; + /* Generate the code for the add */ + g_inc (flags, Expr->IVal); + } else if (ScaleFactor == 1) { + /* Constant address but no need to scale */ + g_addaddr_static (flags, Expr->Name, Expr->IVal); + } else { + /* Constant address that must be scaled */ + g_push (TypeOf (Expr2.Type), 0); /* rhs --> stack */ + g_getimmed (flags, Expr->Name, Expr->IVal); + g_scale (CF_PTR, ScaleFactor); + g_add (CF_PTR, 0); + } + } else if (IsClassInt (lhst) && IsClassInt (rhst)) { + /* Integer addition */ + flags |= typeadjust (Expr, &Expr2, 1); + /* Generate the code for the add */ + if (ED_IsLocAbs (Expr)) { + /* Numeric constant */ + g_inc (flags, Expr->IVal); + } else { + /* Constant address */ + g_addaddr_static (flags, Expr->Name, Expr->IVal); + } + } else { + /* OOPS */ + Error ("Invalid operands for binary operator `+'"); + flags = CF_INT; + } + + /* Result is a rvalue in primary register */ + ED_MakeRValExpr (Expr); + } } else { - /* Left hand side is not constant. Get the value onto the stack. */ - LoadExpr (CF_NONE, Expr); /* --> primary register */ - GetCodePos (&Mark); - g_push (TypeOf (Expr->Type), 0); /* --> stack */ - - /* Evaluate the rhs */ - if (evalexpr (CF_NONE, hie9, &Expr2) == 0) { - - /* Right hand side is a constant. Get the rhs type */ - rhst = Expr2.Type; - - /* Remove pushed value from stack */ - RemoveCode (&Mark); - - /* Check for pointer arithmetic */ - if (IsClassPtr (lhst) && IsClassInt (rhst)) { - /* Left is pointer, right is int, must scale rhs */ - Expr2.IVal *= CheckedPSizeOf (lhst); - /* Operate on pointers, result type is a pointer */ - flags = CF_PTR; - } else if (IsClassInt (lhst) && IsClassPtr (rhst)) { - /* Left is int, right is pointer, must scale lhs (ptr only) */ - g_scale (CF_INT | CF_CONST, CheckedPSizeOf (rhst)); - /* Operate on pointers, result type is a pointer */ - flags = CF_PTR; - Expr->Type = Expr2.Type; - } else if (IsClassInt (lhst) && IsClassInt (rhst)) { - /* Integer addition */ - flags = typeadjust (Expr, &Expr2, 1); - } else { - /* OOPS */ - Error ("Invalid operands for binary operator `+'"); - } - - /* Generate code for the add */ - g_inc (flags | CF_CONST, Expr2.IVal); - - } else { - - /* lhs and rhs are not constant. Get the rhs type. */ - rhst = Expr2.Type; - - /* Check for pointer arithmetic */ - if (IsClassPtr (lhst) && IsClassInt (rhst)) { - /* Left is pointer, right is int, must scale rhs */ - g_scale (CF_INT, CheckedPSizeOf (lhst)); - /* Operate on pointers, result type is a pointer */ - flags = CF_PTR; - } else if (IsClassInt (lhst) && IsClassPtr (rhst)) { - /* Left is int, right is pointer, must scale lhs */ - g_tosint (TypeOf (rhst)); /* Make sure, TOS is int */ - g_swap (CF_INT); /* Swap TOS and primary */ - g_scale (CF_INT, CheckedPSizeOf (rhst)); - /* Operate on pointers, result type is a pointer */ - flags = CF_PTR; - Expr->Type = Expr2.Type; - } else if (IsClassInt (lhst) && IsClassInt (rhst)) { - /* 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 (Expr, &Expr2, 0) & ~CF_CONST; - } else { - /* OOPS */ - Error ("Invalid operands for binary operator `+'"); - } - - /* Generate code for the add */ - g_add (flags, 0); - - } + /* Left hand side is not constant. Get the value onto the stack. */ + LoadExpr (CF_NONE, Expr); /* --> primary register */ + GetCodePos (&Mark); + g_push (TypeOf (Expr->Type), 0); /* --> stack */ + + /* Evaluate the rhs */ + MarkedExprWithCheck (hie9, &Expr2); + + /* Check for a constant rhs expression */ + if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) { + + /* Right hand side is a constant. Get the rhs type */ + rhst = Expr2.Type; + + /* Remove pushed value from stack */ + RemoveCode (&Mark); + + /* Check for pointer arithmetic */ + if (IsClassPtr (lhst) && IsClassInt (rhst)) { + /* Left is pointer, right is int, must scale rhs */ + Expr2.IVal *= CheckedPSizeOf (lhst); + /* Operate on pointers, result type is a pointer */ + flags = CF_PTR; + } else if (IsClassInt (lhst) && IsClassPtr (rhst)) { + /* Left is int, right is pointer, must scale lhs (ptr only) */ + g_scale (CF_INT | CF_CONST, CheckedPSizeOf (rhst)); + /* Operate on pointers, result type is a pointer */ + flags = CF_PTR; + Expr->Type = Expr2.Type; + } else if (IsClassInt (lhst) && IsClassInt (rhst)) { + /* Integer addition */ + flags = typeadjust (Expr, &Expr2, 1); + } else { + /* OOPS */ + Error ("Invalid operands for binary operator `+'"); + flags = CF_INT; + } + + /* Generate code for the add */ + g_inc (flags | CF_CONST, Expr2.IVal); + + } else { + + /* Not constant, load into the primary */ + LoadExpr (CF_NONE, &Expr2); + + /* lhs and rhs are not constant. Get the rhs type. */ + rhst = Expr2.Type; + + /* Check for pointer arithmetic */ + if (IsClassPtr (lhst) && IsClassInt (rhst)) { + /* Left is pointer, right is int, must scale rhs */ + g_scale (CF_INT, CheckedPSizeOf (lhst)); + /* Operate on pointers, result type is a pointer */ + flags = CF_PTR; + } else if (IsClassInt (lhst) && IsClassPtr (rhst)) { + /* Left is int, right is pointer, must scale lhs */ + g_tosint (TypeOf (rhst)); /* Make sure, TOS is int */ + g_swap (CF_INT); /* Swap TOS and primary */ + g_scale (CF_INT, CheckedPSizeOf (rhst)); + /* Operate on pointers, result type is a pointer */ + flags = CF_PTR; + Expr->Type = Expr2.Type; + } else if (IsClassInt (lhst) && IsClassInt (rhst)) { + /* 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 (Expr, &Expr2, 0) & ~CF_CONST; + } else { + /* OOPS */ + Error ("Invalid operands for binary operator `+'"); + flags = CF_INT; + } + + /* Generate code for the add */ + g_add (flags, 0); + + } /* Result is a rvalue in primary register */ ED_MakeRValExpr (Expr); @@ -2065,17 +2587,17 @@ static void parseadd (ExprDesc* Expr) static void parsesub (ExprDesc* Expr) /* Parse an expression with the binary minus operator. Expr contains the - * unprocessed left hand side of the expression and will contain the - * result of the expression on return. - */ +** unprocessed left hand side of the expression and will contain the +** result of the expression on return. +*/ { ExprDesc Expr2; - unsigned flags; /* Operation flags */ - type* lhst; /* Type of left hand side */ - type* rhst; /* Type of right hand side */ - CodeMark Mark1; /* Save position of output queue */ - CodeMark Mark2; /* Another position in the queue */ - int rscale; /* Scale factor for the result */ + unsigned flags; /* Operation flags */ + Type* lhst; /* Type of left hand side */ + Type* rhst; /* Type of right hand side */ + CodeMark Mark1; /* Save position of output queue */ + CodeMark Mark2; /* Another position in the queue */ + int rscale; /* Scale factor for the result */ /* Skip the MINUS token */ @@ -2083,145 +2605,152 @@ static void parsesub (ExprDesc* Expr) /* Get the left hand side type, initialize operation flags */ lhst = Expr->Type; - flags = 0; - rscale = 1; /* Scale by 1, that is, don't scale */ + rscale = 1; /* Scale by 1, that is, don't scale */ /* Remember the output queue position, then bring the value onto the stack */ GetCodePos (&Mark1); LoadExpr (CF_NONE, Expr); /* --> primary register */ GetCodePos (&Mark2); - g_push (TypeOf (lhst), 0); /* --> stack */ + g_push (TypeOf (lhst), 0); /* --> stack */ /* Parse the right hand side */ - if (evalexpr (CF_NONE, hie9, &Expr2) == 0) { - - /* The right hand side is constant. Get the rhs type. */ - rhst = Expr2.Type; - - /* Check left hand side */ - if (ED_IsConstAbs (Expr)) { - - /* Both sides are constant, remove generated code */ - RemoveCode (&Mark1); - - /* Check for pointer arithmetic */ - if (IsClassPtr (lhst) && IsClassInt (rhst)) { - /* Left is pointer, right is int, must scale rhs */ - Expr->IVal -= Expr2.IVal * CheckedPSizeOf (lhst); - /* Operate on pointers, result type is a pointer */ - } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) { - /* Left is pointer, right is pointer, must scale result */ - if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) { - Error ("Incompatible pointer types"); - } else { - Expr->IVal = (Expr->IVal - Expr2.IVal) / + MarkedExprWithCheck (hie9, &Expr2); + + /* Check for a constant rhs expression */ + if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) { + + /* The right hand side is constant. Get the rhs type. */ + rhst = Expr2.Type; + + /* Check left hand side */ + if (ED_IsConstAbs (Expr)) { + + /* Both sides are constant, remove generated code */ + RemoveCode (&Mark1); + + /* Check for pointer arithmetic */ + if (IsClassPtr (lhst) && IsClassInt (rhst)) { + /* Left is pointer, right is int, must scale rhs */ + Expr->IVal -= Expr2.IVal * CheckedPSizeOf (lhst); + /* Operate on pointers, result type is a pointer */ + } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) { + /* Left is pointer, right is pointer, must scale result */ + if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) { + Error ("Incompatible pointer types"); + } else { + Expr->IVal = (Expr->IVal - Expr2.IVal) / CheckedPSizeOf (lhst); - } - /* Operate on pointers, result type is an integer */ - Expr->Type = type_int; - } else if (IsClassInt (lhst) && IsClassInt (rhst)) { - /* Integer subtraction */ - typeadjust (Expr, &Expr2, 1); - Expr->IVal -= Expr2.IVal; - } else { - /* OOPS */ - Error ("Invalid operands for binary operator `-'"); - } - - /* Result is constant, condition codes not set */ - ED_MarkAsUntested (Expr); - - } else { - - /* Left hand side is not constant, right hand side is. - * Remove pushed value from stack. - */ - RemoveCode (&Mark2); - - if (IsClassPtr (lhst) && IsClassInt (rhst)) { - /* Left is pointer, right is int, must scale rhs */ - Expr2.IVal *= CheckedPSizeOf (lhst); - /* Operate on pointers, result type is a pointer */ - flags = CF_PTR; - } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) { - /* Left is pointer, right is pointer, must scale result */ - if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) { - Error ("Incompatible pointer types"); - } else { - rscale = CheckedPSizeOf (lhst); - } - /* Operate on pointers, result type is an integer */ - flags = CF_PTR; - Expr->Type = type_int; - } else if (IsClassInt (lhst) && IsClassInt (rhst)) { - /* Integer subtraction */ - flags = typeadjust (Expr, &Expr2, 1); - } else { - /* OOPS */ - Error ("Invalid operands for binary operator `-'"); - } - - /* Do the subtraction */ - g_dec (flags | CF_CONST, Expr2.IVal); - - /* If this was a pointer subtraction, we must scale the result */ - if (rscale != 1) { - g_scale (flags, -rscale); - } - - /* Result is a rvalue in the primary register */ - ED_MakeRValExpr (Expr); - ED_MarkAsUntested (Expr); - - } + } + /* Operate on pointers, result type is an integer */ + Expr->Type = type_int; + } else if (IsClassInt (lhst) && IsClassInt (rhst)) { + /* Integer subtraction */ + typeadjust (Expr, &Expr2, 1); + Expr->IVal -= Expr2.IVal; + } else { + /* OOPS */ + Error ("Invalid operands for binary operator `-'"); + } + + /* Result is constant, condition codes not set */ + ED_MarkAsUntested (Expr); + + } else { + + /* Left hand side is not constant, right hand side is. + ** Remove pushed value from stack. + */ + RemoveCode (&Mark2); + + if (IsClassPtr (lhst) && IsClassInt (rhst)) { + /* Left is pointer, right is int, must scale rhs */ + Expr2.IVal *= CheckedPSizeOf (lhst); + /* Operate on pointers, result type is a pointer */ + flags = CF_PTR; + } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) { + /* Left is pointer, right is pointer, must scale result */ + if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) { + Error ("Incompatible pointer types"); + } else { + rscale = CheckedPSizeOf (lhst); + } + /* Operate on pointers, result type is an integer */ + flags = CF_PTR; + Expr->Type = type_int; + } else if (IsClassInt (lhst) && IsClassInt (rhst)) { + /* Integer subtraction */ + flags = typeadjust (Expr, &Expr2, 1); + } else { + /* OOPS */ + Error ("Invalid operands for binary operator `-'"); + flags = CF_INT; + } + + /* Do the subtraction */ + g_dec (flags | CF_CONST, Expr2.IVal); + + /* If this was a pointer subtraction, we must scale the result */ + if (rscale != 1) { + g_scale (flags, -rscale); + } + + /* Result is a rvalue in the primary register */ + ED_MakeRValExpr (Expr); + ED_MarkAsUntested (Expr); + + } } else { - /* Right hand side is not constant. Get the rhs type. */ - rhst = Expr2.Type; - - /* Check for pointer arithmetic */ - if (IsClassPtr (lhst) && IsClassInt (rhst)) { - /* Left is pointer, right is int, must scale rhs */ - g_scale (CF_INT, CheckedPSizeOf (lhst)); - /* Operate on pointers, result type is a pointer */ - flags = CF_PTR; - } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) { - /* Left is pointer, right is pointer, must scale result */ - if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) { - Error ("Incompatible pointer types"); - } else { - rscale = CheckedPSizeOf (lhst); - } - /* Operate on pointers, result type is an integer */ - flags = CF_PTR; - Expr->Type = type_int; - } else if (IsClassInt (lhst) && IsClassInt (rhst)) { - /* Integer subtraction. If the left hand side descriptor says that - * the lhs is const, we have to remove this mark, since this is no - * longer true, lhs is on stack instead. - */ - if (ED_IsLocAbs (Expr)) { - ED_MakeRValExpr (Expr); - } - /* Adjust operand types */ - flags = typeadjust (Expr, &Expr2, 0); - } else { - /* OOPS */ - Error ("Invalid operands for binary operator `-'"); - } - - /* Generate code for the sub (the & is a hack here) */ - g_sub (flags & ~CF_CONST, 0); - - /* If this was a pointer subtraction, we must scale the result */ - if (rscale != 1) { - g_scale (flags, -rscale); - } - - /* Result is a rvalue in the primary register */ - ED_MakeRValExpr (Expr); - ED_MarkAsUntested (Expr); + /* Not constant, load into the primary */ + LoadExpr (CF_NONE, &Expr2); + + /* Right hand side is not constant. Get the rhs type. */ + rhst = Expr2.Type; + + /* Check for pointer arithmetic */ + if (IsClassPtr (lhst) && IsClassInt (rhst)) { + /* Left is pointer, right is int, must scale rhs */ + g_scale (CF_INT, CheckedPSizeOf (lhst)); + /* Operate on pointers, result type is a pointer */ + flags = CF_PTR; + } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) { + /* Left is pointer, right is pointer, must scale result */ + if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) { + Error ("Incompatible pointer types"); + } else { + rscale = CheckedPSizeOf (lhst); + } + /* Operate on pointers, result type is an integer */ + flags = CF_PTR; + Expr->Type = type_int; + } else if (IsClassInt (lhst) && IsClassInt (rhst)) { + /* Integer subtraction. If the left hand side descriptor says that + ** the lhs is const, we have to remove this mark, since this is no + ** longer true, lhs is on stack instead. + */ + if (ED_IsLocAbs (Expr)) { + ED_MakeRValExpr (Expr); + } + /* Adjust operand types */ + flags = typeadjust (Expr, &Expr2, 0); + } else { + /* OOPS */ + Error ("Invalid operands for binary operator `-'"); + flags = CF_INT; + } + + /* Generate code for the sub (the & is a hack here) */ + g_sub (flags & ~CF_CONST, 0); + + /* If this was a pointer subtraction, we must scale the result */ + if (rscale != 1) { + g_scale (flags, -rscale); + } + + /* Result is a rvalue in the primary register */ + ED_MakeRValExpr (Expr); + ED_MarkAsUntested (Expr); } } @@ -2230,13 +2759,13 @@ static void parsesub (ExprDesc* Expr) void hie8 (ExprDesc* Expr) /* Process + and - binary operators. */ { - hie9 (Expr); + ExprWithCheck (hie9, Expr); while (CurTok.Tok == TOK_PLUS || CurTok.Tok == TOK_MINUS) { - if (CurTok.Tok == TOK_PLUS) { - parseadd (Expr); - } else { - parsesub (Expr); - } + if (CurTok.Tok == TOK_PLUS) { + parseadd (Expr); + } else { + parsesub (Expr); + } } } @@ -2246,10 +2775,10 @@ static void hie6 (ExprDesc* Expr) /* Handle greater-than type comparators */ { static const GenDesc hie6_ops [] = { - { TOK_LT, GEN_NOPUSH, g_lt }, - { TOK_LE, GEN_NOPUSH, g_le }, - { TOK_GE, GEN_NOPUSH, g_ge }, - { TOK_GT, GEN_NOPUSH, g_gt }, + { TOK_LT, GEN_NOPUSH, g_lt }, + { TOK_LE, GEN_NOPUSH, g_le }, + { TOK_GE, GEN_NOPUSH, g_ge }, + { TOK_GT, GEN_NOPUSH, g_gt }, { TOK_INVALID, 0, 0 } }; hie_compare (hie6_ops, Expr, ShiftExpr); @@ -2261,8 +2790,8 @@ static void hie5 (ExprDesc* Expr) /* Handle == and != */ { static const GenDesc hie5_ops[] = { - { TOK_EQ, GEN_NOPUSH, g_eq }, - { TOK_NE, GEN_NOPUSH, g_ne }, + { TOK_EQ, GEN_NOPUSH, g_eq }, + { TOK_NE, GEN_NOPUSH, g_ne }, { TOK_INVALID, 0, 0 } }; hie_compare (hie5_ops, Expr, hie6); @@ -2274,8 +2803,8 @@ static void hie4 (ExprDesc* Expr) /* Handle & (bitwise and) */ { static const GenDesc hie4_ops[] = { - { TOK_AND, GEN_NOPUSH, g_and }, - { TOK_INVALID, 0, 0 } + { TOK_AND, GEN_NOPUSH | GEN_COMM, g_and }, + { TOK_INVALID, 0, 0 } }; int UsedGen; @@ -2288,8 +2817,8 @@ static void hie3 (ExprDesc* Expr) /* Handle ^ (bitwise exclusive or) */ { static const GenDesc hie3_ops[] = { - { TOK_XOR, GEN_NOPUSH, g_xor }, - { TOK_INVALID, 0, 0 } + { TOK_XOR, GEN_NOPUSH | GEN_COMM, g_xor }, + { TOK_INVALID, 0, 0 } }; int UsedGen; @@ -2302,8 +2831,8 @@ static void hie2 (ExprDesc* Expr) /* Handle | (bitwise or) */ { static const GenDesc hie2_ops[] = { - { TOK_OR, GEN_NOPUSH, g_or }, - { TOK_INVALID, 0, 0 } + { TOK_OR, GEN_NOPUSH | GEN_COMM, g_or }, + { TOK_INVALID, 0, 0 } }; int UsedGen; @@ -2314,22 +2843,22 @@ static void hie2 (ExprDesc* Expr) static void hieAndPP (ExprDesc* Expr) /* Process "exp && exp" in preprocessor mode (that is, when the parser is - * called recursively from the preprocessor. - */ +** called recursively from the preprocessor. +*/ { ExprDesc Expr2; ConstAbsIntExpr (hie2, Expr); while (CurTok.Tok == TOK_BOOL_AND) { - /* Skip the && */ - NextToken (); + /* Skip the && */ + NextToken (); - /* Get rhs */ - ConstAbsIntExpr (hie2, &Expr2); + /* Get rhs */ + ConstAbsIntExpr (hie2, &Expr2); - /* Combine the two */ - Expr->IVal = (Expr->IVal && Expr2.IVal); + /* Combine the two */ + Expr->IVal = (Expr->IVal && Expr2.IVal); } } @@ -2337,22 +2866,22 @@ static void hieAndPP (ExprDesc* Expr) static void hieOrPP (ExprDesc *Expr) /* Process "exp || exp" in preprocessor mode (that is, when the parser is - * called recursively from the preprocessor. - */ +** called recursively from the preprocessor. +*/ { ExprDesc Expr2; ConstAbsIntExpr (hieAndPP, Expr); while (CurTok.Tok == TOK_BOOL_OR) { - /* Skip the && */ - NextToken (); + /* Skip the && */ + NextToken (); - /* Get rhs */ - ConstAbsIntExpr (hieAndPP, &Expr2); + /* Get rhs */ + ConstAbsIntExpr (hieAndPP, &Expr2); - /* Combine the two */ - Expr->IVal = (Expr->IVal || Expr2.IVal); + /* Combine the two */ + Expr->IVal = (Expr->IVal || Expr2.IVal); } } @@ -2361,57 +2890,57 @@ static void hieOrPP (ExprDesc *Expr) static void hieAnd (ExprDesc* Expr, unsigned TrueLab, int* BoolOp) /* Process "exp && exp" */ { - int lab; + int FalseLab; ExprDesc Expr2; - hie2 (Expr); + ExprWithCheck (hie2, Expr); if (CurTok.Tok == TOK_BOOL_AND) { - /* Tell our caller that we're evaluating a boolean */ - *BoolOp = 1; + /* Tell our caller that we're evaluating a boolean */ + *BoolOp = 1; - /* Get a label that we will use for false expressions */ - lab = GetLocalLabel (); + /* Get a label that we will use for false expressions */ + FalseLab = GetLocalLabel (); - /* If the expr hasn't set condition codes, set the force-test flag */ - if (!ED_IsTested (Expr)) { - ED_MarkForTest (Expr); - } + /* If the expr hasn't set condition codes, set the force-test flag */ + if (!ED_IsTested (Expr)) { + ED_MarkForTest (Expr); + } - /* Load the value */ - LoadExpr (CF_FORCECHAR, Expr); + /* Load the value */ + LoadExpr (CF_FORCECHAR, Expr); - /* Generate the jump */ - g_falsejump (CF_NONE, lab); + /* Generate the jump */ + g_falsejump (CF_NONE, FalseLab); - /* Parse more boolean and's */ - while (CurTok.Tok == TOK_BOOL_AND) { + /* Parse more boolean and's */ + while (CurTok.Tok == TOK_BOOL_AND) { - /* Skip the && */ - NextToken (); + /* Skip the && */ + NextToken (); - /* Get rhs */ - hie2 (&Expr2); - if (!ED_IsTested (&Expr2)) { - ED_MarkForTest (&Expr2); - } - LoadExpr (CF_FORCECHAR, &Expr2); + /* Get rhs */ + hie2 (&Expr2); + if (!ED_IsTested (&Expr2)) { + ED_MarkForTest (&Expr2); + } + LoadExpr (CF_FORCECHAR, &Expr2); - /* Do short circuit evaluation */ - if (CurTok.Tok == TOK_BOOL_AND) { - g_falsejump (CF_NONE, lab); - } else { - /* Last expression - will evaluate to true */ - g_truejump (CF_NONE, TrueLab); - } - } + /* Do short circuit evaluation */ + if (CurTok.Tok == TOK_BOOL_AND) { + g_falsejump (CF_NONE, FalseLab); + } else { + /* Last expression - will evaluate to true */ + g_truejump (CF_NONE, TrueLab); + } + } - /* Define the false jump label here */ - g_defcodelabel (lab); + /* Define the false jump label here */ + g_defcodelabel (FalseLab); - /* The result is an rvalue in primary */ - ED_MakeRValExpr (Expr); - ED_TestDone (Expr); /* Condition codes are set */ + /* The result is an rvalue in primary */ + ED_MakeRValExpr (Expr); + ED_TestDone (Expr); /* Condition codes are set */ } } @@ -2421,9 +2950,9 @@ static void hieOr (ExprDesc *Expr) /* Process "exp || exp". */ { ExprDesc Expr2; - int BoolOp = 0; /* Did we have a boolean op? */ - int AndOp; /* Did we have a && operation? */ - unsigned TrueLab; /* Jump to this label if true */ + int BoolOp = 0; /* Did we have a boolean op? */ + int AndOp; /* Did we have a && operation? */ + unsigned TrueLab; /* Jump to this label if true */ unsigned DoneLab; /* Get a label */ @@ -2435,56 +2964,56 @@ static void hieOr (ExprDesc *Expr) /* Any boolean or's? */ if (CurTok.Tok == TOK_BOOL_OR) { - /* If the expr hasn't set condition codes, set the force-test flag */ - if (!ED_IsTested (Expr)) { - ED_MarkForTest (Expr); - } + /* If the expr hasn't set condition codes, set the force-test flag */ + if (!ED_IsTested (Expr)) { + ED_MarkForTest (Expr); + } - /* Get first expr */ - LoadExpr (CF_FORCECHAR, Expr); + /* Get first expr */ + LoadExpr (CF_FORCECHAR, Expr); - /* For each expression jump to TrueLab if true. Beware: If we - * had && operators, the jump is already in place! - */ - if (!BoolOp) { - g_truejump (CF_NONE, TrueLab); - } + /* For each expression jump to TrueLab if true. Beware: If we + ** had && operators, the jump is already in place! + */ + if (!BoolOp) { + g_truejump (CF_NONE, TrueLab); + } - /* Remember that we had a boolean op */ - BoolOp = 1; + /* Remember that we had a boolean op */ + BoolOp = 1; - /* while there's more expr */ - while (CurTok.Tok == TOK_BOOL_OR) { + /* while there's more expr */ + while (CurTok.Tok == TOK_BOOL_OR) { - /* skip the || */ - NextToken (); + /* skip the || */ + NextToken (); - /* Get a subexpr */ - AndOp = 0; - hieAnd (&Expr2, TrueLab, &AndOp); - if (!ED_IsTested (&Expr2)) { - ED_MarkForTest (&Expr2); - } - LoadExpr (CF_FORCECHAR, &Expr2); + /* Get a subexpr */ + AndOp = 0; + hieAnd (&Expr2, TrueLab, &AndOp); + if (!ED_IsTested (&Expr2)) { + ED_MarkForTest (&Expr2); + } + LoadExpr (CF_FORCECHAR, &Expr2); - /* If there is more to come, add shortcut boolean eval. */ - g_truejump (CF_NONE, TrueLab); + /* If there is more to come, add shortcut boolean eval. */ + g_truejump (CF_NONE, TrueLab); - } + } - /* The result is an rvalue in primary */ - ED_MakeRValExpr (Expr); - ED_TestDone (Expr); /* Condition codes are set */ + /* The result is an rvalue in primary */ + ED_MakeRValExpr (Expr); + ED_TestDone (Expr); /* Condition codes are set */ } /* If we really had boolean ops, generate the end sequence */ if (BoolOp) { - DoneLab = GetLocalLabel (); - g_getimmed (CF_INT | CF_CONST, 0, 0); /* Load FALSE */ - g_falsejump (CF_NONE, DoneLab); - g_defcodelabel (TrueLab); - g_getimmed (CF_INT | CF_CONST, 1, 0); /* Load TRUE */ - g_defcodelabel (DoneLab); + DoneLab = GetLocalLabel (); + g_getimmed (CF_INT | CF_CONST, 0, 0); /* Load FALSE */ + g_falsejump (CF_NONE, DoneLab); + g_defcodelabel (TrueLab); + g_getimmed (CF_INT | CF_CONST, 1, 0); /* Load TRUE */ + g_defcodelabel (DoneLab); } } @@ -2493,133 +3022,139 @@ static void hieOr (ExprDesc *Expr) static void hieQuest (ExprDesc* Expr) /* Parse the ternary operator */ { - int labf; - int labt; - ExprDesc Expr2; /* Expression 2 */ - ExprDesc Expr3; /* Expression 3 */ + int FalseLab; + int TrueLab; + CodeMark TrueCodeEnd; + ExprDesc Expr2; /* Expression 2 */ + ExprDesc Expr3; /* Expression 3 */ int Expr2IsNULL; /* Expression 2 is a NULL pointer */ int Expr3IsNULL; /* Expression 3 is a NULL pointer */ - type* ResultType; /* Type of result */ + Type* ResultType; /* Type of result */ /* Call the lower level eval routine */ if (Preprocessing) { - hieOrPP (Expr); + ExprWithCheck (hieOrPP, Expr); } else { - hieOr (Expr); + ExprWithCheck (hieOr, Expr); } /* Check if it's a ternary expression */ if (CurTok.Tok == TOK_QUEST) { - NextToken (); - if (!ED_IsTested (Expr)) { - /* Condition codes not set, request a test */ - ED_MarkForTest (Expr); - } - LoadExpr (CF_NONE, Expr); - labf = GetLocalLabel (); - g_falsejump (CF_NONE, labf); - - /* Parse second expression. Remember for later if it is a NULL pointer - * expression, then load it into the primary. - */ + NextToken (); + if (!ED_IsTested (Expr)) { + /* Condition codes not set, request a test */ + ED_MarkForTest (Expr); + } + LoadExpr (CF_NONE, Expr); + FalseLab = GetLocalLabel (); + g_falsejump (CF_NONE, FalseLab); + + /* Parse second expression. Remember for later if it is a NULL pointer + ** expression, then load it into the primary. + */ ExprWithCheck (hie1, &Expr2); Expr2IsNULL = ED_IsNullPtr (&Expr2); if (!IsTypeVoid (Expr2.Type)) { /* Load it into the primary */ LoadExpr (CF_NONE, &Expr2); ED_MakeRValExpr (&Expr2); + Expr2.Type = PtrConversion (Expr2.Type); } - labt = GetLocalLabel (); - ConsumeColon (); - g_jump (labt); + + /* Remember the current code position */ + GetCodePos (&TrueCodeEnd); + + /* Jump around the evaluation of the third expression */ + TrueLab = GetLocalLabel (); + ConsumeColon (); + g_jump (TrueLab); /* Jump here if the first expression was false */ - g_defcodelabel (labf); + g_defcodelabel (FalseLab); - /* Parse second expression. Remember for later if it is a NULL pointer - * expression, then load it into the primary. - */ + /* Parse third expression. Remember for later if it is a NULL pointer + ** expression, then load it into the primary. + */ ExprWithCheck (hie1, &Expr3); Expr3IsNULL = ED_IsNullPtr (&Expr3); if (!IsTypeVoid (Expr3.Type)) { /* Load it into the primary */ LoadExpr (CF_NONE, &Expr3); ED_MakeRValExpr (&Expr3); + Expr3.Type = PtrConversion (Expr3.Type); } - /* Check if any conversions are needed, if so, do them. - * Conversion rules for ?: expression are: - * - if both expressions are int expressions, default promotion - * rules for ints apply. - * - if both expressions are pointers of the same type, the - * result of the expression is of this type. - * - if one of the expressions is a pointer and the other is - * a zero constant, the resulting type is that of the pointer - * type. - * - if both expressions are void expressions, the result is of - * type void. - * - all other cases are flagged by an error. - */ - if (IsClassInt (Expr2.Type) && IsClassInt (Expr3.Type)) { - - /* Get common type */ - ResultType = promoteint (Expr2.Type, Expr3.Type); - - /* Convert the third expression to this type if needed */ - TypeConversion (&Expr3, ResultType); - - /* Setup a new label so that the expr3 code will jump around - * the type cast code for expr2. - */ - labf = GetLocalLabel (); /* Get new label */ - g_jump (labf); /* Jump around code */ - - /* The jump for expr2 goes here */ - g_defcodelabel (labt); - - /* Create the typecast code for expr2 */ - TypeConversion (&Expr2, ResultType); - - /* Jump here around the typecase code. */ - g_defcodelabel (labf); - labt = 0; /* Mark other label as invalid */ - - } else if (IsClassPtr (Expr2.Type) && IsClassPtr (Expr3.Type)) { - /* Must point to same type */ - if (TypeCmp (Indirect (Expr2.Type), Indirect (Expr3.Type)) < TC_EQUAL) { - Error ("Incompatible pointer types"); - } - /* Result has the common type */ - ResultType = Expr2.Type; - } else if (IsClassPtr (Expr2.Type) && Expr3IsNULL) { - /* Result type is pointer, no cast needed */ - ResultType = Expr2.Type; - } else if (Expr2IsNULL && IsClassPtr (Expr3.Type)) { - /* Result type is pointer, no cast needed */ - ResultType = Expr3.Type; + /* Check if any conversions are needed, if so, do them. + ** Conversion rules for ?: expression are: + ** - if both expressions are int expressions, default promotion + ** rules for ints apply. + ** - if both expressions are pointers of the same type, the + ** result of the expression is of this type. + ** - if one of the expressions is a pointer and the other is + ** a zero constant, the resulting type is that of the pointer + ** type. + ** - if both expressions are void expressions, the result is of + ** type void. + ** - all other cases are flagged by an error. + */ + if (IsClassInt (Expr2.Type) && IsClassInt (Expr3.Type)) { + + CodeMark CvtCodeStart; + CodeMark CvtCodeEnd; + + + /* Get common type */ + ResultType = promoteint (Expr2.Type, Expr3.Type); + + /* Convert the third expression to this type if needed */ + TypeConversion (&Expr3, ResultType); + + /* Emit conversion code for the second expression, but remember + ** where it starts end ends. + */ + GetCodePos (&CvtCodeStart); + TypeConversion (&Expr2, ResultType); + GetCodePos (&CvtCodeEnd); + + /* If we had conversion code, move it to the right place */ + if (!CodeRangeIsEmpty (&CvtCodeStart, &CvtCodeEnd)) { + MoveCode (&CvtCodeStart, &CvtCodeEnd, &TrueCodeEnd); + } + + } else if (IsClassPtr (Expr2.Type) && IsClassPtr (Expr3.Type)) { + /* Must point to same type */ + if (TypeCmp (Indirect (Expr2.Type), Indirect (Expr3.Type)) < TC_EQUAL) { + Error ("Incompatible pointer types"); + } + /* Result has the common type */ + ResultType = Expr2.Type; + } else if (IsClassPtr (Expr2.Type) && Expr3IsNULL) { + /* Result type is pointer, no cast needed */ + ResultType = Expr2.Type; + } else if (Expr2IsNULL && IsClassPtr (Expr3.Type)) { + /* Result type is pointer, no cast needed */ + ResultType = Expr3.Type; } else if (IsTypeVoid (Expr2.Type) && IsTypeVoid (Expr3.Type)) { /* Result type is void */ ResultType = Expr3.Type; - } else { - Error ("Incompatible types"); - ResultType = Expr2.Type; /* Doesn't matter here */ - } + } else { + Error ("Incompatible types"); + ResultType = Expr2.Type; /* Doesn't matter here */ + } - /* If we don't have the label defined until now, do it */ - if (labt) { - g_defcodelabel (labt); - } + /* Define the final label */ + g_defcodelabel (TrueLab); - /* Setup the target expression */ - ED_MakeRValExpr (Expr); - Expr->Type = ResultType; + /* Setup the target expression */ + ED_MakeRValExpr (Expr); + Expr->Type = ResultType; } } -static void opeq (const GenDesc* Gen, ExprDesc* Expr) +static void opeq (const GenDesc* Gen, ExprDesc* Expr, const char* Op) /* Process "op=" operators. */ { ExprDesc Expr2; @@ -2629,16 +3164,21 @@ static void opeq (const GenDesc* Gen, ExprDesc* Expr) /* op= can only be used with lvalues */ if (!ED_IsLVal (Expr)) { - Error ("Invalid lvalue in assignment"); - return; + Error ("Invalid lvalue in assignment"); + return; + } + + /* The left side must not be const qualified */ + if (IsQualConst (Expr->Type)) { + Error ("Assignment to const"); } /* There must be an integer or pointer on the left side */ if (!IsClassInt (Expr->Type) && !IsTypePtr (Expr->Type)) { Error ("Invalid left operand type"); /* Continue. Wrong code will be generated, but the compiler won't - * break, so this is the best error recovery. - */ + ** break, so this is the best error recovery. + */ } /* Skip the operator token */ @@ -2659,49 +3199,70 @@ static void opeq (const GenDesc* Gen, ExprDesc* Expr) g_push (flags, 0); /* Evaluate the rhs */ - if (evalexpr (CF_NONE, hie1, &Expr2) == 0) { - /* The resulting value is a constant. If the generator has the NOPUSH - * flag set, don't push the lhs. - */ - if (Gen->Flags & GEN_NOPUSH) { - RemoveCode (&Mark); - } - if (MustScale) { - /* lhs is a pointer, scale rhs */ - Expr2.IVal *= CheckedSizeOf (Expr->Type+1); - } - - /* If the lhs is character sized, the operation may be later done - * with characters. - */ - if (CheckedSizeOf (Expr->Type) == SIZEOF_CHAR) { - flags |= CF_FORCECHAR; - } - - /* Special handling for add and sub - some sort of a hack, but short code */ - if (Gen->Func == g_add) { - g_inc (flags | CF_CONST, Expr2.IVal); - } else if (Gen->Func == g_sub) { - g_dec (flags | CF_CONST, Expr2.IVal); - } else { - Gen->Func (flags | CF_CONST, Expr2.IVal); - } + MarkedExprWithCheck (hie1, &Expr2); + + /* The rhs must be an integer (or a float, but we don't support that yet */ + if (!IsClassInt (Expr2.Type)) { + Error ("Invalid right operand for binary operator `%s'", Op); + /* Continue. Wrong code will be generated, but the compiler won't + ** break, so this is the best error recovery. + */ + } + + /* Check for a constant expression */ + if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) { + /* The resulting value is a constant. If the generator has the NOPUSH + ** flag set, don't push the lhs. + */ + if (Gen->Flags & GEN_NOPUSH) { + RemoveCode (&Mark); + } + if (MustScale) { + /* lhs is a pointer, scale rhs */ + Expr2.IVal *= CheckedSizeOf (Expr->Type+1); + } + + /* If the lhs is character sized, the operation may be later done + ** with characters. + */ + if (CheckedSizeOf (Expr->Type) == SIZEOF_CHAR) { + flags |= CF_FORCECHAR; + } + + /* Special handling for add and sub - some sort of a hack, but short code */ + if (Gen->Func == g_add) { + g_inc (flags | CF_CONST, Expr2.IVal); + } else if (Gen->Func == g_sub) { + g_dec (flags | CF_CONST, Expr2.IVal); + } else { + if (Expr2.IVal == 0) { + /* Check for div by zero/mod by zero */ + if (Gen->Func == g_div) { + Error ("Division by zero"); + } else if (Gen->Func == g_mod) { + Error ("Modulo operation with zero"); + } + } + Gen->Func (flags | CF_CONST, Expr2.IVal); + } } else { - /* rhs is not constant and already in the primary register */ - if (MustScale) { - /* lhs is a pointer, scale rhs */ - g_scale (TypeOf (Expr2.Type), CheckedSizeOf (Expr->Type+1)); - } - - /* If the lhs is character sized, the operation may be later done - * with characters. - */ - if (CheckedSizeOf (Expr->Type) == SIZEOF_CHAR) { - flags |= CF_FORCECHAR; - } - - /* Adjust the types of the operands if needed */ - Gen->Func (g_typeadjust (flags, TypeOf (Expr2.Type)), 0); + + /* rhs is not constant. Load into the primary */ + LoadExpr (CF_NONE, &Expr2); + if (MustScale) { + /* lhs is a pointer, scale rhs */ + g_scale (TypeOf (Expr2.Type), CheckedSizeOf (Expr->Type+1)); + } + + /* If the lhs is character sized, the operation may be later done + ** with characters. + */ + if (CheckedSizeOf (Expr->Type) == SIZEOF_CHAR) { + flags |= CF_FORCECHAR; + } + + /* Adjust the types of the operands if needed */ + Gen->Func (g_typeadjust (flags, TypeOf (Expr2.Type)), 0); } Store (Expr, 0); ED_MakeRValExpr (Expr); @@ -2709,7 +3270,7 @@ static void opeq (const GenDesc* Gen, ExprDesc* Expr) -static void addsubeq (const GenDesc* Gen, ExprDesc *Expr) +static void addsubeq (const GenDesc* Gen, ExprDesc *Expr, const char* Op) /* Process the += and -= operators */ { ExprDesc Expr2; @@ -2720,23 +3281,28 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *Expr) /* We're currently only able to handle some adressing modes */ if (ED_GetLoc (Expr) == E_LOC_EXPR || ED_GetLoc (Expr) == E_LOC_PRIMARY) { - /* Use generic routine */ - opeq (Gen, Expr); - return; + /* Use generic routine */ + opeq (Gen, Expr, Op); + return; } /* We must have an lvalue */ if (ED_IsRVal (Expr)) { - Error ("Invalid lvalue in assignment"); - return; + Error ("Invalid lvalue in assignment"); + return; + } + + /* The left side must not be const qualified */ + if (IsQualConst (Expr->Type)) { + Error ("Assignment to const"); } /* There must be an integer or pointer on the left side */ if (!IsClassInt (Expr->Type) && !IsTypePtr (Expr->Type)) { Error ("Invalid left operand type"); /* Continue. Wrong code will be generated, but the compiler won't - * break, so this is the best error recovery. - */ + ** break, so this is the best error recovery. + */ } /* Skip the operator */ @@ -2749,27 +3315,35 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *Expr) lflags = 0; rflags = 0; - /* Evaluate the rhs */ + /* Evaluate the rhs. We expect an integer here, since float is not + ** supported + */ hie1 (&Expr2); + if (!IsClassInt (Expr2.Type)) { + Error ("Invalid right operand for binary operator `%s'", Op); + /* Continue. Wrong code will be generated, but the compiler won't + ** break, so this is the best error recovery. + */ + } if (ED_IsConstAbs (&Expr2)) { - /* The resulting value is a constant. Scale it. */ + /* The resulting value is a constant. Scale it. */ if (MustScale) { Expr2.IVal *= CheckedSizeOf (Indirect (Expr->Type)); } - rflags |= CF_CONST; - lflags |= CF_CONST; + rflags |= CF_CONST; + lflags |= CF_CONST; } else { - /* Not constant, load into the primary */ + /* Not constant, load into the primary */ LoadExpr (CF_NONE, &Expr2); - if (MustScale) { - /* lhs is a pointer, scale rhs */ - g_scale (TypeOf (Expr2.Type), CheckedSizeOf (Indirect (Expr->Type))); - } + if (MustScale) { + /* lhs is a pointer, scale rhs */ + g_scale (TypeOf (Expr2.Type), CheckedSizeOf (Indirect (Expr->Type))); + } } /* Setup the code generator flags */ - lflags |= TypeOf (Expr->Type) | CF_FORCECHAR; - rflags |= TypeOf (Expr2.Type); + lflags |= TypeOf (Expr->Type) | GlobalModeFlags (Expr) | CF_FORCECHAR; + rflags |= TypeOf (Expr2.Type) | CF_FORCECHAR; /* Convert the type of the lhs to that of the rhs */ g_typecast (lflags, rflags); @@ -2779,7 +3353,6 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *Expr) case E_LOC_ABS: /* Absolute: numeric address or const */ - lflags |= CF_ABSOLUTE; if (Gen->Tok == TOK_PLUS_ASSIGN) { g_addeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal); } else { @@ -2789,7 +3362,6 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *Expr) case E_LOC_GLOBAL: /* Global variable */ - lflags |= CF_EXTERNAL; if (Gen->Tok == TOK_PLUS_ASSIGN) { g_addeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal); } else { @@ -2800,7 +3372,6 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *Expr) case E_LOC_STATIC: case E_LOC_LITERAL: /* Static variable or literal in the literal pool */ - lflags |= CF_STATIC; if (Gen->Tok == TOK_PLUS_ASSIGN) { g_addeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal); } else { @@ -2810,7 +3381,6 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *Expr) case E_LOC_REGISTER: /* Register variable */ - lflags |= CF_REGVAR; if (Gen->Tok == TOK_PLUS_ASSIGN) { g_addeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal); } else { @@ -2843,52 +3413,52 @@ void hie1 (ExprDesc* Expr) hieQuest (Expr); switch (CurTok.Tok) { - case TOK_ASSIGN: + case TOK_ASSIGN: Assignment (Expr); - break; + break; - case TOK_PLUS_ASSIGN: - addsubeq (&GenPASGN, Expr); - break; + case TOK_PLUS_ASSIGN: + addsubeq (&GenPASGN, Expr, "+="); + break; - case TOK_MINUS_ASSIGN: - addsubeq (&GenSASGN, Expr); - break; + case TOK_MINUS_ASSIGN: + addsubeq (&GenSASGN, Expr, "-="); + break; - case TOK_MUL_ASSIGN: - opeq (&GenMASGN, Expr); - break; + case TOK_MUL_ASSIGN: + opeq (&GenMASGN, Expr, "*="); + break; - case TOK_DIV_ASSIGN: - opeq (&GenDASGN, Expr); - break; + case TOK_DIV_ASSIGN: + opeq (&GenDASGN, Expr, "/="); + break; - case TOK_MOD_ASSIGN: - opeq (&GenMOASGN, Expr); - break; + case TOK_MOD_ASSIGN: + opeq (&GenMOASGN, Expr, "%="); + break; - case TOK_SHL_ASSIGN: - opeq (&GenSLASGN, Expr); - break; + case TOK_SHL_ASSIGN: + opeq (&GenSLASGN, Expr, "<<="); + break; - case TOK_SHR_ASSIGN: - opeq (&GenSRASGN, Expr); - break; + case TOK_SHR_ASSIGN: + opeq (&GenSRASGN, Expr, ">>="); + break; - case TOK_AND_ASSIGN: - opeq (&GenAASGN, Expr); - break; + case TOK_AND_ASSIGN: + opeq (&GenAASGN, Expr, "&="); + break; - case TOK_XOR_ASSIGN: - opeq (&GenXOASGN, Expr); - break; + case TOK_XOR_ASSIGN: + opeq (&GenXOASGN, Expr, "^="); + break; - case TOK_OR_ASSIGN: - opeq (&GenOASGN, Expr); - break; + case TOK_OR_ASSIGN: + opeq (&GenOASGN, Expr, "|="); + break; - default: - break; + default: + break; } } @@ -2899,8 +3469,8 @@ void hie0 (ExprDesc *Expr) { hie1 (Expr); while (CurTok.Tok == TOK_COMMA) { - NextToken (); - hie1 (Expr); + NextToken (); + hie1 (Expr); } } @@ -2908,22 +3478,22 @@ void hie0 (ExprDesc *Expr) 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 Expr struct. If the - * result is not constant, LoadExpr is called to bring the value into the - * primary register and 1 is returned. - */ +** constant, 0 is returned and the value is put in the Expr struct. If the +** result is not constant, LoadExpr is called to bring the value into the +** primary register and 1 is returned. +*/ { /* Evaluate */ ExprWithCheck (Func, Expr); /* Check for a constant expression */ if (ED_IsConstAbs (Expr)) { - /* Constant expression */ - return 0; + /* Constant expression */ + return 0; } else { - /* Not constant, load into the primary */ + /* Not constant, load into the primary */ LoadExpr (Flags, Expr); - return 1; + return 1; } } @@ -2940,16 +3510,16 @@ void Expression0 (ExprDesc* Expr) void ConstExpr (void (*Func) (ExprDesc*), ExprDesc* Expr) /* Will evaluate an expression via the given function. If the result is not - * a constant of some sort, a diagnostic will be printed, and the value is - * replaced by a constant one to make sure there are no internal errors that - * result from this input error. - */ +** a constant of some sort, a diagnostic will be printed, and the value is +** replaced by a constant one to make sure there are no internal errors that +** result from this input error. +*/ { ExprWithCheck (Func, Expr); if (!ED_IsConst (Expr)) { - Error ("Constant expression expected"); - /* To avoid any compiler errors, make the expression a valid const */ - ED_MakeConstAbsInt (Expr, 1); + Error ("Constant expression expected"); + /* To avoid any compiler errors, make the expression a valid const */ + ED_MakeConstAbsInt (Expr, 1); } } @@ -2957,16 +3527,16 @@ void ConstExpr (void (*Func) (ExprDesc*), ExprDesc* Expr) void BoolExpr (void (*Func) (ExprDesc*), ExprDesc* Expr) /* Will evaluate an expression via the given function. If the result is not - * something that may be evaluated in a boolean context, a diagnostic will be - * printed, and the value is replaced by a constant one to make sure there - * are no internal errors that result from this input error. - */ +** something that may be evaluated in a boolean context, a diagnostic will be +** printed, and the value is replaced by a constant one to make sure there +** are no internal errors that result from this input error. +*/ { ExprWithCheck (Func, Expr); if (!ED_IsBool (Expr)) { - Error ("Boolean expression expected"); - /* To avoid any compiler errors, make the expression a valid int */ - ED_MakeConstAbsInt (Expr, 1); + Error ("Boolean expression expected"); + /* To avoid any compiler errors, make the expression a valid int */ + ED_MakeConstAbsInt (Expr, 1); } } @@ -2974,18 +3544,15 @@ void BoolExpr (void (*Func) (ExprDesc*), ExprDesc* Expr) void ConstAbsIntExpr (void (*Func) (ExprDesc*), ExprDesc* Expr) /* Will evaluate an expression via the given function. If the result is not - * a constant numeric integer value, a diagnostic will be printed, and the - * value is replaced by a constant one to make sure there are no internal - * errors that result from this input error. - */ +** a constant numeric integer value, a diagnostic will be printed, and the +** value is replaced by a constant one to make sure there are no internal +** errors that result from this input error. +*/ { ExprWithCheck (Func, Expr); if (!ED_IsConstAbsInt (Expr)) { - Error ("Constant integer expression expected"); - /* To avoid any compiler errors, make the expression a valid const */ - ED_MakeConstAbsInt (Expr, 1); + Error ("Constant integer expression expected"); + /* To avoid any compiler errors, make the expression a valid const */ + ED_MakeConstAbsInt (Expr, 1); } } - - -