Skip to content

Commit e079baf

Browse files
explicitly convert when dummy arg doesnt match callers type
1 parent fca533a commit e079baf

File tree

15 files changed

+149
-53
lines changed

15 files changed

+149
-53
lines changed

flang/include/flang/Optimizer/Builder/FIRBuilder.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,9 @@ class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener {
363363
mlir::Value createConvert(mlir::Location loc, mlir::Type toTy,
364364
mlir::Value val);
365365

366+
mlir::Value createConvertWithVolatileCast(mlir::Location loc, mlir::Type toTy,
367+
mlir::Value val);
368+
366369
/// Create a fir.store of \p val into \p addr. A lazy conversion
367370
/// of \p val to the element type of \p addr is created if needed.
368371
void createStoreWithConvert(mlir::Location loc, mlir::Value val,

flang/include/flang/Optimizer/Dialect/FIROps.td

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ def fir_LoadOp : fir_OneResultOp<"load", [FirAliasTagOpInterface, DeclareOpInter
302302
or null.
303303
}];
304304

305-
let arguments = (ins Arg<AnyReferenceLike, "">:$memref,
305+
let arguments = (ins AnyReferenceLike:$memref,
306306
OptionalAttr<LLVM_TBAATagArrayAttr>:$tbaa);
307307

308308
let builders = [OpBuilder<(ins "mlir::Value":$refVal)>,
@@ -336,7 +336,7 @@ def fir_StoreOp : fir_Op<"store", [FirAliasTagOpInterface,
336336
}];
337337

338338
let arguments = (ins AnyType:$value,
339-
Arg<AnyReferenceLike, "">:$memref,
339+
AnyReferenceLike:$memref,
340340
OptionalAttr<LLVM_TBAATagArrayAttr>:$tbaa);
341341

342342
let builders = [OpBuilder<(ins "mlir::Value":$value, "mlir::Value":$memref)>];
@@ -2765,6 +2765,7 @@ def fir_VolatileCastOp : fir_SimpleOneResultOp<"volatile_cast", [NoMemoryEffect]
27652765
$value attr-dict `:` functional-type($value, results)
27662766
}];
27672767
let hasVerifier = 1;
2768+
let hasFolder = 1;
27682769
}
27692770

27702771
def fir_ConvertOp : fir_SimpleOneResultOp<"convert", [NoMemoryEffect]> {

flang/include/flang/Optimizer/Dialect/FIRType.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,10 @@ inline mlir::Type wrapInClassOrBoxType(mlir::Type eleTy,
462462
return fir::BoxType::get(eleTy);
463463
}
464464

465+
/// Re-create the given type with the given volatility, if this is a type
466+
/// that can represent volatility.
467+
mlir::Type updateTypeWithVolatility(mlir::Type type, bool isVolatile);
468+
465469
/// Return the elementType where intrinsic types are replaced with none for
466470
/// unlimited polymorphic entities.
467471
///

flang/include/flang/Optimizer/Dialect/FIRTypes.td

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ def fir_ReferenceType : FIR_Type<"Reference", "ref"> {
365365
References can be volatile. Any ops taking an operand of a volatile
366366
reference must set their memory effects appropriately. Accesses of
367367
volatile references are currently modeled as read and write effects
368-
to an unknown memory location.
368+
to a specific memory resource.
369369
}];
370370

371371
let parameters = (ins
@@ -386,8 +386,6 @@ def fir_ReferenceType : FIR_Type<"Reference", "ref"> {
386386
}];
387387

388388
let genVerifyDecl = 1;
389-
// let assemblyFormat = "`<` $eleTy (`,` `volatile` $isVolatile^)? `>`";
390-
// let assemblyFormat = "`<` $eleTy custom<IsVolatile>($isVolatile)`>`";
391389
let hasCustomAssemblyFormat = 1;
392390
}
393391

