-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[flang] Attach proper storage to [hl]fir.declare in lowering. #155742
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: main
Are you sure you want to change the base?
Conversation
As described in https://discourse.llvm.org/t/rfc-flang-representation-for-objects-inside-physical-storage/88026, `[hl]fir.declare` should carry information about the layout of COMMON/EQUIVALENCE variables within the physical storage. This patch modifes Flang lowering to attach this information.
@llvm/pr-subscribers-flang-openmp @llvm/pr-subscribers-flang-fir-hlfir Author: Slava Zakharin (vzakhari) ChangesAs described in https://discourse.llvm.org/t/rfc-flang-representation-for-objects-inside-physical-storage/88026, This patch modifes Flang lowering to attach this information. Patch is 141.33 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/155742.diff 40 Files Affected:
diff --git a/flang/include/flang/Lower/AbstractConverter.h b/flang/include/flang/Lower/AbstractConverter.h
index ef956a36917fd..e674cd7e1c233 100644
--- a/flang/include/flang/Lower/AbstractConverter.h
+++ b/flang/include/flang/Lower/AbstractConverter.h
@@ -108,6 +108,21 @@ class AbstractConverter {
/// added or replaced at the inner-most level of the local symbol map.
virtual void bindSymbol(SymbolRef sym, const fir::ExtendedValue &exval) = 0;
+ /// Binds the symbol's physical storage to a storage descriptor,
+ /// which is the base address of the storage and the offset
+ /// within the storage, where the symbol begins.
+ /// The symbol binding will be added or replaced at the innermost level
+ /// of the local symbol map.
+ virtual void
+ bindSymbolStorage(SymbolRef sym,
+ Fortran::lower::SymMap::StorageDesc storage) = 0;
+
+ /// Returns the storage descriptor previouslt bound to this symbol.
+ /// If there is no bound storage, the descriptor will contain
+ /// nullptr base address.
+ virtual Fortran::lower::SymMap::StorageDesc
+ getSymbolStorage(SymbolRef sym) = 0;
+
/// Override lowering of expression with pre-lowered values.
/// Associate mlir::Value to evaluate::Expr. All subsequent call to
/// genExprXXX() will replace any occurrence of an overridden
diff --git a/flang/include/flang/Lower/ConvertVariable.h b/flang/include/flang/Lower/ConvertVariable.h
index b938f6be196af..31f3c72c5c86c 100644
--- a/flang/include/flang/Lower/ConvertVariable.h
+++ b/flang/include/flang/Lower/ConvertVariable.h
@@ -92,10 +92,14 @@ void defineCommonBlocks(
/// The COMMON block is a global structure. \p commonValue is the base address
/// of the COMMON block. As the offset from the symbol \p sym, generate the
/// COMMON block member value (commonValue + offset) for the symbol.
+/// \p commonSize specifies the syze of the COMMON block in bytes.
+/// The size is used to represent a COMMON block reference as
+/// a !fir.ref<!fir.array<SIZExi8>>.
mlir::Value genCommonBlockMember(AbstractConverter &converter,
mlir::Location loc,
const Fortran::semantics::Symbol &sym,
- mlir::Value commonValue);
+ mlir::Value commonValue,
+ std::size_t commonSize);
/// Lower a symbol attributes given an optional storage \p and add it to the
/// provided symbol map. If \preAlloc is not provided, a temporary storage will
diff --git a/flang/include/flang/Lower/SymbolMap.h b/flang/include/flang/Lower/SymbolMap.h
index e52d1075e2b9d..813df777d7a39 100644
--- a/flang/include/flang/Lower/SymbolMap.h
+++ b/flang/include/flang/Lower/SymbolMap.h
@@ -146,14 +146,22 @@ struct SymbolBox : public fir::details::matcher<SymbolBox> {
class SymMap {
public:
using AcDoVar = llvm::StringRef;
+ /// Descriptor of a symbol's storage consists of the base address
+ /// of the storage and the offset within that storage.
+ using StorageDesc = std::pair<mlir::Value, std::uint64_t>;
SymMap() { pushScope(); }
SymMap(const SymMap &) = delete;
- void pushScope() { symbolMapStack.emplace_back(); }
+ void pushScope() {
+ symbolMapStack.emplace_back();
+ storageMapStack.emplace_back();
+ }
void popScope() {
symbolMapStack.pop_back();
assert(symbolMapStack.size() >= 1);
+ storageMapStack.pop_back();
+ assert(storageMapStack.size() >= 1);
}
/// Add an extended value to the symbol table.
@@ -287,6 +295,8 @@ class SymMap {
symbolMapStack.emplace_back();
assert(symbolMapStack.size() == 1);
impliedDoStack.clear();
+ storageMapStack.clear();
+ storageMapStack.emplace_back();
}
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
@@ -315,6 +325,16 @@ class SymMap {
return std::nullopt;
}
+ /// Register the symbol's storage at the innermost level
+ /// of the symbol table. If the storage is already registered,
+ /// it will be replaced.
+ void registerStorage(semantics::SymbolRef sym, StorageDesc storage);
+ /// Lookup the symbol's storage at the innermost level of the symbol table.
+ StorageDesc lookupStorage(semantics::SymbolRef sym);
+ StorageDesc lookupStorage(const semantics::Symbol *sym) {
+ return lookupStorage(*sym);
+ }
+
private:
/// Bind `box` to `symRef` in the symbol map.
void makeSym(semantics::SymbolRef symRef, const SymbolBox &box,
@@ -332,6 +352,10 @@ class SymMap {
// Implied DO induction variables are not represented as Se::Symbol in
// Ev::Expr. Keep the variable markers in their own stack.
llvm::SmallVector<std::pair<AcDoVar, mlir::Value>> impliedDoStack;
+
+ // A stack of maps between the symbols and their storage descriptors.
+ llvm::SmallVector<llvm::DenseMap<const semantics::Symbol *, StorageDesc>>
+ storageMapStack;
};
/// RAII wrapper for SymMap.
diff --git a/flang/include/flang/Optimizer/Builder/HLFIRTools.h b/flang/include/flang/Optimizer/Builder/HLFIRTools.h
index 49dfc85dc76e6..4d2a5bf385857 100644
--- a/flang/include/flang/Optimizer/Builder/HLFIRTools.h
+++ b/flang/include/flang/Optimizer/Builder/HLFIRTools.h
@@ -224,7 +224,8 @@ fir::FortranVariableOpInterface
genDeclare(mlir::Location loc, fir::FirOpBuilder &builder,
const fir::ExtendedValue &exv, llvm::StringRef name,
fir::FortranVariableFlagsAttr flags,
- mlir::Value dummyScope = nullptr,
+ mlir::Value dummyScope = nullptr, mlir::Value storage = nullptr,
+ std::uint64_t storageOffset = 0,
cuf::DataAttributeAttr dataAttr = {});
/// Generate an hlfir.associate to build a variable from an expression value.
diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
index 44a8a2e81a497..0811b7bbc13d6 100644
--- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
+++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
@@ -109,10 +109,12 @@ def hlfir_DeclareOp
attr-dict `:` functional-type(operands, results)
}];
- let builders = [
- OpBuilder<(ins "mlir::Value":$memref, "llvm::StringRef":$uniq_name,
- CArg<"mlir::Value", "{}">:$shape, CArg<"mlir::ValueRange", "{}">:$typeparams,
+ let builders = [OpBuilder<(ins "mlir::Value":$memref,
+ "llvm::StringRef":$uniq_name, CArg<"mlir::Value", "{}">:$shape,
+ CArg<"mlir::ValueRange", "{}">:$typeparams,
CArg<"mlir::Value", "{}">:$dummy_scope,
+ CArg<"mlir::Value", "{}">:$storage,
+ CArg<"std::uint64_t", "0">:$storage_offset,
CArg<"fir::FortranVariableFlagsAttr", "{}">:$fortran_attrs,
CArg<"cuf::DataAttributeAttr", "{}">:$data_attr)>];
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index c003a5b04ecd5..e91fa2db15fa2 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -631,6 +631,17 @@ class FirConverter : public Fortran::lower::AbstractConverter {
addSymbol(sym, exval, /*forced=*/true);
}
+ void bindSymbolStorage(
+ Fortran::lower::SymbolRef sym,
+ Fortran::lower::SymMap::StorageDesc storage) override final {
+ localSymbols.registerStorage(sym, std::move(storage));
+ }
+
+ Fortran::lower::SymMap::StorageDesc
+ getSymbolStorage(Fortran::lower::SymbolRef sym) override final {
+ return localSymbols.lookupStorage(sym);
+ }
+
void
overrideExprValues(const Fortran::lower::ExprToValueMap *map) override final {
exprValueOverrides = map;
diff --git a/flang/lib/Lower/ConvertArrayConstructor.cpp b/flang/lib/Lower/ConvertArrayConstructor.cpp
index 87824110b4a0c..006f022b5379a 100644
--- a/flang/lib/Lower/ConvertArrayConstructor.cpp
+++ b/flang/lib/Lower/ConvertArrayConstructor.cpp
@@ -315,9 +315,8 @@ class RuntimeTempStrategy : public StrategyBase {
mlir::Value tempStorage = builder.createHeapTemporary(
loc, declaredType, tempName, extents, lengths);
mlir::Value shape = builder.genShape(loc, extents);
- declare = hlfir::DeclareOp::create(
- builder, loc, tempStorage, tempName, shape, lengths,
- /*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{});
+ declare = hlfir::DeclareOp::create(builder, loc, tempStorage, tempName,
+ shape, lengths);
initialBoxValue =
builder.createBox(loc, boxType, declare->getOriginalBase(), shape,
/*slice=*/mlir::Value{}, lengths, /*tdesc=*/{});
diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index 81e09a1ca5bc9..1eda1f1b61355 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -1813,10 +1813,8 @@ class HlfirBuilder {
// Allocate scalar temporary that will be initialized
// with the values specified by the constructor.
mlir::Value storagePtr = builder.createTemporary(loc, recTy);
- auto varOp = hlfir::EntityWithAttributes{hlfir::DeclareOp::create(
- builder, loc, storagePtr, "ctor.temp", /*shape=*/nullptr,
- /*typeparams=*/mlir::ValueRange{}, /*dummy_scope=*/nullptr,
- fir::FortranVariableFlagsAttr{})};
+ auto varOp = hlfir::EntityWithAttributes{
+ hlfir::DeclareOp::create(builder, loc, storagePtr, "ctor.temp")};
// Initialize any components that need initialization.
mlir::Value box = builder.createBox(loc, fir::ExtendedValue{varOp});
diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index 80af7f4c1aaad..88fc3128d21f7 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -1413,6 +1413,7 @@ static void instantiateAlias(Fortran::lower::AbstractConverter &converter,
mlir::Value bytePtr = fir::CoordinateOp::create(
builder, loc, i8Ptr, storeAddr, mlir::ValueRange{offset});
mlir::Value typedPtr = castAliasToPointer(builder, loc, symType, bytePtr);
+ converter.bindSymbolStorage(sym, {storeAddr, off});
Fortran::lower::StatementContext stmtCtx;
mapSymbolAttributes(converter, var, symMap, stmtCtx, typedPtr);
// Default initialization is possible for equivalence members: see
@@ -1655,13 +1656,15 @@ void Fortran::lower::defineCommonBlocks(
mlir::Value Fortran::lower::genCommonBlockMember(
Fortran::lower::AbstractConverter &converter, mlir::Location loc,
- const Fortran::semantics::Symbol &sym, mlir::Value commonValue) {
+ const Fortran::semantics::Symbol &sym, mlir::Value commonValue,
+ std::size_t commonSize) {
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
std::size_t byteOffset = sym.GetUltimate().offset();
mlir::IntegerType i8Ty = builder.getIntegerType(8);
mlir::Type i8Ptr = builder.getRefType(i8Ty);
- mlir::Type seqTy = builder.getRefType(builder.getVarLenSeqTy(i8Ty));
+ fir::SequenceType::Shape shape(1, commonSize);
+ mlir::Type seqTy = builder.getRefType(fir::SequenceType::get(shape, i8Ty));
mlir::Value base = builder.createConvert(loc, seqTy, commonValue);
mlir::Value offs =
@@ -1670,6 +1673,8 @@ mlir::Value Fortran::lower::genCommonBlockMember(
mlir::ValueRange{offs});
mlir::Type symType = converter.genType(sym);
+ converter.bindSymbolStorage(sym, {base, byteOffset});
+
return Fortran::semantics::FindEquivalenceSet(sym) != nullptr
? castAliasToPointer(builder, loc, symType, varAddr)
: builder.createConvert(loc, builder.getRefType(symType), varAddr);
@@ -1698,7 +1703,8 @@ static void instantiateCommon(Fortran::lower::AbstractConverter &converter,
symMap.addSymbol(common, commonAddr);
}
- mlir::Value local = genCommonBlockMember(converter, loc, varSym, commonAddr);
+ mlir::Value local =
+ genCommonBlockMember(converter, loc, varSym, commonAddr, common.size());
Fortran::lower::StatementContext stmtCtx;
mapSymbolAttributes(converter, var, symMap, stmtCtx, local);
}
@@ -1970,7 +1976,8 @@ static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter,
// Declare a local pointer variable.
auto newBase = hlfir::DeclareOp::create(
builder, loc, boxAlloc, name, /*shape=*/nullptr, lenParams,
- /*dummy_scope=*/nullptr, attributes);
+ /*dummy_scope=*/nullptr, /*storage=*/nullptr,
+ /*storage_offset=*/0, attributes);
mlir::Value nullAddr = builder.createNullConstant(
loc, llvm::cast<fir::BaseBoxType>(ptrBoxType).getEleTy());
@@ -2000,9 +2007,10 @@ static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter,
mlir::Value dummyScope;
if (converter.isRegisteredDummySymbol(sym))
dummyScope = converter.dummyArgsScopeValue();
- auto newBase =
- hlfir::DeclareOp::create(builder, loc, base, name, shapeOrShift,
- lenParams, dummyScope, attributes, dataAttr);
+ auto [storage, storageOffset] = converter.getSymbolStorage(sym);
+ auto newBase = hlfir::DeclareOp::create(
+ builder, loc, base, name, shapeOrShift, lenParams, dummyScope, storage,
+ storageOffset, attributes, dataAttr);
symMap.addVariableDefinition(sym, newBase, force);
return;
}
@@ -2060,8 +2068,10 @@ void Fortran::lower::genDeclareSymbol(
base = genPackArray(converter, sym, exv);
dummyScope = converter.dummyArgsScopeValue();
}
- hlfir::EntityWithAttributes declare = hlfir::genDeclare(
- loc, builder, base, name, attributes, dummyScope, dataAttr);
+ auto [storage, storageOffset] = converter.getSymbolStorage(sym);
+ hlfir::EntityWithAttributes declare =
+ hlfir::genDeclare(loc, builder, base, name, attributes, dummyScope,
+ storage, storageOffset, dataAttr);
symMap.addVariableDefinition(sym, declare.getIfVariableInterface(), force);
return;
}
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 7a84b21913bae..bbe749f8c8805 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -1212,12 +1212,10 @@ mlir::acc::FirstprivateRecipeOp Fortran::lower::createOrGetFirstprivateRecipe(
auto leftDeclOp = hlfir::DeclareOp::create(
builder, loc, recipe.getCopyRegion().getArgument(0), llvm::StringRef{},
- shape, llvm::ArrayRef<mlir::Value>{}, /*dummy_scope=*/nullptr,
- fir::FortranVariableFlagsAttr{});
+ shape);
auto rightDeclOp = hlfir::DeclareOp::create(
builder, loc, recipe.getCopyRegion().getArgument(1), llvm::StringRef{},
- shape, llvm::ArrayRef<mlir::Value>{}, /*dummy_scope=*/nullptr,
- fir::FortranVariableFlagsAttr{});
+ shape);
hlfir::DesignateOp::Subscripts triplets =
getSubscriptsFromArgs(recipe.getCopyRegion().getArguments());
@@ -1523,14 +1521,10 @@ static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc,
auto shape =
genShapeFromBoundsOrArgs(loc, builder, seqTy, bounds,
recipe.getCombinerRegion().getArguments());
- auto v1DeclareOp = hlfir::DeclareOp::create(
- builder, loc, value1, llvm::StringRef{}, shape,
- llvm::ArrayRef<mlir::Value>{},
- /*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{});
- auto v2DeclareOp = hlfir::DeclareOp::create(
- builder, loc, value2, llvm::StringRef{}, shape,
- llvm::ArrayRef<mlir::Value>{},
- /*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{});
+ auto v1DeclareOp = hlfir::DeclareOp::create(builder, loc, value1,
+ llvm::StringRef{}, shape);
+ auto v2DeclareOp = hlfir::DeclareOp::create(builder, loc, value2,
+ llvm::StringRef{}, shape);
hlfir::DesignateOp::Subscripts triplets = getTripletsFromArgs(recipe);
llvm::SmallVector<mlir::Value> lenParamsLeft;
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index bedcb2a267d92..972f47275cf22 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -847,10 +847,12 @@ createCopyFunc(mlir::Location loc, lower::AbstractConverter &converter,
}
auto declDst = hlfir::DeclareOp::create(
builder, loc, dst, copyFuncName + "_dst", shape, typeparams,
- /*dummy_scope=*/nullptr, attrs);
+ /*dummy_scope=*/nullptr, /*storage=*/nullptr,
+ /*storage_offset=*/0, attrs);
auto declSrc = hlfir::DeclareOp::create(
builder, loc, src, copyFuncName + "_src", shape, typeparams,
- /*dummy_scope=*/nullptr, attrs);
+ /*dummy_scope=*/nullptr, /*storage=*/nullptr,
+ /*storage_offset=*/0, attrs);
converter.copyVar(loc, declDst.getBase(), declSrc.getBase(), varAttrs);
mlir::func::ReturnOp::create(builder, loc);
return funcOp;
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 9df2f1d79aa67..0a38f53f8f991 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -688,7 +688,7 @@ static void threadPrivatizeVars(lower::AbstractConverter &converter,
}
symThreadprivateValue = lower::genCommonBlockMember(
converter, currentLocation, sym->GetUltimate(),
- commonThreadprivateValue);
+ commonThreadprivateValue, common->size());
} else {
symThreadprivateValue = genThreadprivateOp(*sym);
}
@@ -1401,7 +1401,7 @@ static void genIntermediateCommonBlockAccessors(
for (auto obj : details->objects()) {
auto targetCBMemberBind = Fortran::lower::genCommonBlockMember(
- converter, currentLocation, *obj, mapArg);
+ converter, currentLocation, *obj, mapArg, mapSym->size());
fir::ExtendedValue sexv = converter.getSymbolExtendedValue(*obj);
fir::ExtendedValue targetCBExv =
getExtendedValue(sexv, targetCBMemberBind);
@@ -4086,8 +4086,9 @@ void Fortran::lower::genThreadprivateOp(lower::AbstractConverter &converter,
firOpBuilder, currentLocation, commonValue.getType(), commonValue);
converter.bindSymbol(*common, commonThreadprivateValue);
// Generate the threadprivate value for the common block member.
- symThreadprivateValue = genCommonBlockMember(converter, currentLocation,
- sym, commonThreadprivateValue);
+ symThreadprivateValue =
+ genCommonBlockMember(converter, currentLocation, sym,
+ commonThreadprivateValue, common->size());
} else if (!var.isGlobal()) {
// Non-global variable which can be in threadprivate directive must be one
// variable in main program, and it has implicit SAVE attribute. Take it as
diff --git a/flang/lib/Lower/SymbolMap.cpp b/flang/lib/Lower/SymbolMap.cpp
index b929dfbd5aec4..080f21ec67400 100644
--- a/flang/lib/Lower/SymbolMap.cpp
+++ b/flang/lib/Lower/SymbolMap.cpp
@@ -82,6 +82,23 @@ Fortran::lower::SymMap::lookupImpliedDo(Fortran::lower::SymMap::AcDoVar var) {
return {};
}
+void Fortran::lower::SymMap::registerStorage(
+ semantics::SymbolRef symRef, Fortran::lower::SymMap::StorageDesc storage) {
+ auto *sym = symRef->HasLocalLocality() ? &*symRef : &symRef->GetUltimate();
+ assert(storage.first && "registerting storage without an address");
+ storageMapStack.back().insert_or_assign(sym, std::move(storage));
+}
+
+Fortran::lower::SymMap::StorageDesc
+Fortran::lower::SymMap::lookupStorage(Fortran::semantics::SymbolRef symRef) {
+ auto *sym = symRef->HasLocalLocality() ? &*symRef : &symRef->GetUltimate();
+ auto &map = storageMapStack.back();
+ auto iter = map.find(sym);
+ if (iter != map.end())
+ return iter->second;
+ return {nullptr, 0};
+}
+
void Fortran::lower::SymbolBox::dump() const { llvm::errs() << *this << '\n'; }
void Fortran::lower::SymMap::dump() const { llvm::errs() << *this << '\n'; }
diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
index 086dd66711602..f93eaf7ba90b4 100644
--- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp
+++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
@@ -249,6 +249,7 @@ fir::FortranVariableOpInterface
hlfir::genDeclare(mlir::Location loc, fir::FirOpBuilder &builder,
const fir::ExtendedValue &exv, llvm::StringRef name,
fir::For...
[truncated]
|
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.
Looks great to me
bindSymbolStorage(SymbolRef sym, | ||
Fortran::lower::SymMap::StorageDesc storage) = 0; | ||
|
||
/// Returns the storage descriptor previouslt bound to this symbol. |
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.
/// Returns the storage descriptor previouslt bound to this symbol. | |
/// Returns the storage descriptor previously bound to this symbol. |
As described in https://discourse.llvm.org/t/rfc-flang-representation-for-objects-inside-physical-storage/88026,
[hl]fir.declare
should carry information about the layoutof COMMON/EQUIVALENCE variables within the physical storage.
This patch modifes Flang lowering to attach this information.