Reference Guide  2.5.0
psyclone.psyir.transformations.inline_trans.InlineTrans Class Reference
Inheritance diagram for psyclone.psyir.transformations.inline_trans.InlineTrans:
Collaboration diagram for psyclone.psyir.transformations.inline_trans.InlineTrans:

Public Member Functions

def apply (self, node, options=None)
 
def validate (self, node, options=None)
 
- Public Member Functions inherited from psyclone.psyGen.Transformation
def name (self)
 

Detailed Description

This transformation takes a Call (which may have a return value)
and replaces it with the body of the target routine. It is used as
follows:

>>> from psyclone.psyir.backend.fortran import FortranWriter
>>> from psyclone.psyir.frontend.fortran import FortranReader
>>> from psyclone.psyir.nodes import Call, Routine
>>> from psyclone.psyir.transformations import InlineTrans
>>> code = """
... module test_mod
... contains
...   subroutine run_it()
...     integer :: i
...     real :: a(10)
...     do i=1,10
...       a(i) = 1.0
...       call sub(a(i))
...     end do
...   end subroutine run_it
...   subroutine sub(x)
...     real, intent(inout) :: x
...     x = 2.0*x
...   end subroutine sub
... end module test_mod"""
>>> psyir = FortranReader().psyir_from_source(code)
>>> call = psyir.walk(Call)[0]
>>> inline_trans = InlineTrans()
>>> inline_trans.apply(call)
>>> # Uncomment the following line to see a text view of the schedule
>>> # print(psyir.walk(Routine)[0].view())
>>> print(FortranWriter()(psyir.walk(Routine)[0]))
subroutine run_it()
  integer :: i
  real, dimension(10) :: a
<BLANKLINE>
  do i = 1, 10, 1
    a(i) = 1.0
    a(i) = 2.0 * a(i)
  enddo
<BLANKLINE>
end subroutine run_it
<BLANKLINE>

.. warning::
    Routines/calls with any of the following characteristics are not
    supported and will result in a TransformationError:

    * the routine is not in the same file as the call;
    * the routine contains an early Return statement;
    * the routine contains a variable with UnknownInterface;
    * the routine contains a variable with StaticInterface;
    * the routine contains an UnsupportedType variable with
      ArgumentInterface;
    * the routine has a named argument;
    * the shape of any array arguments as declared inside the routine does
      not match the shape of the arrays being passed as arguments;
    * the routine accesses an un-resolved symbol;
    * the routine accesses a symbol declared in the Container to which it
      belongs.

    Some of these restrictions will be lifted by #924.

Definition at line 60 of file inline_trans.py.

Member Function Documentation

◆ apply()

def psyclone.psyir.transformations.inline_trans.InlineTrans.apply (   self,
  node,
  options = None 
)
Takes the body of the routine that is the target of the supplied
call and replaces the call with it.

:param node: target PSyIR node.
:type node: :py:class:`psyclone.psyir.nodes.Routine`
:param options: a dictionary with options for transformations.
:type options: Optional[Dict[str, Any]]

Reimplemented from psyclone.psyGen.Transformation.

Definition at line 125 of file inline_trans.py.

