Skip to content

Commit cbb49d4

Browse files
authored
[flang][fir] fix ABI bug 116844 (#118121)
Fix issue #116844. The issue came from a look-up on the func.func for the sret attribute when lowering fir.call with character arguments. This was broken because the func.func may or may not have been rewritten when dealing with the fir.call, but the lookup assumed it had not been rewritten yet. If the func.func was rewritten and the result moved to a sret argument, the call was lowered as if the character was meant to be the result, leading to bad call code and an assert. It turns out that the whole logic is actually useless since fir.boxchar are never lowered as sret arguments, instead, lowering directly breaks the character result into the first two `fir.ref<>, i64` arguments. So, the sret case was actually never used, except in this bug. Hence, instead of fixing the logic (probably by looking for argument attributes on the call itself), just remove this logic that brings unnecessary complexity.
1 parent da23a83 commit cbb49d4

File tree

5 files changed

+21
-104
lines changed

5 files changed

+21
-104
lines changed

flang/include/flang/Optimizer/CodeGen/Target.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -133,15 +133,7 @@ class CodeGenSpecifics {
133133

134134
/// Type representation of a `boxchar<n>` type argument when passed by value.
135135
/// An argument value may need to be passed as a (safe) reference argument.
136-
///
137-
/// A function that returns a `boxchar<n>` type value must already have
138-
/// converted that return value to a parameter decorated with the 'sret'
139-
/// Attribute (https://llvm.org/docs/LangRef.html#parameter-attributes).
140-
/// This requirement is in keeping with Fortran semantics, which require the
141-
/// caller to allocate the space for the return CHARACTER value and pass
142-
/// a pointer and the length of that space (a boxchar) to the called function.
143-
virtual Marshalling boxcharArgumentType(mlir::Type eleTy,
144-
bool sret = false) const = 0;
136+
virtual Marshalling boxcharArgumentType(mlir::Type eleTy) const = 0;
145137

146138
// Compute ABI rules for an integer argument of the given mlir::IntegerType
147139
// \p argTy. Note that this methods is supposed to be called for

flang/lib/Optimizer/CodeGen/Target.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,17 +80,17 @@ struct GenericTarget : public CodeGenSpecifics {
8080
mlir::TypeRange{ptrTy, idxTy});
8181
}
8282

83-
Marshalling boxcharArgumentType(mlir::Type eleTy, bool sret) const override {
83+
Marshalling boxcharArgumentType(mlir::Type eleTy) const override {
8484
CodeGenSpecifics::Marshalling marshal;
8585
auto idxTy = mlir::IntegerType::get(eleTy.getContext(), S::defaultWidth);
8686
auto ptrTy = fir::ReferenceType::get(eleTy);
8787
marshal.emplace_back(ptrTy, AT{});
88-
// Return value arguments are grouped as a pair. Others are passed in a
89-
// split format with all pointers first (in the declared position) and all
90-
// LEN arguments appended after all of the dummy arguments.
88+
// Characters are passed in a split format with all pointers first (in the
89+
// declared position) and all LEN arguments appended after all of the dummy
90+
// arguments.
9191
// NB: Other conventions/ABIs can/should be supported via options.
9292
marshal.emplace_back(idxTy, AT{/*alignment=*/0, /*byval=*/false,
93-
/*sret=*/sret, /*append=*/!sret});
93+
/*sret=*/false, /*append=*/true});
9494
return marshal;
9595
}
9696

