Skip to content

Commit d43b00d

Browse files
[flang][nfc] Support volatile on ref and box types
1 parent 46e2c07 commit d43b00d

File tree

7 files changed

+192
-24
lines changed

7 files changed

+192
-24
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener {
150150
mlir::Block *getAllocaBlock();
151151

152152
/// Safely create a reference type to the type `eleTy`.
153-
mlir::Type getRefType(mlir::Type eleTy);
153+
mlir::Type getRefType(mlir::Type eleTy, bool isVolatile = false);
154154

155155
/// Create a sequence of `eleTy` with `rank` dimensions of unknown size.
156156
mlir::Type getVarLenSeqTy(mlir::Type eleTy, unsigned rank = 1);

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,10 @@ inline bool isa_char_string(mlir::Type t) {
221221
/// (since they may hold one), and are not considered to be unknown size.
222222
bool isa_unknown_size_box(mlir::Type t);
223223

224+
/// Returns true iff `t` is a type capable of representing volatility and has
225+
/// the volatile attribute set.
226+
bool isa_volatile_type(mlir::Type t);
227+
224228
/// Returns true iff `t` is a fir.char type and has an unknown length.
225229
inline bool characterWithDynamicLen(mlir::Type t) {
226230
if (auto charTy = mlir::dyn_cast<fir::CharacterType>(t))
@@ -474,6 +478,10 @@ inline mlir::Type updateTypeForUnlimitedPolymorphic(mlir::Type ty) {
474478
return ty;
475479
}
476480

481+
/// Re-create the given type with the given volatility, if this is a type
482+
/// that can represent volatility.
483+
mlir::Type updateTypeWithVolatility(mlir::Type type, bool isVolatile);
484+
477485
/// Replace the element type of \p type by \p newElementType, preserving
478486
/// all other layers of the type (fir.ref/ptr/heap/array/box/class).
479487
/// If \p turnBoxIntoClass and the input is a fir.box, it will be turned into

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

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -77,24 +77,24 @@ def fir_BoxType : FIR_Type<"Box", "box", [], "BaseBoxType"> {
7777
to) whether the entity is an array, its size, or what type it has.
7878
}];
7979

80-
let parameters = (ins "mlir::Type":$eleTy);
80+
let parameters = (ins "mlir::Type":$eleTy, "bool":$isVolatile);
8181

8282
let skipDefaultBuilders = 1;
8383

8484
let builders = [
8585
TypeBuilderWithInferredContext<(ins
86-
"mlir::Type":$eleTy), [{
87-
return Base::get(eleTy.getContext(), eleTy);
86+
"mlir::Type":$eleTy, CArg<"bool", "false">:$isVolatile), [{
87+
return Base::get(eleTy.getContext(), eleTy, isVolatile);
8888
}]>,
8989
];
9090

9191
let extraClassDeclaration = [{
9292
mlir::Type getElementType() const { return getEleTy(); }
93+
bool isVolatile() const { return getIsVolatile(); }
9394
}];
9495

9596
let genVerifyDecl = 1;
96-
97-
let assemblyFormat = "`<` $eleTy `>`";
97+
let hasCustomAssemblyFormat = 1;
9898
}
9999

100100
def fir_CharacterType : FIR_Type<"Character", "char"> {
@@ -146,16 +146,20 @@ def fir_ClassType : FIR_Type<"Class", "class", [], "BaseBoxType"> {
146146
is equivalent to a fir.box type with a dynamic type.
147147
}];
148148

149-
let parameters = (ins "mlir::Type":$eleTy);
149+
let parameters = (ins "mlir::Type":$eleTy, "bool":$isVolatile);
150150

151151
let builders = [
152-
TypeBuilderWithInferredContext<(ins "mlir::Type":$eleTy), [{
153-
return $_get(eleTy.getContext(), eleTy);
152+
TypeBuilderWithInferredContext<(ins "mlir::Type":$eleTy, CArg<"bool", "false">:$isVolatile), [{
153+
return $_get(eleTy.getContext(), eleTy, isVolatile);
154154
}]>
155155
];
156156

157+
let extraClassDeclaration = [{
158+
bool isVolatile() const { return getIsVolatile(); }
159+
}];
160+
157161
let genVerifyDecl = 1;
158-
let assemblyFormat = "`<` $eleTy `>`";
162+
let hasCustomAssemblyFormat = 1;
159163
}
160164

161165
def fir_FieldType : FIR_Type<"Field", "field"> {
@@ -363,18 +367,19 @@ def fir_ReferenceType : FIR_Type<"Reference", "ref"> {
363367
The type of a reference to an entity in memory.
364368
}];
365369

366-
let parameters = (ins "mlir::Type":$eleTy);
370+
let parameters = (ins "mlir::Type":$eleTy, "bool":$isVolatile);
367371

368372
let skipDefaultBuilders = 1;
369373

370374
let builders = [
371-
TypeBuilderWithInferredContext<(ins "mlir::Type":$elementType), [{
372-
return Base::get(elementType.getContext(), elementType);
375+
TypeBuilderWithInferredContext<(ins "mlir::Type":$elementType, CArg<"bool", "false">:$isVolatile), [{
376+
return Base::get(elementType.getContext(), elementType, isVolatile);
373377
}]>,
374378
];
375379

376380
let extraClassDeclaration = [{
377381
mlir::Type getElementType() const { return getEleTy(); }
382+
bool isVolatile() const { return getIsVolatile(); }
378383
}];
379384

380385
let genVerifyDecl = 1;

flang/lib/Optimizer/Builder/FIRBuilder.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ fir::FirOpBuilder::getNamedGlobal(mlir::ModuleOp modOp,
105105
return modOp.lookupSymbol<fir::GlobalOp>(name);
106106
}
107107

108-
mlir::Type fir::FirOpBuilder::getRefType(mlir::Type eleTy) {
108+
mlir::Type fir::FirOpBuilder::getRefType(mlir::Type eleTy, bool isVolatile) {
109109
assert(!mlir::isa<fir::ReferenceType>(eleTy) && "cannot be a reference type");
110-
return fir::ReferenceType::get(eleTy);
110+
return fir::ReferenceType::get(eleTy, isVolatile);
111111
}
112112

113113
mlir::Type fir::FirOpBuilder::getVarLenSeqTy(mlir::Type eleTy, unsigned rank) {

flang/lib/Optimizer/Dialect/FIRType.cpp

Lines changed: 101 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,21 @@ using namespace fir;
3232

3333
namespace {
3434

35+
static llvm::StringRef getVolatileKeyword() { return "volatile"; }
36+
37+
static mlir::ParseResult parseOptionalCommaAndKeyword(mlir::AsmParser &parser,
38+
mlir::StringRef keyword,
39+
bool &parsedKeyword) {
40+
if (!parser.parseOptionalComma()) {
41+
if (parser.parseKeyword(keyword))
42+
return mlir::failure();
43+
parsedKeyword = true;
44+
return mlir::success();
45+
}
46+
parsedKeyword = false;
47+
return mlir::success();
48+
}
49+
3550
template <typename TYPE>
3651
TYPE parseIntSingleton(mlir::AsmParser &parser) {
3752
int kind = 0;
@@ -215,6 +230,19 @@ mlir::Type getDerivedType(mlir::Type ty) {
215230
.Default([](mlir::Type t) { return t; });
216231
}
217232

233+
mlir::Type updateTypeWithVolatility(mlir::Type type, bool isVolatile) {
234+
// If we already have the volatility we asked for, return the type unchanged.
235+
if (fir::isa_volatile_type(type) == isVolatile)
236+
return type;
237+
return mlir::TypeSwitch<mlir::Type, mlir::Type>(type)
238+
.Case<fir::BoxType, fir::ClassType, fir::ReferenceType>(
239+
[&](auto ty) -> mlir::Type {
240+
using TYPE = decltype(ty);
241+
return TYPE::get(ty.getEleTy(), isVolatile);
242+
})
243+
.Default([&](mlir::Type t) -> mlir::Type { return t; });
244+
}
245+
218246
mlir::Type dyn_cast_ptrEleTy(mlir::Type t) {
219247
return llvm::TypeSwitch<mlir::Type, mlir::Type>(t)
220248
.Case<fir::ReferenceType, fir::PointerType, fir::HeapType,
@@ -701,6 +729,13 @@ bool fir::isa_unknown_size_box(mlir::Type t) {
701729
return false;
702730
}
703731

732+
bool fir::isa_volatile_type(mlir::Type t) {
733+
return llvm::TypeSwitch<mlir::Type, bool>(t)
734+
.Case<fir::ReferenceType, fir::BoxType, fir::ClassType>(
735+
[](auto t) { return t.isVolatile(); })
736+
.Default([](mlir::Type) { return false; });
737+
}
738+
704739
//===----------------------------------------------------------------------===//
705740
// BoxProcType
706741
//===----------------------------------------------------------------------===//
@@ -738,9 +773,31 @@ static bool cannotBePointerOrHeapElementType(mlir::Type eleTy) {
738773
// BoxType
739774
//===----------------------------------------------------------------------===//
740775

776+
// `box` `<` type (`, volatile` $volatile^)? `>`
777+
mlir::Type fir::BoxType::parse(mlir::AsmParser &parser) {
778+
mlir::Type eleTy;
779+
auto location = parser.getCurrentLocation();
780+
auto *context = parser.getContext();
781+
bool isVolatile = false;
782+
if (parser.parseLess() || parser.parseType(eleTy))
783+
return {};
784+
if (parseOptionalCommaAndKeyword(parser, getVolatileKeyword(), isVolatile))
785+
return {};
786+
if (parser.parseGreater())
787+
return {};
788+
return parser.getChecked<fir::BoxType>(location, context, eleTy, isVolatile);
789+
}
790+
791+
void fir::BoxType::print(mlir::AsmPrinter &printer) const {
792+
printer << "<" << getEleTy();
793+
if (isVolatile())
794+
printer << ", " << getVolatileKeyword();
795+
printer << '>';
796+
}
797+
741798
llvm::LogicalResult
742799
fir::BoxType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
743-
mlir::Type eleTy) {
800+
mlir::Type eleTy, bool isVolatile) {
744801
if (mlir::isa<fir::BaseBoxType>(eleTy))
745802
return emitError() << "invalid element type\n";
746803
// TODO
@@ -807,9 +864,32 @@ void fir::CharacterType::print(mlir::AsmPrinter &printer) const {
807864
// ClassType
808865
//===----------------------------------------------------------------------===//
809866

867+
// `class` `<` type (`, volatile` $volatile^)? `>`
868+
mlir::Type fir::ClassType::parse(mlir::AsmParser &parser) {
869+
mlir::Type eleTy;
870+
auto location = parser.getCurrentLocation();
871+
auto *context = parser.getContext();
872+
bool isVolatile = false;
873+
if (parser.parseLess() || parser.parseType(eleTy))
874+
return {};
875+
if (parseOptionalCommaAndKeyword(parser, getVolatileKeyword(), isVolatile))
876+
return {};
877+
if (parser.parseGreater())
878+
return {};
879+
return parser.getChecked<fir::ClassType>(location, context, eleTy,
880+
isVolatile);
881+
}
882+
883+
void fir::ClassType::print(mlir::AsmPrinter &printer) const {
884+
printer << "<" << getEleTy();
885+
if (isVolatile())
886+
printer << ", " << getVolatileKeyword();
887+
printer << '>';
888+
}
889+
810890
llvm::LogicalResult
811891
fir::ClassType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
812-
mlir::Type eleTy) {
892+
mlir::Type eleTy, bool isVolatile) {
813893
if (mlir::isa<fir::RecordType, fir::SequenceType, fir::HeapType,
814894
fir::PointerType, mlir::NoneType, mlir::IntegerType,
815895
mlir::FloatType, fir::CharacterType, fir::LogicalType,
@@ -1057,18 +1137,32 @@ unsigned fir::RecordType::getFieldIndex(llvm::StringRef ident) {
10571137
// ReferenceType
10581138
//===----------------------------------------------------------------------===//
10591139

1060-
// `ref` `<` type `>`
1140+
// `ref` `<` type (`, volatile` $volatile^)? `>`
10611141
mlir::Type fir::ReferenceType::parse(mlir::AsmParser &parser) {
1062-
return parseTypeSingleton<fir::ReferenceType>(parser);
1142+
auto location = parser.getCurrentLocation();
1143+
auto *context = parser.getContext();
1144+
mlir::Type eleTy;
1145+
bool isVolatile = false;
1146+
if (parser.parseLess() || parser.parseType(eleTy))
1147+
return {};
1148+
if (parseOptionalCommaAndKeyword(parser, getVolatileKeyword(), isVolatile))
1149+
return {};
1150+
if (parser.parseGreater())
1151+
return {};
1152+
return parser.getChecked<fir::ReferenceType>(location, context, eleTy,
1153+
isVolatile);
10631154
}
10641155

10651156
void fir::ReferenceType::print(mlir::AsmPrinter &printer) const {
1066-
printer << "<" << getEleTy() << '>';
1157+
printer << "<" << getEleTy();
1158+
if (isVolatile())
1159+
printer << ", " << getVolatileKeyword();
1160+
printer << '>';
10671161
}
10681162

10691163
llvm::LogicalResult fir::ReferenceType::verify(
1070-
llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
1071-
mlir::Type eleTy) {
1164+
llvm::function_ref<mlir::InFlightDiagnostic()> emitError, mlir::Type eleTy,
1165+
bool isVolatile) {
10721166
if (mlir::isa<ShapeType, ShapeShiftType, SliceType, FieldType, LenType,
10731167
ReferenceType, TypeDescType>(eleTy))
10741168
return emitError() << "cannot build a reference to type: " << eleTy << '\n';

flang/test/Fir/invalid-types.fir

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ func.func private @box3() -> !fir.boxproc<>
66

77
// -----
88

9-
// expected-error@+2 {{expected non-function type}}
10-
// expected-error@+1 {{failed to parse fir_BoxType parameter 'eleTy' which is to be a `mlir::Type`}}
9+
// expected-error@+1 {{expected non-function type}}
1110
func.func private @box1() -> !fir.box<>
1211

1312
// -----
@@ -105,6 +104,11 @@ func.func private @mem3() -> !fir.ref<>
105104

106105
// -----
107106

107+
// expected-error@+1 {{expected non-function type}}
108+
func.func private @mem3() -> !fir.ref<, volatile>
109+
110+
// -----
111+
108112
// expected-error@+1 {{expected ':'}}
109113
func.func private @arr1() -> !fir.array<*>
110114

@@ -162,3 +166,24 @@ func.func private @upe() -> !fir.class<!fir.box<i32>>
162166

163167
// expected-error@+1 {{invalid element type}}
164168
func.func private @upe() -> !fir.box<!fir.class<none>>
169+
170+
// -----
171+
172+
// expected-error@+1 {{invalid element type}}
173+
func.func private @upe() -> !fir.box<!fir.class<none>, volatile>
174+
175+
// -----
176+
177+
// expected-error@+1 {{invalid element type}}
178+
func.func private @upe() -> !fir.class<!fir.box<i32>>
179+
180+
// -----
181+
182+
// expected-error@+1 {{invalid element type}}
183+
func.func private @upe() -> !fir.class<!fir.box<i32>, volatile>
184+
185+
// -----
186+
187+
// expected-error@+1 {{expected non-function type}}
188+
func.func private @upe() -> !fir.class<, volatile>
189+

flang/unittests/Optimizer/FIRTypesTest.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,3 +316,39 @@ TEST_F(FIRTypesTest, getTypeAsString) {
316316
EXPECT_EQ("boxchar_c8xU",
317317
fir::getTypeAsString(fir::BoxCharType::get(&context, 1), *kindMap));
318318
}
319+
320+
TEST_F(FIRTypesTest, isVolatileType) {
321+
mlir::Type i32 = mlir::IntegerType::get(&context, 32);
322+
323+
mlir::Type i32NonVolatileRef = fir::ReferenceType::get(i32);
324+
mlir::Type i32NonVolatileBox = fir::BoxType::get(i32);
325+
mlir::Type i32NonVolatileClass = fir::ClassType::get(i32);
326+
327+
// Ensure the default value is false
328+
EXPECT_EQ(i32NonVolatileRef, fir::ReferenceType::get(i32, false));
329+
EXPECT_EQ(i32NonVolatileBox, fir::BoxType::get(i32, false));
330+
EXPECT_EQ(i32NonVolatileClass, fir::ClassType::get(i32, false));
331+
332+
EXPECT_FALSE(fir::isa_volatile_type(i32));
333+
EXPECT_FALSE(fir::isa_volatile_type(i32NonVolatileRef));
334+
EXPECT_FALSE(fir::isa_volatile_type(i32NonVolatileBox));
335+
EXPECT_FALSE(fir::isa_volatile_type(i32NonVolatileClass));
336+
337+
// Should return the same type if it's not capable of representing volatility.
338+
EXPECT_EQ(i32, fir::updateTypeWithVolatility(i32, true));
339+
340+
mlir::Type i32VolatileRef =
341+
fir::updateTypeWithVolatility(i32NonVolatileRef, true);
342+
mlir::Type i32VolatileBox =
343+
fir::updateTypeWithVolatility(i32NonVolatileBox, true);
344+
mlir::Type i32VolatileClass =
345+
fir::updateTypeWithVolatility(i32NonVolatileClass, true);
346+
347+
EXPECT_TRUE(fir::isa_volatile_type(i32VolatileRef));
348+
EXPECT_TRUE(fir::isa_volatile_type(i32VolatileBox));
349+
EXPECT_TRUE(fir::isa_volatile_type(i32VolatileClass));
350+
351+
EXPECT_EQ(i32VolatileRef, fir::ReferenceType::get(i32, true));
352+
EXPECT_EQ(i32VolatileBox, fir::BoxType::get(i32, true));
353+
EXPECT_EQ(i32VolatileClass, fir::ClassType::get(i32, true));
354+
}

0 commit comments

Comments
 (0)