flang/lib/Lower/CallInterface.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1150,7 +1150,8 @@ class Fortran::lower::CallInterfaceImpl {
11501150

11511151
if (obj.attrs.test(Attrs::Allocatable) || obj.attrs.test(Attrs::Pointer)) {
11521152
// Pass as fir.ref<fir.box> or fir.ref<fir.class>
1153-
mlir::Type boxRefType = fir::ReferenceType::get(boxType);
1153+
const bool isVolatile = obj.attrs.test(Attrs::Volatile);
1154+
mlir::Type boxRefType = fir::ReferenceType::get(boxType, isVolatile);
11541155
addFirOperand(boxRefType, nextPassedArgPosition(), Property::MutableBox,
11551156
attrs);
11561157
addPassedArg(PassEntityBy::MutableBox, entity, characteristics);

flang/lib/Lower/ConvertCall.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,6 @@ Fortran::lower::genCallOpAndResult(
327327
charFuncPointerLength = charBox->getLen();
328328
}
329329
}
330-
331330
const bool isExprCall =
332331
converter.getLoweringOptions().getLowerToHighLevelFIR() &&
333332
callSiteType.getNumResults() == 1 &&
@@ -1417,6 +1416,25 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
14171416
addr = hlfir::genVariableRawAddress(loc, builder, entity);
14181417
}
14191418

1419+
// If the volatility of the input type does not match the dummy type,
1420+
// we need to cast the argument.
1421+
if (fir::isa_volatile_type(dummyTypeWithActualRank) !=
1422+
fir::isa_volatile_type(addr.getType())) {
1423+
const bool isToTypeVolatile =
1424+
fir::isa_volatile_type(dummyTypeWithActualRank);
1425+
mlir::Type volatileAdjustedType =
1426+
llvm::TypeSwitch<mlir::Type, mlir::Type>(addr.getType())
1427+
.Case<fir::ReferenceType, fir::BoxType>([&](auto ty) {
1428+
using TYPE = decltype(ty);
1429+
return TYPE::get(ty.getElementType(), isToTypeVolatile);
1430+
})
1431+
.Default([](auto t) {
1432+
assert(false && "unexpected type");
1433+
return t;
1434+
});
1435+
addr = builder.create<fir::VolatileCastOp>(loc, volatileAdjustedType, addr);
1436+
}
1437+
14201438
// For ranked actual passed to assumed-rank dummy, the cast to assumed-rank
14211439
// box is inserted when building the fir.call op. Inserting it here would
14221440
// cause the fir.if results to be assumed-rank in case of OPTIONAL dummy,

flang/lib/Lower/ConvertExprToHLFIR.cpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -232,15 +232,11 @@ class HlfirDesignatorBuilder {
232232
isVolatile = fir::isa_volatile_type(baseType);
233233
}
234234

235-
auto isVolatileSymbol = [](const Fortran::semantics::Symbol &symbol) {
236-
return symbol.GetUltimate().attrs().test(
237-
Fortran::semantics::Attr::VOLATILE);
238-
};
239-
240235
// Check if this should be a volatile reference
241236
if constexpr (std::is_same_v<std::decay_t<T>,
242237
Fortran::evaluate::SymbolRef>) {
243-
if (isVolatileSymbol(designatorNode.get()))
238+
if (designatorNode.get().GetUltimate().attrs().test(
239+
Fortran::semantics::Attr::VOLATILE))
244240
isVolatile = true;
245241
}
246242

