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