125  def apply(self, node, options=None):
126  '''
127  Takes the body of the routine that is the target of the supplied
128  call and replaces the call with it.
129 
130  :param node: target PSyIR node.
131  :type node: :py:class:`psyclone.psyir.nodes.Routine`
132  :param options: a dictionary with options for transformations.
133  :type options: Optional[Dict[str, Any]]
134 
135  '''
136  self.validate(node, options)
137  # The table associated with the scoping region holding the Call.
138  table = node.scope.symbol_table
139  # Find the routine to be inlined.
140  orig_routine = self._find_routine(node)
141 
142  if not orig_routine.children or isinstance(orig_routine.children[0],
143  Return):
144  # Called routine is empty so just remove the call.
145  node.detach()
146  return
147 
148  # Ensure we don't modify the original Routine by working with a
149  # copy of it.
150  routine = orig_routine.copy()
151  routine_table = routine.symbol_table
152 
153  # Construct lists of the nodes that will be inserted and all of the
154  # References that they contain.
155  new_stmts = []
156  refs = []
157  for child in routine.children:
158  new_stmts.append(child.copy())
159  refs.extend(new_stmts[-1].walk(Reference))
160 
161  # Shallow copy the symbols from the routine into the table at the
162  # call site.
163  table.merge(routine_table,
164  symbols_to_skip=self._symbols_to_skip(routine_table))
165 
166  # When constructing new references to replace references to formal
167  # args, we need to know whether any of the actual arguments are array
168  # accesses. If they use 'array notation' (i.e. represent a whole array)
169  # then they won't have index expressions and will have been captured
170  # as a Reference.
171  ref2arraytrans = Reference2ArrayRangeTrans()
172 
173  for child in node.arguments:
174  try:
175  # TODO #1858, this won't yet work for arrays inside structures.
176  ref2arraytrans.apply(child)
177  except (TransformationError, ValueError):
178  pass
179 
180  # Replace any references to formal arguments with copies of the
181  # actual arguments.
182  formal_args = routine_table.argument_list
183  for ref in refs[:]:
184  self._replace_formal_arg(ref, node, formal_args)
185 
186  # Store the Routine level symbol table and node's current scope
187  # so we can merge symbol tables later if required.
188  ancestor_table = node.ancestor(Routine).scope.symbol_table
189  scope = node.scope
190 
191  # Copy the nodes from the Routine into the call site.
192  # TODO #924 - while doing this we should ensure that any References
193  # to common/shared Symbols in the inlined code are updated to point
194  # to the ones at the call site.
195  if isinstance(new_stmts[-1], Return):
196  # If the final statement of the routine is a return then
197  # remove it from the list.
198  del new_stmts[-1]
199 
200  if routine.return_symbol:
201  # This is a function
202  assignment = node.ancestor(Assignment)
203  parent = assignment.parent
204  idx = assignment.position-1
205  for child in new_stmts:
206  idx += 1
207  parent.addchild(child, idx)
208  table = parent.scope.symbol_table
209  # Avoid a potential name clash with the original function
210  table.rename_symbol(
211  routine.return_symbol, table.next_available_name(
212  f"inlined_{routine.return_symbol.name}"))
213  node.replace_with(Reference(routine.return_symbol))
214  else:
215  # This is a call
216  parent = node.parent
217  idx = node.position
218  node.replace_with(new_stmts[0])
219  for child in new_stmts[1:]:
220  idx += 1
221  parent.addchild(child, idx)
222 
223  # If the scope we merged the inlined function's symbol table into
224  # is not a Routine scope then we now merge that symbol table into
225  # the ancestor Routine. This avoids issues like #2424 when
226  # applying ParallelLoopTrans to loops containing inlined calls.
227  if ancestor_table is not scope.symbol_table:
228  ancestor_table.merge(scope.symbol_table)
229  replacement = type(scope.symbol_table)()
230  scope.symbol_table.detach()
231  replacement.attach(scope)
232 

