(Towards #2577) Add pointer and target attributes in datatypes, frontend and backend#2822
(Towards #2577) Add pointer and target attributes in datatypes, frontend and backend#2822JulienRemy wants to merge 12 commits intomasterfrom
pointer and target attributes in datatypes, frontend and backend#2822Conversation
…ureType.ComponentType`, frontend and backend. NOTE: tests not done.
…nstead of Symbols. Some tests.
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #2822 +/- ##
==========================================
- Coverage 99.88% 99.88% -0.01%
==========================================
Files 357 357
Lines 49742 49960 +218
==========================================
+ Hits 49686 49903 +217
- Misses 56 57 +1 ☔ View full report in Codecov by Sentry. |
arporter
left a comment
There was a problem hiding this comment.
Very nicely done, thanks Julien. Implementation is good, tests good (just need a bit more coverage). As you say in a previous comment, I am concerned about putting this onto master as is as it opens the door to potential problems. Therefore, I think we do have to tackle making sure that transformations that care about this do the right thing (at this stage, that can simply be refuse to do anything). I suggest going through the list in the Reference Guide:

and checking whether or not they should care about aliasing.
| has_pointer_attr = True | ||
| elif normalized_string == "target": | ||
| has_target_attr = True | ||
| elif isinstance(attr, (Fortran2003.Attr_Spec, |
There was a problem hiding this comment.
Since you do normalized_string = str(attr).lower().replace(' ', '') in both cases, can you now remove the elif isinstance(attr, (Fortran2003.xxxxx)) and hoist the if normalized_string == "save": up a level?
| f"SAVE and PARAMETER attributes are not compatible but " | ||
| f"found:\n {decl}") | ||
|
|
||
| # TODO check these are needed |
There was a problem hiding this comment.
I think they are. I bet fparser doesn't check. Please update the comment.
| f"found:\n {decl}") | ||
| if has_pointer_attr and has_constant_value: | ||
| raise GenerationError( | ||
| f"POINTER and PARAMETER attributes are not compatible but " |
There was a problem hiding this comment.
Probably also true for TARGET and PARAMETER?
|
|
||
| # 2: Remove any unsupported attributes | ||
| unsupported_attribute_names = ["pointer", "target", "optional"] | ||
| unsupported_attribute_names = ["asynchronous", "volatile", "optional"] |
There was a problem hiding this comment.
Possibly "contiguous" too although @hiker wants to add support for that soon I think.
| :param is_target: whether this is a target symbol. | ||
| :type is_target: bool | ||
|
|
||
| ''' |
There was a problem hiding this comment.
Please document the new :raises: that you've added.
| # Test that when it is part of an UnsupportedType (target attribute in | ||
| # this case) it becomes an UnknownInterface. | ||
| reader = FortranStringReader("integer, target :: var5") | ||
| # Test that when it is part of an UnsupportedType (asynchronous attribute |
| "INTEGER, PRIVATE, DIMENSION(3), POINTER :: g") | ||
| "INTEGER, PRIVATE, DIMENSION(3), ASYNCHRONOUS :: g") | ||
|
|
||
| # Test with unsupported intrinsic type. Note the space before complex |
There was a problem hiding this comment.
Please add/extend tests that the partial datatype of an UnsupportedFortranType correctly captures the new is_pointer/is_target properties of a declaration.
| with pytest.raises(ValueError) as err: | ||
| _ = DataTypeSymbol("my_type", UnresolvedType(), is_pointer=True, | ||
| is_target=True) | ||
| assert ("A symbol cannot be both a pointer and a target" in str(err.value)) |
There was a problem hiding this comment.
Useful to include the name of the proposed symbol in this error message.
| assert ("__str__" in msg) | ||
|
|
||
|
|
||
| def test_datatype_is_pointer_is_target(): |
There was a problem hiding this comment.
As commented on in the source, an unresolved type is just that - if we have any information on it then that goes in its partial_datatype (although I think only an UnsupportedFortranType has that).
| f"Expected result and operands of MATMUL IntrinsicCall to " | ||
| f"be references to arrays that are not potentially aliased " | ||
| f"but found '{result.symbol}', '{matrix1.symbol}' and " | ||
| f"'{matrix2.symbol}'.") |
There was a problem hiding this comment.
probably worth adding "...symbol}' in '{node.debug_string()}'." to give more information.
sergisiso
left a comment
There was a problem hiding this comment.
I see @arporter already reviewed it, so I will let him continue being the reviewer for this, but I had some comments already stored in github so I will push them anyway (even though some are the same as @arporter ). The reason I never finished this review is that it was unclear to me if the "is a pointer" attribute had to be part of the symbol itself or the datatype of the symbol. And I think it would be good to discuss this before we commit to a solution.
| # NOTE: for a routine declaration, 'POINTER' or 'TARGET' is | ||
| # an Attr_Spec, but in a derived type declaration component | ||
| # it is not. | ||
| normalized_string = str(attr).lower().replace(' ', '') | ||
| if normalized_string == "pointer": | ||
| has_pointer_attr = True | ||
| elif normalized_string == "target": | ||
| has_target_attr = True |
There was a problem hiding this comment.
Can this not be part of the normalized_string checks inside the:
if isinstance(attr, (Fortran2003.Attr_Spec, Fortran2003.Component_Attr_Spec)
Looking at the standard for derived type it should be in "Component_Attr_Spec" so I don't know why this is different than "save", "parameter", ...
| f"SAVE and PARAMETER attributes are not compatible but " | ||
| f"found:\n {decl}") | ||
|
|
||
| # TODO check these are needed |
There was a problem hiding this comment.
I tried with 'gfortran' and they are both errors, but fparser does not report them, so it is good to have them here. You can remove the TODO.
There was a problem hiding this comment.
Target and parameter together also fails, can you add it here?
| :raises TransformationError: if any of the arrays are potentially \ | ||
| aliased. | ||
| :raises TransformationError: if sub-sections of an array are present \ |
There was a problem hiding this comment.
You don't need the backslashes
|
|
||
| @property | ||
| def is_unresolved(self): | ||
| ''' | ||
| :returns: whether the Symbol has an UnresolvedInterface or its | ||
| datatype is an UnresolvedType. | ||
| :rtype: bool | ||
| ''' | ||
| # Import here to avoid circular dependencies | ||
| # pylint: disable=import-outside-toplevel | ||
| from psyclone.psyir.symbols.datatypes import UnresolvedType | ||
| return (super().is_unresolved | ||
| or isinstance(self.datatype, UnresolvedType)) |
There was a problem hiding this comment.
I would prefer to remove this, as it changes the definition of the super class which is that this only checks for UnresolvedInterface.
I suppose you needed this in some place that then checks for properties of the datatype (e.g. symbol.datatype. ...), I think you will need to do this check there. Would that work?
This starts implementing point 2 of Sergi's list in #2577 by adding new attributes to datatypes, as well as frontend and backend support for them.
Note that
is_potentially_aliasedis not used anywhere, except to fix an existingMatmul2CodeTranstest.So this does not check for aliasing anywhere else for now. Stated differently, this might be dangerous to merge as it effectively supports pointers in PSyIR but does not yet restrict transformations to non-aliased variables.