@@ -3553,10 +3553,10 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
35533553 TODO (converter.getCurrentLocation (), " OpenMPDeclareSimdConstruct" );
35543554}
35553555
3556- static void genOMP (lower::AbstractConverter &converter, lower::SymMap &symTable,
3557- semantics::SemanticsContext &semaCtx,
3558- lower::pft::Evaluation &eval ,
3559- const parser::OpenMPDeclareMapperConstruct &construct ) {
3556+ static void genOpenMPDeclareMapperImpl (
3557+ lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx,
3558+ const parser::OpenMPDeclareMapperConstruct &construct ,
3559+ const semantics::Symbol *mapperSymOpt = nullptr ) {
35603560 mlir::Location loc = converter.genLocation (construct.source );
35613561 fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder ();
35623562 const parser::OmpArgumentList &args = construct.v .Arguments ();
@@ -3572,8 +3572,17 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
35723572 " Expected derived type" );
35733573
35743574 std::string mapperNameStr = mapperName;
3575- if (auto *sym = converter.getCurrentScope ().FindSymbol (mapperNameStr))
3575+ if (mapperSymOpt && mapperNameStr != " default" ) {
3576+ mapperNameStr = converter.mangleName (mapperNameStr, mapperSymOpt->owner ());
3577+ } else if (auto *sym =
3578+ converter.getCurrentScope ().FindSymbol (mapperNameStr)) {
35763579 mapperNameStr = converter.mangleName (mapperNameStr, sym->owner ());
3580+ }
3581+
3582+ // If the mapper op already exists (e.g., created by regular lowering),
3583+ // do not recreate it.
3584+ if (converter.getModuleOp ().lookupSymbol (mapperNameStr))
3585+ return ;
35773586
35783587 // Save current insertion point before moving to the module scope to create
35793588 // the DeclareMapperOp
@@ -3596,6 +3605,13 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
35963605 mlir::omp::DeclareMapperInfoOp::create (firOpBuilder, loc, clauseOps.mapVars );
35973606}
35983607
3608+ static void genOMP (lower::AbstractConverter &converter, lower::SymMap &symTable,
3609+ semantics::SemanticsContext &semaCtx,
3610+ lower::pft::Evaluation &eval,
3611+ const parser::OpenMPDeclareMapperConstruct &construct) {
3612+ genOpenMPDeclareMapperImpl (converter, semaCtx, construct);
3613+ }
3614+
35993615static void
36003616genOMP (lower::AbstractConverter &converter, lower::SymMap &symTable,
36013617 semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
@@ -4239,3 +4255,32 @@ void Fortran::lower::genOpenMPRequires(mlir::Operation *mod,
42394255 offloadMod.setRequires (mlirFlags);
42404256 }
42414257}
4258+
4259+ // Walk scopes and materialize omp.declare_mapper ops for mapper declarations
4260+ // found in imported modules. If \p scope is null, start from the global scope.
4261+ void Fortran::lower::materializeOpenMPDeclareMappers (
4262+ Fortran::lower::AbstractConverter &converter,
4263+ semantics::SemanticsContext &semaCtx, const semantics::Scope *scope) {
4264+ const semantics::Scope &root = scope ? *scope : semaCtx.globalScope ();
4265+
4266+ // Recurse into child scopes first (modules, submodules, etc.).
4267+ for (const semantics::Scope &child : root.children ())
4268+ materializeOpenMPDeclareMappers (converter, semaCtx, &child);
4269+
4270+ // Only consider module scopes to avoid duplicating local constructs.
4271+ if (!root.IsModule ())
4272+ return ;
4273+
4274+ // Scan symbols in this module scope for MapperDetails.
4275+ for (auto &it : root) {
4276+ const semantics::Symbol &sym = *it.second ;
4277+ if (auto *md = sym.detailsIf <semantics::MapperDetails>()) {
4278+ for (const auto *decl : md->GetDeclList ()) {
4279+ if (const auto *mapperDecl =
4280+ std::get_if<parser::OpenMPDeclareMapperConstruct>(&decl->u )) {
4281+ genOpenMPDeclareMapperImpl (converter, semaCtx, *mapperDecl, &sym);
4282+ }
4283+ }
4284+ }
4285+ }
4286+ }
0 commit comments