References psyclone.psyir.transformations.inline_trans.InlineTrans._create_inlined_idx(), psyclone.psyir.transformations.inline_trans.InlineTrans._find_routine(), psyclone.psyir.transformations.inline_trans.InlineTrans._replace_formal_arg(), psyclone.psyir.transformations.inline_trans.InlineTrans._replace_formal_struc_arg(), psyclone.psyir.transformations.inline_trans.InlineTrans._symbols_to_skip(), psyclone.psyir.transformations.inline_trans.InlineTrans._update_actual_indices(), psyclone.domain.lfric.kernel.lfric_kernel_metadata.LFRicKernelMetadata.validate(), psyclone.transformations.MoveTrans.validate(), psyclone.transformations.Dynamo0p3AsyncHaloExchangeTrans.validate(), psyclone.domain.common.transformations.alg_invoke_2_psy_call_trans.AlgInvoke2PSyCallTrans.validate(), psyclone.domain.common.transformations.alg_trans.AlgTrans.validate(), psyclone.domain.common.transformations.kernel_module_inline_trans.KernelModuleInlineTrans.validate(), psyclone.domain.common.transformations.raise_psyir_2_alg_trans.RaisePSyIR2AlgTrans.validate(), psyclone.domain.gocean.transformations.gocean_const_loop_bounds_trans.GOConstLoopBoundsTrans.validate(), psyclone.domain.gocean.transformations.gocean_move_iteration_boundaries_inside_kernel_trans.GOMoveIterationBoundariesInsideKernelTrans.validate(), psyclone.domain.gocean.transformations.gocean_opencl_trans.GOOpenCLTrans.validate(), psyclone.domain.gocean.transformations.raise_psyir_2_gocean_kern_trans.RaisePSyIR2GOceanKernTrans.validate(), psyclone.domain.lfric.transformations.lfric_alg_invoke_2_psy_call_trans.LFRicAlgInvoke2PSyCallTrans.validate(), psyclone.domain.lfric.transformations.raise_psyir_2_lfric_kern_trans.RaisePSyIR2LFRicKernTrans.validate(), psyclone.domain.nemo.transformations.create_nemo_invoke_schedule_trans.CreateNemoInvokeScheduleTrans.validate(), psyclone.domain.nemo.transformations.create_nemo_psy_trans.CreateNemoPSyTrans.validate(), psyclone.domain.nemo.transformations.nemo_allarrayrange2loop_trans.NemoAllArrayRange2LoopTrans.validate(), psyclone.domain.nemo.transformations.nemo_arrayrange2loop_trans.NemoArrayRange2LoopTrans.validate(), psyclone.domain.nemo.transformations.nemo_outerarrayrange2loop_trans.NemoOuterArrayRange2LoopTrans.validate(), psyclone.psyad.transformations.assignment_trans.AssignmentTrans.validate(), psyclone.psyGen.Transformation.validate(), psyclone.psyir.transformations.acc_update_trans.ACCUpdateTrans.validate(), psyclone.psyir.transformations.allarrayaccess2loop_trans.AllArrayAccess2LoopTrans.validate(), psyclone.psyir.transformations.arrayaccess2loop_trans.ArrayAccess2LoopTrans.validate(), psyclone.psyir.transformations.arrayrange2loop_trans.ArrayRange2LoopTrans.validate(), psyclone.psyir.transformations.chunk_loop_trans.ChunkLoopTrans.validate(), psyclone.psyir.transformations.fold_conditional_return_expressions_trans.FoldConditionalReturnExpressionsTrans.validate(), psyclone.psyir.transformations.hoist_local_arrays_trans.HoistLocalArraysTrans.validate(), psyclone.psyir.transformations.hoist_loop_bound_expr_trans.HoistLoopBoundExprTrans.validate(), psyclone.psyir.transformations.hoist_trans.HoistTrans.validate(), psyclone.psyir.transformations.inline_trans.InlineTrans.validate(), psyclone.psyir.transformations.intrinsics.array_reduction_base_trans.ArrayReductionBaseTrans.validate(), psyclone.psyir.transformations.intrinsics.dotproduct2code_trans.DotProduct2CodeTrans.validate(), psyclone.psyir.transformations.intrinsics.intrinsic2code_trans.Intrinsic2CodeTrans.validate(), psyclone.psyir.transformations.intrinsics.matmul2code_trans.Matmul2CodeTrans.validate(), psyclone.psyir.transformations.loop_swap_trans.LoopSwapTrans.validate(), psyclone.psyir.transformations.loop_tiling_2d_trans.LoopTiling2DTrans.validate(), psyclone.psyir.transformations.loop_trans.LoopTrans.validate(), psyclone.psyir.transformations.omp_task_trans.OMPTaskTrans.validate(), psyclone.psyir.transformations.omp_taskwait_trans.OMPTaskwaitTrans.validate(), psyclone.psyir.transformations.parallel_loop_trans.ParallelLoopTrans.validate(), psyclone.psyir.transformations.reference2arrayrange_trans.Reference2ArrayRangeTrans.validate(), psyclone.psyir.transformations.replace_induction_variables_trans.ReplaceInductionVariablesTrans.validate(), psyclone.transformations.OMPDeclareTargetTrans.validate(), psyclone.transformations.DynamoOMPParallelLoopTrans.validate(), psyclone.transformations.Dynamo0p3OMPLoopTrans.validate(), psyclone.transformations.GOceanOMPLoopTrans.validate(), psyclone.transformations.Dynamo0p3RedundantComputationTrans.validate(), psyclone.transformations.Dynamo0p3KernelConstTrans.validate(), psyclone.transformations.ACCRoutineTrans.validate(), psyclone.transformations.KernelImportsToArguments.validate(), psyclone.domain.gocean.transformations.gocean_loop_fuse_trans.GOceanLoopFuseTrans.validate(), psyclone.domain.lfric.transformations.lfric_loop_fuse_trans.LFRicLoopFuseTrans.validate(), psyclone.psyir.transformations.loop_fuse_trans.LoopFuseTrans.validate(), psyclone.domain.gocean.transformations.gocean_extract_trans.GOceanExtractTrans.validate(), psyclone.domain.lfric.transformations.lfric_extract_trans.LFRicExtractTrans.validate(), psyclone.psyir.transformations.extract_trans.ExtractTrans.validate(), psyclone.psyir.transformations.nan_test_trans.NanTestTrans.validate(), psyclone.psyir.transformations.read_only_verify_trans.ReadOnlyVerifyTrans.validate(), psyclone.transformations.ParallelRegionTrans.validate(), psyclone.transformations.OMPParallelTrans.validate(), psyclone.transformations.ACCParallelTrans.validate(), psyclone.transformations.ACCKernelsTrans.validate(), psyclone.transformations.ACCDataTrans.validate(), psyclone.psyir.transformations.psy_data_trans.PSyDataTrans.validate(), psyclone.psyir.transformations.region_trans.RegionTrans.validate(), and psyclone.transformations.ACCEnterDataTrans.validate().