flang/lib/Optimizer/CodeGen/TargetRewrite.cpp

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -403,25 +403,21 @@ class TargetRewrite : public fir::impl::TargetRewritePassBase<TargetRewrite> {
403403
unsigned index = e.index();
404404
llvm::TypeSwitch<mlir::Type>(ty)
405405
.template Case<fir::BoxCharType>([&](fir::BoxCharType boxTy) {
406-
bool sret;
407406
if constexpr (std::is_same_v<std::decay_t<A>, fir::CallOp>) {
408407
if (noCharacterConversion) {
409408
newInTyAndAttrs.push_back(
410409
fir::CodeGenSpecifics::getTypeAndAttr(boxTy));
411410
newOpers.push_back(oper);
412411
return;
413412
}
414-
sret = callOp.getCallee() &&
415-
functionArgIsSRet(
416-
index, getModule().lookupSymbol<mlir::func::FuncOp>(
417-
*callOp.getCallee()));
418413
} else {
419-
// TODO: dispatch case; how do we put arguments on a call?
420-
// We cannot put both an sret and the dispatch object first.
421-
sret = false;
422-
TODO(loc, "dispatch + sret not supported yet");
414+
// TODO: dispatch case; it used to be a to-do because of sret,
415+
// but is not tested and maybe should be removed. This pass is
416+
// anyway ran after lowering fir.dispatch in flang, so maybe that
417+
// should just be a requirement of the pass.
418+
TODO(loc, "ABI of fir.dispatch with character arguments");
423419
}
424-
auto m = specifics->boxcharArgumentType(boxTy.getEleTy(), sret);
420+
auto m = specifics->boxcharArgumentType(boxTy.getEleTy());
425421
auto unbox = rewriter->create<fir::UnboxCharOp>(
426422
loc, std::get<mlir::Type>(m[0]), std::get<mlir::Type>(m[1]),
427423
oper);
@@ -846,24 +842,18 @@ class TargetRewrite : public fir::impl::TargetRewritePassBase<TargetRewrite> {
846842
// Convert a CHARACTER argument type. This can involve separating
847843
// the pointer and the LEN into two arguments and moving the LEN
848844
// argument to the end of the arg list.
849-
bool sret = functionArgIsSRet(index, func);
850-
for (auto e : llvm::enumerate(specifics->boxcharArgumentType(
851-
boxTy.getEleTy(), sret))) {
845+
for (auto e : llvm::enumerate(
846+
specifics->boxcharArgumentType(boxTy.getEleTy()))) {
852847
auto &tup = e.value();
853848
auto index = e.index();
854849
auto attr = std::get<fir::CodeGenSpecifics::Attributes>(tup);
855850
auto argTy = std::get<mlir::Type>(tup);
856851
if (attr.isAppend()) {
857852
trailingTys.push_back(argTy);
858853
} else {
859-
if (sret) {
860-
fixups.emplace_back(FixupTy::Codes::CharPair,
861-
newInTyAndAttrs.size(), index);
862-
} else {
863-
fixups.emplace_back(FixupTy::Codes::Trailing,
864-
newInTyAndAttrs.size(),
865-
trailingTys.size());
866-
}
854+
fixups.emplace_back(FixupTy::Codes::Trailing,
855+
newInTyAndAttrs.size(),
856+
trailingTys.size());
867857
newInTyAndAttrs.push_back(tup);
868858
}
869859
}
@@ -1112,12 +1102,6 @@ class TargetRewrite : public fir::impl::TargetRewritePassBase<TargetRewrite> {
11121102
(*fixup.finalizer)(func);
11131103
}
11141104

1115-
inline bool functionArgIsSRet(unsigned index, mlir::func::FuncOp func) {
1116-
if (auto attr = func.getArgAttrOfType<mlir::TypeAttr>(index, "llvm.sret"))
1117-
return true;
1118-
return false;
1119-
}
1120-
11211105
template <typename Ty, typename FIXUPS>
11221106
void doReturn(mlir::func::FuncOp func, Ty &newResTys,
11231107
fir::CodeGenSpecifics::Marshalling &newInTyAndAttrs,

flang/test/Fir/target-rewrite-boxchar.fir

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -27,43 +27,13 @@ func.func @boxcharparams(%arg0 : !fir.boxchar<1>, %arg1 : !fir.boxchar<1>) -> i6
2727
return %3 : i64
2828
}
2929

30-
// Test that we rewrite the signatures and bodies of functions that return a
31-
// boxchar.
32-
// INT32-LABEL: @boxcharsret
33-
// INT32-SAME: ([[ARG0:%[0-9A-Za-z]+]]: !fir.ref<!fir.char<1,?>> {llvm.sret = !fir.char<1,?>}, [[ARG1:%[0-9A-Za-z]+]]: i32, [[ARG2:%[0-9A-Za-z]+]]: !fir.ref<!fir.char<1,?>>, [[ARG3:%[0-9A-Za-z]+]]: i32)
34-
// INT64-LABEL: @boxcharsret
35-
// INT64-SAME: ([[ARG0:%[0-9A-Za-z]+]]: !fir.ref<!fir.char<1,?>> {llvm.sret = !fir.char<1,?>}, [[ARG1:%[0-9A-Za-z]+]]: i64, [[ARG2:%[0-9A-Za-z]+]]: !fir.ref<!fir.char<1,?>>, [[ARG3:%[0-9A-Za-z]+]]: i64)
36-
func.func @boxcharsret(%arg0 : !fir.boxchar<1> {llvm.sret = !fir.char<1,?>}, %arg1 : !fir.boxchar<1>) {
37-
// INT32-DAG: [[B0:%[0-9]+]] = fir.emboxchar [[ARG0]], [[ARG1]] : (!fir.ref<!fir.char<1,?>>, i32) -> !fir.boxchar<1>
38-
// INT32-DAG: [[B1:%[0-9]+]] = fir.emboxchar [[ARG2]], [[ARG3]] : (!fir.ref<!fir.char<1,?>>, i32) -> !fir.boxchar<1>
39-
// INT32-DAG: fir.unboxchar [[B0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.array<?x!fir.char<1>>>, i64)
40-
// INT32-DAG: fir.unboxchar [[B1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.array<?x!fir.char<1>>>, i64)
41-
// INT64-DAG: [[B0:%[0-9]+]] = fir.emboxchar [[ARG0]], [[ARG1]] : (!fir.ref<!fir.char<1,?>>, i64) -> !fir.boxchar<1>
42-
// INT64-DAG: [[B1:%[0-9]+]] = fir.emboxchar [[ARG2]], [[ARG3]] : (!fir.ref<!fir.char<1,?>>, i64) -> !fir.boxchar<1>
43-
// INT64-DAG: fir.unboxchar [[B0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.array<?x!fir.char<1>>>, i64)
44-
// INT64-DAG: fir.unboxchar [[B1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.array<?x!fir.char<1>>>, i64)
45-
%1:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.array<?x!fir.char<1>>>, i64)
46-
%2:2 = fir.unboxchar %arg1 : (!fir.boxchar<1>) -> (!fir.ref<!fir.array<?x!fir.char<1>>>, i64)
47-
%c0 = arith.constant 0 : index
48-
%c1 = arith.constant 1 : index
49-
%3 = fir.convert %1#1 : (i64) -> index
50-
%last = arith.subi %3, %c1 : index
51-
fir.do_loop %i = %c0 to %last step %c1 {
52-
%in_pos = fir.coordinate_of %2#0, %i : (!fir.ref<!fir.array<?x!fir.char<1>>>, index) -> !fir.ref<!fir.char<1>>
53-
%out_pos = fir.coordinate_of %1#0, %i : (!fir.ref<!fir.array<?x!fir.char<1>>>, index) -> !fir.ref<!fir.char<1>>
54-
%ch = fir.load %in_pos : !fir.ref<!fir.char<1>>
55-
fir.store %ch to %out_pos : !fir.ref<!fir.char<1>>
56-
}
57-
return
58-
}
59-
60-
// Test that we rewrite the signatures of functions with a sret parameter and
30+
// Test that we rewrite the signatures of functions with several parameters.
6131
// several other parameters.
6232
// INT32-LABEL: @boxcharmultiple
63-
// INT32-SAME: ({{%[0-9A-Za-z]+}}: !fir.ref<!fir.char<1,?>> {llvm.sret = !fir.char<1,?>}, {{%[0-9A-Za-z]+}}: i32, {{%[0-9A-Za-z]+}}: !fir.ref<!fir.char<1,?>>, {{%[0-9A-Za-z]+}}: !fir.ref<!fir.char<1,?>>, {{%[0-9A-Za-z]+}}: i32, {{%[0-9A-Za-z]+}}: i32)
33+
// INT32-SAME: ({{%[0-9A-Za-z]+}}: !fir.ref<!fir.char<1,?>>, {{%[0-9A-Za-z]+}}: !fir.ref<!fir.char<1,?>>, {{%[0-9A-Za-z]+}}: !fir.ref<!fir.char<1,?>>, {{%[0-9A-Za-z]+}}: i32, {{%[0-9A-Za-z]+}}: i32, {{%[0-9A-Za-z]+}}: i32)
6434
// INT64-LABEL: @boxcharmultiple
65-
// INT64-SAME: ({{%[0-9A-Za-z]+}}: !fir.ref<!fir.char<1,?>> {llvm.sret = !fir.char<1,?>}, {{%[0-9A-Za-z]+}}: i64, {{%[0-9A-Za-z]+}}: !fir.ref<!fir.char<1,?>>, {{%[0-9A-Za-z]+}}: !fir.ref<!fir.char<1,?>>, {{%[0-9A-Za-z]+}}: i64, {{%[0-9A-Za-z]+}}: i64)
66-
func.func @boxcharmultiple(%arg0 : !fir.boxchar<1> {llvm.sret = !fir.char<1,?>}, %arg1 : !fir.boxchar<1>, %arg2 : !fir.boxchar<1>) {
35+
// INT64-SAME: ({{%[0-9A-Za-z]+}}: !fir.ref<!fir.char<1,?>>, {{%[0-9A-Za-z]+}}: !fir.ref<!fir.char<1,?>>, {{%[0-9A-Za-z]+}}: !fir.ref<!fir.char<1,?>>, {{%[0-9A-Za-z]+}}: i64, {{%[0-9A-Za-z]+}}: i64, {{%[0-9A-Za-z]+}}: i64)
36+
func.func @boxcharmultiple(%arg0 : !fir.boxchar<1>, %arg1 : !fir.boxchar<1>, %arg2 : !fir.boxchar<1>) {
6737
return
6838
}
6939

flang/test/Fir/target.fir

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -110,32 +110,3 @@ func.func @char1lensum(%arg0 : !fir.boxchar<1>, %arg1 : !fir.boxchar<1>) -> i64
110110
// X64: ret i64 %[[add]]
111111
return %3 : i64
112112
}
113-
114-
// I32-LABEL: define void @char1copy(ptr nocapture sret(i8) %0, i32 %1, ptr nocapture %2, i32 %3)
115-
// I64-LABEL: define void @char1copy(ptr nocapture sret(i8) %0, i64 %1, ptr nocapture %2, i64 %3)
116-
// PPC-LABEL: define void @char1copy(ptr nocapture sret(i8) %0, i64 %1, ptr nocapture %2, i64 %3)
117-
func.func @char1copy(%arg0 : !fir.boxchar<1> {llvm.sret = !fir.char<1, ?>}, %arg1 : !fir.boxchar<1>) {
118-
// I32-DAG: %[[p0:.*]] = insertvalue { ptr, i32 } undef, ptr %2, 0
119-
// I32-DAG: = insertvalue { ptr, i32 } %[[p0]], i32 %3, 1
120-
// I32-DAG: %[[p1:.*]] = insertvalue { ptr, i32 } undef, ptr %0, 0
121-
// I32-DAG: = insertvalue { ptr, i32 } %[[p1]], i32 %1, 1
122-
// X64-DAG: %[[p0:.*]] = insertvalue { ptr, i64 } undef, ptr %2, 0
123-
// X64-DAG: = insertvalue { ptr, i64 } %[[p0]], i64 %3, 1
124-
// X64-DAG: %[[p1:.*]] = insertvalue { ptr, i64 } undef, ptr %0, 0
125-
// X64-DAG: = insertvalue { ptr, i64 } %[[p1]], i64 %1, 1
126-
%1:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.array<?x!fir.char<1>>>, i64)
127-
%2:2 = fir.unboxchar %arg1 : (!fir.boxchar<1>) -> (!fir.ref<!fir.array<?x!fir.char<1>>>, i64)
128-
%c0 = arith.constant 0 : index
129-
%c1 = arith.constant 1 : index
130-
%3 = fir.convert %1#1 : (i64) -> index
131-
%last = arith.subi %3, %c1 : index
132-
fir.do_loop %i = %c0 to %last step %c1 {
133-
%in_pos = fir.coordinate_of %2#0, %i : (!fir.ref<!fir.array<?x!fir.char<1>>>, index) -> !fir.ref<!fir.char<1>>
134-
%out_pos = fir.coordinate_of %1#0, %i : (!fir.ref<!fir.array<?x!fir.char<1>>>, index) -> !fir.ref<!fir.char<1>>
135-
%ch = fir.load %in_pos : !fir.ref<!fir.char<1>>
136-
fir.store %ch to %out_pos : !fir.ref<!fir.char<1>>
137-
}
138-
// I32: ret void
139-
// X64: ret void
140-
return
141-
}

0 commit comments

Comments
 (0)