-
Notifications
You must be signed in to change notification settings - Fork 33
Updates for inlining with common variables #3389
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
b417624
0ea7758
2961d29
7a17765
c6fc922
73c8e95
40778f2
5fb11a8
f6ed6c0
fde246d
2d47e40
d387d0e
f45714d
2906609
3d3af9d
e747e28
4ddfcf1
e7c0906
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -48,6 +48,7 @@ | |
| import inspect | ||
| import copy | ||
| import logging | ||
| import re | ||
| from typing import Any, List, Optional, Union, TYPE_CHECKING | ||
|
|
||
| from psyclone.configuration import Config | ||
|
|
@@ -57,6 +58,7 @@ | |
| ImportInterface, RoutineSymbol, Symbol, SymbolError, UnresolvedInterface) | ||
| from psyclone.psyir.symbols.intrinsic_symbol import IntrinsicSymbol | ||
| from psyclone.psyir.symbols.typed_symbol import TypedSymbol | ||
| from psyclone.psyir.symbols.datatypes import UnsupportedFortranType | ||
|
|
||
| if TYPE_CHECKING: | ||
| from psyclone.psyir.nodes.scoping_node import ScopingNode | ||
|
|
@@ -704,6 +706,12 @@ def check_for_clashes(self, other_table, symbols_to_skip=()): | |
| isinstance(other_sym, IntrinsicSymbol)): | ||
| continue | ||
|
|
||
| # If both symbols have CommonBlockInterface, they represent the | ||
| # same shared COMMON-block data. They cannot (and do not need to) | ||
| # be renamed, so treat this as a benign clash. | ||
| if this_sym.is_commonblock and other_sym.is_commonblock: | ||
| continue | ||
|
|
||
| if other_sym.is_import and this_sym.is_import: | ||
| # Both symbols are imported. That's fine as long as they have | ||
| # the same import interface (are imported from the same | ||
|
|
@@ -945,13 +953,34 @@ def _add_symbols_from_table(self, other_table, symbols_to_skip=()): | |
| already been updated to refer to a Container in this table. | ||
|
|
||
| ''' | ||
|
|
||
| for old_sym in other_table.symbols: | ||
|
|
||
| if old_sym in symbols_to_skip or isinstance(old_sym, | ||
| ContainerSymbol): | ||
| # We've dealt with Container symbols in _add_container_symbols. | ||
| continue | ||
|
|
||
| # Avoid duplicate COMMON-block marker symbols when multiple | ||
| # routines sharing the same COMMON blocks are inlined into a | ||
| # single caller. Each routine is parsed independently so its | ||
| # _PSYCLONE_INTERNAL_COMMONBLOCK_N markers carry different | ||
| # numbers and may therefore never trigger the name-clash path; | ||
| # we must scan *all* existing markers in self for an identical | ||
| # declaration before attempting to add. | ||
| if (self._normalize(old_sym.name).startswith( | ||
| "_psyclone_internal_commonblock") | ||
| and isinstance(old_sym.datatype, UnsupportedFortranType)): | ||
| if any( | ||
| sym.datatype.declaration == old_sym.datatype.declaration | ||
| for sym in self.symbols | ||
| if (self._normalize(sym.name).startswith( | ||
| "_psyclone_internal_commonblock") | ||
| and isinstance(sym.datatype, | ||
| UnsupportedFortranType)) | ||
| ): | ||
| continue | ||
|
|
||
| try: | ||
| self.add(old_sym) | ||
|
|
||
|
|
@@ -1000,11 +1029,45 @@ def _handle_symbol_clash(self, old_sym, other_table): | |
|
|
||
| self_sym = self.lookup(old_sym.name) | ||
| if old_sym.is_unresolved and self_sym.is_unresolved: | ||
| # Update after fixing issue #3392 | ||
| # The clashing symbols are both unresolved so we ASSUME that | ||
| # check_for_clashes has previously determined that they must | ||
| # refer to the same thing and we don't have to do anything. | ||
| return | ||
|
|
||
| if old_sym.is_commonblock and self_sym.is_commonblock: | ||
| return | ||
|
|
||
| if (isinstance(old_sym.datatype, UnsupportedFortranType) and | ||
| isinstance(self_sym.datatype, UnsupportedFortranType)): | ||
| if old_sym.datatype.declaration == self_sym.datatype.declaration: | ||
| # Identical COMMON-block markers – already present in self. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment isn't right - they are just the same unsupported type, not necessarily a common block.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In fact, this is quite confusing. I think what we have here is that the two symbols that have a name collision both have a 'common block' interface and also happen to be of UnsupportedFortranType. I think (but could be wrong) that it would also be possible for them to be of a supported type. Unfortunately, we have no way of knowing whether they are both the (same) variable from the same common block. |
||
| return | ||
| # Markers have different declarations. Skip the incoming one only | ||
| # if its COMMON-block name(s) overlap with those already in self: | ||
| # that means the block is already declared and adding a second | ||
| # marker for it would produce a "Symbol X is already in a COMMON | ||
| # block" compile error. If the block names are different this is | ||
| # a genuinely new COMMON block and we fall through to the | ||
| # rename-and-add path below. | ||
| if self._normalize(old_sym.name).startswith( | ||
| "_psyclone_internal_commonblock"): | ||
| _blk_re = re.compile(r"/\s*(\w*)\s*/", re.IGNORECASE) | ||
| old_blocks = set(_blk_re.findall( | ||
| old_sym.datatype.declaration)) | ||
| # Check ALL existing commonblock markers in self, not just | ||
| # the same-named one, because the numbering may differ when | ||
| # the caller already has extra COMMON blocks of its own. | ||
| for sym in self.symbols: | ||
| if (self._normalize(sym.name).startswith( | ||
| "_psyclone_internal_commonblock") | ||
| and isinstance(sym.datatype, | ||
| UnsupportedFortranType)): | ||
| self_blocks = set(_blk_re.findall( | ||
| sym.datatype.declaration)) | ||
| if old_blocks & self_blocks: | ||
| return | ||
|
|
||
| # A Symbol with the same name already exists so we attempt to rename | ||
| # first the one that we are adding and failing that, the existing | ||
| # symbol in this table. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed above, unfortunately this check is insufficient but it is all that PSyclone is capable of supporting at the moment. To do better, we would need to extend CommonBlockInterface so that it holds the name of the common block. (Note that this name is not in the same space as the datasymbols themselves so can't just be a normal Symbol.)