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