[flang] Extend common block size to cover equivalence storage
The size of common block should be extended to cover any storage sequence that are storage associated with the common block via equivalences (8.10.2.2 point 1 (2)). In symbol size and offset computation, the size of the common block was not always extended to cover storage association. It was only done if the "base symbol of an equivalence group"(*) appeared in a common block statement. Correct this to cover all cases where a symbol appearing in a common block statement is storage associated. (*) the base symbol of an equivalence group is the symbol whose storage starts first in a storage association (if several symbols starts first, the base symbol is the last one visited by the algorithm going through the equivalence sets). Differential Revision: https://reviews.llvm.org/D109156
This commit is contained in:
parent
0f80961e8c
commit
084d8bebd0
|
@ -151,16 +151,12 @@ void ComputeOffsetsHelper::DoCommonBlock(Symbol &commonBlock) {
|
|||
for (auto &object : details.objects()) {
|
||||
Symbol &symbol{*object};
|
||||
DoSymbol(symbol);
|
||||
auto eqIter{equivalenceBlock_.end()};
|
||||
auto iter{dependents_.find(symbol)};
|
||||
if (iter == dependents_.end()) {
|
||||
// Get full extent of any EQUIVALENCE block into size of COMMON
|
||||
auto eqIter{equivalenceBlock_.find(symbol)};
|
||||
auto eqIter = equivalenceBlock_.find(symbol);
|
||||
if (eqIter != equivalenceBlock_.end()) {
|
||||
SizeAndAlignment &blockInfo{eqIter->second};
|
||||
DoEquivalenceBlockBase(symbol, blockInfo);
|
||||
minSize = std::max(
|
||||
minSize, std::max(offset_, symbol.offset() + blockInfo.size));
|
||||
minAlignment = std::max(minAlignment, blockInfo.alignment);
|
||||
DoEquivalenceBlockBase(symbol, eqIter->second);
|
||||
}
|
||||
} else {
|
||||
SymbolAndOffset &dep{iter->second};
|
||||
|
@ -183,10 +179,19 @@ void ComputeOffsetsHelper::DoCommonBlock(Symbol &commonBlock) {
|
|||
"'%s' cannot backward-extend COMMON block /%s/ via EQUIVALENCE with '%s'"_err_en_US,
|
||||
symbol.name(), commonBlock.name(), base.name());
|
||||
} else {
|
||||
eqIter = equivalenceBlock_.find(base);
|
||||
base.get<ObjectEntityDetails>().set_commonBlock(commonBlock);
|
||||
base.set_offset(symbol.offset() - dep.offset);
|
||||
}
|
||||
}
|
||||
// Get full extent of any EQUIVALENCE block into size of COMMON ( see
|
||||
// 8.10.2.2 point 1 (2))
|
||||
if (eqIter != equivalenceBlock_.end()) {
|
||||
SizeAndAlignment &blockInfo{eqIter->second};
|
||||
minSize = std::max(
|
||||
minSize, std::max(offset_, eqIter->first->offset() + blockInfo.size));
|
||||
minAlignment = std::max(minAlignment, blockInfo.alignment);
|
||||
}
|
||||
}
|
||||
commonBlock.set_size(std::max(minSize, offset_));
|
||||
details.set_alignment(std::max(minAlignment, alignment_));
|
||||
|
|
|
@ -37,3 +37,23 @@ module md !CHECK: Module scope: md size=1 alignment=1
|
|||
common /common1/ d3,d2,d1 !CHECK: common1 size=10 offset=0: CommonBlockDetails alignment=4:
|
||||
common /common2/ d4 !CHECK: common2 size=2 offset=0: CommonBlockDetails alignment=2:
|
||||
end
|
||||
|
||||
! Test extension of common block size through equivalence statements.
|
||||
module me
|
||||
integer :: i1, j1, l1(10)
|
||||
equivalence(i1, l1)
|
||||
common /common3/ j1, i1 ! CHECK: common3 size=44 offset=0: CommonBlockDetails alignment=4:
|
||||
|
||||
integer :: i2, j2, l2(10)
|
||||
equivalence(i2, l2(2))
|
||||
common /common4/ j2, i2 ! CHECK: common4 size=40 offset=0: CommonBlockDetails alignment=4:
|
||||
|
||||
integer :: i3, j3, l3(10)
|
||||
equivalence(i3, l3)
|
||||
common /common5/ i3, j3 ! CHECK: common5 size=40 offset=0: CommonBlockDetails alignment=4:
|
||||
|
||||
integer :: i4, j4, l4(10), k4(10)
|
||||
equivalence(i4, l4)
|
||||
equivalence(l4(10), k4)
|
||||
common /common6/ i4, j4 ! CHECK: common6 size=76 offset=0: CommonBlockDetails alignment=4:
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue