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