@@ -436,16 +432,15 @@ class HlfirDesignatorBuilder {
436432
.Case<fir::SequenceType>([&](fir::SequenceType seqTy) -> mlir::Type {
437433
return fir::SequenceType::get(seqTy.getShape(), newEleTy);
438434
})
439-
// TODO: handle volatility for other types
440-
.Case<fir::PointerType, fir::HeapType, fir::BoxType, fir::ClassType>(
435+
.Case<fir::PointerType, fir::HeapType, fir::ClassType>(
441436
[&](auto t) -> mlir::Type {
442437
using FIRT = decltype(t);
443438
return FIRT::get(changeElementType(t.getEleTy(), newEleTy));
444439
})
445-
.Case<fir::ReferenceType>([&](fir::ReferenceType refTy) -> mlir::Type {
446-
return fir::ReferenceType::get(
447-
changeElementType(refTy.getEleTy(), newEleTy),
448-
refTy.isVolatile());
440+
.Case<fir::ReferenceType, fir::BoxType>([&](auto t) -> mlir::Type {
441+
using FIRT = decltype(t);
442+
return FIRT::get(changeElementType(t.getEleTy(), newEleTy),
443+
t.isVolatile());
449444
})
450445
.Default([newEleTy](mlir::Type t) -> mlir::Type { return newEleTy; });
451446
}

flang/lib/Lower/IO.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ static void genOutputItemList(
709709
fir::factory::CharacterExprHelper helper{builder, loc};
710710
if (mlir::isa<fir::BoxType>(argType)) {
711711
mlir::Value box = fir::getBase(converter.genExprBox(loc, *expr, stmtCtx));
712-
outputFuncArgs.push_back(builder.createConvert(loc, argType, box));
712+
outputFuncArgs.push_back(builder.createConvertWithVolatileCast(loc, argType, box));
713713
if (mlir::isa<fir::RecordType>(fir::unwrapPassByRefType(itemTy)))
714714
outputFuncArgs.push_back(getNonTbpDefinedIoTableAddr(converter));
715715
} else if (helper.isCharacterScalar(itemTy)) {
@@ -719,9 +719,9 @@ static void genOutputItemList(
719719
if (!exv.getCharBox())
720720
llvm::report_fatal_error(
721721
"internal error: scalar character not in CharBox");
722-
outputFuncArgs.push_back(builder.createConvert(
722+
outputFuncArgs.push_back(builder.createConvertWithVolatileCast(
723723
loc, outputFunc.getFunctionType().getInput(1), fir::getBase(exv)));
724-
outputFuncArgs.push_back(builder.createConvert(
724+
outputFuncArgs.push_back(builder.createConvertWithVolatileCast(
725725
loc, outputFunc.getFunctionType().getInput(2), fir::getLen(exv)));
726726
} else {
727727
fir::ExtendedValue itemBox = converter.genExprValue(loc, expr, stmtCtx);
@@ -822,6 +822,17 @@ createIoRuntimeCallForItem(Fortran::lower::AbstractConverter &converter,
822822
} else {
823823
mlir::Value itemAddr = fir::getBase(item);
824824
mlir::Type itemTy = fir::unwrapPassByRefType(itemAddr.getType());
825+
826+
// Handle conversion between volatile and non-volatile reference types
827+
// Need to explicitly cast when volatility qualification differs
828+
bool srcIsVolatile = fir::isa_volatile_type(itemAddr.getType());
829+
bool dstIsVolatile = fir::isa_volatile_type(argType);
830+
831+
if (srcIsVolatile != dstIsVolatile) {
832+
// Create an explicit conversion to handle the volatility difference
833+
itemAddr = builder.create<fir::VolatileCastOp>(loc, argType, itemAddr);
834+
}
835+
825836
inputFuncArgs.push_back(builder.createConvert(loc, argType, itemAddr));
826837
fir::factory::CharacterExprHelper charHelper{builder, loc};
827838
if (charHelper.isCharacterScalar(itemTy)) {

flang/lib/Optimizer/Builder/FIRBuilder.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,16 @@ mlir::Value fir::FirOpBuilder::convertWithSemantics(
510510
return createConvert(loc, toTy, val);
511511
}
512512

513+
mlir::Value fir::FirOpBuilder::createConvertWithVolatileCast(mlir::Location loc,
514+
mlir::Type toTy,
515+
mlir::Value val) {
516+
if (fir::isa_volatile_type(val.getType()) != fir::isa_volatile_type(toTy)) {
517+
mlir::Type volatileAdjustedType = fir::updateTypeWithVolatility(val.getType(), fir::isa_volatile_type(toTy));
518+
val = create<fir::VolatileCastOp>(loc, volatileAdjustedType, val);
519+
}
520+
return createConvert(loc, toTy, val);
521+
}
522+
513523
mlir::Value fir::factory::createConvert(mlir::OpBuilder &builder,
514524
mlir::Location loc, mlir::Type toTy,
515525
mlir::Value val) {
@@ -672,17 +682,18 @@ mlir::Value fir::FirOpBuilder::createBox(mlir::Location loc,
672682
<< itemAddr.getType();
673683
llvm_unreachable("not a memory reference type");
674684
}
685+
const bool isVolatile = fir::isa_volatile_type(itemAddr.getType());
675686
mlir::Type boxTy;
676687
mlir::Value tdesc;
677688
// Avoid to wrap a box/class with box/class.
678689
if (mlir::isa<fir::BaseBoxType>(elementType)) {
679690
boxTy = elementType;
680691
} else {
681-
boxTy = fir::BoxType::get(elementType);
692+
boxTy = fir::BoxType::get(elementType, isVolatile);
682693
if (isPolymorphic) {
683694
elementType = fir::updateTypeForUnlimitedPolymorphic(elementType);
684695
if (isAssumedType)
685-
boxTy = fir::BoxType::get(elementType);
696+
boxTy = fir::BoxType::get(elementType, isVolatile);
686697
else
687698
boxTy = fir::ClassType::get(elementType);
688699
}

flang/lib/Optimizer/Dialect/FIROps.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,8 +1357,6 @@ llvm::LogicalResult fir::VolatileCastOp::verify() {
13571357
mlir::isa<fir::ReferenceType>(toType));
13581358
bool sameElementType = fir::dyn_cast_ptrOrBoxEleTy(fromType) ==
13591359
fir::dyn_cast_ptrOrBoxEleTy(toType);
1360-
llvm::dbgs() << fromType << " / " << toType << "\n"
1361-
<< sameBaseType << " " << sameElementType << "\n";
13621360
if (fromType == toType ||
13631361
fir::isa_volatile_type(fromType) == fir::isa_volatile_type(toType) ||
13641362
!sameBaseType || !sameElementType)
@@ -1367,6 +1365,12 @@ llvm::LogicalResult fir::VolatileCastOp::verify() {
13671365
return mlir::success();
13681366
}
13691367

1368+
mlir::OpFoldResult fir::VolatileCastOp::fold(FoldAdaptor adaptor) {
1369+
if (getValue().getType() == getType())
1370+
return getValue();
1371+
return {};
1372+
}
1373+
13701374
//===----------------------------------------------------------------------===//
13711375
// ConvertOp
13721376
//===----------------------------------------------------------------------===//
@@ -1838,9 +1842,9 @@ llvm::LogicalResult fir::EmboxOp::verify() {
18381842
return emitOpError("slice must not be provided for a scalar");
18391843
if (getSourceBox() && !mlir::isa<fir::ClassType>(getResult().getType()))
18401844
return emitOpError("source_box must be used with fir.class result type");
1841-
if (fir::isa_volatile_type(getMemref().getType()) !=
1842-
fir::isa_volatile_type(getResult().getType()))
1843-
return emitOpError("input and output types must have the same volatility");
1845+
// if (fir::isa_volatile_type(getMemref().getType()) !=
1846+
// fir::isa_volatile_type(getResult().getType()))
1847+
// return emitOpError("input and output types must have the same volatility");
18441848
return mlir::success();
18451849
}
18461850

flang/lib/Optimizer/Dialect/FIRType.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,6 +1319,19 @@ bool fir::hasAbstractResult(mlir::FunctionType ty) {
13191319
resultType);
13201320
}
13211321

1322+
mlir::Type fir::updateTypeWithVolatility(mlir::Type type, bool isVolatile) {
1323+
if (fir::isa_volatile_type(type) == isVolatile)
1324+
return type;
1325+
return mlir::TypeSwitch<mlir::Type, mlir::Type>(type)
1326+
.Case<fir::BoxType, fir::ReferenceType>([&](auto ty) -> mlir::Type {
1327+
using TYPE = decltype(ty);
1328+
return TYPE::get(ty.getEleTy(), isVolatile);
1329+
})
1330+
.Default([&](mlir::Type t) -> mlir::Type {
1331+
return t;
1332+
});
1333+
}
1334+
13221335
/// Convert llvm::Type::TypeID to mlir::Type. \p kind is provided for error
13231336
/// messages only.
13241337
mlir::Type fir::fromRealTypeID(mlir::MLIRContext *context,

flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,7 @@ getIntrinsicEffects(mlir::Operation *self,
6161
// }
6262
for (mlir::OpOperand &operand : self->getOpOperands()) {
6363
mlir::Type opTy = operand.get().getType();
64-
if (fir::isa_volatile_type(opTy)) {
65-
effects.emplace_back(mlir::MemoryEffects::Read::get(), &operand,
66-
mlir::SideEffects::DefaultResource::get());
67-
effects.emplace_back(mlir::MemoryEffects::Write::get(), &operand,
68-
mlir::SideEffects::DefaultResource::get());
69-
}
64+
fir::addVolatileMemoryEffects({opTy}, effects);
7065
if (fir::isa_ref_type(opTy) || fir::isa_box_type(opTy))
7166
effects.emplace_back(mlir::MemoryEffects::Read::get(), &operand,
7267
mlir::SideEffects::DefaultResource::get());
@@ -203,7 +198,7 @@ mlir::Type hlfir::DeclareOp::getHLFIRVariableType(mlir::Type inputType,
203198
bool hasDynamicLengthParams = fir::characterWithDynamicLen(eleType) ||
204199
fir::isRecordWithTypeParameters(eleType);
205200
if (hasExplicitLowerBounds || hasDynamicExtents || hasDynamicLengthParams)
206-
return fir::BoxType::get(type);
201+
return fir::BoxType::get(type, fir::isa_volatile_type(inputType));
207202
return inputType;
208203
}
209204

flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,7 @@ class AssignOpConversion : public mlir::OpRewritePattern<hlfir::AssignOp> {
8989
return fir::getBase(builder.createBox(loc, rhsExv));
9090
};
9191

92-
if (fir::isa_volatile_type(lhs.getType()) ||
93-
fir::isa_volatile_type(rhs.getType())) {
94-
fir::factory::genScalarAssignment(builder, loc, lhsExv, rhsExv,
95-
/*needFinalization=*/false,
96-
assignOp.isTemporaryLHS());
97-
} else if (assignOp.isAllocatableAssignment()) {
92+
if (assignOp.isAllocatableAssignment()) {
9893
// Whole allocatable assignment: use the runtime to deal with the
9994
// reallocation.
10095
mlir::Value from = emboxRHS(rhsExv);

flang/test/Fir/invalid-types.fir

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,14 @@ func.func private @oth3() -> !fir.vector<10:>
157157
// expected-error@+1 {{invalid element type}}
158158
func.func private @upe() -> !fir.class<!fir.box<i32>>
159159

160+
// -----
161+
160162
// TODO: why are source locations lost on the error message?
161163
// the error message is printed but without a proper source location.
162-
// -- ---
163-
// expected-error skipme @+1 {{invalid element type}}
164+
// expected-error <skipme> @+1 {{invalid element type}}
164165
// func.func private @upe() -> !fir.box<!fir.class<none>>
166+
167+
// -----
168+
169+
// expected-error@+1 {{invalid element type}}
170+
func.func private @upe() -> !fir.class<!fir.box<i32>>

flang/test/Lower/volatile.f90

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,52 @@
11
! RUN: bbc %s -o - | FileCheck %s
2-
logical, volatile :: a
3-
logical :: b
4-
integer :: i
5-
a = .false.
6-
b = a
7-
a = .true.
8-
end
92

10-
! CHECK: %{{.+}} = fir.load %{{.+}} : !fir.ref<!fir.logical<4>, volatile>
11-
! CHECK: hlfir.assign %{{.+}} to %{{.+}} : !fir.logical<4>, !fir.ref<!fir.logical<4>, volatile>
3+
program p
4+
integer,volatile::i,arr(10)
5+
i=0
6+
arr=1
7+
! casting from volatile ref to non-volatile ref should be okay here
8+
call not_declared_volatile_in_this_scope(i)
9+
call not_declared_volatile_in_this_scope(arr)
10+
call declared_volatile_in_this_scope(arr,10)
11+
print*,arr,i
12+
contains
13+
elemental subroutine not_declared_volatile_in_this_scope(v)
14+
integer,intent(inout)::v
15+
v=1
16+
end subroutine
17+
subroutine declared_volatile_in_this_scope(v,n)
18+
integer,intent(in)::n
19+
integer,volatile,intent(inout)::v(n)
20+
v=1
21+
end subroutine
22+
end program
23+
24+
! CHECK-LABEL: _QQmain
25+
! CHECK: %[[VAL_10:.*]] = fir.volatile_cast %{{.+}} : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
26+
! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare {{.+}} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>)
27+
! CHECK: %[[VAL_12:.*]] = fir.alloca i32
28+
! CHECK: %[[VAL_13:.*]] = fir.volatile_cast %[[VAL_12]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
29+
! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare {{.+}} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>)
30+
! CHECK: hlfir.assign %{{.+}} to %[[VAL_14]]#0 : i32, !fir.ref<i32, volatile>
31+
! CHECK: hlfir.assign %{{.+}} to %[[VAL_11]]#0 : i32, !fir.ref<!fir.array<10xi32>, volatile>
32+
! CHECK: %[[VAL_15:.*]] = fir.volatile_cast %[[VAL_14]]#0 : (!fir.ref<i32, volatile>) -> !fir.ref<i32>
33+
! CHECK: fir.call @_QFPnot_declared_volatile_in_this_scope(%[[VAL_15]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<i32>) -> ()
34+
! CHECK: %[[VAL_19:.*]] = hlfir.designate %{{.+}} (%{{.+}}) : (!fir.ref<!fir.array<10xi32>, volatile>, index) -> !fir.ref<i32, volatile>
35+
! CHECK: %[[VAL_20:.*]] = fir.volatile_cast %[[VAL_19]] : (!fir.ref<i32, volatile>) -> !fir.ref<i32>
36+
! CHECK: fir.call @_QFPnot_declared_volatile_in_this_scope(%[[VAL_20]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<i32>) -> ()
37+
! CHECK: %[[VAL_23:.*]] = fir.volatile_cast %[[VAL_11]]#0 : (!fir.ref<!fir.array<10xi32>, volatile>) -> !fir.ref<!fir.array<10xi32>>
38+
! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_23]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<?xi32>>
39+
! CHECK: %[[VAL_25:.*]]:3 = hlfir.associate %{{.+}} {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1)
40+
! CHECK: fir.call @_QFPdeclared_volatile_in_this_scope(%[[VAL_24]], %[[VAL_25]]#0) fastmath<contract> : (!fir.ref<!fir.array<?xi32>>, !fir.ref<i32>) -> ()
41+
! CHECK: hlfir.end_associate %[[VAL_25]]#1, %[[VAL_25]]#2 : !fir.ref<i32>, i1
42+
! CHECK: %[[VAL_26:.*]] = fir.address_of(@_QQclX6951b66b308fd310127f64e03dcd1051) : !fir.ref<!fir.char<1,78>>
43+
! CHECK: %[[VAL_27:.*]] = fir.convert %[[VAL_26]] : (!fir.ref<!fir.char<1,78>>) -> !fir.ref<i8>
44+
! CHECK: %[[VAL_28:.*]] = fir.call @_FortranAioBeginExternalListOutput(
45+
! CHECK: %[[VAL_29:.*]] = fir.embox %{{.+}} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>, volatile>
46+
! CHECK: %[[VAL_30:.*]] = fir.volatile_cast %[[VAL_29]] : (!fir.box<!fir.array<10xi32>, volatile>) -> !fir.box<!fir.array<10xi32>>
47+
! CHECK: %[[VAL_31:.*]] = fir.convert %[[VAL_30]] : (!fir.box<!fir.array<10xi32>>) -> !fir.box<none>
48+
! CHECK: %[[VAL_32:.*]] = fir.call @_FortranAioOutputDescriptor(
49+
! CHECK: %[[VAL_33:.*]] = fir.load %[[VAL_14]]#0 : !fir.ref<i32, volatile>
50+
! CHECK: %[[VAL_34:.*]] = fir.call @_FortranAioOutputInteger32(
51+
! CHECK: %[[VAL_35:.*]] = fir.call @_FortranAioEndIoStatement(
52+
! CHECK: return

0 commit comments

Comments
 (0)