[flang-commits] [flang] [flang] Align runtime info and lowering regarding passing ABIs (PR #81166)
via flang-commits
flang-commits at lists.llvm.org
Thu Feb 8 09:49:25 PST 2024
https://github.com/jeanPerier created https://github.com/llvm/llvm-project/pull/81166
Runtime derived type info contains information to tell the runtime if some argument in a user defined assignment must be passed with a descriptor or not. This information was not properly build, it would tell the runtime that TARGET argument must be passed via descriptor, which is incorrect.
Share the logic between lowering and runtime info generation to determine if an argument must be passed by descriptor or not.
>From 1ffc0f9f1bea38851541f2ceb4ca5a2d01625883 Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Thu, 8 Feb 2024 09:20:16 -0800
Subject: [PATCH] [flang] Align runtime info and lowering regarding passing
ABIs
Runtime derived type info contains information to tell the runtime
if some argument in a user defined assignment must be passed with
a descriptor or not. This information was not properly build, it
would tell the runtime that TARGET argument must be passed via
descriptor, which is incorrect.
Share the logic between lowering and runtime info generation to
determine if an argument must be passed by descriptor or not.
---
.../include/flang/Evaluate/characteristics.h | 1 +
flang/lib/Evaluate/characteristics.cpp | 24 +++++++++++++++++
flang/lib/Lower/CallInterface.cpp | 27 +------------------
flang/lib/Semantics/runtime-type-info.cpp | 14 ++++++----
flang/test/Semantics/typeinfo09.f90 | 20 ++++++++++++++
5 files changed, 55 insertions(+), 31 deletions(-)
create mode 100644 flang/test/Semantics/typeinfo09.f90
diff --git a/flang/include/flang/Evaluate/characteristics.h b/flang/include/flang/Evaluate/characteristics.h
index fd4af157f7937..04a0d71e1adeb 100644
--- a/flang/include/flang/Evaluate/characteristics.h
+++ b/flang/include/flang/Evaluate/characteristics.h
@@ -229,6 +229,7 @@ struct DummyDataObject {
static std::optional<DummyDataObject> Characterize(
const semantics::Symbol &, FoldingContext &);
bool CanBePassedViaImplicitInterface(std::string *whyNot = nullptr) const;
+ bool IsPassedByDescriptor(bool isBindC) const;
llvm::raw_ostream &Dump(llvm::raw_ostream &) const;
TypeAndShape type;
diff --git a/flang/lib/Evaluate/characteristics.cpp b/flang/lib/Evaluate/characteristics.cpp
index d480050d354fb..c14a422ad038f 100644
--- a/flang/lib/Evaluate/characteristics.cpp
+++ b/flang/lib/Evaluate/characteristics.cpp
@@ -461,6 +461,30 @@ bool DummyDataObject::CanBePassedViaImplicitInterface(
}
}
+bool DummyDataObject::IsPassedByDescriptor(bool isBindC) const {
+ constexpr TypeAndShape::Attrs shapeRequiringBox = {
+ TypeAndShape::Attr::AssumedShape, TypeAndShape::Attr::DeferredShape,
+ TypeAndShape::Attr::AssumedRank, TypeAndShape::Attr::Coarray};
+ if ((attrs & Attrs{Attr::Allocatable, Attr::Pointer}).any()) {
+ return true;
+ } else if ((type.attrs() & shapeRequiringBox).any()) {
+ // Need to pass shape/coshape info in a descriptor.
+ return true;
+ } else if (type.type().IsPolymorphic() && !type.type().IsAssumedType()) {
+ // Need to pass dynamic type info in a descriptor.
+ return true;
+ } else if (const auto *derived{GetDerivedTypeSpec(type.type())}) {
+ if (const semantics::Scope *scope = derived->scope()) {
+ // Need to pass length type parameters in a descriptor if any.
+ return scope->IsDerivedTypeWithLengthParameter();
+ }
+ } else if (isBindC && type.type().IsAssumedLengthCharacter()) {
+ // Fortran 2018 18.3.6 point 2 (5)
+ return true;
+ }
+ return false;
+}
+
llvm::raw_ostream &DummyDataObject::Dump(llvm::raw_ostream &o) const {
attrs.Dump(o, EnumToString);
if (intent != common::Intent::Default) {
diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp
index b007c958cb6b3..5a199668f5187 100644
--- a/flang/lib/Lower/CallInterface.cpp
+++ b/flang/lib/Lower/CallInterface.cpp
@@ -915,31 +915,6 @@ class Fortran::lower::CallInterfaceImpl {
}
}
- // Define when an explicit argument must be passed in a fir.box.
- bool dummyRequiresBox(
- const Fortran::evaluate::characteristics::DummyDataObject &obj,
- bool isBindC) {
- using ShapeAttr = Fortran::evaluate::characteristics::TypeAndShape::Attr;
- using ShapeAttrs = Fortran::evaluate::characteristics::TypeAndShape::Attrs;
- constexpr ShapeAttrs shapeRequiringBox = {
- ShapeAttr::AssumedShape, ShapeAttr::DeferredShape,
- ShapeAttr::AssumedRank, ShapeAttr::Coarray};
- if ((obj.type.attrs() & shapeRequiringBox).any())
- // Need to pass shape/coshape info in fir.box.
- return true;
- if (obj.type.type().IsPolymorphic() && !obj.type.type().IsAssumedType())
- // Need to pass dynamic type info in fir.box.
- return true;
- if (const Fortran::semantics::DerivedTypeSpec *derived =
- Fortran::evaluate::GetDerivedTypeSpec(obj.type.type()))
- if (const Fortran::semantics::Scope *scope = derived->scope())
- // Need to pass length type parameters in fir.box if any.
- return scope->IsDerivedTypeWithLengthParameter();
- if (isBindC && obj.type.type().IsAssumedLengthCharacter())
- return true; // Fortran 2018 18.3.6 point 2 (5)
- return false;
- }
-
mlir::Type
translateDynamicType(const Fortran::evaluate::DynamicType &dynamicType) {
Fortran::common::TypeCategory cat = dynamicType.category();
@@ -1022,7 +997,7 @@ class Fortran::lower::CallInterfaceImpl {
addFirOperand(boxRefType, nextPassedArgPosition(), Property::MutableBox,
attrs);
addPassedArg(PassEntityBy::MutableBox, entity, characteristics);
- } else if (dummyRequiresBox(obj, isBindC)) {
+ } else if (obj.IsPassedByDescriptor(isBindC)) {
// Pass as fir.box or fir.class
if (isValueAttr &&
!getConverter().getLoweringOptions().getLowerToHighLevelFIR())
diff --git a/flang/lib/Semantics/runtime-type-info.cpp b/flang/lib/Semantics/runtime-type-info.cpp
index de71083a21ff5..66c42160ee9e9 100644
--- a/flang/lib/Semantics/runtime-type-info.cpp
+++ b/flang/lib/Semantics/runtime-type-info.cpp
@@ -1144,7 +1144,7 @@ void RuntimeTableBuilder::DescribeSpecialProc(
which = scalarFinalEnum_;
if (int rank{evaluate::GetRank(typeAndShape.shape())}; rank > 0) {
which = IntExpr<1>(ToInt64(which).value() + rank);
- if (!proc->dummyArguments[0].CanBePassedViaImplicitInterface()) {
+ if (dummyData.IsPassedByDescriptor(proc->IsBindC())) {
argThatMightBeDescriptor = 1;
}
if (!typeAndShape.attrs().test(evaluate::characteristics::
@@ -1187,10 +1187,14 @@ void RuntimeTableBuilder::DescribeSpecialProc(
break;
}
}
- if (argThatMightBeDescriptor != 0 &&
- !proc->dummyArguments.at(argThatMightBeDescriptor - 1)
- .CanBePassedViaImplicitInterface()) {
- isArgDescriptorSet |= 1 << (argThatMightBeDescriptor - 1);
+ if (argThatMightBeDescriptor != 0) {
+ if (const auto *dummyData{
+ std::get_if<evaluate::characteristics::DummyDataObject>(
+ &proc->dummyArguments.at(argThatMightBeDescriptor - 1).u)}) {
+ if (dummyData->IsPassedByDescriptor(proc->IsBindC())) {
+ isArgDescriptorSet |= 1 << (argThatMightBeDescriptor - 1);
+ }
+ }
}
evaluate::StructureConstructorValues values;
auto index{evaluate::ToInt64(which)};
diff --git a/flang/test/Semantics/typeinfo09.f90 b/flang/test/Semantics/typeinfo09.f90
new file mode 100644
index 0000000000000..5e8707e91c047
--- /dev/null
+++ b/flang/test/Semantics/typeinfo09.f90
@@ -0,0 +1,20 @@
+!RUN: bbc --dump-symbols %s | FileCheck %s
+!RUN: %flang_fc1 -fdebug-dump-symbols %s | FileCheck %s
+! test setting of isargcontiguousset in the runtime type info.
+
+module m
+ type :: sometype
+ contains
+ procedure :: copy => copy_impl
+ generic :: assignment(=) => copy
+ end type
+interface
+ subroutine copy_impl(this, x)
+ import
+ class(sometype), intent(out) :: this
+ type(sometype), target, intent(in) :: x
+ end subroutine
+end interface
+end module
+
+!CHECK: .s.sometype, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=1_1,isargdescriptorset=1_1,istypebound=1_1,isargcontiguousset=0_1,proc=copy_impl)]
More information about the flang-commits
mailing list