3import exahype2.dslhype.SyntaxTree
as SyntaxTree
4import exahype2.dslhype.Printer
as Printer
5from exahype2.dslhype.printers.CPPPrinter
import CPPPrinter
72 def __init__(self, spaces_per_tab = 2, use_omp = False):
81 if function_definition._top_level:
82 for argument
in function_definition._arguments:
83 SyntaxTree.Node.type_map.update({argument.id: argument._namespace})
84 if SyntaxTree.Node.type_map.get(argument._type.print(self.
cpp_printer))
is None:
85 SyntaxTree.Node.type_map.update({argument._type.print(self.
cpp_printer): argument._namespace})
86 SyntaxTree.Node.use_accelerator = function_definition.use_accelerator
87 SyntaxTree.Node.use_mlir_omp = self.
use_omp
90 if function_definition._top_level:
91 SyntaxTree.Node.reset_mlir_ids()
98 if function_definition._template
is not None:
99 for argument
in function_definition._arguments:
100 mlir_signature = argument._namespace
103 if argument._is_function:
106 func_decl = f
"func.func private @{argument.id}_bridge{mlir_signature}"
107 globals_mlir.append(
' ' * (indent_level) * SyntaxTree.Node.spaces_per_tab + func_decl)
113 "MLIR code generation requires template parameters to determine bridge function signatures. "
114 "Ensure the function has template parameters that specify the required functors."
118 function_global_loads = []
119 if function_definition._template
is not None:
120 for argument
in function_definition._template:
122 new_id = SyntaxTree.Node.get_mlir_id()
123 globals_mlir.append(
' ' * (indent_level) * SyntaxTree.Node.spaces_per_tab +f
"llvm.mlir.global external @{argument.id}() : {argument._type.print(self)}")
124 function_global_loads.append(
' ' * (indent_level + 1) * SyntaxTree.Node.spaces_per_tab + f
"%{new_id} = llvm.mlir.addressof @{argument.id} : !llvm.ptr")
127 arg_mlir_type = argument._type.print(self)
130 if arg_mlir_type
and arg_mlir_type.strip() !=
'' and len(arg_mlir_type.strip()) > 0:
131 function_global_loads.append(
' ' * (indent_level + 1) * SyntaxTree.Node.spaces_per_tab + f
"%{argument.id} = llvm.load %{new_id} {{name = \"{argument.id.strip('%')}\"}} : !llvm.ptr -> {arg_mlir_type}")
134 function_global_loads.append(
' ' * (indent_level + 1) * SyntaxTree.Node.spaces_per_tab + f
"// Skipping load for {argument.id} (empty type: '{arg_mlir_type}')")
138 SyntaxTree.Node.context.push_block()
139 argument_prints = [argument.print(self, indent_level).strip(
'')
for argument
in function_definition._arguments]
140 SyntaxTree.Node.context.push_block()
142 statement_prints = []
143 for statement
in function_definition._body:
144 statement_prints.append(statement.print(self, indent_level + 1))
145 statements = SyntaxTree.Node.context.pop_block().get_mlir()
146 statements += statement_prints
148 return_type = function_definition._return_type.print(self)
149 return_type_str = f
" -> ({return_type})" if return_type !=
'void' else ''
153{os.linesep.join(globals_mlir)}
154 func.func @{function_definition.id + "_omp" if SyntaxTree.Node.use_mlir_omp else function_definition.id}({', '.join(argument_prints)}){return_type_str} {{
155{os.linesep.join(function_global_loads)}
156{os.linesep.join(statements)}
162 SyntaxTree.Node.context.push_block()
163 argument_prints = [argument.print(self, indent_level)
for argument
in function_definition._arguments]
164 SyntaxTree.Node.context.push_block()
165 statement_prints = [statement.print(self, indent_level + 1)
for statement
in function_definition._body]
166 statements = SyntaxTree.Node.context.pop_block().get_mlir()
167 statements += statement_prints
168 return_type = function_definition._return_type.print(self, indent_level)
169 return_type_str = f
" -> ({return_type})" if return_type !=
'void' else ''
171 func.func @{function_definition.id}({', '.join(argument_prints)}){return_type_str} {{
172{os.linesep.join(statements)}
179 extra_namespace =
"omp::mlir"
181 extra_namespace =
"mlir"
182 namespace_header = f
"""namespace {"::".join(function_definition._namespaces)}::{extra_namespace} {{"""
183 namespace_footer =
"}"
185 if function_definition._template
is not None:
186 template_strings = [argument.print(self.
cpp_printer)
for argument
in function_definition._template]
187 template_string =
"template <" +
",".join(template_strings) +
">\n"
189 current_indent = indent_level + 1
190 argument_prints = [argument.print(self.
cpp_printer)
for argument
in function_definition._arguments]
192 return f
"""{namespace_header}
193{template_string}{self.get_indent(indent_level)}{function_definition._return_type.print(self.cpp_printer)} {function_definition.id}({', '.join(argument_prints)});
199 extra_namespace =
"omp::mlir"
201 extra_namespace =
"mlir"
202 namespace_header = f
"""namespace {"::".join(function_definition._namespaces)}::{extra_namespace} {{"""
203 namespace_footer =
"}"
205 function_call_string = function_definition.id
206 if function_definition._template
is not None:
207 template_strings = [argument.print(self.
cpp_printer)
for argument
in function_definition._template]
208 template_string =
"template <" +
",".join(template_strings) +
">\n"
209 function_call_string +=
"<" +
",".join([template.split(
' ')[1]
for template
in template_strings]) +
">"
211 arguments = copy.deepcopy(function_definition._arguments)
212 arguments.append(SyntaxTree.Argument(
"measurement", SyntaxTree.TCustom(
"tarch::timing::Measurement&")))
214 current_indent = indent_level + 1
215 argument_prints = [argument.print(self.
cpp_printer)
for argument
in arguments]
217 return f
"""{namespace_header}
218{template_string}{self.get_indent(indent_level)}{function_definition._return_type.print(self.cpp_printer)} {function_definition.id}({', '.join(argument_prints)}) {{
219tarch::timing::Watch watch("{"::".join(function_definition._namespaces)}", "{function_definition.id}", false, true);
220{function_call_string}({",".join([argument.print(self.cpp_printer).split(' ')[-1] for argument in function_definition._arguments])});
222measurement.setValue(watch.getCalendarTime());
223{self.get_indent(indent_level)}}}
229 extra_namespace =
"omp::mlir"
231 extra_namespace =
"mlir"
232 namespace_header = f
"""namespace {"::".join(function_definition._namespaces)}::{extra_namespace} {{"""
233 namespace_footer =
"}"
235 if function_definition._template
is not None:
236 template_strings = [argument.print(self.
cpp_printer)
for argument
in function_definition._template]
237 template_string =
"template <" +
",".join(template_strings) +
">\n"
239 arguments = copy.deepcopy(function_definition._arguments)
240 arguments.append(SyntaxTree.Argument(
"measurement", SyntaxTree.TCustom(
"tarch::timing::Measurement&")))
242 current_indent = indent_level + 1
243 argument_prints = [argument.print(self.
cpp_printer)
for argument
in arguments]
245 return f
"""{namespace_header}
246{template_string}{self.get_indent(indent_level)}{function_definition._return_type.print(self.cpp_printer)} {function_definition.id}({', '.join(argument_prints)});
252 return f
"%{argument.id} : {argument._type.print(self)}"
259 if integer._string
is None:
260 value = str(integer._value)
262 integer.mlir_id(SyntaxTree.Node.get_mlir_id())
263 mlir_str =
"".join(SyntaxTree.Node.context.get_block().pop_mlir())
264 mlir_str += indent + f
"%{integer.mlir_id()} = arith.constant {integer._value} : {integer.get_type().print(self)}\n"
265 SyntaxTree.Node.context.push_block()
266 SyntaxTree.Node.context.get_block().mlir_append(mlir_str)
267 id = f
"%{integer.mlir_id()}"
275 match integer._string:
277 struct, field = x.split(
'.')
278 if struct
in SyntaxTree.Node.struct_map:
279 struct_list = SyntaxTree.Node.struct_map[struct]
280 idx = [item[0]
for item
in struct_list].index(field)
281 mlir_type = struct_list[idx][1]
283 mlir_type_struct = mlir_type.split(
'|||')[1]
if '|||' in mlir_type
else mlir_type
285 mlir_str = f
"llvm.getelementptr %{struct}[0, {idx}] : (!llvm.ptr) -> !llvm.ptr, {mlir_type_struct}"
287 return integer._string
289 def print_if(self, if_statement: SyntaxTree.If, indent_level=0):
291 SyntaxTree.Node.context.push_block()
292 statement_prints = [statement.print(self, indent_level + 1)
for statement
in if_statement._statements]
293 body_statements =
''.join(SyntaxTree.Node.context.pop_block().get_mlir())
294 body_statements +=
''.join(statement_prints)
295 return indent + f
"""scf.if {if_statement._boolean.print(self, indent_level)} {{
296{body_statements}""" + indent +
"}"
298 def print_for(self, for_statement: SyntaxTree.For, indent_level = 0):
302 if isinstance(for_statement._iteration_range[0], list)
or isinstance(for_statement._iteration_range[0], tuple):
303 dims = len(for_statement._iteration_range)
308 for d
in range(dims):
309 var = For._iteration_variable_names[d]
310 iter_vars.append(f
"%{var}")
311 for_statement._iteration_range[d][0].hoist(
True)
312 for_statement._iteration_range[d][1].hoist(
True)
313 if isinstance(for_statement._iteration_range[d][0], SyntaxTree.Integer):
314 mlir_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
315 bounds_casting += indent + f
"{mlir_id} = arith.constant {for_statement._iteration_range[d][0].print(self, indent_level)} : index\n"
318 lwb = for_statement._iteration_range[d][0].print(self, indent_level).strip()
319 if isinstance(for_statement._iteration_range[d][1], SyntaxTree.Integer):
320 mlir_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
321 bounds_casting += indent + f
"{mlir_id} = arith.constant {for_statement._iteration_range[d][1].print(self, indent_level)} : index\n"
324 upb = for_statement._iteration_range[d][1].print(self, indent_level).strip()
327 mlir_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
328 bounds_casting += indent + f
"{mlir_id} = arith.constant 1 : index\n"
329 steps.append(mlir_id)
331 for_statement._iteration_range[0].hoist(
True)
332 for_statement._iteration_range[1].hoist(
True)
333 if not for_statement._iteration_variable._index_type:
334 for_statement._iteration_variable.hoist(
True)
335 mlir_str = for_statement._iteration_variable.print(self, indent_level).strip()
336 mlir_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
337 bounds_casting +=
''.join(SyntaxTree.Node.context.pop_block().get_mlir())
338 SyntaxTree.Node.context.push_block()
339 bounds_casting += indent + f
"{mlir_id} = arith.index_cast {mlir_str} : {for_statement._iteration_variable.get_type().print(self)} to index\n"
340 iter_vars = [mlir_id]
342 iter_vars = [for_statement._iteration_variable.print(self, indent_level).strip()]
344 if not for_statement._iteration_range[0]._index_type:
345 for_statement._iteration_range[0].hoist(
True)
346 mlir_str = for_statement._iteration_range[0].print(self, indent_level).strip()
347 mlir_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
348 bounds_casting +=
''.join(SyntaxTree.Node.context.pop_block().get_mlir())
349 SyntaxTree.Node.context.push_block()
350 bounds_casting += indent + f
"{mlir_id} = arith.index_cast {mlir_str} : {for_statement._iteration_range[0].get_type().print(self, indent_level).strip()} to index\n"
353 lwbs += [for_statement._iteration_range[0].print(self, indent_level).strip()]
355 if not for_statement._iteration_range[1]._index_type:
356 for_statement._iteration_range[1].hoist(
True)
357 mlir_str = for_statement._iteration_range[1].print(self, indent_level).strip()
358 mlir_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
359 bounds_casting +=
''.join(SyntaxTree.Node.context.pop_block().get_mlir())
360 SyntaxTree.Node.context.push_block()
361 bounds_casting += indent + f
"{mlir_id} = arith.index_cast {mlir_str} : {for_statement._iteration_range[1].get_type().print(self, indent_level).strip()} to index\n"
364 upbs += [for_statement._iteration_range[1].print(self, indent_level).strip()]
366 bounds_casting +=
''.join(SyntaxTree.Node.context.pop_block().get_mlir())
367 mlir_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
368 bounds_casting += indent + f
"{mlir_id} = arith.constant 1 : index\n"
372 SyntaxTree.Node.context.push_block()
373 statement_prints = [statement.print(self, indent_level + 1)
for statement
in for_statement._statements]
374 statements =
''.join(SyntaxTree.Node.context.pop_block().get_mlir())
375 statements +=
''.join(statement_prints)
379 has_allocation = any(isinstance(stmt, SyntaxTree.MemoryAllocation)
for stmt
in for_statement._statements)
384 f
"{indent}scf.for {', '.join(iter_vars)} = "
385 f
"{', '.join(lwbs)} to {', '.join(upbs)} step {', '.join(steps)} {{\n"
390 f
"{indent}scf.parallel ({', '.join(iter_vars)}) = "
391 f
"({', '.join(lwbs)}) to ({', '.join(upbs)}) step ({', '.join(steps)}) {{\n"
393 loop_footer =
"\n" + indent +
"}\n"
395 return bounds_casting + loop_header + statements + loop_footer
398 return self.
get_indent(indent_level) +
"//" + comment._comment[1:]
402 SyntaxTree.Node.context.push_block()
405 is_bridge_call = function_call.id
in [
'sourceTerm',
'flux',
'nonconservativeProduct']
409 for i, argument
in enumerate(function_call._arguments):
413 is_reference_to_2d_subscript = (
415 isinstance(argument, SyntaxTree.Reference)
and
416 isinstance(argument._expression, SyntaxTree.Subscript)
and
417 isinstance(argument._expression._value, SyntaxTree.Subscript)
420 if is_reference_to_2d_subscript:
423 outer_subscript = argument._expression
424 inner_subscript = outer_subscript._value
425 memref_2d = inner_subscript._value
427 outer_subscript.hoist(
True)
428 outer_mlir = outer_subscript.print(self, indent_level)
429 mlir_str_from_outer =
"".join(SyntaxTree.Node.context.get_block().pop_mlir())
430 SyntaxTree.Node.context.get_block().mlir_append(mlir_str_from_outer)
433 memref_2d.hoist(
True)
434 memref_2d_mlir = memref_2d.print(self, indent_level).strip(
' ')
437 base_mlir_name = memref_2d_mlir.lstrip(
'%')
438 is_nested_base =
False
439 if base_mlir_name
in SyntaxTree.Node.type_map
and SyntaxTree._is_nested_memref(SyntaxTree.Node.type_map[base_mlir_name]):
440 is_nested_base =
True
443 ptr_code, final_ptr = SyntaxTree.Node.generate_pointer_to_2d_element(
444 memref_2d_mlir, inner_subscript._new_index, outer_subscript._new_index, is_nested_base, indent_level
446 SyntaxTree.Node.context.get_block().mlir_append(ptr_code)
450 arg_mlir = argument.print(self, indent_level).strip(
' ')
453 if not is_reference_to_2d_subscript
and isinstance(argument, SyntaxTree.Subscript):
455 base_value = arg_mlir
456 index = argument._new_index
457 base_type = argument._value.get_type()
459 if isinstance(base_type, SyntaxTree.TDataBlock):
461 if isinstance(base_type._dimensions, int)
and base_type._dimensions >= 2:
464 arg_mlir = f
"{base_value}[{index}]"
467 element_type_class, is_vector, mlir_element_type = base_type.get_array_element_info()
471 result_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
472 load_op = indent + f
"{result_id} = memref.load {base_value}[{index}] {{name = \"{base_value.strip('%')}\"}} : memref<?x{mlir_element_type}>\n"
473 SyntaxTree.Node.context.get_block().mlir_append(load_op)
475 ptr_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
476 cast_op = indent + f
"{ptr_id} = llvm.inttoptr {result_id} : {mlir_element_type} to !llvm.ptr\n"
477 SyntaxTree.Node.context.get_block().mlir_append(cast_op)
481 result_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
482 load_op = indent + f
"{result_id} = memref.load {base_value}[{index}] {{name = \"{base_value.strip('%')}\"}} : memref<?x{mlir_element_type}>\n"
483 SyntaxTree.Node.context.get_block().mlir_append(load_op)
487 if str(base_type).startswith(
"memref<?xmemref<?xf64>>"):
489 result_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
490 load_op = indent + f
"{result_id} = memref.load {base_value}[{index}] {{name = \"{base_value.strip('%')}\"}} : memref<?xmemref<?xf64>>\n"
491 SyntaxTree.Node.context.get_block().mlir_append(load_op)
495 arg_mlir = f
"{base_value}[{index}]"
497 argument_prints.append(arg_mlir)
499 argument_block = SyntaxTree.Node.context.pop_block().get_mlir()
500 for op
in argument_block:
501 SyntaxTree.Node.context.get_block().mlir_append(
' ' * indent_level * SyntaxTree.Node.spaces_per_tab + op.strip(
' '))
504 id = function_call.id[0].upper() + function_call.id[1:]
505 type_entry = SyntaxTree.Node.type_map[function_call.id]
507 if isinstance(type_entry, str):
510 fn_type = type_entry.print(self).strip()
512 bridge_function_name = f
"{function_call.id}_bridge"
513 call_statement = f
"""func.call @{bridge_function_name}({", ".join(argument_prints)}) : {fn_type.strip(' ')}"""
515 SyntaxTree.Node.context.get_block().mlir_append(indent + call_statement)
518 def print_max(self, max: SyntaxTree.Max, indent_level=0):
521 def unpack_nested_memref_access(expr, indent_level):
522 indent =
' ' * indent_level * SyntaxTree.Node.spaces_per_tab
524 if not (isinstance(expr, SyntaxTree.Subscript)
and isinstance(expr._value, SyntaxTree.Subscript)):
525 return expr.print(self, indent_level).strip(
' ')
527 outer_subscript = expr._value
529 if not hasattr(outer_subscript,
'_new_index'):
530 outer_subscript.print(self, indent_level)
531 if not hasattr(expr,
'_new_index'):
532 expr.print(self, indent_level)
534 outer_index = getattr(outer_subscript,
'_new_index', outer_subscript._index.print(self, indent_level))
535 inner_index = getattr(expr,
'_new_index', expr._index.print(self, indent_level))
537 inner_memref_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
540 outer_memref_var = outer_subscript._value.print(self, indent_level).strip(
' ')
546 outer_var_cpp = outer_subscript._value.print(self.
cpp_printer).strip()
547 if outer_var_cpp
in SyntaxTree.Node.type_map:
548 type_entry = SyntaxTree.Node.type_map[outer_var_cpp]
550 if isinstance(type_entry, str):
551 outer_memref_type = type_entry
554 outer_memref_type = type_entry.print(self).strip()
557 outer_memref_type =
"memref<?xmemref<?xf64>>"
559 outer_memref_type =
"memref<?xmemref<?xf64>>"
561 mlir_str = indent + f
"{inner_memref_id} = memref.load {outer_memref_var}[{outer_index}] {{name = \"{outer_memref_var.strip('%')}\"}} : {outer_memref_type}\n"
562 value_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
563 mlir_str += indent + f
"{value_id} = memref.load {inner_memref_id}[{inner_index}] {{name = \"{outer_memref_var.strip('%')}\"}} : memref<?xf64>\n"
564 SyntaxTree.Node.context.get_block().mlir_append(mlir_str)
568 SyntaxTree.Node.context.push_block()
570 if type(max._lhs.get_type())
is SyntaxTree.TDataBlock:
572 if type(max._rhs.get_type())
is SyntaxTree.TDataBlock:
576 if isinstance(max._lhs, SyntaxTree.Subscript)
and isinstance(max._lhs._value, SyntaxTree.Subscript):
577 lhs = unpack_nested_memref_access(max._lhs, indent_level)
579 lhs = max._lhs.print(self, indent_level).strip(
' ')
580 if SyntaxTree.TDataBlock.needs_memref_load(max._lhs):
581 const_zero_id = SyntaxTree.TDataBlock.ensure_const_zero(const_zero_id, indent_level)
582 lhs = SyntaxTree.TDataBlock.generate_memref_load(max._lhs, lhs, max._lhs._index.print(self), indent_level)
584 if isinstance(max._rhs, SyntaxTree.Subscript)
and isinstance(max._rhs._value, SyntaxTree.Subscript):
585 rhs = unpack_nested_memref_access(max._rhs, indent_level)
587 rhs = max._rhs.print(self, indent_level).strip(
' ')
588 if SyntaxTree.TDataBlock.needs_memref_load(max._rhs):
589 const_zero_id = SyntaxTree.TDataBlock.ensure_const_zero(const_zero_id, indent_level)
590 rhs = SyntaxTree.TDataBlock.generate_memref_load(max._rhs, rhs, const_zero_id, indent_level)
592 argument_block = SyntaxTree.Node.context.pop_block().get_mlir()
593 for op
in argument_block:
594 SyntaxTree.Node.context.get_block().mlir_append(op)
597 op_type_class = SyntaxTree.TDataBlock.get_mlir_type_for_operation(max._lhs, max._rhs)
598 result_type = op_type_class().print(self)
600 if op_type_class
is SyntaxTree.TInteger:
601 mlir_op =
"arith.maxsi"
603 mlir_op =
"arith.maximumf"
605 new_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
606 mlir_str = indent + f
"{new_id} = {mlir_op} {lhs}, {rhs} : {result_type}\n"
607 SyntaxTree.Node.context.get_block().mlir_append(mlir_str)
615 name_mlir = memory_allocation._name.print(self)
616 name_type = memory_allocation._name.get_type()
617 is_datablock = isinstance(name_type, SyntaxTree.TDataBlock)
618 var_name_for_map = memory_allocation._name.print(self.
cpp_printer).strip()
619 in_type_map = var_name_for_map
in SyntaxTree.Node.type_map
621 if len(memory_allocation._dimensions) == 1:
623 SyntaxTree.Node.context.push_block()
624 index_val = memory_allocation._dimensions[0].print(self, indent_level)
625 intermediate_ops = SyntaxTree.Node.context.pop_block().get_mlir()
628 index_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
629 decl =
''.join(intermediate_ops)
632 index_type = memory_allocation._dimensions[0].get_type()
633 index_mlir_type = index_type.print(self).strip()
634 decl += indent + f
"{index_id} = arith.index_cast {index_val} : {index_mlir_type} to index\n"
635 new_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
639 name_type = memory_allocation._name.get_type()
640 if isinstance(name_type, SyntaxTree.TDataBlock)
or isinstance(name_type, SyntaxTree.TDiagonalMatrix)
or isinstance(name_type, SyntaxTree.TMatrix):
642 element_type_class = name_type.get_element_type()
643 element_type = element_type_class().print(self)
644 mlir_type = f
"memref<?x{element_type}>"
646 mlir_type = name_type.print(self)
648 if mlir_type
is None and SyntaxTree.Node.type_map[var_name_for_map] ==
"double*":
649 mlir_type =
"memref<?xf64>"
650 matrix_names = [
"identity_matrix",
"mass_matrix_2d"]
651 if name_mlir.strip(
"%")
in matrix_names:
652 new_id =
"%" + name_mlir.strip(
"%")
653 SyntaxTree.MemoryAllocation.allocated_types[memory_allocation._name.print(self)] = mlir_type
654 decl += indent + f
"{new_id} = memref.alloc({index_id}) {{name = \"{name_mlir.strip('%')}\"}} : {mlir_type}\n"
656 SyntaxTree.MemoryAllocation.allocated_types[new_id] = mlir_type
660 if isinstance(memory_allocation._name, SyntaxTree.Subscript)
and not memory_allocation._specify_type:
663 outer_array = memory_allocation._name._value
664 outer_index = memory_allocation._name._index
667 SyntaxTree.Node.context.push_block()
668 outer_array_mlir = outer_array.print(self, indent_level)
669 outer_index_mlir = outer_index.print(self, indent_level)
670 additional_ops = SyntaxTree.Node.context.pop_block().get_mlir()
673 decl +=
''.join(additional_ops)
676 type_mlir = SyntaxTree.Node.get_mlir_type(memory_allocation._type)
677 if type_mlir
is None:
678 type_entry = SyntaxTree.Node.type_map[memory_allocation._type.print(self.
cpp_printer)]
680 if isinstance(type_entry, str):
681 type_mlir = type_entry.strip(
' ')
684 type_mlir = type_entry.print(self).strip()
685 outer_type = f
"memref<?xmemref<?x{type_mlir}>>"
688 decl += indent + f
"memref.store {new_id}, {outer_array_mlir}[{outer_index_mlir}] {{name = \"{outer_array_mlir.strip('%')}\"}} : {outer_type}"
693 var_name_for_type_check = memory_allocation._name.print(self.
cpp_printer).strip()
694 in_type_map = var_name_for_type_check
in SyntaxTree.Node.type_map
700 actual_dims_calc = -1
704 is_datablock = isinstance(memory_allocation._name.get_type(), SyntaxTree.TDataBlock)
708 datablock_obj = memory_allocation._name.get_type()
710 if hasattr(datablock_obj,
'_iteration_range'):
711 actual_dims_calc = len(datablock_obj._iteration_range)
712 elif isinstance(datablock_obj._dimensions, int):
713 actual_dims_calc = 1
if datablock_obj._dimensions == 1
else 2
714 elif isinstance(datablock_obj._dimensions, list):
715 actual_dims_calc = len(datablock_obj._dimensions)
if len(datablock_obj._dimensions) > 0
else 1
719 actual_dims_calc = -1
721 if is_datablock
and actual_dims_calc >= 2:
723 element_type_class = memory_allocation._name.get_type().get_element_type()
724 element_type = element_type_class().print(self)
729 dim_exprs = memory_allocation._dimensions[:actual_dims_calc]
730 if len(dim_exprs) < actual_dims_calc:
732 dim_exprs = memory_allocation._dimensions
734 intermediate_decl =
""
737 for i, dim_expr
in enumerate(dim_exprs):
739 dim_val = dim_expr.print(self, indent_level)
740 dim_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
741 dim_ids.append(dim_id)
742 dim_type = dim_expr.get_type()
743 dim_mlir_type = dim_type.print(self).strip()
746 intermediate_decl += indent + f
"{dim_id} = arith.index_cast {dim_val} : {dim_mlir_type} to index\n"
749 dim_expr_ops = SyntaxTree.Node.context.pop_block().get_mlir()
750 intermediate_decl =
''.join(dim_expr_ops) + intermediate_decl
753 SyntaxTree.Node.context.push_block()
756 name_mlir = memory_allocation._name.print(self, indent_level)
759 dimension_list = [
"?"] * actual_dims_calc
760 memref_dims =
"x".join(dimension_list)
761 alloc_args =
", ".join(dim_ids)
764 alloc_line = indent + f
"{name_mlir} = memref.alloc({alloc_args}) {{name = \"{name_mlir.strip('%')}\"}} : memref<{memref_dims}x{element_type}>\n"
767 memref_type_full = f
"memref<{memref_dims}x{element_type}>"
768 SyntaxTree.Node.mlir_memref_types[name_mlir] = memref_type_full
769 SyntaxTree.MemoryAllocation.allocated_types[name_mlir] = memref_type_full
771 return intermediate_decl + alloc_line
775 size = memory_allocation._dimensions[-2]
776 for i
in range(len(memory_allocation._dimensions) - 3, -1, -1):
777 size = size * memory_allocation._dimensions[i]
780 SyntaxTree.Node.context.push_block()
781 outer_size_val = memory_allocation._dimensions[-1].print(self, indent_level)
782 intermediate_ops = SyntaxTree.Node.context.pop_block().get_mlir()
785 decl =
''.join(intermediate_ops)
788 outer_size_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
789 outer_size_type = memory_allocation._dimensions[-1].get_type()
790 outer_size_mlir_type = outer_size_type.print(self).strip()
791 decl += indent + f
"{outer_size_id} = arith.index_cast {outer_size_val} : {outer_size_mlir_type} to index\n"
795 var_name = memory_allocation._name.print(self.
cpp_printer).strip()
798 if var_name
in SyntaxTree.Node.type_map:
800 type_entry = SyntaxTree.Node.type_map[var_name]
803 if isinstance(type_entry, str):
804 outer_type = type_entry
807 outer_type = type_entry.print(self).strip()
808 elif isinstance(memory_allocation._name.get_type(), SyntaxTree.TDataBlock):
810 element_type_class = memory_allocation._name.get_type().get_element_type()
811 element_type = element_type_class().print(self)
812 outer_type = f
"memref<?xmemref<?x{element_type}>>"
815 name_type_mlir = memory_allocation._name.get_type().print(self)
817 if name_type_mlir
is None:
818 type_entry = SyntaxTree.Node.type_map[memory_allocation._name.get_type().print(self.
cpp_printer)]
820 if isinstance(type_entry, str):
821 name_type_mlir = type_entry.strip(
' ')
824 name_type_mlir = type_entry.print(self).strip()
825 outer_type = f
"memref<?x{name_type_mlir}>"
828 SyntaxTree.Node.context.push_block()
829 name_mlir = memory_allocation._name.print(self, indent_level)
830 name_ops = SyntaxTree.Node.context.pop_block().get_mlir()
833 decl +=
''.join(name_ops)
834 decl += indent + f
"{name_mlir} = memref.alloc({outer_size_id}) {{name = \"{name_mlir.strip('%')}\"}} : {outer_type}\n"
836 SyntaxTree.MemoryAllocation.allocated_types[name_mlir] = outer_type
839 loop_mlir = memory_allocation._loop.print(self, indent_level)
841 return decl + loop_mlir
847 name_mlir = memory_deallocation._name.print(self, indent_level)
849 if name_mlir
in SyntaxTree.MemoryAllocation.allocated_types:
850 name_type_mlir = SyntaxTree.MemoryAllocation.allocated_types[name_mlir]
851 elif memory_deallocation._allocated_type
is not None:
853 name_type_mlir = memory_deallocation._allocated_type
858 name_element_type = memory_deallocation._name.get_type()
859 element_type = name_element_type.print(self).strip()
861 if len(memory_deallocation._dimensions) == 1:
862 name_type_mlir = f
"memref<?x{element_type}>"
865 name_type_mlir = f
"memref<?xmemref<?x{element_type}>>"
867 if name_mlir[0] !=
"%":
868 name_mlir =
"%" + name_mlir
869 return "\n" + indent + f
"""memref.dealloc {name_mlir} : {name_type_mlir}\n"""
874 SyntaxTree.Node.context.push_block()
875 rhs = assignment._rhs.print(self, indent_level)
879 rhs_casting_mlir =
''
881 if isinstance(assignment._rhs, SyntaxTree.Subscript):
882 mlir_list = SyntaxTree.Node.context.get_block().get_mlir()
883 for i
in range(assignment._rhs._dimensions):
885 if len(mlir_list) > 0:
886 rhs_indices.insert(0, assignment._rhs._new_index)
887 rhs_casting_mlir += mlir_list.pop()
889 mlir_str +=
''.join(SyntaxTree.Node.context.pop_block().get_mlir())
890 mlir_str += rhs_casting_mlir
893 tmp =
''.join(SyntaxTree.Node.context.pop_block().get_mlir())
896 SyntaxTree.Node.context.push_block()
897 lhs = assignment._lhs.print(self, indent_level)
901 lhs_casting_mlir =
''
903 if isinstance(assignment._lhs, SyntaxTree.Subscript):
904 mlir_list = SyntaxTree.Node.context.get_block().get_mlir()
905 for i
in range(assignment._lhs._dimensions):
907 if len(mlir_list) > 0:
908 popped = mlir_list.pop()
909 lhs_indices.insert(0, assignment._lhs._new_index)
910 lhs_casting_mlir += popped
912 mlir_str +=
''.join(SyntaxTree.Node.context.pop_block().get_mlir())
913 mlir_str += lhs_casting_mlir
915 tmp =
''.join(SyntaxTree.Node.context.pop_block().get_mlir())
919 lhs_is_flat_2d =
False
920 lhs_memref_name =
None
923 if isinstance(assignment._lhs, SyntaxTree.Subscript)
and isinstance(assignment._lhs._value, SyntaxTree.Subscript):
925 base_base = assignment._lhs._value._value
926 if isinstance(base_base, SyntaxTree.DataBlock)
and isinstance(base_base._internal, SyntaxTree.String):
928 lhs_is_flat_2d =
True
929 dsl_name = base_base._internal._value
930 lhs_memref_name = SyntaxTree.Node.mlir_symbol_table[dsl_name]
932 outer_sub = assignment._lhs
933 inner_sub = assignment._lhs._value
935 if hasattr(inner_sub,
'_new_index'):
936 all_lhs_indices.append(inner_sub._new_index)
937 if hasattr(outer_sub,
'_new_index'):
938 all_lhs_indices.append(outer_sub._new_index)
943 lhs_index_str =
'[' +
','.join(all_lhs_indices) +
']'
944 lhs_type = f
"memref<?x?xf64>"
945 mlir_str += indent + f
"memref.store {rhs_value}, {lhs_memref_name}{lhs_index_str} {{name = \"{lhs_memref_name.strip('%')}\"}} : {lhs_type}\n"
946 elif isinstance(assignment._lhs, SyntaxTree.Subscript)
and isinstance(assignment._lhs._value, SyntaxTree.Subscript):
947 base_base = assignment._lhs._value._value
950 if not (isinstance(base_base, SyntaxTree.DataBlock)
and isinstance(base_base._internal, SyntaxTree.String)):
953 if isinstance(assignment._rhs, SyntaxTree.Float):
954 const_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
955 mlir_str += indent + f
"{const_id} = arith.constant {assignment._rhs._value} : f64\n"
957 elif isinstance(assignment._rhs, SyntaxTree.Integer):
958 const_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
959 mlir_str += indent + f
"{const_id} = arith.constant {assignment._rhs._value} : i32\n"
961 elif isinstance(assignment._rhs, SyntaxTree.Subscript):
962 rhs_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
963 rhs_index_str =
'[' +
','.join(rhs_indices) +
']'
964 rhs_type =
"memref<?xf64>" if not rhs_dims
else f
"memref<{ 'x'.join(rhs_dims) }xf64>"
965 mlir_str += indent + f
"{rhs_id} = memref.load {rhs}{rhs_index_str} {{name = \"{rhs.strip('%')}\"}} : {rhs_type.strip(' ')}\n"
970 outer_index = assignment._lhs._new_index
971 inner_memref_var = assignment._lhs._value._value.print(self, indent_level)
974 inner_memref_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
976 base_var = assignment._lhs._value._value
977 type_entry = SyntaxTree.Node.type_map[base_var.id]
979 if isinstance(type_entry, str):
980 outer_memref_type = type_entry
982 outer_memref_type = type_entry.print(self).strip()
985 inner_sub_index = assignment._lhs._value._new_index
986 mlir_str += indent + f
"{inner_memref_id} = memref.load {inner_memref_var}[{inner_sub_index}] {{name = \"{inner_memref_var.strip('%')}\"}} : {outer_memref_type}\n"
989 inner_memref_type =
"memref<?xf64>"
990 mlir_str += indent + f
"memref.store {rhs_value}, {inner_memref_id}[{outer_index}] {{name = \"{inner_memref_var.strip('%')}\"}} : {inner_memref_type}\n"
993 rhs_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
995 lhs_index_str =
'[' +
','.join(lhs_indices) +
']'
998 lhs_type = f
"memref<{ 'x'.join(lhs_dims) }xf64>"
1000 lhs_type =
"memref<?xf64>"
1001 rhs_index_str =
'[' +
','.join(rhs_indices) +
']'
1003 rhs_type = f
"memref<{ 'x'.join(rhs_dims) }x f64>"
1005 rhs_type =
"memref<?xf64>"
1007 if isinstance(assignment._rhs, SyntaxTree.Subscript):
1008 mlir_str += indent + f
"{rhs_id} = memref.load {rhs}{rhs_index_str} {{name = \"{rhs.strip('%')}\"}} : {rhs_type.strip(' ')}\n"
1013 if isinstance(assignment._rhs, SyntaxTree.Float):
1014 const_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1015 mlir_str += indent + f
"{const_id} = arith.constant {assignment._rhs._value} : f64\n"
1016 rhs_value = const_id
1017 elif isinstance(assignment._rhs, SyntaxTree.Integer):
1018 const_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1019 mlir_str += indent + f
"{const_id} = arith.constant {assignment._rhs._value} : i32\n"
1020 rhs_value = const_id
1022 if isinstance(assignment._lhs, SyntaxTree.Subscript):
1023 mlir_str += indent + f
"memref.store {rhs_value}, {lhs}{lhs_index_str} {{name = \"{lhs.strip('%')}\"}} : {lhs_type.strip(' ')}\n"
1025 lhs_type_obj = assignment._lhs.get_type()
1026 lhs_mlir_type = lhs_type_obj.print(self, indent_level).strip(
' ')
1027 mlir_str += indent + f
"memref.store {rhs_value}, {lhs} {{name = \"{lhs.strip('%')}\"}} : {lhs_mlir_type}\n"
1034 if isinstance(construction._expression, SyntaxTree.Integer):
1035 if construction._expression._string
is None:
1036 expr_mlir = construction._expression.print(self, indent_level)
1039 mlir_str =
''.join(SyntaxTree.Node.context.get_block().pop_mlir())
1040 mlir_str += indent + f
"{construction._name.print(self, indent_level)} = {expr_mlir} : {construction._name.get_type().print(self, indent_level).strip(' ')}\n"
1043 new_id = SyntaxTree.Node.get_mlir_id()
1044 mlir_str = indent + f
"%{new_id} = {construction._expression.print(self, indent_level)}\n"
1047 expr_type = construction._expression.get_type().print(self, indent_level).strip(
' ')
1048 mlir_str += indent + f
"{construction._name.print(self, indent_level)} = llvm.load %{new_id} {{name = \"{construction._name.print(self, indent_level).strip('%')}\"}} : !llvm.ptr -> {expr_type}\n"
1050 mlir_str = f
"{self.get_indent(indent_level)}{construction._name.print(self)} = {construction._expression.print(self, indent_level)}\n"
1051 SyntaxTree.Node.context.get_block().mlir_append(mlir_str)
1057 if construction._name.id[-2:] ==
"1d":
1058 return f
"""{self.get_indent(indent_level)}{construction._name.print(self)} = builtin.unrealized_conversion_cast %{construction._dataBlock._internal._value} : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> to memref<?xf64> {{name = "{construction._name.print(self.cpp_printer)}"}} """
1061 type_print = construction._name.get_type().print(self, indent_level)
1065 for i
in range(len(construction._dataBlock._iteration_range) - 3, -1, -1):
1066 dims.append(construction._dataBlock._iteration_range[i])
1068 if len(construction._dataBlock._iteration_range) > 1:
1069 type_print =
"!llvm.ptr "
1073 target_var_name = construction._name.print(self, indent_level)
1074 SyntaxTree.Node.target_variable_name = target_var_name
1078 dsl_name = construction._dataBlock._internal._value
1079 SyntaxTree.Node.mlir_symbol_table[dsl_name] = target_var_name
1082 struct_mlir = construction._dataBlock._internal.print(self, indent_level).strip(
' ')
1083 mlir_str =
''.join(SyntaxTree.Node.context.pop_block().get_mlir())
1086 SyntaxTree.Node.target_variable_name =
None
1091 return f
"""{construction.memoryAllocation.print(self, indent_level)}
1092{construction.assignment.print(self, indent_level)}"""
1095 SyntaxTree.Node.context.push_block()
1096 mem_alloc = construction.memoryAllocation.print(self, indent_level)
1097 init = construction.initialisation.print(self, indent_level)
1098 alloc_block = SyntaxTree.Node.context.pop_block().get_mlir()
1099 for op
in alloc_block:
1100 SyntaxTree.Node.context.get_block().mlir_append(op)
1102 return f
"""{mem_alloc}
1106 return f
"""{construction.memoryAllocation.print(self, indent_level)}
1107{construction.assignment.print(self, indent_level)}"""
1110 return f
"""{construction.memoryAllocation.print(self, indent_level)}
1111{construction.assignment.print(self, indent_level)}"""
1114 if matrix._id
is None:
1115 return matrix._internal.print(self, indent_level)
1118 return "%" + str(matrix._id)
1121 if construction.id
is None:
1122 return construction._internal.print(self, indent_level)
1124 return "%" + construction.id
1127 SyntaxTree.Node.type_map.update({construction._matrix.print(self.
cpp_printer): SyntaxTree.TDiagonalMatrix().print(self.
cpp_printer)})
1128 return f
"""{construction._memory_allocation.print(self, indent_level)}
1129{construction._assignment.print(self, indent_level)}"""
1132 return f
"""{construction._memory_allocation.print(self, indent_level)}
1133{construction._assignment.print(self, indent_level)}"""
1136 return f
"""{construction._memory_allocation.print(self, indent_level)}
1137{construction._initialisation.print(self, indent_level)}
1138{construction._assignment.print(self, indent_level)}"""
1141 return assignment._loop.print(self, indent_level)
1145 return str(boolean._value)
1150 match string._value:
1152 struct, field = x.split(
'.')
1153 if struct
in SyntaxTree.Node.struct_map:
1154 struct_list = SyntaxTree.Node.struct_map[struct]
1155 idx = [item[0]
for item
in struct_list].index(field)
1156 mlir_type_target, mlir_type_struct = struct_list[idx][1].split(
'|||')
1159 struct_val_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1162 if field ==
"maxEigenvalue":
1163 field_id = f
"%{field}s"
1165 field_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1168 mlir_str = indent + f
"{struct_val_id} = llvm.load %{struct} {{name = \"{struct.strip('%')}\"}}: !llvm.ptr -> {mlir_type_struct}\n"
1172 if not mlir_type_target.startswith(
"!llvm.struct<"):
1174 ptr_field_id = f
"%{field}{'_ptr' if field != 'maxEigenvalue' else '_ptr'}"
1175 mlir_str += indent + f
"{ptr_field_id} = llvm.extractvalue {struct_val_id}[{idx}] : {mlir_type_struct}\n"
1176 field_id = ptr_field_id
1179 mlir_str += indent + f
"{field_id} = llvm.extractvalue {struct_val_id}[{idx}] : {mlir_type_struct}\n"
1184 if mlir_type_target.startswith(
"!llvm.struct<"):
1186 ptr_getelementptr_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1187 ptr_load_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1188 mlir_str += indent + f
"{ptr_getelementptr_id} = llvm.getelementptr %{struct}[0, {idx}] : (!llvm.ptr) -> !llvm.ptr, {mlir_type_struct}\n"
1189 mlir_str += indent + f
"{ptr_load_id} = llvm.load {ptr_getelementptr_id} {{name = \"{struct.strip('%')}\"}}: !llvm.ptr -> {mlir_type_target}\n"
1192 alloc_ptr_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1193 aligned_ptr_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1194 offset_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1195 sizes_0_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1196 strides_0_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1198 mlir_str += indent + f
"{alloc_ptr_id} = llvm.extractvalue {ptr_load_id}[0] : {mlir_type_target}\n"
1199 mlir_str += indent + f
"{aligned_ptr_id} = llvm.extractvalue {ptr_load_id}[1] : {mlir_type_target}\n"
1200 mlir_str += indent + f
"{offset_id} = llvm.extractvalue {ptr_load_id}[2] : {mlir_type_target}\n"
1201 mlir_str += indent + f
"{sizes_0_id} = llvm.extractvalue {ptr_load_id}[3, 0] : {mlir_type_target}\n"
1202 mlir_str += indent + f
"{strides_0_id} = llvm.extractvalue {ptr_load_id}[4, 0] : {mlir_type_target}\n"
1205 is_2d =
"array<2 x i64>" in mlir_type_target
1212 sizes_1_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1213 strides_1_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1214 mlir_str += indent + f
"{sizes_1_id} = llvm.extractvalue {ptr_load_id}[3, 1] : {mlir_type_target}\n"
1215 mlir_str += indent + f
"{strides_1_id} = llvm.extractvalue {ptr_load_id}[4, 1] : {mlir_type_target}\n"
1219 if field
in SyntaxTree.Node.type_map:
1220 type_entry = SyntaxTree.Node.type_map[field]
1222 if isinstance(type_entry, str):
1223 target_memref_type = type_entry
1226 target_memref_type = type_entry.print(self).strip()
1231 target_memref_type =
"memref<?x?xf64>"
1234 target_memref_type =
"memref<?xf64>"
1237 conversion_mlir, memref_id = SyntaxTree.Node.create_memref_from_extracted_descriptor(
1248 target_var_name=SyntaxTree.Node.target_variable_name,
1250 mlir_str += conversion_mlir
1251 final_id = memref_id
1252 elif 'memref' in mlir_type_target
or mlir_type_target ==
'!llvm.ptr':
1255 clean_target_type = mlir_type_target.strip(
'()')
1257 conversion_mlir, memref_id = SyntaxTree.Node.create_memref_from_ptr(
1261 target_var_name=SyntaxTree.Node.target_variable_name)
1262 mlir_str += conversion_mlir
1263 final_id = memref_id
1266 SyntaxTree.Node.context.get_block().mlir_append(mlir_str)
1268 return string._value
1273 if float._string
is None:
1274 value = str(float._value)
1276 float.mlir_id(SyntaxTree.Node.get_mlir_id())
1277 mlir_str =
"".join(SyntaxTree.Node.context.get_block().pop_mlir())
1278 mlir_str += indent + f
"%{float.mlir_id()} = arith.constant {float._value} : {float.get_type().print(self)}\n"
1279 SyntaxTree.Node.context.push_block()
1280 SyntaxTree.Node.context.get_block().mlir_append(mlir_str)
1281 id = f
"%{float.mlir_id()}"
1285 return str(float._string)
1288 if data_block.id
is None:
1289 return data_block._internal.print(self, indent_level)
1291 return "%" + data_block.id
1296 tmp = subscript._value
1297 while isinstance(tmp, SyntaxTree.Subscript):
1301 subscript._dimensions = dims
1302 value_type = subscript._value.get_type()
1303 type_str = value_type.print(self.
cpp_printer).strip()
1305 mlir_type = SyntaxTree.Node.type_map.get(type_str)
1306 if mlir_type
is None:
1308 mlir_type =
'' + value_type.print(self)
1310 mlir_str =
"".join(SyntaxTree.Node.context.get_block().pop_mlir())
1312 subscript._index.hoist(
True)
1313 index = subscript._index.print(self, indent_level)
1314 mlir_str +=
"".join(SyntaxTree.Node.context.get_block().pop_mlir())
1316 if not getattr(subscript._index,
'_index_type',
False):
1317 new_index = f
"%{SyntaxTree.Node.get_mlir_id()}"
1319 index_expr_type = subscript._index.get_type()
1320 mlir_type_cast = index_expr_type.print(self).strip()
1321 mlir_str += indent + new_index + f
" = arith.index_cast {index.strip(' ')}: {mlir_type_cast} to index\n"
1322 subscript._new_index = new_index
1324 subscript._new_index = index
1327 if isinstance(subscript._value, SyntaxTree.String):
1330 base_mlir = subscript._value.print(self, indent_level)
1331 base_type = subscript._value.get_type()
1333 if isinstance(base_type, SyntaxTree.TDataBlock):
1334 memref_type = base_type.print(self).strip()
1337 if "x?x" in memref_type:
1340 result_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1341 mlir_str += indent + f
"{result_id} = memref.load {base_mlir}[%0, {subscript._new_index}] {{name = \"{base_mlir.strip('%')}\"}} : {memref_type}\n"
1342 SyntaxTree.Node.context.push_block()
1343 SyntaxTree.Node.context.get_block().mlir_append(mlir_str)
1347 result_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1348 mlir_str += indent + f
"{result_id} = memref.load {base_mlir}[{subscript._new_index}] {{name = \"{base_mlir.strip('%')}\"}} : {memref_type}\n"
1349 SyntaxTree.Node.context.push_block()
1350 SyntaxTree.Node.context.get_block().mlir_append(mlir_str)
1356 SyntaxTree.Node.context.push_block()
1357 SyntaxTree.Node.context.get_block().mlir_append(mlir_str)
1359 subscript._value.hoist(
True)
1360 base_value = subscript._value.print(self, indent_level)
1363 if subscript.is_nested_subscript():
1364 result_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1367 outer_base = base_expr.print(self, indent_level)
1370 if outer_base
in SyntaxTree.Node.mlir_memref_types:
1371 actual_memref_type = SyntaxTree.Node.mlir_memref_types[outer_base]
1374 base_expr_type = base_expr.get_type()
1375 if isinstance(base_expr_type, SyntaxTree.TDataBlock):
1376 actual_memref_type = base_expr_type.print(self).strip()
1378 actual_memref_type =
"memref<?x?xf64>"
1382 if isinstance(base_expr, SyntaxTree.Name):
1383 base_name = base_expr.id
1384 elif hasattr(base_expr,
'id'):
1386 base_name = base_expr.id
1388 if base_name
and base_name
in SyntaxTree.Node.type_map
and SyntaxTree._is_nested_memref(SyntaxTree.Node.type_map[base_name]):
1389 actual_memref_type = SyntaxTree.Node.type_map[base_name]
1394 while isinstance(current, SyntaxTree.Subscript):
1395 indices.insert(0, current._new_index)
1396 current = current._value
1399 indices_str =
", ".join(indices)
1400 mlir_str =
"".join(SyntaxTree.Node.context.get_block().pop_mlir())
1404 if isinstance(actual_memref_type, str):
1405 is_nested = actual_memref_type.count(
"memref<") > 1
1406 actual_memref_type_str = actual_memref_type
1409 is_nested = actual_memref_type.is_nested_memref()
1410 actual_memref_type_str = actual_memref_type.print(self).strip()
1412 if is_nested
and len(indices) >= 2:
1415 inner_memref_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1417 if actual_memref_type_str.startswith(
"memref<?x")
and actual_memref_type_str.endswith(
">>"):
1418 inner_type = actual_memref_type_str[9:-1]
1420 inner_type =
"memref<?xf64>"
1422 mlir_str += indent + f
"{inner_memref_id} = memref.load {outer_base}[{indices[0]}] {{name = \"{outer_base.strip('%')}\"}} : {actual_memref_type_str}\n"
1424 remaining_indices =
", ".join(indices[1:])
1425 mlir_str += indent + f
"{result_id} = memref.load {inner_memref_id}[{remaining_indices}] {{name = \"{outer_base.strip('%')}\"}} : {inner_type}\n"
1428 mlir_str += indent + f
"{result_id} = memref.load {outer_base}[{indices_str}] {{name = \"{outer_base.strip('%')}\"}} : {actual_memref_type_str}\n"
1430 SyntaxTree.Node.context.push_block()
1431 SyntaxTree.Node.context.get_block().mlir_append(mlir_str)
1441 mlir_str =
"".join(SyntaxTree.Node.context.get_block().pop_mlir())
1443 reference._expression.hoist(
True)
1446 if isinstance(reference._expression, SyntaxTree.Subscript):
1447 base_expr = reference._expression._value
1448 index_expr = reference._expression._index
1450 base_expr.hoist(
True)
1451 base_mlir = base_expr.print(self, indent_level)
1453 mlir_str +=
"".join(SyntaxTree.Node.context.get_block().pop_mlir())
1455 if not hasattr(reference._expression,
'_new_index'):
1457 index_expr.hoist(
True)
1458 index_mlir = index_expr.print(self, indent_level)
1459 mlir_str +=
"".join(SyntaxTree.Node.context.get_block().pop_mlir())
1462 new_index = f
"%{SyntaxTree.Node.get_mlir_id()}"
1463 mlir_type = (
'index' if hasattr(index_expr,
'_index_type')
and index_expr._index_type
else 'i32')
1464 mlir_str += indent + new_index + f
" = arith.index_cast {index_mlir.strip(' ')}: {mlir_type} to index\n"
1465 reference._expression._new_index = new_index
1467 new_index = reference._expression._new_index
1470 base_type = base_expr.get_type()
1471 if isinstance(base_type, SyntaxTree.TDataBlock):
1472 result_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1475 if isinstance(base_expr, SyntaxTree.Subscript):
1478 if isinstance(base_expr._value, SyntaxTree.Subscript):
1479 result_id = base_mlir
1482 base_mlir_name = base_mlir.lstrip(
'%')
1483 is_nested_memref =
False
1484 if base_mlir_name
in SyntaxTree.Node.type_map
and SyntaxTree._is_nested_memref(SyntaxTree.Node.type_map[base_mlir_name]):
1485 is_nested_memref =
True
1487 outer_index = base_expr._new_index
1490 ptr_code, result_id = SyntaxTree.Node.generate_pointer_to_2d_element(
1491 base_mlir, outer_index, new_index, is_nested_memref, indent_level
1494 mlir_str += ptr_code
1496 element_type =
"f64"
1497 mlir_str += indent + f
"{result_id} = memref.subview {base_mlir}[{new_index}][1][1] : memref<?x{element_type}> to memref<?x{element_type}>\n"
1500 SyntaxTree.Node.context.push_block()
1501 SyntaxTree.Node.context.get_block().mlir_append(mlir_str)
1504 return result_id
if result_id
is not None else reference._expression.print(self, indent_level)
1513 if isinstance(vector_index._value, SyntaxTree.Subscript):
1514 array_base = vector_index._value._value
1515 array_index = vector_index._value._index
1516 array_base_mlir = array_base.print(self, indent_level)
1517 array_index_mlir = array_index.print(self, indent_level)
1519 if not getattr(array_index,
'_index_type',
False):
1520 array_index_cast = f
"%{SyntaxTree.Node.get_mlir_id()}"
1521 array_index_type = array_index.get_type()
1522 array_index_mlir_type = array_index_type.print(self).strip()
1523 mlir_str += indent + f
"{array_index_cast} = arith.index_cast {array_index_mlir} : {array_index_mlir_type} to index\n"
1525 array_index_cast = array_index_mlir
1527 raw_ptr = f
"%{SyntaxTree.Node.get_mlir_id()}"
1528 mlir_str += indent + f
"{raw_ptr} = memref.load {array_base_mlir}[{array_index_cast}] {{name = \"{array_base_mlir.strip('%')}\"}} : memref<?xi64>\n"
1530 vec_ptr = f
"%{SyntaxTree.Node.get_mlir_id()}"
1531 mlir_str += indent + f
"{vec_ptr} = llvm.inttoptr {raw_ptr} {{name = \"{array_base_mlir.strip('%')}\"}} : i64 to !llvm.ptr\n"
1533 func_param_mlir = vector_index._index.print(self, indent_level)
1535 if isinstance(vector_index._index, SyntaxTree.Integer):
1536 func_param_i32 = f
"%{SyntaxTree.Node.get_mlir_id()}"
1537 mlir_str += indent + f
"{func_param_i32} = arith.constant {int(vector_index._index._value)} : i32\n"
1538 elif not getattr(vector_index._index,
'_index_type',
False):
1539 func_param_i32 = f
"%{SyntaxTree.Node.get_mlir_id()}"
1540 mlir_str += indent + f
"{func_param_i32} = arith.index_cast {func_param_mlir} : index to i32\n"
1542 func_param_i32 = func_param_mlir
1544 result = f
"%{SyntaxTree.Node.get_mlir_id()}"
1546 func_param_i64 = f
"%{SyntaxTree.Node.get_mlir_id()}"
1547 mlir_str += indent + f
"{func_param_i64} = arith.extsi {func_param_i32} : i32 to i64\n"
1549 velem_ptr = f
"%{SyntaxTree.Node.get_mlir_id()}"
1550 mlir_str += indent + f
"{velem_ptr} = llvm.getelementptr {vec_ptr}[{func_param_i64}] {{name = \"{array_base_mlir.strip('%')}\"}} : (!llvm.ptr, i64) -> !llvm.ptr, f64\n"
1552 mlir_str += indent + f
"{result} = llvm.load {velem_ptr} {{name = \"{array_base_mlir.strip('%')}\"}} : !llvm.ptr -> f64\n"
1553 SyntaxTree.Node.context.get_block().mlir_append(mlir_str)
1558 op_type_class = SyntaxTree.TDataBlock.get_mlir_type_for_operation(comparison._lhs, comparison._rhs)
1560 mlir_operation = Comparison.get_mlir_comparison_op(comparison._operation, op_type_class)
1563 if mlir_operation
is None:
1564 raise ValueError(f
"Unsupported comparison operation: {comparison._operation}")
1566 const_zero_id =
None
1568 lhs_mlir = comparison._lhs.print(self, indent_level)
1569 if SyntaxTree.TDataBlock.needs_memref_load(comparison._lhs):
1570 const_zero_id = SyntaxTree.TDataBlock.ensure_const_zero(const_zero_id, indent_level)
1571 lhs_mlir = SyntaxTree.TDataBlock.generate_memref_load(comparison._lhs, lhs_mlir, const_zero_id, indent_level)
1573 rhs_mlir = comparison._rhs.print(self, indent_level)
1574 if SyntaxTree.TDataBlock.needs_memref_load(comparison._rhs):
1575 const_zero_id = SyntaxTree.TDataBlock.ensure_const_zero(const_zero_id, indent_level)
1576 rhs_mlir = SyntaxTree.TDataBlock.generate_memref_load(comparison._rhs, rhs_mlir, const_zero_id, indent_level)
1578 return self.
get_indent(indent_level) + f
"""{mlir_operation} {lhs_mlir}, {rhs_mlir} : {result_type}"""
1582 binary_operation._lhs.hoist(
True)
1583 binary_operation._rhs.hoist(
True)
1585 op_type_class = SyntaxTree.TDataBlock.get_mlir_type_for_operation(binary_operation._lhs, binary_operation._rhs)
1586 result_type = op_type_class().print_mlir()
1588 op_type_class = SyntaxTree.TDataBlock.get_mlir_type_for_operation(binary_operation._lhs, binary_operation._rhs)
1589 result_type = op_type_class().print(self)
1591 const_zero_id =
None
1593 binary_operation._lhs.hoist(
True)
1594 lhs = binary_operation._lhs.print(self, indent_level).strip(
' ')
1596 if SyntaxTree.TDataBlock.needs_memref_load(binary_operation._lhs):
1597 const_zero_id = SyntaxTree.TDataBlock.ensure_const_zero(const_zero_id, indent_level)
1598 lhs = SyntaxTree.TDataBlock.generate_memref_load(binary_operation._lhs, lhs, const_zero_id, indent_level)
1600 lhs = SyntaxTree.BinaryOperation.cast_operand(lhs, binary_operation._lhs, op_type_class, indent_level)
1602 binary_operation._rhs.hoist(
True)
1603 rhs = binary_operation._rhs.print(self, indent_level).strip(
' ')
1605 if SyntaxTree.TDataBlock.needs_memref_load(binary_operation._rhs):
1606 const_zero_id = SyntaxTree.TDataBlock.ensure_const_zero(const_zero_id, indent_level)
1607 rhs = SyntaxTree.TDataBlock.generate_memref_load(binary_operation._rhs, rhs, const_zero_id, indent_level)
1609 rhs = SyntaxTree.BinaryOperation.cast_operand(rhs, binary_operation._rhs, op_type_class, indent_level)
1612 for mlir
in SyntaxTree.Node.context.pop_block().get_mlir():
1613 mlir_str += indent + mlir.strip(
' ')
1615 binary_operation.mlir_id(f
"%{SyntaxTree.Node.get_mlir_id()}")
1617 mlir_str += indent + f
"""{binary_operation.mlir_id()} = {binary_operation.get_mlir_op()} {lhs}, {rhs} : {result_type}\n"""
1618 SyntaxTree.Node.context.push_block()
1619 SyntaxTree.Node.context.get_block().mlir_append(mlir_str)
1621 return binary_operation.mlir_id()
1625 unary_operation._operand.hoist(
True)
1627 operand_type = unary_operation._operand.get_type()
1628 if isinstance(operand_type, SyntaxTree.TDataBlock):
1629 element_type_class = operand_type.get_element_type()
1630 operand_type = element_type_class()
if element_type_class
else operand_type
1632 if isinstance(operand_type, SyntaxTree.TFloat):
1633 if unary_operation._operation ==
"+":
1634 SyntaxTree.Node.context.get_block().mlir_append(unary_operation._operand.print(self, indent_level))
1635 return unary_operation.mlir_id()
1636 elif unary_operation._operation ==
"-":
1637 op_mlir = unary_operation._operand.print(self, indent_level).strip(
' ')
1638 mlir_str =
"".join(SyntaxTree.Node.context.get_block().pop_mlir())
1639 neg_one_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1640 mlir_str += indent + f
"{neg_one_id} = arith.constant -1.0 : f64\n"
1642 unary_operation.mlir_id(f
"%{SyntaxTree.Node.get_mlir_id()}")
1643 mlir_str += indent + f
"{unary_operation.mlir_id()} = arith.mulf {op_mlir}, {neg_one_id} : f64\n"
1644 SyntaxTree.Node.context.push_block()
1645 SyntaxTree.Node.context.get_block().mlir_append(mlir_str)
1646 return unary_operation.mlir_id()
1648 if unary_operation._operation ==
"+":
1649 SyntaxTree.Node.context.get_block().mlir_append(unary_operation._operand.print(self, indent_level))
1650 return unary_operation.mlir_id()
1651 elif unary_operation._operation ==
"-":
1652 op_mlir = unary_operation._operand.print(self, indent_level).strip(
' ')
1653 mlir_str =
"".join(SyntaxTree.Node.context.get_block().pop_mlir())
1654 neg_one_id = f
"%{SyntaxTree.Node.get_mlir_id()}"
1655 mlir_str += indent + f
"{neg_one_id} = arith.constant -1 : i32\n"
1657 unary_operation.mlir_id(f
"%{SyntaxTree.Node.get_mlir_id()}")
1658 mlir_str += indent + f
"{unary_operation.mlir_id()} = arith.muli {op_mlir}, {neg_one_id} : i32\n"
1659 SyntaxTree.Node.context.push_block()
1660 SyntaxTree.Node.context.get_block().mlir_append(mlir_str)
1661 return unary_operation.mlir_id()
1664 return unary_max._loop.print(self, indent_level)
1667 mlir_type = SyntaxTree.Node.get_mlir_type(type._type)
1668 if mlir_type
is not None:
1669 return ' ' * indent_level * SyntaxTree.Node.spaces_per_tab + mlir_type
1672 type_entry = SyntaxTree.Node.type_map[f
"{type._type}"]
1673 if isinstance(type_entry, str):
1674 return self.
get_indent(indent_level) + type_entry
1677 return self.
get_indent(indent_level) + type_entry.print(self)
1680 return self.
get_indent(indent_level) +
'void'
1700 if isinstance(type._dimensions, int):
1701 dims.append(str(type._dimensions))
1703 for dim
in type._dimensions:
1706 dims.append(str(dim))
1708 dims.append(dim.print(self, indent_level))
1710 SyntaxTree.Node.context.push_block()
1712 op.print(self, indent_level)
1713 dims.append(
''.join(SyntaxTree.Node.context.pop_block().get_mlir()))
1717 if isinstance(type._underlying_type, SyntaxTree.Type):
1718 type_name = type._underlying_type.print(self, indent_level)
1721 type_name = SyntaxTree.Node.get_mlir_type(type._underlying_type._value)
1722 if type_name
is None:
1724 type_name = SyntaxTree.Node.type_map[f
"{type._underlying_type}"]
1728 if isinstance(type_name, str)
and type_name.startswith(
"memref<"):
1729 return ' ' * indent_level * SyntaxTree.Node.spaces_per_tab + type_name
1736 if isinstance(type._dimensions, int):
1737 if type._dimensions == 1:
1743 elif isinstance(type._dimensions, list):
1744 if len(type._dimensions) <= 1:
1752 dimension_list = [
"?"] * actual_dims
1753 memref_dims =
"x".join(dimension_list)
1755 return self.
get_indent(indent_level) + f
"""memref<{memref_dims}x{type_name}>"""
1758 return self.
get_indent(indent_level) + f
'memref<?x{type._element_type.print(self).strip()}>'
1761 return self.
get_indent(indent_level) + f
'memref<?xmemref<?x{type._element_type.print(self).strip()}>>'
1765 dims =
'x'.join([
'?'] * type._dimensions)
1766 return self.
get_indent(indent_level) + f
'memref<{dims}x{type._element_type.print(self).strip()}>'
1769 return self.
get_indent(indent_level) + type._signature
We need to track the context of the code generation to support MLIR class Context:
print_integer_type(self, SyntaxTree.TInteger type, indent_level=0)
print_data_block_construction_from_matrix_vector_product(self, SyntaxTree.DataBlockConstructionFromFunction construction, indent_level=0)
print_argument(self, SyntaxTree.Argument argument, indent_level=0)
print_matrix(self, SyntaxTree.Matrix construction, indent_level=0)
print_string(self, SyntaxTree.String string, indent_level=0)
print_if(self, SyntaxTree.If if_statement, indent_level=0)
print_data_block_construction_from_operation(self, SyntaxTree.DataBlockConstructionFromOperation construction, indent_level=0)
print_string_type(self, SyntaxTree.TString type, indent_level=0)
print_binary_operation(self, SyntaxTree.BinaryOperation binary_operation, indent_level=0)
print_boolean_type(self, SyntaxTree.TBoolean type, indent_level=0)
print_integer(self, SyntaxTree.Integer integer, indent_level=0)
print_custom_type(self, SyntaxTree.TCustom type, indent_level=0)
print_function_call(self, SyntaxTree.FunctionCall function_call, indent_level=0)
str get_indent(self, int indent_level)
print_nested_memref_type(self, SyntaxTree.TNestedMemref type, indent_level=0)
print_diagonal_matrix_construction_from_value(self, SyntaxTree.DataBlockConstructionFromFunction construction, indent_level=0)
print_vector(self, SyntaxTree.Vector vector, indent_level=0)
print_float(self, SyntaxTree.Float float, indent_level=0)
print_data_block_type(self, SyntaxTree.TString type, indent_level=0)
print_memory_deallocation(self, SyntaxTree.MemoryDeallocation memory_deallocation, indent_level=0)
print_function_declaration(self, SyntaxTree.FunctionDefinition function_definition, indent_level=0)
print_boolean(self, SyntaxTree.Boolean boolean, indent_level=0)
print_diagonal_matrix_construction_from_kronecker_product(self, SyntaxTree.DataBlockConstructionFromFunction construction, indent_level=0)
print_max(self, SyntaxTree.Max max, indent_level=0)
print_unary_operation(self, SyntaxTree.UnaryOperation unary_operation, indent_level=0)
print_data_block_construction_from_dot_product(self, SyntaxTree.DataBlockConstructionFromFunction construction, indent_level=0)
print_function_definition(self, SyntaxTree.FunctionDefinition function_definition, indent_level=0)
print_memory_allocation(self, SyntaxTree.MemoryAllocation memory_allocation, indent_level=0)
print_function_declaration_with_timer(self, SyntaxTree.FunctionDefinition function_definition, indent_level=0)
print_comment(self, SyntaxTree.Comment comment, indent_level=0)
print_simple_memref_type(self, SyntaxTree.TSimpleMemref type, indent_level=0)
print_name(self, SyntaxTree.Name name, indent_level=0)
print_void_type(self, SyntaxTree.TVoid type, indent_level=0)
print_reference(self, SyntaxTree.Reference reference, indent_level=0)
print_function_type(self, SyntaxTree.TFunctionType type, indent_level=0)
print_data_block_construction_from_existing(self, SyntaxTree.DataBlockConstructionFromExisting construction, indent_level=0)
print_matrix_construction_from_kronecker_product(self, SyntaxTree.DataBlockConstructionFromFunction construction, indent_level=0)
print_data_block_unary_max(self, SyntaxTree.DataBlockUnaryMax unary_max, indent_level=0)
print_diagonal_matrix(self, SyntaxTree.DiagonalMatrix matrix, indent_level=0)
print_vector_index(self, SyntaxTree.VectorIndex vector_index, indent_level=0)
print_data_block_construction_from_function(self, SyntaxTree.DataBlockConstructionFromFunction construction, indent_level=0)
print_function_definition_with_timer(self, SyntaxTree.FunctionDefinition function_definition, indent_level=0)
print_comparison(self, SyntaxTree.Comparison comparison, indent_level=0)
__init__(self, spaces_per_tab=2, use_omp=False)
print_data_block_assignment(self, SyntaxTree.DataBlockAssignment assignment, indent_level=0)
print_long_type(self, SyntaxTree.TLong type, indent_level=0)
print_subscript(self, SyntaxTree.Subscript subscript, indent_level=0)
print_assignment(self, SyntaxTree.Assignment assignment, indent_level=0)
print_data_block(self, SyntaxTree.DataBlock data_block, indent_level=0)
print_float_type(self, SyntaxTree.TFloat type, indent_level=0)
print_vector_type(self, SyntaxTree.TVector type, indent_level=0)
print_construction(self, SyntaxTree.Construction construction, indent_level=0)
print_for(self, SyntaxTree.For for_statement, indent_level=0)