[flang-commits] [flang] [flang] Compiler directives defined by plugins (PR #228757)
Valentin Clement バレンタイン クレメン via flang-commits
flang-commits at lists.llvm.org
Wed Oct 7 10:03:26 PDT 2026
================
@@ -687,9 +687,129 @@ class FirConverter : public Fortran::lower::AbstractConverter {
*this, bridge.getSemanticsContext());
});
+ createBuilderOutsideOfFuncOpAndDo([&]() { lowerPluginDirectives(); });
+
finalizeOpenMPLowering(globalOmpRequiresSymbols);
}
+ /// Attach the directives defined by plugins to the operations of their
+ /// subjects in this module (a func.func for a procedure, a fir.global for a
+ /// variable), as a `fir.directives` array of dictionaries:
+ /// {prefix = "enzyme", keyword = "custom_rule",
+ /// args = {reverse = @_QMmPrev, ...}}
+ /// Procedure and variable arguments are symbol references, declaring the
+ /// procedure or module variable if this module does not yet; the plugin's
+ /// passes give them a meaning.
+ void lowerPluginDirectives() {
+ mlir::ModuleOp module{getModuleOp()};
+ mlir::MLIRContext *ctx{module.getContext()};
+ // What semantics lets a directive refer to: a subprogram or an external
+ // procedure, a variable, or a COMMON block. Nothing else has an operation
+ // (or even a mangled name).
+ auto isReferable{[](const Fortran::semantics::Symbol &sym) {
+ if (Fortran::semantics::IsProcedure(sym)) {
+ return !sym.has<Fortran::semantics::GenericDetails>() &&
+ !Fortran::semantics::IsDummy(sym) &&
+ !Fortran::semantics::IsProcedurePointer(sym) &&
+ !Fortran::semantics::IsStmtFunction(sym) &&
+ !sym.attrs().test(Fortran::semantics::Attr::INTRINSIC);
+ }
+ return sym.has<Fortran::semantics::ObjectEntityDetails>() ||
+ sym.has<Fortran::semantics::CommonBlockDetails>();
+ }};
+ // The operation of a procedure or variable, declared if need be (as a
+ // reference to it would): procedures, and variables of modules, which
+ // may be another module's.
+ auto getOrDeclare{[&](const Fortran::semantics::Symbol &sym)
+ -> mlir::Operation * {
+ if (!isReferable(sym)) {
+ return nullptr;
+ }
+ if (mlir::Operation *op = module.lookupSymbol(mangleName(sym)))
+ return op;
+ if (Fortran::semantics::IsProcedure(sym)) {
+ mlir::func::FuncOp func = Fortran::lower::getOrDeclareFunction(
+ Fortran::evaluate::ProcedureDesignator{sym}, *this);
+ return func.getOperation();
+ }
+ if (sym.has<Fortran::semantics::ObjectEntityDetails>() &&
+ sym.owner().IsModule()) {
+ return Fortran::lower::declareModuleVariable(*this, sym).getOperation();
+ }
+ return nullptr;
+ }};
+ for (const auto &[subject, directive, fromModFile] :
+ bridge.getSemanticsContext().GetPluginDirectives()) {
+ const Fortran::semantics::Symbol &ultimate{subject->GetUltimate()};
+ // The unit with the directive keeps it even for a procedure or variable
+ // it does not use otherwise (e.g. an external procedure with an
+ // interface body); a unit that sees it through a module file only for
+ // those it uses.
+ mlir::Operation *target{nullptr};
+ if (!fromModFile)
+ target = getOrDeclare(ultimate);
+ else if (isReferable(ultimate))
+ target = module.lookupSymbol(mangleName(ultimate));
+ if (!target) {
+ continue; // neither defined nor referenced here
+ }
+ const auto &[prefix, keyword, args]{
+ std::get<Fortran::parser::CompilerDirective::Plugin>(directive->u).t};
+ llvm::SmallVector<mlir::NamedAttribute> argAttrs;
+ for (const Fortran::parser::CompilerDirective::Plugin::Arg &arg : args) {
+ const auto &argKeyword{std::get<0>(arg.t)};
+ if (!argKeyword) {
+ continue; // the subject
+ }
----------------
clementval wrote:
no braces
https://github.com/llvm/llvm-project/pull/228757
More information about the flang-commits
mailing list