Skip to content

Commit

Permalink
Merge pull request #2283 from stfc/2282_ubound_expression
Browse files Browse the repository at this point in the history
(Closes #2282 and #2286) Added and tested a get_ubound_expression function
  • Loading branch information
arporter authored Sep 11, 2023
2 parents d42daab + 5a77078 commit 3fc7ae0
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 57 deletions.
3 changes: 3 additions & 0 deletions changelog
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,9 @@

197) PR #2281 for #2258. Adds a PSyData wrapper for the TAU profiler.

198) PR #2283 for #2282 and #2286. Adds a get_ubound_expression
method to ArrayMixin (analagous to get_lbound_expression).

release 2.3.1 17th of June 2022

1) PR #1747 for #1720. Adds support for If blocks to PSyAD.
Expand Down
77 changes: 61 additions & 16 deletions src/psyclone/psyir/nodes/array_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
# Authors R. W. Ford, A. R. Porter, S. Siso and N. Nobre, STFC Daresbury Lab
# I. Kavcic, Met Office
# J. Henrichs, Bureau of Meteorology
# Modified: A. B. G. Chalk, STFC Daresbury Lab
# -----------------------------------------------------------------------------

''' This module contains the implementation of the abstract ArrayMixin. '''
Expand Down Expand Up @@ -169,29 +170,32 @@ def is_lower_bound(self, index):
'''
return self._is_bound(index, "lower")

def get_lbound_expression(self, pos):
def _get_bound_expression(self, pos, bound):
'''
Lookup the lower bound of this ArrayMixin. If we don't have the
necessary type information then a call to the LBOUND intrinsic is
constructed and returned.
Lookup the upper or lower bound of this ArrayMixin.
:param int pos: the dimension of the array for which to lookup the \
:param int pos: the dimension of the array for which to lookup the
lower bound.
:param str bound: "upper" or "lower" - the bound which to lookup.
:returns: the declared lower bound for the specified dimension of \
the array accesed or a call to the LBOUND intrinsic if it is \
unknown.
:returns: the declared bound for the specified dimension of this array
or a call to the {U/L}BOUND intrinsic if it is unknown.
:rtype: :py:class:`psyclone.psyir.nodes.Node`
:raises InternalError: if bound is neither upper or lower.
'''
if bound not in ("upper", "lower"):
raise InternalError(f"'bound' argument must be 'lower' or 'upper. "
f"Found '{bound}'.")

# First, walk up to the parent reference and get its type. For a simple
# ArrayReference this will just be self.
root_ref = self.ancestor(Reference, include_self=True)
cursor_type = root_ref.symbol.datatype

# Walk back down the structure, looking up the type information as we
# go. We also collect the necessary information for creating a new
# Reference as argument to the LBOUND intrinsic in case the type
# Reference as argument to the {U/L}BOUND intrinsic in case the type
# information is not available.
cnames = []
cursor = root_ref
Expand All @@ -200,9 +204,9 @@ def get_lbound_expression(self, pos):
# Collect member information.
if isinstance(cursor, ArrayMixin):
new_indices = [idx.copy() for idx in cursor.indices]
cnames.append((cursor.name, new_indices))
cnames.append((cursor.name.lower(), new_indices))
else:
cnames.append(cursor.name)
cnames.append(cursor.name.lower())
# Continue to resolve datatype unless we hit an
# UnknownType or DeferredType.
if isinstance(cursor_type, ArrayType):
Expand All @@ -211,16 +215,18 @@ def get_lbound_expression(self, pos):
cursor_type = cursor_type.datatype
if isinstance(cursor_type, (UnknownType, DeferredType)):
continue
cursor_type = cursor_type.components[cursor.name].datatype
cursor_type = cursor_type.components[cursor.name.lower()].datatype

if (isinstance(cursor_type, ArrayType) and
cursor_type.shape[pos] not in [ArrayType.Extent.DEFERRED,
ArrayType.Extent.ATTRIBUTE]):
# We have the full type information and the lower bound is known.
return cursor_type.shape[pos].lower.copy()
# We have the full type information and the bound is known.
if bound == "lower":
return cursor_type.shape[pos].lower.copy()
return cursor_type.shape[pos].upper.copy()

# We've either failed to resolve the type or we don't know the extent
# of the array dimension so construct a call to the LBOUND intrinsic.
# of the array dimension so construct a call to the BOUND intrinsic.
if cnames:
# We have some sort of structure access - remove any indexing
# information from the ultimate member of the structure access.
Expand All @@ -240,9 +246,48 @@ def get_lbound_expression(self, pos):
# A simple Reference.
ref = Reference(root_ref.symbol)

return BinaryOperation.create(BinaryOperation.Operator.LBOUND, ref,
if bound == "lower":
return BinaryOperation.create(BinaryOperation.Operator.LBOUND, ref,
Literal(str(pos+1), INTEGER_TYPE))
return BinaryOperation.create(BinaryOperation.Operator.UBOUND, ref,
Literal(str(pos+1), INTEGER_TYPE))

def get_lbound_expression(self, pos):
'''
Lookup the lower bound of this ArrayMixin. If we don't have the
necessary type information then a call to the LBOUND intrinsic is
constructed and returned.
:param int pos: the dimension of the array for which to lookup the
lower bound.
:returns: the declared lower bound for the specified dimension of
the array accesed or a call to the LBOUND intrinsic if it is
unknown.
:rtype: :py:class:`psyclone.psyir.nodes.Node`
'''
# Call the helper function
return self._get_bound_expression(pos, "lower")

def get_ubound_expression(self, pos):
'''
Lookup the upper bound of this ArrayMixin. If we don't have the
necessary type information then a call to the UBOUND intrinsic is
constructed and returned.
:param int pos: the dimension of the array for which to lookup the
upper bound.
:returns: the declared upper bound for the specified dimension of
the array accesed or a call to the UBOUND intrinsic if it is
unknown.
:rtype: :py:class:`psyclone.psyir.nodes.Node`
'''
# Call the helper function
return self._get_bound_expression(pos, "upper")

def is_upper_bound(self, index):
'''Returns whether this array access includes the upper bound of
the array for the specified index. Returns True if it is and False
Expand Down
Loading

0 comments on commit 3fc7ae0

Please sign in to comment.