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