◆ validate()

def psyclone.psyir.transformations.inline_trans.InlineTrans.validate (   self,
  node,
  options = None 
)
Checks that the supplied node is a valid target for inlining.

:param node: target PSyIR node.
:type node: subclass of :py:class:`psyclone.psyir.nodes.Call`
:param options: a dictionary with options for transformations.
:type options: Optional[Dict[str, Any]]

:raises TransformationError: if the supplied node is not a Call or is \
    an IntrinsicCall.
:raises TransformationError: if the routine has a return value.
:raises TransformationError: if the routine body contains a Return \
    that is not the first or last statement.
:raises TransformationError: if the routine body contains a CodeBlock.
:raises TransformationError: if the called routine has a named \
    argument.
:raises TransformationError: if any of the variables declared within \
    the called routine are of UnknownInterface.
:raises TransformationError: if any of the variables declared within \
    the called routine have a StaticInterface.
:raises TransformationError: if any of the subroutine arguments is of \
    UnsupportedType.
:raises TransformationError: if a symbol of a given name is imported \
    from different containers at the call site and within the routine.
:raises TransformationError: if the routine accesses an un-resolved \
    symbol.
:raises TransformationError: if the number of arguments in the call \
    does not match the number of formal arguments of the routine.
:raises TransformationError: if a symbol declared in the parent \
    container is accessed in the target routine.
:raises TransformationError: if the shape of an array formal argument \
    does not match that of the corresponding actual argument.

Reimplemented from psyclone.psyGen.Transformation.

Definition at line 604 of file inline_trans.py.

