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

0 commit comments

Comments
 (0)