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