Skip to content

Commit 49ca7b2

Browse files
Pierre-vhronlieb
authored andcommitted
[mlir][spirv] Handle failed conversions of struct elements (llvm#70005)
LLVMStructTypes could be emitted with some null elements. This caused a crash later in the LLVMDialect verifier. We now use `convertTypes` and check that all types were successfully converted before passing them to the `LLVMStructType` constructor. See llvm#59990 Change-Id: I0f0ff1f8eb939bd760e5acb7e24017061a2eeac5
1 parent 41f20a1 commit 49ca7b2

File tree

4 files changed

+23
-39
lines changed

4 files changed

+23
-39
lines changed

mlir/include/mlir/Dialect/SPIRV/IR/SPIRVTypes.h

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -347,27 +347,7 @@ class StructType
347347

348348
Type getElementType(unsigned) const;
349349

350-
/// Range class for element types.
351-
class ElementTypeRange
352-
: public ::llvm::detail::indexed_accessor_range_base<
353-
ElementTypeRange, const Type *, Type, Type, Type> {
354-
private:
355-
using RangeBaseT::RangeBaseT;
356-
357-
/// See `llvm::detail::indexed_accessor_range_base` for details.
358-
static const Type *offset_base(const Type *object, ptrdiff_t index) {
359-
return object + index;
360-
}
361-
/// See `llvm::detail::indexed_accessor_range_base` for details.
362-
static Type dereference_iterator(const Type *object, ptrdiff_t index) {
363-
return object[index];
364-
}
365-
366-
/// Allow base class access to `offset_base` and `dereference_iterator`.
367-
friend RangeBaseT;
368-
};
369-
370-
ElementTypeRange getElementTypes() const;
350+
TypeRange getElementTypes() const;
371351

372352
bool hasOffset() const;
373353

mlir/lib/Conversion/SPIRVToLLVM/SPIRVToLLVM.cpp

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -195,27 +195,24 @@ static Value processCountOrOffset(Location loc, Value value, Type srcType,
195195

196196
/// Converts SPIR-V struct with a regular (according to `VulkanLayoutUtils`)
197197
/// offset to LLVM struct. Otherwise, the conversion is not supported.
198-
static std::optional<Type>
199-
convertStructTypeWithOffset(spirv::StructType type,
200-
LLVMTypeConverter &converter) {
198+
static Type convertStructTypeWithOffset(spirv::StructType type,
199+
LLVMTypeConverter &converter) {
201200
if (type != VulkanLayoutUtils::decorateType(type))
202-
return std::nullopt;
201+
return nullptr;
203202

204-
auto elementsVector = llvm::to_vector<8>(
205-
llvm::map_range(type.getElementTypes(), [&](Type elementType) {
206-
return converter.convertType(elementType);
207-
}));
203+
SmallVector<Type> elementsVector;
204+
if (failed(converter.convertTypes(type.getElementTypes(), elementsVector)))
205+
return nullptr;
208206
return LLVM::LLVMStructType::getLiteral(type.getContext(), elementsVector,
209207
/*isPacked=*/false);
210208
}
211209

212210
/// Converts SPIR-V struct with no offset to packed LLVM struct.
213211
static Type convertStructTypePacked(spirv::StructType type,
214212
LLVMTypeConverter &converter) {
215-
auto elementsVector = llvm::to_vector<8>(
216-
llvm::map_range(type.getElementTypes(), [&](Type elementType) {
217-
return converter.convertType(elementType);
218-
}));
213+
SmallVector<Type> elementsVector;
214+
if (failed(converter.convertTypes(type.getElementTypes(), elementsVector)))
215+
return nullptr;
219216
return LLVM::LLVMStructType::getLiteral(type.getContext(), elementsVector,
220217
/*isPacked=*/true);
221218
}
@@ -292,12 +289,12 @@ static std::optional<Type> convertRuntimeArrayType(spirv::RuntimeArrayType type,
292289

293290
/// Converts SPIR-V struct to LLVM struct. There is no support of structs with
294291
/// member decorations. Also, only natural offset is supported.
295-
static std::optional<Type> convertStructType(spirv::StructType type,
296-
LLVMTypeConverter &converter) {
292+
static Type convertStructType(spirv::StructType type,
293+
LLVMTypeConverter &converter) {
297294
SmallVector<spirv::StructType::MemberDecorationInfo, 4> memberDecorations;
298295
type.getMemberDecorations(memberDecorations);
299296
if (!memberDecorations.empty())
300-
return std::nullopt;
297+
return nullptr;
301298
if (type.hasOffset())
302299
return convertStructTypeWithOffset(type, converter);
303300
return convertStructTypePacked(type, converter);

mlir/lib/Dialect/SPIRV/IR/SPIRVTypes.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,9 +1154,9 @@ Type StructType::getElementType(unsigned index) const {
11541154
return getImpl()->memberTypesAndIsBodySet.getPointer()[index];
11551155
}
11561156

1157-
StructType::ElementTypeRange StructType::getElementTypes() const {
1158-
return ElementTypeRange(getImpl()->memberTypesAndIsBodySet.getPointer(),
1159-
getNumElements());
1157+
TypeRange StructType::getElementTypes() const {
1158+
return TypeRange(getImpl()->memberTypesAndIsBodySet.getPointer(),
1159+
getNumElements());
11601160
}
11611161

11621162
bool StructType::hasOffset() const { return getImpl()->offsetInfo; }

mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm-invalid.mlir

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ spirv.func @array_with_unnatural_stride(%arg: !spirv.array<4 x f32, stride=8>) -
77

88
// -----
99

10+
// expected-error@+1 {{failed to legalize operation 'spirv.func' that was explicitly marked illegal}}
11+
spirv.func @struct_array_with_unnatural_stride(%arg: !spirv.struct<(!spirv.array<4 x f32, stride=8>)>) -> () "None" {
12+
spirv.Return
13+
}
14+
15+
// -----
16+
1017
// expected-error@+1 {{failed to legalize operation 'spirv.func' that was explicitly marked illegal}}
1118
spirv.func @struct_with_unnatural_offset(%arg: !spirv.struct<(i32[0], i32[8])>) -> () "None" {
1219
spirv.Return

0 commit comments

Comments
 (0)