Skip to content

Commit 6861426

Browse files
committed
Regroup all emboxing boilerplate in FirOpBuilder::createBox
1 parent a1813e1 commit 6861426

File tree

5 files changed

+98
-1
lines changed

5 files changed

+98
-1
lines changed

flang/include/flang/Lower/CharacterExpr.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ class CharacterExprHelper {
104104
/// - fir.array<len x fir.char<kind>>
105105
static bool isCharacterScalar(mlir::Type type);
106106

107+
/// Does this extended value holds a !fir.array<len x ... fir.char<kind>>
108+
/// where len is not the unknown extent ?
109+
static bool hasConstantLengthInType(const fir::ExtendedValue &);
110+
107111
/// Extract the kind of a character type
108112
static fir::KindTy getCharacterKind(mlir::Type type);
109113

flang/include/flang/Lower/FIRBuilder.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,13 @@ class FirOpBuilder : public mlir::OpBuilder {
210210
/// Create one of the shape ops given an extended value.
211211
mlir::Value createShape(mlir::Location loc, const fir::ExtendedValue &exv);
212212

213+
/// Create a boxed value (Fortran descriptor) to be passed to the runtime.
214+
/// \p exv is an extended value holding a memory reference to the object that
215+
/// must be boxed. This function will crash if provided something that is not
216+
/// a memory reference type.
217+
/// Array entities are boxed with a shape and character with their length.
218+
mlir::Value createBox(mlir::Location loc, const fir::ExtendedValue &exv);
219+
213220
private:
214221
const fir::KindMapping &kindMap;
215222
};

flang/lib/Lower/CharacterExpr.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,3 +632,20 @@ Fortran::lower::CharacterExprHelper::readLengthFromBox(mlir::Value box) {
632632
}
633633
return size;
634634
}
635+
636+
bool Fortran::lower::CharacterExprHelper::hasConstantLengthInType(
637+
const fir::ExtendedValue &exv) {
638+
auto type = fir::getBase(exv).getType();
639+
if (auto boxTy = type.dyn_cast<fir::BoxType>())
640+
type = boxTy.getEleTy();
641+
if (auto eleTy = fir::dyn_cast_ptrEleTy(type))
642+
type = eleTy;
643+
if (auto seqTy = type.dyn_cast<fir::SequenceType>()) {
644+
assert(seqTy.getEleTy().isa<fir::CharacterType>() &&
645+
"entity is not a character");
646+
assert(seqTy.getShape().size() > 0 && "character has empty shape");
647+
auto lenVal = seqTy.getShape()[0];
648+
return lenVal != fir::SequenceType::getUnknownExtent();
649+
}
650+
return false;
651+
}

