diff options
author | jeanPerier <jperier@nvidia.com> | 2023-12-19 17:17:09 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-19 17:17:09 +0100 |
commit | c373f58134997a6d037f0143f13f97451278700f (patch) | |
tree | 5006341df9db56accd10cc596a9506986dabcc5e /flang/lib/Lower/Bridge.cpp | |
parent | 747061f9ba7e2d6cdf730d3bd2cda1134f1175a1 (diff) | |
download | llvm-c373f58134997a6d037f0143f13f97451278700f.zip llvm-c373f58134997a6d037f0143f13f97451278700f.tar.gz llvm-c373f58134997a6d037f0143f13f97451278700f.tar.bz2 |
[flang] Lower procedure pointer components (#75453)
Lower procedure pointer components, except in the context of structure
constructor (left TODO).
Procedure pointer components lowering share most of the lowering logic
of procedure poionters with the following particularities:
- They are components, so an hlfir.designate must be generated to
retrieve the procedure pointer address from its derived type base.
- They may have a PASS argument. While there is no dispatching as with
type bound procedure, special care must be taken to retrieve the derived
type component base in this case since semantics placed it in the
argument list and not in the evaluate::ProcedureDesignator.
These components also bring a new level of recursive MLIR types since a
fir.type may now contain a component with an MLIR function type where
one of the argument is the fir.type itself. This required moving the
"derived type in construction" stackto the converter so that the object
and function type lowering utilities share the same state (currently the
function type utilty would end-up creating a new stack when lowering its
arguments, leading to infinite loops). The BoxedProcedurePass also
needed an update to deal with this recursive aspect.
Diffstat (limited to 'flang/lib/Lower/Bridge.cpp')
-rw-r--r-- | flang/lib/Lower/Bridge.cpp | 52 |
1 files changed, 31 insertions, 21 deletions
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 61393d2..e1d406e 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -170,25 +170,22 @@ public: if (seen.contains(typeInfoSym)) return; seen.insert(typeInfoSym); - if (!skipRegistration) { - registeredTypeInfo.emplace_back( - TypeInfo{typeInfoSym, typeSpec, type, loc}); - return; - } - // Once the registration is closed, symbols cannot be added to the - // registeredTypeInfoSymbols list because it may be iterated over. - // However, after registration is closed, it is safe to directly generate - // the globals because all FuncOps whose addresses may be required by the - // initializers have been generated. - createTypeInfoOpAndGlobal(converter, - TypeInfo{typeInfoSym, typeSpec, type, loc}); + currentTypeInfoStack->emplace_back( + TypeInfo{typeInfoSym, typeSpec, type, loc}); + return; } void createTypeInfo(Fortran::lower::AbstractConverter &converter) { - skipRegistration = true; - for (const TypeInfo &info : registeredTypeInfo) - createTypeInfoOpAndGlobal(converter, info); - registeredTypeInfo.clear(); + while (!registeredTypeInfoA.empty()) { + currentTypeInfoStack = ®isteredTypeInfoB; + for (const TypeInfo &info : registeredTypeInfoA) + createTypeInfoOpAndGlobal(converter, info); + registeredTypeInfoA.clear(); + currentTypeInfoStack = ®isteredTypeInfoA; + for (const TypeInfo &info : registeredTypeInfoB) + createTypeInfoOpAndGlobal(converter, info); + registeredTypeInfoB.clear(); + } } private: @@ -249,11 +246,12 @@ private: } /// Store the front-end data that will be required to generate the type info - /// for the derived types that have been converted to fir.type<>. - llvm::SmallVector<TypeInfo> registeredTypeInfo; - /// Create derived type info immediately without storing the - /// symbol in registeredTypeInfo. - bool skipRegistration = false; + /// for the derived types that have been converted to fir.type<>. There are + /// two stacks since the type info may visit new types, so the new types must + /// be added to a new stack. + llvm::SmallVector<TypeInfo> registeredTypeInfoA; + llvm::SmallVector<TypeInfo> registeredTypeInfoB; + llvm::SmallVector<TypeInfo> *currentTypeInfoStack = ®isteredTypeInfoA; /// Track symbols symbols processed during and after the registration /// to avoid infinite loops between type conversions and global variable /// creation. @@ -602,6 +600,11 @@ public: std::nullopt); } + Fortran::lower::TypeConstructionStack & + getTypeConstructionStack() override final { + return typeConstructionStack; + } + bool isPresentShallowLookup(Fortran::semantics::Symbol &sym) override final { return bool(shallowLookupSymbol(sym)); } @@ -5008,6 +5011,13 @@ private: bool ompDeviceCodeFound = false; const Fortran::lower::ExprToValueMap *exprValueOverrides{nullptr}; + + /// Stack of derived type under construction to avoid infinite loops when + /// dealing with recursive derived types. This is held in the bridge because + /// the state needs to be maintained between data and function type lowering + /// utilities to deal with procedure pointer components whose arguments have + /// the type of the containing derived type. + Fortran::lower::TypeConstructionStack typeConstructionStack; }; } // namespace |