@@ -3543,10 +3543,10 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
35433543 TODO (converter.getCurrentLocation (), " OpenMPDeclareSimdConstruct" );
35443544}
35453545
3546- static void genOMP (lower::AbstractConverter &converter, lower::SymMap &symTable,
3547- semantics::SemanticsContext &semaCtx,
3548- lower::pft::Evaluation &eval ,
3549- const parser::OpenMPDeclareMapperConstruct &construct ) {
3546+ static void genOpenMPDeclareMapperImpl (
3547+ lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx,
3548+ const parser::OpenMPDeclareMapperConstruct &construct ,
3549+ const semantics::Symbol *mapperSymOpt = nullptr ) {
35503550 mlir::Location loc = converter.genLocation (construct.source );
35513551 fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder ();
35523552 const parser::OmpArgumentList &args = construct.v .Arguments ();
@@ -3562,8 +3562,17 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
35623562 " Expected derived type" );
35633563
35643564 std::string mapperNameStr = mapperName;
3565- if (auto *sym = converter.getCurrentScope ().FindSymbol (mapperNameStr))
3565+ if (mapperSymOpt && mapperNameStr != " default" ) {
3566+ mapperNameStr = converter.mangleName (mapperNameStr, mapperSymOpt->owner ());
3567+ } else if (auto *sym =
3568+ converter.getCurrentScope ().FindSymbol (mapperNameStr)) {
35663569 mapperNameStr = converter.mangleName (mapperNameStr, sym->owner ());
3570+ }
3571+
3572+ // If the mapper op already exists (e.g., created by regular lowering),
3573+ // do not recreate it.
3574+ if (converter.getModuleOp ().lookupSymbol (mapperNameStr))
3575+ return ;
35673576
35683577 // Save current insertion point before moving to the module scope to create
35693578 // the DeclareMapperOp
@@ -3586,6 +3595,13 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
35863595 mlir::omp::DeclareMapperInfoOp::create (firOpBuilder, loc, clauseOps.mapVars );
35873596}
35883597
3598+ static void genOMP (lower::AbstractConverter &converter, lower::SymMap &symTable,
3599+ semantics::SemanticsContext &semaCtx,
3600+ lower::pft::Evaluation &eval,
3601+ const parser::OpenMPDeclareMapperConstruct &construct) {
3602+ genOpenMPDeclareMapperImpl (converter, semaCtx, construct);
3603+ }
3604+
35893605static void
35903606genOMP (lower::AbstractConverter &converter, lower::SymMap &symTable,
35913607 semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
@@ -4229,3 +4245,32 @@ void Fortran::lower::genOpenMPRequires(mlir::Operation *mod,
42294245 offloadMod.setRequires (mlirFlags);
42304246 }
42314247}
4248+
4249+ // Walk scopes and materialize omp.declare_mapper ops for mapper declarations
4250+ // found in imported modules. If \p scope is null, start from the global scope.
4251+ void Fortran::lower::materializeOpenMPDeclareMappers (
4252+ Fortran::lower::AbstractConverter &converter,
4253+ semantics::SemanticsContext &semaCtx, const semantics::Scope *scope) {
4254+ const semantics::Scope &root = scope ? *scope : semaCtx.globalScope ();
4255+
4256+ // Recurse into child scopes first (modules, submodules, etc.).
4257+ for (const semantics::Scope &child : root.children ())
4258+ materializeOpenMPDeclareMappers (converter, semaCtx, &child);
4259+
4260+ // Only consider module scopes to avoid duplicating local constructs.
4261+ if (!root.IsModule ())
4262+ return ;
4263+
4264+ // Scan symbols in this module scope for MapperDetails.
4265+ for (auto &it : root) {
4266+ const semantics::Symbol &sym = *it.second ;
4267+ if (auto *md = sym.detailsIf <semantics::MapperDetails>()) {
4268+ for (const auto *decl : md->GetDeclList ()) {
4269+ if (const auto *mapperDecl =
4270+ std::get_if<parser::OpenMPDeclareMapperConstruct>(&decl->u )) {
4271+ genOpenMPDeclareMapperImpl (converter, semaCtx, *mapperDecl, &sym);
4272+ }
4273+ }
4274+ }
4275+ }
4276+ }
0 commit comments