]> git.sur5r.net Git - cc65/blob - src/cc65/expr.c
e5c1a17b91b5b0cef39448c040eb98cbf58e295e
[cc65] / src / cc65 / expr.c
1 /* expr.c
2 **
3 ** 1998-06-21, Ullrich von Bassewitz
4 ** 2015-06-26, Greg King
5 */
6
7
8
9 #include <stdio.h>
10 #include <stdlib.h>
11
12 /* common */
13 #include "check.h"
14 #include "debugflag.h"
15 #include "xmalloc.h"
16
17 /* cc65 */
18 #include "asmcode.h"
19 #include "asmlabel.h"
20 #include "asmstmt.h"
21 #include "assignment.h"
22 #include "codegen.h"
23 #include "declare.h"
24 #include "error.h"
25 #include "funcdesc.h"
26 #include "function.h"
27 #include "global.h"
28 #include "litpool.h"
29 #include "loadexpr.h"
30 #include "macrotab.h"
31 #include "preproc.h"
32 #include "scanner.h"
33 #include "shiftexpr.h"
34 #include "stackptr.h"
35 #include "standard.h"
36 #include "stdfunc.h"
37 #include "symtab.h"
38 #include "typecmp.h"
39 #include "typeconv.h"
40 #include "expr.h"
41
42
43
44 /*****************************************************************************/
45 /*                                   Data                                    */
46 /*****************************************************************************/
47
48
49
50 /* Generator attributes */
51 #define GEN_NOPUSH      0x01            /* Don't push lhs */
52 #define GEN_COMM        0x02            /* Operator is commutative */
53 #define GEN_NOFUNC      0x04            /* Not allowed for function pointers */
54
55 /* Map a generator function and its attributes to a token */
56 typedef struct {
57     token_t       Tok;                  /* Token to map to */
58     unsigned      Flags;                /* Flags for generator function */
59     void          (*Func) (unsigned, unsigned long);    /* Generator func */
60 } GenDesc;
61
62 /* Descriptors for the operations */
63 static GenDesc GenPASGN  = { TOK_PLUS_ASSIGN,   GEN_NOPUSH,     g_add };
64 static GenDesc GenSASGN  = { TOK_MINUS_ASSIGN,  GEN_NOPUSH,     g_sub };
65 static GenDesc GenMASGN  = { TOK_MUL_ASSIGN,    GEN_NOPUSH,     g_mul };
66 static GenDesc GenDASGN  = { TOK_DIV_ASSIGN,    GEN_NOPUSH,     g_div };
67 static GenDesc GenMOASGN = { TOK_MOD_ASSIGN,    GEN_NOPUSH,     g_mod };
68 static GenDesc GenSLASGN = { TOK_SHL_ASSIGN,    GEN_NOPUSH,     g_asl };
69 static GenDesc GenSRASGN = { TOK_SHR_ASSIGN,    GEN_NOPUSH,     g_asr };
70 static GenDesc GenAASGN  = { TOK_AND_ASSIGN,    GEN_NOPUSH,     g_and };
71 static GenDesc GenXOASGN = { TOK_XOR_ASSIGN,    GEN_NOPUSH,     g_xor };
72 static GenDesc GenOASGN  = { TOK_OR_ASSIGN,     GEN_NOPUSH,     g_or  };
73
74
75
76 /*****************************************************************************/
77 /*                             Helper functions                              */
78 /*****************************************************************************/
79
80
81
82 static unsigned GlobalModeFlags (const ExprDesc* Expr)
83 /* Return the addressing mode flags for the given expression */
84 {
85     switch (ED_GetLoc (Expr)) {
86         case E_LOC_ABS:         return CF_ABSOLUTE;
87         case E_LOC_GLOBAL:      return CF_EXTERNAL;
88         case E_LOC_STATIC:      return CF_STATIC;
89         case E_LOC_REGISTER:    return CF_REGVAR;
90         case E_LOC_STACK:       return CF_NONE;
91         case E_LOC_PRIMARY:     return CF_NONE;
92         case E_LOC_EXPR:        return CF_NONE;
93         case E_LOC_LITERAL:     return CF_STATIC;       /* Same as static */
94         default:
95             Internal ("GlobalModeFlags: Invalid location flags value: 0x%04X", Expr->Flags);
96             /* NOTREACHED */
97             return 0;
98     }
99 }
100
101
102
103 void ExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr)
104 /* Call an expression function with checks. */
105 {
106     /* Remember the stack pointer */
107     int OldSP = StackPtr;
108
109     /* Call the expression function */
110     (*Func) (Expr);
111
112     /* Do some checks to see if code generation is still consistent */
113     if (StackPtr != OldSP) {
114         if (Debug) {
115             Error ("Code generation messed up: "
116                    "StackPtr is %d, should be %d",
117                    StackPtr, OldSP);
118         } else {
119             Internal ("Code generation messed up: "
120                       "StackPtr is %d, should be %d",
121                       StackPtr, OldSP);
122         }
123     }
124 }
125
126
127
128 void MarkedExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr)
129 /* Call an expression function with checks and record start and end of the
130 ** generated code.
131 */
132 {
133     CodeMark Start, End;
134     GetCodePos (&Start);
135     ExprWithCheck (Func, Expr);
136     GetCodePos (&End);
137     ED_SetCodeRange (Expr, &Start, &End);
138 }
139
140
141
142 static Type* promoteint (Type* lhst, Type* rhst)
143 /* In an expression with two ints, return the type of the result */
144 {
145     /* Rules for integer types:
146     **   - If one of the values is a long, the result is long.
147     **   - If one of the values is unsigned, the result is also unsigned.
148     **   - Otherwise the result is an int.
149     */
150     if (IsTypeLong (lhst) || IsTypeLong (rhst)) {
151         if (IsSignUnsigned (lhst) || IsSignUnsigned (rhst)) {
152             return type_ulong;
153         } else {
154             return type_long;
155         }
156     } else {
157         if (IsSignUnsigned (lhst) || IsSignUnsigned (rhst)) {
158             return type_uint;
159         } else {
160             return type_int;
161         }
162     }
163 }
164
165
166
167 static unsigned typeadjust (ExprDesc* lhs, ExprDesc* rhs, int NoPush)
168 /* Adjust the two values for a binary operation. lhs is expected on stack or
169 ** to be constant, rhs is expected to be in the primary register or constant.
170 ** The function will put the type of the result into lhs and return the
171 ** code generator flags for the operation.
172 ** If NoPush is given, it is assumed that the operation does not expect the lhs
173 ** to be on stack, and that lhs is in a register instead.
174 ** Beware: The function does only accept int types.
175 */
176 {
177     unsigned ltype, rtype;
178     unsigned flags;
179
180     /* Get the type strings */
181     Type* lhst = lhs->Type;
182     Type* rhst = rhs->Type;
183
184     /* Generate type adjustment code if needed */
185     ltype = TypeOf (lhst);
186     if (ED_IsLocAbs (lhs)) {
187         ltype |= CF_CONST;
188     }
189     if (NoPush) {
190         /* Value is in primary register*/
191         ltype |= CF_REG;
192     }
193     rtype = TypeOf (rhst);
194     if (ED_IsLocAbs (rhs)) {
195         rtype |= CF_CONST;
196     }
197     flags = g_typeadjust (ltype, rtype);
198
199     /* Set the type of the result */
200     lhs->Type = promoteint (lhst, rhst);
201
202     /* Return the code generator flags */
203     return flags;
204 }
205
206
207
208 static const GenDesc* FindGen (token_t Tok, const GenDesc* Table)
209 /* Find a token in a generator table */
210 {
211     while (Table->Tok != TOK_INVALID) {
212         if (Table->Tok == Tok) {
213             return Table;
214         }
215         ++Table;
216     }
217     return 0;
218 }
219
220
221
222 static int TypeSpecAhead (void)
223 /* Return true if some sort of type is waiting (helper for cast and sizeof()
224 ** in hie10).
225 */
226 {
227     SymEntry* Entry;
228
229     /* There's a type waiting if:
230     **
231     ** We have an opening paren, and
232     **   a.  the next token is a type, or
233     **   b.  the next token is a type qualifier, or
234     **   c.  the next token is a typedef'd type
235     */
236     return CurTok.Tok == TOK_LPAREN && (
237            TokIsType (&NextTok)                         ||
238            TokIsTypeQual (&NextTok)                     ||
239            (NextTok.Tok  == TOK_IDENT                   &&
240            (Entry = FindSym (NextTok.Ident)) != 0       &&
241            SymIsTypeDef (Entry)));
242 }
243
244
245
246 void PushAddr (const ExprDesc* Expr)
247 /* If the expression contains an address that was somehow evaluated,
248 ** push this address on the stack. This is a helper function for all
249 ** sorts of implicit or explicit assignment functions where the lvalue
250 ** must be saved if it's not constant, before evaluating the rhs.
251 */
252 {
253     /* Get the address on stack if needed */
254     if (ED_IsLocExpr (Expr)) {
255         /* Push the address (always a pointer) */
256         g_push (CF_PTR, 0);
257     }
258 }
259
260
261
262 static void WarnConstCompareResult (void)
263 /* If the result of a comparison is constant, this is suspicious when not in
264 ** preprocessor mode.
265 */
266 {
267     if (!Preprocessing && IS_Get (&WarnConstComparison) != 0) {
268         Warning ("Result of comparison is constant");
269     }
270 }
271
272
273
274 /*****************************************************************************/
275 /*                                   code                                    */
276 /*****************************************************************************/
277
278
279
280 static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall)
281 /* Parse a function parameter list and pass the parameters to the called
282 ** function. Depending on several criteria this may be done by just pushing
283 ** each parameter separately, or creating the parameter frame once and then
284 ** storing into this frame.
285 ** The function returns the size of the parameters pushed.
286 */
287 {
288     ExprDesc Expr;
289
290     /* Initialize variables */
291     SymEntry* Param       = 0;  /* Keep gcc silent */
292     unsigned  ParamSize   = 0;  /* Size of parameters pushed */
293     unsigned  ParamCount  = 0;  /* Number of parameters pushed */
294     unsigned  FrameSize   = 0;  /* Size of parameter frame */
295     unsigned  FrameParams = 0;  /* Number of params in frame */
296     int       FrameOffs   = 0;  /* Offset into parameter frame */
297     int       Ellipsis    = 0;  /* Function is variadic */
298
299     /* As an optimization, we may allocate the complete parameter frame at
300     ** once instead of pushing each parameter as it comes. We may do that,
301     ** if...
302     **
303     **  - optimizations that increase code size are enabled (allocating the
304     **    stack frame at once gives usually larger code).
305     **  - we have more than one parameter to push (don't count the last param
306     **    for __fastcall__ functions).
307     **
308     ** The FrameSize variable will contain a value > 0 if storing into a frame
309     ** (instead of pushing) is enabled.
310     **
311     */
312     if (IS_Get (&CodeSizeFactor) >= 200) {
313
314         /* Calculate the number and size of the parameters */
315         FrameParams = Func->ParamCount;
316         FrameSize   = Func->ParamSize;
317         if (FrameParams > 0 && IsFastcall) {
318             /* Last parameter is not pushed */
319             FrameSize -= CheckedSizeOf (Func->LastParam->Type);
320             --FrameParams;
321         }
322
323         /* Do we have more than one parameter in the frame? */
324         if (FrameParams > 1) {
325             /* Okeydokey, setup the frame */
326             FrameOffs = StackPtr;
327             g_space (FrameSize);
328             StackPtr -= FrameSize;
329         } else {
330             /* Don't use a preallocated frame */
331             FrameSize = 0;
332         }
333     }
334
335     /* Parse the actual parameter list */
336     while (CurTok.Tok != TOK_RPAREN) {
337
338         unsigned Flags;
339
340         /* Count arguments */
341         ++ParamCount;
342
343         /* Fetch the pointer to the next argument, check for too many args */
344         if (ParamCount <= Func->ParamCount) {
345             /* Beware: If there are parameters with identical names, they
346             ** cannot go into the same symbol table, which means that in this
347             ** case of errorneous input, the number of nodes in the symbol
348             ** table and ParamCount are NOT equal. We have to handle this case
349             ** below to avoid segmentation violations. Since we know that this
350             ** problem can only occur if there is more than one parameter,
351             ** we will just use the last one.
352             */
353             if (ParamCount == 1) {
354                 /* First argument */
355                 Param = Func->SymTab->SymHead;
356             } else if (Param->NextSym != 0) {
357                 /* Next argument */
358                 Param = Param->NextSym;
359                 CHECK ((Param->Flags & SC_PARAM) != 0);
360             }
361         } else if (!Ellipsis) {
362             /* Too many arguments. Do we have an open param list? */
363             if ((Func->Flags & FD_VARIADIC) == 0) {
364                 /* End of param list reached, no ellipsis */
365                 Error ("Too many arguments in function call");
366             }
367             /* Assume an ellipsis even in case of errors to avoid an error
368             ** message for each other argument.
369             */
370             Ellipsis = 1;
371         }
372
373         /* Evaluate the parameter expression */
374         hie1 (&Expr);
375
376         /* If we don't have an argument spec, accept anything, otherwise
377         ** convert the actual argument to the type needed.
378         */
379         Flags = CF_NONE;
380         if (!Ellipsis) {
381
382             /* Convert the argument to the parameter type if needed */
383             TypeConversion (&Expr, Param->Type);
384
385             /* If we have a prototype, chars may be pushed as chars */
386             Flags |= CF_FORCECHAR;
387
388         } else {
389
390             /* No prototype available. Convert array to "pointer to first
391             ** element", and function to "pointer to function".
392             */
393             Expr.Type = PtrConversion (Expr.Type);
394
395         }
396
397         /* Load the value into the primary if it is not already there */
398         LoadExpr (Flags, &Expr);
399
400         /* Use the type of the argument for the push */
401         Flags |= TypeOf (Expr.Type);
402
403         /* If this is a fastcall function, don't push the last argument */
404         if (ParamCount != Func->ParamCount || !IsFastcall) {
405             unsigned ArgSize = sizeofarg (Flags);
406             if (FrameSize > 0) {
407                 /* We have the space already allocated, store in the frame.
408                 ** Because of invalid type conversions (that have produced an
409                 ** error before), we can end up here with a non-aligned stack
410                 ** frame. Since no output will be generated anyway, handle
411                 ** these cases gracefully instead of doing a CHECK.
412                 */
413                 if (FrameSize >= ArgSize) {
414                     FrameSize -= ArgSize;
415                 } else {
416                     FrameSize = 0;
417                 }
418                 FrameOffs -= ArgSize;
419                 /* Store */
420                 g_putlocal (Flags | CF_NOKEEP, FrameOffs, Expr.IVal);
421             } else {
422                 /* Push the argument */
423                 g_push (Flags, Expr.IVal);
424             }
425
426             /* Calculate total parameter size */
427             ParamSize += ArgSize;
428         }
429
430         /* Check for end of argument list */
431         if (CurTok.Tok != TOK_COMMA) {
432             break;
433         }
434         NextToken ();
435     }
436
437     /* Check if we had enough parameters */
438     if (ParamCount < Func->ParamCount) {
439         Error ("Too few arguments in function call");
440     }
441
442     /* The function returns the size of all parameters pushed onto the stack.
443     ** However, if there are parameters missing (which is an error and was
444     ** flagged by the compiler) AND a stack frame was preallocated above,
445     ** we would loose track of the stackpointer and generate an internal error
446     ** later. So we correct the value by the parameters that should have been
447     ** pushed to avoid an internal compiler error. Since an error was
448     ** generated before, no code will be output anyway.
449     */
450     return ParamSize + FrameSize;
451 }
452
453
454
455 static void FunctionCall (ExprDesc* Expr)
456 /* Perform a function call. */
457 {
458     FuncDesc*     Func;           /* Function descriptor */
459     int           IsFuncPtr;      /* Flag */
460     unsigned      ParamSize;      /* Number of parameter bytes */
461     CodeMark      Mark;
462     int           PtrOffs = 0;    /* Offset of function pointer on stack */
463     int           IsFastcall = 0; /* True if it's a fast-call function */
464     int           PtrOnStack = 0; /* True if a pointer copy is on stack */
465
466     /* Skip the left paren */
467     NextToken ();
468
469     /* Get a pointer to the function descriptor from the type string */
470     Func = GetFuncDesc (Expr->Type);
471
472     /* Handle function pointers transparently */
473     IsFuncPtr = IsTypeFuncPtr (Expr->Type);
474     if (IsFuncPtr) {
475         /* Check whether it's a fastcall function that has parameters */
476         IsFastcall = (Func->Flags & FD_VARIADIC) == 0 && Func->ParamCount > 0 &&
477             (AutoCDecl ?
478              IsQualFastcall (Expr->Type + 1) :
479              !IsQualCDecl (Expr->Type + 1));
480
481         /* Things may be difficult, depending on where the function pointer
482         ** resides. If the function pointer is an expression of some sort
483         ** (not a local or global variable), we have to evaluate this
484         ** expression now and save the result for later. Since calls to
485         ** function pointers may be nested, we must save it onto the stack.
486         ** For fastcall functions we do also need to place a copy of the
487         ** pointer on stack, since we cannot use a/x.
488         */
489         PtrOnStack = IsFastcall || !ED_IsConst (Expr);
490         if (PtrOnStack) {
491
492             /* Not a global or local variable, or a fastcall function. Load
493             ** the pointer into the primary and mark it as an expression.
494             */
495             LoadExpr (CF_NONE, Expr);
496             ED_MakeRValExpr (Expr);
497
498             /* Remember the code position */
499             GetCodePos (&Mark);
500
501             /* Push the pointer onto the stack and remember the offset */
502             g_push (CF_PTR, 0);
503             PtrOffs = StackPtr;
504         }
505
506     } else {
507         /* Check function attributes */
508         if (Expr->Sym && SymHasAttr (Expr->Sym, atNoReturn)) {
509             /* For now, handle as if a return statement was encountered */
510             F_ReturnFound (CurrentFunc);
511         }
512
513         /* Check for known standard functions and inline them */
514         if (Expr->Name != 0) {
515             int StdFunc = FindStdFunc ((const char*) Expr->Name);
516             if (StdFunc >= 0) {
517                 /* Inline this function */
518                 HandleStdFunc (StdFunc, Func, Expr);
519                 return;
520             }
521         }
522
523         /* If we didn't inline the function, get fastcall info */
524         IsFastcall = (Func->Flags & FD_VARIADIC) == 0 &&
525             (AutoCDecl ?
526              IsQualFastcall (Expr->Type) :
527              !IsQualCDecl (Expr->Type));
528     }
529
530     /* Parse the parameter list */
531     ParamSize = FunctionParamList (Func, IsFastcall);
532
533     /* We need the closing paren here */
534     ConsumeRParen ();
535
536     /* Special handling for function pointers */
537     if (IsFuncPtr) {
538
539         /* If the function is not a fastcall function, load the pointer to
540         ** the function into the primary.
541         */
542         if (!IsFastcall) {
543
544             /* Not a fastcall function - we may use the primary */
545             if (PtrOnStack) {
546                 /* If we have no parameters, the pointer is still in the
547                 ** primary. Remove the code to push it and correct the
548                 ** stack pointer.
549                 */
550                 if (ParamSize == 0) {
551                     RemoveCode (&Mark);
552                     PtrOnStack = 0;
553                 } else {
554                     /* Load from the saved copy */
555                     g_getlocal (CF_PTR, PtrOffs);
556                 }
557             } else {
558                 /* Load from original location */
559                 LoadExpr (CF_NONE, Expr);
560             }
561
562             /* Call the function */
563             g_callind (TypeOf (Expr->Type+1), ParamSize, PtrOffs);
564
565         } else {
566
567             /* Fastcall function. We cannot use the primary for the function
568             ** pointer and must therefore use an offset to the stack location.
569             ** Since fastcall functions may never be variadic, we can use the
570             ** index register for this purpose.
571             */
572             g_callind (CF_LOCAL, ParamSize, PtrOffs);
573         }
574
575         /* If we have a pointer on stack, remove it */
576         if (PtrOnStack) {
577             g_drop (SIZEOF_PTR);
578             pop (CF_PTR);
579         }
580
581         /* Skip T_PTR */
582         ++Expr->Type;
583
584     } else {
585
586         /* Normal function */
587         g_call (TypeOf (Expr->Type), (const char*) Expr->Name, ParamSize);
588
589     }
590
591     /* The function result is an rvalue in the primary register */
592     ED_MakeRValExpr (Expr);
593     Expr->Type = GetFuncReturn (Expr->Type);
594 }
595
596
597
598 static void Primary (ExprDesc* E)
599 /* This is the lowest level of the expression parser. */
600 {
601     SymEntry* Sym;
602
603     /* Initialize fields in the expression stucture */
604     ED_Init (E);
605
606     /* Character and integer constants. */
607     if (CurTok.Tok == TOK_ICONST || CurTok.Tok == TOK_CCONST) {
608         E->IVal  = CurTok.IVal;
609         E->Flags = E_LOC_ABS | E_RTYPE_RVAL;
610         E->Type  = CurTok.Type;
611         NextToken ();
612         return;
613     }
614
615     /* Floating point constant */
616     if (CurTok.Tok == TOK_FCONST) {
617         E->FVal  = CurTok.FVal;
618         E->Flags = E_LOC_ABS | E_RTYPE_RVAL;
619         E->Type  = CurTok.Type;
620         NextToken ();
621         return;
622     }
623
624     /* Process parenthesized subexpression by calling the whole parser
625     ** recursively.
626     */
627     if (CurTok.Tok == TOK_LPAREN) {
628         NextToken ();
629         hie0 (E);
630         ConsumeRParen ();
631         return;
632     }
633
634     /* If we run into an identifier in preprocessing mode, we assume that this
635     ** is an undefined macro and replace it by a constant value of zero.
636     */
637     if (Preprocessing && CurTok.Tok == TOK_IDENT) {
638         NextToken ();
639         ED_MakeConstAbsInt (E, 0);
640         return;
641     }
642
643     /* All others may only be used if the expression evaluation is not called
644     ** recursively by the preprocessor.
645     */
646     if (Preprocessing) {
647         /* Illegal expression in PP mode */
648         Error ("Preprocessor expression expected");
649         ED_MakeConstAbsInt (E, 1);
650         return;
651     }
652
653     switch (CurTok.Tok) {
654
655         case TOK_IDENT:
656             /* Identifier. Get a pointer to the symbol table entry */
657             Sym = E->Sym = FindSym (CurTok.Ident);
658
659             /* Is the symbol known? */
660             if (Sym) {
661
662                 /* We found the symbol - skip the name token */
663                 NextToken ();
664
665                 /* Check for illegal symbol types */
666                 CHECK ((Sym->Flags & SC_LABEL) != SC_LABEL);
667                 if (Sym->Flags & SC_TYPE) {
668                     /* Cannot use type symbols */
669                     Error ("Variable identifier expected");
670                     /* Assume an int type to make E valid */
671                     E->Flags = E_LOC_STACK | E_RTYPE_LVAL;
672                     E->Type  = type_int;
673                     return;
674                 }
675
676                 /* Mark the symbol as referenced */
677                 Sym->Flags |= SC_REF;
678
679                 /* The expression type is the symbol type */
680                 E->Type = Sym->Type;
681
682                 /* Check for legal symbol types */
683                 if ((Sym->Flags & SC_CONST) == SC_CONST) {
684                     /* Enum or some other numeric constant */
685                     E->Flags = E_LOC_ABS | E_RTYPE_RVAL;
686                     E->IVal = Sym->V.ConstVal;
687                 } else if ((Sym->Flags & SC_FUNC) == SC_FUNC) {
688                     /* Function */
689                     E->Flags = E_LOC_GLOBAL | E_RTYPE_LVAL;
690                     E->Name = (unsigned long) Sym->Name;
691                 } else if ((Sym->Flags & SC_AUTO) == SC_AUTO) {
692                     /* Local variable. If this is a parameter for a variadic
693                     ** function, we have to add some address calculations, and the
694                     ** address is not const.
695                     */
696                     if ((Sym->Flags & SC_PARAM) == SC_PARAM && F_IsVariadic (CurrentFunc)) {
697                         /* Variadic parameter */
698                         g_leavariadic (Sym->V.Offs - F_GetParamSize (CurrentFunc));
699                         E->Flags = E_LOC_EXPR | E_RTYPE_LVAL;
700                     } else {
701                         /* Normal parameter */
702                         E->Flags = E_LOC_STACK | E_RTYPE_LVAL;
703                         E->IVal  = Sym->V.Offs;
704                     }
705                 } else if ((Sym->Flags & SC_REGISTER) == SC_REGISTER) {
706                     /* Register variable, zero page based */
707                     E->Flags = E_LOC_REGISTER | E_RTYPE_LVAL;
708                     E->Name  = Sym->V.R.RegOffs;
709                 } else if ((Sym->Flags & SC_STATIC) == SC_STATIC) {
710                     /* Static variable */
711                     if (Sym->Flags & (SC_EXTERN | SC_STORAGE)) {
712                         E->Flags = E_LOC_GLOBAL | E_RTYPE_LVAL;
713                         E->Name = (unsigned long) Sym->Name;
714                     } else {
715                         E->Flags = E_LOC_STATIC | E_RTYPE_LVAL;
716                         E->Name = Sym->V.Label;
717                     }
718                 } else {
719                     /* Local static variable */
720                     E->Flags = E_LOC_STATIC | E_RTYPE_LVAL;
721                     E->Name  = Sym->V.Offs;
722                 }
723
724                 /* We've made all variables lvalues above. However, this is
725                 ** not always correct: An array is actually the address of its
726                 ** first element, which is a rvalue, and a function is a
727                 ** rvalue, too, because we cannot store anything in a function.
728                 ** So fix the flags depending on the type.
729                 */
730                 if (IsTypeArray (E->Type) || IsTypeFunc (E->Type)) {
731                     ED_MakeRVal (E);
732                 }
733
734             } else {
735
736                 /* We did not find the symbol. Remember the name, then skip it */
737                 ident Ident;
738                 strcpy (Ident, CurTok.Ident);
739                 NextToken ();
740
741                 /* IDENT is either an auto-declared function or an undefined variable. */
742                 if (CurTok.Tok == TOK_LPAREN) {
743                     /* C99 doesn't allow calls to undefined functions, so
744                     ** generate an error and otherwise a warning. Declare a
745                     ** function returning int. For that purpose, prepare a
746                     ** function signature for a function having an empty param
747                     ** list and returning int.
748                     */
749                     if (IS_Get (&Standard) >= STD_C99) {
750                         Error ("Call to undefined function `%s'", Ident);
751                     } else {
752                         Warning ("Call to undefined function `%s'", Ident);
753                     }
754                     Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_EXTERN | SC_REF | SC_FUNC);
755                     E->Type  = Sym->Type;
756                     E->Flags = E_LOC_GLOBAL | E_RTYPE_RVAL;
757                     E->Name  = (unsigned long) Sym->Name;
758                 } else {
759                     /* Undeclared Variable */
760                     Sym = AddLocalSym (Ident, type_int, SC_AUTO | SC_REF, 0);
761                     E->Flags = E_LOC_STACK | E_RTYPE_LVAL;
762                     E->Type = type_int;
763                     Error ("Undefined symbol: `%s'", Ident);
764                 }
765
766             }
767             break;
768
769         case TOK_SCONST:
770         case TOK_WCSCONST:
771             /* String literal */
772             E->LVal  = UseLiteral (CurTok.SVal);
773             E->Type  = GetCharArrayType (GetLiteralSize (CurTok.SVal));
774             E->Flags = E_LOC_LITERAL | E_RTYPE_RVAL;
775             E->IVal  = 0;
776             E->Name  = GetLiteralLabel (CurTok.SVal);
777             NextToken ();
778             break;
779
780         case TOK_ASM:
781             /* ASM statement */
782             AsmStatement ();
783             E->Flags = E_LOC_EXPR | E_RTYPE_RVAL;
784             E->Type  = type_void;
785             break;
786
787         case TOK_A:
788             /* Register pseudo variable */
789             E->Type  = type_uchar;
790             E->Flags = E_LOC_PRIMARY | E_RTYPE_LVAL;
791             NextToken ();
792             break;
793
794         case TOK_AX:
795             /* Register pseudo variable */
796             E->Type  = type_uint;
797             E->Flags = E_LOC_PRIMARY | E_RTYPE_LVAL;
798             NextToken ();
799             break;
800
801         case TOK_EAX:
802             /* Register pseudo variable */
803             E->Type  = type_ulong;
804             E->Flags = E_LOC_PRIMARY | E_RTYPE_LVAL;
805             NextToken ();
806             break;
807
808         default:
809             /* Illegal primary. Be sure to skip the token to avoid endless
810             ** error loops.
811             */
812             Error ("Expression expected");
813             NextToken ();
814             ED_MakeConstAbsInt (E, 1);
815             break;
816     }
817 }
818
819
820
821 static void ArrayRef (ExprDesc* Expr)
822 /* Handle an array reference. This function needs a rewrite. */
823 {
824     int         ConstBaseAddr;
825     ExprDesc    Subscript;
826     CodeMark    Mark1;
827     CodeMark    Mark2;
828     TypeCode    Qualifiers;
829     Type*       ElementType;
830     Type*       tptr1;
831
832
833     /* Skip the bracket */
834     NextToken ();
835
836     /* Get the type of left side */
837     tptr1 = Expr->Type;
838
839     /* We can apply a special treatment for arrays that have a const base
840     ** address. This is true for most arrays and will produce a lot better
841     ** code. Check if this is a const base address.
842     */
843     ConstBaseAddr = ED_IsRVal (Expr) &&
844                     (ED_IsLocConst (Expr) || ED_IsLocStack (Expr));
845
846     /* If we have a constant base, we delay the address fetch */
847     GetCodePos (&Mark1);
848     if (!ConstBaseAddr) {
849         /* Get a pointer to the array into the primary */
850         LoadExpr (CF_NONE, Expr);
851
852         /* Get the array pointer on stack. Do not push more than 16
853         ** bit, even if this value is greater, since we cannot handle
854         ** other than 16bit stuff when doing indexing.
855         */
856         GetCodePos (&Mark2);
857         g_push (CF_PTR, 0);
858     }
859
860     /* TOS now contains ptr to array elements. Get the subscript. */
861     MarkedExprWithCheck (hie0, &Subscript);
862
863     /* Check the types of array and subscript. We can either have a
864     ** pointer/array to the left, in which case the subscript must be of an
865     ** integer type, or we have an integer to the left, in which case the
866     ** subscript must be a pointer/array.
867     ** Since we do the necessary checking here, we can rely later on the
868     ** correct types.
869     */
870     Qualifiers = T_QUAL_NONE;
871     if (IsClassPtr (Expr->Type)) {
872         if (!IsClassInt (Subscript.Type))  {
873             Error ("Array subscript is not an integer");
874             /* To avoid any compiler errors, make the expression a valid int */
875             ED_MakeConstAbsInt (&Subscript, 0);
876         }
877         if (IsTypeArray (Expr->Type)) {
878             Qualifiers = GetQualifier (Expr->Type);
879         }
880         ElementType = Indirect (Expr->Type);
881     } else if (IsClassInt (Expr->Type)) {
882         if (!IsClassPtr (Subscript.Type)) {
883             Error ("Subscripted value is neither array nor pointer");
884             /* To avoid compiler errors, make the subscript a char[] at
885             ** address 0.
886             */
887             ED_MakeConstAbs (&Subscript, 0, GetCharArrayType (1));
888         } else if (IsTypeArray (Subscript.Type)) {
889             Qualifiers = GetQualifier (Subscript.Type);
890         }
891         ElementType = Indirect (Subscript.Type);
892     } else {
893         Error ("Cannot subscript");
894         /* To avoid compiler errors, fake both the array and the subscript, so
895         ** we can just proceed.
896         */
897         ED_MakeConstAbs (Expr, 0, GetCharArrayType (1));
898         ED_MakeConstAbsInt (&Subscript, 0);
899         ElementType = Indirect (Expr->Type);
900     }
901
902     /* The element type has the combined qualifiers from itself and the array,
903     ** it is a member of (if any).
904     */
905     if (GetQualifier (ElementType) != (GetQualifier (ElementType) | Qualifiers)) {
906         ElementType = TypeDup (ElementType);
907         ElementType->C |= Qualifiers;
908     }
909
910     /* If the subscript is a bit-field, load it and make it an rvalue */
911     if (ED_IsBitField (&Subscript)) {
912         LoadExpr (CF_NONE, &Subscript);
913         ED_MakeRValExpr (&Subscript);
914     }
915
916     /* Check if the subscript is constant absolute value */
917     if (ED_IsConstAbs (&Subscript) && ED_CodeRangeIsEmpty (&Subscript)) {
918
919         /* The array subscript is a numeric constant. If we had pushed the
920         ** array base address onto the stack before, we can remove this value,
921         ** since we can generate expression+offset.
922         */
923         if (!ConstBaseAddr) {
924             RemoveCode (&Mark2);
925         } else {
926             /* Get an array pointer into the primary */
927             LoadExpr (CF_NONE, Expr);
928         }
929
930         if (IsClassPtr (Expr->Type)) {
931
932             /* Lhs is pointer/array. Scale the subscript value according to
933             ** the element size.
934             */
935             Subscript.IVal *= CheckedSizeOf (ElementType);
936
937             /* Remove the address load code */
938             RemoveCode (&Mark1);
939
940             /* In case of an array, we can adjust the offset of the expression
941             ** already in Expr. If the base address was a constant, we can even
942             ** remove the code that loaded the address into the primary.
943             */
944             if (IsTypeArray (Expr->Type)) {
945
946                 /* Adjust the offset */
947                 Expr->IVal += Subscript.IVal;
948
949             } else {
950
951                 /* It's a pointer, so we do have to load it into the primary
952                 ** first (if it's not already there).
953                 */
954                 if (ConstBaseAddr || ED_IsLVal (Expr)) {
955                     LoadExpr (CF_NONE, Expr);
956                     ED_MakeRValExpr (Expr);
957                 }
958
959                 /* Use the offset */
960                 Expr->IVal = Subscript.IVal;
961             }
962
963         } else {
964
965             /* Scale the rhs value according to the element type */
966             g_scale (TypeOf (tptr1), CheckedSizeOf (ElementType));
967
968             /* Add the subscript. Since arrays are indexed by integers,
969             ** we will ignore the true type of the subscript here and
970             ** use always an int. #### Use offset but beware of LoadExpr!
971             */
972             g_inc (CF_INT | CF_CONST, Subscript.IVal);
973
974         }
975
976     } else {
977
978         /* Array subscript is not constant. Load it into the primary */
979         GetCodePos (&Mark2);
980         LoadExpr (CF_NONE, &Subscript);
981
982         /* Do scaling */
983         if (IsClassPtr (Expr->Type)) {
984
985             /* Indexing is based on unsigneds, so we will just use the integer
986             ** portion of the index (which is in (e)ax, so there's no further
987             ** action required).
988             */
989             g_scale (CF_INT, CheckedSizeOf (ElementType));
990
991         } else {
992
993             /* Get the int value on top. If we come here, we're sure, both
994             ** values are 16 bit (the first one was truncated if necessary
995             ** and the second one is a pointer). Note: If ConstBaseAddr is
996             ** true, we don't have a value on stack, so to "swap" both, just
997             ** push the subscript.
998             */
999             if (ConstBaseAddr) {
1000                 g_push (CF_INT, 0);
1001                 LoadExpr (CF_NONE, Expr);
1002                 ConstBaseAddr = 0;
1003             } else {
1004                 g_swap (CF_INT);
1005             }
1006
1007             /* Scale it */
1008             g_scale (TypeOf (tptr1), CheckedSizeOf (ElementType));
1009
1010         }
1011
1012         /* The offset is now in the primary register. It we didn't have a
1013         ** constant base address for the lhs, the lhs address is already
1014         ** on stack, and we must add the offset. If the base address was
1015         ** constant, we call special functions to add the address to the
1016         ** offset value.
1017         */
1018         if (!ConstBaseAddr) {
1019
1020             /* The array base address is on stack and the subscript is in the
1021             ** primary. Add both.
1022             */
1023             g_add (CF_INT, 0);
1024
1025         } else {
1026
1027             /* The subscript is in the primary, and the array base address is
1028             ** in Expr. If the subscript has itself a constant address, it is
1029             ** often a better idea to reverse again the order of the
1030             ** evaluation. This will generate better code if the subscript is
1031             ** a byte sized variable. But beware: This is only possible if the
1032             ** subscript was not scaled, that is, if this was a byte array
1033             ** or pointer.
1034             */
1035             if ((ED_IsLocConst (&Subscript) || ED_IsLocStack (&Subscript)) &&
1036                 CheckedSizeOf (ElementType) == SIZEOF_CHAR) {
1037
1038                 unsigned Flags;
1039
1040                 /* Reverse the order of evaluation */
1041                 if (CheckedSizeOf (Subscript.Type) == SIZEOF_CHAR) {
1042                     Flags = CF_CHAR;
1043                 } else {
1044                     Flags = CF_INT;
1045                 }
1046                 RemoveCode (&Mark2);
1047
1048                 /* Get a pointer to the array into the primary. */
1049                 LoadExpr (CF_NONE, Expr);
1050
1051                 /* Add the variable */
1052                 if (ED_IsLocStack (&Subscript)) {
1053                     g_addlocal (Flags, Subscript.IVal);
1054                 } else {
1055                     Flags |= GlobalModeFlags (&Subscript);
1056                     g_addstatic (Flags, Subscript.Name, Subscript.IVal);
1057                 }
1058             } else {
1059
1060                 if (ED_IsLocAbs (Expr)) {
1061                     /* Constant numeric address. Just add it */
1062                     g_inc (CF_INT, Expr->IVal);
1063                 } else if (ED_IsLocStack (Expr)) {
1064                     /* Base address is a local variable address */
1065                     if (IsTypeArray (Expr->Type)) {
1066                         g_addaddr_local (CF_INT, Expr->IVal);
1067                     } else {
1068                         g_addlocal (CF_PTR, Expr->IVal);
1069                     }
1070                 } else {
1071                     /* Base address is a static variable address */
1072                     unsigned Flags = CF_INT | GlobalModeFlags (Expr);
1073                     if (ED_IsRVal (Expr)) {
1074                         /* Add the address of the location */
1075                         g_addaddr_static (Flags, Expr->Name, Expr->IVal);
1076                     } else {
1077                         /* Add the contents of the location */
1078                         g_addstatic (Flags, Expr->Name, Expr->IVal);
1079                     }
1080                 }
1081             }
1082
1083
1084         }
1085
1086         /* The result is an expression in the primary */
1087         ED_MakeRValExpr (Expr);
1088
1089     }
1090
1091     /* Result is of element type */
1092     Expr->Type = ElementType;
1093
1094     /* An array element is actually a variable. So the rules for variables
1095     ** with respect to the reference type apply: If it's an array, it is
1096     ** a rvalue, otherwise it's an lvalue. (A function would also be a rvalue,
1097     ** but an array cannot contain functions).
1098     */
1099     if (IsTypeArray (Expr->Type)) {
1100         ED_MakeRVal (Expr);
1101     } else {
1102         ED_MakeLVal (Expr);
1103     }
1104
1105     /* Consume the closing bracket */
1106     ConsumeRBrack ();
1107 }
1108
1109
1110
1111 static void StructRef (ExprDesc* Expr)
1112 /* Process struct field after . or ->. */
1113 {
1114     ident Ident;
1115     SymEntry* Field;
1116     Type* FinalType;
1117     TypeCode Q;
1118
1119     /* Skip the token and check for an identifier */
1120     NextToken ();
1121     if (CurTok.Tok != TOK_IDENT) {
1122         Error ("Identifier expected");
1123         /* Make the expression an integer at address zero */
1124         ED_MakeConstAbs (Expr, 0, type_int);
1125         return;
1126     }
1127
1128     /* Get the symbol table entry and check for a struct field */
1129     strcpy (Ident, CurTok.Ident);
1130     NextToken ();
1131     Field = FindStructField (Expr->Type, Ident);
1132     if (Field == 0) {
1133         Error ("Struct/union has no field named `%s'", Ident);
1134         /* Make the expression an integer at address zero */
1135         ED_MakeConstAbs (Expr, 0, type_int);
1136         return;
1137     }
1138
1139     /* If we have a struct pointer that is an lvalue and not already in the
1140     ** primary, load it now.
1141     */
1142     if (ED_IsLVal (Expr) && IsTypePtr (Expr->Type)) {
1143
1144         /* Load into the primary */
1145         LoadExpr (CF_NONE, Expr);
1146
1147         /* Make it an lvalue expression */
1148         ED_MakeLValExpr (Expr);
1149     }
1150
1151     /* The type is the type of the field plus any qualifiers from the struct */
1152     if (IsClassStruct (Expr->Type)) {
1153         Q = GetQualifier (Expr->Type);
1154     } else {
1155         Q = GetQualifier (Indirect (Expr->Type));
1156     }
1157     if (GetQualifier (Field->Type) == (GetQualifier (Field->Type) | Q)) {
1158         FinalType = Field->Type;
1159     } else {
1160         FinalType = TypeDup (Field->Type);
1161         FinalType->C |= Q;
1162     }
1163
1164     /* A struct is usually an lvalue. If not, it is a struct in the primary
1165     ** register.
1166     */
1167     if (ED_IsRVal (Expr) && ED_IsLocExpr (Expr) && !IsTypePtr (Expr->Type)) {
1168
1169         unsigned Flags = 0;
1170         unsigned BitOffs;
1171
1172         /* Get the size of the type */
1173         unsigned Size = SizeOf (Expr->Type);
1174
1175         /* Safety check */
1176         CHECK (Field->V.Offs + Size <= SIZEOF_LONG);
1177
1178         /* The type of the operation depends on the type of the struct */
1179         switch (Size) {
1180             case 1:     Flags = CF_CHAR | CF_UNSIGNED | CF_CONST;       break;
1181             case 2:     Flags = CF_INT  | CF_UNSIGNED | CF_CONST;       break;
1182             case 3:     /* FALLTHROUGH */
1183             case 4:     Flags = CF_LONG | CF_UNSIGNED | CF_CONST;       break;
1184             default:    Internal ("Invalid struct size: %u", Size);     break;
1185         }
1186
1187         /* Generate a shift to get the field in the proper position in the
1188         ** primary. For bit fields, mask the value.
1189         */
1190         BitOffs = Field->V.Offs * CHAR_BITS;
1191         if (SymIsBitField (Field)) {
1192             BitOffs += Field->V.B.BitOffs;
1193             g_asr (Flags, BitOffs);
1194             /* Mask the value. This is unnecessary if the shift executed above
1195             ** moved only zeroes into the value.
1196             */
1197             if (BitOffs + Field->V.B.BitWidth != Size * CHAR_BITS) {
1198                 g_and (CF_INT | CF_UNSIGNED | CF_CONST,
1199                        (0x0001U << Field->V.B.BitWidth) - 1U);
1200             }
1201         } else {
1202             g_asr (Flags, BitOffs);
1203         }
1204
1205         /* Use the new type */
1206         Expr->Type = FinalType;
1207
1208     } else {
1209
1210         /* Set the struct field offset */
1211         Expr->IVal += Field->V.Offs;
1212
1213         /* Use the new type */
1214         Expr->Type = FinalType;
1215
1216         /* An struct member is actually a variable. So the rules for variables
1217         ** with respect to the reference type apply: If it's an array, it is
1218         ** a rvalue, otherwise it's an lvalue. (A function would also be a rvalue,
1219         ** but a struct field cannot be a function).
1220         */
1221         if (IsTypeArray (Expr->Type)) {
1222             ED_MakeRVal (Expr);
1223         } else {
1224             ED_MakeLVal (Expr);
1225         }
1226
1227         /* Make the expression a bit field if necessary */
1228         if (SymIsBitField (Field)) {
1229             ED_MakeBitField (Expr, Field->V.B.BitOffs, Field->V.B.BitWidth);
1230         }
1231     }
1232
1233 }
1234
1235
1236
1237 static void hie11 (ExprDesc *Expr)
1238 /* Handle compound types (structs and arrays) */
1239 {
1240     /* Name value used in invalid function calls */
1241     static const char IllegalFunc[] = "illegal_function_call";
1242
1243     /* Evaluate the lhs */
1244     Primary (Expr);
1245
1246     /* Check for a rhs */
1247     while (CurTok.Tok == TOK_LBRACK || CurTok.Tok == TOK_LPAREN ||
1248            CurTok.Tok == TOK_DOT    || CurTok.Tok == TOK_PTR_REF) {
1249
1250         switch (CurTok.Tok) {
1251
1252             case TOK_LBRACK:
1253                 /* Array reference */
1254                 ArrayRef (Expr);
1255                 break;
1256
1257             case TOK_LPAREN:
1258                 /* Function call. */
1259                 if (!IsTypeFunc (Expr->Type) && !IsTypeFuncPtr (Expr->Type)) {
1260                     /* Not a function */
1261                     Error ("Illegal function call");
1262                     /* Force the type to be a implicitly defined function, one
1263                     ** returning an int and taking any number of arguments.
1264                     ** Since we don't have a name, invent one.
1265                     */
1266                     ED_MakeConstAbs (Expr, 0, GetImplicitFuncType ());
1267                     Expr->Name = (long) IllegalFunc;
1268                 }
1269                 /* Call the function */
1270                 FunctionCall (Expr);
1271                 break;
1272
1273             case TOK_DOT:
1274                 if (!IsClassStruct (Expr->Type)) {
1275                     Error ("Struct expected");
1276                 }
1277                 StructRef (Expr);
1278                 break;
1279
1280             case TOK_PTR_REF:
1281                 /* If we have an array, convert it to pointer to first element */
1282                 if (IsTypeArray (Expr->Type)) {
1283                     Expr->Type = ArrayToPtr (Expr->Type);
1284                 }
1285                 if (!IsClassPtr (Expr->Type) || !IsClassStruct (Indirect (Expr->Type))) {
1286                     Error ("Struct pointer expected");
1287                 }
1288                 StructRef (Expr);
1289                 break;
1290
1291             default:
1292                 Internal ("Invalid token in hie11: %d", CurTok.Tok);
1293
1294         }
1295     }
1296 }
1297
1298
1299
1300 void Store (ExprDesc* Expr, const Type* StoreType)
1301 /* Store the primary register into the location denoted by Expr. If StoreType
1302 ** is given, use this type when storing instead of Expr->Type. If StoreType
1303 ** is NULL, use Expr->Type instead.
1304 */
1305 {
1306     unsigned Flags;
1307
1308     /* If StoreType was not given, use Expr->Type instead */
1309     if (StoreType == 0) {
1310         StoreType = Expr->Type;
1311     }
1312
1313     /* Prepare the code generator flags */
1314     Flags = TypeOf (StoreType) | GlobalModeFlags (Expr);
1315
1316     /* Do the store depending on the location */
1317     switch (ED_GetLoc (Expr)) {
1318
1319         case E_LOC_ABS:
1320             /* Absolute: numeric address or const */
1321             g_putstatic (Flags, Expr->IVal, 0);
1322             break;
1323
1324         case E_LOC_GLOBAL:
1325             /* Global variable */
1326             g_putstatic (Flags, Expr->Name, Expr->IVal);
1327             break;
1328
1329         case E_LOC_STATIC:
1330         case E_LOC_LITERAL:
1331             /* Static variable or literal in the literal pool */
1332             g_putstatic (Flags, Expr->Name, Expr->IVal);
1333             break;
1334
1335         case E_LOC_REGISTER:
1336             /* Register variable */
1337             g_putstatic (Flags, Expr->Name, Expr->IVal);
1338             break;
1339
1340         case E_LOC_STACK:
1341             /* Value on the stack */
1342             g_putlocal (Flags, Expr->IVal, 0);
1343             break;
1344
1345         case E_LOC_PRIMARY:
1346             /* The primary register (value is already there) */
1347             break;
1348
1349         case E_LOC_EXPR:
1350             /* An expression in the primary register */
1351             g_putind (Flags, Expr->IVal);
1352             break;
1353
1354         default:
1355             Internal ("Invalid location in Store(): 0x%04X", ED_GetLoc (Expr));
1356     }
1357
1358     /* Assume that each one of the stores will invalidate CC */
1359     ED_MarkAsUntested (Expr);
1360 }
1361
1362
1363
1364 static void PreInc (ExprDesc* Expr)
1365 /* Handle the preincrement operators */
1366 {
1367     unsigned Flags;
1368     unsigned long Val;
1369
1370     /* Skip the operator token */
1371     NextToken ();
1372
1373     /* Evaluate the expression and check that it is an lvalue */
1374     hie10 (Expr);
1375     if (!ED_IsLVal (Expr)) {
1376         Error ("Invalid lvalue");
1377         return;
1378     }
1379
1380     /* We cannot modify const values */
1381     if (IsQualConst (Expr->Type)) {
1382         Error ("Increment of read-only variable");
1383     }
1384
1385     /* Get the data type */
1386     Flags = TypeOf (Expr->Type) | GlobalModeFlags (Expr) | CF_FORCECHAR | CF_CONST;
1387
1388     /* Get the increment value in bytes */
1389     Val = IsTypePtr (Expr->Type)? CheckedPSizeOf (Expr->Type) : 1;
1390
1391     /* Check the location of the data */
1392     switch (ED_GetLoc (Expr)) {
1393
1394         case E_LOC_ABS:
1395             /* Absolute: numeric address or const */
1396             g_addeqstatic (Flags, Expr->IVal, 0, Val);
1397             break;
1398
1399         case E_LOC_GLOBAL:
1400             /* Global variable */
1401             g_addeqstatic (Flags, Expr->Name, Expr->IVal, Val);
1402             break;
1403
1404         case E_LOC_STATIC:
1405         case E_LOC_LITERAL:
1406             /* Static variable or literal in the literal pool */
1407             g_addeqstatic (Flags, Expr->Name, Expr->IVal, Val);
1408             break;
1409
1410         case E_LOC_REGISTER:
1411             /* Register variable */
1412             g_addeqstatic (Flags, Expr->Name, Expr->IVal, Val);
1413             break;
1414
1415         case E_LOC_STACK:
1416             /* Value on the stack */
1417             g_addeqlocal (Flags, Expr->IVal, Val);
1418             break;
1419
1420         case E_LOC_PRIMARY:
1421             /* The primary register */
1422             g_inc (Flags, Val);
1423             break;
1424
1425         case E_LOC_EXPR:
1426             /* An expression in the primary register */
1427             g_addeqind (Flags, Expr->IVal, Val);
1428             break;
1429
1430         default:
1431             Internal ("Invalid location in PreInc(): 0x%04X", ED_GetLoc (Expr));
1432     }
1433
1434     /* Result is an expression, no reference */
1435     ED_MakeRValExpr (Expr);
1436 }
1437
1438
1439
1440 static void PreDec (ExprDesc* Expr)
1441 /* Handle the predecrement operators */
1442 {
1443     unsigned Flags;
1444     unsigned long Val;
1445
1446     /* Skip the operator token */
1447     NextToken ();
1448
1449     /* Evaluate the expression and check that it is an lvalue */
1450     hie10 (Expr);
1451     if (!ED_IsLVal (Expr)) {
1452         Error ("Invalid lvalue");
1453         return;
1454     }
1455
1456     /* We cannot modify const values */
1457     if (IsQualConst (Expr->Type)) {
1458         Error ("Decrement of read-only variable");
1459     }
1460
1461     /* Get the data type */
1462     Flags = TypeOf (Expr->Type) | GlobalModeFlags (Expr) | CF_FORCECHAR | CF_CONST;
1463
1464     /* Get the increment value in bytes */
1465     Val = IsTypePtr (Expr->Type)? CheckedPSizeOf (Expr->Type) : 1;
1466
1467     /* Check the location of the data */
1468     switch (ED_GetLoc (Expr)) {
1469
1470         case E_LOC_ABS:
1471             /* Absolute: numeric address or const */
1472             g_subeqstatic (Flags, Expr->IVal, 0, Val);
1473             break;
1474
1475         case E_LOC_GLOBAL:
1476             /* Global variable */
1477             g_subeqstatic (Flags, Expr->Name, Expr->IVal, Val);
1478             break;
1479
1480         case E_LOC_STATIC:
1481         case E_LOC_LITERAL:
1482             /* Static variable or literal in the literal pool */
1483             g_subeqstatic (Flags, Expr->Name, Expr->IVal, Val);
1484             break;
1485
1486         case E_LOC_REGISTER:
1487             /* Register variable */
1488             g_subeqstatic (Flags, Expr->Name, Expr->IVal, Val);
1489             break;
1490
1491         case E_LOC_STACK:
1492             /* Value on the stack */
1493             g_subeqlocal (Flags, Expr->IVal, Val);
1494             break;
1495
1496         case E_LOC_PRIMARY:
1497             /* The primary register */
1498             g_inc (Flags, Val);
1499             break;
1500
1501         case E_LOC_EXPR:
1502             /* An expression in the primary register */
1503             g_subeqind (Flags, Expr->IVal, Val);
1504             break;
1505
1506         default:
1507             Internal ("Invalid location in PreDec(): 0x%04X", ED_GetLoc (Expr));
1508     }
1509
1510     /* Result is an expression, no reference */
1511     ED_MakeRValExpr (Expr);
1512 }
1513
1514
1515
1516 static void PostInc (ExprDesc* Expr)
1517 /* Handle the postincrement operator */
1518 {
1519     unsigned Flags;
1520
1521     NextToken ();
1522
1523     /* The expression to increment must be an lvalue */
1524     if (!ED_IsLVal (Expr)) {
1525         Error ("Invalid lvalue");
1526         return;
1527     }
1528
1529     /* We cannot modify const values */
1530     if (IsQualConst (Expr->Type)) {
1531         Error ("Increment of read-only variable");
1532     }
1533
1534     /* Get the data type */
1535     Flags = TypeOf (Expr->Type);
1536
1537     /* Fast path: char */
1538     if ((Flags & CF_CHAR) == CF_CHAR && ED_GetLoc(Expr) & (E_LOC_GLOBAL | E_LOC_STATIC)) {
1539
1540         LoadExpr (CF_NONE, Expr);
1541         AddCodeLine ("inc %s", ED_GetLabelName(Expr, 0));
1542
1543     } else {
1544
1545         /* Push the address if needed */
1546         PushAddr (Expr);
1547
1548         /* Fetch the value and save it (since it's the result of the expression) */
1549         LoadExpr (CF_NONE, Expr);
1550         g_save (Flags | CF_FORCECHAR);
1551
1552         /* If we have a pointer expression, increment by the size of the type */
1553         if (IsTypePtr (Expr->Type)) {
1554             g_inc (Flags | CF_CONST | CF_FORCECHAR, CheckedSizeOf (Expr->Type + 1));
1555         } else {
1556             g_inc (Flags | CF_CONST | CF_FORCECHAR, 1);
1557         }
1558
1559         /* Store the result back */
1560         Store (Expr, 0);
1561
1562         /* Restore the original value in the primary register */
1563         g_restore (Flags | CF_FORCECHAR);
1564     }
1565
1566     /* The result is always an expression, no reference */
1567     ED_MakeRValExpr (Expr);
1568 }
1569
1570
1571
1572 static void PostDec (ExprDesc* Expr)
1573 /* Handle the postdecrement operator */
1574 {
1575     unsigned Flags;
1576
1577     NextToken ();
1578
1579     /* The expression to increment must be an lvalue */
1580     if (!ED_IsLVal (Expr)) {
1581         Error ("Invalid lvalue");
1582         return;
1583     }
1584
1585     /* We cannot modify const values */
1586     if (IsQualConst (Expr->Type)) {
1587         Error ("Decrement of read-only variable");
1588     }
1589
1590     /* Get the data type */
1591     Flags = TypeOf (Expr->Type);
1592
1593     /* Fast path: char */
1594     if ((Flags & CF_CHAR) == CF_CHAR && ED_GetLoc(Expr) & (E_LOC_GLOBAL | E_LOC_STATIC)) {
1595
1596         LoadExpr (CF_NONE, Expr);
1597         AddCodeLine ("dec %s", ED_GetLabelName(Expr, 0));
1598
1599     } else {
1600
1601         /* Push the address if needed */
1602         PushAddr (Expr);
1603
1604         /* Fetch the value and save it (since it's the result of the expression) */
1605         LoadExpr (CF_NONE, Expr);
1606         g_save (Flags | CF_FORCECHAR);
1607
1608         /* If we have a pointer expression, increment by the size of the type */
1609         if (IsTypePtr (Expr->Type)) {
1610             g_dec (Flags | CF_CONST | CF_FORCECHAR, CheckedSizeOf (Expr->Type + 1));
1611         } else {
1612             g_dec (Flags | CF_CONST | CF_FORCECHAR, 1);
1613         }
1614
1615         /* Store the result back */
1616         Store (Expr, 0);
1617
1618         /* Restore the original value in the primary register */
1619         g_restore (Flags | CF_FORCECHAR);
1620     }
1621
1622     /* The result is always an expression, no reference */
1623     ED_MakeRValExpr (Expr);
1624 }
1625
1626
1627
1628 static void UnaryOp (ExprDesc* Expr)
1629 /* Handle unary -/+ and ~ */
1630 {
1631     unsigned Flags;
1632
1633     /* Remember the operator token and skip it */
1634     token_t Tok = CurTok.Tok;
1635     NextToken ();
1636
1637     /* Get the expression */
1638     hie10 (Expr);
1639
1640     /* We can only handle integer types */
1641     if (!IsClassInt (Expr->Type)) {
1642         Error ("Argument must have integer type");
1643         ED_MakeConstAbsInt (Expr, 1);
1644     }
1645
1646     /* Check for a constant expression */
1647     if (ED_IsConstAbs (Expr)) {
1648         /* Value is constant */
1649         switch (Tok) {
1650             case TOK_MINUS: Expr->IVal = -Expr->IVal;   break;
1651             case TOK_PLUS:                              break;
1652             case TOK_COMP:  Expr->IVal = ~Expr->IVal;   break;
1653             default:        Internal ("Unexpected token: %d", Tok);
1654         }
1655     } else {
1656         /* Value is not constant */
1657         LoadExpr (CF_NONE, Expr);
1658
1659         /* Get the type of the expression */
1660         Flags = TypeOf (Expr->Type);
1661
1662         /* Handle the operation */
1663         switch (Tok) {
1664             case TOK_MINUS: g_neg (Flags);  break;
1665             case TOK_PLUS:                  break;
1666             case TOK_COMP:  g_com (Flags);  break;
1667             default:        Internal ("Unexpected token: %d", Tok);
1668         }
1669
1670         /* The result is a rvalue in the primary */
1671         ED_MakeRValExpr (Expr);
1672     }
1673 }
1674
1675
1676
1677 void hie10 (ExprDesc* Expr)
1678 /* Handle ++, --, !, unary - etc. */
1679 {
1680     unsigned long Size;
1681
1682     switch (CurTok.Tok) {
1683
1684         case TOK_INC:
1685             PreInc (Expr);
1686             break;
1687
1688         case TOK_DEC:
1689             PreDec (Expr);
1690             break;
1691
1692         case TOK_PLUS:
1693         case TOK_MINUS:
1694         case TOK_COMP:
1695             UnaryOp (Expr);
1696             break;
1697
1698         case TOK_BOOL_NOT:
1699             NextToken ();
1700             if (evalexpr (CF_NONE, hie10, Expr) == 0) {
1701                 /* Constant expression */
1702                 Expr->IVal = !Expr->IVal;
1703             } else {
1704                 g_bneg (TypeOf (Expr->Type));
1705                 ED_MakeRValExpr (Expr);
1706                 ED_TestDone (Expr);             /* bneg will set cc */
1707             }
1708             break;
1709
1710         case TOK_STAR:
1711             NextToken ();
1712             ExprWithCheck (hie10, Expr);
1713             if (ED_IsLVal (Expr) || !(ED_IsLocConst (Expr) || ED_IsLocStack (Expr))) {
1714                 /* Not a const, load it into the primary and make it a
1715                 ** calculated value.
1716                 */
1717                 LoadExpr (CF_NONE, Expr);
1718                 ED_MakeRValExpr (Expr);
1719             }
1720             /* If the expression is already a pointer to function, the
1721             ** additional dereferencing operator must be ignored. A function
1722             ** itself is represented as "pointer to function", so any number
1723             ** of dereference operators is legal, since the result will
1724             ** always be converted to "pointer to function".
1725             */
1726             if (IsTypeFuncPtr (Expr->Type) || IsTypeFunc (Expr->Type)) {
1727                 /* Expression not storable */
1728                 ED_MakeRVal (Expr);
1729             } else {
1730                 if (IsClassPtr (Expr->Type)) {
1731                     Expr->Type = Indirect (Expr->Type);
1732                 } else {
1733                     Error ("Illegal indirection");
1734                 }
1735                 /* If the expression points to an array, then don't convert the
1736                 ** address -- it already is the location of the first element.
1737                 */
1738                 if (!IsTypeArray (Expr->Type)) {
1739                     /* The * operator yields an lvalue */
1740                     ED_MakeLVal (Expr);
1741                 }
1742             }
1743             break;
1744
1745         case TOK_AND:
1746             NextToken ();
1747             ExprWithCheck (hie10, Expr);
1748             /* The & operator may be applied to any lvalue, and it may be
1749             ** applied to functions, even if they're no lvalues.
1750             */
1751             if (ED_IsRVal (Expr) && !IsTypeFunc (Expr->Type) && !IsTypeArray (Expr->Type)) {
1752                 Error ("Illegal address");
1753             } else {
1754                 if (ED_IsBitField (Expr)) {
1755                     Error ("Cannot take address of bit-field");
1756                     /* Do it anyway, just to avoid further warnings */
1757                     Expr->Flags &= ~E_BITFIELD;
1758                 }
1759                 Expr->Type = PointerTo (Expr->Type);
1760                 /* The & operator yields an rvalue */
1761                 ED_MakeRVal (Expr);
1762             }
1763             break;
1764
1765         case TOK_SIZEOF:
1766             NextToken ();
1767             if (TypeSpecAhead ()) {
1768                 Type T[MAXTYPELEN];
1769                 NextToken ();
1770                 Size = CheckedSizeOf (ParseType (T));
1771                 ConsumeRParen ();
1772             } else {
1773                 /* Remember the output queue pointer */
1774                 CodeMark Mark;
1775                 GetCodePos (&Mark);
1776                 hie10 (Expr);
1777                 /* If the expression is a literal string, release it, so it
1778                 ** won't be output as data if not used elsewhere.
1779                 */
1780                 if (ED_IsLocLiteral (Expr)) {
1781                     ReleaseLiteral (Expr->LVal);
1782                 }
1783                 /* Calculate the size */
1784                 Size = CheckedSizeOf (Expr->Type);
1785                 /* Remove any generated code */
1786                 RemoveCode (&Mark);
1787             }
1788             ED_MakeConstAbs (Expr, Size, type_size_t);
1789             ED_MarkAsUntested (Expr);
1790             break;
1791
1792         default:
1793             if (TypeSpecAhead ()) {
1794
1795                 /* A typecast */
1796                 TypeCast (Expr);
1797
1798             } else {
1799
1800                 /* An expression */
1801                 hie11 (Expr);
1802
1803                 /* Handle post increment */
1804                 switch (CurTok.Tok) {
1805                     case TOK_INC:   PostInc (Expr); break;
1806                     case TOK_DEC:   PostDec (Expr); break;
1807                     default:                        break;
1808                 }
1809
1810             }
1811             break;
1812     }
1813 }
1814
1815
1816
1817 static void hie_internal (const GenDesc* Ops,   /* List of generators */
1818                           ExprDesc* Expr,
1819                           void (*hienext) (ExprDesc*),
1820                           int* UsedGen)
1821 /* Helper function */
1822 {
1823     ExprDesc Expr2;
1824     CodeMark Mark1;
1825     CodeMark Mark2;
1826     const GenDesc* Gen;
1827     token_t Tok;                        /* The operator token */
1828     unsigned ltype, type;
1829     int lconst;                         /* Left operand is a constant */
1830     int rconst;                         /* Right operand is a constant */
1831
1832
1833     ExprWithCheck (hienext, Expr);
1834
1835     *UsedGen = 0;
1836     while ((Gen = FindGen (CurTok.Tok, Ops)) != 0) {
1837
1838         /* Tell the caller that we handled it's ops */
1839         *UsedGen = 1;
1840
1841         /* All operators that call this function expect an int on the lhs */
1842         if (!IsClassInt (Expr->Type)) {
1843             Error ("Integer expression expected");
1844             /* To avoid further errors, make Expr a valid int expression */
1845             ED_MakeConstAbsInt (Expr, 1);
1846         }
1847
1848         /* Remember the operator token, then skip it */
1849         Tok = CurTok.Tok;
1850         NextToken ();
1851
1852         /* Get the lhs on stack */
1853         GetCodePos (&Mark1);
1854         ltype = TypeOf (Expr->Type);
1855         lconst = ED_IsConstAbs (Expr);
1856         if (lconst) {
1857             /* Constant value */
1858             GetCodePos (&Mark2);
1859             /* If the operator is commutative, don't push the left side, if
1860             ** it's a constant, since we will exchange both operands.
1861             */
1862             if ((Gen->Flags & GEN_COMM) == 0) {
1863                 g_push (ltype | CF_CONST, Expr->IVal);
1864             }
1865         } else {
1866             /* Value not constant */
1867             LoadExpr (CF_NONE, Expr);
1868             GetCodePos (&Mark2);
1869             g_push (ltype, 0);
1870         }
1871
1872         /* Get the right hand side */
1873         MarkedExprWithCheck (hienext, &Expr2);
1874
1875         /* Check for a constant expression */
1876         rconst = (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2));
1877         if (!rconst) {
1878             /* Not constant, load into the primary */
1879             LoadExpr (CF_NONE, &Expr2);
1880         }
1881
1882         /* Check the type of the rhs */
1883         if (!IsClassInt (Expr2.Type)) {
1884             Error ("Integer expression expected");
1885         }
1886
1887         /* Check for const operands */
1888         if (lconst && rconst) {
1889
1890             /* Both operands are constant, remove the generated code */
1891             RemoveCode (&Mark1);
1892
1893             /* Get the type of the result */
1894             Expr->Type = promoteint (Expr->Type, Expr2.Type);
1895
1896             /* Handle the op differently for signed and unsigned types */
1897             if (IsSignSigned (Expr->Type)) {
1898
1899                 /* Evaluate the result for signed operands */
1900                 signed long Val1 = Expr->IVal;
1901                 signed long Val2 = Expr2.IVal;
1902                 switch (Tok) {
1903                     case TOK_OR:
1904                         Expr->IVal = (Val1 | Val2);
1905                         break;
1906                     case TOK_XOR:
1907                         Expr->IVal = (Val1 ^ Val2);
1908                         break;
1909                     case TOK_AND:
1910                         Expr->IVal = (Val1 & Val2);
1911                         break;
1912                     case TOK_STAR:
1913                         Expr->IVal = (Val1 * Val2);
1914                         break;
1915                     case TOK_DIV:
1916                         if (Val2 == 0) {
1917                             Error ("Division by zero");
1918                             Expr->IVal = 0x7FFFFFFF;
1919                         } else {
1920                             Expr->IVal = (Val1 / Val2);
1921                         }
1922                         break;
1923                     case TOK_MOD:
1924                         if (Val2 == 0) {
1925                             Error ("Modulo operation with zero");
1926                             Expr->IVal = 0;
1927                         } else {
1928                             Expr->IVal = (Val1 % Val2);
1929                         }
1930                         break;
1931                     default:
1932                         Internal ("hie_internal: got token 0x%X\n", Tok);
1933                 }
1934             } else {
1935
1936                 /* Evaluate the result for unsigned operands */
1937                 unsigned long Val1 = Expr->IVal;
1938                 unsigned long Val2 = Expr2.IVal;
1939                 switch (Tok) {
1940                     case TOK_OR:
1941                         Expr->IVal = (Val1 | Val2);
1942                         break;
1943                     case TOK_XOR:
1944                         Expr->IVal = (Val1 ^ Val2);
1945                         break;
1946                     case TOK_AND:
1947                         Expr->IVal = (Val1 & Val2);
1948                         break;
1949                     case TOK_STAR:
1950                         Expr->IVal = (Val1 * Val2);
1951                         break;
1952                     case TOK_DIV:
1953                         if (Val2 == 0) {
1954                             Error ("Division by zero");
1955                             Expr->IVal = 0xFFFFFFFF;
1956                         } else {
1957                             Expr->IVal = (Val1 / Val2);
1958                         }
1959                         break;
1960                     case TOK_MOD:
1961                         if (Val2 == 0) {
1962                             Error ("Modulo operation with zero");
1963                             Expr->IVal = 0;
1964                         } else {
1965                             Expr->IVal = (Val1 % Val2);
1966                         }
1967                         break;
1968                     default:
1969                         Internal ("hie_internal: got token 0x%X\n", Tok);
1970                 }
1971             }
1972
1973         } else if (lconst && (Gen->Flags & GEN_COMM) && !rconst) {
1974
1975             /* The left side is constant, the right side is not, and the
1976             ** operator allows swapping the operands. We haven't pushed the
1977             ** left side onto the stack in this case, and will reverse the
1978             ** operation because this allows for better code.
1979             */
1980             unsigned rtype = ltype | CF_CONST;
1981             ltype = TypeOf (Expr2.Type);       /* Expr2 is now left */
1982             type = CF_CONST;
1983             if ((Gen->Flags & GEN_NOPUSH) == 0) {
1984                 g_push (ltype, 0);
1985             } else {
1986                 ltype |= CF_REG;        /* Value is in register */
1987             }
1988
1989             /* Determine the type of the operation result. */
1990             type |= g_typeadjust (ltype, rtype);
1991             Expr->Type = promoteint (Expr->Type, Expr2.Type);
1992
1993             /* Generate code */
1994             Gen->Func (type, Expr->IVal);
1995
1996             /* We have a rvalue in the primary now */
1997             ED_MakeRValExpr (Expr);
1998
1999         } else {
2000
2001             /* If the right hand side is constant, and the generator function
2002             ** expects the lhs in the primary, remove the push of the primary
2003             ** now.
2004             */
2005             unsigned rtype = TypeOf (Expr2.Type);
2006             type = 0;
2007             if (rconst) {
2008                 /* Second value is constant - check for div */
2009                 type |= CF_CONST;
2010                 rtype |= CF_CONST;
2011                 if (Tok == TOK_DIV && Expr2.IVal == 0) {
2012                     Error ("Division by zero");
2013                 } else if (Tok == TOK_MOD && Expr2.IVal == 0) {
2014                     Error ("Modulo operation with zero");
2015                 }
2016                 if ((Gen->Flags & GEN_NOPUSH) != 0) {
2017                     RemoveCode (&Mark2);
2018                     ltype |= CF_REG;    /* Value is in register */
2019                 }
2020             }
2021
2022             /* Determine the type of the operation result. */
2023             type |= g_typeadjust (ltype, rtype);
2024             Expr->Type = promoteint (Expr->Type, Expr2.Type);
2025
2026             /* Generate code */
2027             Gen->Func (type, Expr2.IVal);
2028
2029             /* We have a rvalue in the primary now */
2030             ED_MakeRValExpr (Expr);
2031         }
2032     }
2033 }
2034
2035
2036
2037 static void hie_compare (const GenDesc* Ops,    /* List of generators */
2038                          ExprDesc* Expr,
2039                          void (*hienext) (ExprDesc*))
2040 /* Helper function for the compare operators */
2041 {
2042     ExprDesc Expr2;
2043     CodeMark Mark0;
2044     CodeMark Mark1;
2045     CodeMark Mark2;
2046     const GenDesc* Gen;
2047     token_t Tok;                        /* The operator token */
2048     unsigned ltype;
2049     int rconst;                         /* Operand is a constant */
2050
2051
2052     GetCodePos (&Mark0);
2053     ExprWithCheck (hienext, Expr);
2054
2055     while ((Gen = FindGen (CurTok.Tok, Ops)) != 0) {
2056
2057         /* Remember the generator function */
2058         void (*GenFunc) (unsigned, unsigned long) = Gen->Func;
2059
2060         /* Remember the operator token, then skip it */
2061         Tok = CurTok.Tok;
2062         NextToken ();
2063
2064         /* If lhs is a function, convert it to pointer to function */
2065         if (IsTypeFunc (Expr->Type)) {
2066             Expr->Type = PointerTo (Expr->Type);
2067         }
2068
2069         /* Get the lhs on stack */
2070         GetCodePos (&Mark1);
2071         ltype = TypeOf (Expr->Type);
2072         if (ED_IsConstAbs (Expr)) {
2073             /* Constant value */
2074             GetCodePos (&Mark2);
2075             g_push (ltype | CF_CONST, Expr->IVal);
2076         } else {
2077             /* Value not constant */
2078             LoadExpr (CF_NONE, Expr);
2079             GetCodePos (&Mark2);
2080             g_push (ltype, 0);
2081         }
2082
2083         /* Get the right hand side */
2084         MarkedExprWithCheck (hienext, &Expr2);
2085
2086         /* If rhs is a function, convert it to pointer to function */
2087         if (IsTypeFunc (Expr2.Type)) {
2088             Expr2.Type = PointerTo (Expr2.Type);
2089         }
2090
2091         /* Check for a constant expression */
2092         rconst = (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2));
2093         if (!rconst) {
2094             /* Not constant, load into the primary */
2095             LoadExpr (CF_NONE, &Expr2);
2096         }
2097
2098         /* Some operations aren't allowed on function pointers */
2099         if ((Gen->Flags & GEN_NOFUNC) != 0) {
2100             /* Output only one message even if both sides are wrong */
2101             if (IsTypeFuncPtr (Expr->Type)) {
2102                 Error ("Invalid left operand for relational operator");
2103                 /* Avoid further errors */
2104                 ED_MakeConstAbsInt (Expr, 0);
2105                 ED_MakeConstAbsInt (&Expr2, 0);
2106             } else if (IsTypeFuncPtr (Expr2.Type)) {
2107                 Error ("Invalid right operand for relational operator");
2108                 /* Avoid further errors */
2109                 ED_MakeConstAbsInt (Expr, 0);
2110                 ED_MakeConstAbsInt (&Expr2, 0);
2111             }
2112         }
2113
2114         /* Make sure, the types are compatible */
2115         if (IsClassInt (Expr->Type)) {
2116             if (!IsClassInt (Expr2.Type) && !(IsClassPtr(Expr2.Type) && ED_IsNullPtr(Expr))) {
2117                 Error ("Incompatible types");
2118             }
2119         } else if (IsClassPtr (Expr->Type)) {
2120             if (IsClassPtr (Expr2.Type)) {
2121                 /* Both pointers are allowed in comparison if they point to
2122                 ** the same type, or if one of them is a void pointer.
2123                 */
2124                 Type* left  = Indirect (Expr->Type);
2125                 Type* right = Indirect (Expr2.Type);
2126                 if (TypeCmp (left, right) < TC_QUAL_DIFF && left->C != T_VOID && right->C != T_VOID) {
2127                     /* Incompatible pointers */
2128                     Error ("Incompatible types");
2129                 }
2130             } else if (!ED_IsNullPtr (&Expr2)) {
2131                 Error ("Incompatible types");
2132             }
2133         }
2134
2135         /* Check for const operands */
2136         if (ED_IsConstAbs (Expr) && rconst) {
2137
2138             /* If the result is constant, this is suspicious when not in
2139             ** preprocessor mode.
2140             */
2141             WarnConstCompareResult ();
2142
2143             /* Both operands are constant, remove the generated code */
2144             RemoveCode (&Mark1);
2145
2146             /* Determine if this is a signed or unsigned compare */
2147             if (IsClassInt (Expr->Type) && IsSignSigned (Expr->Type) &&
2148                 IsClassInt (Expr2.Type) && IsSignSigned (Expr2.Type)) {
2149
2150                 /* Evaluate the result for signed operands */
2151                 signed long Val1 = Expr->IVal;
2152                 signed long Val2 = Expr2.IVal;
2153                 switch (Tok) {
2154                     case TOK_EQ: Expr->IVal = (Val1 == Val2);   break;
2155                     case TOK_NE: Expr->IVal = (Val1 != Val2);   break;
2156                     case TOK_LT: Expr->IVal = (Val1 < Val2);    break;
2157                     case TOK_LE: Expr->IVal = (Val1 <= Val2);   break;
2158                     case TOK_GE: Expr->IVal = (Val1 >= Val2);   break;
2159                     case TOK_GT: Expr->IVal = (Val1 > Val2);    break;
2160                     default:     Internal ("hie_compare: got token 0x%X\n", Tok);
2161                 }
2162
2163             } else {
2164
2165                 /* Evaluate the result for unsigned operands */
2166                 unsigned long Val1 = Expr->IVal;
2167                 unsigned long Val2 = Expr2.IVal;
2168                 switch (Tok) {
2169                     case TOK_EQ: Expr->IVal = (Val1 == Val2);   break;
2170                     case TOK_NE: Expr->IVal = (Val1 != Val2);   break;
2171                     case TOK_LT: Expr->IVal = (Val1 < Val2);    break;
2172                     case TOK_LE: Expr->IVal = (Val1 <= Val2);   break;
2173                     case TOK_GE: Expr->IVal = (Val1 >= Val2);   break;
2174                     case TOK_GT: Expr->IVal = (Val1 > Val2);    break;
2175                     default:     Internal ("hie_compare: got token 0x%X\n", Tok);
2176                 }
2177             }
2178
2179         } else {
2180
2181             /* Determine the signedness of the operands */
2182             int LeftSigned  = IsSignSigned (Expr->Type);
2183             int RightSigned = IsSignSigned (Expr2.Type);
2184
2185             /* If the right hand side is constant, and the generator function
2186             ** expects the lhs in the primary, remove the push of the primary
2187             ** now.
2188             */
2189             unsigned flags = 0;
2190             if (rconst) {
2191                 flags |= CF_CONST;
2192                 if ((Gen->Flags & GEN_NOPUSH) != 0) {
2193                     RemoveCode (&Mark2);
2194                     ltype |= CF_REG;    /* Value is in register */
2195                 }
2196             }
2197
2198             /* Determine the type of the operation. */
2199             if (IsTypeChar (Expr->Type) && rconst) {
2200
2201                 /* Left side is unsigned char, right side is constant.
2202                 ** Determine the minimum and maximum values
2203                 */
2204                 int LeftMin, LeftMax;
2205                 if (LeftSigned) {
2206                     LeftMin = -128;
2207                     LeftMax = 127;
2208                 } else {
2209                     LeftMin = 0;
2210                     LeftMax = 255;
2211                 }
2212                 /* An integer value is always represented as a signed in the
2213                 ** ExprDesc structure. This may lead to false results below,
2214                 ** if it is actually unsigned, but interpreted as signed
2215                 ** because of the representation. Fortunately, in this case,
2216                 ** the actual value doesn't matter, since it's always greater
2217                 ** than what can be represented in a char. So correct the
2218                 ** value accordingly.
2219                 */
2220                 if (!RightSigned && Expr2.IVal < 0) {
2221                     /* Correct the value so it is an unsigned. It will then
2222                     ** anyway match one of the cases below.
2223                     */
2224                     Expr2.IVal = LeftMax + 1;
2225                 }
2226
2227                 /* Comparing a char against a constant may have a constant
2228                 ** result. Please note: It is not possible to remove the code
2229                 ** for the compare alltogether, because it may have side
2230                 ** effects.
2231                 */
2232                 switch (Tok) {
2233
2234                     case TOK_EQ:
2235                         if (Expr2.IVal < LeftMin || Expr2.IVal > LeftMax) {
2236                             ED_MakeConstAbsInt (Expr, 0);
2237                             WarnConstCompareResult ();
2238                             goto Done;
2239                         }
2240                         break;
2241
2242                     case TOK_NE:
2243                         if (Expr2.IVal < LeftMin || Expr2.IVal > LeftMax) {
2244                             ED_MakeConstAbsInt (Expr, 1);
2245                             WarnConstCompareResult ();
2246                             goto Done;
2247                         }
2248                         break;
2249
2250                     case TOK_LT:
2251                         if (Expr2.IVal <= LeftMin || Expr2.IVal > LeftMax) {
2252                             ED_MakeConstAbsInt (Expr, Expr2.IVal > LeftMax);
2253                             WarnConstCompareResult ();
2254                             goto Done;
2255                         }
2256                         break;
2257
2258                     case TOK_LE:
2259                         if (Expr2.IVal < LeftMin || Expr2.IVal >= LeftMax) {
2260                             ED_MakeConstAbsInt (Expr, Expr2.IVal >= LeftMax);
2261                             WarnConstCompareResult ();
2262                             goto Done;
2263                         }
2264                         break;
2265
2266                     case TOK_GE:
2267                         if (Expr2.IVal <= LeftMin || Expr2.IVal > LeftMax) {
2268                             ED_MakeConstAbsInt (Expr, Expr2.IVal <= LeftMin);
2269                             WarnConstCompareResult ();
2270                             goto Done;
2271                         }
2272                         break;
2273
2274                     case TOK_GT:
2275                         if (Expr2.IVal < LeftMin || Expr2.IVal >= LeftMax) {
2276                             ED_MakeConstAbsInt (Expr, Expr2.IVal < LeftMin);
2277                             WarnConstCompareResult ();
2278                             goto Done;
2279                         }
2280                         break;
2281
2282                     default:
2283                         Internal ("hie_compare: got token 0x%X\n", Tok);
2284                 }
2285
2286                 /* If the result is not already constant (as evaluated in the
2287                 ** switch above), we can execute the operation as a char op,
2288                 ** since the right side constant is in a valid range.
2289                 */
2290                 flags |= (CF_CHAR | CF_FORCECHAR);
2291                 if (!LeftSigned) {
2292                     flags |= CF_UNSIGNED;
2293                 }
2294
2295             } else if (IsTypeChar (Expr->Type) && IsTypeChar (Expr2.Type) &&
2296                 GetSignedness (Expr->Type) == GetSignedness (Expr2.Type)) {
2297
2298                 /* Both are chars with the same signedness. We can encode the
2299                 ** operation as a char operation.
2300                 */
2301                 flags |= CF_CHAR;
2302                 if (rconst) {
2303                     flags |= CF_FORCECHAR;
2304                 }
2305                 if (!LeftSigned) {
2306                     flags |= CF_UNSIGNED;
2307                 }
2308             } else {
2309                 unsigned rtype = TypeOf (Expr2.Type) | (flags & CF_CONST);
2310                 flags |= g_typeadjust (ltype, rtype);
2311             }
2312
2313             /* If the left side is an unsigned and the right is a constant,
2314             ** we may be able to change the compares to something more
2315             ** effective.
2316             */
2317             if (!LeftSigned && rconst) {
2318
2319                 switch (Tok) {
2320
2321                     case TOK_LT:
2322                         if (Expr2.IVal == 1) {
2323                             /* An unsigned compare to one means that the value
2324                             ** must be zero.
2325                             */
2326                             GenFunc = g_eq;
2327                             Expr2.IVal = 0;
2328                         }
2329                         break;
2330
2331                     case TOK_LE:
2332                         if (Expr2.IVal == 0) {
2333                             /* An unsigned compare to zero means that the value
2334                             ** must be zero.
2335                             */
2336                             GenFunc = g_eq;
2337                         }
2338                         break;
2339
2340                     case TOK_GE:
2341                         if (Expr2.IVal == 1) {
2342                             /* An unsigned compare to one means that the value
2343                             ** must not be zero.
2344                             */
2345                             GenFunc = g_ne;
2346                             Expr2.IVal = 0;
2347                         }
2348                         break;
2349
2350                     case TOK_GT:
2351                         if (Expr2.IVal == 0) {
2352                             /* An unsigned compare to zero means that the value
2353                             ** must not be zero.
2354                             */
2355                             GenFunc = g_ne;
2356                         }
2357                         break;
2358
2359                     default:
2360                         break;
2361
2362                 }
2363
2364             }
2365
2366             /* Generate code */
2367             GenFunc (flags, Expr2.IVal);
2368
2369             /* The result is an rvalue in the primary */
2370             ED_MakeRValExpr (Expr);
2371         }
2372
2373         /* Result type is always int */
2374         Expr->Type = type_int;
2375
2376 Done:   /* Condition codes are set */
2377         ED_TestDone (Expr);
2378     }
2379 }
2380
2381
2382
2383 static void hie9 (ExprDesc *Expr)
2384 /* Process * and / operators. */
2385 {
2386     static const GenDesc hie9_ops[] = {
2387         { TOK_STAR,     GEN_NOPUSH | GEN_COMM,  g_mul   },
2388         { TOK_DIV,      GEN_NOPUSH,             g_div   },
2389         { TOK_MOD,      GEN_NOPUSH,             g_mod   },
2390         { TOK_INVALID,  0,                      0       }
2391     };
2392     int UsedGen;
2393
2394     hie_internal (hie9_ops, Expr, hie10, &UsedGen);
2395 }
2396
2397
2398
2399 static void parseadd (ExprDesc* Expr)
2400 /* Parse an expression with the binary plus operator. Expr contains the
2401 ** unprocessed left hand side of the expression and will contain the
2402 ** result of the expression on return.
2403 */
2404 {
2405     ExprDesc Expr2;
2406     unsigned flags;             /* Operation flags */
2407     CodeMark Mark;              /* Remember code position */
2408     Type* lhst;                 /* Type of left hand side */
2409     Type* rhst;                 /* Type of right hand side */
2410
2411     /* Skip the PLUS token */
2412     NextToken ();
2413
2414     /* Get the left hand side type, initialize operation flags */
2415     lhst = Expr->Type;
2416     flags = 0;
2417
2418     /* Check for constness on both sides */
2419     if (ED_IsConst (Expr)) {
2420
2421         /* The left hand side is a constant of some sort. Good. Get rhs */
2422         ExprWithCheck (hie9, &Expr2);
2423         if (ED_IsConstAbs (&Expr2)) {
2424
2425             /* Right hand side is a constant numeric value. Get the rhs type */
2426             rhst = Expr2.Type;
2427
2428             /* Both expressions are constants. Check for pointer arithmetic */
2429             if (IsClassPtr (lhst) && IsClassInt (rhst)) {
2430                 /* Left is pointer, right is int, must scale rhs */
2431                 Expr->IVal += Expr2.IVal * CheckedPSizeOf (lhst);
2432                 /* Result type is a pointer */
2433             } else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
2434                 /* Left is int, right is pointer, must scale lhs */
2435                 Expr->IVal = Expr->IVal * CheckedPSizeOf (rhst) + Expr2.IVal;
2436                 /* Result type is a pointer */
2437                 Expr->Type = Expr2.Type;
2438             } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
2439                 /* Integer addition */
2440                 Expr->IVal += Expr2.IVal;
2441                 typeadjust (Expr, &Expr2, 1);
2442             } else {
2443                 /* OOPS */
2444                 Error ("Invalid operands for binary operator `+'");
2445             }
2446
2447         } else {
2448
2449             /* lhs is a constant and rhs is not constant. Load rhs into
2450             ** the primary.
2451             */
2452             LoadExpr (CF_NONE, &Expr2);
2453
2454             /* Beware: The check above (for lhs) lets not only pass numeric
2455             ** constants, but also constant addresses (labels), maybe even
2456             ** with an offset. We have to check for that here.
2457             */
2458
2459             /* First, get the rhs type. */
2460             rhst = Expr2.Type;
2461
2462             /* Setup flags */
2463             if (ED_IsLocAbs (Expr)) {
2464                 /* A numerical constant */
2465                 flags |= CF_CONST;
2466             } else {
2467                 /* Constant address label */
2468                 flags |= GlobalModeFlags (Expr) | CF_CONSTADDR;
2469             }
2470
2471             /* Check for pointer arithmetic */
2472             if (IsClassPtr (lhst) && IsClassInt (rhst)) {
2473                 /* Left is pointer, right is int, must scale rhs */
2474                 g_scale (CF_INT, CheckedPSizeOf (lhst));
2475                 /* Operate on pointers, result type is a pointer */
2476                 flags |= CF_PTR;
2477                 /* Generate the code for the add */
2478                 if (ED_GetLoc (Expr) == E_LOC_ABS) {
2479                     /* Numeric constant */
2480                     g_inc (flags, Expr->IVal);
2481                 } else {
2482                     /* Constant address */
2483                     g_addaddr_static (flags, Expr->Name, Expr->IVal);
2484                 }
2485             } else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
2486
2487                 /* Left is int, right is pointer, must scale lhs. */
2488                 unsigned ScaleFactor = CheckedPSizeOf (rhst);
2489
2490                 /* Operate on pointers, result type is a pointer */
2491                 flags |= CF_PTR;
2492                 Expr->Type = Expr2.Type;
2493
2494                 /* Since we do already have rhs in the primary, if lhs is
2495                 ** not a numeric constant, and the scale factor is not one
2496                 ** (no scaling), we must take the long way over the stack.
2497                 */
2498                 if (ED_IsLocAbs (Expr)) {
2499                     /* Numeric constant, scale lhs */
2500                     Expr->IVal *= ScaleFactor;
2501                     /* Generate the code for the add */
2502                     g_inc (flags, Expr->IVal);
2503                 } else if (ScaleFactor == 1) {
2504                     /* Constant address but no need to scale */
2505                     g_addaddr_static (flags, Expr->Name, Expr->IVal);
2506                 } else {
2507                     /* Constant address that must be scaled */
2508                     g_push (TypeOf (Expr2.Type), 0);    /* rhs --> stack */
2509                     g_getimmed (flags, Expr->Name, Expr->IVal);
2510                     g_scale (CF_PTR, ScaleFactor);
2511                     g_add (CF_PTR, 0);
2512                 }
2513             } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
2514                 /* Integer addition */
2515                 flags |= typeadjust (Expr, &Expr2, 1);
2516                 /* Generate the code for the add */
2517                 if (ED_IsLocAbs (Expr)) {
2518                     /* Numeric constant */
2519                     g_inc (flags, Expr->IVal);
2520                 } else {
2521                     /* Constant address */
2522                     g_addaddr_static (flags, Expr->Name, Expr->IVal);
2523                 }
2524             } else {
2525                 /* OOPS */
2526                 Error ("Invalid operands for binary operator `+'");
2527                 flags = CF_INT;
2528             }
2529
2530             /* Result is a rvalue in primary register */
2531             ED_MakeRValExpr (Expr);
2532         }
2533
2534     } else {
2535
2536         /* Left hand side is not constant. Get the value onto the stack. */
2537         LoadExpr (CF_NONE, Expr);              /* --> primary register */
2538         GetCodePos (&Mark);
2539         g_push (TypeOf (Expr->Type), 0);        /* --> stack */
2540
2541         /* Evaluate the rhs */
2542         MarkedExprWithCheck (hie9, &Expr2);
2543
2544         /* Check for a constant rhs expression */
2545         if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) {
2546
2547             /* Right hand side is a constant. Get the rhs type */
2548             rhst = Expr2.Type;
2549
2550             /* Remove pushed value from stack */
2551             RemoveCode (&Mark);
2552
2553             /* Check for pointer arithmetic */
2554             if (IsClassPtr (lhst) && IsClassInt (rhst)) {
2555                 /* Left is pointer, right is int, must scale rhs */
2556                 Expr2.IVal *= CheckedPSizeOf (lhst);
2557                 /* Operate on pointers, result type is a pointer */
2558                 flags = CF_PTR;
2559             } else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
2560                 /* Left is int, right is pointer, must scale lhs (ptr only) */
2561                 g_scale (CF_INT | CF_CONST, CheckedPSizeOf (rhst));
2562                 /* Operate on pointers, result type is a pointer */
2563                 flags = CF_PTR;
2564                 Expr->Type = Expr2.Type;
2565             } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
2566                 /* Integer addition */
2567                 flags = typeadjust (Expr, &Expr2, 1);
2568             } else {
2569                 /* OOPS */
2570                 Error ("Invalid operands for binary operator `+'");
2571                 flags = CF_INT;
2572             }
2573
2574             /* Generate code for the add */
2575             g_inc (flags | CF_CONST, Expr2.IVal);
2576
2577         } else {
2578
2579             /* Not constant, load into the primary */
2580             LoadExpr (CF_NONE, &Expr2);
2581
2582             /* lhs and rhs are not constant. Get the rhs type. */
2583             rhst = Expr2.Type;
2584
2585             /* Check for pointer arithmetic */
2586             if (IsClassPtr (lhst) && IsClassInt (rhst)) {
2587                 /* Left is pointer, right is int, must scale rhs */
2588                 g_scale (CF_INT, CheckedPSizeOf (lhst));
2589                 /* Operate on pointers, result type is a pointer */
2590                 flags = CF_PTR;
2591             } else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
2592                 /* Left is int, right is pointer, must scale lhs */
2593                 g_tosint (TypeOf (lhst));       /* Make sure TOS is int */
2594                 g_swap (CF_INT);                /* Swap TOS and primary */
2595                 g_scale (CF_INT, CheckedPSizeOf (rhst));
2596                 /* Operate on pointers, result type is a pointer */
2597                 flags = CF_PTR;
2598                 Expr->Type = Expr2.Type;
2599             } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
2600                 /* Integer addition. Note: Result is never constant.
2601                 ** Problem here is that typeadjust does not know if the
2602                 ** variable is an rvalue or lvalue, so if both operands
2603                 ** are dereferenced constant numeric addresses, typeadjust
2604                 ** thinks the operation works on constants. Removing
2605                 ** CF_CONST here means handling the symptoms, however, the
2606                 ** whole parser is such a mess that I fear to break anything
2607                 ** when trying to apply another solution.
2608                 */
2609                 flags = typeadjust (Expr, &Expr2, 0) & ~CF_CONST;
2610             } else {
2611                 /* OOPS */
2612                 Error ("Invalid operands for binary operator `+'");
2613                 flags = CF_INT;
2614             }
2615
2616             /* Generate code for the add */
2617             g_add (flags, 0);
2618
2619         }
2620
2621         /* Result is a rvalue in primary register */
2622         ED_MakeRValExpr (Expr);
2623     }
2624
2625     /* Condition codes not set */
2626     ED_MarkAsUntested (Expr);
2627 }
2628
2629
2630
2631 static void parsesub (ExprDesc* Expr)
2632 /* Parse an expression with the binary minus operator. Expr contains the
2633 ** unprocessed left hand side of the expression and will contain the
2634 ** result of the expression on return.
2635 */
2636 {
2637     ExprDesc Expr2;
2638     unsigned flags;             /* Operation flags */
2639     Type* lhst;                 /* Type of left hand side */
2640     Type* rhst;                 /* Type of right hand side */
2641     CodeMark Mark1;             /* Save position of output queue */
2642     CodeMark Mark2;             /* Another position in the queue */
2643     int rscale;                 /* Scale factor for the result */
2644
2645
2646     /* lhs cannot be function or pointer to function */
2647     if (IsTypeFunc (Expr->Type) || IsTypeFuncPtr (Expr->Type)) {
2648         Error ("Invalid left operand for binary operator `-'");
2649         /* Make it pointer to char to avoid further errors */
2650         Expr->Type = type_uchar;
2651     }
2652
2653     /* Skip the MINUS token */
2654     NextToken ();
2655
2656     /* Get the left hand side type, initialize operation flags */
2657     lhst = Expr->Type;
2658     rscale = 1;                 /* Scale by 1, that is, don't scale */
2659
2660     /* Remember the output queue position, then bring the value onto the stack */
2661     GetCodePos (&Mark1);
2662     LoadExpr (CF_NONE, Expr);  /* --> primary register */
2663     GetCodePos (&Mark2);
2664     g_push (TypeOf (lhst), 0);  /* --> stack */
2665
2666     /* Parse the right hand side */
2667     MarkedExprWithCheck (hie9, &Expr2);
2668
2669     /* rhs cannot be function or pointer to function */
2670     if (IsTypeFunc (Expr2.Type) || IsTypeFuncPtr (Expr2.Type)) {
2671         Error ("Invalid right operand for binary operator `-'");
2672         /* Make it pointer to char to avoid further errors */
2673         Expr2.Type = type_uchar;
2674     }
2675
2676     /* Check for a constant rhs expression */
2677     if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) {
2678
2679         /* The right hand side is constant. Get the rhs type. */
2680         rhst = Expr2.Type;
2681
2682         /* Check left hand side */
2683         if (ED_IsConstAbs (Expr)) {
2684
2685             /* Both sides are constant, remove generated code */
2686             RemoveCode (&Mark1);
2687
2688             /* Check for pointer arithmetic */
2689             if (IsClassPtr (lhst) && IsClassInt (rhst)) {
2690                 /* Left is pointer, right is int, must scale rhs */
2691                 Expr->IVal -= Expr2.IVal * CheckedPSizeOf (lhst);
2692                 /* Operate on pointers, result type is a pointer */
2693             } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
2694                 /* Left is pointer, right is pointer, must scale result */
2695                 if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) {
2696                     Error ("Incompatible pointer types");
2697                 } else {
2698                     Expr->IVal = (Expr->IVal - Expr2.IVal) /
2699                                       CheckedPSizeOf (lhst);
2700                 }
2701                 /* Operate on pointers, result type is an integer */
2702                 Expr->Type = type_int;
2703             } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
2704                 /* Integer subtraction */
2705                 typeadjust (Expr, &Expr2, 1);
2706                 Expr->IVal -= Expr2.IVal;
2707             } else {
2708                 /* OOPS */
2709                 Error ("Invalid operands for binary operator `-'");
2710             }
2711
2712             /* Result is constant, condition codes not set */
2713             ED_MarkAsUntested (Expr);
2714
2715         } else {
2716
2717             /* Left hand side is not constant, right hand side is.
2718             ** Remove pushed value from stack.
2719             */
2720             RemoveCode (&Mark2);
2721
2722             if (IsClassPtr (lhst) && IsClassInt (rhst)) {
2723                 /* Left is pointer, right is int, must scale rhs */
2724                 Expr2.IVal *= CheckedPSizeOf (lhst);
2725                 /* Operate on pointers, result type is a pointer */
2726                 flags = CF_PTR;
2727             } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
2728                 /* Left is pointer, right is pointer, must scale result */
2729                 if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) {
2730                     Error ("Incompatible pointer types");
2731                 } else {
2732                     rscale = CheckedPSizeOf (lhst);
2733                 }
2734                 /* Operate on pointers, result type is an integer */
2735                 flags = CF_PTR;
2736                 Expr->Type = type_int;
2737             } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
2738                 /* Integer subtraction */
2739                 flags = typeadjust (Expr, &Expr2, 1);
2740             } else {
2741                 /* OOPS */
2742                 Error ("Invalid operands for binary operator `-'");
2743                 flags = CF_INT;
2744             }
2745
2746             /* Do the subtraction */
2747             g_dec (flags | CF_CONST, Expr2.IVal);
2748
2749             /* If this was a pointer subtraction, we must scale the result */
2750             if (rscale != 1) {
2751                 g_scale (flags, -rscale);
2752             }
2753
2754             /* Result is a rvalue in the primary register */
2755             ED_MakeRValExpr (Expr);
2756             ED_MarkAsUntested (Expr);
2757
2758         }
2759
2760     } else {
2761
2762         /* Not constant, load into the primary */
2763         LoadExpr (CF_NONE, &Expr2);
2764
2765         /* Right hand side is not constant. Get the rhs type. */
2766         rhst = Expr2.Type;
2767
2768         /* Check for pointer arithmetic */
2769         if (IsClassPtr (lhst) && IsClassInt (rhst)) {
2770             /* Left is pointer, right is int, must scale rhs */
2771             g_scale (CF_INT, CheckedPSizeOf (lhst));
2772             /* Operate on pointers, result type is a pointer */
2773             flags = CF_PTR;
2774         } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
2775             /* Left is pointer, right is pointer, must scale result */
2776             if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) {
2777                 Error ("Incompatible pointer types");
2778             } else {
2779                 rscale = CheckedPSizeOf (lhst);
2780             }
2781             /* Operate on pointers, result type is an integer */
2782             flags = CF_PTR;
2783             Expr->Type = type_int;
2784         } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
2785             /* Integer subtraction. If the left hand side descriptor says that
2786             ** the lhs is const, we have to remove this mark, since this is no
2787             ** longer true, lhs is on stack instead.
2788             */
2789             if (ED_IsLocAbs (Expr)) {
2790                 ED_MakeRValExpr (Expr);
2791             }
2792             /* Adjust operand types */
2793             flags = typeadjust (Expr, &Expr2, 0);
2794         } else {
2795             /* OOPS */
2796             Error ("Invalid operands for binary operator `-'");
2797             flags = CF_INT;
2798         }
2799
2800         /* Generate code for the sub (the & is a hack here) */
2801         g_sub (flags & ~CF_CONST, 0);
2802
2803         /* If this was a pointer subtraction, we must scale the result */
2804         if (rscale != 1) {
2805             g_scale (flags, -rscale);
2806         }
2807
2808         /* Result is a rvalue in the primary register */
2809         ED_MakeRValExpr (Expr);
2810         ED_MarkAsUntested (Expr);
2811     }
2812 }
2813
2814
2815
2816 void hie8 (ExprDesc* Expr)
2817 /* Process + and - binary operators. */
2818 {
2819     ExprWithCheck (hie9, Expr);
2820     while (CurTok.Tok == TOK_PLUS || CurTok.Tok == TOK_MINUS) {
2821         if (CurTok.Tok == TOK_PLUS) {
2822             parseadd (Expr);
2823         } else {
2824             parsesub (Expr);
2825         }
2826     }
2827 }
2828
2829
2830
2831 static void hie6 (ExprDesc* Expr)
2832 /* Handle greater-than type comparators */
2833 {
2834     static const GenDesc hie6_ops [] = {
2835         { TOK_LT,       GEN_NOPUSH | GEN_NOFUNC,     g_lt    },
2836         { TOK_LE,       GEN_NOPUSH | GEN_NOFUNC,     g_le    },
2837         { TOK_GE,       GEN_NOPUSH | GEN_NOFUNC,     g_ge    },
2838         { TOK_GT,       GEN_NOPUSH | GEN_NOFUNC,     g_gt    },
2839         { TOK_INVALID,  0,                           0       }
2840     };
2841     hie_compare (hie6_ops, Expr, ShiftExpr);
2842 }
2843
2844
2845
2846 static void hie5 (ExprDesc* Expr)
2847 /* Handle == and != */
2848 {
2849     static const GenDesc hie5_ops[] = {
2850         { TOK_EQ,       GEN_NOPUSH,     g_eq    },
2851         { TOK_NE,       GEN_NOPUSH,     g_ne    },
2852         { TOK_INVALID,  0,              0       }
2853     };
2854     hie_compare (hie5_ops, Expr, hie6);
2855 }
2856
2857
2858
2859 static void hie4 (ExprDesc* Expr)
2860 /* Handle & (bitwise and) */
2861 {
2862     static const GenDesc hie4_ops[] = {
2863         { TOK_AND,      GEN_NOPUSH | GEN_COMM,  g_and   },
2864         { TOK_INVALID,  0,                      0       }
2865     };
2866     int UsedGen;
2867
2868     hie_internal (hie4_ops, Expr, hie5, &UsedGen);
2869 }
2870
2871
2872
2873 static void hie3 (ExprDesc* Expr)
2874 /* Handle ^ (bitwise exclusive or) */
2875 {
2876     static const GenDesc hie3_ops[] = {
2877         { TOK_XOR,      GEN_NOPUSH | GEN_COMM,  g_xor   },
2878         { TOK_INVALID,  0,                      0       }
2879     };
2880     int UsedGen;
2881
2882     hie_internal (hie3_ops, Expr, hie4, &UsedGen);
2883 }
2884
2885
2886
2887 static void hie2 (ExprDesc* Expr)
2888 /* Handle | (bitwise or) */
2889 {
2890     static const GenDesc hie2_ops[] = {
2891         { TOK_OR,       GEN_NOPUSH | GEN_COMM,  g_or    },
2892         { TOK_INVALID,  0,                      0       }
2893     };
2894     int UsedGen;
2895
2896     hie_internal (hie2_ops, Expr, hie3, &UsedGen);
2897 }
2898
2899
2900
2901 static void hieAndPP (ExprDesc* Expr)
2902 /* Process "exp && exp" in preprocessor mode (that is, when the parser is
2903 ** called recursively from the preprocessor.
2904 */
2905 {
2906     ExprDesc Expr2;
2907
2908     ConstAbsIntExpr (hie2, Expr);
2909     while (CurTok.Tok == TOK_BOOL_AND) {
2910
2911         /* Skip the && */
2912         NextToken ();
2913
2914         /* Get rhs */
2915         ConstAbsIntExpr (hie2, &Expr2);
2916
2917         /* Combine the two */
2918         Expr->IVal = (Expr->IVal && Expr2.IVal);
2919     }
2920 }
2921
2922
2923
2924 static void hieOrPP (ExprDesc *Expr)
2925 /* Process "exp || exp" in preprocessor mode (that is, when the parser is
2926 ** called recursively from the preprocessor.
2927 */
2928 {
2929     ExprDesc Expr2;
2930
2931     ConstAbsIntExpr (hieAndPP, Expr);
2932     while (CurTok.Tok == TOK_BOOL_OR) {
2933
2934         /* Skip the && */
2935         NextToken ();
2936
2937         /* Get rhs */
2938         ConstAbsIntExpr (hieAndPP, &Expr2);
2939
2940         /* Combine the two */
2941         Expr->IVal = (Expr->IVal || Expr2.IVal);
2942     }
2943 }
2944
2945
2946
2947 static void hieAnd (ExprDesc* Expr, unsigned TrueLab, int* BoolOp)
2948 /* Process "exp && exp" */
2949 {
2950     int FalseLab;
2951     ExprDesc Expr2;
2952
2953     ExprWithCheck (hie2, Expr);
2954     if (CurTok.Tok == TOK_BOOL_AND) {
2955
2956         /* Tell our caller that we're evaluating a boolean */
2957         *BoolOp = 1;
2958
2959         /* Get a label that we will use for false expressions */
2960         FalseLab = GetLocalLabel ();
2961
2962         /* If the expr hasn't set condition codes, set the force-test flag */
2963         if (!ED_IsTested (Expr)) {
2964             ED_MarkForTest (Expr);
2965         }
2966
2967         /* Load the value */
2968         LoadExpr (CF_FORCECHAR, Expr);
2969
2970         /* Generate the jump */
2971         g_falsejump (CF_NONE, FalseLab);
2972
2973         /* Parse more boolean and's */
2974         while (CurTok.Tok == TOK_BOOL_AND) {
2975
2976             /* Skip the && */
2977             NextToken ();
2978
2979             /* Get rhs */
2980             hie2 (&Expr2);
2981             if (!ED_IsTested (&Expr2)) {
2982                 ED_MarkForTest (&Expr2);
2983             }
2984             LoadExpr (CF_FORCECHAR, &Expr2);
2985
2986             /* Do short circuit evaluation */
2987             if (CurTok.Tok == TOK_BOOL_AND) {
2988                 g_falsejump (CF_NONE, FalseLab);
2989             } else {
2990                 /* Last expression - will evaluate to true */
2991                 g_truejump (CF_NONE, TrueLab);
2992             }
2993         }
2994
2995         /* Define the false jump label here */
2996         g_defcodelabel (FalseLab);
2997
2998         /* The result is an rvalue in primary */
2999         ED_MakeRValExpr (Expr);
3000         ED_TestDone (Expr);     /* Condition codes are set */
3001     }
3002 }
3003
3004
3005
3006 static void hieOr (ExprDesc *Expr)
3007 /* Process "exp || exp". */
3008 {
3009     ExprDesc Expr2;
3010     int BoolOp = 0;             /* Did we have a boolean op? */
3011     int AndOp;                  /* Did we have a && operation? */
3012     unsigned TrueLab;           /* Jump to this label if true */
3013     unsigned DoneLab;
3014
3015     /* Get a label */
3016     TrueLab = GetLocalLabel ();
3017
3018     /* Call the next level parser */
3019     hieAnd (Expr, TrueLab, &BoolOp);
3020
3021     /* Any boolean or's? */
3022     if (CurTok.Tok == TOK_BOOL_OR) {
3023
3024         /* If the expr hasn't set condition codes, set the force-test flag */
3025         if (!ED_IsTested (Expr)) {
3026             ED_MarkForTest (Expr);
3027         }
3028
3029         /* Get first expr */
3030         LoadExpr (CF_FORCECHAR, Expr);
3031
3032         /* For each expression jump to TrueLab if true. Beware: If we
3033         ** had && operators, the jump is already in place!
3034         */
3035         if (!BoolOp) {
3036             g_truejump (CF_NONE, TrueLab);
3037         }
3038
3039         /* Remember that we had a boolean op */
3040         BoolOp = 1;
3041
3042         /* while there's more expr */
3043         while (CurTok.Tok == TOK_BOOL_OR) {
3044
3045             /* skip the || */
3046             NextToken ();
3047
3048             /* Get a subexpr */
3049             AndOp = 0;
3050             hieAnd (&Expr2, TrueLab, &AndOp);
3051             if (!ED_IsTested (&Expr2)) {
3052                 ED_MarkForTest (&Expr2);
3053             }
3054             LoadExpr (CF_FORCECHAR, &Expr2);
3055
3056             /* If there is more to come, add shortcut boolean eval. */
3057             g_truejump (CF_NONE, TrueLab);
3058
3059         }
3060
3061         /* The result is an rvalue in primary */
3062         ED_MakeRValExpr (Expr);
3063         ED_TestDone (Expr);                     /* Condition codes are set */
3064     }
3065
3066     /* If we really had boolean ops, generate the end sequence */
3067     if (BoolOp) {
3068         DoneLab = GetLocalLabel ();
3069         g_getimmed (CF_INT | CF_CONST, 0, 0);   /* Load FALSE */
3070         g_falsejump (CF_NONE, DoneLab);
3071         g_defcodelabel (TrueLab);
3072         g_getimmed (CF_INT | CF_CONST, 1, 0);   /* Load TRUE */
3073         g_defcodelabel (DoneLab);
3074     }
3075 }
3076
3077
3078
3079 static void hieQuest (ExprDesc* Expr)
3080 /* Parse the ternary operator */
3081 {
3082     int         FalseLab;
3083     int         TrueLab;
3084     CodeMark    TrueCodeEnd;
3085     ExprDesc    Expr2;          /* Expression 2 */
3086     ExprDesc    Expr3;          /* Expression 3 */
3087     int         Expr2IsNULL;    /* Expression 2 is a NULL pointer */
3088     int         Expr3IsNULL;    /* Expression 3 is a NULL pointer */
3089     Type*       ResultType;     /* Type of result */
3090
3091
3092     /* Call the lower level eval routine */
3093     if (Preprocessing) {
3094         ExprWithCheck (hieOrPP, Expr);
3095     } else {
3096         ExprWithCheck (hieOr, Expr);
3097     }
3098
3099     /* Check if it's a ternary expression */
3100     if (CurTok.Tok == TOK_QUEST) {
3101         NextToken ();
3102         if (!ED_IsTested (Expr)) {
3103             /* Condition codes not set, request a test */
3104             ED_MarkForTest (Expr);
3105         }
3106         LoadExpr (CF_NONE, Expr);
3107         FalseLab = GetLocalLabel ();
3108         g_falsejump (CF_NONE, FalseLab);
3109
3110         /* Parse second expression. Remember for later if it is a NULL pointer
3111         ** expression, then load it into the primary.
3112         */
3113         ExprWithCheck (hie1, &Expr2);
3114         Expr2IsNULL = ED_IsNullPtr (&Expr2);
3115         if (!IsTypeVoid (Expr2.Type)) {
3116             /* Load it into the primary */
3117             LoadExpr (CF_NONE, &Expr2);
3118             ED_MakeRValExpr (&Expr2);
3119             Expr2.Type = PtrConversion (Expr2.Type);
3120         }
3121
3122         /* Remember the current code position */
3123         GetCodePos (&TrueCodeEnd);
3124
3125         /* Jump around the evaluation of the third expression */
3126         TrueLab = GetLocalLabel ();
3127         ConsumeColon ();
3128         g_jump (TrueLab);
3129
3130         /* Jump here if the first expression was false */
3131         g_defcodelabel (FalseLab);
3132
3133         /* Parse third expression. Remember for later if it is a NULL pointer
3134         ** expression, then load it into the primary.
3135         */
3136         ExprWithCheck (hie1, &Expr3);
3137         Expr3IsNULL = ED_IsNullPtr (&Expr3);
3138         if (!IsTypeVoid (Expr3.Type)) {
3139             /* Load it into the primary */
3140             LoadExpr (CF_NONE, &Expr3);
3141             ED_MakeRValExpr (&Expr3);
3142             Expr3.Type = PtrConversion (Expr3.Type);
3143         }
3144
3145         /* Check if any conversions are needed, if so, do them.
3146         ** Conversion rules for ?: expression are:
3147         **   - if both expressions are int expressions, default promotion
3148         **     rules for ints apply.
3149         **   - if both expressions are pointers of the same type, the
3150         **     result of the expression is of this type.
3151         **   - if one of the expressions is a pointer and the other is
3152         **     a zero constant, the resulting type is that of the pointer
3153         **     type.
3154         **   - if both expressions are void expressions, the result is of
3155         **     type void.
3156         **   - all other cases are flagged by an error.
3157         */
3158         if (IsClassInt (Expr2.Type) && IsClassInt (Expr3.Type)) {
3159
3160             CodeMark    CvtCodeStart;
3161             CodeMark    CvtCodeEnd;
3162
3163
3164             /* Get common type */
3165             ResultType = promoteint (Expr2.Type, Expr3.Type);
3166
3167             /* Convert the third expression to this type if needed */
3168             TypeConversion (&Expr3, ResultType);
3169
3170             /* Emit conversion code for the second expression, but remember
3171             ** where it starts end ends.
3172             */
3173             GetCodePos (&CvtCodeStart);
3174             TypeConversion (&Expr2, ResultType);
3175             GetCodePos (&CvtCodeEnd);
3176
3177             /* If we had conversion code, move it to the right place */
3178             if (!CodeRangeIsEmpty (&CvtCodeStart, &CvtCodeEnd)) {
3179                 MoveCode (&CvtCodeStart, &CvtCodeEnd, &TrueCodeEnd);
3180             }
3181
3182         } else if (IsClassPtr (Expr2.Type) && IsClassPtr (Expr3.Type)) {
3183             /* Must point to same type */
3184             if (TypeCmp (Indirect (Expr2.Type), Indirect (Expr3.Type)) < TC_EQUAL) {
3185                 Error ("Incompatible pointer types");
3186             }
3187             /* Result has the common type */
3188             ResultType = Expr2.Type;
3189         } else if (IsClassPtr (Expr2.Type) && Expr3IsNULL) {
3190             /* Result type is pointer, no cast needed */
3191             ResultType = Expr2.Type;
3192         } else if (Expr2IsNULL && IsClassPtr (Expr3.Type)) {
3193             /* Result type is pointer, no cast needed */
3194             ResultType = Expr3.Type;
3195         } else if (IsTypeVoid (Expr2.Type) && IsTypeVoid (Expr3.Type)) {
3196             /* Result type is void */
3197             ResultType = Expr3.Type;
3198         } else {
3199             Error ("Incompatible types");
3200             ResultType = Expr2.Type;            /* Doesn't matter here */
3201         }
3202
3203         /* Define the final label */
3204         g_defcodelabel (TrueLab);
3205
3206         /* Setup the target expression */
3207         ED_MakeRValExpr (Expr);
3208         Expr->Type  = ResultType;
3209     }
3210 }
3211
3212
3213
3214 static void opeq (const GenDesc* Gen, ExprDesc* Expr, const char* Op)
3215 /* Process "op=" operators. */
3216 {
3217     ExprDesc Expr2;
3218     unsigned flags;
3219     CodeMark Mark;
3220     int MustScale;
3221
3222     /* op= can only be used with lvalues */
3223     if (!ED_IsLVal (Expr)) {
3224         Error ("Invalid lvalue in assignment");
3225         return;
3226     }
3227
3228     /* The left side must not be const qualified */
3229     if (IsQualConst (Expr->Type)) {
3230         Error ("Assignment to const");
3231     }
3232
3233     /* There must be an integer or pointer on the left side */
3234     if (!IsClassInt (Expr->Type) && !IsTypePtr (Expr->Type)) {
3235         Error ("Invalid left operand type");
3236         /* Continue. Wrong code will be generated, but the compiler won't
3237         ** break, so this is the best error recovery.
3238         */
3239     }
3240
3241     /* Skip the operator token */
3242     NextToken ();
3243
3244     /* Determine the type of the lhs */
3245     flags = TypeOf (Expr->Type);
3246     MustScale = (Gen->Func == g_add || Gen->Func == g_sub) && IsTypePtr (Expr->Type);
3247
3248     /* Get the lhs address on stack (if needed) */
3249     PushAddr (Expr);
3250
3251     /* Fetch the lhs into the primary register if needed */
3252     LoadExpr (CF_NONE, Expr);
3253
3254     /* Bring the lhs on stack */
3255     GetCodePos (&Mark);
3256     g_push (flags, 0);
3257
3258     /* Evaluate the rhs */
3259     MarkedExprWithCheck (hie1, &Expr2);
3260
3261     /* The rhs must be an integer (or a float, but we don't support that yet */
3262     if (!IsClassInt (Expr2.Type)) {
3263         Error ("Invalid right operand for binary operator `%s'", Op);
3264         /* Continue. Wrong code will be generated, but the compiler won't
3265         ** break, so this is the best error recovery.
3266         */
3267     }
3268
3269     /* Check for a constant expression */
3270     if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) {
3271         /* The resulting value is a constant. If the generator has the NOPUSH
3272         ** flag set, don't push the lhs.
3273         */
3274         if (Gen->Flags & GEN_NOPUSH) {
3275             RemoveCode (&Mark);
3276         }
3277         if (MustScale) {
3278             /* lhs is a pointer, scale rhs */
3279             Expr2.IVal *= CheckedSizeOf (Expr->Type+1);
3280         }
3281
3282         /* If the lhs is character sized, the operation may be later done
3283         ** with characters.
3284         */
3285         if (CheckedSizeOf (Expr->Type) == SIZEOF_CHAR) {
3286             flags |= CF_FORCECHAR;
3287         }
3288
3289         /* Special handling for add and sub - some sort of a hack, but short code */
3290         if (Gen->Func == g_add) {
3291             g_inc (flags | CF_CONST, Expr2.IVal);
3292         } else if (Gen->Func == g_sub) {
3293             g_dec (flags | CF_CONST, Expr2.IVal);
3294         } else {
3295             if (Expr2.IVal == 0) {
3296                 /* Check for div by zero/mod by zero */
3297                 if (Gen->Func == g_div) {
3298                     Error ("Division by zero");
3299                 } else if (Gen->Func == g_mod) {
3300                     Error ("Modulo operation with zero");
3301                 }
3302             }
3303             Gen->Func (flags | CF_CONST, Expr2.IVal);
3304         }
3305     } else {
3306
3307         /* rhs is not constant. Load into the primary */
3308         LoadExpr (CF_NONE, &Expr2);
3309         if (MustScale) {
3310             /* lhs is a pointer, scale rhs */
3311             g_scale (TypeOf (Expr2.Type), CheckedSizeOf (Expr->Type+1));
3312         }
3313
3314         /* If the lhs is character sized, the operation may be later done
3315         ** with characters.
3316         */
3317         if (CheckedSizeOf (Expr->Type) == SIZEOF_CHAR) {
3318             flags |= CF_FORCECHAR;
3319         }
3320
3321         /* Adjust the types of the operands if needed */
3322         Gen->Func (g_typeadjust (flags, TypeOf (Expr2.Type)), 0);
3323     }
3324     Store (Expr, 0);
3325     ED_MakeRValExpr (Expr);
3326 }
3327
3328
3329
3330 static void addsubeq (const GenDesc* Gen, ExprDesc *Expr, const char* Op)
3331 /* Process the += and -= operators */
3332 {
3333     ExprDesc Expr2;
3334     unsigned lflags;
3335     unsigned rflags;
3336     int      MustScale;
3337
3338
3339     /* We're currently only able to handle some adressing modes */
3340     if (ED_GetLoc (Expr) == E_LOC_EXPR || ED_GetLoc (Expr) == E_LOC_PRIMARY) {
3341         /* Use generic routine */
3342         opeq (Gen, Expr, Op);
3343         return;
3344     }
3345
3346     /* We must have an lvalue */
3347     if (ED_IsRVal (Expr)) {
3348         Error ("Invalid lvalue in assignment");
3349         return;
3350     }
3351
3352     /* The left side must not be const qualified */
3353     if (IsQualConst (Expr->Type)) {
3354         Error ("Assignment to const");
3355     }
3356
3357     /* There must be an integer or pointer on the left side */
3358     if (!IsClassInt (Expr->Type) && !IsTypePtr (Expr->Type)) {
3359         Error ("Invalid left operand type");
3360         /* Continue. Wrong code will be generated, but the compiler won't
3361         ** break, so this is the best error recovery.
3362         */
3363     }
3364
3365     /* Skip the operator */
3366     NextToken ();
3367
3368     /* Check if we have a pointer expression and must scale rhs */
3369     MustScale = IsTypePtr (Expr->Type);
3370
3371     /* Initialize the code generator flags */
3372     lflags = 0;
3373     rflags = 0;
3374
3375     /* Evaluate the rhs. We expect an integer here, since float is not
3376     ** supported
3377     */
3378     hie1 (&Expr2);
3379     if (!IsClassInt (Expr2.Type)) {
3380         Error ("Invalid right operand for binary operator `%s'", Op);
3381         /* Continue. Wrong code will be generated, but the compiler won't
3382         ** break, so this is the best error recovery.
3383         */
3384     }
3385     if (ED_IsConstAbs (&Expr2)) {
3386         /* The resulting value is a constant. Scale it. */
3387         if (MustScale) {
3388             Expr2.IVal *= CheckedSizeOf (Indirect (Expr->Type));
3389         }
3390         rflags |= CF_CONST;
3391         lflags |= CF_CONST;
3392     } else {
3393         /* Not constant, load into the primary */
3394         LoadExpr (CF_NONE, &Expr2);
3395         if (MustScale) {
3396             /* lhs is a pointer, scale rhs */
3397             g_scale (TypeOf (Expr2.Type), CheckedSizeOf (Indirect (Expr->Type)));
3398         }
3399     }
3400
3401     /* Setup the code generator flags */
3402     lflags |= TypeOf (Expr->Type) | GlobalModeFlags (Expr) | CF_FORCECHAR;
3403     rflags |= TypeOf (Expr2.Type) | CF_FORCECHAR;
3404
3405     /* Convert the type of the lhs to that of the rhs */
3406     g_typecast (lflags, rflags);
3407
3408     /* Output apropriate code depending on the location */
3409     switch (ED_GetLoc (Expr)) {
3410
3411         case E_LOC_ABS:
3412             /* Absolute: numeric address or const */
3413             if (Gen->Tok == TOK_PLUS_ASSIGN) {
3414                 g_addeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal);
3415             } else {
3416                 g_subeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal);
3417             }
3418             break;
3419
3420         case E_LOC_GLOBAL:
3421             /* Global variable */
3422             if (Gen->Tok == TOK_PLUS_ASSIGN) {
3423                 g_addeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal);
3424             } else {
3425                 g_subeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal);
3426             }
3427             break;
3428
3429         case E_LOC_STATIC:
3430         case E_LOC_LITERAL:
3431             /* Static variable or literal in the literal pool */
3432             if (Gen->Tok == TOK_PLUS_ASSIGN) {
3433                 g_addeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal);
3434             } else {
3435                 g_subeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal);
3436             }
3437             break;
3438
3439         case E_LOC_REGISTER:
3440             /* Register variable */
3441             if (Gen->Tok == TOK_PLUS_ASSIGN) {
3442                 g_addeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal);
3443             } else {
3444                 g_subeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal);
3445             }
3446             break;
3447
3448         case E_LOC_STACK:
3449             /* Value on the stack */
3450             if (Gen->Tok == TOK_PLUS_ASSIGN) {
3451                 g_addeqlocal (lflags, Expr->IVal, Expr2.IVal);
3452             } else {
3453                 g_subeqlocal (lflags, Expr->IVal, Expr2.IVal);
3454             }
3455             break;
3456
3457         default:
3458             Internal ("Invalid location in Store(): 0x%04X", ED_GetLoc (Expr));
3459     }
3460
3461     /* Expression is a rvalue in the primary now */
3462     ED_MakeRValExpr (Expr);
3463 }
3464
3465
3466
3467 void hie1 (ExprDesc* Expr)
3468 /* Parse first level of expression hierarchy. */
3469 {
3470     hieQuest (Expr);
3471     switch (CurTok.Tok) {
3472
3473         case TOK_ASSIGN:
3474             Assignment (Expr);
3475             break;
3476
3477         case TOK_PLUS_ASSIGN:
3478             addsubeq (&GenPASGN, Expr, "+=");
3479             break;
3480
3481         case TOK_MINUS_ASSIGN:
3482             addsubeq (&GenSASGN, Expr, "-=");
3483             break;
3484
3485         case TOK_MUL_ASSIGN:
3486             opeq (&GenMASGN, Expr, "*=");
3487             break;
3488
3489         case TOK_DIV_ASSIGN:
3490             opeq (&GenDASGN, Expr, "/=");
3491             break;
3492
3493         case TOK_MOD_ASSIGN:
3494             opeq (&GenMOASGN, Expr, "%=");
3495             break;
3496
3497         case TOK_SHL_ASSIGN:
3498             opeq (&GenSLASGN, Expr, "<<=");
3499             break;
3500
3501         case TOK_SHR_ASSIGN:
3502             opeq (&GenSRASGN, Expr, ">>=");
3503             break;
3504
3505         case TOK_AND_ASSIGN:
3506             opeq (&GenAASGN, Expr, "&=");
3507             break;
3508
3509         case TOK_XOR_ASSIGN:
3510             opeq (&GenXOASGN, Expr, "^=");
3511             break;
3512
3513         case TOK_OR_ASSIGN:
3514             opeq (&GenOASGN, Expr, "|=");
3515             break;
3516
3517         default:
3518             break;
3519     }
3520 }
3521
3522
3523
3524 void hie0 (ExprDesc *Expr)
3525 /* Parse comma operator. */
3526 {
3527     hie1 (Expr);
3528     while (CurTok.Tok == TOK_COMMA) {
3529         NextToken ();
3530         hie1 (Expr);
3531     }
3532 }
3533
3534
3535
3536 int evalexpr (unsigned Flags, void (*Func) (ExprDesc*), ExprDesc* Expr)
3537 /* Will evaluate an expression via the given function. If the result is a
3538 ** constant, 0 is returned and the value is put in the Expr struct. If the
3539 ** result is not constant, LoadExpr is called to bring the value into the
3540 ** primary register and 1 is returned.
3541 */
3542 {
3543     /* Evaluate */
3544     ExprWithCheck (Func, Expr);
3545
3546     /* Check for a constant expression */
3547     if (ED_IsConstAbs (Expr)) {
3548         /* Constant expression */
3549         return 0;
3550     } else {
3551         /* Not constant, load into the primary */
3552         LoadExpr (Flags, Expr);
3553         return 1;
3554     }
3555 }
3556
3557
3558
3559 void Expression0 (ExprDesc* Expr)
3560 /* Evaluate an expression via hie0 and put the result into the primary register */
3561 {
3562     ExprWithCheck (hie0, Expr);
3563     LoadExpr (CF_NONE, Expr);
3564 }
3565
3566
3567
3568 void ConstExpr (void (*Func) (ExprDesc*), ExprDesc* Expr)
3569 /* Will evaluate an expression via the given function. If the result is not
3570 ** a constant of some sort, a diagnostic will be printed, and the value is
3571 ** replaced by a constant one to make sure there are no internal errors that
3572 ** result from this input error.
3573 */
3574 {
3575     ExprWithCheck (Func, Expr);
3576     if (!ED_IsConst (Expr)) {
3577         Error ("Constant expression expected");
3578         /* To avoid any compiler errors, make the expression a valid const */
3579         ED_MakeConstAbsInt (Expr, 1);
3580     }
3581 }
3582
3583
3584
3585 void BoolExpr (void (*Func) (ExprDesc*), ExprDesc* Expr)
3586 /* Will evaluate an expression via the given function. If the result is not
3587 ** something that may be evaluated in a boolean context, a diagnostic will be
3588 ** printed, and the value is replaced by a constant one to make sure there
3589 ** are no internal errors that result from this input error.
3590 */
3591 {
3592     ExprWithCheck (Func, Expr);
3593     if (!ED_IsBool (Expr)) {
3594         Error ("Boolean expression expected");
3595         /* To avoid any compiler errors, make the expression a valid int */
3596         ED_MakeConstAbsInt (Expr, 1);
3597     }
3598 }
3599
3600
3601
3602 void ConstAbsIntExpr (void (*Func) (ExprDesc*), ExprDesc* Expr)
3603 /* Will evaluate an expression via the given function. If the result is not
3604 ** a constant numeric integer value, a diagnostic will be printed, and the
3605 ** value is replaced by a constant one to make sure there are no internal
3606 ** errors that result from this input error.
3607 */
3608 {
3609     ExprWithCheck (Func, Expr);
3610     if (!ED_IsConstAbsInt (Expr)) {
3611         Error ("Constant integer expression expected");
3612         /* To avoid any compiler errors, make the expression a valid const */
3613         ED_MakeConstAbsInt (Expr, 1);
3614     }
3615 }