]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/m2/gm2-gcc/m2expr.cc
PR modula2/102989: reimplement overflow detection in ztype though WIDE_INT_MAX_PRECISION
[thirdparty/gcc.git] / gcc / m2 / gm2-gcc / m2expr.cc
1 /* m2expr.cc provides an interface to GCC expression trees.
2
3 Copyright (C) 2012-2023 Free Software Foundation, Inc.
4 Contributed by Gaius Mulley <gaius@glam.ac.uk>.
5
6 This file is part of GNU Modula-2.
7
8 GNU Modula-2 is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
13 GNU Modula-2 is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU Modula-2; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
21
22 #include "gcc-consolidation.h"
23
24 #include "../gm2-lang.h"
25 #include "../m2-tree.h"
26 #include "m2convert.h"
27
28 /* Prototypes. */
29
30 #define m2expr_c
31 #include "m2assert.h"
32 #include "m2builtins.h"
33 #include "m2convert.h"
34 #include "m2decl.h"
35 #include "m2expr.h"
36 #include "m2options.h"
37 #include "m2range.h"
38 #include "m2statement.h"
39 #include "m2tree.h"
40 #include "m2treelib.h"
41 #include "m2type.h"
42 #include "m2linemap.h"
43 #include "math.h"
44
45 static void m2expr_checkRealOverflow (location_t location, enum tree_code code,
46 tree result);
47 static tree checkWholeNegateOverflow (location_t location, tree i, tree lowest,
48 tree min, tree max);
49 // static tree m2expr_Build4LogicalAnd (location_t location, tree a, tree b,
50 // tree c, tree d);
51 static tree m2expr_Build4LogicalOr (location_t location, tree a, tree b,
52 tree c, tree d);
53 static tree m2expr_Build4TruthOrIf (location_t location, tree a, tree b,
54 tree c, tree d);
55 static tree m2expr_Build4TruthAndIf (location_t location, tree a, tree b,
56 tree c, tree d);
57
58 static int label_count = 0;
59 static GTY (()) tree set_full_complement;
60
61 /* Return an integer string using base 10 and no padding. The string returned
62 will have been malloc'd. */
63
64 char *
65 m2expr_CSTIntToString (tree t)
66 {
67 char val[100];
68
69 snprintf (val, 100, HOST_WIDE_INT_PRINT_UNSIGNED, TREE_INT_CST_LOW (t));
70 return xstrndup (val, 100);
71 }
72
73 /* Return the char representation of tree t. */
74
75 char
76 m2expr_CSTIntToChar (tree t)
77 {
78 return (char) (TREE_INT_CST_LOW (t));
79 }
80
81 /* CompareTrees returns -1 if e1 < e2, 0 if e1 == e2, and 1 if e1 > e2. */
82
83 int
84 m2expr_CompareTrees (tree e1, tree e2)
85 {
86 return tree_int_cst_compare (m2expr_FoldAndStrip (e1),
87 m2expr_FoldAndStrip (e2));
88 }
89
90 /* FoldAndStrip return expression, t, after it has been folded (if
91 possible). */
92
93 tree
94 m2expr_FoldAndStrip (tree t)
95 {
96 if (t != NULL)
97 {
98 t = fold (t);
99 if (TREE_CODE (t) == CONST_DECL)
100 return m2expr_FoldAndStrip (DECL_INITIAL (t));
101 }
102
103 return t;
104 }
105
106 /* StringLength returns an unsigned int which is the length of, string. */
107
108 unsigned int
109 m2expr_StringLength (tree string)
110 {
111 return TREE_STRING_LENGTH (string);
112 }
113
114 /* CheckAddressToCardinal if op is a pointer convert it to the ADDRESS type. */
115
116 static tree
117 CheckAddressToCardinal (location_t location, tree op)
118 {
119 if (m2type_IsAddress (TREE_TYPE (op)))
120 return m2convert_BuildConvert (location, m2type_GetCardinalAddressType (),
121 op, false);
122 return op;
123 }
124
125 /* BuildTruthAndIf return true if a && b. Retain order left to right. */
126
127 static tree
128 m2expr_BuildTruthAndIf (location_t location, tree a, tree b)
129 {
130 return m2expr_build_binary_op (location, TRUTH_ANDIF_EXPR, a, b, false);
131 }
132
133 /* BuildTruthOrIf return true if a || b. Retain order left to right. */
134
135 static tree
136 m2expr_BuildTruthOrIf (location_t location, tree a, tree b)
137 {
138 return m2expr_build_binary_op (location, TRUTH_ORIF_EXPR, a, b, false);
139 }
140
141 /* BuildTruthNotIf inverts the boolean value of expr and returns the result. */
142
143 static tree
144 m2expr_BuildTruthNot (location_t location, tree expr)
145 {
146 return m2expr_build_unary_op (location, TRUTH_NOT_EXPR, expr, false);
147 }
148
149 /* BuildPostInc builds a post increment tree, the second operand is
150 always one. */
151
152 static tree
153 m2expr_BuildPostInc (location_t location, tree op)
154 {
155 return m2expr_BuildAdd (location, op, build_int_cst (TREE_TYPE (op), 1), false);
156 }
157
158 /* BuildPostDec builds a post decrement tree, the second operand is
159 always one. */
160
161 static tree
162 m2expr_BuildPostDec (location_t location, tree op)
163 {
164 return m2expr_BuildSub (location, op, build_int_cst (TREE_TYPE (op), 1), false);
165 }
166
167 /* BuildAddCheck builds an addition tree. */
168
169 tree
170 m2expr_BuildAddCheck (location_t location, tree op1, tree op2, tree lowest,
171 tree min, tree max)
172 {
173 tree t;
174
175 m2assert_AssertLocation (location);
176
177 op1 = m2expr_FoldAndStrip (op1);
178 op2 = m2expr_FoldAndStrip (op2);
179
180 op1 = CheckAddressToCardinal (location, op1);
181 op2 = CheckAddressToCardinal (location, op2);
182
183 t = m2expr_build_binary_op_check (location, PLUS_EXPR, op1, op2, false,
184 lowest, min, max);
185 return m2expr_FoldAndStrip (t);
186 }
187
188 /* BuildAdd builds an addition tree. */
189
190 tree
191 m2expr_BuildAdd (location_t location, tree op1, tree op2, bool needconvert)
192 {
193 tree t;
194
195 m2assert_AssertLocation (location);
196
197 op1 = m2expr_FoldAndStrip (op1);
198 op2 = m2expr_FoldAndStrip (op2);
199
200 op1 = CheckAddressToCardinal (location, op1);
201 op2 = CheckAddressToCardinal (location, op2);
202
203 t = m2expr_build_binary_op (location, PLUS_EXPR, op1, op2, needconvert);
204 return m2expr_FoldAndStrip (t);
205 }
206
207 /* BuildSubCheck builds a subtraction tree. */
208
209 tree
210 m2expr_BuildSubCheck (location_t location, tree op1, tree op2, tree lowest,
211 tree min, tree max)
212 {
213 tree t;
214
215 m2assert_AssertLocation (location);
216
217 op1 = m2expr_FoldAndStrip (op1);
218 op2 = m2expr_FoldAndStrip (op2);
219
220 op1 = CheckAddressToCardinal (location, op1);
221 op2 = CheckAddressToCardinal (location, op2);
222
223 t = m2expr_build_binary_op_check (location, MINUS_EXPR, op1, op2, false,
224 lowest, min, max);
225 return m2expr_FoldAndStrip (t);
226 }
227
228 /* BuildSub builds a subtraction tree. */
229
230 tree
231 m2expr_BuildSub (location_t location, tree op1, tree op2, bool needconvert)
232 {
233 tree t;
234
235 m2assert_AssertLocation (location);
236
237 op1 = m2expr_FoldAndStrip (op1);
238 op2 = m2expr_FoldAndStrip (op2);
239
240 op1 = CheckAddressToCardinal (location, op1);
241 op2 = CheckAddressToCardinal (location, op2);
242
243 t = m2expr_build_binary_op (location, MINUS_EXPR, op1, op2, needconvert);
244 return m2expr_FoldAndStrip (t);
245 }
246
247 /* BuildDivTrunc builds a trunc division tree. */
248
249 tree
250 m2expr_BuildDivTrunc (location_t location, tree op1, tree op2, bool needconvert)
251 {
252 tree t;
253
254 m2assert_AssertLocation (location);
255
256 op1 = m2expr_FoldAndStrip (op1);
257 op2 = m2expr_FoldAndStrip (op2);
258
259 op1 = CheckAddressToCardinal (location, op1);
260 op2 = CheckAddressToCardinal (location, op2);
261
262 t = m2expr_build_binary_op (location, TRUNC_DIV_EXPR, op1, op2, needconvert);
263 return m2expr_FoldAndStrip (t);
264 }
265
266 /* BuildDivTruncCheck builds a trunc division tree. */
267
268 tree
269 m2expr_BuildDivTruncCheck (location_t location, tree op1, tree op2, tree lowest,
270 tree min, tree max)
271 {
272 tree t;
273
274 m2assert_AssertLocation (location);
275
276 op1 = m2expr_FoldAndStrip (op1);
277 op2 = m2expr_FoldAndStrip (op2);
278
279 op1 = CheckAddressToCardinal (location, op1);
280 op2 = CheckAddressToCardinal (location, op2);
281
282 t = m2expr_build_binary_op_check (location, TRUNC_DIV_EXPR, op1, op2, false,
283 lowest, min, max);
284 return m2expr_FoldAndStrip (t);
285 }
286
287 /* BuildModTruncCheck builds a trunc modulus tree. */
288
289 tree
290 m2expr_BuildModTruncCheck (location_t location, tree op1, tree op2, tree lowest,
291 tree min, tree max)
292 {
293 tree t;
294
295 m2assert_AssertLocation (location);
296
297 op1 = m2expr_FoldAndStrip (op1);
298 op2 = m2expr_FoldAndStrip (op2);
299
300 op1 = CheckAddressToCardinal (location, op1);
301 op2 = CheckAddressToCardinal (location, op2);
302
303 t = m2expr_build_binary_op_check (location, TRUNC_MOD_EXPR, op1, op2, false,
304 lowest, min, max);
305 return m2expr_FoldAndStrip (t);
306 }
307
308 /* BuildModTrunc builds a trunc modulus tree. */
309
310 tree
311 m2expr_BuildModTrunc (location_t location, tree op1, tree op2, bool needconvert)
312 {
313 tree t;
314
315 m2assert_AssertLocation (location);
316
317 op1 = m2expr_FoldAndStrip (op1);
318 op2 = m2expr_FoldAndStrip (op2);
319
320 op1 = CheckAddressToCardinal (location, op1);
321 op2 = CheckAddressToCardinal (location, op2);
322
323 t = m2expr_build_binary_op (location, TRUNC_MOD_EXPR, op1, op2, needconvert);
324 return m2expr_FoldAndStrip (t);
325 }
326
327 /* BuildModCeilCheck builds a ceil modulus tree. */
328
329 tree
330 m2expr_BuildModCeilCheck (location_t location, tree op1, tree op2, tree lowest,
331 tree min, tree max)
332 {
333 tree t;
334
335 m2assert_AssertLocation (location);
336
337 op1 = m2expr_FoldAndStrip (op1);
338 op2 = m2expr_FoldAndStrip (op2);
339
340 op1 = CheckAddressToCardinal (location, op1);
341 op2 = CheckAddressToCardinal (location, op2);
342
343 t = m2expr_build_binary_op_check (location, CEIL_MOD_EXPR, op1, op2, false,
344 lowest, min, max);
345 return m2expr_FoldAndStrip (t);
346 }
347
348 /* BuildModFloorCheck builds a trunc modulus tree. */
349
350 tree
351 m2expr_BuildModFloorCheck (location_t location, tree op1, tree op2, tree lowest,
352 tree min, tree max)
353 {
354 tree t;
355
356 m2assert_AssertLocation (location);
357
358 op1 = m2expr_FoldAndStrip (op1);
359 op2 = m2expr_FoldAndStrip (op2);
360
361 op1 = CheckAddressToCardinal (location, op1);
362 op2 = CheckAddressToCardinal (location, op2);
363
364 t = m2expr_build_binary_op_check (location, FLOOR_MOD_EXPR, op1, op2, false,
365 lowest, min, max);
366 return m2expr_FoldAndStrip (t);
367 }
368
369 /* BuildDivCeil builds a ceil division tree. */
370
371 tree
372 m2expr_BuildDivCeil (location_t location, tree op1, tree op2, bool needconvert)
373 {
374 tree t;
375
376 m2assert_AssertLocation (location);
377
378 op1 = m2expr_FoldAndStrip (op1);
379 op2 = m2expr_FoldAndStrip (op2);
380
381 op1 = CheckAddressToCardinal (location, op1);
382 op2 = CheckAddressToCardinal (location, op2);
383
384 t = m2expr_build_binary_op (location, CEIL_DIV_EXPR, op1, op2, needconvert);
385 return m2expr_FoldAndStrip (t);
386 }
387
388 /* BuildDivCeilCheck builds a check ceil division tree. */
389
390 tree
391 m2expr_BuildDivCeilCheck (location_t location, tree op1, tree op2, tree lowest,
392 tree min, tree max)
393 {
394 tree t;
395
396 m2assert_AssertLocation (location);
397
398 op1 = m2expr_FoldAndStrip (op1);
399 op2 = m2expr_FoldAndStrip (op2);
400
401 op1 = CheckAddressToCardinal (location, op1);
402 op2 = CheckAddressToCardinal (location, op2);
403
404 t = m2expr_build_binary_op_check (location, CEIL_DIV_EXPR, op1, op2, false,
405 lowest, min, max);
406 return m2expr_FoldAndStrip (t);
407 }
408
409 /* BuildModCeil builds a ceil modulus tree. */
410
411 tree
412 m2expr_BuildModCeil (location_t location, tree op1, tree op2, bool needconvert)
413 {
414 tree t;
415
416 m2assert_AssertLocation (location);
417
418 op1 = m2expr_FoldAndStrip (op1);
419 op2 = m2expr_FoldAndStrip (op2);
420
421 op1 = CheckAddressToCardinal (location, op1);
422 op2 = CheckAddressToCardinal (location, op2);
423
424 t = m2expr_build_binary_op (location, CEIL_MOD_EXPR, op1, op2, needconvert);
425 return m2expr_FoldAndStrip (t);
426 }
427
428 /* BuildDivFloor builds a floor division tree. */
429
430 tree
431 m2expr_BuildDivFloor (location_t location, tree op1, tree op2, bool needconvert)
432 {
433 tree t;
434
435 m2assert_AssertLocation (location);
436
437 op1 = m2expr_FoldAndStrip (op1);
438 op2 = m2expr_FoldAndStrip (op2);
439
440 op1 = CheckAddressToCardinal (location, op1);
441 op2 = CheckAddressToCardinal (location, op2);
442
443 t = m2expr_build_binary_op (location, FLOOR_DIV_EXPR, op1, op2, needconvert);
444 return m2expr_FoldAndStrip (t);
445 }
446
447 /* BuildDivFloorCheck builds a check floor division tree. */
448
449 tree
450 m2expr_BuildDivFloorCheck (location_t location, tree op1, tree op2, tree lowest,
451 tree min, tree max)
452 {
453 tree t;
454
455 m2assert_AssertLocation (location);
456
457 op1 = m2expr_FoldAndStrip (op1);
458 op2 = m2expr_FoldAndStrip (op2);
459
460 op1 = CheckAddressToCardinal (location, op1);
461 op2 = CheckAddressToCardinal (location, op2);
462
463 t = m2expr_build_binary_op_check (location, FLOOR_DIV_EXPR, op1, op2, false,
464 lowest, min, max);
465 return m2expr_FoldAndStrip (t);
466 }
467
468 /* BuildRDiv builds a division tree (this should only be used for
469 REAL and COMPLEX types and NEVER for integer based types). */
470
471 tree
472 m2expr_BuildRDiv (location_t location, tree op1, tree op2, bool needconvert)
473 {
474 tree t;
475
476 m2assert_AssertLocation (location);
477
478 op1 = m2expr_FoldAndStrip (op1);
479 op2 = m2expr_FoldAndStrip (op2);
480
481 t = m2expr_build_binary_op (location, RDIV_EXPR, op1, op2, needconvert);
482 return m2expr_FoldAndStrip (t);
483 }
484
485 /* BuildModFloor builds a modulus tree. */
486
487 tree
488 m2expr_BuildModFloor (location_t location, tree op1, tree op2, bool needconvert)
489 {
490 tree t;
491
492 m2assert_AssertLocation (location);
493
494 op1 = m2expr_FoldAndStrip (op1);
495 op2 = m2expr_FoldAndStrip (op2);
496
497 op1 = CheckAddressToCardinal (location, op1);
498 op2 = CheckAddressToCardinal (location, op2);
499
500 t = m2expr_build_binary_op (location, FLOOR_MOD_EXPR, op1, op2, needconvert);
501 return m2expr_FoldAndStrip (t);
502 }
503
504 /* BuildLSL builds and returns tree (op1 << op2). */
505
506 tree
507 m2expr_BuildLSL (location_t location, tree op1, tree op2, bool needconvert)
508 {
509 tree t;
510
511 m2assert_AssertLocation (location);
512
513 op1 = m2expr_FoldAndStrip (op1);
514 op2 = m2expr_FoldAndStrip (op2);
515
516 t = m2expr_build_binary_op (location, LSHIFT_EXPR, op1, op2, needconvert);
517 return m2expr_FoldAndStrip (t);
518 }
519
520 /* BuildLSR builds and returns tree (op1 >> op2). */
521
522 tree
523 m2expr_BuildLSR (location_t location, tree op1, tree op2, bool needconvert)
524 {
525 tree t;
526
527 m2assert_AssertLocation (location);
528
529 op1 = m2expr_FoldAndStrip (op1);
530 op2 = m2expr_FoldAndStrip (op2);
531
532 t = m2expr_build_binary_op (location, RSHIFT_EXPR, op1, op2, needconvert);
533 return m2expr_FoldAndStrip (t);
534 }
535
536 /* createUniqueLabel returns a unique label which has been alloc'ed. */
537
538 static char *
539 createUniqueLabel (void)
540 {
541 int size, i;
542 char *label;
543
544 label_count++;
545 i = label_count;
546 size = strlen (".LSHIFT") + 2;
547 while (i > 0)
548 {
549 i /= 10;
550 size++;
551 }
552 label = (char *)ggc_alloc_atomic (size);
553 sprintf (label, ".LSHIFT%d", label_count);
554 return label;
555 }
556
557 /* BuildLogicalShift builds the ISO Modula-2 SHIFT operator for a
558 fundamental data type. */
559
560 void
561 m2expr_BuildLogicalShift (location_t location, tree op1, tree op2, tree op3,
562 tree nBits ATTRIBUTE_UNUSED, bool needconvert)
563 {
564 tree res;
565
566 m2assert_AssertLocation (location);
567 op2 = m2expr_FoldAndStrip (op2);
568 op3 = m2expr_FoldAndStrip (op3);
569 if (TREE_CODE (op3) == INTEGER_CST)
570 {
571 op2 = m2convert_ToWord (location, op2);
572 if (tree_int_cst_sgn (op3) < 0)
573 res = m2expr_BuildLSR (
574 location, op2,
575 m2convert_ToWord (location,
576 m2expr_BuildNegate (location, op3, needconvert)),
577 needconvert);
578 else
579 res = m2expr_BuildLSL (location, op2, m2convert_ToWord (location, op3),
580 needconvert);
581 res = m2convert_BuildConvert (
582 location, m2tree_skip_type_decl (TREE_TYPE (op1)), res, false);
583 m2statement_BuildAssignmentTree (location, op1, res);
584 }
585 else
586 {
587 char *labelElseName = createUniqueLabel ();
588 char *labelEndName = createUniqueLabel ();
589 tree is_less = m2expr_BuildLessThan (location,
590 m2convert_ToInteger (location, op3),
591 m2expr_GetIntegerZero (location));
592
593 m2statement_DoJump (location, is_less, NULL, labelElseName);
594 op2 = m2convert_ToWord (location, op2);
595 op3 = m2convert_ToWord (location, op3);
596 res = m2expr_BuildLSL (location, op2, op3, needconvert);
597 res = m2convert_BuildConvert (
598 location, m2tree_skip_type_decl (TREE_TYPE (op1)), res, false);
599 m2statement_BuildAssignmentTree (location, op1, res);
600 m2statement_BuildGoto (location, labelEndName);
601 m2statement_DeclareLabel (location, labelElseName);
602 res = m2expr_BuildLSR (location, op2,
603 m2expr_BuildNegate (location, op3, needconvert),
604 needconvert);
605 res = m2convert_BuildConvert (
606 location, m2tree_skip_type_decl (TREE_TYPE (op1)), res, false);
607 m2statement_BuildAssignmentTree (location, op1, res);
608 m2statement_DeclareLabel (location, labelEndName);
609 }
610 }
611
612 /* BuildLRL builds and returns tree (op1 rotate left by op2 bits). */
613
614 tree
615 m2expr_BuildLRL (location_t location, tree op1, tree op2, bool needconvert)
616 {
617 tree t;
618
619 m2assert_AssertLocation (location);
620
621 op1 = m2expr_FoldAndStrip (op1);
622 op2 = m2expr_FoldAndStrip (op2);
623
624 t = m2expr_build_binary_op (location, LROTATE_EXPR, op1, op2, needconvert);
625 return m2expr_FoldAndStrip (t);
626 }
627
628 /* BuildLRR builds and returns tree (op1 rotate right by op2 bits). */
629
630 tree
631 m2expr_BuildLRR (location_t location, tree op1, tree op2, bool needconvert)
632 {
633 tree t;
634
635 m2assert_AssertLocation (location);
636
637 op1 = m2expr_FoldAndStrip (op1);
638 op2 = m2expr_FoldAndStrip (op2);
639
640 t = m2expr_build_binary_op (location, RROTATE_EXPR, op1, op2, needconvert);
641 return m2expr_FoldAndStrip (t);
642 }
643
644 /* m2expr_BuildMask returns a tree for the mask of a set of nBits.
645 It assumes nBits is <= TSIZE (WORD). */
646
647 tree
648 m2expr_BuildMask (location_t location, tree nBits, bool needconvert)
649 {
650 tree mask = m2expr_BuildLSL (location, m2expr_GetIntegerOne (location),
651 nBits, needconvert);
652 m2assert_AssertLocation (location);
653 return m2expr_BuildSub (location, mask, m2expr_GetIntegerOne (location),
654 needconvert);
655 }
656
657 /* m2expr_BuildLRotate returns a tree in which op1 has been left
658 rotated by nBits. It assumes nBits is <= TSIZE (WORD). */
659
660 tree
661 m2expr_BuildLRotate (location_t location, tree op1, tree nBits,
662 bool needconvert)
663 {
664 tree t;
665
666 op1 = m2expr_FoldAndStrip (op1);
667 nBits = m2expr_FoldAndStrip (nBits);
668 t = m2expr_build_binary_op (location, LROTATE_EXPR, op1, nBits, needconvert);
669 return m2expr_FoldAndStrip (t);
670 }
671
672 /* m2expr_BuildRRotate returns a tree in which op1 has been left
673 rotated by nBits. It assumes nBits is <= TSIZE (WORD). */
674
675 tree
676 m2expr_BuildRRotate (location_t location, tree op1, tree nBits,
677 bool needconvert)
678 {
679 tree t;
680
681 op1 = m2expr_FoldAndStrip (op1);
682 nBits = m2expr_FoldAndStrip (nBits);
683 t = m2expr_build_binary_op (location, RROTATE_EXPR, op1, nBits, needconvert);
684 return m2expr_FoldAndStrip (t);
685 }
686
687 /* BuildLRLn builds and returns tree (op1 rotate left by op2 bits) it
688 rotates a set of size, nBits. */
689
690 tree
691 m2expr_BuildLRLn (location_t location, tree op1, tree op2, tree nBits,
692 bool needconvert)
693 {
694 tree op2min;
695
696 m2assert_AssertLocation (location);
697
698 /* Ensure we wrap the rotate. */
699
700 op2min = m2expr_BuildModTrunc (
701 location, m2convert_ToCardinal (location, op2),
702 m2convert_ToCardinal (location, nBits), needconvert);
703
704 /* Optimize if we are we going to rotate a TSIZE(BITSET) set. */
705
706 if (m2expr_CompareTrees (
707 m2decl_BuildIntegerConstant (m2decl_GetBitsPerBitset ()), nBits)
708 == 0)
709 return m2expr_BuildLRotate (location, op1, op2min, needconvert);
710 else
711 {
712 tree mask = m2expr_BuildMask (location, nBits, needconvert);
713 tree left, right;
714
715 /* Make absolutely sure there are no high order bits lying around. */
716
717 op1 = m2expr_BuildLogicalAnd (location, op1, mask, needconvert);
718 left = m2expr_BuildLSL (location, op1, op2min, needconvert);
719 left = m2expr_BuildLogicalAnd (location, left, mask, needconvert);
720 right = m2expr_BuildLSR (
721 location, op1,
722 m2expr_BuildSub (location, m2convert_ToCardinal (location, nBits),
723 op2min, needconvert),
724 needconvert);
725 return m2expr_BuildLogicalOr (location, left, right, needconvert);
726 }
727 }
728
729 /* BuildLRRn builds and returns tree (op1 rotate right by op2 bits).
730 It rotates a set of size, nBits. */
731
732 tree
733 m2expr_BuildLRRn (location_t location, tree op1, tree op2, tree nBits,
734 bool needconvert)
735 {
736 tree op2min;
737
738 m2assert_AssertLocation (location);
739
740 /* Ensure we wrap the rotate. */
741
742 op2min = m2expr_BuildModTrunc (
743 location, m2convert_ToCardinal (location, op2),
744 m2convert_ToCardinal (location, nBits), needconvert);
745 /* Optimize if we are we going to rotate a TSIZE(BITSET) set. */
746
747 if (m2expr_CompareTrees (
748 m2decl_BuildIntegerConstant (m2decl_GetBitsPerBitset ()), nBits)
749 == 0)
750 return m2expr_BuildRRotate (location, op1, op2min, needconvert);
751 else
752 {
753 tree mask = m2expr_BuildMask (location, nBits, needconvert);
754 tree left, right;
755
756 /* Make absolutely sure there are no high order bits lying around. */
757
758 op1 = m2expr_BuildLogicalAnd (location, op1, mask, needconvert);
759 right = m2expr_BuildLSR (location, op1, op2min, needconvert);
760 left = m2expr_BuildLSL (
761 location, op1,
762 m2expr_BuildSub (location, m2convert_ToCardinal (location, nBits),
763 op2min, needconvert),
764 needconvert);
765 left = m2expr_BuildLogicalAnd (location, left, mask, needconvert);
766 return m2expr_BuildLogicalOr (location, left, right, needconvert);
767 }
768 }
769
770 /* BuildLogicalRotate build the ISO Modula-2 ROTATE operator for a
771 fundamental data type. */
772
773 void
774 m2expr_BuildLogicalRotate (location_t location, tree op1, tree op2, tree op3,
775 tree nBits, bool needconvert)
776 {
777 tree res;
778
779 m2assert_AssertLocation (location);
780 op2 = m2expr_FoldAndStrip (op2);
781 op3 = m2expr_FoldAndStrip (op3);
782 if (TREE_CODE (op3) == INTEGER_CST)
783 {
784 if (tree_int_cst_sgn (op3) < 0)
785 res = m2expr_BuildLRRn (
786 location, op2, m2expr_BuildNegate (location, op3, needconvert),
787 nBits, needconvert);
788 else
789 res = m2expr_BuildLRLn (location, op2, op3, nBits, needconvert);
790 m2statement_BuildAssignmentTree (location, op1, res);
791 }
792 else
793 {
794 char *labelElseName = createUniqueLabel ();
795 char *labelEndName = createUniqueLabel ();
796 tree is_less = m2expr_BuildLessThan (location,
797 m2convert_ToInteger (location, op3),
798 m2expr_GetIntegerZero (location));
799
800 m2statement_DoJump (location, is_less, NULL, labelElseName);
801 res = m2expr_BuildLRLn (location, op2, op3, nBits, needconvert);
802 m2statement_BuildAssignmentTree (location, op1, res);
803 m2statement_BuildGoto (location, labelEndName);
804 m2statement_DeclareLabel (location, labelElseName);
805 res = m2expr_BuildLRRn (location, op2,
806 m2expr_BuildNegate (location, op3, needconvert),
807 nBits, needconvert);
808 m2statement_BuildAssignmentTree (location, op1, res);
809 m2statement_DeclareLabel (location, labelEndName);
810 }
811 }
812
813 /* buildUnboundedArrayOf construct an unbounded struct and returns
814 the gcc tree. The two fields of the structure are initialized to
815 contentsPtr and high. */
816
817 static tree
818 buildUnboundedArrayOf (tree unbounded, tree contentsPtr, tree high)
819 {
820 tree fields = TYPE_FIELDS (unbounded);
821 tree field_list = NULL_TREE;
822 tree constructor;
823
824 field_list = tree_cons (fields, contentsPtr, field_list);
825 fields = TREE_CHAIN (fields);
826
827 field_list = tree_cons (fields, high, field_list);
828
829 constructor = build_constructor_from_list (unbounded, nreverse (field_list));
830 TREE_CONSTANT (constructor) = 0;
831 TREE_STATIC (constructor) = 0;
832
833 return constructor;
834 }
835
836 /* BuildBinarySetDo if the size of the set is <= TSIZE(WORD) then op1
837 := binop(op2, op3) else call m2rtsprocedure(op1, op2, op3). */
838
839 void
840 m2expr_BuildBinarySetDo (location_t location, tree settype, tree op1, tree op2,
841 tree op3, void (*binop) (location_t, tree, tree, tree,
842 tree, bool),
843 bool is_op1lvalue, bool is_op2lvalue, bool is_op3lvalue,
844 tree nBits, tree unbounded, tree varproc,
845 tree leftproc, tree rightproc)
846 {
847 tree size = m2expr_GetSizeOf (location, settype);
848 bool is_const = false;
849 bool is_left = false;
850
851 m2assert_AssertLocation (location);
852
853 ASSERT_BOOL (is_op1lvalue);
854 ASSERT_BOOL (is_op2lvalue);
855 ASSERT_BOOL (is_op3lvalue);
856
857 if (m2expr_CompareTrees (
858 size, m2decl_BuildIntegerConstant (SET_WORD_SIZE / BITS_PER_UNIT))
859 <= 0)
860 /* Small set size <= TSIZE(WORD). */
861 (*binop) (location,
862 m2treelib_get_rvalue (location, op1, settype, is_op1lvalue),
863 m2treelib_get_rvalue (location, op2, settype, is_op2lvalue),
864 m2treelib_get_rvalue (location, op3, settype, is_op3lvalue),
865 nBits, false);
866 else
867 {
868 tree result;
869 tree high = m2expr_BuildSub (
870 location,
871 m2convert_ToCardinal (
872 location,
873 m2expr_BuildDivTrunc (
874 location, size,
875 m2expr_GetSizeOf (location, m2type_GetBitsetType ()),
876 false)),
877 m2expr_GetCardinalOne (location), false);
878
879 /* If op3 is constant then make op3 positive and remember which
880 direction we are shifting. */
881
882 op3 = m2tree_skip_const_decl (op3);
883 if (TREE_CODE (op3) == INTEGER_CST)
884 {
885 is_const = true;
886 if (tree_int_cst_sgn (op3) < 0)
887 op3 = m2expr_BuildNegate (location, op3, false);
888 else
889 is_left = true;
890 op3 = m2convert_BuildConvert (location, m2type_GetM2CardinalType (),
891 op3, false);
892 }
893
894 /* These parameters must match the prototypes of the procedures:
895 ShiftLeft, ShiftRight, ShiftVal, RotateLeft, RotateRight, RotateVal
896 inside gm2-iso/SYSTEM.mod. */
897
898 /* Remember we must build the parameters in reverse. */
899
900 /* Parameter 4 amount. */
901 m2statement_BuildParam (
902 location,
903 m2convert_BuildConvert (
904 location, m2type_GetM2IntegerType (),
905 m2treelib_get_rvalue (location, op3,
906 m2tree_skip_type_decl (TREE_TYPE (op3)),
907 is_op3lvalue),
908 false));
909
910 /* Parameter 3 nBits. */
911 m2statement_BuildParam (
912 location,
913 m2convert_BuildConvert (location, m2type_GetM2CardinalType (),
914 m2expr_FoldAndStrip (nBits), false));
915
916 /* Parameter 2 destination set. */
917 m2statement_BuildParam (
918 location,
919 buildUnboundedArrayOf (
920 unbounded,
921 m2treelib_get_set_address (location, op1, is_op1lvalue), high));
922
923 /* Parameter 1 source set. */
924 m2statement_BuildParam (
925 location,
926 buildUnboundedArrayOf (
927 unbounded,
928 m2treelib_get_set_address (location, op2, is_op2lvalue), high));
929
930 /* Now call the appropriate procedure inside SYSTEM.mod. */
931 if (is_const)
932 if (is_left)
933 result = m2statement_BuildProcedureCallTree (location, leftproc,
934 NULL_TREE);
935 else
936 result = m2statement_BuildProcedureCallTree (location, rightproc,
937 NULL_TREE);
938 else
939 result = m2statement_BuildProcedureCallTree (location, varproc,
940 NULL_TREE);
941 add_stmt (location, result);
942 }
943 }
944
945 /* Print a warning if a constant expression had overflow in folding.
946 Invoke this function on every expression that the language requires
947 to be a constant expression. */
948
949 void
950 m2expr_ConstantExpressionWarning (tree value)
951 {
952 if ((TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST
953 || TREE_CODE (value) == FIXED_CST || TREE_CODE (value) == VECTOR_CST
954 || TREE_CODE (value) == COMPLEX_CST)
955 && TREE_OVERFLOW (value))
956 pedwarn (input_location, OPT_Woverflow, "overflow in constant expression");
957 }
958
959 /* TreeOverflow return true if the contant expression, t, has caused
960 an overflow. No error message or warning is emitted and no
961 modification is made to, t. */
962
963 bool
964 m2expr_TreeOverflow (tree t)
965 {
966 if ((TREE_CODE (t) == INTEGER_CST
967 || (TREE_CODE (t) == COMPLEX_CST
968 && TREE_CODE (TREE_REALPART (t)) == INTEGER_CST))
969 && TREE_OVERFLOW (t))
970 return true;
971 else if ((TREE_CODE (t) == REAL_CST
972 || (TREE_CODE (t) == COMPLEX_CST
973 && TREE_CODE (TREE_REALPART (t)) == REAL_CST))
974 && TREE_OVERFLOW (t))
975 return true;
976 else
977 return false;
978 }
979
980 /* RemoveOverflow if tree, t, is a constant expression it removes any
981 overflow flag and returns, t. */
982
983 tree
984 m2expr_RemoveOverflow (tree t)
985 {
986 if (TREE_CODE (t) == INTEGER_CST
987 || (TREE_CODE (t) == COMPLEX_CST
988 && TREE_CODE (TREE_REALPART (t)) == INTEGER_CST))
989 TREE_OVERFLOW (t) = 0;
990 else if (TREE_CODE (t) == REAL_CST
991 || (TREE_CODE (t) == COMPLEX_CST
992 && TREE_CODE (TREE_REALPART (t)) == REAL_CST))
993 TREE_OVERFLOW (t) = 0;
994 return t;
995 }
996
997 /* BuildCoerce return a tree containing the expression, expr, after
998 it has been coersed to, type. */
999
1000 tree
1001 m2expr_BuildCoerce (location_t location, tree des, tree type, tree expr)
1002 {
1003 tree copy = copy_node (expr);
1004 TREE_TYPE (copy) = type;
1005
1006 m2assert_AssertLocation (location);
1007
1008 return m2treelib_build_modify_expr (location, des, NOP_EXPR, copy);
1009 }
1010
1011 /* BuildTrunc return an integer expression from a REAL or LONGREAL op1. */
1012
1013 tree
1014 m2expr_BuildTrunc (tree op1)
1015 {
1016 return convert_to_integer (m2type_GetIntegerType (),
1017 m2expr_FoldAndStrip (op1));
1018 }
1019
1020 /* checkUnaryWholeOverflow decide if we can check this unary expression. */
1021
1022 tree
1023 m2expr_checkUnaryWholeOverflow (location_t location, enum tree_code code,
1024 tree arg, tree lowest, tree min, tree max)
1025 {
1026 if (M2Options_GetWholeValueCheck () && (min != NULL))
1027 {
1028 lowest = m2tree_skip_type_decl (lowest);
1029 arg = fold_convert_loc (location, lowest, arg);
1030
1031 switch (code)
1032 {
1033 case NEGATE_EXPR:
1034 return checkWholeNegateOverflow (location, arg, lowest, min, max);
1035 default:
1036 return NULL;
1037 }
1038 }
1039 return NULL;
1040 }
1041
1042 /* build_unary_op return a unary tree node. */
1043
1044 tree
1045 m2expr_build_unary_op_check (location_t location, enum tree_code code,
1046 tree arg, tree lowest, tree min, tree max)
1047 {
1048 tree argtype = TREE_TYPE (arg);
1049 tree result;
1050 tree check = NULL;
1051
1052 m2assert_AssertLocation (location);
1053
1054 arg = m2expr_FoldAndStrip (arg);
1055
1056 if ((TREE_CODE (argtype) != REAL_TYPE) && (min != NULL))
1057 check = m2expr_checkUnaryWholeOverflow (location, code, arg, lowest, min, max);
1058
1059 result = build1 (code, argtype, arg);
1060 protected_set_expr_location (result, location);
1061
1062 if (check != NULL)
1063 result = build2 (COMPOUND_EXPR, argtype, check, result);
1064
1065 if (SCALAR_FLOAT_TYPE_P (argtype))
1066 m2expr_checkRealOverflow (location, code, result);
1067
1068 return m2expr_FoldAndStrip (result);
1069 }
1070
1071 /* build_unary_op return a unary tree node. */
1072
1073 tree
1074 m2expr_build_unary_op (location_t location, enum tree_code code, tree arg,
1075 int flag ATTRIBUTE_UNUSED)
1076 {
1077 tree argtype = TREE_TYPE (arg);
1078 tree result;
1079
1080 m2assert_AssertLocation (location);
1081
1082 arg = m2expr_FoldAndStrip (arg);
1083 result = build1 (code, argtype, arg);
1084 protected_set_expr_location (result, location);
1085
1086 return m2expr_FoldAndStrip (result);
1087 }
1088
1089 /* build_binary_op is a heavily pruned version of the one found in
1090 c-typeck.cc. The Modula-2 expression rules are much more restricted
1091 than C. */
1092
1093 tree
1094 build_binary_op (location_t location, enum tree_code code, tree op1, tree op2,
1095 int convert ATTRIBUTE_UNUSED)
1096 {
1097 tree type1 = TREE_TYPE (op1);
1098 tree result;
1099
1100 m2assert_AssertLocation (location);
1101
1102 /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */
1103 STRIP_TYPE_NOPS (op1);
1104 STRIP_TYPE_NOPS (op2);
1105
1106 op1 = m2expr_FoldAndStrip (op1);
1107 op2 = m2expr_FoldAndStrip (op2);
1108
1109 result = build2 (code, type1, op1, op2);
1110 protected_set_expr_location (result, location);
1111
1112 return m2expr_FoldAndStrip (result);
1113 }
1114
1115 /* BuildLessThanZero - returns a tree containing (< value 0). It
1116 checks the min and max value to ensure that the test can be safely
1117 achieved and will short circuit the result otherwise. */
1118
1119 tree
1120 m2expr_BuildLessThanZero (location_t location, tree value, tree type, tree min,
1121 tree max)
1122 {
1123 if (m2expr_CompareTrees (min, m2expr_GetIntegerZero (location)) >= 0)
1124 /* min is greater than or equal to zero therefore value will always
1125 be >= 0. */
1126 return m2type_GetBooleanFalse ();
1127 else if (m2expr_CompareTrees (max, m2expr_GetIntegerZero (location)) == -1)
1128 /* max is less than zero therefore value will always be < 0. */
1129 return m2type_GetBooleanTrue ();
1130 /* We now know 0 lies in the range min..max so we can safely cast
1131 zero to type. */
1132 return m2expr_BuildLessThan (
1133 location, value,
1134 fold_convert_loc (location, type, m2expr_GetIntegerZero (location)));
1135 }
1136
1137 /* BuildGreaterThanZero - returns a tree containing (> value 0). It
1138 checks the min and max value to ensure that the test can be safely
1139 achieved and will short circuit the result otherwise. */
1140
1141 tree
1142 m2expr_BuildGreaterThanZero (location_t location, tree value, tree type,
1143 tree min, tree max)
1144 {
1145 if (m2expr_CompareTrees (min, m2expr_GetIntegerZero (location)) == 1)
1146 /* min is greater than zero therefore value will always be > 0. */
1147 return m2type_GetBooleanTrue ();
1148 else if (m2expr_CompareTrees (max, m2expr_GetIntegerZero (location)) <= 0)
1149 /* max is less than or equal to zero therefore value will always be
1150 <= 0. */
1151 return m2type_GetBooleanFalse ();
1152 /* We now know 0 lies in the range min..max so we can safely cast
1153 zero to type. */
1154 return m2expr_BuildGreaterThan (
1155 location, value,
1156 fold_convert_loc (location, type, m2expr_GetIntegerZero (location)));
1157 }
1158
1159 /* BuildEqualToZero - returns a tree containing (= value 0). It
1160 checks the min and max value to ensure that the test can be safely
1161 achieved and will short circuit the result otherwise. */
1162
1163 tree
1164 m2expr_BuildEqualToZero (location_t location, tree value, tree type, tree min,
1165 tree max)
1166 {
1167 if (m2expr_CompareTrees (min, m2expr_GetIntegerZero (location)) == 1)
1168 /* min is greater than zero therefore value will always be > 0. */
1169 return m2type_GetBooleanFalse ();
1170 else if (m2expr_CompareTrees (max, m2expr_GetIntegerZero (location)) < 0)
1171 /* max is less than or equal to zero therefore value will always be <
1172 0. */
1173 return m2type_GetBooleanFalse ();
1174 /* We now know 0 lies in the range min..max so we can safely cast
1175 zero to type. */
1176 return m2expr_BuildEqualTo (
1177 location, value,
1178 fold_convert_loc (location, type, m2expr_GetIntegerZero (location)));
1179 }
1180
1181 /* BuildNotEqualToZero - returns a tree containing (# value 0). It
1182 checks the min and max value to ensure that the test can be safely
1183 achieved and will short circuit the result otherwise. */
1184
1185 tree
1186 m2expr_BuildNotEqualToZero (location_t location, tree value, tree type,
1187 tree min, tree max)
1188 {
1189 if (m2expr_CompareTrees (min, m2expr_GetIntegerZero (location)) == 1)
1190 /* min is greater than zero therefore value will always be true. */
1191 return m2type_GetBooleanTrue ();
1192 else if (m2expr_CompareTrees (max, m2expr_GetIntegerZero (location)) < 0)
1193 /* max is less than or equal to zero therefore value will always be
1194 true. */
1195 return m2type_GetBooleanTrue ();
1196 /* We now know 0 lies in the range min..max so we can safely cast
1197 zero to type. */
1198 return m2expr_BuildNotEqualTo (
1199 location, value,
1200 fold_convert_loc (location, type, m2expr_GetIntegerZero (location)));
1201 }
1202
1203
1204 /* BuildGreaterThanOrEqualZero - returns a tree containing (>= value 0). It
1205 checks the min and max value to ensure that the test can be safely
1206 achieved and will short circuit the result otherwise. */
1207
1208 tree
1209 m2expr_BuildGreaterThanOrEqualZero (location_t location, tree value, tree type,
1210 tree min, tree max)
1211 {
1212 if (m2expr_CompareTrees (min, m2expr_GetIntegerZero (location)) >= 0)
1213 /* min is greater than or equal to zero therefore value will always be >= 0. */
1214 return m2type_GetBooleanTrue ();
1215 else if (m2expr_CompareTrees (max, m2expr_GetIntegerZero (location)) < 0)
1216 /* max is less than zero therefore value will always be < 0. */
1217 return m2type_GetBooleanFalse ();
1218 /* We now know 0 lies in the range min..max so we can safely cast
1219 zero to type. */
1220 return m2expr_BuildGreaterThan (
1221 location, value,
1222 fold_convert_loc (location, type, m2expr_GetIntegerZero (location)));
1223 }
1224
1225
1226 /* BuildLessThanOrEqualZero - returns a tree containing (<= value 0). It
1227 checks the min and max value to ensure that the test can be safely
1228 achieved and will short circuit the result otherwise. */
1229
1230 tree
1231 m2expr_BuildLessThanOrEqualZero (location_t location, tree value, tree type,
1232 tree min, tree max)
1233 {
1234 if (m2expr_CompareTrees (min, m2expr_GetIntegerZero (location)) > 0)
1235 /* min is greater than zero therefore value will always be > 0. */
1236 return m2type_GetBooleanFalse ();
1237 else if (m2expr_CompareTrees (max, m2expr_GetIntegerZero (location)) <= 0)
1238 /* max is less than or equal to zero therefore value will always be <= 0. */
1239 return m2type_GetBooleanTrue ();
1240 /* We now know 0 lies in the range min..max so we can safely cast
1241 zero to type. */
1242 return m2expr_BuildLessThanOrEqual (
1243 location, value,
1244 fold_convert_loc (location, type, m2expr_GetIntegerZero (location)));
1245 }
1246
1247
1248 /* get_current_function_name, return the name of the current function if
1249 it currently exists. NULL is returned if we are not inside a function. */
1250
1251 static const char *
1252 get_current_function_name (void)
1253 {
1254 if (current_function_decl != NULL
1255 && (DECL_NAME (current_function_decl) != NULL)
1256 && (IDENTIFIER_POINTER (DECL_NAME (current_function_decl)) != NULL))
1257 return IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
1258 return NULL;
1259 }
1260
1261 /* checkWholeNegateOverflow - check to see whether -arg will overflow
1262 an integer.
1263
1264 PROCEDURE sneg (i: INTEGER) ;
1265 BEGIN
1266 IF i = MIN(INTEGER)
1267 THEN
1268 'integer overflow'
1269 END
1270 END sneg ;
1271
1272 general purpose subrange type, i, is currently legal, min is
1273 MIN(type) and max is MAX(type).
1274
1275 PROCEDURE sneg (i: type) ;
1276 BEGIN
1277 max := MAX (type) ;
1278 min := MIN (type) ;
1279 (* cannot overflow if i is 0 *)
1280 IF (i#0) AND
1281 (* will overflow if entire range is positive. *)
1282 ((min >= 0) OR
1283 (* will overflow if entire range is negative. *)
1284 (max <= 0) OR
1285 (* c7 and c8 and c9 and c10 -> c17 more units positive. *)
1286 ((min < 0) AND (max > 0) AND ((min + max) > 0) AND (i > -min)) OR
1287 (* c11 and c12 and c13 and c14 -> c18 more units negative. *)
1288 ((min < 0) AND (max > 0) AND ((min + max) < 0) AND (i < -max)))
1289 THEN
1290 'type overflow'
1291 END
1292 END sneg ; */
1293
1294 static tree
1295 checkWholeNegateOverflow (location_t location,
1296 tree i, tree type, tree min,
1297 tree max)
1298 {
1299 tree a1
1300 = m2expr_BuildNotEqualToZero (location, i, type, min, max); /* i # 0. */
1301 tree c1 = m2expr_BuildGreaterThanZero (location, min, type, min,
1302 max); /* min > 0. */
1303 tree c2 = m2expr_BuildEqualToZero (location, min, type, min,
1304 max); /* min == 0. */
1305 tree c4 = m2expr_BuildLessThanZero (location, max, type, min,
1306 max); /* max < 0. */
1307 tree c5 = m2expr_BuildEqualToZero (location, max, type, min,
1308 max); /* max == 0. */
1309 tree c7 = m2expr_BuildLessThanZero (location, min, type, min,
1310 max); /* min < 0. */
1311 tree c8 = m2expr_BuildGreaterThanZero (location, max, type, min,
1312 max); /* max > 0. */
1313 tree c9 = m2expr_BuildGreaterThanZero (
1314 location, m2expr_BuildAdd (location, min, max, false), type, min,
1315 max); /* min + max > 0. */
1316 tree c10 = m2expr_BuildGreaterThan (
1317 location, i, m2expr_BuildNegate (location, min, false)); /* i > -min. */
1318 tree c11 = m2expr_BuildLessThanZero (
1319 location, m2expr_BuildAdd (location, min, max, false), type, min,
1320 max); /* min + max < 0. */
1321 tree c12 = m2expr_BuildLessThan (
1322 location, i, m2expr_BuildNegate (location, max, false)); /* i < -max. */
1323
1324 tree b1 = m2expr_BuildTruthOrIf (location, c1, c2);
1325 tree b2 = m2expr_BuildTruthOrIf (location, c8, c5);
1326 tree o1 = m2expr_BuildTruthAndIf (location, b1, b2);
1327
1328 tree b3 = m2expr_BuildTruthOrIf (location, c7, c2);
1329 tree b4 = m2expr_BuildTruthOrIf (location, c4, c5);
1330 tree o2 = m2expr_BuildTruthAndIf (location, b3, b4);
1331
1332 tree o3 = m2expr_Build4TruthAndIf (location, c7, c8, c9, c10);
1333 tree o4 = m2expr_Build4TruthAndIf (location, c7, c8, c11, c12);
1334
1335 tree a2 = m2expr_Build4TruthOrIf (location, o1, o2, o3, o4);
1336 tree condition
1337 = m2expr_FoldAndStrip (m2expr_BuildTruthAndIf (location, a1, a2));
1338
1339 tree t = M2Range_BuildIfCallWholeHandlerLoc (location, condition,
1340 get_current_function_name (),
1341 "whole value unary minus will cause range overflow");
1342 return t;
1343 }
1344
1345 /* checkWholeAddOverflow - check to see whether op1 + op2 will
1346 overflow an integer.
1347
1348 PROCEDURE sadd (i, j: INTEGER) ;
1349 BEGIN
1350 IF ((j>0) AND (i > MAX(INTEGER)-j)) OR ((j<0) AND (i < MIN(INTEGER)-j))
1351 THEN
1352 'signed addition overflow'
1353 END
1354 END sadd. */
1355
1356 static tree
1357 checkWholeAddOverflow (location_t location, tree i, tree j, tree lowest,
1358 tree min, tree max)
1359 {
1360 tree j_gt_zero = m2expr_BuildGreaterThanZero (location, j, lowest, min, max);
1361 tree i_gt_max_sub_j = m2expr_BuildGreaterThan (
1362 location, i, m2expr_BuildSub (location, max, j, false));
1363 tree j_lt_zero = m2expr_BuildLessThanZero (location, j, lowest, min, max);
1364 tree i_lt_min_sub_j = m2expr_BuildLessThan (location, i,
1365 m2expr_BuildSub (location, min, j, false));
1366 tree lhs_or = m2expr_FoldAndStrip (m2expr_BuildTruthAndIf (location, j_gt_zero, i_gt_max_sub_j));
1367 tree rhs_or = m2expr_FoldAndStrip (m2expr_BuildTruthAndIf (location, j_lt_zero, i_lt_min_sub_j));
1368 tree condition
1369 = m2expr_FoldAndStrip (m2expr_BuildTruthOrIf (location, lhs_or, rhs_or));
1370 tree result = M2Range_BuildIfCallWholeHandlerLoc (location, condition,
1371 get_current_function_name (),
1372 "whole value addition will cause a range overflow");
1373 return result;
1374 }
1375
1376 /* checkWholeSubOverflow - check to see whether op1 - op2 will
1377 overflow an integer.
1378
1379 PROCEDURE ssub (i, j: INTEGER) ;
1380 BEGIN
1381 IF ((j>0) AND (i < MIN(INTEGER)+j)) OR ((j<0) AND (i > MAX(INTEGER)+j))
1382 THEN
1383 'signed subtraction overflow'
1384 END
1385 END ssub. */
1386
1387 static tree
1388 checkWholeSubOverflow (location_t location, tree i, tree j, tree lowest,
1389 tree min, tree max)
1390 {
1391 tree c1 = m2expr_BuildGreaterThanZero (location, j, lowest, min, max);
1392 tree c2 = m2expr_BuildLessThan (location, i,
1393 m2expr_BuildAdd (location, min, j, false));
1394 tree c3 = m2expr_BuildLessThanZero (location, j, lowest, min, max);
1395 tree c4 = m2expr_BuildGreaterThan (location, i,
1396 m2expr_BuildAdd (location, max, j, false));
1397 tree c5 = m2expr_FoldAndStrip (m2expr_BuildTruthAndIf (location, c1, c2));
1398 tree c6 = m2expr_FoldAndStrip (m2expr_BuildTruthAndIf (location, c3, c4));
1399 tree condition
1400 = m2expr_FoldAndStrip (m2expr_BuildTruthOrIf (location, c5, c6));
1401 tree t = M2Range_BuildIfCallWholeHandlerLoc (location, condition,
1402 get_current_function_name (),
1403 "whole value subtraction will cause a range overflow");
1404 return t;
1405 }
1406
1407 /* Build4TruthAndIf - return true if a && b && c && d. Retain order left to
1408 * right. */
1409
1410 static tree
1411 m2expr_Build4TruthAndIf (location_t location, tree a, tree b, tree c, tree d)
1412 {
1413 tree t1 = m2expr_FoldAndStrip (m2expr_BuildTruthAndIf (location, a, b));
1414 tree t2 = m2expr_FoldAndStrip (m2expr_BuildTruthAndIf (location, t1, c));
1415 return m2expr_FoldAndStrip (m2expr_BuildTruthAndIf (location, t2, d));
1416 }
1417
1418 /* Build3TruthAndIf - return true if a && b && c. Retain order left to right.
1419 */
1420
1421 static tree
1422 m2expr_Build3TruthAndIf (location_t location, tree op1, tree op2, tree op3)
1423 {
1424 tree t = m2expr_FoldAndStrip (m2expr_BuildTruthAndIf (location, op1, op2));
1425 return m2expr_FoldAndStrip (m2expr_BuildTruthAndIf (location, t, op3));
1426 }
1427
1428 /* Build3TruthOrIf - return true if a || b || c. Retain order left to right.
1429 */
1430
1431 static tree
1432 m2expr_Build3TruthOrIf (location_t location, tree op1, tree op2, tree op3)
1433 {
1434 tree t = m2expr_FoldAndStrip (m2expr_BuildTruthOrIf (location, op1, op2));
1435 return m2expr_FoldAndStrip (m2expr_BuildTruthOrIf (location, t, op3));
1436 }
1437
1438 /* Build4TruthOrIf - return true if op1 || op2 || op3 || op4. Retain order
1439 left to right. */
1440
1441 static tree
1442 m2expr_Build4TruthOrIf (location_t location, tree op1, tree op2, tree op3,
1443 tree op4)
1444 {
1445 tree t1 = m2expr_FoldAndStrip (m2expr_BuildTruthOrIf (location, op1, op2));
1446 tree t2 = m2expr_FoldAndStrip (m2expr_BuildTruthOrIf (location, t1, op3));
1447 return m2expr_FoldAndStrip (m2expr_BuildTruthOrIf (location, t2, op4));
1448 }
1449
1450 /* Build4LogicalOr - return true if op1 || op2 || op3 || op4. */
1451
1452 static tree
1453 m2expr_Build4LogicalOr (location_t location, tree op1, tree op2, tree op3,
1454 tree op4)
1455 {
1456 tree t1 = m2expr_FoldAndStrip (
1457 m2expr_BuildLogicalOr (location, op1, op2, false));
1458 tree t2
1459 = m2expr_FoldAndStrip (m2expr_BuildLogicalOr (location, t1, op3, false));
1460 return m2expr_FoldAndStrip (
1461 m2expr_BuildLogicalOr (location, t2, op4, false));
1462 }
1463
1464 /* checkWholeMultOverflow - check to see whether i * j will overflow
1465 an integer.
1466
1467 PROCEDURE smult (lhs, rhs: INTEGER) ;
1468 BEGIN
1469 IF ((lhs > 0) AND (rhs > 0) AND (lhs > max DIV rhs)) OR
1470 ((lhs > 0) AND (rhs < 0) AND (rhs < min DIV lhs)) OR
1471 ((lhs < 0) AND (rhs > 0) AND (lhs < min DIV rhs)) OR
1472 ((lhs < 0) AND (rhs < 0) AND (lhs < max DIV rhs))
1473 THEN
1474 error ('signed multiplication overflow')
1475 END
1476 END smult ;
1477
1478 if ((c1 && c3 && c4)
1479 || (c1 && c5 && c6)
1480 || (c2 && c3 && c7)
1481 || (c2 && c5 && c8))
1482 error ('signed subtraction overflow'). */
1483
1484 static tree
1485 testWholeMultOverflow (location_t location, tree lhs, tree rhs,
1486 tree lowest, tree min, tree max)
1487 {
1488 tree c1 = m2expr_BuildGreaterThanZero (location, lhs, lowest, min, max);
1489 tree c2 = m2expr_BuildLessThanZero (location, lhs, lowest, min, max);
1490
1491 tree c3 = m2expr_BuildGreaterThanZero (location, rhs, lowest, min, max);
1492 tree c4 = m2expr_BuildGreaterThan (
1493 location, lhs, m2expr_BuildDivTrunc (location, max, rhs, false));
1494
1495 tree c5 = m2expr_BuildLessThanZero (location, rhs, lowest, min, max);
1496 tree c6 = m2expr_BuildLessThan (
1497 location, rhs, m2expr_BuildDivTrunc (location, min, lhs, false));
1498 tree c7 = m2expr_BuildLessThan (
1499 location, lhs, m2expr_BuildDivTrunc (location, min, rhs, false));
1500 tree c8 = m2expr_BuildLessThan (
1501 location, lhs, m2expr_BuildDivTrunc (location, max, rhs, false));
1502
1503 tree c9 = m2expr_Build3TruthAndIf (location, c1, c3, c4);
1504 tree c10 = m2expr_Build3TruthAndIf (location, c1, c5, c6);
1505 tree c11 = m2expr_Build3TruthAndIf (location, c2, c3, c7);
1506 tree c12 = m2expr_Build3TruthAndIf (location, c2, c5, c8);
1507
1508 tree condition = m2expr_Build4LogicalOr (location, c9, c10, c11, c12);
1509 return condition;
1510 }
1511
1512
1513 static tree
1514 checkWholeMultOverflow (location_t location, tree i, tree j, tree lowest,
1515 tree min, tree max)
1516 {
1517 tree condition = testWholeMultOverflow (location, i, j, lowest, min, max);
1518 tree result = M2Range_BuildIfCallWholeHandlerLoc (location, condition,
1519 get_current_function_name (),
1520 "whole value multiplication will cause a range overflow");
1521 return result;
1522 }
1523
1524
1525 static tree
1526 divMinUnderflow (location_t location, tree value, tree lowest, tree min, tree max)
1527 {
1528 tree min2 = m2expr_BuildMult (location, min, min, false);
1529 tree rhs = m2expr_BuildGreaterThanOrEqual (location, value, min2);
1530 tree lhs = testWholeMultOverflow (location, min, min, lowest, min, max);
1531 return m2expr_BuildTruthAndIf (location, lhs, rhs);
1532 }
1533
1534 /*
1535 divexpr - returns true if a DIV_TRUNC b will overflow.
1536 */
1537
1538 /* checkWholeDivOverflow - check to see whether i DIV_TRUNC j will overflow
1539 an integer. The Modula-2 implementation of the GCC trees follows:
1540
1541 PROCEDURE divtruncexpr (a, b: INTEGER) : BOOLEAN ;
1542 BEGIN
1543 (* Firstly catch division by 0. *)
1544 RETURN ((b = 0) OR
1545 (* Case 2 range is always negative. *)
1546 (* In which case a division will be illegal as result will be positive. *)
1547 (max < 0) OR
1548 (* Case 1 both min / max are positive, check for underflow. *)
1549 ((min >= 0) AND (max >= 0) AND (multMinOverflow (b) OR (a < b * min))) OR
1550 (* Case 1 both min / max are positive, check for overflow. *)
1551 ((min >= 0) AND (max >= 0) AND (divMinUnderflow (a) OR (b > a DIV min))) OR
1552 (* Case 3 mixed range, need to check underflow. *)
1553 ((min < 0) AND (max >= 0) AND (a < 0) AND (b < 0) AND (b >= a DIV min)) OR
1554 ((min < 0) AND (max >= 0) AND (a < 0) AND (b > 0) AND (b <= a DIV max)) OR
1555 ((min < 0) AND (max >= 0) AND (a >= 0) AND (b < 0) AND (a DIV b < min)))
1556 END divtruncexpr ;
1557
1558 s1 -> a DIV min
1559 s2 -> a DIV max
1560 s3 -> a DIV b
1561
1562 b4 -> (min >= 0) AND (max >= 0)
1563 b5 -> (min < 0) AND (max >= 0)
1564 a_lt_b_mult_min -> (a < b * min)
1565 b_mult_min_overflow -> testWholeMultOverflow (location, b, min, lowest, min, max)
1566 b6 -> (b_mult_min_overflow OR a_lt_b_mult_min)
1567 b_gt_s1 -> (b > s1)
1568 a_div_min_overflow -> divMinUnderflow (location, a, min, lowest, min, max)
1569 b7 -> (a_div_min_overflow OR b_gt_s1)
1570 b8 -> (a < 0)
1571 b9 -> (b < 0)
1572 b10 -> (b > 0)
1573 b11 -> (b >= s1)
1574 b12 -> (b <= s2)
1575 b13 -> (s3 < min)
1576 b14 -> a >= 0
1577
1578 c1 -> (b = 0)
1579 c2 -> (max < 0)
1580 c3 -> (b4 AND b6)
1581 c4 -> (b4 AND b7)
1582 c5 -> (b5 AND b8 AND b9 AND b11)
1583 c6 -> (b5 AND b8 AND b10 AND b12)
1584 c7 -> (b5 AND b14 AND b9 AND b13)
1585
1586 if (c1 || c2 || c3 || c4 || c5 || c6 || c7)
1587 error ('signed div trunc overflow'). */
1588
1589 static tree
1590 checkWholeDivTruncOverflow (location_t location, tree i, tree j, tree lowest,
1591 tree min, tree max)
1592 {
1593 tree b4a = m2expr_BuildGreaterThanOrEqualZero (location, min, lowest, min, max);
1594 tree b4b = m2expr_BuildGreaterThanOrEqualZero (location, max, lowest, min, max);
1595 tree b4 = m2expr_BuildTruthAndIf (location, b4a, b4b);
1596 tree b5a = m2expr_BuildLessThanZero (location, min, lowest, min, max);
1597 tree b5 = m2expr_BuildTruthAndIf (location, b5a, b4b);
1598 tree c1 = m2expr_BuildEqualToZero (location, j, lowest, min, max);
1599 tree c2 = m2expr_BuildLessThanZero (location, max, lowest, min, max);
1600 tree i_lt_j_mult_min = m2expr_BuildLessThan (location, i, m2expr_BuildMult (location, j, min, false));
1601 tree j_mult_min_overflow = testWholeMultOverflow (location, j, min, lowest, min, max);
1602 tree b6 = m2expr_BuildTruthOrIf (location, j_mult_min_overflow, i_lt_j_mult_min);
1603 tree c3 = m2expr_BuildTruthAndIf (location, b4, b6);
1604 tree s1 = m2expr_BuildDivTrunc (location, i, min, false);
1605 tree s2 = m2expr_BuildDivTrunc (location, i, max, false);
1606 tree s3 = m2expr_BuildDivTrunc (location, i, j, false);
1607
1608 tree j_gt_s1 = m2expr_BuildGreaterThan (location, j, s1);
1609 tree i_div_min_overflow = divMinUnderflow (location, i, lowest, min, max);
1610 tree b7 = m2expr_BuildTruthOrIf (location, i_div_min_overflow, j_gt_s1);
1611 tree c4 = m2expr_BuildTruthAndIf (location, b4, b7);
1612 tree b8 = m2expr_BuildLessThanZero (location, i, lowest, min, max);
1613 tree b9 = m2expr_BuildLessThanZero (location, j, lowest, min, max);
1614 tree b10 = m2expr_BuildGreaterThanZero (location, j, lowest, min, max);
1615 tree b11 = m2expr_BuildGreaterThanOrEqual (location, j, s1);
1616 tree b12 = m2expr_BuildLessThanOrEqual (location, j, s2);
1617 tree b13 = m2expr_BuildLessThan (location, s3, min);
1618 tree b14 = m2expr_BuildGreaterThanOrEqualZero (location, i, lowest, min, max);
1619 tree c5 = m2expr_Build4TruthAndIf (location, b5, b8, b9, b11);
1620 tree c6 = m2expr_Build4TruthAndIf (location, b5, b8, b10, b12);
1621 tree c7 = m2expr_Build4TruthAndIf (location, b5, b14, b9, b13);
1622 tree c8 = m2expr_Build4TruthOrIf (location, c1, c2, c3, c4);
1623 tree condition = m2expr_Build4TruthOrIf (location, c5, c6, c7, c8);
1624 tree t = M2Range_BuildIfCallWholeHandlerLoc (location, condition,
1625 get_current_function_name (),
1626 "whole value truncated division will cause a range overflow");
1627 return t;
1628 }
1629
1630 #if 0
1631 (*
1632 divexpr - returns true if a DIV_CEIL b will overflow.
1633 *)
1634
1635 (* checkWholeDivCeilOverflow - check to see whether i DIV_CEIL j will overflow
1636 an integer. *)
1637
1638 PROCEDURE divceilexpr (i, j: INTEGER) : BOOLEAN ;
1639 BEGIN
1640 RETURN ((j = 0) OR (* division by zero. *)
1641 (maxT < 0) OR (* both inputs are < 0 and max is < 0,
1642 therefore error. *)
1643 ((i # 0) AND (* first operand is legally zero,
1644 result is also legally zero. *)
1645 divCeilOverflowCases (i, j)))
1646 END divceilexpr ;
1647
1648
1649 (*
1650 divCeilOverflowCases - precondition: i, j are in range values.
1651 postcondition: true is returned if i divceil will
1652 result in an overflow/underflow.
1653 *)
1654
1655 PROCEDURE divCeilOverflowCases (i, j: INTEGER) : BOOLEAN ;
1656 BEGIN
1657 RETURN (((i > 0) AND (j > 0) AND divCeilOverflowPosPos (i, j)) OR
1658 ((i < 0) AND (j < 0) AND divCeilOverflowNegNeg (i, j)) OR
1659 ((i > 0) AND (j < 0) AND divCeilOverflowPosNeg (i, j)) OR
1660 ((i < 0) AND (j > 0) AND divCeilOverflowNegPos (i, j)))
1661 END divCeilOverflowCases ;
1662
1663
1664 (*
1665 divCeilOverflowPosPos - precondition: i, j are legal and are both >= 0.
1666 postcondition: true is returned if i divceil will
1667 result in an overflow/underflow.
1668 *)
1669
1670 PROCEDURE divCeilOverflowPosPos (i, j: INTEGER) : BOOLEAN ;
1671 BEGIN
1672 RETURN (((i MOD j = 0) AND (i < j * minT)) OR
1673 (((i MOD j # 0) AND (i < j * minT + 1))))
1674 END divCeilOverflowPosPos ;
1675
1676
1677 (*
1678 divCeilOverflowNegNeg - precondition: i, j are in range values and both < 0.
1679 postcondition: true is returned if i divceil will
1680 result in an overflow/underflow.
1681 *)
1682
1683 PROCEDURE divCeilOverflowNegNeg (i, j: INTEGER) : BOOLEAN ;
1684 BEGIN
1685 RETURN ((maxT <= 0) OR (* signs will cause overflow. *)
1686 (* check for underflow. *)
1687 ((ABS (i) MOD ABS (j) = 0) AND (i >= j * minT)) OR
1688 ((ABS (i) MOD ABS (j) # 0) AND (i >= j * minT - 1)) OR
1689 (* check for overflow. *)
1690 (((ABS (i) MOD maxT) = 0) AND (ABS (i) DIV maxT > ABS (j))) OR
1691 (((ABS (i) MOD maxT) # 0) AND (ABS (i) DIV maxT > ABS (j) + 1)))
1692 END divCeilOverflowNegNeg ;
1693
1694
1695 (*
1696 divCeilOverflowNegPos - precondition: i, j are in range values. i < 0, j >= 0.
1697 postcondition: true is returned if i divceil will
1698 result in an overflow/underflow.
1699 *)
1700
1701 PROCEDURE divCeilOverflowNegPos (i, j: INTEGER) : BOOLEAN ;
1702 BEGIN
1703 (* easier than might be initially expected. We know minT < 0 and maxT > 0.
1704 We know the result will be negative and therefore we only need to test
1705 against minT. *)
1706 RETURN (((ABS (i) MOD j = 0) AND (i < j * minT)) OR
1707 ((ABS (i) MOD j # 0) AND (i < j * minT - 1)))
1708 END divCeilOverflowNegPos ;
1709
1710
1711 (*
1712 divCeilOverflowPosNeg - precondition: i, j are in range values. i >= 0, j < 0.
1713 postcondition: true is returned if i divceil will
1714 result in an overflow/underflow.
1715 *)
1716
1717 PROCEDURE divCeilOverflowPosNeg (i, j: INTEGER) : BOOLEAN ;
1718 BEGIN
1719 (* easier than might be initially expected. We know minT < 0 and maxT > 0.
1720 We know the result will be negative and therefore we only need to test
1721 against minT. *)
1722 RETURN (((i MOD ABS (j) = 0) AND (i > j * minT)) OR
1723 ((i MOD ABS (j) # 0) AND (i > j * minT - 1)))
1724 END divCeilOverflowPosNeg ;
1725 #endif
1726
1727 /* divCeilOverflowPosPos, precondition: lhs, rhs are legal and are both >= 0.
1728 Postcondition: TRUE is returned if lhs divceil rhs will result
1729 in an overflow/underflow.
1730
1731 A handbuilt expression of trees implementing:
1732
1733 RETURN (((lhs MOD rhs = 0) AND (min >= 0) AND (lhs < rhs * min)) OR (* check for underflow, no remainder. *)
1734 lhs_lt_rhs_mult_min
1735 (((lhs MOD rhs # 0) AND (lhs < rhs * min + 1)))) (* check for underflow with remainder. *)
1736 ((lhs > min) AND (lhs - 1 > rhs * min))
1737 lhs_gt_rhs_mult_min
1738
1739 a -> (lhs MOD rhs = 0) AND (lhs < rhs * min)
1740 b -> (lhs MOD rhs # 0) AND (lhs < rhs * min + 1)
1741 RETURN a OR b. */
1742
1743 static tree
1744 divCeilOverflowPosPos (location_t location, tree i, tree j, tree lowest,
1745 tree min, tree max)
1746 {
1747 tree i_mod_j = m2expr_BuildModTrunc (location, i, j, false);
1748 tree i_mod_j_eq_zero = m2expr_BuildEqualToZero (location, i_mod_j, lowest, min, max);
1749 tree i_mod_j_ne_zero = m2expr_BuildNotEqualToZero (location, i_mod_j, lowest, min, max);
1750 tree j_min = m2expr_BuildMult (location, j, min, false);
1751 tree j_min_1 = m2expr_BuildAdd (location, j_min, m2expr_GetIntegerOne (location), false);
1752 tree i_lt_j_min = m2expr_BuildLessThan (location, i, j_min);
1753 tree i_lt_j_min_1 = m2expr_BuildLessThan (location, i, j_min_1);
1754 tree a = m2expr_BuildTruthAndIf (location, i_mod_j_eq_zero, i_lt_j_min);
1755 tree b = m2expr_BuildTruthAndIf (location, i_mod_j_ne_zero, i_lt_j_min_1);
1756 return m2expr_BuildTruthOrIf (location, a, b);
1757 }
1758
1759
1760 /* divCeilOverflowPosNeg precondition: i, j are in range values and i >=0, j < 0.
1761 Postcondition: TRUE is returned if i divceil j will result in an
1762 overflow/underflow.
1763
1764 A handbuilt expression of trees implementing:
1765
1766 RETURN (((i MOD ABS (j) = 0) AND (i > j * min)) OR
1767 ((i MOD ABS (j) # 0) AND (i > j * min - 1)))
1768
1769 abs_j -> (ABS (j))
1770 i_mod_abs_j -> (i MOD abs_j)
1771 i_mod_abs_j_eq_0 -> (i_mod_abs_j = 0)
1772 i_mod_abs_j_ne_0 -> (i_mod_abs_j # 0)
1773 j_mult_min -> (j * min)
1774 j_mult_min_1 -> (j_mult_min - 1)
1775 i_gt_j_mult_min -> (i > j_mult_min)
1776 i_gt_j_mult_min_1 -> (i > j_mult_min_1)
1777 a -> (i_mod_abs_j_eq_0 AND i_gt_j_mult_min)
1778 b -> (i_mod_abs_j_ne_0 AND i_gt_j_mult_min_1)
1779 c -> (a OR b). */
1780
1781 static tree
1782 divCeilOverflowPosNeg (location_t location, tree i, tree j, tree lowest, tree min, tree max)
1783 {
1784 tree abs_j = m2expr_BuildAbs (location, j);
1785 tree i_mod_abs_j = m2expr_BuildModFloor (location, i, abs_j, false);
1786 tree i_mod_abs_j_eq_0 = m2expr_BuildEqualToZero (location, i_mod_abs_j, lowest, min, max);
1787 tree i_mod_abs_j_ne_0 = m2expr_BuildNotEqualToZero (location, i_mod_abs_j, lowest, min, max);
1788 tree j_mult_min = m2expr_BuildMult (location, j, min, false);
1789 tree j_mult_min_1 = m2expr_BuildPostDec (location, j_mult_min);
1790 tree i_gt_j_mult_min = m2expr_BuildGreaterThan (location, i, j_mult_min);
1791 tree i_gt_j_mult_min_1 = m2expr_BuildGreaterThan (location, i, j_mult_min_1);
1792 tree a = m2expr_BuildTruthAndIf (location, i_mod_abs_j_eq_0, i_gt_j_mult_min);
1793 tree b = m2expr_BuildTruthAndIf (location, i_mod_abs_j_ne_0, i_gt_j_mult_min_1);
1794 tree c = m2expr_BuildTruthOrIf (location, a, b);
1795 return c;
1796 }
1797
1798
1799 /* divCeilOverflowNegPos precondition: i, j are in range values and i < 0, j >= 0.
1800 Postcondition: TRUE is returned if i divceil j will result in an
1801 overflow/underflow.
1802
1803 A handbuilt expression of trees implementing:
1804
1805 RETURN (((ABS (i) MOD j = 0) AND (i < j * min)) OR
1806 ((ABS (i) MOD j # 0) AND (i < j * min - 1)))
1807
1808 abs_i -> (ABS (i))
1809 abs_i_mod_j -> (abs_i MOD j)
1810 abs_i_mod_j_eq_0 -> (abs_i_mod_j = 0)
1811 abs_i_mod_j_ne_0 -> (abs_i_mod_j # 0)
1812 j_mult_min -> (j * min)
1813 j_mult_min_1 -> (j_mult_min - 1)
1814 i_lt_j_mult_min -> (i < j_mult_min)
1815 i_lt_j_mult_min_1 -> (i < j_mult_min_1)
1816 a = (abs_i_mod_j_eq_0 AND i_lt_j_mult_min)
1817 b = (abs_i_mod_j_ne_0 AND i_lt_j_mult_min_1)
1818 c -> (a OR b). */
1819
1820 static tree
1821 divCeilOverflowNegPos (location_t location, tree i, tree j, tree lowest, tree min, tree max)
1822 {
1823 tree abs_i = m2expr_BuildAbs (location, i);
1824 tree abs_i_mod_j = m2expr_BuildModFloor (location, abs_i, j, false);
1825 tree abs_i_mod_j_eq_0 = m2expr_BuildEqualToZero (location, abs_i_mod_j, lowest, min, max);
1826 tree abs_i_mod_j_ne_0 = m2expr_BuildNotEqualToZero (location, abs_i_mod_j, lowest, min, max);
1827 tree j_mult_min = m2expr_BuildMult (location, j, min, false);
1828 tree j_mult_min_1 = m2expr_BuildPostDec (location, j_mult_min);
1829 tree i_lt_j_mult_min = m2expr_BuildLessThan (location, i, j_mult_min);
1830 tree i_lt_j_mult_min_1 = m2expr_BuildLessThan (location, i, j_mult_min_1);
1831 tree a = m2expr_BuildTruthAndIf (location, abs_i_mod_j_eq_0, i_lt_j_mult_min);
1832 tree b = m2expr_BuildTruthAndIf (location, abs_i_mod_j_ne_0, i_lt_j_mult_min_1);
1833 tree c = m2expr_BuildTruthOrIf (location, a, b);
1834 return c;
1835 }
1836
1837
1838 /* divCeilOverflowNegNeg precondition: i, j are in range values and both < 0.
1839 Postcondition: TRUE is returned if i divceil j will result in an
1840 overflow/underflow.
1841
1842 A handbuilt expression of trees implementing:
1843
1844 RETURN ((max <= 0) OR (* signs will cause overflow. *)
1845 (* check for underflow. *)
1846 ((ABS (i) MOD ABS (j) = 0) AND (i >= j * min)) OR
1847 ((ABS (i) MOD ABS (j) # 0) AND (i >= j * min - 1)) OR
1848 (* check for overflow. *)
1849 (((ABS (i) MOD max) = 0) AND (ABS (i) DIV max > ABS (j))) OR
1850 (((ABS (i) MOD max) # 0) AND (ABS (i) DIV max > ABS (j) + 1)))
1851
1852 max_lte_0 -> (max <= 0)
1853 abs_i -> (ABS (i))
1854 abs_j -> (ABS (j))
1855 abs_i_mod_abs_j -> (abs_i MOD abs_j)
1856 abs_i_mod_abs_j_eq_0 -> (abs_i_mod_abs_j = 0)
1857 abs_i_mod_abs_j_ne_0 -> (abs_i_mod_abs_j # 0)
1858 j_mult_min -> (j * min)
1859 j_mult_min_1 -> (j_mult_min - 1)
1860 i_ge_j_mult_min -> (i >= j_mult_min)
1861 i_ge_j_mult_min_1 -> (i >= j_mult_min_1)
1862 abs_i_mod_max -> (abs_i mod max)
1863 abs_i_div_max -> (abs_i DIVfloor max)
1864 abs_j_1 -> (abs_j + 1)
1865 abs_i_mod_max_eq_0 -> (abs_i_mod_max = 0)
1866 abs_i_mod_max_ne_0 -> (abs_i_mod_max # 0)
1867 abs_i_div_max_gt_abs_j -> (abs_i_div_max > abs_j)
1868 abs_i_div_max_gt_abs_j_1 -> (abs_i_div_max > abs_j_1)
1869
1870 a -> (abs_i_mod_abs_j_eq_0 AND i_ge_j_mult_min)
1871 b -> (abs_i_mod_abs_j_ne_0 AND i_ge_j_mult_min_1)
1872 c -> (abs_i_mod_max_eq_0 AND abs_i_div_max_gt_abs_j)
1873 d -> (abs_i_mod_max_ne_0 AND abs_i_div_max_gt_abs_j_1)
1874 e -> (a OR b OR c OR d)
1875 return max_lte_0 OR e. */
1876
1877 static tree
1878 divCeilOverflowNegNeg (location_t location, tree i, tree j, tree lowest,
1879 tree min, tree max)
1880 {
1881 tree max_lte_0 = m2expr_BuildLessThanOrEqualZero (location, max, lowest, min, max);
1882 tree abs_i = m2expr_BuildAbs (location, i);
1883 tree abs_j = m2expr_BuildAbs (location, j);
1884 tree abs_i_mod_abs_j = m2expr_BuildModFloor (location, abs_i, abs_j, false);
1885 tree abs_i_mod_abs_j_eq_0 = m2expr_BuildEqualToZero (location, abs_i_mod_abs_j,
1886 lowest, min, max);
1887 tree abs_i_mod_abs_j_ne_0 = m2expr_BuildNotEqualToZero (location, abs_i_mod_abs_j,
1888 lowest, min, max);
1889 tree j_mult_min = m2expr_BuildMult (location, j, min, false);
1890 tree j_mult_min_1 = m2expr_BuildPostDec (location, j_mult_min);
1891 tree i_ge_j_mult_min = m2expr_BuildGreaterThanOrEqual (location, i, j_mult_min);
1892 tree i_ge_j_mult_min_1 = m2expr_BuildGreaterThanOrEqual (location, i, j_mult_min_1);
1893 tree abs_i_mod_max = m2expr_BuildModFloor (location, abs_i, max, false);
1894 tree abs_i_div_max = m2expr_BuildDivFloor (location, abs_i, max, false);
1895 tree abs_j_1 = m2expr_BuildPostInc (location, abs_j);
1896 tree abs_i_mod_max_eq_0 = m2expr_BuildEqualToZero (location, abs_i_mod_max, lowest, min, max);
1897 tree abs_i_mod_max_ne_0 = m2expr_BuildNotEqualToZero (location, abs_i_mod_max, lowest, min, max);
1898 tree abs_i_div_max_gt_abs_j = m2expr_BuildGreaterThan (location, abs_i_div_max, abs_j);
1899 tree abs_i_div_max_gt_abs_j_1 = m2expr_BuildGreaterThan (location, abs_i_div_max, abs_j_1);
1900
1901 tree a = m2expr_BuildTruthAndIf (location, abs_i_mod_abs_j_eq_0, i_ge_j_mult_min);
1902 tree b = m2expr_BuildTruthAndIf (location, abs_i_mod_abs_j_ne_0, i_ge_j_mult_min_1);
1903 tree c = m2expr_BuildTruthAndIf (location, abs_i_mod_max_eq_0, abs_i_div_max_gt_abs_j);
1904 tree d = m2expr_BuildTruthAndIf (location, abs_i_mod_max_ne_0, abs_i_div_max_gt_abs_j_1);
1905 tree e = m2expr_Build4TruthOrIf (location, a, b, c, d);
1906 return m2expr_BuildTruthOrIf (location, max_lte_0, e);
1907 }
1908
1909
1910 /* divCeilOverflowCases, precondition: i, j are in range values.
1911 Postcondition: TRUE is returned if i divceil will result in an
1912 overflow/underflow.
1913
1914 A handbuilt expression of trees implementing:
1915
1916 RETURN (((i > 0) AND (j > 0) AND divCeilOverflowPosPos (i, j)) OR
1917 ((i < 0) AND (j < 0) AND divCeilOverflowNegNeg (i, j)) OR
1918 ((i > 0) AND (j < 0) AND divCeilOverflowPosNeg (i, j)) OR
1919 ((i < 0) AND (j > 0) AND divCeilOverflowNegPos (i, j)))
1920
1921 a -> ((i > 0) AND (j > 0) AND divCeilOverflowPosPos (i, j))
1922 b -> ((i < 0) AND (j < 0) AND divCeilOverflowNegNeg (i, j))
1923 c -> ((i > 0) AND (j < 0) AND divCeilOverflowPosNeg (i, j))
1924 d -> ((i < 0) AND (j > 0) AND divCeilOverflowNegPos (i, j))
1925
1926 RETURN a AND b AND c AND d. */
1927
1928 static tree
1929 divCeilOverflowCases (location_t location, tree i, tree j, tree lowest,
1930 tree min, tree max)
1931 {
1932 tree i_gt_zero = m2expr_BuildGreaterThanZero (location, i, lowest, min, max);
1933 tree j_gt_zero = m2expr_BuildGreaterThanZero (location, j, lowest, min, max);
1934 tree i_lt_zero = m2expr_BuildLessThanZero (location, i, lowest, min, max);
1935 tree j_lt_zero = m2expr_BuildLessThanZero (location, j, lowest, min, max);
1936 tree a = m2expr_Build3TruthAndIf (location, i_gt_zero, j_gt_zero,
1937 divCeilOverflowPosPos (location, i, j, lowest, min, max));
1938 tree b = m2expr_Build3TruthAndIf (location, i_lt_zero, j_lt_zero,
1939 divCeilOverflowNegNeg (location, i, j, lowest, min, max));
1940 tree c = m2expr_Build3TruthAndIf (location, i_gt_zero, j_lt_zero,
1941 divCeilOverflowPosNeg (location, i, j, lowest, min, max));
1942 tree d = m2expr_Build3TruthAndIf (location, i_lt_zero, j_gt_zero,
1943 divCeilOverflowNegPos (location, i, j, lowest, min, max));
1944 return m2expr_Build4TruthOrIf (location, a, b, c, d);
1945 }
1946
1947
1948 /* checkWholeDivCeilOverflow check to see whether i DIV_CEIL j will overflow
1949 an integer. A handbuilt expression of trees implementing:
1950
1951 RETURN ((j = 0) OR (* division by zero. *)
1952 (maxT < 0) OR (* both inputs are < 0 and max is < 0,
1953 therefore error. *)
1954 ((i # 0) AND (* first operand is legally zero,
1955 result is also legally zero. *)
1956 divCeilOverflowCases (i, j)))
1957
1958 using the following subexpressions:
1959
1960 j_eq_zero -> (j == 0)
1961 max_lt_zero -> (max < 0)
1962 i_ne_zero -> (i # 0). */
1963
1964 static tree
1965 checkWholeDivCeilOverflow (location_t location, tree i, tree j, tree lowest,
1966 tree min, tree max)
1967 {
1968 tree j_eq_zero = m2expr_BuildEqualToZero (location, j, lowest, min, max);
1969 tree max_lt_zero = m2expr_BuildLessThanZero (location, max, lowest, min, max);
1970 tree i_ne_zero = m2expr_BuildNotEqualToZero (location, i, lowest, min, max);
1971 tree j_lt_zero;
1972 tree rhs = m2expr_BuildTruthAndIf (location,
1973 i_ne_zero,
1974 divCeilOverflowCases (location,
1975 i, j, lowest, min, max));
1976
1977 if (M2Options_GetISO ())
1978 j_lt_zero = m2expr_FoldAndStrip (m2expr_BuildLessThanZero (location, j, lowest, min, max));
1979 else
1980 j_lt_zero = m2expr_GetIntegerZero (location);
1981 j_eq_zero = m2expr_FoldAndStrip (j_eq_zero);
1982 max_lt_zero = m2expr_FoldAndStrip (max_lt_zero);
1983 i_ne_zero = m2expr_FoldAndStrip (i_ne_zero);
1984 rhs = m2expr_FoldAndStrip (rhs);
1985
1986 tree condition = m2expr_Build4TruthOrIf (location, j_eq_zero, max_lt_zero, rhs, j_lt_zero);
1987 tree t = M2Range_BuildIfCallWholeHandlerLoc (location, condition,
1988 get_current_function_name (),
1989 "whole value ceil division will cause a range overflow");
1990 return t;
1991 }
1992
1993
1994 /* checkWholeModTruncOverflow, the GCC tree.def defines TRUNC_MOD_EXPR to return
1995 the remainder which has the same sign as the dividend. In ISO Modula-2 the
1996 divisor must never be negative (or zero). The pseudo code for implementing these
1997 checks is given below:
1998
1999 IF j = 0
2000 THEN
2001 RETURN TRUE (* division by zero. *)
2002 ELSIF j < 0
2003 THEN
2004 RETURN TRUE (* modulus and division by negative (rhs) not allowed in ISO Modula-2. *)
2005 ELSIF i = 0
2006 THEN
2007 RETURN FALSE (* must be legal as result is same as operand. *)
2008 ELSIF i > 0
2009 THEN
2010 (* test for: i MOD j < minT *)
2011 IF j > i
2012 THEN
2013 RETURN FALSE
2014 END ;
2015 RETURN i - ((i DIV j) * j) < minT
2016 ELSIF i < 0
2017 THEN
2018 (* the result will always be positive and less than i, given that j is less than zero
2019 we know that minT must be < 0 as well and therefore the result of i MOD j will
2020 never underflow. *)
2021 RETURN FALSE
2022 END ;
2023 RETURN FALSE
2024
2025 which can be converted into a large expression:
2026
2027 RETURN (j = 0) OR ((j < 0) AND ISO) OR
2028 ((i # 0) AND (j <= i) AND (i - ((i DIVtrunc j) * j) < minT)
2029
2030 and into GCC trees:
2031
2032 c1 -> (j = 0)
2033 c2 -> (j < 0) (* only called from ISO or PIM4 or -fpositive-mod-floor *)
2034 c3 -> (i # 0)
2035 c4 -> (j <= i)
2036 c6 -> (i DIVtrunc j)
2037 c7 -> (i - (c6 * j))
2038 c5 -> c7 < minT
2039
2040 t -> (c1 OR c2 OR
2041 (c3 AND c4 AND c5)). */
2042
2043 static tree
2044 checkWholeModTruncOverflow (location_t location, tree i, tree j, tree lowest,
2045 tree min, tree max)
2046 {
2047 tree c1 = m2expr_BuildEqualToZero (location, j, lowest, min, max);
2048 tree c2 = m2expr_BuildLessThanZero (location, j, lowest, min, max);
2049 tree c3 = m2expr_BuildNotEqualToZero (location, i, lowest, min, max);
2050 tree c4 = m2expr_BuildLessThanOrEqual (location, j, i);
2051 tree c6 = m2expr_BuildDivTrunc (location, i, j, false);
2052 tree c7 = m2expr_BuildSub (location, i, m2expr_BuildMult (location, c6, j, false), false);
2053 tree c5 = m2expr_BuildLessThan (location, c7, min);
2054 tree c8 = m2expr_Build3TruthAndIf (location, c3, c4, c5);
2055 tree condition = m2expr_Build3TruthOrIf (location, c1, c2, c8);
2056 tree t = M2Range_BuildIfCallWholeHandlerLoc (location, condition,
2057 get_current_function_name (),
2058 "whole value trunc modulus will cause a range overflow");
2059 return t;
2060 }
2061
2062
2063 /* checkWholeModCeilOverflow, the GCC tree.def defines CEIL_MOD_EXPR to return
2064 the remainder which has the same opposite of the divisor. In gm2 this is
2065 only called when the divisor is negative. The pseudo code for implementing
2066 these checks is given below:
2067
2068 IF j = 0
2069 THEN
2070 RETURN TRUE (* division by zero. *)
2071 END ;
2072 t := i - j * divceil (i, j) ;
2073 printf ("t = %d, i = %d, j = %d, %d / %d = %d\n",
2074 t, i, j, i, j, divceil (i, j));
2075 RETURN NOT ((t >= minT) AND (t <= maxT))
2076
2077 which can be converted into the expression:
2078
2079 t := i - j * divceil (i, j) ;
2080 RETURN (j = 0) OR (NOT ((t >= minT) AND (t <= maxT)))
2081
2082 and into GCC trees:
2083
2084 c1 -> (j = 0)
2085 c2 -> (i - j)
2086 c3 -> (i DIVceil j)
2087 t -> (c2 * c3)
2088 c4 -> (t >= minT)
2089 c5 -> (t <= maxT)
2090 c6 -> (c4 AND c5)
2091 c7 -> (NOT c6)
2092 c8 -> (c1 OR c7)
2093 return c8. */
2094
2095 static tree
2096 checkWholeModCeilOverflow (location_t location,
2097 tree i, tree j, tree lowest,
2098 tree min, tree max)
2099 {
2100 tree c1 = m2expr_BuildEqualToZero (location, j, lowest, min, max);
2101 tree c2 = m2expr_BuildSub (location, i, j, false);
2102 tree c3 = m2expr_BuildDivCeil (location, i, j, false);
2103 tree t = m2expr_BuildMult (location, c2, c3, false);
2104 tree c4 = m2expr_BuildGreaterThanOrEqual (location, t, min);
2105 tree c5 = m2expr_BuildLessThanOrEqual (location, t, max);
2106 tree c6 = m2expr_BuildTruthAndIf (location, c4, c5);
2107 tree c7 = m2expr_BuildTruthNot (location, c6);
2108 tree condition = m2expr_BuildTruthOrIf (location, c1, c7);
2109 tree s = M2Range_BuildIfCallWholeHandlerLoc (location, condition,
2110 get_current_function_name (),
2111 "whole value ceil modulus will cause a range overflow");
2112 return s;
2113 }
2114
2115
2116 /* checkWholeModFloorOverflow, the GCC tree.def defines FLOOR_MOD_EXPR to return
2117 the remainder which has the same sign as the divisor. In gm2 this is
2118 only called when the divisor is positive. The pseudo code for implementing
2119 these checks is given below:
2120
2121 IF j = 0
2122 THEN
2123 RETURN TRUE (* division by zero. *)
2124 END ;
2125 t := i - j * divfloor (i, j) ;
2126 printf ("t = %d, i = %d, j = %d, %d / %d = %d\n",
2127 t, i, j, i, j, divfloor (i, j));
2128 RETURN NOT ((t >= minT) AND (t <= maxT))
2129
2130 which can be converted into the expression:
2131
2132 t := i - j * divfloor (i, j) ;
2133 RETURN (j = 0) OR (NOT ((t >= minT) AND (t <= maxT)))
2134
2135 and into GCC trees:
2136
2137 c1 -> (j = 0)
2138 c2 -> (i - j)
2139 c3 -> (i DIVfloor j)
2140 t -> (c2 * c3)
2141 c4 -> (t >= minT)
2142 c5 -> (t <= maxT)
2143 c6 -> (c4 AND c5)
2144 c7 -> (NOT c6)
2145 c8 -> (c1 OR c7)
2146 return c8. */
2147
2148 static tree
2149 checkWholeModFloorOverflow (location_t location,
2150 tree i, tree j, tree lowest,
2151 tree min, tree max)
2152 {
2153 tree c1 = m2expr_BuildEqualToZero (location, j, lowest, min, max);
2154 tree c2 = m2expr_BuildSub (location, i, j, false);
2155 tree c3 = m2expr_BuildDivFloor (location, i, j, false);
2156 tree t = m2expr_BuildMult (location, c2, c3, false);
2157 tree c4 = m2expr_BuildGreaterThanOrEqual (location, t, min);
2158 tree c5 = m2expr_BuildLessThanOrEqual (location, t, max);
2159 tree c6 = m2expr_BuildTruthAndIf (location, c4, c5);
2160 tree c7 = m2expr_BuildTruthNot (location, c6);
2161 tree condition = m2expr_BuildTruthOrIf (location, c1, c7);
2162 tree s = M2Range_BuildIfCallWholeHandlerLoc (location, condition,
2163 get_current_function_name (),
2164 "whole value floor modulus will cause a range overflow");
2165 return s;
2166 }
2167
2168
2169 #if 0
2170 /* The following is a Modula-2 implementation of the C tree node code
2171 this code has been hand translated into GCC trees. */
2172
2173 (*
2174 divFloorOverflow2 - returns true if an overflow will occur
2175 if i divfloor j is performed.
2176 *)
2177
2178 PROCEDURE divFloorOverflow (i, j: INTEGER) : BOOLEAN ;
2179 BEGIN
2180 RETURN ((j = 0) OR (* division by zero. *)
2181 (maxT < 0) OR (* both inputs are < 0 and max is < 0,
2182 therefore error. *)
2183 (* --fixme-- remember here to also check
2184 if ISO M2 dialect and j < 0
2185 which will also generate an error. *)
2186 ((i # 0) AND (* first operand is legally zero,
2187 result is also legally zero. *)
2188 divFloorOverflowCases (i, j)))
2189 END divFloorOverflow ;
2190
2191
2192 (*
2193 divFloorOverflowCases - precondition: i, j are in range values.
2194 postcondition: true is returned if i divfloor will
2195 result in an overflow/underflow.
2196 *)
2197
2198 PROCEDURE divFloorOverflowCases (i, j: INTEGER) : BOOLEAN ;
2199 BEGIN
2200 RETURN (((i > 0) AND (j > 0) AND divFloorOverflowPosPos (i, j)) OR
2201 ((i < 0) AND (j < 0) AND divFloorOverflowNegNeg (i, j)) OR
2202 ((i > 0) AND (j < 0) AND divFloorOverflowPosNeg (i, j)) OR
2203 ((i < 0) AND (j > 0) AND divFloorOverflowNegPos (i, j)))
2204 END divFloorOverflowCases ;
2205
2206
2207 (*
2208 divFloorOverflowPosPos - precondition: lhs, rhs are legal and are both >= 0.
2209 postcondition: true is returned if lhs divfloor rhs will
2210 result in an overflow/underflow.
2211 *)
2212
2213 PROCEDURE divFloorOverflowPosPos (lhs, rhs: INTEGER) : BOOLEAN ;
2214 BEGIN
2215 RETURN multMinOverflow (rhs) OR (lhs < rhs * min)
2216 END divFloorOverflowPosPos ;
2217
2218
2219 (*
2220 divFloorOverflowNegNeg - precondition: i, j are in range values and both < 0.
2221 postcondition: true is returned if i divfloor will
2222 result in an overflow/underflow.
2223 *)
2224
2225 PROCEDURE divFloorOverflowNegNeg (i, j: INTEGER) : BOOLEAN ;
2226 BEGIN
2227 RETURN ((maxT <= 0) OR (* signs will cause overflow. *)
2228 (* check for underflow. *)
2229 (i >= j * minT) OR
2230 (* check for overflow. *)
2231 (ABS (i) DIV maxT > ABS (j)))
2232 END divFloorOverflowNegNeg ;
2233
2234
2235 (*
2236 divFloorOverflowNegPos - precondition: i, j are in range values. i < 0, j >= 0.
2237 postcondition: true is returned if i divfloor will
2238 result in an overflow/underflow.
2239 *)
2240
2241 PROCEDURE divFloorOverflowNegPos (i, j: INTEGER) : BOOLEAN ;
2242 BEGIN
2243 (* easier than might be initially expected. We know minT < 0 and maxT > 0.
2244 We know the result will be negative and therefore we only need to test
2245 against minT. *)
2246 RETURN i < j * minT
2247 END divFloorOverflowNegPos ;
2248
2249
2250 (*
2251 divFloorOverflowPosNeg - precondition: i, j are in range values. i >= 0, j < 0.
2252 postcondition: true is returned if i divfloor will
2253 result in an overflow/underflow.
2254 *)
2255
2256 PROCEDURE divFloorOverflowPosNeg (i, j: INTEGER) : BOOLEAN ;
2257 BEGIN
2258 (* easier than might be initially expected. We know minT < 0 and maxT > 0.
2259 We know the result will be negative and therefore we only need to test
2260 against minT. *)
2261 RETURN i >= j * minT - j (* is safer than i > j * minT -1 *)
2262 END divFloorOverflowPosNeg ;
2263 #endif
2264
2265
2266 /* divFloorOverflowPosPos, precondition: i, j are legal and are both >= 0.
2267 Postcondition: true is returned if i divfloor will result in an overflow/underflow.
2268
2269 A handbuilt expression of trees implementing:
2270
2271 RETURN i < j * min
2272
2273 j_mult_min -> (j * min)
2274 RETURN i < j_mult_min. */
2275
2276 static tree
2277 divFloorOverflowPosPos (location_t location, tree i, tree j, tree min)
2278 {
2279 tree j_mult_min = m2expr_BuildMult (location, j, min, false);
2280 tree i_lt_j_mult_min = m2expr_BuildLessThan (location, i, j_mult_min);
2281 return i_lt_j_mult_min;
2282 }
2283
2284
2285 /* divFloorOverflowNegNeg precondition: i, j are in range values and both < 0.
2286 Postcondition: true is returned if i divfloor j will result in an
2287 overflow/underflow.
2288
2289 A handbuilt expression of trees implementing:
2290
2291 RETURN ((maxT <= 0) OR (* signs will cause overflow. *)
2292 (* check for underflow. *)
2293 (i >= j * min) OR
2294 (* check for overflow. *)
2295 (ABS (i) DIV max > ABS (j)))
2296
2297 max_lte_0 -> (max <= 0)
2298 abs_i -> (ABS (i))
2299 abs_j -> (ABS (j))
2300 j_mult_min -> (j * min)
2301 i_ge_j_mult_min -> (i >= j_mult_min)
2302 abs_i_div_max -> (abs_i divfloor max)
2303 abs_i_div_max_gt_abs_j -> (abs_i_div_max > abs_j)
2304
2305 return max_lte_0 OR
2306 i_ge_j_mult_min OR
2307 abs_i_div_max_gt_abs_j. */
2308
2309 static tree
2310 divFloorOverflowNegNeg (location_t location, tree i, tree j, tree lowest,
2311 tree min, tree max)
2312 {
2313 tree max_lte_0 = m2expr_BuildLessThanOrEqualZero (location, max, lowest, min, max);
2314 tree abs_i = m2expr_BuildAbs (location, i);
2315 tree abs_j = m2expr_BuildAbs (location, j);
2316 tree j_mult_min = m2expr_BuildMult (location, j, min, false);
2317 tree i_ge_j_mult_min = m2expr_BuildGreaterThanOrEqual (location, i, j_mult_min);
2318 tree abs_i_div_max = m2expr_BuildDivFloor (location, abs_i, max, false);
2319 tree abs_i_div_max_gt_abs_j = m2expr_BuildGreaterThan (location, abs_i_div_max, abs_j);
2320
2321 return m2expr_Build3TruthOrIf (location, max_lte_0, i_ge_j_mult_min, abs_i_div_max_gt_abs_j);
2322 }
2323
2324
2325 /* divFloorOverflowPosNeg precondition: i, j are in range values and i >=0, j < 0.
2326 Postcondition: true is returned if i divfloor j will result in an
2327 overflow/underflow.
2328
2329 A handbuilt expression of trees implementing:
2330
2331 RETURN i >= j * min - j (* is safer than i > j * min -1 *)
2332
2333 j_mult_min -> (j * min)
2334 j_mult_min_sub_j -> (j_mult_min - j)
2335 i_ge_j_mult_min_sub_j -> (i >= j_mult_min_sub_j)
2336
2337 return i_ge_j_mult_min_sub_j. */
2338
2339 static tree
2340 divFloorOverflowPosNeg (location_t location, tree i, tree j, tree min)
2341 {
2342 tree j_mult_min = m2expr_BuildMult (location, j, min, false);
2343 tree j_mult_min_sub_j = m2expr_BuildSub (location, j_mult_min, j, false);
2344 tree i_ge_j_mult_min_sub_j = m2expr_BuildGreaterThanOrEqual (location, i, j_mult_min_sub_j);
2345 return i_ge_j_mult_min_sub_j;
2346 }
2347
2348
2349 /* divFloorOverflowNegPos precondition: i, j are in range values and i < 0, j > 0.
2350 Postcondition: true is returned if i divfloor j will result in an
2351 overflow/underflow.
2352
2353 A handbuilt expression of trees implementing:
2354
2355 RETURN i < j * min
2356
2357 j_mult_min -> (j * min)
2358 RETURN i < j_mult_min. */
2359
2360 static tree
2361 divFloorOverflowNegPos (location_t location, tree i, tree j, tree min)
2362 {
2363 tree j_mult_min = m2expr_BuildMult (location, j, min, false);
2364 tree i_lt_j_mult_min = m2expr_BuildLessThan (location, i, j_mult_min);
2365 return i_lt_j_mult_min;
2366 }
2367
2368
2369 /* divFloorOverflowCases, precondition: i, j are in range values.
2370 Postcondition: true is returned if i divfloor will result in an
2371 overflow/underflow.
2372
2373 A handbuilt expression of trees implementing:
2374
2375 RETURN (((i > 0) AND (j > 0) AND divFloorOverflowPosPos (i, j)) OR
2376 ((i < 0) AND (j < 0) AND divFloorOverflowNegNeg (i, j)) OR
2377 ((i > 0) AND (j < 0) AND divFloorOverflowPosNeg (i, j)) OR
2378 ((i < 0) AND (j > 0) AND divFloorOverflowNegPos (i, j)))
2379
2380 a -> ((i > 0) AND (j > 0) AND divFloorOverflowPosPos (i, j))
2381 b -> ((i < 0) AND (j < 0) AND divFloorOverflowNegNeg (i, j))
2382 c -> ((i > 0) AND (j < 0) AND divFloorOverflowPosNeg (i, j))
2383 d -> ((i < 0) AND (j > 0) AND divFloorOverflowNegPos (i, j))
2384
2385 RETURN a AND b AND c AND d. */
2386
2387 static tree
2388 divFloorOverflowCases (location_t location, tree i, tree j, tree lowest,
2389 tree min, tree max)
2390 {
2391 tree i_gt_zero = m2expr_BuildGreaterThanZero (location, i, lowest, min, max);
2392 tree j_gt_zero = m2expr_BuildGreaterThanZero (location, j, lowest, min, max);
2393 tree i_lt_zero = m2expr_BuildLessThanZero (location, i, lowest, min, max);
2394 tree j_lt_zero = m2expr_BuildLessThanZero (location, j, lowest, min, max);
2395 tree a = m2expr_Build3TruthAndIf (location, i_gt_zero, j_gt_zero,
2396 divFloorOverflowPosPos (location, i, j, min));
2397 tree b = m2expr_Build3TruthAndIf (location, i_lt_zero, j_lt_zero,
2398 divFloorOverflowNegNeg (location, i, j, lowest, min, max));
2399 tree c = m2expr_Build3TruthAndIf (location, i_gt_zero, j_lt_zero,
2400 divFloorOverflowPosNeg (location, i, j, min));
2401 tree d = m2expr_Build3TruthAndIf (location, i_lt_zero, j_gt_zero,
2402 divFloorOverflowNegPos (location, i, j, min));
2403 return m2expr_Build4TruthOrIf (location, a, b, c, d);
2404 }
2405
2406
2407 /* checkWholeDivFloorOverflow check to see whether i DIV_FLOOR j will overflow
2408 an integer. A handbuilt expression of trees implementing:
2409
2410 RETURN ((j = 0) OR (* division by zero. *)
2411 (maxT < 0) OR (* both inputs are < 0 and max is < 0,
2412 therefore error. *)
2413 (* we also check
2414 if ISO M2 dialect and j < 0
2415 which will also generate an error. *)
2416 ((i # 0) AND (* first operand is legally zero,
2417 result is also legally zero. *)
2418 divFloorOverflowCases (i, j)))
2419
2420 using the following subexpressions:
2421
2422 j_eq_zero -> (j == 0)
2423 max_lt_zero -> (max < 0)
2424 i_ne_zero -> (i # 0). */
2425
2426 static tree
2427 checkWholeDivFloorOverflow (location_t location, tree i, tree j, tree lowest,
2428 tree min, tree max)
2429 {
2430 tree j_eq_zero = m2expr_BuildEqualToZero (location, j, lowest, min, max);
2431 tree max_lt_zero = m2expr_BuildLessThanZero (location, max, lowest, min, max);
2432 tree i_ne_zero = m2expr_BuildNotEqualToZero (location, i, lowest, min, max);
2433 tree j_lt_zero;
2434 tree rhs = m2expr_BuildTruthAndIf (location,
2435 i_ne_zero,
2436 divFloorOverflowCases (location,
2437 i, j, lowest, min, max));
2438
2439 if (M2Options_GetISO ())
2440 /* ISO Modula-2 raises an exception if the right hand operand is < 0. */
2441 j_lt_zero = m2expr_FoldAndStrip (m2expr_BuildLessThanZero (location, j, lowest, min, max));
2442 else
2443 j_lt_zero = m2expr_GetIntegerZero (location);
2444 j_eq_zero = m2expr_FoldAndStrip (j_eq_zero);
2445 max_lt_zero = m2expr_FoldAndStrip (max_lt_zero);
2446 i_ne_zero = m2expr_FoldAndStrip (i_ne_zero);
2447 rhs = m2expr_FoldAndStrip (rhs);
2448
2449 tree condition = m2expr_Build4TruthOrIf (location, j_eq_zero, max_lt_zero, rhs, j_lt_zero);
2450 tree t = M2Range_BuildIfCallWholeHandlerLoc (location, condition,
2451 get_current_function_name (),
2452 "whole value floor division will cause a range overflow");
2453 return t;
2454 }
2455
2456 /* checkWholeOverflow check to see if the binary operators will overflow
2457 ordinal types. */
2458
2459 static tree
2460 m2expr_checkWholeOverflow (location_t location, enum tree_code code, tree op1,
2461 tree op2, tree lowest, tree min, tree max)
2462 {
2463 if (M2Options_GetWholeValueCheck () && (min != NULL))
2464 {
2465 lowest = m2tree_skip_type_decl (lowest);
2466 op1 = fold_convert_loc (location, lowest, op1);
2467 op2 = fold_convert_loc (location, lowest, op2);
2468
2469 switch (code)
2470 {
2471 case PLUS_EXPR:
2472 return checkWholeAddOverflow (location, op1, op2, lowest, min, max);
2473 case MINUS_EXPR:
2474 return checkWholeSubOverflow (location, op1, op2, lowest, min, max);
2475 case MULT_EXPR:
2476 return checkWholeMultOverflow (location, op1, op2, lowest, min, max);
2477 case TRUNC_DIV_EXPR:
2478 return checkWholeDivTruncOverflow (location, op1, op2, lowest, min, max);
2479 case CEIL_DIV_EXPR:
2480 return checkWholeDivCeilOverflow (location, op1, op2, lowest, min, max);
2481 case FLOOR_DIV_EXPR:
2482 return checkWholeDivFloorOverflow (location, op1, op2, lowest, min, max);
2483 case TRUNC_MOD_EXPR:
2484 return checkWholeModTruncOverflow (location, op1, op2, lowest, min, max);
2485 case CEIL_MOD_EXPR:
2486 return checkWholeModCeilOverflow (location, op1, op2, lowest, min, max);
2487 case FLOOR_MOD_EXPR:
2488 return checkWholeModFloorOverflow (location, op1, op2, lowest, min, max);
2489 default:
2490 return NULL;
2491 }
2492 }
2493 return NULL;
2494 }
2495
2496 /* checkRealOverflow if we have enabled real value checking then
2497 generate an overflow check appropriate to the tree code being used. */
2498
2499 static void
2500 m2expr_checkRealOverflow (location_t location, enum tree_code code,
2501 tree result)
2502 {
2503 if (M2Options_GetFloatValueCheck ())
2504 {
2505 tree condition = m2expr_BuildEqualTo (
2506 location, m2builtins_BuiltInIsfinite (location, result),
2507 m2expr_GetIntegerZero (location));
2508 switch (code)
2509 {
2510 case PLUS_EXPR:
2511 m2type_AddStatement (location,
2512 M2Range_BuildIfCallRealHandlerLoc (
2513 location, condition,
2514 get_current_function_name (),
2515 "floating point + has caused an overflow"));
2516 break;
2517 case MINUS_EXPR:
2518 m2type_AddStatement (location,
2519 M2Range_BuildIfCallRealHandlerLoc (
2520 location, condition,
2521 get_current_function_name (),
2522 "floating point - has caused an overflow"));
2523 break;
2524 case RDIV_EXPR:
2525 case FLOOR_DIV_EXPR:
2526 case CEIL_DIV_EXPR:
2527 case TRUNC_DIV_EXPR:
2528 m2type_AddStatement (location,
2529 M2Range_BuildIfCallRealHandlerLoc (
2530 location, condition,
2531 get_current_function_name (),
2532 "floating point / has caused an overflow"));
2533 break;
2534 case MULT_EXPR:
2535 m2type_AddStatement (location,
2536 M2Range_BuildIfCallRealHandlerLoc (
2537 location, condition,
2538 get_current_function_name (),
2539 "floating point * has caused an overflow"));
2540 break;
2541 case NEGATE_EXPR:
2542 m2type_AddStatement (
2543 location, M2Range_BuildIfCallRealHandlerLoc (
2544 location, condition,
2545 get_current_function_name (),
2546 "floating point unary - has caused an overflow"));
2547 default:
2548 break;
2549 }
2550 }
2551 }
2552
2553 /* build_binary_op, a wrapper for the lower level build_binary_op
2554 above. */
2555
2556 tree
2557 m2expr_build_binary_op_check (location_t location, enum tree_code code,
2558 tree op1, tree op2, bool needconvert, tree lowest,
2559 tree min, tree max)
2560 {
2561 tree type1, type2, result;
2562 tree check = NULL;
2563
2564 op1 = m2expr_FoldAndStrip (op1);
2565 op2 = m2expr_FoldAndStrip (op2);
2566
2567 type1 = m2tree_skip_type_decl (TREE_TYPE (op1));
2568 type2 = m2tree_skip_type_decl (TREE_TYPE (op2));
2569
2570 m2assert_AssertLocation (location);
2571
2572 if (code == PLUS_EXPR)
2573 {
2574 if (POINTER_TYPE_P (type1))
2575 {
2576 op2 = fold_convert_loc (location, sizetype, unshare_expr (op2));
2577 return fold_build2_loc (location, POINTER_PLUS_EXPR, TREE_TYPE (op1),
2578 op1, op2);
2579 }
2580 else if (POINTER_TYPE_P (type2))
2581 {
2582 op1 = fold_convert_loc (location, sizetype, unshare_expr (op1));
2583 return fold_build2_loc (location, POINTER_PLUS_EXPR, TREE_TYPE (op2),
2584 op2, op1);
2585 }
2586 }
2587 if (code == MINUS_EXPR)
2588 {
2589 if (POINTER_TYPE_P (type1))
2590 {
2591 op2 = fold_convert_loc (location, sizetype, unshare_expr (op2));
2592 op2 = fold_build1_loc (location, NEGATE_EXPR, sizetype, op2);
2593 return fold_build2_loc (location, POINTER_PLUS_EXPR, TREE_TYPE (op1),
2594 op1, op2);
2595 }
2596 else if (POINTER_TYPE_P (type2))
2597 {
2598 op2 = fold_convert_loc (location, sizetype, unshare_expr (op2));
2599 op2 = fold_build1_loc (location, NEGATE_EXPR, sizetype, op2);
2600 op1 = fold_convert_loc (location, sizetype, unshare_expr (op1));
2601 return fold_build2_loc (location, POINTER_PLUS_EXPR, TREE_TYPE (op2),
2602 op2, op1);
2603 }
2604 }
2605
2606 if ((code != LSHIFT_EXPR) && (code != RSHIFT_EXPR) && (code != LROTATE_EXPR)
2607 && (code == RROTATE_EXPR))
2608 if (type1 != type2)
2609 error_at (location, "not expecting different types to binary operator");
2610
2611 if ((TREE_CODE (type1) != REAL_TYPE) && (min != NULL))
2612 check = m2expr_checkWholeOverflow (location, code, op1, op2, lowest, min, max);
2613
2614 result = build_binary_op (location, code, op1, op2, needconvert);
2615 if (check != NULL)
2616 result = build2 (COMPOUND_EXPR, TREE_TYPE (result), check, result);
2617
2618 if (SCALAR_FLOAT_TYPE_P (type1))
2619 m2expr_checkRealOverflow (location, code, result);
2620 return result;
2621 }
2622
2623 /* build_binary_op, a wrapper for the lower level build_binary_op
2624 above. */
2625
2626 tree
2627 m2expr_build_binary_op (location_t location, enum tree_code code, tree op1,
2628 tree op2, int convert)
2629 {
2630 return m2expr_build_binary_op_check (location, code, op1, op2, convert, NULL,
2631 NULL, NULL);
2632 }
2633
2634 /* BuildAddAddress return an expression op1+op2 where op1 is a
2635 pointer type and op2 is not a pointer type. */
2636
2637 tree
2638 m2expr_BuildAddAddress (location_t location, tree op1, tree op2)
2639 {
2640 tree type1, type2;
2641
2642 op1 = m2expr_FoldAndStrip (op1);
2643 op2 = m2expr_FoldAndStrip (op2);
2644
2645 type1 = m2tree_skip_type_decl (TREE_TYPE (op1));
2646 type2 = m2tree_skip_type_decl (TREE_TYPE (op2));
2647
2648 m2assert_AssertLocation (location);
2649 ASSERT_CONDITION (POINTER_TYPE_P (type1));
2650 ASSERT_CONDITION (!POINTER_TYPE_P (type2));
2651
2652 op2 = fold_convert_loc (location, sizetype, unshare_expr (op2));
2653 return fold_build2_loc (location, POINTER_PLUS_EXPR, TREE_TYPE (op1),
2654 m2expr_FoldAndStrip (op1),
2655 m2expr_FoldAndStrip (op2));
2656 }
2657
2658 /* BuildNegateCheck builds a negate tree. */
2659
2660 tree
2661 m2expr_BuildNegateCheck (location_t location, tree arg, tree lowest, tree min,
2662 tree max)
2663 {
2664 tree t;
2665
2666 m2assert_AssertLocation (location);
2667
2668 arg = m2expr_FoldAndStrip (arg);
2669 arg = CheckAddressToCardinal (location, arg);
2670
2671 t = m2expr_build_unary_op_check (location, NEGATE_EXPR, arg, lowest, min,
2672 max);
2673 return m2expr_FoldAndStrip (t);
2674 }
2675
2676 /* BuildNegate build a negate expression and returns the tree. */
2677
2678 tree
2679 m2expr_BuildNegate (location_t location, tree op1, bool needconvert)
2680 {
2681 m2assert_AssertLocation (location);
2682 op1 = m2expr_FoldAndStrip (op1);
2683 op1 = CheckAddressToCardinal (location, op1);
2684
2685 return m2expr_build_unary_op (location, NEGATE_EXPR, op1, needconvert);
2686 }
2687
2688 /* BuildSetNegate build a set negate expression and returns the tree. */
2689
2690 tree
2691 m2expr_BuildSetNegate (location_t location, tree op1, bool needconvert)
2692 {
2693 m2assert_AssertLocation (location);
2694
2695 return m2expr_build_binary_op (
2696 location, BIT_XOR_EXPR,
2697 m2convert_BuildConvert (location, m2type_GetWordType (),
2698 m2expr_FoldAndStrip (op1), false),
2699 set_full_complement, needconvert);
2700 }
2701
2702 /* BuildMult build a multiplication tree. */
2703
2704 tree
2705 m2expr_BuildMult (location_t location, tree op1, tree op2, bool needconvert)
2706 {
2707 op1 = m2expr_FoldAndStrip (op1);
2708 op2 = m2expr_FoldAndStrip (op2);
2709
2710 m2assert_AssertLocation (location);
2711
2712 op1 = CheckAddressToCardinal (location, op1);
2713 op2 = CheckAddressToCardinal (location, op2);
2714
2715 return m2expr_build_binary_op (location, MULT_EXPR, op1, op2, needconvert);
2716 }
2717
2718 /* BuildMultCheck builds a multiplication tree. */
2719
2720 tree
2721 m2expr_BuildMultCheck (location_t location, tree op1, tree op2, tree lowest,
2722 tree min, tree max)
2723 {
2724 tree t;
2725
2726 m2assert_AssertLocation (location);
2727
2728 op1 = m2expr_FoldAndStrip (op1);
2729 op2 = m2expr_FoldAndStrip (op2);
2730
2731 op1 = CheckAddressToCardinal (location, op1);
2732 op2 = CheckAddressToCardinal (location, op2);
2733
2734 t = m2expr_build_binary_op_check (location, MULT_EXPR, op1, op2, false,
2735 lowest, min, max);
2736 return m2expr_FoldAndStrip (t);
2737 }
2738
2739 /* testLimits return the number of bits required to represent:
2740 min..max if it matches the, type. Otherwise NULL_TREE is returned. */
2741
2742 static tree
2743 testLimits (location_t location, tree type, tree min, tree max)
2744 {
2745 m2assert_AssertLocation (location);
2746
2747 if ((m2expr_CompareTrees (TYPE_MAX_VALUE (type), max) == 0)
2748 && (m2expr_CompareTrees (TYPE_MIN_VALUE (type), min) == 0))
2749 return m2expr_BuildMult (location, m2expr_GetSizeOf (location, type),
2750 m2decl_BuildIntegerConstant (BITS_PER_UNIT),
2751 false);
2752 return NULL_TREE;
2753 }
2754
2755 /* noBitsRequired return the number of bits required to contain, values. */
2756
2757 static tree
2758 noBitsRequired (tree values)
2759 {
2760 int bits = tree_floor_log2 (values);
2761
2762 return m2decl_BuildIntegerConstant (bits + 1);
2763 }
2764
2765 /* getMax return the result of max (a, b). */
2766
2767 static tree
2768 getMax (tree a, tree b)
2769 {
2770 if (m2expr_CompareTrees (a, b) > 0)
2771 return a;
2772 else
2773 return b;
2774 }
2775
2776 /* calcNbits return the smallest number of bits required to
2777 represent: min..max. */
2778
2779 tree
2780 m2expr_calcNbits (location_t location, tree min, tree max)
2781 {
2782 int negative = false;
2783 tree t = testLimits (location, m2type_GetIntegerType (), min, max);
2784
2785 m2assert_AssertLocation (location);
2786
2787 if (t == NULL)
2788 t = testLimits (location, m2type_GetCardinalType (), min, max);
2789
2790 if (t == NULL)
2791 {
2792 if (m2expr_CompareTrees (min, m2expr_GetIntegerZero (location)) < 0)
2793 {
2794 min = m2expr_BuildAdd (location, min,
2795 m2expr_GetIntegerOne (location), false);
2796 min = fold (m2expr_BuildNegate (location, min, false));
2797 negative = true;
2798 }
2799 if (m2expr_CompareTrees (max, m2expr_GetIntegerZero (location)) < 0)
2800 {
2801 max = fold (m2expr_BuildNegate (location, max, false));
2802 negative = true;
2803 }
2804 t = noBitsRequired (getMax (min, max));
2805 if (negative)
2806 t = m2expr_BuildAdd (location, t, m2expr_GetIntegerOne (location),
2807 false);
2808 }
2809 return t;
2810 }
2811
2812 /* BuildTBitSize return the minimum number of bits to represent, type. */
2813
2814 tree
2815 m2expr_BuildTBitSize (location_t location, tree type)
2816 {
2817 enum tree_code code = TREE_CODE (type);
2818 tree min;
2819 tree max;
2820 m2assert_AssertLocation (location);
2821
2822 switch (code)
2823 {
2824
2825 case TYPE_DECL:
2826 return m2expr_BuildTBitSize (location, TREE_TYPE (type));
2827 case INTEGER_TYPE:
2828 case ENUMERAL_TYPE:
2829 max = m2convert_BuildConvert (location, m2type_GetIntegerType (),
2830 TYPE_MAX_VALUE (type), false);
2831 min = m2convert_BuildConvert (location, m2type_GetIntegerType (),
2832 TYPE_MIN_VALUE (type), false);
2833 return m2expr_calcNbits (location, min, max);
2834 case BOOLEAN_TYPE:
2835 return m2expr_GetIntegerOne (location);
2836 default:
2837 return m2expr_BuildMult (location, m2expr_GetSizeOf (location, type),
2838 m2decl_BuildIntegerConstant (BITS_PER_UNIT),
2839 false);
2840 }
2841 }
2842
2843 /* BuildSize build a SIZE function expression and returns the tree. */
2844
2845 tree
2846 m2expr_BuildSize (location_t location, tree op1,
2847 bool needconvert ATTRIBUTE_UNUSED)
2848 {
2849 m2assert_AssertLocation (location);
2850 return m2expr_GetSizeOf (location, op1);
2851 }
2852
2853 /* BuildAddr return an expression which calculates the address of op1
2854 and returns the tree. If use_generic is true then create a generic
2855 pointer type. */
2856
2857 tree
2858 m2expr_BuildAddr (location_t location, tree op1, bool use_generic)
2859 {
2860 tree type = m2tree_skip_type_decl (TREE_TYPE (op1));
2861 tree ptrType = build_pointer_type (type);
2862 tree result;
2863
2864 m2assert_AssertLocation (location);
2865
2866 if (!gm2_mark_addressable (op1))
2867 error_at (location, "cannot take the address of this expression");
2868
2869 if (use_generic)
2870 result = build1 (ADDR_EXPR, m2type_GetPointerType (), op1);
2871 else
2872 result = build1 (ADDR_EXPR, ptrType, op1);
2873 protected_set_expr_location (result, location);
2874 return result;
2875 }
2876
2877 /* BuildOffset1 build and return an expression containing the number
2878 of bytes the field is offset from the start of the record structure.
2879 This function is the same as the above, except that it derives the
2880 record from the field and then calls BuildOffset. */
2881
2882 tree
2883 m2expr_BuildOffset1 (location_t location, tree field,
2884 bool needconvert ATTRIBUTE_UNUSED)
2885 {
2886 m2assert_AssertLocation (location);
2887 return m2expr_BuildOffset (location, DECL_CONTEXT (field), field,
2888 needconvert);
2889 }
2890
2891 /* determinePenultimateField return the field associated with the
2892 DECL_CONTEXT (field) within a record or varient. The record, is a
2893 record/varient but it maybe an outer nested record to the field that
2894 we are searching. Ie:
2895
2896 record = RECORD x: CARDINAL ; y: RECORD field: CARDINAL ; END END ;
2897
2898 determinePenultimateField (record, field) returns, y. We are
2899 assurred that the chain of records leading to field will be unique as
2900 they are built on the fly to implement varient records. */
2901
2902 static tree
2903 determinePenultimateField (tree record, tree field)
2904 {
2905 tree fieldlist = TYPE_FIELDS (record);
2906 tree x, r;
2907
2908 for (x = fieldlist; x; x = TREE_CHAIN (x))
2909 {
2910 if (DECL_CONTEXT (field) == TREE_TYPE (x))
2911 return x;
2912 switch (TREE_CODE (TREE_TYPE (x)))
2913 {
2914 case RECORD_TYPE:
2915 case UNION_TYPE:
2916 r = determinePenultimateField (TREE_TYPE (x), field);
2917 if (r != NULL)
2918 return r;
2919 break;
2920 default:
2921 break;
2922 }
2923 }
2924 return NULL_TREE;
2925 }
2926
2927 /* BuildOffset builds an expression containing the number of bytes
2928 the field is offset from the start of the record structure. The
2929 expression is returned. */
2930
2931 tree
2932 m2expr_BuildOffset (location_t location, tree record, tree field,
2933 bool needconvert ATTRIBUTE_UNUSED)
2934 {
2935 m2assert_AssertLocation (location);
2936
2937 if (DECL_CONTEXT (field) == record)
2938 return m2convert_BuildConvert (
2939 location, m2type_GetIntegerType (),
2940 m2expr_BuildAdd (
2941 location, DECL_FIELD_OFFSET (field),
2942 m2expr_BuildDivTrunc (location, DECL_FIELD_BIT_OFFSET (field),
2943 m2decl_BuildIntegerConstant (BITS_PER_UNIT),
2944 false),
2945 false),
2946 false);
2947 else
2948 {
2949 tree r1 = DECL_CONTEXT (field);
2950 tree r2 = determinePenultimateField (record, field);
2951 return m2convert_BuildConvert (
2952 location, m2type_GetIntegerType (),
2953 m2expr_BuildAdd (
2954 location, m2expr_BuildOffset (location, r1, field, needconvert),
2955 m2expr_BuildOffset (location, record, r2, needconvert), false),
2956 false);
2957 }
2958 }
2959
2960 /* BuildLogicalOrAddress build a logical or expressions and return the tree. */
2961
2962 tree
2963 m2expr_BuildLogicalOrAddress (location_t location, tree op1, tree op2,
2964 bool needconvert)
2965 {
2966 m2assert_AssertLocation (location);
2967 return m2expr_build_binary_op (location, BIT_IOR_EXPR, op1, op2,
2968 needconvert);
2969 }
2970
2971 /* BuildLogicalOr build a logical or expressions and return the tree. */
2972
2973 tree
2974 m2expr_BuildLogicalOr (location_t location, tree op1, tree op2,
2975 bool needconvert)
2976 {
2977 m2assert_AssertLocation (location);
2978 return m2expr_build_binary_op (
2979 location, BIT_IOR_EXPR,
2980 m2convert_BuildConvert (location, m2type_GetWordType (), op1, false),
2981 m2convert_BuildConvert (location, m2type_GetWordType (), op2, false),
2982 needconvert);
2983 }
2984
2985 /* BuildLogicalAnd build a logical and expression and return the tree. */
2986
2987 tree
2988 m2expr_BuildLogicalAnd (location_t location, tree op1, tree op2,
2989 bool needconvert)
2990 {
2991 m2assert_AssertLocation (location);
2992 return m2expr_build_binary_op (
2993 location, BIT_AND_EXPR,
2994 m2convert_BuildConvert (location, m2type_GetWordType (), op1, false),
2995 m2convert_BuildConvert (location, m2type_GetWordType (), op2, false),
2996 needconvert);
2997 }
2998
2999 /* BuildSymmetricalDifference build a logical xor expression and return the
3000 * tree. */
3001
3002 tree
3003 m2expr_BuildSymmetricDifference (location_t location, tree op1, tree op2,
3004 bool needconvert)
3005 {
3006 m2assert_AssertLocation (location);
3007 return m2expr_build_binary_op (
3008 location, BIT_XOR_EXPR,
3009 m2convert_BuildConvert (location, m2type_GetWordType (), op1, false),
3010 m2convert_BuildConvert (location, m2type_GetWordType (), op2, false),
3011 needconvert);
3012 }
3013
3014 /* BuildLogicalDifference build a logical difference expression and
3015 return the tree. (op1 and (not op2)). */
3016
3017 tree
3018 m2expr_BuildLogicalDifference (location_t location, tree op1, tree op2,
3019 bool needconvert)
3020 {
3021 m2assert_AssertLocation (location);
3022 return m2expr_build_binary_op (
3023 location, BIT_AND_EXPR,
3024 m2convert_BuildConvert (location, m2type_GetWordType (), op1, false),
3025 m2expr_BuildSetNegate (location, op2, needconvert), needconvert);
3026 }
3027
3028 /* base_type returns the base type of an ordinal subrange, or the
3029 type itself if it is not a subrange. */
3030
3031 static tree
3032 base_type (tree type)
3033 {
3034 if (type == error_mark_node)
3035 return error_mark_node;
3036
3037 /* Check for ordinal subranges. */
3038 if (m2tree_IsOrdinal (type) && TREE_TYPE (type))
3039 type = TREE_TYPE (type);
3040 return TYPE_MAIN_VARIANT (type);
3041 }
3042
3043 /* boolean_enum_to_unsigned convert a BOOLEAN_TYPE, t, or
3044 ENUMERAL_TYPE to an unsigned type. */
3045
3046 static tree
3047 boolean_enum_to_unsigned (location_t location, tree t)
3048 {
3049 tree type = TREE_TYPE (t);
3050
3051 if (TREE_CODE (base_type (type)) == BOOLEAN_TYPE)
3052 return m2convert_BuildConvert (location, unsigned_type_node, t, false);
3053 else if (TREE_CODE (base_type (type)) == ENUMERAL_TYPE)
3054 return m2convert_BuildConvert (location, unsigned_type_node, t, false);
3055 else
3056 return t;
3057 }
3058
3059 /* check_for_comparison check to see if, op, is of type, badType. If
3060 so then it returns op after it has been cast to, goodType. op will
3061 be an array so we take the address and cast the contents. */
3062
3063 static tree
3064 check_for_comparison (location_t location, tree op, tree badType,
3065 tree goodType)
3066 {
3067 m2assert_AssertLocation (location);
3068 if (m2tree_skip_type_decl (TREE_TYPE (op)) == badType)
3069 /* Cannot compare array contents in m2expr_build_binary_op. */
3070 return m2expr_BuildIndirect (
3071 location, m2expr_BuildAddr (location, op, false), goodType);
3072 return op;
3073 }
3074
3075 /* convert_for_comparison return a tree which can be used as an
3076 argument during a comparison. */
3077
3078 static tree
3079 convert_for_comparison (location_t location, tree op)
3080 {
3081 m2assert_AssertLocation (location);
3082 op = boolean_enum_to_unsigned (location, op);
3083
3084 op = check_for_comparison (location, op, m2type_GetISOWordType (),
3085 m2type_GetWordType ());
3086 op = check_for_comparison (location, op, m2type_GetM2Word16 (),
3087 m2type_GetM2Cardinal16 ());
3088 op = check_for_comparison (location, op, m2type_GetM2Word32 (),
3089 m2type_GetM2Cardinal32 ());
3090 op = check_for_comparison (location, op, m2type_GetM2Word64 (),
3091 m2type_GetM2Cardinal64 ());
3092
3093 return op;
3094 }
3095
3096 /* BuildLessThan return a tree which computes <. */
3097
3098 tree
3099 m2expr_BuildLessThan (location_t location, tree op1, tree op2)
3100 {
3101 m2assert_AssertLocation (location);
3102 return m2expr_build_binary_op (
3103 location, LT_EXPR, boolean_enum_to_unsigned (location, op1),
3104 boolean_enum_to_unsigned (location, op2), true);
3105 }
3106
3107 /* BuildGreaterThan return a tree which computes >. */
3108
3109 tree
3110 m2expr_BuildGreaterThan (location_t location, tree op1, tree op2)
3111 {
3112 m2assert_AssertLocation (location);
3113 return m2expr_build_binary_op (
3114 location, GT_EXPR, boolean_enum_to_unsigned (location, op1),
3115 boolean_enum_to_unsigned (location, op2), true);
3116 }
3117
3118 /* BuildLessThanOrEqual return a tree which computes <. */
3119
3120 tree
3121 m2expr_BuildLessThanOrEqual (location_t location, tree op1, tree op2)
3122 {
3123 m2assert_AssertLocation (location);
3124 return m2expr_build_binary_op (
3125 location, LE_EXPR, boolean_enum_to_unsigned (location, op1),
3126 boolean_enum_to_unsigned (location, op2), true);
3127 }
3128
3129 /* BuildGreaterThanOrEqual return a tree which computes >=. */
3130
3131 tree
3132 m2expr_BuildGreaterThanOrEqual (location_t location, tree op1, tree op2)
3133 {
3134 m2assert_AssertLocation (location);
3135 return m2expr_build_binary_op (
3136 location, GE_EXPR, boolean_enum_to_unsigned (location, op1),
3137 boolean_enum_to_unsigned (location, op2), true);
3138 }
3139
3140 /* BuildEqualTo return a tree which computes =. */
3141
3142 tree
3143 m2expr_BuildEqualTo (location_t location, tree op1, tree op2)
3144 {
3145 m2assert_AssertLocation (location);
3146 return m2expr_build_binary_op (location, EQ_EXPR,
3147 convert_for_comparison (location, op1),
3148 convert_for_comparison (location, op2), true);
3149 }
3150
3151 /* BuildEqualNotTo return a tree which computes #. */
3152
3153 tree
3154 m2expr_BuildNotEqualTo (location_t location, tree op1, tree op2)
3155 {
3156 m2assert_AssertLocation (location);
3157 return m2expr_build_binary_op (location, NE_EXPR,
3158 convert_for_comparison (location, op1),
3159 convert_for_comparison (location, op2), true);
3160 }
3161
3162 /* BuildIsSuperset return a tree which computes: op1 & op2 == op2. */
3163
3164 tree
3165 m2expr_BuildIsSuperset (location_t location, tree op1, tree op2)
3166 {
3167 m2assert_AssertLocation (location);
3168 return m2expr_BuildEqualTo (
3169 location, op2, m2expr_BuildLogicalAnd (location, op1, op2, false));
3170 }
3171
3172 /* BuildIsNotSuperset return a tree which computes: op1 & op2 != op2. */
3173
3174 tree
3175 m2expr_BuildIsNotSuperset (location_t location, tree op1, tree op2)
3176 {
3177 m2assert_AssertLocation (location);
3178 return m2expr_BuildNotEqualTo (
3179 location, op2, m2expr_BuildLogicalAnd (location, op1, op2, false));
3180 }
3181
3182 /* BuildIsSubset return a tree which computes: op1 & op2 == op1. */
3183
3184 tree
3185 m2expr_BuildIsSubset (location_t location, tree op1, tree op2)
3186 {
3187 m2assert_AssertLocation (location);
3188 return m2expr_BuildEqualTo (
3189 location, op1, m2expr_BuildLogicalAnd (location, op1, op2, false));
3190 }
3191
3192 /* BuildIsNotSubset return a tree which computes: op1 & op2 != op1. */
3193
3194 tree
3195 m2expr_BuildIsNotSubset (location_t location, tree op1, tree op2)
3196 {
3197 m2assert_AssertLocation (location);
3198 return m2expr_BuildNotEqualTo (
3199 location, op1, m2expr_BuildLogicalAnd (location, op1, op2, false));
3200 }
3201
3202 /* BuildIfConstInVar generates: if constel in varset then goto label. */
3203
3204 void
3205 m2expr_BuildIfConstInVar (location_t location, tree type, tree varset,
3206 tree constel, bool is_lvalue, int fieldno,
3207 char *label)
3208 {
3209 tree size = m2expr_GetSizeOf (location, type);
3210 m2assert_AssertLocation (location);
3211
3212 ASSERT_BOOL (is_lvalue);
3213 if (m2expr_CompareTrees (
3214 size, m2decl_BuildIntegerConstant (SET_WORD_SIZE / BITS_PER_UNIT))
3215 <= 0)
3216 /* Small set size <= TSIZE(WORD). */
3217 m2treelib_do_jump_if_bit (
3218 location, NE_EXPR,
3219 m2treelib_get_rvalue (location, varset, type, is_lvalue), constel,
3220 label);
3221 else
3222 {
3223 tree fieldlist = TYPE_FIELDS (type);
3224 tree field;
3225
3226 for (field = fieldlist; (field != NULL) && (fieldno > 0);
3227 field = TREE_CHAIN (field))
3228 fieldno--;
3229
3230 m2treelib_do_jump_if_bit (
3231 location, NE_EXPR,
3232 m2treelib_get_set_field_rhs (location, varset, field), constel,
3233 label);
3234 }
3235 }
3236
3237 /* BuildIfConstInVar generates: if not (constel in varset) then goto label. */
3238
3239 void
3240 m2expr_BuildIfNotConstInVar (location_t location, tree type, tree varset,
3241 tree constel, bool is_lvalue, int fieldno,
3242 char *label)
3243 {
3244 tree size = m2expr_GetSizeOf (location, type);
3245
3246 m2assert_AssertLocation (location);
3247
3248 ASSERT_BOOL (is_lvalue);
3249 if (m2expr_CompareTrees (
3250 size, m2decl_BuildIntegerConstant (SET_WORD_SIZE / BITS_PER_UNIT))
3251 <= 0)
3252 /* Small set size <= TSIZE(WORD). */
3253 m2treelib_do_jump_if_bit (
3254 location, EQ_EXPR,
3255 m2treelib_get_rvalue (location, varset, type, is_lvalue), constel,
3256 label);
3257 else
3258 {
3259 tree fieldlist = TYPE_FIELDS (type);
3260 tree field;
3261
3262 for (field = fieldlist; (field != NULL) && (fieldno > 0);
3263 field = TREE_CHAIN (field))
3264 fieldno--;
3265
3266 m2treelib_do_jump_if_bit (
3267 location, EQ_EXPR,
3268 m2treelib_get_set_field_rhs (location, varset, field), constel,
3269 label);
3270 }
3271 }
3272
3273 /* BuildIfVarInVar generates: if varel in varset then goto label. */
3274
3275 void
3276 m2expr_BuildIfVarInVar (location_t location, tree type, tree varset,
3277 tree varel, bool is_lvalue, tree low,
3278 tree high ATTRIBUTE_UNUSED, char *label)
3279 {
3280 tree size = m2expr_GetSizeOf (location, type);
3281 /* Calculate the index from the first bit, ie bit 0 represents low value. */
3282 tree index = m2expr_BuildSub (
3283 location, m2convert_BuildConvert (location, m2type_GetIntegerType (),
3284 varel, false),
3285 m2convert_BuildConvert (location, m2type_GetIntegerType (), low, false),
3286 false);
3287
3288 m2assert_AssertLocation (location);
3289
3290 if (m2expr_CompareTrees (
3291 size, m2decl_BuildIntegerConstant (SET_WORD_SIZE / BITS_PER_UNIT))
3292 <= 0)
3293 /* Small set size <= TSIZE(WORD). */
3294 m2treelib_do_jump_if_bit (
3295 location, NE_EXPR,
3296 m2treelib_get_rvalue (location, varset, type, is_lvalue), index,
3297 label);
3298 else
3299 {
3300 tree p1 = m2treelib_get_set_address (location, varset, is_lvalue);
3301 /* Which word do we need to fetch? */
3302 tree word_index = m2expr_FoldAndStrip (m2expr_BuildDivTrunc (
3303 location, index, m2decl_BuildIntegerConstant (SET_WORD_SIZE),
3304 false));
3305 /* Calculate the bit in this word. */
3306 tree offset_into_word = m2expr_FoldAndStrip (m2expr_BuildModTrunc (
3307 location, index, m2decl_BuildIntegerConstant (SET_WORD_SIZE),
3308 false));
3309 tree p2 = m2expr_FoldAndStrip (m2expr_BuildMult (
3310 location, word_index,
3311 m2decl_BuildIntegerConstant (SET_WORD_SIZE / BITS_PER_UNIT), false));
3312
3313 /* Calculate the address of the word we are interested in. */
3314 p1 = m2expr_BuildAddAddress (location,
3315 m2convert_convertToPtr (location, p1), p2);
3316
3317 /* Fetch the word, extract the bit and test for != 0. */
3318 m2treelib_do_jump_if_bit (
3319 location, NE_EXPR,
3320 m2expr_BuildIndirect (location, p1, m2type_GetBitsetType ()),
3321 offset_into_word, label);
3322 }
3323 }
3324
3325 /* BuildIfNotVarInVar generates: if not (varel in varset) then goto label. */
3326
3327 void
3328 m2expr_BuildIfNotVarInVar (location_t location, tree type, tree varset,
3329 tree varel, bool is_lvalue, tree low,
3330 tree high ATTRIBUTE_UNUSED, char *label)
3331 {
3332 tree size = m2expr_GetSizeOf (location, type);
3333 /* Calculate the index from the first bit, ie bit 0 represents low value. */
3334 tree index = m2expr_BuildSub (
3335 location, m2convert_BuildConvert (location, m2type_GetIntegerType (),
3336 m2expr_FoldAndStrip (varel), false),
3337 m2convert_BuildConvert (location, m2type_GetIntegerType (),
3338 m2expr_FoldAndStrip (low), false),
3339 false);
3340
3341 index = m2expr_FoldAndStrip (index);
3342 m2assert_AssertLocation (location);
3343
3344 if (m2expr_CompareTrees (
3345 size, m2decl_BuildIntegerConstant (SET_WORD_SIZE / BITS_PER_UNIT))
3346 <= 0)
3347 /* Small set size <= TSIZE(WORD). */
3348 m2treelib_do_jump_if_bit (
3349 location, EQ_EXPR,
3350 m2treelib_get_rvalue (location, varset, type, is_lvalue), index,
3351 label);
3352 else
3353 {
3354 tree p1 = m2treelib_get_set_address (location, varset, is_lvalue);
3355 /* Calculate the index from the first bit. */
3356
3357 /* Which word do we need to fetch? */
3358 tree word_index = m2expr_FoldAndStrip (m2expr_BuildDivTrunc (
3359 location, index, m2decl_BuildIntegerConstant (SET_WORD_SIZE),
3360 false));
3361 /* Calculate the bit in this word. */
3362 tree offset_into_word = m2expr_FoldAndStrip (m2expr_BuildModTrunc (
3363 location, index, m2decl_BuildIntegerConstant (SET_WORD_SIZE),
3364 false));
3365 tree p2 = m2expr_FoldAndStrip (m2expr_BuildMult (
3366 location, word_index,
3367 m2decl_BuildIntegerConstant (SET_WORD_SIZE / BITS_PER_UNIT), false));
3368
3369 /* Calculate the address of the word we are interested in. */
3370 p1 = m2expr_BuildAddAddress (location, p1, p2);
3371
3372 /* Fetch the word, extract the bit and test for == 0. */
3373 m2treelib_do_jump_if_bit (
3374 location, EQ_EXPR,
3375 m2expr_BuildIndirect (location, p1, m2type_GetBitsetType ()),
3376 offset_into_word, label);
3377 }
3378 }
3379
3380 /* BuildForeachWordInSetDoIfExpr foreach word in set, type, compute
3381 the expression, expr, and if true goto label. */
3382
3383 void
3384 m2expr_BuildForeachWordInSetDoIfExpr (location_t location, tree type, tree op1,
3385 tree op2, bool is_op1lvalue,
3386 bool is_op2lvalue, bool is_op1const,
3387 bool is_op2const,
3388 tree (*expr) (location_t, tree, tree),
3389 char *label)
3390 {
3391 tree p1 = m2treelib_get_set_address_if_var (location, op1, is_op1lvalue,
3392 is_op1const);
3393 tree p2 = m2treelib_get_set_address_if_var (location, op2, is_op2lvalue,
3394 is_op2const);
3395 unsigned int fieldNo = 0;
3396 tree field1 = m2treelib_get_field_no (type, op1, is_op1const, fieldNo);
3397 tree field2 = m2treelib_get_field_no (type, op2, is_op2const, fieldNo);
3398
3399 m2assert_AssertLocation (location);
3400 ASSERT_CONDITION (TREE_CODE (TREE_TYPE (op1)) == RECORD_TYPE);
3401 ASSERT_CONDITION (TREE_CODE (TREE_TYPE (op2)) == RECORD_TYPE);
3402
3403 while (field1 != NULL && field2 != NULL)
3404 {
3405 m2statement_DoJump (
3406 location,
3407 (*expr) (location,
3408 m2treelib_get_set_value (location, p1, field1, is_op1const,
3409 is_op1lvalue, op1, fieldNo),
3410 m2treelib_get_set_value (location, p2, field2, is_op2const,
3411 is_op2lvalue, op2, fieldNo)),
3412 NULL, label);
3413 fieldNo++;
3414 field1 = m2treelib_get_field_no (type, op1, is_op1const, fieldNo);
3415 field2 = m2treelib_get_field_no (type, op2, is_op2const, fieldNo);
3416 }
3417 }
3418
3419 /* BuildIfInRangeGoto returns a tree containing if var is in the
3420 range low..high then goto label. */
3421
3422 void
3423 m2expr_BuildIfInRangeGoto (location_t location, tree var, tree low, tree high,
3424 char *label)
3425 {
3426 m2assert_AssertLocation (location);
3427
3428 if (m2expr_CompareTrees (low, high) == 0)
3429 m2statement_DoJump (location, m2expr_BuildEqualTo (location, var, low),
3430 NULL, label);
3431 else
3432 m2statement_DoJump (
3433 location,
3434 m2expr_build_binary_op (
3435 location, TRUTH_ANDIF_EXPR,
3436 m2expr_BuildGreaterThanOrEqual (location, var, low),
3437 m2expr_BuildLessThanOrEqual (location, var, high), false),
3438 NULL, label);
3439 }
3440
3441 /* BuildIfNotInRangeGoto returns a tree containing if var is not in
3442 the range low..high then goto label. */
3443
3444 void
3445 m2expr_BuildIfNotInRangeGoto (location_t location, tree var, tree low,
3446 tree high, char *label)
3447 {
3448 m2assert_AssertLocation (location);
3449
3450 if (m2expr_CompareTrees (low, high) == 0)
3451 m2statement_DoJump (location, m2expr_BuildNotEqualTo (location, var, low),
3452 NULL, label);
3453 else
3454 m2statement_DoJump (
3455 location, m2expr_build_binary_op (
3456 location, TRUTH_ORIF_EXPR,
3457 m2expr_BuildLessThan (location, var, low),
3458 m2expr_BuildGreaterThan (location, var, high), false),
3459 NULL, label);
3460 }
3461
3462 /* BuildArray - returns a tree which accesses array[index] given,
3463 lowIndice. */
3464
3465 tree
3466 m2expr_BuildArray (location_t location, tree type, tree array, tree index,
3467 tree low_indice)
3468 {
3469 tree array_type = m2tree_skip_type_decl (TREE_TYPE (array));
3470 tree index_type = TYPE_DOMAIN (array_type);
3471 type = m2tree_skip_type_decl (type);
3472 // ASSERT_CONDITION (low_indice == TYPE_MIN_VALUE (index_type));
3473
3474 low_indice
3475 = m2convert_BuildConvert (location, index_type, low_indice, false);
3476 return build4_loc (location, ARRAY_REF, type, array, index, low_indice,
3477 NULL_TREE);
3478 }
3479
3480 /* BuildComponentRef - build a component reference tree which
3481 accesses record.field. If field does not belong to record it
3482 calls BuildComponentRef on the penultimate field. */
3483
3484 tree
3485 m2expr_BuildComponentRef (location_t location, tree record, tree field)
3486 {
3487 tree recordType = m2tree_skip_reference_type (
3488 m2tree_skip_type_decl (TREE_TYPE (record)));
3489
3490 if (DECL_CONTEXT (field) == recordType)
3491 return build3 (COMPONENT_REF, TREE_TYPE (field), record, field, NULL_TREE);
3492 else
3493 {
3494 tree f = determinePenultimateField (recordType, field);
3495 return m2expr_BuildComponentRef (
3496 location, m2expr_BuildComponentRef (location, record, f), field);
3497 }
3498 }
3499
3500 /* BuildIndirect - build: (*target) given that the object to be
3501 copied is of, type. */
3502
3503 tree
3504 m2expr_BuildIndirect (location_t location ATTRIBUTE_UNUSED, tree target,
3505 tree type)
3506 {
3507 /* Note that the second argument to build1 is:
3508
3509 TYPE_QUALS is a list of modifiers such as const or volatile to apply
3510 to the pointer type, represented as identifiers.
3511
3512 it also determines the type of arithmetic and size of the object to
3513 be indirectly moved. */
3514
3515 tree t1 = m2tree_skip_type_decl (type);
3516 tree t2 = build_pointer_type (t1);
3517
3518 m2assert_AssertLocation (location);
3519
3520 return build1 (INDIRECT_REF, t1,
3521 m2convert_BuildConvert (location, t2, target, false));
3522 }
3523
3524 /* IsTrue - returns true if, t, is known to be true. */
3525
3526 bool
3527 m2expr_IsTrue (tree t)
3528 {
3529 return (m2expr_FoldAndStrip (t) == m2type_GetBooleanTrue ());
3530 }
3531
3532 /* IsFalse - returns false if, t, is known to be false. */
3533
3534 bool
3535 m2expr_IsFalse (tree t)
3536 {
3537 return (m2expr_FoldAndStrip (t) == m2type_GetBooleanFalse ());
3538 }
3539
3540 /* AreConstantsEqual - maps onto tree.cc (tree_int_cst_equal). It
3541 returns true if the value of e1 is the same as e2. */
3542
3543 bool
3544 m2expr_AreConstantsEqual (tree e1, tree e2)
3545 {
3546 return tree_int_cst_equal (e1, e2) != 0;
3547 }
3548
3549 /* AreRealOrComplexConstantsEqual - returns true if constants, e1 and
3550 e2 are equal according to IEEE rules. This does not perform bit
3551 equivalence for example IEEE states that -0 == 0 and NaN != NaN. */
3552
3553 bool
3554 m2expr_AreRealOrComplexConstantsEqual (tree e1, tree e2)
3555 {
3556 if (TREE_CODE (e1) == COMPLEX_CST)
3557 return (m2expr_AreRealOrComplexConstantsEqual (TREE_REALPART (e1),
3558 TREE_REALPART (e2))
3559 && m2expr_AreRealOrComplexConstantsEqual (TREE_IMAGPART (e1),
3560 TREE_IMAGPART (e2)));
3561 else
3562 return real_compare (EQ_EXPR, &TREE_REAL_CST (e1), &TREE_REAL_CST (e2));
3563 }
3564
3565 /* DetermineSign, returns -1 if e<0 0 if e==0 1 if e>0
3566 an unsigned constant will never return -1. */
3567
3568 int
3569 m2expr_DetermineSign (tree e)
3570 {
3571 return tree_int_cst_sgn (e);
3572 }
3573
3574 /* Similar to build_int_2 () but allows you to specify the type of
3575 the integer constant that you are creating. */
3576
3577 static tree
3578 build_int_2_type (HOST_WIDE_INT low, HOST_WIDE_INT hi, tree type)
3579 {
3580 tree value;
3581 HOST_WIDE_INT ival[3];
3582
3583 ival[0] = low;
3584 ival[1] = hi;
3585 ival[2] = 0;
3586
3587 widest_int wval = widest_int::from_array (ival, 3);
3588 value = wide_int_to_tree (type, wval);
3589
3590 return value;
3591 }
3592
3593 /* BuildCap - builds the Modula-2 function CAP(t) and returns the
3594 result in a gcc Tree. */
3595
3596 tree
3597 m2expr_BuildCap (location_t location, tree t)
3598 {
3599 tree tt;
3600 tree out_of_range, less_than, greater_than, translated;
3601
3602 m2assert_AssertLocation (location);
3603
3604 t = fold (t);
3605 if (t == error_mark_node)
3606 return error_mark_node;
3607
3608 tt = TREE_TYPE (t);
3609
3610 t = fold (convert (m2type_GetM2CharType (), t));
3611
3612 if (TREE_CODE (tt) == INTEGER_TYPE)
3613 {
3614 less_than = fold (m2expr_build_binary_op (
3615 location, LT_EXPR, t,
3616 build_int_2_type ('a', 0, m2type_GetM2CharType ()), 0));
3617 greater_than = fold (m2expr_build_binary_op (
3618 location, GT_EXPR, t,
3619 build_int_2_type ('z', 0, m2type_GetM2CharType ()), 0));
3620 out_of_range = fold (m2expr_build_binary_op (
3621 location, TRUTH_ORIF_EXPR, less_than, greater_than, 0));
3622
3623 translated = fold (convert (
3624 m2type_GetM2CharType (),
3625 m2expr_build_binary_op (
3626 location, MINUS_EXPR, t,
3627 build_int_2_type ('a' - 'A', 0, m2type_GetM2CharType ()), 0)));
3628
3629 return fold_build3 (COND_EXPR, m2type_GetM2CharType (), out_of_range, t,
3630 translated);
3631 }
3632
3633 error_at (location,
3634 "argument to CAP is not a constant or variable of type CHAR");
3635 return error_mark_node;
3636 }
3637
3638 /* BuildDivM2 if iso or pim4 then all modulus results are positive
3639 and the results from the division are rounded to the floor otherwise
3640 use BuildDivTrunc. */
3641
3642 tree
3643 m2expr_BuildDivM2 (location_t location, tree op1, tree op2,
3644 bool needsconvert)
3645 {
3646 op1 = m2expr_FoldAndStrip (op1);
3647 op2 = m2expr_FoldAndStrip (op2);
3648 ASSERT_CONDITION (TREE_TYPE (op1) == TREE_TYPE (op2));
3649 /* If iso or pim4 then build and return ((op2 < 0) ? (op1
3650 divceil op2) : (op1 divfloor op2)) otherwise use divtrunc. */
3651 if (M2Options_GetPIM4 () || M2Options_GetISO ()
3652 || M2Options_GetPositiveModFloor ())
3653 return fold_build3 (
3654 COND_EXPR, TREE_TYPE (op1),
3655 m2expr_BuildLessThan (
3656 location, op2,
3657 m2convert_BuildConvert (location, TREE_TYPE (op2),
3658 m2expr_GetIntegerZero (location), false)),
3659 m2expr_BuildDivCeil (location, op1, op2, needsconvert),
3660 m2expr_BuildDivFloor (location, op1, op2, needsconvert));
3661 else
3662 return m2expr_BuildDivTrunc (location, op1, op2, needsconvert);
3663 }
3664
3665 /* BuildDivM2Check - build and
3666 return ((op2 < 0) ? (op1 divtrunc op2) : (op1 divfloor op2))
3667 when -fiso, -fpim4 or -fpositive-mod-floor-div is present else
3668 return op1 div trunc op2. Use the checking div equivalents. */
3669
3670 tree
3671 m2expr_BuildDivM2Check (location_t location, tree op1, tree op2,
3672 tree lowest, tree min, tree max)
3673 {
3674 op1 = m2expr_FoldAndStrip (op1);
3675 op2 = m2expr_FoldAndStrip (op2);
3676 ASSERT_CONDITION (TREE_TYPE (op1) == TREE_TYPE (op2));
3677 if (M2Options_GetISO ()
3678 || M2Options_GetPIM4 () || M2Options_GetPositiveModFloor ())
3679 return fold_build3 (
3680 COND_EXPR, TREE_TYPE (op1),
3681 m2expr_BuildLessThan (
3682 location, op2,
3683 m2convert_BuildConvert (location, TREE_TYPE (op2),
3684 m2expr_GetIntegerZero (location), false)),
3685 m2expr_BuildDivCeilCheck (location, op1, op2, lowest, min, max),
3686 m2expr_BuildDivFloorCheck (location, op1, op2, lowest, min, max));
3687 else
3688 return m2expr_BuildDivTruncCheck (location, op1, op2, lowest, min, max);
3689 }
3690
3691 static
3692 tree
3693 m2expr_BuildISOModM2Check (location_t location,
3694 tree op1, tree op2, tree lowest, tree min, tree max)
3695 {
3696 tree cond = m2expr_BuildLessThan (location, op2,
3697 m2convert_BuildConvert (location, TREE_TYPE (op2),
3698 m2expr_GetIntegerZero (location), false));
3699
3700 /* Return the result of the modulus. */
3701 return fold_build3 (COND_EXPR, TREE_TYPE (op1), cond,
3702 /* op2 < 0. */
3703 m2expr_BuildModCeilCheck (location, op1, op2, lowest, min, max),
3704 /* op2 >= 0. */
3705 m2expr_BuildModFloorCheck (location, op1, op2, lowest, min, max));
3706 }
3707
3708
3709 /* BuildModM2Check if iso or pim4 then build and return ((op2 < 0) ? (op1
3710 modceil op2) : (op1 modfloor op2)) otherwise use modtrunc.
3711 Use the checking mod equivalents. */
3712
3713 tree
3714 m2expr_BuildModM2Check (location_t location, tree op1, tree op2,
3715 tree lowest, tree min, tree max)
3716 {
3717 op1 = m2expr_FoldAndStrip (op1);
3718 op2 = m2expr_FoldAndStrip (op2);
3719 ASSERT_CONDITION (TREE_TYPE (op1) == TREE_TYPE (op2));
3720 if (M2Options_GetPIM4 () || M2Options_GetISO ()
3721 || M2Options_GetPositiveModFloor ())
3722 return m2expr_BuildISOModM2Check (location, op1, op2, lowest, min, max);
3723 else
3724 return m2expr_BuildModTruncCheck (location, op1, op2, lowest, min, max);
3725 }
3726
3727 /* BuildModM2 if iso or pim4 then build and return ((op2 < 0) ? (op1
3728 modceil op2) : (op1 modfloor op2)) otherwise use modtrunc. */
3729
3730 tree
3731 m2expr_BuildModM2 (location_t location, tree op1, tree op2,
3732 bool needsconvert)
3733 {
3734 op1 = m2expr_FoldAndStrip (op1);
3735 op2 = m2expr_FoldAndStrip (op2);
3736 ASSERT_CONDITION (TREE_TYPE (op1) == TREE_TYPE (op2));
3737 if (M2Options_GetPIM4 () || M2Options_GetISO ()
3738 || M2Options_GetPositiveModFloor ())
3739 return fold_build3 (
3740 COND_EXPR, TREE_TYPE (op1),
3741 m2expr_BuildLessThan (
3742 location, op2,
3743 m2convert_BuildConvert (location, TREE_TYPE (op2),
3744 m2expr_GetIntegerZero (location), false)),
3745 m2expr_BuildModCeil (location, op1, op2, needsconvert),
3746 m2expr_BuildModFloor (location, op1, op2, needsconvert));
3747 else
3748 return m2expr_BuildModTrunc (location, op1, op2, needsconvert);
3749 }
3750
3751 /* BuildAbs build the Modula-2 function ABS(t) and return the result
3752 in a gcc Tree. */
3753
3754 tree
3755 m2expr_BuildAbs (location_t location, tree t)
3756 {
3757 m2assert_AssertLocation (location);
3758
3759 return m2expr_build_unary_op (location, ABS_EXPR, t, 0);
3760 }
3761
3762 /* BuildRe build an expression for the function RE. */
3763
3764 tree
3765 m2expr_BuildRe (tree op1)
3766 {
3767 op1 = m2expr_FoldAndStrip (op1);
3768 if (TREE_CODE (op1) == COMPLEX_CST)
3769 return fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (op1)), op1);
3770 else
3771 return build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (op1)), op1);
3772 }
3773
3774 /* BuildIm build an expression for the function IM. */
3775
3776 tree
3777 m2expr_BuildIm (tree op1)
3778 {
3779 op1 = m2expr_FoldAndStrip (op1);
3780 if (TREE_CODE (op1) == COMPLEX_CST)
3781 return fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (op1)), op1);
3782 else
3783 return build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (op1)), op1);
3784 }
3785
3786 /* BuildCmplx build an expression for the function CMPLX. */
3787
3788 tree
3789 m2expr_BuildCmplx (location_t location, tree type, tree real, tree imag)
3790 {
3791 tree scalor;
3792 real = m2expr_FoldAndStrip (real);
3793 imag = m2expr_FoldAndStrip (imag);
3794 type = m2tree_skip_type_decl (type);
3795 scalor = TREE_TYPE (type);
3796
3797 if (scalor != TREE_TYPE (real))
3798 real = m2convert_BuildConvert (location, scalor, real, false);
3799 if (scalor != TREE_TYPE (imag))
3800 imag = m2convert_BuildConvert (location, scalor, imag, false);
3801
3802 if ((TREE_CODE (real) == REAL_CST) && (TREE_CODE (imag) == REAL_CST))
3803 return build_complex (type, real, imag);
3804 else
3805 return build2 (COMPLEX_EXPR, type, real, imag);
3806 }
3807
3808 /* BuildBinaryForeachWordDo implements the large set operators. Each
3809 word of the set can be calculated by binop. This function runs along
3810 each word of the large set invoking the binop. */
3811
3812 void
3813 m2expr_BuildBinaryForeachWordDo (location_t location, tree type, tree op1,
3814 tree op2, tree op3,
3815 tree (*binop) (location_t, tree, tree, bool),
3816 bool is_op1lvalue, bool is_op2lvalue,
3817 bool is_op3lvalue, bool is_op1const,
3818 bool is_op2const, bool is_op3const)
3819 {
3820 tree size = m2expr_GetSizeOf (location, type);
3821
3822 m2assert_AssertLocation (location);
3823
3824 ASSERT_BOOL (is_op1lvalue);
3825 ASSERT_BOOL (is_op2lvalue);
3826 ASSERT_BOOL (is_op3lvalue);
3827 ASSERT_BOOL (is_op1const);
3828 ASSERT_BOOL (is_op2const);
3829 ASSERT_BOOL (is_op3const);
3830 if (m2expr_CompareTrees (
3831 size, m2decl_BuildIntegerConstant (SET_WORD_SIZE / BITS_PER_UNIT))
3832 <= 0)
3833 /* Small set size <= TSIZE(WORD). */
3834 m2statement_BuildAssignmentTree (
3835 location, m2treelib_get_rvalue (location, op1, type, is_op1lvalue),
3836 (*binop) (
3837 location, m2treelib_get_rvalue (location, op2, type, is_op2lvalue),
3838 m2treelib_get_rvalue (location, op3, type, is_op3lvalue), false));
3839 else
3840 {
3841 /* Large set size > TSIZE(WORD). */
3842
3843 tree p2 = m2treelib_get_set_address_if_var (location, op2, is_op2lvalue,
3844 is_op2const);
3845 tree p3 = m2treelib_get_set_address_if_var (location, op3, is_op3lvalue,
3846 is_op3const);
3847 unsigned int fieldNo = 0;
3848 tree field1 = m2treelib_get_field_no (type, op1, is_op1const, fieldNo);
3849 tree field2 = m2treelib_get_field_no (type, op2, is_op2const, fieldNo);
3850 tree field3 = m2treelib_get_field_no (type, op3, is_op3const, fieldNo);
3851
3852 if (is_op1const)
3853 m2linemap_internal_error_at (
3854 location,
3855 "not expecting operand1 to be a constant set");
3856
3857 while (field1 != NULL && field2 != NULL && field3 != NULL)
3858 {
3859 m2statement_BuildAssignmentTree (
3860 location, m2treelib_get_set_field_des (location, op1, field1),
3861 (*binop) (
3862 location,
3863 m2treelib_get_set_value (location, p2, field2, is_op2const,
3864 is_op2lvalue, op2, fieldNo),
3865 m2treelib_get_set_value (location, p3, field3, is_op3const,
3866 is_op3lvalue, op3, fieldNo),
3867 false));
3868 fieldNo++;
3869 field1 = m2treelib_get_field_no (type, op1, is_op1const, fieldNo);
3870 field2 = m2treelib_get_field_no (type, op2, is_op2const, fieldNo);
3871 field3 = m2treelib_get_field_no (type, op3, is_op3const, fieldNo);
3872 }
3873 }
3874 }
3875
3876
3877 /* OverflowZType returns true if the ZTYPE str will exceed the
3878 internal representation. This routine is much faster (at
3879 least 2 orders of magnitude faster) than the char at a time overflow
3880 detection used in ToWideInt and so it should be
3881 used to filter out erroneously large constants before calling ToWideInt
3882 allowing a quick fail. */
3883
3884 bool
3885 m2expr_OverflowZType (location_t location, const char *str, unsigned int base,
3886 bool issueError)
3887 {
3888 int length = strlen (str);
3889 bool overflow = false;
3890
3891 switch (base)
3892 {
3893 case 2:
3894 overflow = ((length -1) > WIDE_INT_MAX_PRECISION);
3895 break;
3896 case 8:
3897 overflow = (((length -1) * 3) > WIDE_INT_MAX_PRECISION);
3898 break;
3899 case 10:
3900 {
3901 int str_log10 = length;
3902 int bits_str = (int) (((float) (str_log10)) / log10f (2.0)) + 1;
3903 overflow = (bits_str > WIDE_INT_MAX_PRECISION);
3904 }
3905 break;
3906 case 16:
3907 overflow = (((length -1) * 4) > WIDE_INT_MAX_PRECISION);
3908 break;
3909 default:
3910 gcc_unreachable ();
3911 }
3912 if (issueError && overflow)
3913 error_at (location,
3914 "constant literal %qs exceeds internal ZTYPE range", str);
3915 return overflow;
3916 }
3917
3918
3919 /* ToWideInt converts a ZTYPE str value into result. */
3920
3921 static
3922 bool
3923 ToWideInt (location_t location, const char *str, unsigned int base,
3924 widest_int &result, bool issueError)
3925 {
3926 tree type = m2type_GetM2ZType ();
3927 unsigned int i = 0;
3928 wi::overflow_type overflow = wi::OVF_NONE;
3929 widest_int wbase = wi::to_widest (m2decl_BuildIntegerConstant (base));
3930 unsigned int digit = 0;
3931 result = wi::to_widest (m2decl_BuildIntegerConstant (0));
3932 bool base_specifier = false;
3933
3934 while (((str[i] != (char)0) && (overflow == wi::OVF_NONE))
3935 && (! base_specifier))
3936 {
3937 char ch = str[i];
3938
3939 switch (base)
3940 {
3941 /* GNU m2 extension allows 'A' to represent binary literals. */
3942 case 2:
3943 if (ch == 'A')
3944 base_specifier = true;
3945 else if ((ch < '0') || (ch > '1'))
3946 {
3947 if (issueError)
3948 error_at (location,
3949 "constant literal %qs contains %qc, expected 0 or 1",
3950 str, ch);
3951 return true;
3952 }
3953 else
3954 digit = (unsigned int) (ch - '0');
3955 break;
3956 case 8:
3957 /* An extension of 'B' indicates octal ZTYPE and 'C' octal character. */
3958 if ((ch == 'B') || (ch == 'C'))
3959 base_specifier = true;
3960 else if ((ch < '0') || (ch > '7'))
3961 {
3962 if (issueError)
3963 error_at (location,
3964 "constant literal %qs contains %qc, expected %qs",
3965 str, ch, "0..7");
3966 return true;
3967 }
3968 else
3969 digit = (unsigned int) (ch - '0');
3970 break;
3971 case 10:
3972 if ((ch < '0') || (ch > '9'))
3973 {
3974 if (issueError)
3975 error_at (location,
3976 "constant literal %qs contains %qc, expected %qs",
3977 str, ch, "0..9");
3978 return true;
3979 }
3980 else
3981 digit = (unsigned int) (ch - '0');
3982 break;
3983 case 16:
3984 /* An extension of 'H' indicates hexidecimal ZTYPE. */
3985 if (ch == 'H')
3986 base_specifier = true;
3987 else if ((ch >= '0') && (ch <= '9'))
3988 digit = (unsigned int) (ch - '0');
3989 else if ((ch >= 'A') && (ch <= 'F'))
3990 digit = ((unsigned int) (ch - 'A')) + 10;
3991 else
3992 {
3993 if (issueError)
3994 error_at (location,
3995 "constant literal %qs contains %qc, expected %qs or %qs",
3996 str, ch, "0..9", "A..F");
3997 return true;
3998 }
3999 break;
4000 default:
4001 gcc_unreachable ();
4002 }
4003
4004 if (! base_specifier)
4005 {
4006 widest_int wdigit = wi::to_widest (m2decl_BuildIntegerConstant (digit));
4007 result = wi::umul (result, wbase, &overflow);
4008 if (overflow == wi::OVF_NONE)
4009 result = wi::add (result, wdigit, UNSIGNED, &overflow);
4010 }
4011 i++;
4012 }
4013 if (overflow == wi::OVF_NONE)
4014 {
4015 tree value = wide_int_to_tree (type, result);
4016 if (m2expr_TreeOverflow (value))
4017 {
4018 if (issueError)
4019 error_at (location,
4020 "constant literal %qs exceeds internal ZTYPE range", str);
4021 return true;
4022 }
4023 return false;
4024 }
4025 else
4026 {
4027 if (issueError)
4028 error_at (location,
4029 "constant literal %qs exceeds internal ZTYPE range", str);
4030 return true;
4031 }
4032 }
4033
4034
4035 /* StrToWideInt return true if an overflow occurs when attempting to convert
4036 str to an unsigned ZTYPE the value is contained in the widest_int result.
4037 The value result is undefined if true is returned. */
4038
4039 bool
4040 m2expr_StrToWideInt (location_t location, const char *str, unsigned int base,
4041 widest_int &result, bool issueError)
4042 {
4043 if (m2expr_OverflowZType (location, str, base, issueError))
4044 return true;
4045 return ToWideInt (location, str, base, result, issueError);
4046 }
4047
4048
4049 /* GetSizeOfInBits return the number of bits used to contain, type. */
4050
4051 tree
4052 m2expr_GetSizeOfInBits (tree type)
4053 {
4054 enum tree_code code = TREE_CODE (type);
4055
4056 if (code == FUNCTION_TYPE)
4057 return m2expr_GetSizeOfInBits (ptr_type_node);
4058
4059 if (code == VOID_TYPE)
4060 {
4061 error ("%qs applied to a void type", "sizeof");
4062 return size_one_node;
4063 }
4064
4065 if (code == VAR_DECL)
4066 return m2expr_GetSizeOfInBits (TREE_TYPE (type));
4067
4068 if (code == PARM_DECL)
4069 return m2expr_GetSizeOfInBits (TREE_TYPE (type));
4070
4071 if (code == TYPE_DECL)
4072 return m2expr_GetSizeOfInBits (TREE_TYPE (type));
4073
4074 if (code == COMPONENT_REF)
4075 return m2expr_GetSizeOfInBits (TREE_TYPE (type));
4076
4077 if (code == ERROR_MARK)
4078 return size_one_node;
4079
4080 if (!COMPLETE_TYPE_P (type))
4081 {
4082 error ("%qs applied to an incomplete type", "sizeof");
4083 return size_zero_node;
4084 }
4085
4086 return m2decl_BuildIntegerConstant (TYPE_PRECISION (type));
4087 }
4088
4089 /* GetSizeOf taken from c-typeck.cc (c_sizeof). */
4090
4091 tree
4092 m2expr_GetSizeOf (location_t location, tree type)
4093 {
4094 enum tree_code code = TREE_CODE (type);
4095 m2assert_AssertLocation (location);
4096
4097 if (code == FUNCTION_TYPE)
4098 return m2expr_GetSizeOf (location, m2type_GetPointerType ());
4099
4100 if (code == VOID_TYPE)
4101 return size_one_node;
4102
4103 if (code == VAR_DECL)
4104 return m2expr_GetSizeOf (location, TREE_TYPE (type));
4105
4106 if (code == PARM_DECL)
4107 return m2expr_GetSizeOf (location, TREE_TYPE (type));
4108
4109 if (code == TYPE_DECL)
4110 return m2expr_GetSizeOf (location, TREE_TYPE (type));
4111
4112 if (code == ERROR_MARK)
4113 return size_one_node;
4114
4115 if (code == CONSTRUCTOR)
4116 return m2expr_GetSizeOf (location, TREE_TYPE (type));
4117
4118 if (code == FIELD_DECL)
4119 return m2expr_GetSizeOf (location, TREE_TYPE (type));
4120
4121 if (code == COMPONENT_REF)
4122 return m2expr_GetSizeOf (location, TREE_TYPE (type));
4123
4124 if (!COMPLETE_TYPE_P (type))
4125 {
4126 error_at (location, "%qs applied to an incomplete type", "SIZE");
4127 return size_zero_node;
4128 }
4129
4130 /* Convert in case a char is more than one unit. */
4131 return size_binop_loc (
4132 location, CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
4133 size_int (TYPE_PRECISION (char_type_node) / BITS_PER_UNIT));
4134 }
4135
4136 tree
4137 m2expr_GetIntegerZero (location_t location ATTRIBUTE_UNUSED)
4138 {
4139 return integer_zero_node;
4140 }
4141
4142 tree
4143 m2expr_GetIntegerOne (location_t location ATTRIBUTE_UNUSED)
4144 {
4145 return integer_one_node;
4146 }
4147
4148 tree
4149 m2expr_GetCardinalOne (location_t location)
4150 {
4151 return m2convert_ToCardinal (location, integer_one_node);
4152 }
4153
4154 tree
4155 m2expr_GetCardinalZero (location_t location)
4156 {
4157 return m2convert_ToCardinal (location, integer_zero_node);
4158 }
4159
4160 tree
4161 m2expr_GetWordZero (location_t location)
4162 {
4163 return m2convert_ToWord (location, integer_zero_node);
4164 }
4165
4166 tree
4167 m2expr_GetWordOne (location_t location)
4168 {
4169 return m2convert_ToWord (location, integer_one_node);
4170 }
4171
4172 tree
4173 m2expr_GetPointerZero (location_t location)
4174 {
4175 return m2convert_convertToPtr (location, integer_zero_node);
4176 }
4177
4178 tree
4179 m2expr_GetPointerOne (location_t location)
4180 {
4181 return m2convert_convertToPtr (location, integer_one_node);
4182 }
4183
4184 /* build_set_full_complement return a word size value with all bits
4185 set to one. */
4186
4187 static tree
4188 build_set_full_complement (location_t location)
4189 {
4190 tree value = integer_zero_node;
4191 int i;
4192
4193 m2assert_AssertLocation (location);
4194
4195 for (i = 0; i < SET_WORD_SIZE; i++)
4196 {
4197 value = m2expr_BuildLogicalOr (
4198 location, value,
4199 m2expr_BuildLSL (
4200 location, m2expr_GetWordOne (location),
4201 m2convert_BuildConvert (location, m2type_GetWordType (),
4202 m2decl_BuildIntegerConstant (i), false),
4203 false),
4204 false);
4205 }
4206 return value;
4207 }
4208
4209
4210 /* GetCstInteger return the integer value of the cst tree. */
4211
4212 int
4213 m2expr_GetCstInteger (tree cst)
4214 {
4215 return TREE_INT_CST_LOW (cst);
4216 }
4217
4218
4219 /* init initialise this module. */
4220
4221 void
4222 m2expr_init (location_t location)
4223 {
4224 m2assert_AssertLocation (location);
4225
4226 set_full_complement = build_set_full_complement (location);
4227 }
4228
4229 #include "gt-m2-m2expr.h"