flang/lib/Lower/FIRBuilder.cpp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "flang/Lower/FIRBuilder.h"
1010
#include "SymbolMap.h"
1111
#include "flang/Lower/Bridge.h"
12+
#include "flang/Lower/CharacterExpr.h"
1213
#include "flang/Lower/ComplexExpr.h"
1314
#include "flang/Lower/ConvertType.h"
1415
#include "flang/Lower/Support/BoxValue.h"
@@ -204,7 +205,7 @@ Fortran::lower::FirOpBuilder::createShape(mlir::Location loc,
204205
auto shapeTy =
205206
fir::ShapeShiftType::get(getContext(), box.getExtents().size());
206207
llvm::SmallVector<mlir::Value, 8> pairs;
207-
for (auto [fst,snd] : llvm::zip(box.getLBounds(), box.getExtents())) {
208+
for (auto [fst, snd] : llvm::zip(box.getLBounds(), box.getExtents())) {
208209
pairs.push_back(createConvert(loc, idxTy, fst));
209210
pairs.push_back(createConvert(loc, idxTy, snd));
210211
}
@@ -219,3 +220,44 @@ Fortran::lower::FirOpBuilder::createShape(mlir::Location loc,
219220
return mlir::Value{};
220221
});
221222
}
223+
224+
mlir::Value
225+
Fortran::lower::FirOpBuilder::createBox(mlir::Location loc,
226+
const fir::ExtendedValue &exv) {
227+
auto itemAddr = fir::getBase(exv);
228+
auto elementType = fir::dyn_cast_ptrEleTy(itemAddr.getType());
229+
if (!elementType)
230+
mlir::emitError(loc, "internal: expected a memory reference type ")
231+
<< itemAddr.getType();
232+
auto boxTy = fir::BoxType::get(elementType);
233+
return exv.match(
234+
[&](const fir::ArrayBoxValue &box) -> mlir::Value {
235+
auto s = createShape(loc, exv);
236+
return create<fir::EmboxOp>(loc, boxTy, itemAddr, s);
237+
},
238+
[&](const fir::CharArrayBoxValue &box) -> mlir::Value {
239+
auto s = createShape(loc, exv);
240+
if (Fortran::lower::CharacterExprHelper::hasConstantLengthInType(exv))
241+
return create<fir::EmboxOp>(loc, boxTy, itemAddr, s);
242+
243+
mlir::Value emptySlice;
244+
llvm::SmallVector<mlir::Value, 1> lenParams{box.getLen()};
245+
return create<fir::EmboxOp>(loc, boxTy, itemAddr, s, emptySlice,
246+
lenParams);
247+
},
248+
[&](const fir::BoxValue &box) -> mlir::Value {
249+
auto s = createShape(loc, exv);
250+
return create<fir::EmboxOp>(loc, boxTy, itemAddr, s);
251+
},
252+
[&](const fir::CharBoxValue &box) -> mlir::Value {
253+
if (Fortran::lower::CharacterExprHelper::hasConstantLengthInType(exv))
254+
return create<fir::EmboxOp>(loc, boxTy, itemAddr);
255+
mlir::Value emptyShape, emptySlice;
256+
llvm::SmallVector<mlir::Value, 1> lenParams{box.getLen()};
257+
return create<fir::EmboxOp>(loc, boxTy, itemAddr, emptyShape,
258+
emptySlice, lenParams);
259+
},
260+
[&](const auto &) -> mlir::Value {
261+
return create<fir::EmboxOp>(loc, boxTy, itemAddr);
262+
});
263+
}

flang/test/Lower/io-item-list.f90

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
! RUN: bbc -emit-fir %s -o - | FileCheck %s
2+
3+
! Test that IO item list
4+
5+
! FIXME: embox does not like getting a length when it gets
6+
! a !fir.ref<!fir.char<kind>> buffer. Either the verifier
7+
! should be relaxed, or we should finish up ensuring character
8+
! type for such buffer are !fir.ref<fir.array<?x!fir.char<kind>>>
9+
!
10+
!subroutine pass_assumed_len_char(c)
11+
! character(*) :: c
12+
! write(1, rec=1) c
13+
!end
14+
15+
! CHECK-LABEL: func @_QPpass_assumed_len_char_array
16+
subroutine pass_assumed_len_char_array(carray)
17+
character(*) :: carray(2, 3)
18+
! CHECK-DAG: %[[unboxed:.*]]:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1>>, index)
19+
! CHECK-DAG: %[[buffer:.*]] = fir.convert %[[unboxed]]#0 : (!fir.ref<!fir.char<1>>) -> !fir.ref<!fir.array<?x2x3x!fir.char<1>>>
20+
! CHECK-DAG: %[[c2:.*]] = constant 2 : index
21+
! CHECK-DAG: %[[c3:.*]] = constant 3 : index
22+
! CHECK-DAG: %[[shape:.*]] = fir.shape %[[c2]], %[[c3]] : (index, index) -> !fir.shape<2>
23+
! CHECK: %[[box:.*]] = fir.embox %[[buffer]](%[[shape]]) typeparams %[[unboxed]]#1 : (!fir.ref<!fir.array<?x2x3x!fir.char<1>>>, !fir.shape<2>, index) -> !fir.box<!fir.array<?x2x3x!fir.char<1>>>
24+
! CHECK: %[[descriptor:.*]] = fir.convert %[[box]] : (!fir.box<!fir.array<?x2x3x!fir.char<1>>>) -> !fir.box<none>
25+
! CHECK: fir.call @_FortranAioOutputDescriptor(%{{.*}}, %[[descriptor]]) : (!fir.ref<i8>, !fir.box<none>) -> i1
26+
print *, carray
27+
end

0 commit comments

Comments
 (0)