Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom.ansi / expr.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  */
5 /* $Id: expr.c,v 1.18 1994/06/27 07:59:41 ceriel Exp $ */
6 /* EXPRESSION TREE HANDLING */
7
8 #include        "lint.h"
9 #include        "debug.h"
10 #include        "assert.h"
11 #include        "botch_free.h"
12 #include        <alloc.h>
13 #include        "idf.h"
14 #include        <flt_arith.h>
15 #include        "arith.h"
16 #include        "def.h"
17 #include        "type.h"
18 #include        "label.h"
19 #include        "expr.h"
20 #include        "LLlex.h"
21 #include        "Lpars.h"
22 #include        "decspecs.h"
23 #include        "declar.h"
24 #include        "sizes.h"
25 #include        "level.h"
26 #include        "use_tmp.h"
27
28 extern char *symbol2str();
29 extern char options[];
30 extern int InSizeof;
31
32 int
33 rank_of(oper)
34         int oper;
35 {
36         /*      The rank of the operator oper is returned.
37         */
38         switch (oper)   {
39         default:
40                 return 0;                       /* INT2INT etc. */
41         case '[':
42         case '(':
43         case '.':
44         case ARROW:
45         case PARCOMMA:
46                 return 1;
47         case '!':
48         case PLUSPLUS:
49         case MINMIN:
50         case CAST:
51         case SIZEOF:
52         case ADDRESSOF:
53                 return 2;                       /* monadic */
54         case '*':
55         case '/':
56         case '%':
57                 return 3;
58         case '+':
59         case '-':
60                 return 4;
61         case LEFT:
62         case RIGHT:
63                 return 5;
64         case '<':
65         case '>':
66         case LESSEQ:
67         case GREATEREQ:
68                 return 6;
69         case EQUAL:
70         case NOTEQUAL:
71                 return 7;
72         case '&':
73                 return 8;
74         case '^':
75                 return 9;
76         case '|':
77                 return 10;
78         case AND:
79                 return 11;
80         case OR:
81                 return 12;
82         case '?':
83         case ':':
84                 return 13;
85         case '=':
86         case PLUSAB:
87         case MINAB:
88         case TIMESAB:
89         case DIVAB:
90         case MODAB:
91         case RIGHTAB:
92         case LEFTAB:
93         case ANDAB:
94         case XORAB:
95         case ORAB:
96                 return 14;
97         case ',':
98                 return 15;
99         }
100         /*NOTREACHED*/
101 }
102
103 dot2expr(expp)
104         struct expr **expp;
105 {
106         /*      The token in dot is converted into an expression, a
107                 pointer to which is stored in *expp.
108         */
109         register struct expr *ex = new_expr();
110
111         *expp = ex;
112         ex->ex_file = dot.tk_file;
113         ex->ex_line = dot.tk_line;
114         switch (DOT)    {
115         case IDENTIFIER:
116                 idf2expr(ex);
117                 break;
118         case INTEGER:
119                 int2expr(ex);
120                 break;
121         case FLOATING:
122                 float2expr(ex);
123                 break;
124         default:
125                 crash("bad conversion to expression");
126                 /*NOTREACHED*/
127         }
128 }
129
130 idf2expr(expr)
131         register struct expr *expr;
132 {
133         /*      Dot contains an identifier which is turned into an
134                 expression.
135                 Note that this constitutes an applied occurrence of
136                 the identifier.
137         */
138         register struct idf *idf = dot.tk_idf;  /* != 0*/
139         register struct def *def = idf->id_def;
140         
141         if (def == 0)   {
142                 if (AHEAD == '(') {
143                         /* function call, declare name implicitly (3.3.2.2) */
144                         if (!options['o'])
145                                 warning("implicit declaration of function %s"
146                                         , idf->id_text);
147                         add_def(idf, EXTERN, funint_type, level);
148                 } else  {
149                         if (!is_anon_idf(idf))
150                                 error("%s undefined", idf->id_text);
151                         /* declare idf anyway */
152                         add_def(idf, 0, error_type, level);
153                 }
154                 def = idf->id_def;
155         }
156         /* now def != 0 */
157 #ifndef LINT
158         if (!InSizeof) {
159                 if (! def->df_used) {
160 #ifndef PREPEND_SCOPES
161                         code_scope(idf->id_text, def);
162 #endif /* PREPEND_SCOPES */
163                         def->df_used = 1;
164                 }
165         }
166 #endif  /* LINT */
167         expr->ex_type = def->df_type;
168         if (expr->ex_type == error_type) {
169                 expr->ex_flags |= EX_ERROR;
170         }
171         expr->ex_lvalue =
172                 (       def->df_type->tp_fund == FUNCTION ||
173                         def->df_type->tp_fund == ARRAY ||
174                         def->df_sc == ENUM
175                 ) ? 0 : 1;
176         if (def->df_type->tp_typequal & TQ_CONST)
177                 expr->ex_flags |= EX_READONLY;
178         if (def->df_type->tp_typequal & TQ_VOLATILE)
179                 expr->ex_flags |= EX_VOLATILE;
180         expr->ex_class = Value;
181         if (def->df_sc == ENUM) {
182                 expr->VL_CLASS = Const;
183                 expr->VL_VALUE = def->df_address;
184         }
185 #ifndef LINT
186         else
187         if (def->df_sc == STATIC && def->df_level >= L_LOCAL) {
188                 expr->VL_CLASS = Label;
189                 expr->VL_LBL = def->df_address;
190                 expr->VL_VALUE = (arith)0;
191         }
192 #endif  /* LINT */
193         else {
194                 expr->VL_CLASS = Name;
195                 expr->VL_IDF = idf;
196                 expr->VL_VALUE = (arith)0;
197         }
198 }
199
200 string2expr(expp, str, len)
201         register struct expr **expp;
202         int len;
203         char *str;
204 {
205         /*      The string in the argument is converted into an expression,
206                 a pointer to which is stored in *expp.
207         */
208         register struct expr *ex = new_expr();
209
210         *expp = ex;
211         ex->ex_file = dot.tk_file;
212         ex->ex_line = dot.tk_line;
213         ex->ex_type = string_type;
214         /* ex->ex_type = qualifier_type(ex->ex_type, TQ_CONST); */
215         ex->ex_flags |= EX_READONLY;
216         /* ex->ex_lvalue = 0; */
217         ex->ex_class = String;
218         ex->SG_VALUE = str;
219         ex->SG_LEN = len;
220 }
221
222 int2expr(expr)
223         struct expr *expr;
224 {
225         /*      Dot contains an integer constant which is turned
226                 into an expression.
227         */
228         fill_int_expr(expr, dot.tk_ival, dot.tk_fund);
229 }
230
231 float2expr(expr)
232         register struct expr *expr;
233 {
234         /*      Dot contains a floating point constant which is turned
235                 into an expression.
236         */
237         register int fund;
238
239         fund = dot.tk_fund;
240         switch (fund) {
241         case FLOAT:
242                 expr->ex_type = float_type;
243                 break;
244         case DOUBLE:
245                 expr->ex_type = double_type;
246                 break;
247         case LNGDBL:
248                 expr->ex_type = lngdbl_type;
249                 break;
250         default:
251                 crash("(float2expr) bad fund %s\n", symbol2str(fund));
252         }
253         expr->ex_class = Float;
254         flt_str2flt(dot.tk_fval, &(expr->FL_ARITH));
255         free(dot.tk_fval);
256         ASSERT(flt_status != FLT_NOFLT);
257         if (flt_status == FLT_OVFL)
258                 expr_warning(expr,"internal floating point overflow");
259 }
260
261 struct expr*
262 intexpr(ivalue, fund)
263         arith ivalue;
264         int fund;
265 {
266         /*      The value ivalue is turned into an integer expression of
267                 the size indicated by fund.
268         */
269         register struct expr *expr = new_expr();
270
271         expr->ex_file = dot.tk_file;
272         expr->ex_line = dot.tk_line;
273         fill_int_expr(expr, ivalue, fund);
274         return expr;
275 }
276
277 fill_int_expr(ex, ivalue, fund)
278         register struct expr *ex;
279         arith ivalue;
280         int fund;
281 {
282         /*      Details derived from ivalue and fund are put into the
283                 constant integer expression ex.
284         */
285         switch (fund) {
286         case INT:
287                 ex->ex_type = int_type;
288                 break;
289         case UNSIGNED:
290                 ex->ex_type = uint_type;
291                 break;
292         case LONG:
293                 ex->ex_type =  long_type;
294                 break;
295         case ULONG:
296                 ex->ex_type = ulong_type;
297                 break;
298         default:
299                 crash("(fill_int_expr) bad fund %s\n", symbol2str(fund));
300                 /*NOTREACHED*/
301         }
302         ex->ex_class = Value;
303         ex->VL_CLASS = Const;
304         ex->VL_VALUE = ivalue;
305         cut_size(ex);
306 }
307
308 struct expr *
309 new_oper(tp, e1, oper, e2)
310         struct type *tp;
311         register struct expr *e1, *e2;
312 {
313         /*      A new expression is constructed which consists of the
314                 operator oper which has e1 and e2 as operands; for a
315                 monadic operator e1 == NILEXPR.
316                 During the construction of the right recursive initialisation
317                 tree it is possible for e2 to be NILEXPR.
318         */
319         register struct expr *expr = new_expr();
320         register struct oper *op;
321
322         if (e2) {
323                 register struct expr *e = e2;
324                 
325                 while (e->ex_class == Oper && e->OP_LEFT)
326                         e = e->OP_LEFT;
327                 expr->ex_file = e->ex_file;
328                 expr->ex_line = e->ex_line;
329         }
330         else
331         if (e1) {
332                 register struct expr *e = e1;
333                 
334                 while (e->ex_class == Oper && e->OP_RIGHT)
335                         e = e->OP_RIGHT;
336                 expr->ex_file = e->ex_file;
337                 expr->ex_line = e->ex_line;
338         }
339         else    {
340                 expr->ex_file = dot.tk_file;
341                 expr->ex_line = dot.tk_line;
342         }
343
344         expr->ex_type = tp;
345         expr->ex_class = Oper;
346         /* combine depths and flags of both expressions */
347         if (e2) {
348                 int e1_depth = e1 ? e1->ex_depth : 0;
349                 int e1_flags = e1 ? e1->ex_flags : 0;
350                 
351                 expr->ex_depth =
352                         (e1_depth > e2->ex_depth ? e1_depth : e2->ex_depth) + 1;
353                 expr->ex_flags = (e1_flags | e2->ex_flags)
354                         & ~(EX_PARENS | EX_READONLY | EX_VOLATILE );
355         }
356         /*
357          * A function call should be evaluated first when possible.  Just say
358          * that the expression tree is very deep.
359          */
360         if (oper == '(') {
361                 expr->ex_depth = 50;
362         }
363         op = &expr->ex_object.ex_oper;
364         op->op_type = tp;
365         op->op_oper = oper;
366         op->op_left = e1;
367         op->op_right = e2;
368 #ifdef  LINT
369         lint_new_oper(expr);
370 #endif  /* LINT */
371         return expr;
372 }
373
374 chk_cst_expr(expp)
375         struct expr **expp;
376 {
377         /*      The expression expr is checked for constancy.
378         
379                 There are 6 places where constant expressions occur in C:
380                 1.      after #if
381                 2.      in a global initialization
382                 3.      as size in an array declaration
383                 4.      as value in an enum declaration
384                 5.      as width in a bit field
385                 6.      as case value in a switch
386                 
387                 The constant expression in a global initialization is
388                 handled separately (by IVAL()).
389                 
390                 There are various disparate restrictions on each of
391                 the others in the various C compilers.  I have tried some
392                 hypotheses to unify them, but all have failed.
393                 
394                 Special problems (of which there is only one, sizeof in
395                 Preprocessor #if) have to be dealt with locally
396         */
397         register struct expr *expr = *expp;
398         
399 #ifdef  DEBUG
400         print_expr("constant_expression", expr);
401 #endif  /* DEBUG */
402         switch(expr->ex_type->tp_fund) {
403         case CHAR:
404         case SHORT:
405         case INT:
406         case ENUM:
407         case LONG:
408                 if (is_ld_cst(expr)) {
409                         return;
410                 }
411                 expr_error(expr, "expression is not constant");
412                 break;
413         default:
414                 expr_error(expr, "non-numerical constant expression");
415                 break;
416         }
417         erroneous2int(expp);
418 }
419
420 init_expression(eppp, expr)
421         register struct expr ***eppp;
422         struct expr *expr;
423 {
424         /*      The expression expr is added to the tree designated
425                 indirectly by **eppp.
426                 The natural form of a tree representing an
427                 initial_value_list is right-recursive, ie. with the
428                 left-most comma as main operator. The iterative grammar in
429                 expression.g, however, tends to produce a left-recursive
430                 tree, ie. one with the right-most comma as its main
431                 operator.
432                 To produce a right-recursive tree from the iterative
433                 grammar, we keep track of the address of the pointer where
434                 the next expression must be hooked in.
435         */
436         **eppp = new_oper(void_type, expr, INITCOMMA, NILEXPR);
437         *eppp = &(**eppp)->OP_RIGHT;
438 }
439
440 int
441 is_ld_cst(expr)
442         register struct expr *expr;
443 {
444         /*      An expression is a `load-time constant' if it is of the form
445                 <idf> +/- <integral> or <integral>.
446         */
447 #ifdef  LINT
448         if (expr->ex_class == String)
449                 return 1;
450 #endif  /* LINT */
451         return expr->ex_lvalue == 0 && expr->ex_class == Value;
452 }
453
454 int
455 is_cp_cst(expr)
456         struct expr *expr;
457 {
458         /*      An expression is a `compile-time constant' if it is a
459                 load-time constant, and the idf is not there.
460         */
461         return is_ld_cst(expr) && expr->VL_CLASS == Const;
462 }
463
464 int
465 is_fp_cst(expr)
466         struct expr *expr;
467 {
468         /*      An expression is a `floating-point constant' if it consists
469                 of the float only.
470         */
471         return expr->ex_class == Float;
472 }
473
474 int
475 is_zero_cst(expr)
476         register struct expr *expr;
477 {
478         flt_arith var;
479
480         switch(expr->ex_class) {
481         case Value:
482                 return expr->VL_VALUE == 0;
483         case Float:
484                 flt_arith2flt((arith) 0, &var, 0);
485                 return flt_cmp(&var, &(expr->FL_ARITH)) == 0;
486         }
487         /*NOTREACHED*/
488 }
489
490 free_expression(expr)
491         register struct expr *expr;
492 {
493         /*      The expression expr is freed recursively.
494         */
495         if (expr) {
496                 if (expr->ex_class == Oper)     {
497                         free_expression(expr->OP_LEFT);
498                         free_expression(expr->OP_RIGHT);
499                 }
500                 free_expr(expr);
501         }
502 }