diff --git a/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp b/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp --- a/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp +++ b/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp @@ -165,6 +165,17 @@ return optionallyTruncateOrExtend(loc, broadcasted, dstType, rewriter); } +/// Converts SPIR-V struct with no offset to packed LLVM struct. +static Type convertStructTypePacked(spirv::StructType type, + LLVMTypeConverter &converter) { + auto elementsVector = llvm::to_vector<8>( + llvm::map_range(type.getElementTypes(), [&](Type elementType) { + return converter.convertType(elementType).cast(); + })); + return LLVM::LLVMType::getStructTy(converter.getDialect(), elementsVector, + /*isPacked=*/true); +} + //===----------------------------------------------------------------------===// // Type conversion //===----------------------------------------------------------------------===// @@ -202,6 +213,17 @@ return LLVM::LLVMType::getArrayTy(elementType, 0); } +/// Converts SPIR-V struct to LLVM struct. There is no support of structs with +/// member decorations or with offset. +static Optional convertStructType(spirv::StructType type, + LLVMTypeConverter &converter) { + SmallVector memberDecorations; + type.getMemberDecorations(memberDecorations); + if (type.hasOffset() || !memberDecorations.empty()) + return llvm::None; + return convertStructTypePacked(type, converter); +} + //===----------------------------------------------------------------------===// // Operation conversion //===----------------------------------------------------------------------===// @@ -711,6 +733,9 @@ typeConverter.addConversion([&](spirv::RuntimeArrayType type) { return convertRuntimeArrayType(type, typeConverter); }); + typeConverter.addConversion([&](spirv::StructType type) { + return convertStructType(type, typeConverter); + }); } void mlir::populateSPIRVToLLVMConversionPatterns( diff --git a/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.invalid.mlir b/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.invalid.mlir --- a/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.invalid.mlir +++ b/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.invalid.mlir @@ -4,3 +4,24 @@ spv.func @array_with_stride(%arg: !spv.array<4 x f32, stride=4>) -> () "None" { spv.Return } + +// ----- + +// expected-error@+1 {{failed to legalize operation 'spv.func' that was explicitly marked illegal}} +spv.func @struct_with_offset1(%arg: !spv.struct) -> () "None" { + spv.Return +} + +// ----- + +// expected-error@+1 {{failed to legalize operation 'spv.func' that was explicitly marked illegal}} +spv.func @struct_with_offset2(%arg: !spv.struct) -> () "None" { + spv.Return +} + +// ----- + +// expected-error@+1 {{failed to legalize operation 'spv.func' that was explicitly marked illegal}} +spv.func @struct_with_decorations(%arg: !spv.struct) -> () "None" { + spv.Return +} diff --git a/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.mlir b/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.mlir --- a/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.mlir +++ b/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.mlir @@ -26,3 +26,13 @@ // CHECK-LABEL: @runtime_array_scalar(!llvm<"[0 x float]">) func @runtime_array_scalar(!spv.rtarray) -> () + +//===----------------------------------------------------------------------===// +// Struct type +//===----------------------------------------------------------------------===// + +// CHECK-LABEL: @struct(!llvm<"<{ double }>">) +func @struct(!spv.struct) -> () + +// CHECK-LABEL: @struct_nested(!llvm<"<{ i32, <{ i64, i32 }> }>">) +func @struct_nested(!spv.struct>)