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