604  def validate(self, node, options=None):
605  '''
606  Checks that the supplied node is a valid target for inlining.
607 
608  :param node: target PSyIR node.
609  :type node: subclass of :py:class:`psyclone.psyir.nodes.Call`
610  :param options: a dictionary with options for transformations.
611  :type options: Optional[Dict[str, Any]]
612 
613  :raises TransformationError: if the supplied node is not a Call or is \
614  an IntrinsicCall.
615  :raises TransformationError: if the routine has a return value.
616  :raises TransformationError: if the routine body contains a Return \
617  that is not the first or last statement.
618  :raises TransformationError: if the routine body contains a CodeBlock.
619  :raises TransformationError: if the called routine has a named \
620  argument.
621  :raises TransformationError: if any of the variables declared within \
622  the called routine are of UnknownInterface.
623  :raises TransformationError: if any of the variables declared within \
624  the called routine have a StaticInterface.
625  :raises TransformationError: if any of the subroutine arguments is of \
626  UnsupportedType.
627  :raises TransformationError: if a symbol of a given name is imported \
628  from different containers at the call site and within the routine.
629  :raises TransformationError: if the routine accesses an un-resolved \
630  symbol.
631  :raises TransformationError: if the number of arguments in the call \
632  does not match the number of formal arguments of the routine.
633  :raises TransformationError: if a symbol declared in the parent \
634  container is accessed in the target routine.
635  :raises TransformationError: if the shape of an array formal argument \
636  does not match that of the corresponding actual argument.
637 
638  '''
639  super().validate(node, options=options)
640 
641  # The node should be a Call.
642  if not isinstance(node, Call):
643  raise TransformationError(
644  f"The target of the InlineTrans transformation "
645  f"should be a Call but found '{type(node).__name__}'.")
646 
647  if isinstance(node, IntrinsicCall):
648  raise TransformationError(
649  f"Cannot inline an IntrinsicCall ('{node.routine.name}')")
650  name = node.routine.name
651  # Check that we can find the source of the routine being inlined.
652  routine = self._find_routine(node)
653 
654  if not routine.children or isinstance(routine.children[0], Return):
655  # An empty routine is fine.
656  return
657 
658  return_stmts = routine.walk(Return)
659  if return_stmts:
660  if len(return_stmts) > 1 or not isinstance(routine.children[-1],
661  Return):
662  # Either there is more than one Return statement or there is
663  # just one but it isn't the last statement of the Routine.
664  raise TransformationError(
665  f"Routine '{name}' contains one or more "
666  f"Return statements and therefore cannot be inlined.")
667 
668  if routine.walk(CodeBlock):
669  raise TransformationError(
670  f"Routine '{name}' contains one or more "
671  f"CodeBlocks and therefore cannot be inlined.")
672 
673  # Support for routines with named arguments is not yet implemented.
674  # TODO #924.
675  for arg in node.argument_names:
676  if arg:
677  raise TransformationError(
678  f"Routine '{routine.name}' cannot be inlined because it "
679  f"has a named argument '{arg}' (TODO #924).")
680 
681  table = node.scope.symbol_table
682  routine_table = routine.symbol_table
683 
684  for sym in routine_table.datasymbols:
685  # We don't inline symbols that have an UnsupportedType and are
686  # arguments since we don't know if a simple assingment if
687  # enough (e.g. pointers)
688  if isinstance(sym.interface, ArgumentInterface):
689  if isinstance(sym.datatype, UnsupportedType):
690  raise TransformationError(
691  f"Routine '{routine.name}' cannot be inlined because "
692  f"it contains a Symbol '{sym.name}' which is an "
693  f"Argument of UnsupportedType: "
694  f"'{sym.datatype.declaration}'")
695  # We don't inline symbols that have an UnknownInterface, as we
696  # don't know how they are brought into this scope.
697  if isinstance(sym.interface, UnknownInterface):
698  raise TransformationError(
699  f"Routine '{routine.name}' cannot be inlined because it "
700  f"contains a Symbol '{sym.name}' with an UnknownInterface:"
701  f" '{sym.datatype.declaration}'")
702  # Check that there are no static variables in the routine (because
703  # we don't know whether the routine is called from other places).
704  if (isinstance(sym.interface, StaticInterface) and
705  not sym.is_constant):
706  raise TransformationError(
707  f"Routine '{routine.name}' cannot be inlined because it "
708  f"has a static (Fortran SAVE) interface for Symbol "
709  f"'{sym.name}'.")
710 
711  # We can't handle a clash between (apparently) different symbols that
712  # share a name but are imported from different containers.
713  try:
714  table.check_for_clashes(
715  routine_table,
716  symbols_to_skip=self._symbols_to_skip(routine_table))
717  except SymbolError as err:
718  raise TransformationError(
719  f"One or more symbols from routine '{routine.name}' cannot be "
720  f"added to the table at the call site.") from err
721 
722  # Check for unresolved symbols or for any accessed from the Container
723  # containing the target routine.
724  # TODO #1792 - kind parameters will not be found by simply doing
725  # `walk(Reference)`. Although SymbolTable has the
726  # `precision_datasymbols` property, this only returns those Symbols
727  # that are used to define the precision of other Symbols in the same
728  # table. If a precision symbol is only used within Statements then we
729  # don't currently capture the fact that it is a precision symbol.
730  ref_or_lits = routine.walk((Reference, Literal))
731  # Check for symbols in any initial-value expressions
732  # (including Fortran parameters) or array dimensions.
733  for sym in routine_table.datasymbols:
734  if sym.initial_value:
735  ref_or_lits.extend(
736  sym.initial_value.walk((Reference, Literal)))
737  if isinstance(sym.datatype, ArrayType):
738  for dim in sym.shape:
739  if isinstance(dim, ArrayType.ArrayBounds):
740  if isinstance(dim.lower, Node):
741  ref_or_lits.extend(dim.lower.walk(Reference,
742  Literal))
743  if isinstance(dim.upper, Node):
744  ref_or_lits.extend(dim.upper.walk(Reference,
745  Literal))
746  # Keep a reference to each Symbol that we check so that we can avoid
747  # repeatedly checking the same Symbol.
748  _symbol_cache = set()
749  for lnode in ref_or_lits:
750  if isinstance(lnode, Literal):
751  if not isinstance(lnode.datatype.precision, DataSymbol):
752  continue
753  sym = lnode.datatype.precision
754  else:
755  sym = lnode.symbol
756  # If we've already seen this Symbol then we can skip it.
757  if sym in _symbol_cache:
758  continue
759  _symbol_cache.add(sym)
760  if isinstance(sym, IntrinsicSymbol):
761  continue
762  # We haven't seen this Symbol before.
763  if sym.is_unresolved:
764  try:
765  routine_table.resolve_imports(symbol_target=sym)
766  except KeyError:
767  # The symbol is not (directly) imported into the symbol
768  # table local to the routine.
769  # pylint: disable=raise-missing-from
770  raise TransformationError(
771  f"Routine '{routine.name}' cannot be inlined "
772  f"because it accesses variable '{sym.name}' and this "
773  f"cannot be found in any of the containers directly "
774  f"imported into its symbol table.")
775  else:
776  if sym.name not in routine_table:
777  raise TransformationError(
778  f"Routine '{routine.name}' cannot be inlined because "
779  f"it accesses variable '{sym.name}' from its "
780  f"parent container.")
781 
782  # Check that the shapes of any formal array arguments are the same as
783  # those at the call site.
784  if len(routine_table.argument_list) != len(node.arguments):
785  raise TransformationError(LazyString(
786  lambda: f"Cannot inline '{node.debug_string().strip()}' "
787  f"because the number of arguments supplied to the call "
788  f"({len(node.arguments)}) does not match the number of "
789  f"arguments the routine is declared to have "
790  f"({len(routine_table.argument_list)})."))
791 
792  for formal_arg, actual_arg in zip(routine_table.argument_list,
793  node.arguments):
794  # If the formal argument is an array with non-default bounds then
795  # we also need to know the bounds of that array at the call site.
796  if not isinstance(formal_arg.datatype, ArrayType):
797  # Formal argument is not an array so we don't need to do any
798  # further checks.
799  continue
800 
801  if not isinstance(actual_arg, (Reference, Literal)):
802  # TODO #1799 this really needs the `datatype` method to be
803  # extended to support all nodes. For now we have to abort
804  # if we encounter an argument that is not a scalar (according
805  # to the corresponding formal argument) but is not a
806  # Reference or a Literal as we don't know whether the result
807  # of any general expression is or is not an array.
808  # pylint: disable=cell-var-from-loop
809  raise TransformationError(LazyString(
810  lambda: f"The call '{node.debug_string()}' cannot be "
811  f"inlined because actual argument "
812  f"'{actual_arg.debug_string()}' corresponds to a "
813  f"formal argument with array type but is not a "
814  f"Reference or a Literal."))
815 
816  # We have an array argument. We are only able to check that the
817  # argument is not re-shaped in the called routine if we have full
818  # type information on the actual argument.
819  # TODO #924. It would be useful if the `datatype` property was
820  # a method that took an optional 'resolve' argument to indicate
821  # that it should attempt to resolve any UnresolvedTypes.
822  if (isinstance(actual_arg.datatype,
823  (UnresolvedType, UnsupportedType)) or
824  (isinstance(actual_arg.datatype, ArrayType) and
825  isinstance(actual_arg.datatype.intrinsic,
826  (UnresolvedType, UnsupportedType)))):
827  raise TransformationError(
828  f"Routine '{routine.name}' cannot be inlined because "
829  f"the type of the actual argument "
830  f"'{actual_arg.symbol.name}' corresponding to an array"
831  f" formal argument ('{formal_arg.name}') is unknown.")
832 
833  formal_rank = 0
834  actual_rank = 0
835  if isinstance(formal_arg.datatype, ArrayType):
836  formal_rank = len(formal_arg.datatype.shape)
837  if isinstance(actual_arg.datatype, ArrayType):
838  actual_rank = len(actual_arg.datatype.shape)
839  if formal_rank != actual_rank:
840  # It's OK to use the loop variable in the lambda definition
841  # because if we get to this point then we're going to quit
842  # the loop.
843  # pylint: disable=cell-var-from-loop
844  raise TransformationError(LazyString(
845  lambda: f"Cannot inline routine '{routine.name}' "
846  f"because it reshapes an argument: actual argument "
847  f"'{actual_arg.debug_string()}' has rank {actual_rank}"
848  f" but the corresponding formal argument, "
849  f"'{formal_arg.name}', has rank {formal_rank}"))
850  if actual_rank:
851  ranges = actual_arg.walk(Range)
852  for rge in ranges:
853  ancestor_ref = rge.ancestor(Reference)
854  if ancestor_ref is not actual_arg:
855  # Have a range in an indirect access.
856  # pylint: disable=cell-var-from-loop
857  raise TransformationError(LazyString(
858  lambda: f"Cannot inline routine '{routine.name}' "
859  f"because argument '{actual_arg.debug_string()}' "
860  f"has an array range in an indirect access (TODO "
861  f"#924)."))
862  if rge.step != _ONE:
863  # TODO #1646. We could resolve this problem by making
864  # a new array and copying the necessary values into it.
865  # pylint: disable=cell-var-from-loop
866  raise TransformationError(LazyString(
867  lambda: f"Cannot inline routine '{routine.name}' "
868  f"because one of its arguments is an array slice "
869  f"with a non-unit stride: "
870  f"'{actual_arg.debug_string()}' (TODO #1646)"))
871 

References psyclone.psyir.transformations.inline_trans.InlineTrans._find_routine(), and psyclone.psyir.transformations.inline_trans.InlineTrans._symbols_to_skip().

Here is the call graph for this function:
Here is the caller graph for this function:

The documentation for this class was generated from the following file: