Skip to content

Commit 8301c46

Browse files
committed
[flang][fir] fix ABI bug 116844
1 parent bbea1de commit 8301c46

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)