-
Notifications
You must be signed in to change notification settings - Fork 13.7k
[flang] Retain internal and BIND(C) host procedure link in FIR #87796
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
Conversation
Currently, it is not possible to find back which fun.func is the host procedure of some internal procedure because the mangling of the internal procedure does not contain info about the BIND(C) name of the host. This info may be useful to ensure dwarf DW_TAG_subprogram of internal procedures are nested under DW_TAG_subprogram of host procedures for instance.
@llvm/pr-subscribers-openacc @llvm/pr-subscribers-flang-fir-hlfir Author: None (jeanPerier) ChangesCurrently, it is not possible to find back which fun.func is the host procedure of some internal procedure because the mangling of the internal procedure does not contain info about the BIND(C) name of the host. Full diff: https://github.com/llvm/llvm-project/pull/87796.diff 3 Files Affected:
diff --git a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
index 3266ea3aa7fdc6..c5dd21199676c3 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
+++ b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
@@ -109,6 +109,13 @@ static constexpr llvm::StringRef getInternalProcedureAttrName() {
return "fir.internal_proc";
}
+/// Attribute to link an internal procedure to its host procedure symbol when
+/// the internal procedure mangled name does not allow retrieving the host
+/// func.func because the host is BIND(C).
+static constexpr llvm::StringRef getHostSymbolAttrName() {
+ return "fir.host_symbol";
+}
+
/// Attribute containing the original name of a function from before the
/// ExternalNameConverision pass runs
static constexpr llvm::StringRef getInternalFuncNameAttrName() {
diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp
index 29cdb3cff589ba..d3135ba34ee4b2 100644
--- a/flang/lib/Lower/CallInterface.cpp
+++ b/flang/lib/Lower/CallInterface.cpp
@@ -589,6 +589,21 @@ void Fortran::lower::CalleeInterface::setFuncAttrs(
static void addSymbolAttribute(mlir::func::FuncOp func,
const Fortran::semantics::Symbol &sym,
mlir::MLIRContext &mlirContext) {
+ // The link between an internal procedure and its host procedure is lost
+ // in FIR if the host is BIND(C) since the internal mangling will not
+ // allow retrieving the host bind(C) name, and therefore func.func symbol.
+ // Preserve it as an attribute so that this can be later retrieved.
+ if (sym.owner().kind() == Fortran::semantics::Scope::Kind::Subprogram)
+ if (const Fortran::semantics::Symbol *hostProcedure = sym.owner().symbol())
+ if (Fortran::semantics::IsBindCProcedure(*hostProcedure)) {
+ std::string hostName = Fortran::lower::mangle::mangleName(
+ *hostProcedure, /*keepExternalInScope=*/true);
+ func->setAttr(
+ fir::getHostSymbolAttrName(),
+ mlir::SymbolRefAttr::get(
+ &mlirContext, mlir::StringAttr::get(&mlirContext, hostName)));
+ }
+
// Only add this on bind(C) functions for which the symbol is not reflected in
// the current context.
if (!Fortran::semantics::IsBindCProcedure(sym))
diff --git a/flang/test/Lower/HLFIR/internal-procedures-bindc-host.f90 b/flang/test/Lower/HLFIR/internal-procedures-bindc-host.f90
new file mode 100644
index 00000000000000..cb7470ce92dc03
--- /dev/null
+++ b/flang/test/Lower/HLFIR/internal-procedures-bindc-host.f90
@@ -0,0 +1,13 @@
+! Test fir.host_sym attribute to retain link between internal
+! and host procedure in FIR even when BIND(C) is involved.
+
+! RUN: bbc -emit-hlfir -o - %s | FileCheck %s
+
+subroutine foo() bind(c, name="some_c_name")
+ call bar()
+contains
+ subroutine bar()
+ end subroutine
+end subroutine
+! CHECK: func.func @some_c_name()
+! CHECK: func.func private @_QFfooPbar() attributes {fir.host_symbol = @some_c_name, llvm.linkage = #llvm.linkage<internal>}
|
flang/lib/Lower/CallInterface.cpp
Outdated
// Preserve it as an attribute so that this can be later retrieved. | ||
if (sym.owner().kind() == Fortran::semantics::Scope::Kind::Subprogram) | ||
if (const Fortran::semantics::Symbol *hostProcedure = sym.owner().symbol()) | ||
if (Fortran::semantics::IsBindCProcedure(*hostProcedure)) { |
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.
Just a suggestion: maybe we should just always set it for consistency. I think this should not affect readability of FIR too much.
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.
Thanks for the feedback. Makes sense to me. It is also then possible to get rid of fir.internal_proc and just use the new attribute. I updated the patch to do it for all internal procedures, including the ones from the main programs, and removed fir.internal_proc.
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.
Thank you, Jean! Sorry for the delay, it went under the radar.
No problem, I am the one who took ages to update it, thanks for the review! |
Hi,
Compilation command: I observe ICE when flang-new tries to lower MLIR code to LLVM IR. |
Thanks, I could reproduce. The OMPFunctionFiltering assumed all function symbol uses are calls/address_of. When processing the host program (in the Fortran sense, not OpenMP) it now erases its internal procedures as if it were a call, and then proceeds to process the erased internal function, hence the segfault. Working on a fix. |
The pass assumed that all fun.func symbol usages could be safely replaced by undef, that is not true after #87796 that added a back link from internal procedure back to the parent procedure. This caused the internal procedures to be erased and then processed (segfault). Also set visibility of such internal procedures so that MLIR do not remove them before the target function is generated for the target region.
Currently, it is not possible to find back which fun.func is the host procedure of some internal procedure because the mangling of the internal procedure does not contain info about the BIND(C) name of the host.
This info may be useful to ensure dwarf DW_TAG_subprogram of internal procedures are nested under DW_TAG_subprogram of host procedures for instance.