1 #include <freehdl/vaul.h>
2 #include "v2cc-chunk.h"
3 #include <algorithm>
4 #include <stdlib.h>
5 #include <ctype.h>
6 #if HAVE_MALLOC_H
7 #include <malloc.h>
8 #endif
9 #if HAVE_UNISTD_H
10 #include <unistd.h>
11 #endif
12 #include <math.h>
13 #include <limits.h>
14
15 #include "mapping.h"
16 #include "v2cc-util.h"
17
18
19
20 // Used to generate error messages
21 extern vaul_error_printer codegen_error;
22
23
24
25 // ******************************************************************************************
26 // Name: m_constant_fold, generic function
27 //
28 // Description: performs constant folding optimizations on nodes
29 //
30 // Return value: returns number of errors found during folding
31 //
32 // ******************************************************************************************
33
34
35 int
m_constant_fold(pIIR_Type st,RegionStack & rstack)36 m_constant_fold (pIIR_Type st, RegionStack &rstack)
37 {
38 if (done(st) & CONST_FOLD) return 0; else done(st) |= CONST_FOLD;
39
40 int error_count = 0;
41 if (st->declaration != NULL)
42 error_count += constant_fold(st->declaration->type, rstack);
43
44 return error_count;
45 }
46
47
48 int
m_constant_fold(pIIR_PhysicalType st,RegionStack & rstack)49 m_constant_fold (pIIR_PhysicalType st, RegionStack &rstack)
50 {
51 if (done(st) & CONST_FOLD) return 0; else done(st) |= CONST_FOLD;
52
53 int error_count = 0;
54 if (st->base != NULL)
55 error_count += constant_fold(st->base, rstack);
56
57 for (pIIR_UnitList ul = st->units; ul; ul = ul->rest)
58 if (ul->first->multiplier)
59 error_count += constant_fold(ul->first->multiplier, rstack);
60
61 return error_count;
62 }
63
64
65 int
m_constant_fold(pIIR_ScalarSubtype st,RegionStack & rstack)66 m_constant_fold (pIIR_ScalarSubtype st, RegionStack &rstack)
67 {
68 if (done(st) & CONST_FOLD) return 0; else done(st) |= CONST_FOLD;
69
70 int error_count = 0;
71 error_count += constant_fold(st->immediate_base, rstack);
72
73 if (st->range != NULL)
74 error_count += constant_fold(st->range, rstack);
75
76 return error_count;
77 }
78
79
80 int
m_constant_fold(pIIR_ArrayType st,RegionStack & rstack)81 m_constant_fold (pIIR_ArrayType st, RegionStack &rstack)
82 {
83 if (done(st) & CONST_FOLD) return 0; else done(st) |= CONST_FOLD;
84
85 int error_count = 0;
86 for (pIIR_TypeList tl = st->index_types; tl; tl = tl->rest)
87 error_count += constant_fold(tl->first, rstack);
88
89 error_count += constant_fold(st->element_type, rstack);
90
91 return error_count;
92 }
93
94
95 int
m_constant_fold(pIIR_ArraySubtype st,RegionStack & rstack)96 m_constant_fold (pIIR_ArraySubtype st, RegionStack &rstack)
97 {
98 if (done(st) & CONST_FOLD) return 0; else done(st) |= CONST_FOLD;
99
100 int error_count = 0;
101 error_count += constant_fold(st->immediate_base, rstack);
102 for (pIIR_TypeList tl = st->constraint; tl; tl = tl->rest)
103 error_count += constant_fold(tl->first, rstack);
104
105 return error_count;
106 }
107
108
109 int
m_constant_fold(pIIR_QualifiedExpression e,RegionStack & rstack)110 m_constant_fold (pIIR_QualifiedExpression e, RegionStack &rstack)
111 {
112 if (done(e) & CONST_FOLD) return 0; else done(e) |= CONST_FOLD;
113
114 int error_count = 0;
115 error_count += constant_fold(e->type_mark, rstack);
116 error_count += constant_fold(e->expression, rstack);
117
118 return error_count;
119 }
120
121
122 int
m_constant_fold(pIIR_AttrSigFunc ase,RegionStack & rstack)123 m_constant_fold(pIIR_AttrSigFunc ase, RegionStack &rstack)
124 {
125 if (done(ase) & CONST_FOLD) return 0; else done(ase) |= CONST_FOLD;
126
127 int error_count = constant_fold(ase->signal, rstack);
128
129 return error_count;
130 }
131
132
133 int
m_constant_fold(pIIR_ArrayLiteralExpression le,RegionStack & rstack)134 m_constant_fold(pIIR_ArrayLiteralExpression le, RegionStack &rstack)
135 {
136 if (done(le) & CONST_FOLD) return 0; else done(le) |= CONST_FOLD;
137
138 int error_count = 0;
139 // Get the valid enumeration items
140 pIIR_EnumerationLiteralList enum_item_list =
141 pIIR_EnumerationType(get_base_type(pIIR_ArrayType(get_base_type(le->subtype))->element_type))->enumeration_literals;
142
143 char *str = le->value->text.to_chars() + 1; // Skip leading "
144 int length = strlen(str) - 1; // Get length of array
145 vector<int> literal_value(length);
146
147 // Get enumeration pos for each item
148 int i = 0;
149 string item = "'";
150 while (true) {
151 if (*str == '"' && *(str + 1) == '\0') break; // Skip trailing "
152 item = string("'") + *str + string("'");
153 literal_value[i] = literal_to_pos(enum_item_list, item);
154 i++;
155 str++;
156 }
157
158 // Store folded value
159 folded_value(le).array_literal_value() = literal_value;
160 valid_folded_value(le) = true;
161
162 // Currently array literals are not folded!
163 return error_count;
164 }
165
166
167 int
m_constant_fold(pIIR_EnumLiteralReference le,RegionStack & rstack)168 m_constant_fold(pIIR_EnumLiteralReference le, RegionStack &rstack)
169 {
170 if (done(le) & CONST_FOLD) return 0; else done(le) |= CONST_FOLD;
171
172 int error_count = constant_fold(le->value, rstack);
173 folded_value(le).long_value() = le->value->enum_pos;
174 valid_folded_value(le) = true;
175
176 return error_count;
177 }
178
179
180 int
m_constant_fold(pIIR_CharacterLiteral le,RegionStack & rstack)181 m_constant_fold(pIIR_CharacterLiteral le, RegionStack &rstack)
182 {
183 if (done(le) & CONST_FOLD) return 0; else done(le) |= CONST_FOLD;
184
185 int error_count = 0;
186 folded_value(le).long_value() = (long long int)(le->text.to_chars())[1];
187 valid_folded_value(le) = true;
188
189 return error_count;
190 }
191
192
193 int
m_constant_fold(pIIR_StringLiteral le,RegionStack & rstack)194 m_constant_fold(pIIR_StringLiteral le, RegionStack &rstack)
195 {
196 if (done(le) & CONST_FOLD) return 0; else done(le) |= CONST_FOLD;
197
198 int error_count = 0;
199 // String literals are currently not folded
200 return error_count;
201 }
202
203
204
205 int
m_constant_fold(pIIR_EnumerationLiteral el,RegionStack & rstack)206 m_constant_fold(pIIR_EnumerationLiteral el, RegionStack &rstack)
207 {
208 if (done(el) & CONST_FOLD) return 0; else done(el) |= CONST_FOLD;
209
210 folded_value(el).long_value() = lint(el->enum_pos);
211 valid_folded_value(el) = true;
212
213 return 0;
214 }
215
216
217 int
m_constant_fold(pIIR_IntegerLiteral le,RegionStack & rstack)218 m_constant_fold(pIIR_IntegerLiteral le, RegionStack &rstack)
219 {
220 if (done(le) & CONST_FOLD) return 0; else done(le) |= CONST_FOLD;
221
222 pair<bool, StaticLint> result = string_to_lint (le->text.to_chars());
223 folded_value(le) = result.second;
224 valid_folded_value(le) = result.first;
225
226 // Retrun an error of the constant could not be folded!
227 return result.first? 0 : 1;
228 }
229
230
231 int
m_constant_fold(pIIR_FloatingPointLiteral le,RegionStack & rstack)232 m_constant_fold(pIIR_FloatingPointLiteral le, RegionStack &rstack)
233 {
234 if (done(le) & CONST_FOLD) return 0; else done(le) |= CONST_FOLD;
235
236 pair<bool, StaticDouble> result = string_to_double (le->text.to_chars());
237 folded_value(le) = result.second;
238 valid_folded_value(le) = result.first;
239
240 // Retrun an error of the constant could not be folded!
241 return result.first? 0 : 1;
242 }
243
244
245 int
m_constant_fold(pIIR_AbstractLiteralExpression ale,RegionStack & rstack)246 m_constant_fold(pIIR_AbstractLiteralExpression ale, RegionStack &rstack)
247 {
248 if (done(ale) & CONST_FOLD) return 0; else done(ale) |= CONST_FOLD;
249
250 int error_count = constant_fold(ale->value, rstack);
251 if (valid_folded_value(ale->value))
252 {
253 folded_value(ale) = folded_value(ale->value);
254 valid_folded_value(ale) = valid_folded_value(ale->value);
255 }
256
257 return error_count;
258 }
259
260 // function is used to fold a scalar value
261 template<class T, class A>
262 T perform_operation(pIIR_FunctionCall fc, A a)
263 {
264 string op_str = fc->function->declarator->text.to_chars();
265
266 if (op_str == "\"not\"")
267 return T(int(a)? 0 : 1);
268 else if (op_str == "\"+\"")
269 return T(a);
270 else if (op_str == "\"-\"")
271 return T(A(-1) * a);
272 else if (op_str == "\"abs\"")
273 return T((a < 0)? -a : a);
274 else
275 assert(false);
276 }
277
278 // Returns 0 if parameter is equal to 0, -1 if the parameter is less
279 // than 0, 1 otherwise
280 template<class X>
sign(const X a)281 int sign(const X a)
282 {
283 if (a == X(0))
284 return 0;
285 else if (a < X(0))
286 return -1;
287 else
288 return 1;
289 }
290
291
292 // Overloaded functions returning the min/max values of the
293 // corresponding type. Note that the parameter dummy is actually only
294 // used to select the corresponding function.
max_huge_value(double dummy)295 double max_huge_value(double dummy) { return HUGE_VAL; }
min_huge_value(double dummy)296 double min_huge_value(double dummy) { return -HUGE_VAL; }
max_huge_value(lint dummy)297 lint max_huge_value(lint dummy) { return PHYSICAL_MAX; }
min_huge_value(lint dummy)298 lint min_huge_value(lint dummy) { return PHYSICAL_MIN; }
299
300 //*******************************************************
301 // Add operations
302 //*******************************************************
303 template<class X, class Y>
304 X calculate_plus(const X a, const Y b)
305 {
306 X result = a + b;
307
308 // Check whether the sign of the result is ok
309 if (abs(sign(a) + sign(b)) == 2 &&
310 sign(a) != sign(result))
311 // If the result is wrong then return either the max or the min
312 // lint value
313 return sign(a)==1? max_huge_value(a) : min_huge_value(a);
314 else
315 // Return result of the operation
316 return result;
317 }
318
319 double
calculate_plus(const double a,const double b)320 calculate_plus(const double a, const double b)
321 {
322 return a + b; // If doubles are added we don't have to check the
323 // result as this is done by the floating point operator
324 }
325
326 //*******************************************************
327 // Subtract operations
328 //*******************************************************
329 template<class X, class Y>
330 X calculate_minus(const X a, const Y b)
331 {
332 X result = a - b;
333
334 // Check whether the sign of the result is ok
335 if (abs(sign(a) - sign(b)) == 2 &&
336 sign(a) != sign(result))
337 // If the result is wrong then return either the max or the min
338 // lint value
339 return sign(a)==1? max_huge_value(a) : min_huge_value(a);
340 else
341 // Return result of the operation
342 return result;
343 }
344
345 double
calculate_minus(const double a,const double b)346 calculate_minus(const double a, const double b)
347 {
348 return a - b; // If doubles are subtracted we don't have to check
349 // the result as this is done by the floating point operator
350 }
351
352 //*******************************************************
353 // Multiply operations
354 //*******************************************************
355 template<class X, class Y>
356 X calculate_mult(const X a, const Y b)
357 {
358 X result = a * b;
359
360 // Check whether at least one parameter is equal to 0 or the result
361 // is reasonable. Note that we will compare result / a == b as well
362 // as result / b == a as X and Y may be different types (e.g.,
363 // double and long long int).
364 if (a == X(0) || b == Y(0) ||
365 (Y(result / a) == b) ||
366 (X(result / b) == a))
367 return result;
368 else
369 return sign(a) * sign(b) == -1? min_huge_value(a) : max_huge_value(a);
370 }
371
372 double
calculate_mult(const double a,const double b)373 calculate_mult(const double a, const double b)
374 {
375 return a * b; // If doubles are multiplied we don't have to check
376 // the result as this is done by the floating point operator
377 }
378
379 //*******************************************************
380 // Divide operations
381 //*******************************************************
382 template<class X, class Y>
383 X calculate_div(const X a, const Y b)
384 {
385 // Check second parameter
386 if (b == Y(0))
387 // If the second parameter is 0 then return either the maximum
388 // lint or the min lint value depending on the sign of the first
389 // parameter
390 return sign(a) == -1? min_huge_value(a) : max_huge_value(a);
391 else
392 return X(a / b);
393 }
394
395 double
calculate_div(const double a,const double b)396 calculate_div(const double a, const double b)
397 {
398 return a / b; // If doubles are divided we don't have to check
399 // the result as this is done by the floating point operator
400 }
401
402
403 // function is used to fold two scalar values
404 template<class T, class A, class B>
405 T perform_operation(pIIR_FunctionCall fc, A a, B b)
406 {
407 string op_str = fc->function->declarator->text.to_chars();
408
409 if (op_str == "\"and\"")
410 return T(int(a) & int(b)? 1 : 0);
411 else if (op_str == "\"or\"")
412 return T(int(a) | int(b)? 1 : 0);
413 else if (op_str == "\"xor\"")
414 return T(int(a) ^ int(b) ? 1 : 0);
415 else if (op_str == "\"xnor\"")
416 return T(1 ^ (int(a) ^ int(b)) ? 1 : 0);
417 else if (op_str == "\"nand\"")
418 return T(1 ^ (int(a) & int(b)) ? 1 : 0);
419 else if (op_str == "\"nor\"")
420 return T(1 ^ (int(a) | int(b)) ? 1 : 0);
421 else if (op_str == "\"=\"")
422 return T((a == b)? 1 : 0);
423 else if (op_str == "\">\"")
424 return T((a > b)? 1 : 0);
425 else if (op_str == "\">=\"")
426 return T((a > b)? 1 : 0);
427 else if (op_str == "\"<=\"")
428 return T((a <= b)? 1 : 0);
429 else if (op_str == "\"<\"")
430 return T((a < b)? 1 : 0);
431 else if (op_str == "\"/=\"")
432 return T((a != b)? 1 : 0);
433 else if (op_str == "\"=\"")
434 return T((a == b)? 1 : 0);
435 else if (op_str == "\"+\"")
436 return T(calculate_plus(a, b));
437 else if (op_str == "\"-\"")
438 return T(calculate_minus(a, b));
439 else if (op_str == "\"*\"")
440 return T(calculate_mult(a, b));
441 else if (op_str == "\"/\"")
442 return T(calculate_div(a, b));
443 else if (op_str == "\"mod\"")
444 assert(false);
445 else if (op_str == "\"rem\"")
446 assert(false);
447 else if (op_str == "\"**\"") {
448 return T(calculate_pow(a, b));
449 } else
450 assert(false);
451 }
452
453
454 int
m_constant_fold(pIIR_FunctionCall fc,RegionStack & rstack)455 m_constant_fold(pIIR_FunctionCall fc, RegionStack &rstack)
456 {
457 if (done(fc) & CONST_FOLD) return 0; else done(fc) |= CONST_FOLD;
458
459 int error_count = 0;
460 int n_args = 0;
461 int try_function_folding = true;
462
463 // Try to fold function parameters
464 for (pIIR_AssociationList al = fc->parameter_association_list; al; al = al->rest) {
465 error_count += constant_fold(al->first->actual, rstack);
466 if (!valid_folded_value(al->first->actual))
467 try_function_folding = false;
468 n_args++;
469 }
470
471 // Return if not all prameters are locally static!
472 if (!try_function_folding)
473 return error_count;
474
475 // Now, try to fold function call
476 switch (get_operator_type(fc->function)) { // Analyze function call type
477
478 case STD_OP: // The function call is a standard operator call
479
480 if (n_args == 1) {
481 //**********************************************************************
482 // Function has one parameter
483 //**********************************************************************
484 pIIR_Type base_type = get_base_type(fc->parameter_association_list->first->actual->subtype);
485 if (base_type->is(IR_INTEGER_TYPE) ||
486 base_type->is(IR_ENUMERATION_TYPE) ||
487 base_type->is(IR_PHYSICAL_TYPE)) {
488 lint arg = folded_value(fc->parameter_association_list->first->actual).long_value();
489 folded_value(fc).long_value() = perform_operation<lint, lint>(fc, arg);
490
491 } else if (base_type->is(IR_FLOATING_TYPE)) {
492 double arg = folded_value(fc->parameter_association_list->first->actual).double_value();
493 folded_value(fc).double_value() = perform_operation<double, double>(fc, arg);
494
495 } else
496 assert(false);
497
498 } else if (n_args == 2) {
499 //**********************************************************************
500 // Function has two parameters
501 //**********************************************************************
502 pIIR_Type base_type1 = get_base_type(fc->parameter_association_list->first->actual->subtype);
503 pIIR_Type base_type2 = get_base_type(fc->parameter_association_list->rest->first->actual->subtype);
504 pIIR_Type result_type = get_base_type(fc->subtype);
505
506 if (is_array_type(result_type)) {
507 //**********************************************************************
508 // Two arrays (or an array and an array element, or two array elements) are
509 // concatenated
510 string op_str = fc->function->declarator->text.to_chars();
511 // Only the concatenation operator is predefined for arrays
512 assert(op_str == "\"&\"");
513
514 // First, determine length of arguments
515 int length1 = is_array_type(base_type1)?
516 folded_value(fc->parameter_association_list->first->actual).array_literal_value().size() : 1;
517 int length2 = is_array_type(base_type2)?
518 folded_value(fc->parameter_association_list->rest->first->actual).array_literal_value().size() : 1;
519
520 // Next, concatenate both arguments
521 vector<int> result(length1 + length2);
522 if (is_array_type(base_type1))
523 // The argument is an array
524 copy(folded_value(fc->parameter_association_list->first->actual).array_literal_value().begin(),
525 folded_value(fc->parameter_association_list->first->actual).array_literal_value().end(),
526 result.begin());
527 else
528 // The argument is an array element
529 result[0] = folded_value(fc->parameter_association_list->first->actual).long_value();
530
531 if (is_array_type(base_type2))
532 // The argument is an array
533 copy(folded_value(fc->parameter_association_list->rest->first->actual).array_literal_value().begin(),
534 folded_value(fc->parameter_association_list->rest->first->actual).array_literal_value().end(),
535 &result[length1]);
536 else
537 // The argument is an array element
538 result[length1] = folded_value(fc->parameter_association_list->rest->first->actual).long_value();
539
540 // Check whether length of target array matches length of
541 // concatenation result.
542 if (is_constrained_array_type(fc->subtype)) {
543 // First, try to determine array bounds
544 vector<RangeDescriptor> range_desc = get_discrete_range(fc->subtype, rstack, IR_NOT_STATIC);
545 range_desc[0].constant_fold_rangedes(rstack);
546 StaticRangeDescriptor<lint, IR_Direction> range =
547 range_desc[0].rangedes_to_lint(rstack);
548 // If array bounds are locally static then determine length
549 // of array
550 if (and_reduce(range.valid)) {
551 lint length = range_to_length(range.left, range.dir, range.right);
552 if (length != (length1 + length2)) {
553 codegen_error.error("%:error: length (=%i) of concatenation result does not match length (=%i) of target array.",
554 fc, length1 + length2, length);
555 error_count++;
556 }
557 }
558 }
559
560 folded_value(fc).array_literal_value() = result;
561
562 } else if (base_type1->is(IR_PHYSICAL_TYPE) && base_type2->is(IR_PHYSICAL_TYPE) ||
563 base_type1->is(IR_PHYSICAL_TYPE) && base_type2->is(IR_INTEGER_TYPE) ||
564 base_type1->is(IR_INTEGER_TYPE) && base_type2->is(IR_PHYSICAL_TYPE)) {
565 //**********************************************************************
566 lint arg1 = folded_value(fc->parameter_association_list->first->actual).long_value();
567 lint arg2 = folded_value(fc->parameter_association_list->rest->first->actual).long_value();
568 lint result = perform_operation<lint, lint, lint>(fc, arg1, arg2);
569 // Check whether result is ok
570 if (result > PHYSICAL_MAX || result < PHYSICAL_MIN) {
571 result = result > 0? PHYSICAL_MAX : PHYSICAL_MIN;
572 codegen_error.error("%:error: overflow/underflow in %n.", fc, fc);
573 error_count++;
574 }
575 // Store result
576 folded_value(fc).long_value() = result;
577
578 } else if (base_type1->is(IR_PHYSICAL_TYPE) && base_type2->is(IR_FLOATING_TYPE)) {
579 //**********************************************************************
580 lint arg1 = folded_value(fc->parameter_association_list->first->actual).long_value();
581 double arg2 = folded_value(fc->parameter_association_list->rest->first->actual).double_value();
582 lint result = perform_operation<lint, double, double>(fc, double(arg1), arg2);
583 // Check whether result is ok
584 if (result > PHYSICAL_MAX || result < PHYSICAL_MIN) {
585 result = result > 0? PHYSICAL_MAX : PHYSICAL_MIN;
586 codegen_error.error("%:error: overflow/underflow in %n.", fc, fc);
587 error_count++;
588 }
589 // Store result
590 folded_value(fc).long_value() = result;
591
592 } else if (base_type1->is(IR_FLOATING_TYPE) && base_type2->is(IR_PHYSICAL_TYPE)) {
593 //**********************************************************************
594 double arg1 = folded_value(fc->parameter_association_list->first->actual).double_value();
595 lint arg2 = folded_value(fc->parameter_association_list->rest->first->actual).long_value();
596 lint result = perform_operation<lint, double, double>(fc, arg1, double(arg2));
597 // Check whether result is ok
598 if (result > PHYSICAL_MAX || result < PHYSICAL_MIN) {
599 result = result > 0? PHYSICAL_MAX : PHYSICAL_MIN;
600 codegen_error.error("%:error: overflow/underflow in %n.", fc, fc);
601 error_count++;
602 }
603 // Store result
604 folded_value(fc).long_value() = result;
605
606 } else if ((base_type1->is(IR_ENUMERATION_TYPE) || base_type1->is(IR_INTEGER_TYPE)) &&
607 (base_type2->is(IR_ENUMERATION_TYPE) || base_type2->is(IR_INTEGER_TYPE))) {
608 //**********************************************************************
609 lint arg1 = folded_value(fc->parameter_association_list->first->actual).long_value();
610 lint arg2 = folded_value(fc->parameter_association_list->rest->first->actual).long_value();
611 lint result = perform_operation<lint, lint, lint>(fc, arg1, arg2);
612 // Check whether result is ok
613 if (result > INTEGER_MAX || result < INTEGER_MIN) {
614 result = result > 0? INTEGER_MAX : INTEGER_MIN;
615 codegen_error.error("%:error: overflow/underflow in %n.", fc, fc);
616 error_count++;
617 }
618 // Store result
619 folded_value(fc).long_value() = result;
620
621 } else if (base_type1->is(IR_FLOATING_TYPE) && base_type2->is(IR_FLOATING_TYPE) &&
622 result_type->is(IR_ENUMERATION_TYPE)) {
623 //**********************************************************************
624 // Compare operation
625 double arg1 = folded_value(fc->parameter_association_list->first->actual).double_value();
626 double arg2 = folded_value(fc->parameter_association_list->rest->first->actual).double_value();
627 lint result = perform_operation<lint, double, double>(fc, arg1, arg2);
628 // Check whether result is ok
629 if (result > INTEGER_MAX || result < INTEGER_MIN) {
630 result = result > 0? INTEGER_MAX : INTEGER_MIN;
631 codegen_error.error("%:error: overflow/underflow in %n.", fc, fc);
632 error_count++;
633 }
634 // Store result
635 folded_value(fc).long_value() = result;
636
637 } else if (base_type1->is(IR_FLOATING_TYPE) && base_type2->is(IR_INTEGER_TYPE)) {
638 //**********************************************************************
639 // Power
640 double arg1 = folded_value(fc->parameter_association_list->first->actual).double_value();
641 lint arg2 = folded_value(fc->parameter_association_list->rest->first->actual).long_value();
642 double result = perform_operation<double, double, lint>(fc, arg1, arg2);
643 // Check whether result is ok
644 if (result == HUGE_VAL || result == -HUGE_VAL) {
645 codegen_error.error("%:error: overflow/underflow in %n.", fc, fc);
646 error_count++;
647 }
648 // Store result
649 folded_value(fc).double_value() = result;
650
651 } else if (base_type1->is(IR_FLOATING_TYPE) && base_type2->is(IR_FLOATING_TYPE) &&
652 result_type->is(IR_FLOATING_TYPE)) {
653 //**********************************************************************
654 // Misc operations
655 double arg1 = folded_value(fc->parameter_association_list->first->actual).double_value();
656 double arg2 = folded_value(fc->parameter_association_list->rest->first->actual).double_value();
657 double result = perform_operation<double, double, double>(fc, arg1, arg2);
658 // Check whether result is ok
659 if (result == HUGE_VAL || result == -HUGE_VAL) {
660 codegen_error.error("%:error: overflow/underflow in %n.", fc, fc);
661 error_count++;
662 }
663 // Store result
664 folded_value(fc).double_value() = result;
665
666 } else
667 assert(false);
668
669 }
670
671 if (error_count == 0)
672 valid_folded_value(fc) = true; // The node has been optimized
673
674 break;
675
676 case BASIC_OP: // The function is a operator defined in an IEEE
677 // library. Currently no constant folding is performed for this class
678 // of operators
679 case USER_OP: // The function is an user defined operator call
680 case NO_OP: // A ordinary function call (no operator)
681 break;
682 }
683
684 return error_count;
685 }
686
687
688 int
m_constant_fold(pIIR_PhysicalLiteral le,RegionStack & rstack)689 m_constant_fold(pIIR_PhysicalLiteral le, RegionStack &rstack)
690 {
691 if (done(le) & CONST_FOLD) return 0; else done(le) |= CONST_FOLD;
692
693 // First, try to fold the unit. I.e., evaluate the number of basic
694 // unit the current unit consists of
695 int error_count = constant_fold(le->unit, rstack);
696
697 // Next, fold the value expression
698 if (le->value != NULL)
699 // If value pointer is not NULL then fold value
700 error_count += constant_fold(le->value, rstack);
701
702 if (!valid_folded_value(le->unit) ||
703 !(le->value == NULL || valid_folded_value(le->value)))
704 return error_count;
705
706 // Calculate the resulting physical value. The physical value is
707 // actually converted to a long long int number which represents the
708 // number of basic units the physical value consists of.
709 valid_folded_value(le) = true;
710 if (le->value == NULL)
711 // If the value expression is NULL then only a time unit was
712 // given. Hence, implicitly set value to 1.
713 folded_value(le).long_value() = folded_value(le->unit).long_value();
714 else if (le->value->is(IR_INTEGER_LITERAL))
715 folded_value(le).long_value() =
716 calculate_mult(folded_value(le->value).long_value(), folded_value(le->unit).long_value());
717 else if (le->value->is(IR_FLOATING_POINT_LITERAL))
718 {
719 // XXX - Allow inaccuracies here. `calculate_mult (double,
720 // long)' does extensive checking to ensure that only
721 // multiplications are performed where the result can be
722 // represented exactly. This does not make much sense for
723 // floating point and for example fails for 1.0e-3 * 1000000.
724
725 double res = (folded_value(le->value).double_value()
726 * folded_value(le->unit).long_value());
727 if (res > PHYSICAL_MAX)
728 folded_value(le).long_value() = PHYSICAL_MAX;
729 else if (res < PHYSICAL_MIN)
730 folded_value(le).long_value() = PHYSICAL_MIN;
731 else
732 folded_value(le).long_value() = lint(res);
733 }
734 else
735 assert(false);
736
737 // Check whether no overflow occurred during constant folding
738 if (folded_value(le).long_value() > PHYSICAL_MAX ||
739 folded_value(le).long_value() < PHYSICAL_MIN) {
740 codegen_error.error("%:error: overflow occured during constant folding.", le);
741 error_count++;
742 }
743
744 return error_count;
745 }
746
747
748 int
m_constant_fold(pIIR_PhysicalUnit pu,RegionStack & rstack)749 m_constant_fold(pIIR_PhysicalUnit pu, RegionStack &rstack)
750 {
751 if (done(pu) & CONST_FOLD) return 0; else done(pu) |= CONST_FOLD;
752
753 int error_count = 0;
754
755 // Fold multiplier value
756 if (pu->multiplier != NULL)
757 error_count = constant_fold(pu->multiplier, rstack);
758 // Fold unit name, i.e. determine number of basic units this unit
759 // includes
760 if (pu->unit_name != NULL)
761 error_count += constant_fold(pu->unit_name, rstack);
762
763 // Flag an error if no valid data could be folded
764 if (pu->multiplier != NULL &&
765 !valid_folded_value(pu->multiplier)) {
766 codegen_error.error("%:error: cannot evaluate expression.", pu, pu->multiplier);
767 error_count++;
768 }
769 // Flag an error if no valid data could be folded
770 if (pu->unit_name != NULL &&
771 !valid_folded_value(pu->unit_name)) {
772 codegen_error.error("%:error: cannot evaluate expression.", pu, pu->unit_name);
773 error_count++;
774 }
775
776 // Determine multiplier value an unit value (unit value = value
777 // related to the basic unit)
778 lint mult_value = pu->multiplier == NULL? lint(1) : folded_value(pu->multiplier).long_value();
779 lint unit_value = pu->unit_name == NULL? lint(1) : folded_value(pu->unit_name).long_value();
780
781 // Multiply the multiplier value with the number of basic units and
782 // store result into node
783 folded_value(pu).long_value() = calculate_mult(mult_value, unit_value);
784 valid_folded_value(pu) = true;
785
786 // Check whether no overflow occured during constant folding
787 if (folded_value(pu).long_value() > PHYSICAL_MAX ||
788 folded_value(pu).long_value() < PHYSICAL_MIN) {
789 codegen_error.error("%:error: overflow occured during constant folding.", pu);
790 error_count++;
791 }
792
793 return error_count;
794 }
795
796
797
798 int
m_constant_fold(pIIR_SimpleReference sr,RegionStack & rstack)799 m_constant_fold(pIIR_SimpleReference sr, RegionStack &rstack)
800 {
801 if (done(sr) & CONST_FOLD) return 0; else done(sr) |= CONST_FOLD;
802 // Return if the expression is not locally static or does not
803 // reference a constant
804 if (!sr->object->is(IR_CONSTANT_DECLARATION))
805 return 0;
806
807 pIIR_ConstantDeclaration cdecl = pIIR_ConstantDeclaration(sr->object);
808 int error_count = 0;
809 // Return if constant does not have an initial value
810 if (cdecl->initial_value != NULL)
811 error_count = constant_fold(cdecl->initial_value, rstack);
812 else
813 return 0;
814 // Return if no folded constant value could be determined.
815 if (error_count != 0 ||
816 !valid_folded_value(cdecl->initial_value))
817 return error_count;
818
819 pIIR_Type base_type = get_base_type(sr->subtype); // Get base type
820
821 if (base_type->is(IR_INTEGER_TYPE) ||
822 base_type->is(IR_ENUMERATION_TYPE) ||
823 base_type->is(IR_PHYSICAL_TYPE)) {
824 folded_value(sr).long_value() =
825 folded_value(cdecl->initial_value).long_value();
826 valid_folded_value(sr) = true;
827 } if (base_type->is(IR_FLOATING_TYPE)) {
828 folded_value(sr).double_value() =
829 folded_value(cdecl->initial_value).double_value();
830 valid_folded_value(sr) = true;
831 } else if (folded_value(cdecl->initial_value).is_array_literal_value ()) {
832 folded_value(sr).array_literal_value() =
833 folded_value(cdecl->initial_value).array_literal_value ();
834 valid_folded_value(sr) = true;
835 }
836
837 return 0;
838 }
839
840
841
842 int
m_constant_fold(pIIR_ArrayReference ar,RegionStack & rstack)843 m_constant_fold(pIIR_ArrayReference ar, RegionStack &rstack)
844 {
845 if (done(ar) & CONST_FOLD) return 0; else done(ar) |= CONST_FOLD;
846
847 int error_count = constant_fold(ar->array, rstack);
848 for (pIIR_ExpressionList el = ar->indices; el; el = el->rest)
849 error_count += constant_fold(el, rstack);
850
851 return error_count;
852 }
853
854
855
856 int
m_constant_fold(pIIR_ArrayRange ar,RegionStack & rstack)857 m_constant_fold(pIIR_ArrayRange ar, RegionStack &rstack)
858 {
859 if (done(ar) & CONST_FOLD) return 0; else done(ar) |= CONST_FOLD;
860
861 int error_count = 0;
862
863 if (ar->array != NULL)
864 error_count += constant_fold(ar->array, rstack);
865
866 if (ar->index != NULL)
867 error_count += constant_fold(ar->index, rstack);
868
869 return error_count;
870 }
871
872
873 int
m_constant_fold(pIIR_ExplicitRange er,RegionStack & rstack)874 m_constant_fold(pIIR_ExplicitRange er, RegionStack &rstack)
875 {
876 if (done(er) & CONST_FOLD) return 0; else done(er) |= CONST_FOLD;
877
878 int error_count = constant_fold(er->left, rstack);
879 error_count += constant_fold(er->right, rstack);
880
881 return error_count;
882 }
883
884
885 int
m_constant_fold(pIIR_OthersIndexedAssociation ia,RegionStack & rstack)886 m_constant_fold(pIIR_OthersIndexedAssociation ia, RegionStack &rstack)
887 {
888 int error_count = constant_fold(ia->value, rstack);
889 return error_count;
890 }
891
892
893 int
m_constant_fold(pIIR_RangeIndexedAssociation ia,RegionStack & rstack)894 m_constant_fold(pIIR_RangeIndexedAssociation ia, RegionStack &rstack)
895 {
896 if (done(ia) & CONST_FOLD) return 0; else done(ia) |= CONST_FOLD;
897
898 int error_count = constant_fold(ia->value, rstack);
899 error_count += constant_fold(ia->index_range, rstack);
900
901 return error_count;
902 }
903
904
905 int
m_constant_fold(pIIR_SingleIndexedAssociation ia,RegionStack & rstack)906 m_constant_fold(pIIR_SingleIndexedAssociation ia, RegionStack &rstack)
907 {
908 if (done(ia) & CONST_FOLD) return 0; else done(ia) |= CONST_FOLD;
909
910 int error_count = 0;
911 if (ia->index != NULL)
912 error_count += constant_fold(ia->index, rstack);
913
914 error_count += constant_fold(ia->value, rstack);
915
916 return error_count;
917 }
918
919
920 int
m_constant_fold(pIIR_SliceIndexedAssociation sia,RegionStack & rstack)921 m_constant_fold (pIIR_SliceIndexedAssociation sia, RegionStack &rstack)
922 {
923 if (done(sia) & CONST_FOLD) return 0; else done(sia) |= CONST_FOLD;
924
925 int error_count = constant_fold(sia->value, rstack);
926 error_count += constant_fold(sia->index_range, rstack);
927
928 return error_count;
929 }
930
931
932 int
m_constant_fold(pIIR_SliceReference sr,RegionStack & rstack)933 m_constant_fold(pIIR_SliceReference sr, RegionStack &rstack)
934 {
935 if (done(sr) & CONST_FOLD) return 0; else done(sr) |= CONST_FOLD;
936
937 int error_count = 0;
938 error_count += constant_fold(sr->array, rstack);
939 error_count += constant_fold(sr->range, rstack);
940
941 return error_count;
942 }
943
944
945
946 int
m_constant_fold(pIIR_RecordReference rr,RegionStack & rstack)947 m_constant_fold(pIIR_RecordReference rr, RegionStack &rstack)
948 {
949 if (done(rr) & CONST_FOLD) return 0; else done(rr) |= CONST_FOLD;
950
951 int error_count = 0;
952 error_count += constant_fold(rr->record, rstack);
953
954 return error_count;
955 }
956
957
958
959 int
m_constant_fold(pIIR_Expression e,RegionStack & rstack)960 m_constant_fold(pIIR_Expression e, RegionStack &rstack)
961 {
962 return 0;
963 }
964
965
966 int
m_constant_fold(pIIR_Allocator a,RegionStack & rstack)967 m_constant_fold(pIIR_Allocator a, RegionStack &rstack)
968 {
969 if (done(a) & CONST_FOLD) return 0; else done(a) |= CONST_FOLD;
970
971 int error_count = constant_fold(a->type_mark, rstack);
972 if (a->value != NULL)
973 error_count += constant_fold(a->value, rstack);
974
975 return error_count;
976 }
977
978
979 int
m_constant_fold(pIIR_ExpressionList el,RegionStack & rstack)980 m_constant_fold(pIIR_ExpressionList el, RegionStack &rstack)
981 {
982 if (done(el) & CONST_FOLD) return 0; else done(el) |= CONST_FOLD;
983
984 int error_count = 0;
985 for ( ; el; el = el->rest)
986 error_count += constant_fold(el->first, rstack);
987
988 return error_count;
989 }
990
991
992
993 int
m_constant_fold(pIIR_ArrayAggregate aa,RegionStack & rstack)994 m_constant_fold (pIIR_ArrayAggregate aa, RegionStack &rstack)
995 {
996 if (done(aa) & CONST_FOLD) return 0; else done(aa) |= CONST_FOLD;
997
998 int error_count = 0;
999 // First, determine context of asscociations
1000 for (pIIR_IndexedAssociationList al = aa->indexed_association_list; al; al = al->rest)
1001 error_count += constant_fold(al->first, rstack);
1002
1003 return error_count;
1004 }
1005
1006
1007 int
m_constant_fold(pIIR_RecordAggregate ra,RegionStack & rstack)1008 m_constant_fold (pIIR_RecordAggregate ra, RegionStack &rstack)
1009 {
1010 if (done(ra) & CONST_FOLD) return 0; else done(ra) |= CONST_FOLD;
1011
1012 int error_count = 0;
1013 // First, determine context of asscociations
1014 for (pIIR_ElementAssociationList al = ra->element_association_list; al; al = al->rest)
1015 error_count += constant_fold(al->first->value, rstack);
1016
1017 return error_count;
1018 }
1019
1020
1021 int
m_constant_fold(pIIR_AttrArrayFunc aa,RegionStack & rstack)1022 m_constant_fold (pIIR_AttrArrayFunc aa, RegionStack &rstack)
1023 {
1024 if (done(aa) & CONST_FOLD) return 0; else done(aa) |= CONST_FOLD;
1025
1026 int error_count = 0;
1027 vector<RangeDescriptor> range_des_vec;
1028
1029 if (aa->array != NULL) {
1030 if (!is_constrained_array_type(aa->array->subtype)) return error_count;
1031 // Get range descriptors from array object
1032 range_des_vec = get_discrete_range(aa->array->subtype, rstack, IR_NOT_STATIC);
1033
1034 } else if (aa->array_type != NULL) {
1035 if (!is_constrained_array_type(aa->array_type)) return error_count;
1036 // Get range descriptors from array type
1037 range_des_vec = get_discrete_range(aa->array_type, rstack, IR_NOT_STATIC);
1038
1039 } else
1040 assert(false);
1041
1042 // Constant fold corresponding range descriptor
1043 RangeDescriptor &range_des = range_des_vec[aa->index - 1];
1044 range_des.constant_fold_rangedes(rstack);
1045 StaticRangeDescriptor<lint, IR_Direction> range =
1046 range_des.rangedes_to_lint(rstack);
1047
1048 // Initialize flag
1049 valid_folded_value(aa) = false;
1050
1051 // Check attribute
1052 if (aa->is(IR_ATTR_ARRAY_LENGTH)) {
1053 if (and_reduce(range.valid)) {
1054 folded_value(aa).long_value() =
1055 (range.left <= range.right && range.dir == IR_DIRECTION_UP) ||
1056 (range.left >= range.right && range.dir == IR_DIRECTION_DOWN) ?
1057 lint_abs(range.right - range.left) + 1 : 0;
1058 valid_folded_value(aa) = true;
1059 }
1060
1061 } else if (aa->is(IR_ATTR_ARRAY_ASCENDING)) {
1062 if (range.valid[1]) {
1063 folded_value(aa).long_value() = range.dir == IR_DIRECTION_UP? 1 : 0;
1064 valid_folded_value(aa) = true;
1065 }
1066
1067 } else if (aa->is(IR_ATTR_ARRAY_LOW)) {
1068 if (and_reduce(range.valid)) {
1069 folded_value(aa).long_value() = min (range.left, range.right);
1070 valid_folded_value(aa) = true;
1071 }
1072
1073 } else if (aa->is(IR_ATTR_ARRAY_HIGH)) {
1074 if (and_reduce(range.valid)) {
1075 folded_value(aa).long_value() = max (range.left, range.right);
1076 valid_folded_value(aa) = true;
1077 }
1078
1079 } else if (aa->is(IR_ATTR_ARRAY_RIGHT)) {
1080 if (range.valid[2]) {
1081 folded_value(aa).long_value() = range.right;
1082 valid_folded_value(aa) = true;
1083 }
1084
1085 } else if (aa->is(IR_ATTR_ARRAY_LEFT)) {
1086 if (range.valid[0]) {
1087 folded_value(aa).long_value() = range.left;
1088 valid_folded_value(aa) = true;
1089 }
1090
1091 } else
1092 assert(false);
1093
1094 return error_count;
1095 }
1096
1097
1098
1099 int
m_constant_fold(pIIR_AttrTypeFunc a,RegionStack & rstack)1100 m_constant_fold (pIIR_AttrTypeFunc a, RegionStack &rstack)
1101 {
1102 int error_count = 0;
1103 vector<RangeDescriptor> type_range_des;
1104 StaticRangeDescriptor<lint, IR_Direction> static_lint_range;
1105 StaticRangeDescriptor<double, IR_Direction> static_double_range;
1106
1107 pIIR_Root left_bound_node, right_bound_node;
1108
1109 if (a->prefix != NULL) {
1110 // Determine range of prefix type
1111 type_range_des = get_discrete_range(a->prefix, rstack, IR_NOT_STATIC);
1112 // type_range_des should contain exactly one single
1113 // RangeDescriptor instance
1114 assert(type_range_des.size() == 1);
1115 left_bound_node = type_range_des[0].left;
1116 right_bound_node = type_range_des[0].right;
1117 // Try to fold range descriptor
1118 type_range_des[0].constant_fold_rangedes(rstack);
1119 if (get_base_type (a->prefix)-> is (IR_FLOATING_TYPE))
1120 {
1121 // Determine left, right and direction of range. is_static stores
1122 // whether the corresponding value is static.
1123 static_double_range = type_range_des[0].rangedes_to_double (rstack);
1124 // if neither left or right bound nor the direction are static
1125 // then do not perform any constant folding because no range
1126 // checking can be done at compile time.
1127 if (!or_reduce(static_double_range.valid))
1128 return error_count;
1129 }
1130 else
1131 {
1132 // Determine left, right and direction of range. is_static stores
1133 // whether the corresponding value is static.
1134 static_lint_range = type_range_des[0].rangedes_to_lint (rstack);
1135 // if neither left or right bound nor the direction are static
1136 // then do not perform any constant folding because no range
1137 // checking can be done at compile time.
1138 if (!or_reduce(static_lint_range.valid))
1139 return error_count;
1140 }
1141 }
1142
1143 // Fold argument
1144 if (a->argument != NULL)
1145 constant_fold(a->argument, rstack);
1146 // Return if the argument is not locally static
1147 if (a->argument != NULL && !valid_folded_value(a->argument))
1148 return error_count;
1149
1150 // Determine argument value and store whether the argument is an
1151 // integer/enumeration/physical or floating point type
1152 lint lint_argument;
1153 double double_argument;
1154 bool has_long_argument;
1155 bool has_no_argument = true;
1156 if (a->argument != NULL) {
1157 pIIR_Type type = get_base_type(a->argument->subtype);
1158 has_no_argument = false;
1159 if (type->is(IR_INTEGER_TYPE) ||
1160 type->is(IR_ENUMERATION_TYPE) ||
1161 type->is(IR_PHYSICAL_TYPE)) {
1162 lint_argument = folded_value(a->argument).long_value();
1163 has_long_argument = true;
1164
1165 } else if (type->is(IR_FLOATING_TYPE)) {
1166 double_argument = folded_value(a->argument).double_value();
1167 has_long_argument = false;
1168
1169 } else {
1170 cerr << "unsupported argtype: " << type->base->kind_name () << "\n";
1171 assert(false);
1172 }
1173 }
1174
1175
1176 // Bail out if the attribute is used on an illegal type
1177 if (!has_long_argument &&
1178 (a->is(IR_ATTR_RIGHTOF) ||
1179 a->is(IR_ATTR_LEFTOF) ||
1180 a->is(IR_ATTR_VAL) ||
1181 a->is(IR_ATTR_POS) ||
1182 a->is(IR_ATTR_SUCC) ||
1183 a->is(IR_ATTR_PRED) ||
1184 a->is(IR_ATTR_LEFTOF) ||
1185 a->is(IR_ATTR_RIGHTOF)
1186 )) {
1187 codegen_error.error("%:error: attribute %n is not defined for floating point types.", a, a);
1188 return ++error_count;
1189 }
1190
1191
1192 // Finally, handle the various attributes
1193 // ***** RIGHTOF *******************************************
1194 // Note that this attribute is not defined for floatingpoint types
1195 if (a->is(IR_ATTR_RIGHTOF)) {
1196 folded_value(a).long_value() =
1197 lint_argument + (static_lint_range.dir == IR_DIRECTION_UP? +1 : -1);
1198 // Check result
1199 if (static_lint_range.dir == IR_DIRECTION_DOWN)
1200 if (!static_lint_range.valid[0])
1201 // Return if we cannot range check the result
1202 return error_count;
1203 else if (folded_value(a).long_value() < static_lint_range.left) {
1204 codegen_error.error("%:error: result of attribute %n is out of bounds. Left bound of type %n is %n.",
1205 a, a, a->prefix, left_bound_node);
1206 return ++error_count;
1207 }
1208
1209 if (static_lint_range.dir == IR_DIRECTION_UP)
1210 if (!static_lint_range.valid[2])
1211 // Return if we cannot range check the result
1212 return error_count;
1213 else if (folded_value(a).long_value() > static_lint_range.right) {
1214 codegen_error.error("%:error: result of attribute %n is out of bounds. Right bound of type %n is %n.",
1215 a, a, a->prefix, right_bound_node);
1216 return ++error_count;
1217 }
1218
1219 valid_folded_value(a) = true;
1220
1221 // ***** LEFTOF *******************************************
1222 // Note that this attribute is not defined for floatingpoint types
1223 } else if (a->is(IR_ATTR_LEFTOF)) {
1224 folded_value(a).long_value() = lint_argument - (static_lint_range.dir == IR_DIRECTION_UP? +1 : -1);
1225 // Check result
1226 if (static_lint_range.dir == IR_DIRECTION_UP)
1227 if (!static_lint_range.valid[2])
1228 // Return if we cannot range check the result
1229 return error_count;
1230 else if (folded_value(a).long_value() < static_lint_range.left) {
1231 codegen_error.error("%:error: result of attribute %n is out of bounds. Left bound of type %n is %n.",
1232 a, a, a->prefix, left_bound_node);
1233 return ++error_count;
1234 }
1235
1236 if (static_lint_range.dir == IR_DIRECTION_DOWN)
1237 if (!static_lint_range.valid[0])
1238 // Return if we cannot range check the result
1239 return error_count;
1240 else if (folded_value(a).long_value() > static_lint_range.right) {
1241 codegen_error.error("%:error: result of attribute %n is out of bounds. Right bound of type %n is %n.",
1242 a, a, a->prefix, right_bound_node);
1243 return ++error_count;
1244 }
1245
1246 valid_folded_value(a) = true;
1247
1248 // ***** PRED *******************************************
1249 // Note that this attribute is not defined for floatingpoint types
1250 } else if (a->is(IR_ATTR_PRED)) {
1251 folded_value(a).long_value() = lint_argument - 1;
1252 // Check result
1253 if (!static_lint_range.valid[0])
1254 // Return if we cannot range check the result
1255 return error_count;
1256
1257 if (folded_value(a).long_value() < static_lint_range.left) {
1258 codegen_error.error("%:error: result of attribute %n is out of bound. Left bound of type %n is %n.",
1259 a, a, a->prefix, right_bound_node);
1260 return ++error_count;
1261 }
1262
1263 valid_folded_value(a) = true;
1264
1265 // ***** SUCC *******************************************
1266 // Note that this attribute is not defined for floatingpoint types
1267 } else if (a->is(IR_ATTR_SUCC)) {
1268 folded_value(a).long_value() = lint_argument + 1;
1269 // Check result
1270 if (!static_lint_range.valid[2])
1271 // Return if we cannot range check the result
1272 return error_count;
1273
1274 if (folded_value(a).long_value() > static_lint_range.right) {
1275 codegen_error.error("%:error: result of attribute %n is out of bound. Right bound of type %n is %n.",
1276 a, a, a->prefix, right_bound_node);
1277 return ++error_count;
1278 }
1279
1280 valid_folded_value(a) = true;
1281
1282 // ***** VAL *******************************************
1283 // Note that this attribute is not defined for floatingpoint types
1284 } else if (a->is(IR_ATTR_VAL)) {
1285 folded_value(a).long_value() = lint_argument;
1286 // Check result
1287 if (!static_lint_range.valid[2] ||
1288 !static_lint_range.valid[0])
1289 // Return if we cannot range check the result
1290 return error_count;
1291 else if (folded_value(a).long_value() < static_lint_range.left) {
1292 codegen_error.error("%:error: result of attribute %n is out of bounds. Left bound of type %n is %n.",
1293 a, a, a->prefix, left_bound_node);
1294 return ++error_count;
1295 } else if (folded_value(a).long_value() > static_lint_range.right) {
1296 codegen_error.error("%:error: result of attribute %n is out of bounds. Right bound of type %n is %n.",
1297 a, a, a->prefix, right_bound_node);
1298 return ++error_count;
1299 }
1300 valid_folded_value(a) = true;
1301
1302 // ***** POS *******************************************
1303 // Note that this attribute is not defined for floatingpoint types
1304 } else if (a->is(IR_ATTR_POS)) {
1305 folded_value(a).long_value() = lint_argument;
1306 valid_folded_value(a) = true;
1307
1308 // ***** VALUE *******************************************
1309 } else if (a->is(IR_ATTR_VALUE)) {
1310 // The VALUE attribute is not folded
1311 return error_count;
1312
1313 // ***** IMAGE *******************************************
1314 } else if (a->is(IR_ATTR_IMAGE)) {
1315 // The IMAGE attribute is not folded
1316 return error_count;
1317
1318 } else
1319 assert(false);
1320
1321 return error_count;
1322 }
1323
1324
1325
1326 int
m_constant_fold(pIIR_AttrTypeValue a,RegionStack & rstack)1327 m_constant_fold (pIIR_AttrTypeValue a, RegionStack &rstack)
1328 {
1329 int error_count = 0;
1330 vector<RangeDescriptor> type_range_des;
1331 StaticRangeDescriptor<lint, IR_Direction> static_lint_range;
1332 StaticRangeDescriptor<double, IR_Direction> static_double_range;
1333 bool is_floatingpoint_type = false;
1334
1335 if (a->prefix != NULL) {
1336 // Determine range of prefix type
1337 type_range_des = get_discrete_range(a->prefix, rstack, IR_NOT_STATIC);
1338 // type_range_des should contain exactly one single
1339 // RangeDescriptor instance
1340 assert(type_range_des.size() == 1);
1341 // Try to fold range descriptor
1342 type_range_des[0].constant_fold_rangedes(rstack);
1343 // Determine left, right and direction of range. is_static stores
1344 // whether the corresponding value is static.
1345 if (get_base_type (a->prefix)->is (IR_FLOATING_TYPE))
1346 {
1347 static_double_range = type_range_des[0].rangedes_to_double (rstack);
1348 // if neither left or right bound nor the direction are static
1349 // then do not perform any constant folding because no range
1350 // checking can be done at compile time.
1351 is_floatingpoint_type = true;
1352 if (!or_reduce(static_double_range.valid))
1353 return error_count;
1354 }
1355 else
1356 {
1357 static_lint_range = type_range_des[0].rangedes_to_lint (rstack);
1358 // if neither left or right bound nor the direction are static
1359 // then do not perform any constant folding because no range
1360 // checking can be done at compile time.
1361 is_floatingpoint_type = false;
1362 if (!or_reduce(static_lint_range.valid))
1363 return error_count;
1364 }
1365 }
1366
1367 // Fold argument
1368 if (a->argument != NULL)
1369 constant_fold(a->argument, rstack);
1370 // Return if the argument is not locally static
1371 if (a->argument != NULL && !valid_folded_value(a->argument))
1372 return error_count;
1373
1374 // Determine argument value and store whether the argument is an
1375 // integer/enumeration/physical or floating point type
1376 lint lint_argument;
1377 double double_argument;
1378 bool has_long_argument;
1379 bool has_no_argument = true;
1380 if (a->argument != NULL) {
1381 pIIR_Type type = get_base_type(a->argument->subtype);
1382 has_no_argument = false;
1383 if (type->is(IR_INTEGER_TYPE) ||
1384 type->is(IR_ENUMERATION_TYPE) ||
1385 type->is(IR_PHYSICAL_TYPE)) {
1386 lint_argument = folded_value(a->argument).long_value();
1387 has_long_argument = true;
1388
1389 } else if (type->is(IR_FLOATING_TYPE)) {
1390 double_argument = folded_value(a->argument).double_value();
1391 has_long_argument = false;
1392
1393 } else
1394 assert(false);
1395 }
1396
1397 // Create shortcut to access valid array.
1398 vector<bool> &valid = is_floatingpoint_type?
1399 static_double_range.valid : static_lint_range.valid;
1400
1401 // Finally, handle the various attributes
1402 // ***** LENGTH *******************************************
1403 if (a->is(IR_ATTR_LENGTH)) {
1404 // Actually, this attribute is defined for arrays only!
1405 assert(false);
1406
1407 // ***** ASCENDING *******************************************
1408 } else if (a->is(IR_ATTR_ASCENDING)) {
1409 if (!valid[1])
1410 // Return if direction is not static
1411 return error_count;
1412
1413 if (is_floatingpoint_type)
1414 folded_value(a).double_value() = static_double_range.dir == IR_DIRECTION_UP? 1 : 0;
1415 else
1416 folded_value(a).long_value() = static_lint_range.dir == IR_DIRECTION_UP? 1 : 0;
1417 valid_folded_value(a) = true;
1418
1419 // ***** HIGH *******************************************
1420 } else if (a->is(IR_ATTR_HIGH)) {
1421 if (!valid[2] ||
1422 !valid[0])
1423 // Return if bound is not static
1424 return error_count;
1425
1426 if (is_floatingpoint_type)
1427 folded_value(a).double_value() = max(static_double_range.right, static_double_range.left);
1428 else
1429 folded_value(a).long_value() = max(static_lint_range.right, static_lint_range.left);
1430 valid_folded_value(a) = true;
1431
1432 // ***** LOW *******************************************
1433 } else if (a->is(IR_ATTR_LOW)) {
1434 if (!valid[2] ||
1435 !valid[0])
1436 // Return if bound is not static
1437 return error_count;
1438
1439 if (is_floatingpoint_type)
1440 folded_value(a).double_value() = min(static_double_range.right, static_double_range.left);
1441 else
1442 folded_value(a).long_value() = min(static_lint_range.right, static_lint_range.left);
1443 valid_folded_value(a) = true;
1444
1445 // ***** RIGHT *******************************************
1446 } else if (a->is(IR_ATTR_RIGHT)) {
1447 if (!valid[2])
1448 // Return if bound is not static
1449 return error_count;
1450
1451 if (is_floatingpoint_type)
1452 folded_value(a).double_value() = static_double_range.right;
1453 else
1454 folded_value(a).long_value() = static_lint_range.right;
1455 valid_folded_value(a) = true;
1456
1457 // ***** LEFT *******************************************
1458 } else if (a->is(IR_ATTR_LEFT)) {
1459 if (!valid[0])
1460 // Return if bound is not static
1461 return error_count;
1462
1463 if (is_floatingpoint_type)
1464 folded_value(a).double_value() = static_double_range.left;
1465 else
1466 folded_value(a).long_value() = static_lint_range.left;
1467 valid_folded_value(a) = true;
1468
1469 } else
1470 assert(false);
1471
1472 return error_count;
1473 }
1474
1475
1476 int
m_constant_fold(pIIR_TypeConversion tc,RegionStack & rstack)1477 m_constant_fold (pIIR_TypeConversion tc, RegionStack &rstack)
1478 {
1479 int error_count = 0;
1480
1481 error_count += constant_fold(tc->expression, rstack);
1482 // Return if an error occured during constant folding of the operand
1483 // or no valid folded value could be determined for the operand or
1484 // the operand is not scalar.
1485 if (error_count != 0 ||
1486 !valid_folded_value(tc->expression) ||
1487 !is_scalar_type(tc->expression->subtype))
1488 return error_count;
1489 // Determine converted value
1490 pIIR_Type target_base_type = get_base_type(tc->type_mark);
1491 pIIR_Type source_base_type = get_base_type(tc->expression->subtype);
1492
1493 if (target_base_type->is(IR_FLOATING_TYPE) &&
1494 source_base_type->is(IR_INTEGER_TYPE)) {
1495 folded_value(tc).double_value() = (double)folded_value(tc->expression).long_value();
1496 // Check whether
1497 error_count += check_scalar_against_bounds(tc, folded_value(tc).double_value(), tc->type_mark,
1498 rstack, runtime_checks(tc), true, " illegal type conversion:" );
1499
1500 } else if (source_base_type->is(IR_FLOATING_TYPE) &&
1501 target_base_type->is(IR_INTEGER_TYPE)) {
1502 folded_value(tc).long_value() = (lint)rint(folded_value(tc->expression).double_value());
1503 error_count += check_scalar_against_bounds(tc, folded_value(tc).long_value(), tc->type_mark,
1504 rstack, runtime_checks(tc), true, " illegal type conversion:" );
1505
1506 } else if (target_base_type->is(IR_FLOATING_TYPE) &&
1507 source_base_type->is(IR_FLOATING_TYPE)) {
1508 folded_value(tc).double_value() = folded_value(tc->expression).double_value();
1509 error_count += check_scalar_against_bounds(tc, folded_value(tc).double_value(), tc->type_mark,
1510 rstack, runtime_checks(tc), true, " illegal type conversion:" );
1511
1512 } else {
1513 folded_value(tc).long_value() = folded_value(tc->expression).long_value();
1514 error_count += check_scalar_against_bounds(tc, folded_value(tc).long_value(), tc->type_mark,
1515 rstack, runtime_checks(tc), true, " illegal type conversion:" );
1516
1517 }
1518
1519 valid_folded_value(tc) = (error_count == 0);
1520
1521 return error_count;
1522 }
1523