From 38db490f855499c9416f0b2af70540678e05b44d Mon Sep 17 00:00:00 2001 From: Lorenc Bushi Date: Tue, 8 Oct 2024 13:06:03 -0400 Subject: [PATCH] Translate LLVM-IR zero-length arrays to 1-length arrays in SPIR-V (#2743) The LLVM-IR type of zero-length array does not seem to have a mapping into SPIR-V type, rather it outputs an error since the obvious choice of zero-length array is not valid in SPIR-V. This, for example, prohibits us from using unbounded arrays in SYCL device kernels because they are typically represented in LLVM-IR through zero-length arrays. This PR attempts to introduce a workaround to this by lowering a zero-length array in LLVM-IR to a 1-length array in SPIR-V. --- lib/SPIRV/SPIRVWriter.cpp | 13 ++++--------- lib/SPIRV/libSPIRV/SPIRVErrorEnum.h | 1 - test/{negative => }/zero-length-array.ll | 6 ++++-- 3 files changed, 8 insertions(+), 12 deletions(-) rename test/{negative => }/zero-length-array.ll (85%) diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp index 3dac068a66..6b94cb0210 100644 --- a/lib/SPIRV/SPIRVWriter.cpp +++ b/lib/SPIRV/SPIRVWriter.cpp @@ -449,24 +449,19 @@ SPIRVType *LLVMToSPIRVBase::transType(Type *T) { if (T->isArrayTy()) { // SPIR-V 1.3 s3.32.6: Length is the number of elements in the array. // It must be at least 1. - if (T->getArrayNumElements() < 1) { - std::string Str; - llvm::raw_string_ostream OS(Str); - OS << *T; - SPIRVCK(T->getArrayNumElements() >= 1, InvalidArraySize, OS.str()); - } + const auto ArraySize = + T->getArrayNumElements() ? T->getArrayNumElements() : 1; Type *ElTy = T->getArrayElementType(); SPIRVType *TransType = BM->addArrayType( transType(ElTy), static_cast(transValue( - ConstantInt::get(getSizetType(), T->getArrayNumElements(), false), - nullptr))); + ConstantInt::get(getSizetType(), ArraySize, false), nullptr))); mapType(T, TransType); if (ElTy->isPointerTy()) { mapType( ArrayType::get(TypedPointerType::get(Type::getInt8Ty(*Ctx), ElTy->getPointerAddressSpace()), - T->getArrayNumElements()), + ArraySize), TransType); } return TransType; diff --git a/lib/SPIRV/libSPIRV/SPIRVErrorEnum.h b/lib/SPIRV/libSPIRV/SPIRVErrorEnum.h index 1a45fdd3dc..cda2e8ae3b 100644 --- a/lib/SPIRV/libSPIRV/SPIRVErrorEnum.h +++ b/lib/SPIRV/libSPIRV/SPIRVErrorEnum.h @@ -10,7 +10,6 @@ _SPIRV_OP(InvalidMemoryModel, "Expects 0-3.") _SPIRV_OP(InvalidFunctionControlMask, "") _SPIRV_OP(InvalidBuiltinSetName, "Expects OpenCL.std.") _SPIRV_OP(InvalidFunctionCall, "Unexpected llvm intrinsic:\n") -_SPIRV_OP(InvalidArraySize, "Array size must be at least 1:") _SPIRV_OP(InvalidBitWidth, "Invalid bit width in input:") _SPIRV_OP(InvalidModule, "Invalid SPIR-V module:") _SPIRV_OP(InvalidLlvmModule, "Invalid LLVM module:") diff --git a/test/negative/zero-length-array.ll b/test/zero-length-array.ll similarity index 85% rename from test/negative/zero-length-array.ll rename to test/zero-length-array.ll index 3689093fa6..75fce368a4 100644 --- a/test/negative/zero-length-array.ll +++ b/test/zero-length-array.ll @@ -1,7 +1,9 @@ ; RUN: llvm-as %s -o %t.bc -; RUN: not llvm-spirv %t.bc -o %t.spv 2>&1 | FileCheck %s +; RUN: llvm-spirv %t.bc -o %t.spv +; RUN: spirv-dis %t.spv | FileCheck %s -; CHECK: InvalidArraySize: Array size must be at least 1: [0 x i32] +; CHECK: [[REGISTER:%[a-zA-Z0-9_]+]] = OpConstant %uint 1 +; CHECK: OpTypeArray %uint [[REGISTER]] source_filename = "test.cl" target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"