1 #if HAVE_ALLOCA_H
2 #include <alloca.h>
3 #endif
4 #include <algorithm>
5 #include <stdlib.h>
6 #include <ctype.h>
7 #if HAVE_MALLOC_H
8 #include <malloc.h>
9 #endif
10 #if HAVE_UNISTD_H
11 #include <unistd.h>
12 #endif
13 #include <limits.h>
14 
15 #include <freehdl/vaul.h>
16 #include "v2cc-chunk.h"
17 #include "mapping.h"
18 #include "v2cc-util.h"
19 
20 
21 // used to generate error messages
22 extern vaul_error_printer codegen_error;
23 
24 string sprint_acl(list<string> &acl_list, const string acl_object);
25 
26 
27 // ******************************************************************************************
28 // Singleton Class VHDLOperators
29 // ******************************************************************************************
30 
31 VHDLOperators* VHDLOperators::single_instance = NULL;
32 
33 void
init_operator_macros()34 VHDLOperators::init_operator_macros()
35 {
36   // Add uniary operator macros
37   unary_operator_macro["\"not\""] = "op_not(%s)";
38   unary_operator_macro["\"+\""] = "(+%s)";
39   unary_operator_macro["\"-\""] = "(-%s)";
40   unary_operator_macro["\"abs\""] = "op_abs(%s)";
41 
42   // Add binary operator macros
43   binary_operator_macro["\"and\""] = "(%s&&%s)";
44   binary_operator_macro["\"or\""] = "(%s||%s)";
45   binary_operator_macro["\"xor\""] = "op_xor(%s,%s)";
46   binary_operator_macro["\"xnor\""] = "op_xnor(%s,%s)";
47   binary_operator_macro["\"nand\""] = "op_nand(%s,%s)";
48   binary_operator_macro["\"nor\""] = "op_nor(%s,%s)";
49   binary_operator_macro["\"=\""] = "(%s==%s)";
50   binary_operator_macro["\">\""] = "(%s>%s)";
51   binary_operator_macro["\">=\""] = "(%s>=%s)";
52   binary_operator_macro["\"<\""] = "(%s<%s)";
53   binary_operator_macro["\"<=\""] = "(%s<=%s)";
54   binary_operator_macro["\"/=\""] = "(%s!=%s)";
55   binary_operator_macro["\"+\""] = "(%s+%s)";
56   binary_operator_macro["\"-\""] = "(%s-%s)";
57   binary_operator_macro["\"/\""] = "(%s/%s)";
58   binary_operator_macro["\"*\""] = "(%s*%s)";
59   binary_operator_macro["\"mod\""] = "op_mod(%s,%s)";
60   binary_operator_macro["\"rem\""] = "(%s%%%s)";
61   binary_operator_macro["\"**\""] = "op_power(%s,%s)";
62   binary_operator_macro["\"&\""] = "concat";
63 }
64 
65 
66 void
init_array_operator_macros()67 VHDLOperators::init_array_operator_macros()
68 {
69   // Add uniary operator macros
70   unary_array_operator_macro["\"not\""] = "op_array_not(%s)";
71 
72   // Add binary operator macros
73   binary_array_operator_macro["\"and\""] = "op_array_and(%s,%s)";
74   binary_array_operator_macro["\"or\""] = "op_array_or(%s,%s)";
75   binary_array_operator_macro["\"xor\""] = "op_array_xor(%s,%s)";
76   binary_array_operator_macro["\"xnor\""] = "op_array_xnor(%s,%s)";
77   binary_array_operator_macro["\"nand\""] = "op_array_nand(%s,%s)";
78   binary_array_operator_macro["\"nor\""] = "op_array_nor(%s,%s)";
79   binary_array_operator_macro["\"=\""] = "(%s==%s)";
80   binary_array_operator_macro["\">\""] = "(!op_array_lt(%s,%s))";
81   binary_array_operator_macro["\">=\""] = "(!op_array_le(%s,%s))";
82   binary_array_operator_macro["\"<\""] = "op_array_lt(%s,%s)";
83   binary_array_operator_macro["\"<=\""] = "op_array_le(%s,%s)";
84   binary_array_operator_macro["\"/=\""] = "(!(%s==%s))";
85   binary_array_operator_macro["\"&\""] = "concat";
86 
87   binary_array_operator_macro["\"sll\""] = "op_array_sll(%s,%s)";
88   binary_array_operator_macro["\"srl\""] = "op_array_srl(%s,%s)";
89   binary_array_operator_macro["\"sla\""] = "op_array_sla(%s,%s)";
90   binary_array_operator_macro["\"sra\""] = "op_array_sra(%s,%s)";
91   binary_array_operator_macro["\"rol\""] = "op_array_rol(%s,%s)";
92   binary_array_operator_macro["\"ror\""] = "op_array_ror(%s,%s)";
93 }
94 
95 
96 void
init_user_operator_names()97 VHDLOperators::init_user_operator_names()
98 {
99   // Add uniary operator macros
100   unary_user_operator_name["\"not\""] = "op_not";
101   unary_user_operator_name["\"+\""] = "op_plus";
102   unary_user_operator_name["\"-\""] = "op_minus";
103   unary_user_operator_name["\"abs\""] = "op_abs";
104 
105   // Add binary operator names
106   binary_user_operator_name["\"and\""] = "op_and";
107   binary_user_operator_name["\"or\""] = "op_or";
108   binary_user_operator_name["\"xor\""] = "op_xor";
109   binary_user_operator_name["\"xnor\""] = "op_xnor";
110   binary_user_operator_name["\"nand\""] = "op_nand";
111   binary_user_operator_name["\"nor\""] = "op_nor";
112   binary_user_operator_name["\"=\""] = "op_eq";
113   binary_user_operator_name["\">\""] = "op_gt";
114   binary_user_operator_name["\">=\""] = "op_ge";
115   binary_user_operator_name["\"<\""] = "op_lt";
116   binary_user_operator_name["\"<=\""] = "op_le";
117   binary_user_operator_name["\"/=\""] = "op_ne";
118   binary_user_operator_name["\"+\""] = "op_plus";
119   binary_user_operator_name["\"-\""] = "op_minus";
120   binary_user_operator_name["\"/\""] = "op_div";
121   binary_user_operator_name["\"*\""] = "op_mult";
122   binary_user_operator_name["\"mod\""] = "op_mod";
123   binary_user_operator_name["\"rem\""] = "op_rem";
124   binary_user_operator_name["\"**\""] = "op_power";
125   binary_user_operator_name["\"&\""] = "op_concat";
126 
127   binary_user_operator_name["\"sll\""] = "op_sll";
128   binary_user_operator_name["\"srl\""] = "op_srl";
129   binary_user_operator_name["\"sla\""] = "op_sla";
130   binary_user_operator_name["\"sra\""] = "op_sra";
131   binary_user_operator_name["\"rol\""] = "op_rol";
132   binary_user_operator_name["\"ror\""] = "op_ror";
133 }
134 
135 /* Get unary operator name string */
get_unary_user_operator_name(const string & str)136 string VHDLOperators::get_unary_user_operator_name (const string &str)
137 {
138   return unary_user_operator_name [str];
139 }
140 
141 /* Get unary operator name string */
get_binary_user_operator_name(const string & str)142 string VHDLOperators::get_binary_user_operator_name (const string &str)
143 {
144   return binary_user_operator_name [str];
145 }
146 
147 /* Generate string for a call to a binary operator */
148 string
get_operator_call_string(pIIR_FunctionDeclaration fd,const string arg1,const string arg2)149 VHDLOperators::get_operator_call_string(pIIR_FunctionDeclaration fd, const string arg1, const string arg2)
150 {
151   string macro;
152   if (is_array_type(fd->interface_declarations->first->subtype))
153     macro = binary_array_operator_macro[fd->declarator->text.to_chars()];
154   else
155     macro = binary_operator_macro[fd->declarator->text.to_chars()];
156 
157   int size = macro.length() + arg1.length() + arg2.length() + 1; // Actually "size" is an upper bound
158 #ifdef HAVE_ALLOCA
159   char *str = (char*)alloca (sizeof(char)*size);
160 #else
161   char *str = (char*)malloc (sizeof(char)*size);
162 #endif
163   sprintf(str, macro.c_str(), arg1.c_str(), arg2.c_str());
164 
165   string result = str;
166 
167 #ifndef HAVE_ALLOCA
168   free (str);
169 #endif
170 
171   return result;
172 }
173 
174 
175 /* Generate string for a call to a unary operator */
176 string
get_operator_call_string(pIIR_FunctionDeclaration fd,const string arg1)177 VHDLOperators::get_operator_call_string(pIIR_FunctionDeclaration fd, const string arg1)
178 {
179   string macro;
180   if (is_array_type(fd->interface_declarations->first->subtype))
181     macro = unary_array_operator_macro[fd->declarator->text.to_chars()];
182   else
183     macro = unary_operator_macro[fd->declarator->text.to_chars()];
184 
185   int size = macro.length() + arg1.length() + 1; // Actually "size" is an upper bound
186 #ifdef HAVE_ALLOCA
187   char *str = (char*)alloca (sizeof(char)*size);
188 #else
189   char *str = (char*)malloc (sizeof(char)*size);
190 #endif
191   sprintf(str, macro.c_str(), arg1.c_str());
192 
193   string result = str;
194 
195 #ifndef HAVE_ALLOCA
196   free (str);
197 #endif
198 
199   return result;
200 }
201 
202 
203 // Generated code to concat two arrays
204 string
get_concat_operator_call_string(pIIR_FunctionCall fc,string & arg1,string & arg2,RegionStack & rstack)205 VHDLOperators::get_concat_operator_call_string(pIIR_FunctionCall fc, string &arg1, string &arg2, RegionStack &rstack)
206 {
207  pIIR_Expression arg_exp1 = fc->parameter_association_list->first->actual;
208  pIIR_Expression arg_exp2 = fc->parameter_association_list->rest->first->actual;
209 
210  pIIR_ArrayType dest_type = (pIIR_ArrayType)get_base_type(fc->subtype);
211  pIIR_Type arg_type1 = get_base_type(arg_exp1->subtype);
212  pIIR_Type arg_type2 = get_base_type(arg_exp2->subtype);
213 
214  // Determine range of the destination array
215  vector<RangeDescriptor> range_desc =
216    get_discrete_range (((pIIR_ScalarSubtype)(dest_type->index_types->first))->range, rstack, IR_NOT_STATIC);
217  // Convert to integer strings
218  StaticRangeDescriptor<string, string> range =
219    range_desc[0].rangedes_to_string(rstack, get_default_id_type(rstack));
220 
221  // First, convert the arguments into appropriate array objects if
222  // required
223  if (dest_type != arg_type1) {
224    // First argument is an element of the resulting array.  Create
225    // index range for an array consisting of one single element
226    string range_str = range.left + "," + range.dir + "," + range.left;
227    // Create call to array consructor. The second constructor argument
228    // is a the element value. The first argument is an array_info
229    // instance.
230    arg1 = qid(dest_type->declaration, rstack, TYPE) + "(new array_info(" +
231      qid(dest_type->declaration, rstack, INFO) + "_INFO.element_type," +
232      qid(dest_type->declaration, rstack, INFO) + "_INFO.index_type," +
233      range_str + ",0)," + arg1 + ")";
234  }
235  if (dest_type != arg_type2) {
236    // Second argument is an element of the resulting array.  Create
237    // index range for an array consisting of one single element
238    string range_str = range.left + "," + range.dir + "," + range.left;
239    // Create call to array consructor. The second constructor argument
240    // is a the element value. The first argument is an array_info
241    // instance.
242    arg2= qid(dest_type->declaration, rstack, TYPE) + "(new array_info(" +
243      qid(dest_type->declaration, rstack, INFO) + "_INFO.element_type," +
244      qid(dest_type->declaration, rstack, INFO) + "_INFO.index_type," +
245      range_str + ",0)," + arg2 + ")";
246  }
247 
248  string str = "concat<" + qid(dest_type->declaration, rstack, TYPE) + "," +
249    qid(dest_type->element_type->declaration, rstack, TYPE)+ ">(" + arg1 + "," + arg2 + ")";
250 
251  return str;
252 }
253 
254 /* Test whether operator name denotes contat operator */
is_concat_operator(const string & str)255 bool VHDLOperators::is_concat_operator (const string &str)
256 {
257   return binary_operator_macro[str] == "concat";
258 }
259 
260 
VHDLOperators()261 VHDLOperators::VHDLOperators ()
262 {
263   init_operator_macros();
264   init_array_operator_macros();
265   init_user_operator_names();
266 }
267 
get_instance()268 VHDLOperators* VHDLOperators::get_instance ()
269 {
270   if (single_instance == NULL)
271     {
272       single_instance = new VHDLOperators;
273     }
274   return single_instance;
275 }
276 
277 
278 
279 // ******************************************************************************************
280 
281 
282 bool
m_emit_expr(pIIR_AttrSigFunc af,string & str,RegionStack & rstack,id_type t)283 m_emit_expr (pIIR_AttrSigFunc af, string &str, RegionStack &rstack, id_type t)
284 {
285   string scalar_function_name, composite_function_name;
286 
287   // First, determine attribute kind
288   if (af->is(IR_ATTR_EVENT)) {
289     // Attribute: EVENT
290     scalar_function_name = "attr_scalar_EVENT";
291     composite_function_name = "attr_composite_EVENT";
292 
293   } else if (af->is(IR_ATTR_ACTIVE)) {
294     // Attribute: ACTIVE
295     scalar_function_name = "attr_scalar_ACTIVE";
296     composite_function_name = "attr_composite_ACTIVE";
297 
298   } else if (af->is(IR_ATTR_LAST_VALUE)) {
299     // Attribute: LAST_VALUE
300     scalar_function_name = "attr_scalar_LAST_VALUE<" +
301       qid(get_declaration(af->subtype), rstack, TYPE) + ">";
302     composite_function_name = "attr_composite_LAST_VALUE<" +
303       qid(get_declaration(af->subtype), rstack, TYPE) + ">";;
304 
305   } else if (af->is(IR_ATTR_LAST_EVENT)) {
306     // Attribute: LAST_EVENT
307     scalar_function_name = "attr_scalar_LAST_EVENT";
308     composite_function_name = "attr_composite_LAST_EVENT";
309 
310   } else
311     // else bail out!
312     codegen_error.error("%:error: sorry, this attribute is currently not supported", af);
313 
314 
315   string result;
316   // Next, create attribute code
317   if (af->signal->is(IR_SIMPLE_REFERENCE)) {
318     // Prefix is a scalar signal
319     result += scalar_function_name + "(";
320     emit_expr(af->signal, result, rstack, id_type(SIGNAL, DEFAULT));
321     result += ")";
322 
323   } else {
324     // Prefix is a composite signal
325     result += composite_function_name + "(";
326     // Get object declaration of the prefix signal
327     pIIR_ObjectDeclaration object_decl = get_object_declaration(af->signal);
328     result += qid(object_decl, rstack, SIGNAL);
329 
330     // Append acl
331     list<pair<pIIR_Expression, pIIR_Root> > acl_list;
332     get_acl(af->signal, acl_list, rstack, IR_NOT_STATIC, true);
333     // Create internal acl
334     string internal_acl_name = create_internal_acl(get_acl_size(acl_list), rstack, true);
335     // Add acl sequence
336     if (af->is(IR_ATTR_LAST_VALUE) &&
337 	!is_scalar_type(af->subtype)) {
338       // If the attribute is LAST_VALUE and the result is not scalar
339       // then add a copy of the signal part as an additional parameter
340       result += ",&(" + sprint_acl(acl_list, internal_acl_name + "->clear()", rstack, id_type(SIGNAL, ARCHREF)) + "),";
341       emit_expr(af->signal, result, rstack, id_type(READER, DEREF));
342       result += ")";
343     } else
344       result += ",&(" + sprint_acl(acl_list, internal_acl_name + "->clear()", rstack, id_type(SIGNAL, ARCHREF)) + "))";
345   }
346 
347   str += result;
348 
349   return false;
350 }
351 
352 
353 bool
m_emit_expr(pIIR_AttrArrayFunc at,string & str,RegionStack & rstack,id_type t)354 m_emit_expr (pIIR_AttrArrayFunc at, string &str, RegionStack &rstack, id_type t)
355 {
356   // If the result type is an enumeration type then a cast
357   // operation "enumeration(...)" must be done
358   pIIR_Type type = get_base_type(at->subtype);
359   string cast_start = "", cast_end = "";
360   if (type->is(IR_ENUMERATION_TYPE)) {
361     cast_start = "enumeration(";
362     cast_end = ")";
363   }
364 
365   // First, check whether the attribute was folded successfully.
366   if (valid_folded_value(at)) {
367     // Emit the folded value instead of accessing determining the
368     // attribute at runtime
369     str += cast_start + to_string(folded_value(at).long_value()) + cast_end;
370 
371     return true;
372 
373   } else {
374 
375     string info_instance_str;
376     if (at->array != NULL) {
377       // The range attribute has been applied on an array
378       // instance. First, emit code to extract the info instance from
379       // the array.
380       emit_expr (at->array, info_instance_str, rstack, id_type(READER, DEREF));
381       info_instance_str += ".info";
382 
383     } else
384       // The range attribute has been applied on an array type. Emit
385       // code to reference the range corresponding info instance.
386       info_instance_str += get_type_info_obj(at->array_type, rstack, false);
387 
388     // Get index number
389     int index_number = at->index;
390     // Build code to access the array info instance which
391     // corresponds with the index_number
392     for (int i = 1; i < index_number; i++)
393       info_instance_str = "((array_info*)" + info_instance_str + "->element_type)";
394 
395     // Finally, emit code to determine the attribute code at runtime
396     if (at->is(IR_ATTR_ARRAY_LENGTH))
397       str += info_instance_str + "->length";
398 
399     else if (at->is(IR_ATTR_ARRAY_ASCENDING))
400       str += "enumeration(" + info_instance_str + "->index_direction==to?1:0)";
401 
402     else if (at->is(IR_ATTR_ARRAY_LOW))
403       str += cast_start + "min(" + info_instance_str + "->left_bound," + info_instance_str +
404 	"->right_bound)" + cast_end;
405 
406     else if (at->is(IR_ATTR_ARRAY_HIGH))
407       str += cast_start + "max(" + info_instance_str + "->left_bound," + info_instance_str +
408 	"->right_bound)" + cast_end;
409 
410     else if (at->is(IR_ATTR_ARRAY_RIGHT))
411       str += cast_start + info_instance_str + "->right_bound" + cast_end;
412 
413     else if (at->is(IR_ATTR_ARRAY_LEFT))
414       str += cast_start + info_instance_str + "->left_bound" + cast_end;
415 
416     else
417       assert(false);
418 
419     return false;
420   }
421 }
422 
423 
424 bool
m_emit_expr(pIIR_FunctionCall fc,string & str,RegionStack & rstack,id_type t)425 m_emit_expr (pIIR_FunctionCall fc, string &str, RegionStack &rstack, id_type t)
426 {
427   // If the function call has been folded then return the optimized
428   // result instead of actually emitting the function call
429   if (valid_folded_value(fc)) {
430     emit_folded_value(folded_value(fc), str, rstack, fc->subtype);
431     return true; // Ok, were are done!
432   }
433 
434   VHDLOperators &operators = *VHDLOperators::get_instance ();
435 
436   // count the arguments
437   int n_args = 0;
438   for (pIIR_AssociationList al = fc->parameter_association_list; al; al = al->rest)
439     n_args++;
440 
441   string arg1, arg2;
442   bool int_literal;
443 
444   switch (get_operator_type(fc->function)) { // Analyze function call type
445   case STD_OP: // The function call is a standard operator call
446     // emit first operand
447     int_literal = emit_expr (fc->parameter_association_list->first->actual, arg1,
448 			     rstack, id_type(READER, DEREF)); // First argument
449     //if (int_literal)
450     //arg1 = cast(fc->parameter_association_list->first->actual, arg1);
451 
452     // emit second operand
453     if (n_args == 2) { // Binary operator call
454       int_literal = emit_expr (fc->parameter_association_list->rest->first->actual, arg2,
455 			       rstack, id_type(READER, DEREF)); // Second argument
456       //if (int_literal)
457       //arg2 = cast(fc->parameter_association_list->rest->first->actual, arg2);
458 
459       string call_str;
460       if (operators.is_concat_operator (fc->function->declarator->text.to_chars()))
461 	// Add concat operator call. The concat operator is handled
462 	// differently from the other operators
463 	call_str = operators.get_concat_operator_call_string(fc, arg1, arg2, rstack);
464       else
465 	// Add operator call to code
466 	call_str = operators.get_operator_call_string(fc->function, arg1, arg2);
467 
468       // Next, check whether this is a operator call with mixed
469       // parameter types (e.g., of the form time * integer or time /
470       // real). In this case cast the result to the target type.
471       if (string(fc->function->declarator->text.to_chars()) == "\"*\"" ||
472 	  string(fc->function->declarator->text.to_chars()) == "\"/\"")
473 	{
474 	  pIIR_Type arg1_type = get_base_type (fc->function->interface_declarations->first->subtype);
475 	  pIIR_Type arg2_type = get_base_type (fc->function->interface_declarations->rest->first->subtype);
476 	  if (arg1_type != arg2_type)
477 	    {
478 	      pIIR_Type return_type = get_base_type (fc->function->return_type);
479 	      if (return_type->is (IR_INTEGER_TYPE))
480 		call_str = "integer(" + call_str + ")";
481 	      else if (return_type->is (IR_ENUMERATION_TYPE))
482 		call_str = "enumeration(" + call_str + ")";
483 	      else if (return_type->is (IR_PHYSICAL_TYPE))
484 		call_str = "physical(" + call_str + ")";
485 	      else if (return_type->is (IR_ENUMERATION_TYPE))
486 		call_str = "floatingpoint(" + call_str + ")";
487 	    }
488 	}
489 
490       str += call_str;
491 
492     } else // Unary operator call
493       str += operators.get_operator_call_string(fc->function, arg1); // Add operator call
494 
495     break;
496 
497   case USER_OP: // The function is an user defined operator call
498   case BASIC_OP: // The function is a operator defined in an IEEE
499     // library. Currently this is handled like a user defined operator
500     // call
501   case NO_OP: // A ordinary function call (no operator)
502     void emit_subprogram_associations (string&, RegionStack&, pIIR_AssociationList,
503 				       pIIR_InterfaceList, list<AccessDescriptor>&);
504     str += qid(fc->function, rstack, DEFAULT);
505     str += " (";
506     emit_subprogram_associations (str, rstack, fc->parameter_association_list,
507 				  fc->function->interface_declarations,
508 				  context(fc->function).extra_interface_objects);
509     //emit_associations (str, rstack, fc->parameter_association_list,
510     //		       fc->function->interface_declarations);
511     str += ")";
512   }
513 
514   return false;
515 }
516 
517 bool
m_emit_expr(pIIR_SimpleReference sor,string & str,RegionStack & rstack,id_type t)518 m_emit_expr (pIIR_SimpleReference sor, string &str, RegionStack &rstack, id_type t)
519 {
520   // If the reference has been folded then return the optimized result
521   // instead of accessing the reference
522   if (valid_folded_value(sor)) {
523     emit_folded_value(folded_value(sor), str, rstack, sor->subtype);
524     return true; // Ok, were are done!
525   }
526 
527   //emit_noqual_id (sor->object, str, t);
528   str += qid (sor->object, rstack, t);
529 
530   return false;
531 }
532 
533 
534 bool
m_emit_expr(pIIR_NullExpression ne,string & str,RegionStack & rstack,id_type t)535 m_emit_expr (pIIR_NullExpression ne, string &str, RegionStack &rstack, id_type t)
536 {
537   str += "((vhdlaccess)NULL)";
538   return true;
539 }
540 
541 
542 bool
m_emit_expr(pIIR_Allocator a,string & str,RegionStack & rstack,id_type t)543 m_emit_expr (pIIR_Allocator a, string &str, RegionStack &rstack, id_type t)
544 {
545   str += "(" + get_type_info_obj(pIIR_AccessType(a->type_mark)->designated_type, rstack, false) + ")";
546   if (a->value != NULL) {
547     str += "->clone(const_pointer(";
548     emit_expr(a->value, str, rstack, t);
549     str += "))";
550   } else
551     str += "->create()";
552 
553   return false;
554 }
555 
556 
557 void
emit_lit(pIIR_Literal l,string & str)558 emit_lit (pIIR_Literal l, string &str)
559 {
560   if (l == NULL)
561     str += "1";
562   else if (l->is(IR_TEXT_LITERAL))
563     str += pIIR_TextLiteral(l)->text.to_chars();
564   else if (l->is(IR_INTEGER_LITERAL))
565     str += pIIR_IntegerLiteral(l)->text.to_chars();
566   else if (l->is(IR_FLOATING_POINT_LITERAL))
567     str += pIIR_FloatingPointLiteral(l)->text.to_chars();
568   else
569     str += "<" + string(l->kind_name()) + ">";
570 }
571 
572 
573 /* Emit a physical unit. This done by expressing it in terms of
574    its base unit.
575 */
576 void
emit_unit(pIIR_PhysicalUnit u,string & str,RegionStack & rstack,int l)577 emit_unit (pIIR_PhysicalUnit u, string &str, RegionStack &rstack, int l)
578 {
579   str += qid(u -> type -> declaration, rstack, INFO);
580   str += "::scale[" + to_string ( u -> unit_pos)  + "]";
581 }
582 
583 
584 bool
m_emit_expr(pIIR_AbstractLiteralExpression ale,string & str,RegionStack & rstack,id_type t)585 m_emit_expr (pIIR_AbstractLiteralExpression ale, string &str, RegionStack &rstack, id_type t)
586 {
587   if (ale->is(IR_PHYSICAL_LITERAL)) {
588     if (valid_folded_value(ale)) {
589       str += to_string(folded_value(ale).long_value()) + "LL";
590     } else {
591       assert (false);
592       /* str += "(";
593 	 emit_lit (ale->value, str);
594 	 str += "*";
595 	 emit_unit (pIIR_PhysicalLiteral(ale)->unit, str, rstack, 0);
596 	 str += ")"; */
597     }
598 
599   } else if (valid_folded_value (ale)) {
600     if (ale->value->is(IR_INTEGER_LITERAL))
601       str += to_string (folded_value(ale).long_value ());
602     else if (ale->value->is(IR_FLOATING_POINT_LITERAL))
603       str += (folded_value(ale).original_string () != "") ?
604 	folded_value(ale).original_string () :
605 	to_string (folded_value(ale).double_value ());
606     else
607       abort ();
608   } else
609     assert (false);
610     // emit_lit (ale->value, str);
611 
612   return true;
613 }
614 
615 
616 bool
m_emit_expr(pIIR_TypeConversion tc,string & str,RegionStack & rstack,id_type t)617 m_emit_expr (pIIR_TypeConversion tc, string &str, RegionStack &rstack, id_type t)
618 {
619   if (valid_folded_value(tc)) {
620     // Print folded value if available
621     emit_folded_value(folded_value(tc), str, rstack, tc->type_mark);
622     return true;
623   }
624 
625   pIIR_Type target_base_type = get_base_type(tc->type_mark);
626   pIIR_Declaration target_type_decl = get_declaration(tc->type_mark);
627   string cast_start;
628 
629   string result_str;
630   string expr_str;
631   emit_expr(tc->expression, expr_str, rstack, t);
632 
633   if (target_base_type->is(IR_INTEGER_TYPE))
634     if (get_base_type(tc->expression->subtype)->is(IR_FLOATING_TYPE))
635       // If the the expression to be converted is a floating point
636       // type then we must round the number to the nearest integer
637       // value!
638       result_str += "integer(rint(" + expr_str + "))";
639     else
640       result_str += "integer(" + expr_str + ")";
641 
642   else if (target_base_type->is(IR_ENUMERATION_TYPE))
643     result_str += "enumeration(" + expr_str + ")";
644 
645   else if (target_base_type->is(IR_PHYSICAL_TYPE))
646     result_str += "physical(" + expr_str + ")";
647 
648   else if (target_base_type->is(IR_FLOATING_TYPE))
649     result_str += "floatingpoint(" + expr_str + ")";
650 
651   else if (is_array_type(target_base_type)) {
652     pIIR_ArrayType source_array_base_type =
653       pIIR_ArrayType(get_base_type(tc->expression->subtype));
654     pIIR_ArrayType target_array_base_type = pIIR_ArrayType(target_base_type);
655 
656     // First, considere one-dimensional arrays
657     if (target_array_base_type->index_types->rest == NULL) {
658       // Next, test whether the target array type is constrained
659       if (!is_constrained_array_type(tc->type_mark))
660 	// If the target array is unconstrained then the source
661 	// array is passed over by reference so that the array_alias
662 	// constructor can retrieve the range information from the
663 	// source array. Note that the actual data is not copied but
664 	// reused by the array_alias constructor.
665 	result_str += "array_alias<" + qid(target_type_decl, rstack, TYPE) + " >(" +
666 	  get_type_info_obj(tc->type_mark, rstack, false) + "," + expr_str + ")";
667 
668       else
669 	// If the target array is constrained then the bounds are
670 	// determined from the target type. Note that the data part
671 	// is not copied from the source array. Instead the data
672 	// pointer of the source is copied.
673 	result_str += "array_alias<" + qid(target_type_decl, rstack, TYPE) + " >(" +
674 	  get_type_info_obj(tc->type_mark, rstack, false) + "," + expr_str + ".data)";
675 
676     } else
677       // Handle multi-dimensional arrays
678       result_str += qid(target_type_decl, rstack, TYPE) + "().init(" +
679 	get_type_info_obj(tc->type_mark, rstack, false) + "," + expr_str + ")";
680 
681   } else
682     assert(false);
683 
684   str += result_str;
685 
686   return false;
687 }
688 
689 bool
m_emit_expr(pIIR_QualifiedExpression qe,string & str,RegionStack & rstack,id_type t)690 m_emit_expr (pIIR_QualifiedExpression qe, string &str, RegionStack &rstack, id_type t)
691 {
692   emit_expr (qe->expression, str, rstack, t);
693 
694   return false;
695 }
696 
697 bool
m_emit_expr(pIIR_EnumLiteralReference elr,string & str,RegionStack & rstack,id_type t)698 m_emit_expr (pIIR_EnumLiteralReference elr, string &str, RegionStack &rstack, id_type t)
699 {
700   emit_id (elr->value, str, rstack);
701 
702   return true;
703 }
704 
705 bool
m_emit_expr(pIIR_ArrayReference aor,string & str,RegionStack & rstack,id_type t)706 m_emit_expr (pIIR_ArrayReference aor, string &str, RegionStack &rstack, id_type t)
707 {
708   emit_expr (aor->array, str, rstack, t);
709   for (pIIR_ExpressionList il = aor->indices; il; il = il->rest)
710     {
711       str += "[";
712       string index;
713       bool simple = emit_expr (il->first, index, rstack, t);
714       str += index + "]";
715     }
716 
717   return false;
718 }
719 
720 
721 bool
m_emit_expr(pIIR_ArrayLiteralExpression ale,string & str,RegionStack & rstack,id_type t)722 m_emit_expr (pIIR_ArrayLiteralExpression ale, string &str, RegionStack &rstack, id_type t)
723 {
724   // Array literals are always folded. Hence, valid_folded_value
725   // should return true!
726   assert(valid_folded_value(ale));
727 
728   emit_folded_value(folded_value(ale), str, rstack, ale->subtype);
729 
730   return false;
731 }
732 
733 
734 bool
m_emit_expr(pIIR_RecordReference ror,string & str,RegionStack & rstack,id_type t)735 m_emit_expr (pIIR_RecordReference ror, string &str, RegionStack &rstack, id_type t)
736 {
737   emit_expr (ror->record, str, rstack, t);
738   str += ".value()." + nid (ror->element, DEFAULT);
739 
740   return false;
741 }
742 
743 
744 bool
m_emit_expr(pIIR_RecordAggregate ra,string & str,RegionStack & rstack,id_type t)745 m_emit_expr (pIIR_RecordAggregate ra, string &str, RegionStack &rstack, id_type t)
746 {
747   pIIR_RecordType rt = pIIR_RecordType (get_base_type (ra->subtype->base));
748 
749   str += qid (rt, rstack, TYPE) + "().init(" + get_type_info_obj(rt, rstack, false) + ")";
750 
751   for (pIIR_ElementAssociationList al = ra->element_association_list;
752        al; al = al->rest)
753     {
754       // check out whether the SAME value has been used for another
755       // record element in the aggregate (e.g., this might happen in
756       // case of an "others" choice).
757       pIIR_ElementAssociationList test_al = ra->element_association_list;
758       for (; test_al != al; test_al = test_al->rest)
759 	if (test_al->first->value ==  al->first->value)
760 	  break;
761       if (test_al != al)
762 	// If the same value expression has been used then copy the
763 	// corresponding value to its destination instead of emitting
764 	// the same value expression again.
765 	str += ".aggregate_copy(" + to_string(al->first->element->declaration_pos) + "," +
766 	  to_string(test_al->first->element->declaration_pos) + ")";
767       else {
768 	// Othewise, just call aggregate_set where the fist parameter
769 	// is the record element position number (first record element
770 	// is associated with number 0, ...). The second paramter
771 	// points to the appropriate value expression.
772 	str += ".aggregate_set(" + to_string(al->first->element->declaration_pos) + ",";
773 	str += "const_pointer(";
774 	emit_expr (al->first->value, str, rstack, t);
775 	str += "))";
776       }
777     }
778 
779   return false;
780 }
781 
782 
783 bool
m_emit_expr(pIIR_ArrayAggregate aa,string & str,RegionStack & rstack,id_type t)784 m_emit_expr (pIIR_ArrayAggregate aa, string &str, RegionStack &rstack, id_type t)
785 {
786   // Subtype of aggregate expression. At least the range direction will
787   // be used...
788   string dest_type_str, dest_type_info_str;
789   pIIR_Type dest_type = aa->subtype;
790   int dim_number = 1;
791   if(dest_type->is(VAUL_SUBARRAY_TYPE)) {
792     // If the aggreate is an multi-dimensional then a node
793     // VAUL_SubarrayType is used to describe the (sub)type of the
794     // sub-aggregate
795     dest_type = pVAUL_SubarrayType(aa->subtype)->complete_type->declaration->type;
796     pIIR_ArrayType at = pVAUL_SubarrayType(aa->subtype)->complete_type;
797     // Determine dimension of main array to which the aggregate
798     // belongs
799     int dim_counter = 0;
800     for (pIIR_TypeList tl = at->index_types; tl; tl = tl->rest)
801       dim_counter++;
802     // Next, determine the index associated with the array
803     // aggregate. Note that we can only count how many dimensions are
804     // left from where the aggregate starts.
805     int current_dim_counter = 0;
806     for (pIIR_TypeList tl = pVAUL_SubarrayType(aa->subtype)->index_types; tl; tl = tl->rest)
807       current_dim_counter++;
808     // Now, determine the index number the aggregate belongs to
809     dim_number = dim_counter - current_dim_counter + 1;
810     // Setup dest_type_str and dest_type_info_str
811     dest_type_str = qid(get_declaration(dest_type), rstack, TYPE);
812     dest_type_info_str = get_type_info_obj(dest_type, rstack, false);
813     for (int i = 1; i <= dim_counter - current_dim_counter; i++) {
814       dest_type_str += "::E_type";
815       dest_type_info_str = "parray_info(" + dest_type_info_str + "->element_type)";
816     }
817 
818   } else if (dest_type->is(IR_ARRAY_TYPE)) {
819     dest_type = aa->subtype->declaration->type;
820     dest_type_str = qid(get_declaration(dest_type), rstack, TYPE);
821     dest_type_info_str = get_type_info_obj(get_basic_type(dest_type), rstack, false);
822 
823   } else {
824     dest_type_str = qid(get_declaration(dest_type), rstack, TYPE);
825     dest_type_info_str = get_type_info_obj(get_basic_type(dest_type), rstack, false);
826   }
827   // Get range type of aggregate and determine left bound, right
828   // bound, direction and length of aggregat. Note that if the
829   // aggregate subtype cannot be determined from the context then
830   // dest_range will point to the corresponding index range of the
831   // unconstrained array associated with the aggregate.
832   vector<RangeDescriptor> range_desc = get_discrete_range(dest_type, rstack, IR_NOT_STATIC);
833   // Extract bounds from aggregate range type. Perhaps these
834   // bounds will be used to determine the range bounds of the aggregat.
835   string range_str;
836   StaticRangeDescriptor<string, string> range =
837     range_desc[dim_number - 1].rangedes_to_string(rstack, t);
838   string dest_direction_str =
839     (dest_direction(aa) == IR_DIRECTION_UP? "to" : "downto"); // Direction of aggregate
840 
841   int association_count = 0; // Number of associations
842   int max_len = 0; // Max index range length of a single choice
843   pIIR_IndexedAssociation max_len_choice = NULL; // choice with longest range
844 
845   // First, take a look at all choices to determine the choice which
846   // covers the largest range. However, an others choice will always
847   // be selected as max_len_choice. Further, the number of
848   // associations are counted.
849   for (pIIR_IndexedAssociationList al = aa->indexed_association_list; al; al = al->rest) {
850     if (al->first->is(IR_OTHERS_INDEXED_ASSOCIATION)) { // others choice
851       max_len = INT_MAX; // set length value so that this entry is not overwritten
852       max_len_choice = al->first;
853     } else {
854       if (max_len < length(al->first)) {
855 	max_len = length(al->first);
856 	max_len_choice = al->first;
857       }
858     }
859 
860     association_count++; // Count number of association
861   }
862   // If no max length choice could be found (e.g., because the choice
863   // length could not be determined at compile time) then just take
864   // the very first association element as max_len_choice.
865   if (max_len_choice == NULL)
866     max_len_choice = aa->indexed_association_list->first;
867 
868   // *****************************************************************************
869   // Now, generate the code. First. check some special cases.
870   // *****************************************************************************
871   string value_str;
872   if (has_others(aa)) { // Does the aggregate include an others choice?
873     // If the answer is yes, then the subtype of the aggregate must be
874     // determinable from the context. Get value expression of others choice.
875     emit_expr(pIIR_OthersIndexedAssociation(max_len_choice)->value, value_str, rstack, t);
876     // Determine range of the array aggregate.
877     range_str = range.left + "," + range.dir + "," + range.right;
878 
879   } else {
880     // Ok, aggregate does not have an others choice. Hence, the array
881     // bounds are directly determined from the choices. Generate code
882     // for the first array instance. The initial array instance is
883     // created from those choice which covers the longest range.
884     if (association_count == 1) {
885       // Ok, there is a single choice
886       if (max_len_choice->is(IR_SINGLE_INDEXED_ASSOCIATION)) {
887 	// Array contains only a single element
888 	pIIR_SingleIndexedAssociation saa = pIIR_SingleIndexedAssociation(max_len_choice);
889 	string index_str;
890 	if (named_association(aa)) {
891 	  // In case of named association use index value of choice
892 	  emit_expr(saa->index, index_str, rstack, DEFAULT);
893 	} else
894 	  // In case of positional association use left bound of
895 	  // aggregate type
896 	  index_str = range.left;
897 
898 	range_str = index_str + "," + dest_direction_str + "," + index_str;
899 
900       } else if (max_len_choice->is(IR_RANGE_INDEXED_ASSOCIATION)) {
901 	// Array contains a single range choice. Note that the range
902 	// does not have to be locally static in this case.
903 	pIIR_RangeIndexedAssociation raa = pIIR_RangeIndexedAssociation(max_len_choice);
904 	vector<RangeDescriptor> range_desc =
905 	  get_discrete_range(raa->index_range, rstack, IR_NOT_STATIC);
906 	StaticRangeDescriptor<string, string> range =
907 	  range_desc[0].rangedes_to_string(rstack, t);
908 
909 	if (!is_constrained_array_type(dest_type))
910 	  range_str = range.left + "," + range.dir + "," + range.right;
911 	else if (dest_direction_str == range.dir)
912 	  range_str = range.left + "," + dest_direction_str + "," + range.right;
913 	else
914 	  range_str = range.right + "," + dest_direction_str + "," + range.left;
915 
916       } else
917 	// This should never happen!
918 	assert(false);
919 
920     } else
921       // Ok, there are more than one choices. Hence, we use min_index
922       // and max_index to setup the array range
923       if (named_association(aa)) {
924 	// If the aggregate uses named association then the index
925 	// bounds are derived from the index number given in the
926 	// aggregate
927 	if (dest_direction_str == "to")
928 	  range_str = to_string(min_index(aa)) + "," + dest_direction_str + "," + to_string(max_index(aa));
929 	else
930 	  range_str = to_string(max_index(aa)) + "," + dest_direction_str + "," + to_string(min_index(aa));
931 
932       } else {
933 	// If the aggregate uses positional association then the
934 	// bounds are derived from the left bound of the target
935 	if (dest_direction_str == "to")
936 	  range_str = range.left + "," + dest_direction_str + "," + range.left + "+" + to_string(max_index(aa));
937 	else
938 	  range_str = range.left + "," + dest_direction_str + "," + range.left + "-" + to_string(max_index(aa));
939       }
940 
941     // Generate value of choice
942     if (max_len_choice->is(IR_SINGLE_INDEXED_ASSOCIATION))
943       emit_expr(pIIR_SingleIndexedAssociation(max_len_choice)->value, value_str, rstack, t);
944     else if (max_len_choice->is(IR_RANGE_INDEXED_ASSOCIATION))
945       emit_expr(pIIR_RangeIndexedAssociation(max_len_choice)->value, value_str, rstack, t);
946     else
947       assert(false);
948   }
949 
950   // Create call to array constructor. The second constructor argument
951   // is the element value. The first argument is an array_info
952   // instance.
953   str += dest_type_str + "(new array_info(" + dest_type_info_str + "->element_type," +
954     dest_type_info_str + "->index_type," + range_str + ",0)," + value_str + ")";
955   // If only a single choice is given then were done.
956   if (association_count == 1) return false;
957 
958   // Next, handle the remaining choices
959   for (pIIR_IndexedAssociationList al = aa->indexed_association_list; al; al = al->rest) {
960     pIIR_IndexedAssociation ia = al->first;
961     if (ia == max_len_choice) continue; // Skip choice if it has been already handled
962     // Emit choice value
963     value_str = "";
964     emit_expr(ia->value, value_str, rstack, t);
965     if (ia->is(IR_SINGLE_INDEXED_ASSOCIATION) && !named_association(aa)) {
966       // If choice is a single indexed *positional* association then
967       // index number of the element is determined by adding the
968       // choice number (stored in min_index) to the left bound of the
969       // aggregate (stored in left_str).
970       string index_str = range.left + (dest_direction_str == "to"? "+" : "-") +
971 	to_string(min_index(ia));
972       str += ".aggregate_set(" + index_str + ",to," + index_str + "," + value_str + ")";
973     } else
974       // Add code to set the corresponding array elements
975       str += ".aggregate_set(" + to_string(min_index(ia)) + ",to," +
976 	to_string(max_index(ia)) + "," + value_str + ")";
977   }
978 
979   return false;
980 }
981 
982 
983 
984 bool
m_emit_expr(pIIR_SliceReference sr,string & str,RegionStack & rstack,id_type t)985 m_emit_expr (pIIR_SliceReference sr, string &str, RegionStack &rstack, id_type t)
986 {
987   // Get slice range
988   vector<RangeDescriptor> range_desc = get_discrete_range(sr->range, rstack, IR_NOT_STATIC);
989   StaticRangeDescriptor<string, string> range =
990     range_desc[0].rangedes_to_string(rstack, t);
991 
992   pIIR_TypeDeclaration type_declaration = get_declaration(sr->array->subtype);
993   str += qid(type_declaration, rstack, id_type(TYPE | ALIAS, DEFAULT));
994 
995   str += "(new array_info(";
996   str += get_type_info_obj(get_base_type(sr->array->subtype), rstack, false) + "->element_type," +
997     get_type_info_obj(get_base_type(sr->array->subtype), rstack, false) + "->index_type," +
998     range.left + "," + range.dir + "," + range.right + ",0),&";
999 
1000   emit_expr (sr->array, str, rstack, t);
1001   str += "[" + range.left + "]";
1002 
1003   str += ")";
1004 
1005   return false;
1006 }
1007 
1008 bool
m_emit_expr(pIIR_AccessReference aor,string & str,RegionStack & rstack,id_type t)1009 m_emit_expr (pIIR_AccessReference aor, string &str, RegionStack &rstack, id_type t)
1010 {
1011   str += "deref<" + qid(aor->subtype, rstack, TYPE) + " >(";
1012   emit_expr (aor->access, str, rstack, t);
1013   str += ")";
1014 
1015   return false;
1016 }
1017 
1018 
1019 void
emit_builtin_id(IR_Kind k,string & str)1020 emit_builtin_id (IR_Kind k, string &str)
1021 {
1022   str += tree_kind_name(k);
1023 }
1024 
1025 
1026 bool
m_emit_expr(pIIR_SignalAttr asr,string & str,RegionStack & rstack,id_type t)1027 m_emit_expr (pIIR_SignalAttr asr, string &str, RegionStack &rstack, id_type t)
1028 {
1029   emit_builtin_id (asr->kind(), str);
1030   str += "(";
1031   emit_expr (asr->signal, str, rstack, t);
1032   str += ")";
1033 
1034   return false;
1035 }
1036 
1037 bool
m_emit_expr(pIIR_AttrTypeFunc atf,string & str,RegionStack & rstack,id_type t)1038 m_emit_expr (pIIR_AttrTypeFunc atf, string &str, RegionStack &rstack, id_type t)
1039 {
1040   // If the result type is an enumeration type then a cast
1041   // operation "enumeration(...)" must be done
1042   pIIR_Type return_type = get_base_type(atf->subtype);
1043 
1044   // First, check whether the attribute was folded successfully.
1045   if (valid_folded_value(atf)) {
1046     // Emit the folded value instead of accessing determining the
1047     // attribute at runtime
1048     emit_folded_value(folded_value(atf), str, rstack, return_type);
1049     return true;
1050 
1051   } else {
1052     // ******************************************************************
1053     // The attribute result could not be determined at compile
1054     // time. Hence, generate code to determine the corresponding value
1055     // at runtime.
1056     // ******************************************************************
1057     string info_instance_str = get_type_info_obj(atf->prefix, rstack, false);
1058     pIIR_Type prefix_base_type = get_base_type(atf->prefix);
1059     string argument_str;
1060     if (atf->argument != NULL)
1061       emit_expr(atf->argument, argument_str, rstack, id_type(READER, DEREF));
1062 
1063     // Determine range of prefix type
1064     vector<RangeDescriptor> type_range_des = get_discrete_range(atf->prefix, rstack, IR_NOT_STATIC);
1065     // type_range_des should contain exactly one single
1066     // RangeDescriptor instance
1067     assert(type_range_des.size() == 1);
1068     // Try to fold range descriptor
1069     type_range_des[0].constant_fold_rangedes(rstack);
1070     // Determine left, right and direction of range. is_static stores
1071     // whether the corresponding value is static.
1072     StaticRangeDescriptor<lint, IR_Direction> lint_range;
1073     StaticRangeDescriptor<double, IR_Direction> double_range;
1074 
1075     if (get_base_type (atf->prefix)->is (IR_FLOATING_TYPE))
1076       double_range = type_range_des[0].rangedes_to_double (rstack);
1077     else
1078       lint_range = type_range_des[0].rangedes_to_lint (rstack);
1079 
1080     // Finally, handle the various attributes
1081     // ***** RIGHTOF *******************************************
1082     // Note that this attribute is not defined for floatingpoint types
1083     if (atf->is(IR_ATTR_RIGHTOF)) {
1084       // The resulting string looks like:
1085       // integer_INFO->check(value+(integer_INFO->left_bound <
1086       // integer_INFO->right_bound?+1:-1))
1087       if (lint_range.valid[1])
1088 	// If the range direction could be determined then emit
1089 	// optimized code
1090 	str += info_instance_str + "->check(" + argument_str + (lint_range.dir == IR_DIRECTION_UP? "+1": "-1") + ")";
1091       else
1092 	str += info_instance_str + "->check(" + argument_str + "+(" + info_instance_str + "->left_bound < " +
1093 	  info_instance_str + "->right_bound?+1:-1))";
1094 
1095       // ***** LEFTOF *******************************************
1096       // Note that this attribute is not defined for floatingpoint types
1097     } else if (atf->is(IR_ATTR_LEFTOF)) {
1098       // The resulting string looks like:
1099       // integer_INFO->check(value+(integer_INFO->left_bound < integer_INFO->right_bound?+1:-1))
1100       if (lint_range.valid[1])
1101 	// If the range direction could be determined then emit
1102 	// optimized code
1103 	str += info_instance_str + "->check(" + argument_str + (lint_range.dir == IR_DIRECTION_UP? "-1": "+1") + ")";
1104       else
1105 	str += info_instance_str + "->check(" + argument_str + "-(" + info_instance_str + "->left_bound < " +
1106 	  info_instance_str + "->right_bound?+1:-1))";
1107 
1108       // ***** PRED *******************************************
1109       // Note that this attribute is not defined for floatingpoint types
1110     } else if (atf->is(IR_ATTR_PRED)) {
1111       str += info_instance_str + "->check(" + argument_str + "-1)";
1112 
1113       // ***** SUCC *******************************************
1114       // Note that this attribute is not defined for floatingpoint types
1115     } else if (atf->is(IR_ATTR_SUCC)) {
1116       str += info_instance_str + "->check(" + argument_str + "+1)";
1117 
1118       // ***** VAL *******************************************
1119       // Note that this attribute is not defined for floatingpoint types
1120     } else if (atf->is(IR_ATTR_VAL)) {
1121       str += info_instance_str + "->check(" + argument_str + ")";
1122 
1123       // ***** POS *******************************************
1124       // Note that this attribute is not defined for floatingpoint types
1125     } else if (atf->is(IR_ATTR_POS)) {
1126       str += info_instance_str + "->check(" + argument_str + ")";
1127 
1128       // ***** VALUE *******************************************
1129     } else if (atf->is(IR_ATTR_VALUE)) {
1130       str += "((" + qid(prefix_base_type->declaration, rstack, TYPE) +
1131 	+ ")attribute_value(" + info_instance_str + "," + argument_str + "))";
1132 
1133       // ***** IMAGE *******************************************
1134     } else if (atf->is(IR_ATTR_IMAGE)) {
1135       str += "attribute_image(" + info_instance_str + ",const_pointer(" + argument_str + "))";
1136 
1137     } else
1138       assert(false);
1139 
1140     return false;
1141   }
1142 }
1143 
1144 
1145 bool
m_emit_expr(pIIR_AttrTypeValue atf,string & str,RegionStack & rstack,id_type t)1146 m_emit_expr (pIIR_AttrTypeValue atf, string &str, RegionStack &rstack, id_type t)
1147 {
1148   // If the result type is an enumeration type then a cast
1149   // operation "enumeration(...)" must be done
1150   pIIR_Type return_type = get_base_type(atf->subtype);
1151 
1152   // First, check whether the attribute was folded successfully.
1153   if (valid_folded_value(atf)) {
1154     // Emit the folded value instead of accessing determining the
1155     // attribute at runtime
1156     emit_folded_value(folded_value(atf), str, rstack, return_type);
1157     return true;
1158 
1159   } else {
1160     // ******************************************************************
1161     // The attribute result could not be determined at compile
1162     // time. Hence, generate code to determine the corresponding value
1163     // at runtime.
1164     // ******************************************************************
1165     string info_instance_str = get_type_info_obj(atf->prefix, rstack, false);
1166     pIIR_Type prefix_base_type = get_base_type(atf->prefix);
1167     string argument_str;
1168     if (atf->argument != NULL)
1169       emit_expr(atf->argument, argument_str, rstack, DEREF);
1170 
1171     // Determine range of prefix type
1172     vector<RangeDescriptor> type_range_des =
1173       get_discrete_range(atf->prefix, rstack, IR_NOT_STATIC);
1174     // type_range_des should contain exactly one single
1175     // RangeDescriptor instance
1176     assert(type_range_des.size() == 1);
1177     // Try to fold range descriptor
1178     type_range_des[0].constant_fold_rangedes(rstack);
1179     // Determine left, right and direction of range. is_static stores
1180     // whether the corresponding value is static.
1181     StaticRangeDescriptor<lint, IR_Direction> lint_range;
1182     StaticRangeDescriptor<double, IR_Direction> double_range;
1183 
1184     bool is_floatingpoint_type = false;
1185     if (get_base_type (atf->prefix)->is (IR_FLOATING_TYPE))
1186       {
1187 	double_range = type_range_des[0].rangedes_to_double (rstack);
1188 	is_floatingpoint_type = true;
1189       }
1190     else
1191       {
1192 	lint_range = type_range_des[0].rangedes_to_lint (rstack);
1193 	is_floatingpoint_type = false;
1194       }
1195 
1196     // Finally, handle the various attributes
1197     // ***** LENGTH *******************************************
1198     if (atf->is(IR_ATTR_LENGTH)) {
1199       // Actually, this attribute is defined for arrays only!
1200       assert(false);
1201 
1202       // ***** ASCENDING *******************************************
1203     } else if (atf->is(IR_ATTR_ASCENDING)) {
1204       str += "enumeration(" + info_instance_str + "->left_bound < " +
1205 	info_instance_str + "->right_bound?1:0)";
1206 
1207       // ***** HIGH *******************************************
1208     } else if (atf->is(IR_ATTR_HIGH)) {
1209       if (prefix_base_type->is(IR_ENUMERATION_TYPE))
1210 	str += "max(" + info_instance_str + "->left_bound, " +
1211 	  info_instance_str + "->right_bound?)";
1212       else
1213 	str += info_instance_str + "->high_bound";
1214 
1215       // ***** LOW *******************************************
1216     } else if (atf->is(IR_ATTR_LOW)) {
1217       if (prefix_base_type->is(IR_ENUMERATION_TYPE))
1218 	str += "min(" + info_instance_str + "->left_bound, " +
1219 	  info_instance_str + "->right_bound?)";
1220       else
1221 	str += info_instance_str + "->low_bound";
1222 
1223       // ***** RIGHT *******************************************
1224     } else if (atf->is(IR_ATTR_RIGHT)) {
1225       str += info_instance_str + "->left_bound";
1226 
1227 
1228       // ***** LEFT *******************************************
1229     } else if (atf->is(IR_ATTR_LEFT)) {
1230       str += info_instance_str + "->right_bound";
1231 
1232     } else
1233       assert(false);
1234 
1235     return false;
1236   }
1237 }
1238 
1239 
1240 bool
m_emit_expr(pIIR_Expression e,string & str,RegionStack & rstack,id_type t)1241 m_emit_expr (pIIR_Expression e, string &str, RegionStack &rstack, id_type t)
1242 {
1243   str += "/* IIR_Expression " + string(e->kind_name()) + " */";
1244 
1245   return false;
1246 }
1247 
1248 
1249 // Actually, IIR_EnumerationLiteral is not an expression but we need
1250 // this method for internal use
1251 bool
m_emit_expr(pIIR_EnumerationLiteral e,string & str,RegionStack & rstack,id_type t)1252 m_emit_expr (pIIR_EnumerationLiteral e, string &str, RegionStack &rstack, id_type t)
1253 {
1254   str += qid(e->subtype->declaration, rstack, TYPE) + "(" + to_string(e->enum_pos) + ")";
1255 
1256   return true;
1257 }
1258 
1259