[clang][SPIRV] Add builtin for OpGenericCastToPtrExplicit and its SPIR-V friendly binding (#137805)
The patch introduce __builtin_spirv_generic_cast_to_ptr_explicit which is lowered to the llvm.spv.generic.cast.to.ptr.explicit intrinsic. The SPIR-V builtins are now split into 3 differents file: BuiltinsSPIRVCore.td, BuiltinsSPIRVVK.td for Vulkan specific builtins, BuiltinsSPIRVCL.td for OpenCL specific builtins and BuiltinsSPIRVCommon.td for common ones. The patch also introduces a new header defining its SPIR-V friendly equivalent (__spirv_GenericCastToPtrExplicit_ToGlobal, __spirv_GenericCastToPtrExplicit_ToLocal and __spirv_GenericCastToPtrExplicit_ToPrivate). The functions are declared as aliases to the new builtin allowing C-like languages to have a definition to rely on as well as gaining proper front-end diagnostics. The motivation for the header is to provide a stable binding for applications or library (such as SYCL) and allows non SPIR-V targets to provide an implementation (via libclc or similar to how it is done for gpuintrin.h).
This commit is contained in:
@@ -1,39 +0,0 @@
|
||||
//===--- BuiltinsSPIRV.td - SPIRV Builtin function database ---------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "clang/Basic/BuiltinsBase.td"
|
||||
|
||||
def SPIRVDistance : Builtin {
|
||||
let Spellings = ["__builtin_spirv_distance"];
|
||||
let Attributes = [NoThrow, Const];
|
||||
let Prototype = "void(...)";
|
||||
}
|
||||
|
||||
def SPIRVLength : Builtin {
|
||||
let Spellings = ["__builtin_spirv_length"];
|
||||
let Attributes = [NoThrow, Const];
|
||||
let Prototype = "void(...)";
|
||||
}
|
||||
|
||||
def SPIRVReflect : Builtin {
|
||||
let Spellings = ["__builtin_spirv_reflect"];
|
||||
let Attributes = [NoThrow, Const];
|
||||
let Prototype = "void(...)";
|
||||
}
|
||||
|
||||
def SPIRVSmoothStep : Builtin {
|
||||
let Spellings = ["__builtin_spirv_smoothstep"];
|
||||
let Attributes = [NoThrow, Const, CustomTypeChecking];
|
||||
let Prototype = "void(...)";
|
||||
}
|
||||
|
||||
def SPIRVFaceForward : Builtin {
|
||||
let Spellings = ["__builtin_spirv_faceforward"];
|
||||
let Attributes = [NoThrow, Const, CustomTypeChecking];
|
||||
let Prototype = "void(...)";
|
||||
}
|
||||
15
clang/include/clang/Basic/BuiltinsSPIRVBase.td
Normal file
15
clang/include/clang/Basic/BuiltinsSPIRVBase.td
Normal file
@@ -0,0 +1,15 @@
|
||||
//===--- BuiltinsSPIRVBase.td - SPIRV Builtin function database -*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "clang/Basic/BuiltinsBase.td"
|
||||
|
||||
class SPIRVBuiltin<string prototype, list<Attribute> Attr> : Builtin {
|
||||
let Spellings = ["__builtin_spirv_"#NAME];
|
||||
let Prototype = prototype;
|
||||
let Attributes = !listconcat([NoThrow], Attr);
|
||||
}
|
||||
12
clang/include/clang/Basic/BuiltinsSPIRVCL.td
Normal file
12
clang/include/clang/Basic/BuiltinsSPIRVCL.td
Normal file
@@ -0,0 +1,12 @@
|
||||
//===--- BuiltinsSPIRVCL.td - SPIRV Builtin function database ---*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "clang/Basic/BuiltinsSPIRVBase.td"
|
||||
|
||||
def generic_cast_to_ptr_explicit
|
||||
: SPIRVBuiltin<"void*(void*, int)", [NoThrow, Const, CustomTypeChecking]>;
|
||||
13
clang/include/clang/Basic/BuiltinsSPIRVCommon.td
Normal file
13
clang/include/clang/Basic/BuiltinsSPIRVCommon.td
Normal file
@@ -0,0 +1,13 @@
|
||||
//===- BuiltinsSPIRVCommon.td - SPIRV Builtin function database -*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "clang/Basic/BuiltinsSPIRVBase.td"
|
||||
|
||||
def distance : SPIRVBuiltin<"void(...)", [NoThrow, Const]>;
|
||||
def length : SPIRVBuiltin<"void(...)", [NoThrow, Const]>;
|
||||
def smoothstep : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>;
|
||||
13
clang/include/clang/Basic/BuiltinsSPIRVVK.td
Normal file
13
clang/include/clang/Basic/BuiltinsSPIRVVK.td
Normal file
@@ -0,0 +1,13 @@
|
||||
//===--- BuiltinsSPIRVVK.td - SPIRV Builtin function database ---*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "clang/Basic/BuiltinsSPIRVBase.td"
|
||||
|
||||
|
||||
def reflect : SPIRVBuiltin<"void(...)", [NoThrow, Const]>;
|
||||
def faceforward : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>;
|
||||
@@ -109,9 +109,17 @@ clang_tablegen(BuiltinsRISCV.inc -gen-clang-builtins
|
||||
SOURCE BuiltinsRISCV.td
|
||||
TARGET ClangBuiltinsRISCV)
|
||||
|
||||
clang_tablegen(BuiltinsSPIRV.inc -gen-clang-builtins
|
||||
SOURCE BuiltinsSPIRV.td
|
||||
TARGET ClangBuiltinsSPIRV)
|
||||
clang_tablegen(BuiltinsSPIRVCommon.inc -gen-clang-builtins
|
||||
SOURCE BuiltinsSPIRVCommon.td
|
||||
TARGET ClangBuiltinsSPIRVCommon)
|
||||
|
||||
clang_tablegen(BuiltinsSPIRVVK.inc -gen-clang-builtins
|
||||
SOURCE BuiltinsSPIRVVK.td
|
||||
TARGET ClangBuiltinsSPIRVVK)
|
||||
|
||||
clang_tablegen(BuiltinsSPIRVCL.inc -gen-clang-builtins
|
||||
SOURCE BuiltinsSPIRVCL.td
|
||||
TARGET ClangBuiltinsSPIRVCL)
|
||||
|
||||
clang_tablegen(BuiltinsX86.inc -gen-clang-builtins
|
||||
SOURCE BuiltinsX86.td
|
||||
|
||||
@@ -4679,7 +4679,7 @@ def err_attribute_preferred_name_arg_invalid : Error<
|
||||
"argument %0 to 'preferred_name' attribute is not a typedef for "
|
||||
"a specialization of %1">;
|
||||
def err_attribute_builtin_alias : Error<
|
||||
"%0 attribute can only be applied to a ARM, HLSL or RISC-V builtin">;
|
||||
"%0 attribute can only be applied to a ARM, HLSL, SPIR-V or RISC-V builtin">;
|
||||
|
||||
// called-once attribute diagnostics.
|
||||
def err_called_once_attribute_wrong_type : Error<
|
||||
@@ -12878,6 +12878,16 @@ def err_bit_int_bad_size : Error<"%select{signed|unsigned}0 _BitInt must "
|
||||
def err_bit_int_max_size : Error<"%select{signed|unsigned}0 _BitInt of bit "
|
||||
"sizes greater than %1 not supported">;
|
||||
|
||||
// SPIR-V builtins diagnostics
|
||||
def err_spirv_invalid_target : Error<
|
||||
"builtin requires %select{spirv|spirv32 or spirv64}0 target">;
|
||||
def err_spirv_builtin_generic_cast_invalid_arg : Error<
|
||||
"expecting a pointer argument to the generic address space">;
|
||||
def err_spirv_enum_not_int : Error<
|
||||
"%0{storage class} argument for SPIR-V builtin is not a 32-bits integer">;
|
||||
def err_spirv_enum_not_valid : Error<
|
||||
"invalid value for %select{storage class}0 argument">;
|
||||
|
||||
// errors of expect.with.probability
|
||||
def err_probability_not_constant_float : Error<
|
||||
"probability argument to __builtin_expect_with_probability must be constant "
|
||||
|
||||
@@ -157,7 +157,17 @@ namespace clang {
|
||||
enum {
|
||||
LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
|
||||
#define GET_BUILTIN_ENUMERATORS
|
||||
#include "clang/Basic/BuiltinsSPIRV.inc"
|
||||
#include "clang/Basic/BuiltinsSPIRVCommon.inc"
|
||||
#undef GET_BUILTIN_ENUMERATORS
|
||||
FirstVKBuiltin,
|
||||
LastCoreBuiltin = FirstVKBuiltin - 1,
|
||||
#define GET_BUILTIN_ENUMERATORS
|
||||
#include "clang/Basic/BuiltinsSPIRVVK.inc"
|
||||
#undef GET_BUILTIN_ENUMERATORS
|
||||
FirstCLBuiltin,
|
||||
LastVKBuiltin = FirstCLBuiltin - 1,
|
||||
#define GET_BUILTIN_ENUMERATORS
|
||||
#include "clang/Basic/BuiltinsSPIRVCL.inc"
|
||||
#undef GET_BUILTIN_ENUMERATORS
|
||||
LastTSBuiltin
|
||||
};
|
||||
|
||||
@@ -21,7 +21,8 @@ class SemaSPIRV : public SemaBase {
|
||||
public:
|
||||
SemaSPIRV(Sema &S);
|
||||
|
||||
bool CheckSPIRVBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
|
||||
bool CheckSPIRVBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
|
||||
CallExpr *TheCall);
|
||||
};
|
||||
} // namespace clang
|
||||
|
||||
|
||||
@@ -10165,6 +10165,11 @@ bool ASTContext::canBuiltinBeRedeclared(const FunctionDecl *FD) const {
|
||||
if (LangOpts.HLSL && FD->getBuiltinID() != Builtin::NotBuiltin &&
|
||||
BuiltinInfo.hasCustomTypechecking(FD->getBuiltinID()))
|
||||
return true;
|
||||
// Allow redecl custom type checking builtin for SPIR-V.
|
||||
if (getTargetInfo().getTriple().isSPIROrSPIRV() &&
|
||||
BuiltinInfo.isTSBuiltin(FD->getBuiltinID()) &&
|
||||
BuiltinInfo.hasCustomTypechecking(FD->getBuiltinID()))
|
||||
return true;
|
||||
return BuiltinInfo.canBeRedeclared(FD->getBuiltinID());
|
||||
}
|
||||
|
||||
|
||||
@@ -24,19 +24,48 @@ static constexpr int NumBuiltins =
|
||||
clang::SPIRV::LastTSBuiltin - Builtin::FirstTSBuiltin;
|
||||
|
||||
#define GET_BUILTIN_STR_TABLE
|
||||
#include "clang/Basic/BuiltinsSPIRV.inc"
|
||||
#include "clang/Basic/BuiltinsSPIRVCommon.inc"
|
||||
#undef GET_BUILTIN_STR_TABLE
|
||||
|
||||
static constexpr Builtin::Info BuiltinInfos[] = {
|
||||
#define GET_BUILTIN_INFOS
|
||||
#include "clang/Basic/BuiltinsSPIRV.inc"
|
||||
#include "clang/Basic/BuiltinsSPIRVCommon.inc"
|
||||
#undef GET_BUILTIN_INFOS
|
||||
};
|
||||
static_assert(std::size(BuiltinInfos) == NumBuiltins);
|
||||
|
||||
namespace CL {
|
||||
#define GET_BUILTIN_STR_TABLE
|
||||
#include "clang/Basic/BuiltinsSPIRVCL.inc"
|
||||
#undef GET_BUILTIN_STR_TABLE
|
||||
|
||||
static constexpr Builtin::Info BuiltinInfos[] = {
|
||||
#define GET_BUILTIN_INFOS
|
||||
#include "clang/Basic/BuiltinsSPIRVCL.inc"
|
||||
#undef GET_BUILTIN_INFOS
|
||||
};
|
||||
} // namespace CL
|
||||
|
||||
namespace VK {
|
||||
#define GET_BUILTIN_STR_TABLE
|
||||
#include "clang/Basic/BuiltinsSPIRVVK.inc"
|
||||
#undef GET_BUILTIN_STR_TABLE
|
||||
|
||||
static constexpr Builtin::Info BuiltinInfos[] = {
|
||||
#define GET_BUILTIN_INFOS
|
||||
#include "clang/Basic/BuiltinsSPIRVVK.inc"
|
||||
#undef GET_BUILTIN_INFOS
|
||||
};
|
||||
} // namespace VK
|
||||
|
||||
static_assert(std::size(BuiltinInfos) + std::size(CL::BuiltinInfos) +
|
||||
std::size(VK::BuiltinInfos) ==
|
||||
NumBuiltins);
|
||||
|
||||
llvm::SmallVector<Builtin::InfosShard>
|
||||
SPIRVTargetInfo::getTargetBuiltins() const {
|
||||
return {{&BuiltinStrings, BuiltinInfos}};
|
||||
BaseSPIRVTargetInfo::getTargetBuiltins() const {
|
||||
return {{&BuiltinStrings, BuiltinInfos},
|
||||
{&VK::BuiltinStrings, VK::BuiltinInfos},
|
||||
{&CL::BuiltinStrings, CL::BuiltinInfos}};
|
||||
}
|
||||
|
||||
void SPIRTargetInfo::getTargetDefines(const LangOptions &Opts,
|
||||
|
||||
@@ -293,6 +293,8 @@ public:
|
||||
assert(Triple.isSPIRV() && "Invalid architecture for SPIR-V.");
|
||||
}
|
||||
|
||||
llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
|
||||
|
||||
bool hasFeature(StringRef Feature) const override {
|
||||
return Feature == "spirv";
|
||||
}
|
||||
@@ -321,8 +323,6 @@ public:
|
||||
"v256:256-v512:512-v1024:1024-n8:16:32:64-G10");
|
||||
}
|
||||
|
||||
llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
|
||||
|
||||
void getTargetDefines(const LangOptions &Opts,
|
||||
MacroBuilder &Builder) const override;
|
||||
};
|
||||
|
||||
@@ -122,12 +122,13 @@ static Value *EmitTargetArchBuiltinExpr(CodeGenFunction *CGF,
|
||||
case llvm::Triple::riscv32:
|
||||
case llvm::Triple::riscv64:
|
||||
return CGF->EmitRISCVBuiltinExpr(BuiltinID, E, ReturnValue);
|
||||
case llvm::Triple::spirv32:
|
||||
case llvm::Triple::spirv64:
|
||||
if (CGF->getTarget().getTriple().getOS() == llvm::Triple::OSType::AMDHSA)
|
||||
return CGF->EmitAMDGPUBuiltinExpr(BuiltinID, E);
|
||||
[[fallthrough]];
|
||||
case llvm::Triple::spirv:
|
||||
return CGF->EmitSPIRVBuiltinExpr(BuiltinID, E);
|
||||
case llvm::Triple::spirv64:
|
||||
if (CGF->getTarget().getTriple().getOS() != llvm::Triple::OSType::AMDHSA)
|
||||
return nullptr;
|
||||
return CGF->EmitAMDGPUBuiltinExpr(BuiltinID, E);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -83,6 +83,20 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID,
|
||||
/*ReturnType=*/N->getType(), Intrinsic::spv_faceforward,
|
||||
ArrayRef<Value *>{N, I, Ng}, /*FMFSource=*/nullptr, "spv.faceforward");
|
||||
}
|
||||
case SPIRV::BI__builtin_spirv_generic_cast_to_ptr_explicit: {
|
||||
Value *Ptr = EmitScalarExpr(E->getArg(0));
|
||||
assert(E->getArg(0)->getType()->hasPointerRepresentation() &&
|
||||
E->getArg(1)->getType()->hasIntegerRepresentation() &&
|
||||
"GenericCastToPtrExplicit takes a pointer and an int");
|
||||
llvm::Type *Res = getTypes().ConvertType(E->getType());
|
||||
assert(Res->isPointerTy() &&
|
||||
"GenericCastToPtrExplicit doesn't return a pointer");
|
||||
llvm::CallInst *Call = Builder.CreateIntrinsic(
|
||||
/*ReturnType=*/Res, Intrinsic::spv_generic_cast_to_ptr_explicit,
|
||||
ArrayRef<Value *>{Ptr}, nullptr, "spv.generic_cast");
|
||||
Call->addRetAttr(llvm::Attribute::AttrKind::NoUndef);
|
||||
return Call;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -132,6 +132,10 @@ set(riscv_files
|
||||
andes_vector.h
|
||||
)
|
||||
|
||||
set(spirv_files
|
||||
__clang_spirv_builtins.h
|
||||
)
|
||||
|
||||
set(systemz_files
|
||||
s390intrin.h
|
||||
vecintrin.h
|
||||
@@ -319,6 +323,7 @@ set(files
|
||||
${ppc_files}
|
||||
${ppc_htm_files}
|
||||
${riscv_files}
|
||||
${spirv_files}
|
||||
${systemz_files}
|
||||
${ve_files}
|
||||
${x86_files}
|
||||
@@ -529,6 +534,7 @@ add_dependencies("clang-resource-headers"
|
||||
"ppc-resource-headers"
|
||||
"ppc-htm-resource-headers"
|
||||
"riscv-resource-headers"
|
||||
"spirv-resource-headers"
|
||||
"systemz-resource-headers"
|
||||
"ve-resource-headers"
|
||||
"webassembly-resource-headers"
|
||||
@@ -562,6 +568,7 @@ add_header_target("gpu-resource-headers" "${gpu_files}")
|
||||
|
||||
# Other header groupings
|
||||
add_header_target("hlsl-resource-headers" ${hlsl_files})
|
||||
add_header_target("spirv-resource-headers" ${spirv_files})
|
||||
add_header_target("opencl-resource-headers" ${opencl_files})
|
||||
add_header_target("llvm-libc-resource-headers" ${llvm_libc_wrapper_files})
|
||||
add_header_target("openmp-resource-headers" ${openmp_wrapper_files})
|
||||
@@ -767,6 +774,12 @@ install(
|
||||
${EXCLUDE_HLSL}
|
||||
COMPONENT hlsl-resource-headers)
|
||||
|
||||
install(
|
||||
FILES ${spirv_files}
|
||||
DESTINATION ${header_install_dir}
|
||||
EXCLUDE_FROM_ALL
|
||||
COMPONENT spirv-resource-headers)
|
||||
|
||||
install(
|
||||
FILES ${opencl_files}
|
||||
DESTINATION ${header_install_dir}
|
||||
@@ -836,6 +849,9 @@ if (NOT LLVM_ENABLE_IDE)
|
||||
add_llvm_install_targets(install-riscv-resource-headers
|
||||
DEPENDS riscv-resource-headers
|
||||
COMPONENT riscv-resource-headers)
|
||||
add_llvm_install_targets(install-spirv-resource-headers
|
||||
DEPENDS spirv-resource-headers
|
||||
COMPONENT spirv-resource-headers)
|
||||
add_llvm_install_targets(install-systemz-resource-headers
|
||||
DEPENDS systemz-resource-headers
|
||||
COMPONENT systemz-resource-headers)
|
||||
|
||||
179
clang/lib/Headers/__clang_spirv_builtins.h
Normal file
179
clang/lib/Headers/__clang_spirv_builtins.h
Normal file
@@ -0,0 +1,179 @@
|
||||
/*===---- spirv_builtin_vars.h - SPIR-V built-in ---------------------------===
|
||||
*
|
||||
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
* See https://llvm.org/LICENSE.txt for license information.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*
|
||||
*===-----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#ifndef __SPIRV_BUILTIN_VARS_H
|
||||
#define __SPIRV_BUILTIN_VARS_H
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#define __SPIRV_NOEXCEPT noexcept
|
||||
#else
|
||||
#define __SPIRV_NOEXCEPT
|
||||
#endif
|
||||
|
||||
#define __SPIRV_overloadable __attribute__((overloadable))
|
||||
#define __SPIRV_convergent __attribute__((convergent))
|
||||
#define __SPIRV_inline __attribute__((always_inline))
|
||||
|
||||
#define __global __attribute__((opencl_global))
|
||||
#define __local __attribute__((opencl_local))
|
||||
#define __private __attribute__((opencl_private))
|
||||
#define __constant __attribute__((opencl_constant))
|
||||
#ifdef __SYCL_DEVICE_ONLY__
|
||||
#define __generic
|
||||
#else
|
||||
#define __generic __attribute__((opencl_generic))
|
||||
#endif
|
||||
|
||||
// Check if SPIR-V builtins are supported.
|
||||
// As the translator doesn't use the LLVM intrinsics (which would be emitted if
|
||||
// we use the SPIR-V builtins) we can't rely on the SPIRV32/SPIRV64 etc macros
|
||||
// to establish if we can use the builtin alias. We disable builtin altogether
|
||||
// if we do not intent to use the backend. So instead of use target macros, rely
|
||||
// on a __has_builtin test.
|
||||
#if (__has_builtin(__builtin_spirv_generic_cast_to_ptr_explicit))
|
||||
#define __SPIRV_BUILTIN_ALIAS(builtin) \
|
||||
__attribute__((clang_builtin_alias(builtin)))
|
||||
#else
|
||||
#define __SPIRV_BUILTIN_ALIAS(builtin)
|
||||
#endif
|
||||
|
||||
// OpGenericCastToPtrExplicit
|
||||
|
||||
extern __SPIRV_overloadable
|
||||
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
|
||||
__global void *__spirv_GenericCastToPtrExplicit_ToGlobal(__generic void *,
|
||||
int) __SPIRV_NOEXCEPT;
|
||||
extern __SPIRV_overloadable
|
||||
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
|
||||
__global const void *
|
||||
__spirv_GenericCastToPtrExplicit_ToGlobal(__generic const void *,
|
||||
int) __SPIRV_NOEXCEPT;
|
||||
extern __SPIRV_overloadable
|
||||
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
|
||||
__global volatile void *
|
||||
__spirv_GenericCastToPtrExplicit_ToGlobal(__generic volatile void *,
|
||||
int) __SPIRV_NOEXCEPT;
|
||||
extern __SPIRV_overloadable
|
||||
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
|
||||
__global const volatile void *
|
||||
__spirv_GenericCastToPtrExplicit_ToGlobal(__generic const volatile void *,
|
||||
int) __SPIRV_NOEXCEPT;
|
||||
extern __SPIRV_overloadable
|
||||
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
|
||||
__local void *__spirv_GenericCastToPtrExplicit_ToLocal(__generic void *,
|
||||
int) __SPIRV_NOEXCEPT;
|
||||
extern __SPIRV_overloadable
|
||||
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
|
||||
__local const void *
|
||||
__spirv_GenericCastToPtrExplicit_ToLocal(__generic const void *,
|
||||
int) __SPIRV_NOEXCEPT;
|
||||
extern __SPIRV_overloadable
|
||||
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
|
||||
__local volatile void *
|
||||
__spirv_GenericCastToPtrExplicit_ToLocal(__generic volatile void *,
|
||||
int) __SPIRV_NOEXCEPT;
|
||||
extern __SPIRV_overloadable
|
||||
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
|
||||
__local const volatile void *
|
||||
__spirv_GenericCastToPtrExplicit_ToLocal(__generic const volatile void *,
|
||||
int) __SPIRV_NOEXCEPT;
|
||||
extern __SPIRV_overloadable
|
||||
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
|
||||
__private void *
|
||||
__spirv_GenericCastToPtrExplicit_ToPrivate(__generic void *,
|
||||
int) __SPIRV_NOEXCEPT;
|
||||
extern __SPIRV_overloadable
|
||||
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
|
||||
__private const void *
|
||||
__spirv_GenericCastToPtrExplicit_ToPrivate(__generic const void *,
|
||||
int) __SPIRV_NOEXCEPT;
|
||||
extern __SPIRV_overloadable
|
||||
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
|
||||
__private volatile void *
|
||||
__spirv_GenericCastToPtrExplicit_ToPrivate(__generic volatile void *,
|
||||
int) __SPIRV_NOEXCEPT;
|
||||
extern __SPIRV_overloadable
|
||||
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
|
||||
__private const volatile void *
|
||||
__spirv_GenericCastToPtrExplicit_ToPrivate(__generic const volatile void *,
|
||||
int) __SPIRV_NOEXCEPT;
|
||||
|
||||
// OpGenericCastToPtr
|
||||
|
||||
static __SPIRV_overloadable __SPIRV_inline __global void *
|
||||
__spirv_GenericCastToPtr_ToGlobal(__generic void *p, int) __SPIRV_NOEXCEPT {
|
||||
return (__global void *)p;
|
||||
}
|
||||
static __SPIRV_overloadable __SPIRV_inline __global const void *
|
||||
__spirv_GenericCastToPtr_ToGlobal(__generic const void *p,
|
||||
int) __SPIRV_NOEXCEPT {
|
||||
return (__global const void *)p;
|
||||
}
|
||||
static __SPIRV_overloadable __SPIRV_inline __global volatile void *
|
||||
__spirv_GenericCastToPtr_ToGlobal(__generic volatile void *p,
|
||||
int) __SPIRV_NOEXCEPT {
|
||||
return (__global volatile void *)p;
|
||||
}
|
||||
static __SPIRV_overloadable __SPIRV_inline __global const volatile void *
|
||||
__spirv_GenericCastToPtr_ToGlobal(__generic const volatile void *p,
|
||||
int) __SPIRV_NOEXCEPT {
|
||||
return (__global const volatile void *)p;
|
||||
}
|
||||
static __SPIRV_overloadable __SPIRV_inline __local void *
|
||||
__spirv_GenericCastToPtr_ToLocal(__generic void *p, int) __SPIRV_NOEXCEPT {
|
||||
return (__local void *)p;
|
||||
}
|
||||
static __SPIRV_overloadable __SPIRV_inline __local const void *
|
||||
__spirv_GenericCastToPtr_ToLocal(__generic const void *p,
|
||||
int) __SPIRV_NOEXCEPT {
|
||||
return (__local const void *)p;
|
||||
}
|
||||
static __SPIRV_overloadable __SPIRV_inline __local volatile void *
|
||||
__spirv_GenericCastToPtr_ToLocal(__generic volatile void *p,
|
||||
int) __SPIRV_NOEXCEPT {
|
||||
return (__local volatile void *)p;
|
||||
}
|
||||
static __SPIRV_overloadable __SPIRV_inline __local const volatile void *
|
||||
__spirv_GenericCastToPtr_ToLocal(__generic const volatile void *p,
|
||||
int) __SPIRV_NOEXCEPT {
|
||||
return (__local const volatile void *)p;
|
||||
}
|
||||
static __SPIRV_overloadable __SPIRV_inline __private void *
|
||||
__spirv_GenericCastToPtr_ToPrivate(__generic void *p, int) __SPIRV_NOEXCEPT {
|
||||
return (__private void *)p;
|
||||
}
|
||||
static __SPIRV_overloadable __SPIRV_inline __private const void *
|
||||
__spirv_GenericCastToPtr_ToPrivate(__generic const void *p,
|
||||
int) __SPIRV_NOEXCEPT {
|
||||
return (__private const void *)p;
|
||||
}
|
||||
static __SPIRV_overloadable __SPIRV_inline __private volatile void *
|
||||
__spirv_GenericCastToPtr_ToPrivate(__generic volatile void *p,
|
||||
int) __SPIRV_NOEXCEPT {
|
||||
return (__private volatile void *)p;
|
||||
}
|
||||
static __SPIRV_overloadable __SPIRV_inline __private const volatile void *
|
||||
__spirv_GenericCastToPtr_ToPrivate(__generic const volatile void *p,
|
||||
int) __SPIRV_NOEXCEPT {
|
||||
return (__private const volatile void *)p;
|
||||
}
|
||||
|
||||
#undef __SPIRV_overloadable
|
||||
#undef __SPIRV_convergent
|
||||
#undef __SPIRV_inline
|
||||
|
||||
#undef __global
|
||||
#undef __local
|
||||
#undef __constant
|
||||
#undef __generic
|
||||
|
||||
#undef __SPIRV_BUILTIN_ALIAS
|
||||
#undef __SPIRV_NOEXCEPT
|
||||
|
||||
#endif /* __SPIRV_BUILTIN_VARS_H */
|
||||
@@ -2033,7 +2033,11 @@ bool Sema::CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
|
||||
case llvm::Triple::mips64el:
|
||||
return MIPS().CheckMipsBuiltinFunctionCall(TI, BuiltinID, TheCall);
|
||||
case llvm::Triple::spirv:
|
||||
return SPIRV().CheckSPIRVBuiltinFunctionCall(BuiltinID, TheCall);
|
||||
case llvm::Triple::spirv32:
|
||||
case llvm::Triple::spirv64:
|
||||
if (TI.getTriple().getOS() != llvm::Triple::OSType::AMDHSA)
|
||||
return SPIRV().CheckSPIRVBuiltinFunctionCall(TI, BuiltinID, TheCall);
|
||||
return false;
|
||||
case llvm::Triple::systemz:
|
||||
return SystemZ().CheckSystemZBuiltinFunctionCall(BuiltinID, TheCall);
|
||||
case llvm::Triple::x86:
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#include "clang/Sema/SemaOpenCL.h"
|
||||
#include "clang/Sema/SemaOpenMP.h"
|
||||
#include "clang/Sema/SemaRISCV.h"
|
||||
#include "clang/Sema/SemaSPIRV.h"
|
||||
#include "clang/Sema/SemaSYCL.h"
|
||||
#include "clang/Sema/SemaSwift.h"
|
||||
#include "clang/Sema/SemaWasm.h"
|
||||
@@ -5863,12 +5864,13 @@ static void handleBuiltinAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
|
||||
bool IsAArch64 = S.Context.getTargetInfo().getTriple().isAArch64();
|
||||
bool IsARM = S.Context.getTargetInfo().getTriple().isARM();
|
||||
bool IsRISCV = S.Context.getTargetInfo().getTriple().isRISCV();
|
||||
bool IsSPIRV = S.Context.getTargetInfo().getTriple().isSPIRV();
|
||||
bool IsHLSL = S.Context.getLangOpts().HLSL;
|
||||
if ((IsAArch64 && !S.ARM().SveAliasValid(BuiltinID, AliasName)) ||
|
||||
(IsARM && !S.ARM().MveAliasValid(BuiltinID, AliasName) &&
|
||||
!S.ARM().CdeAliasValid(BuiltinID, AliasName)) ||
|
||||
(IsRISCV && !S.RISCV().isAliasValid(BuiltinID, AliasName)) ||
|
||||
(!IsAArch64 && !IsARM && !IsRISCV && !IsHLSL)) {
|
||||
(!IsAArch64 && !IsARM && !IsRISCV && !IsHLSL && !IsSPIRV)) {
|
||||
S.Diag(AL.getLoc(), diag::err_attribute_builtin_alias) << AL;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -10,8 +10,21 @@
|
||||
|
||||
#include "clang/Sema/SemaSPIRV.h"
|
||||
#include "clang/Basic/TargetBuiltins.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/Sema/Sema.h"
|
||||
|
||||
// SPIR-V enumerants. Enums have only the required entries, see SPIR-V specs for
|
||||
// values.
|
||||
// FIXME: either use the SPIRV-Headers or generate a custom header using the
|
||||
// grammar (like done with MLIR).
|
||||
namespace spirv {
|
||||
enum class StorageClass : int {
|
||||
Workgroup = 4,
|
||||
CrossWorkgroup = 5,
|
||||
Function = 7
|
||||
};
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
|
||||
SemaSPIRV::SemaSPIRV(Sema &S) : SemaBase(S) {}
|
||||
@@ -33,8 +46,114 @@ static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(unsigned BuiltinID,
|
||||
static std::optional<int>
|
||||
processConstant32BitIntArgument(Sema &SemaRef, CallExpr *Call, int Argument) {
|
||||
ExprResult Arg =
|
||||
SemaRef.DefaultFunctionArrayLvalueConversion(Call->getArg(Argument));
|
||||
if (Arg.isInvalid())
|
||||
return true;
|
||||
Call->setArg(Argument, Arg.get());
|
||||
|
||||
const Expr *IntArg = Arg.get();
|
||||
SmallVector<PartialDiagnosticAt, 8> Notes;
|
||||
Expr::EvalResult Eval;
|
||||
Eval.Diag = &Notes;
|
||||
if ((!IntArg->EvaluateAsConstantExpr(Eval, SemaRef.getASTContext())) ||
|
||||
!Eval.Val.isInt() || Eval.Val.getInt().getBitWidth() > 32) {
|
||||
SemaRef.Diag(IntArg->getBeginLoc(), diag::err_spirv_enum_not_int)
|
||||
<< 0 << IntArg->getSourceRange();
|
||||
for (const PartialDiagnosticAt &PDiag : Notes)
|
||||
SemaRef.Diag(PDiag.first, PDiag.second);
|
||||
return true;
|
||||
}
|
||||
return {Eval.Val.getInt().getZExtValue()};
|
||||
}
|
||||
|
||||
static bool checkGenericCastToPtr(Sema &SemaRef, CallExpr *Call) {
|
||||
if (SemaRef.checkArgCount(Call, 2))
|
||||
return true;
|
||||
|
||||
{
|
||||
ExprResult Arg =
|
||||
SemaRef.DefaultFunctionArrayLvalueConversion(Call->getArg(0));
|
||||
if (Arg.isInvalid())
|
||||
return true;
|
||||
Call->setArg(0, Arg.get());
|
||||
|
||||
QualType Ty = Arg.get()->getType();
|
||||
const auto *PtrTy = Ty->getAs<PointerType>();
|
||||
auto AddressSpaceNotInGeneric = [&](LangAS AS) {
|
||||
if (SemaRef.LangOpts.OpenCL)
|
||||
return AS != LangAS::opencl_generic;
|
||||
return AS != LangAS::Default;
|
||||
};
|
||||
if (!PtrTy ||
|
||||
AddressSpaceNotInGeneric(PtrTy->getPointeeType().getAddressSpace())) {
|
||||
SemaRef.Diag(Arg.get()->getBeginLoc(),
|
||||
diag::err_spirv_builtin_generic_cast_invalid_arg)
|
||||
<< Call->getSourceRange();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
spirv::StorageClass StorageClass;
|
||||
if (std::optional<int> SCInt =
|
||||
processConstant32BitIntArgument(SemaRef, Call, 1);
|
||||
SCInt.has_value()) {
|
||||
StorageClass = static_cast<spirv::StorageClass>(SCInt.value());
|
||||
if (StorageClass != spirv::StorageClass::CrossWorkgroup &&
|
||||
StorageClass != spirv::StorageClass::Workgroup &&
|
||||
StorageClass != spirv::StorageClass::Function) {
|
||||
SemaRef.Diag(Call->getArg(1)->getBeginLoc(),
|
||||
diag::err_spirv_enum_not_valid)
|
||||
<< 0 << Call->getArg(1)->getSourceRange();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
auto RT = Call->getArg(0)->getType();
|
||||
RT = RT->getPointeeType();
|
||||
auto Qual = RT.getQualifiers();
|
||||
LangAS AddrSpace;
|
||||
switch (static_cast<spirv::StorageClass>(StorageClass)) {
|
||||
case spirv::StorageClass::CrossWorkgroup:
|
||||
AddrSpace =
|
||||
SemaRef.LangOpts.isSYCL() ? LangAS::sycl_global : LangAS::opencl_global;
|
||||
break;
|
||||
case spirv::StorageClass::Workgroup:
|
||||
AddrSpace =
|
||||
SemaRef.LangOpts.isSYCL() ? LangAS::sycl_local : LangAS::opencl_local;
|
||||
break;
|
||||
case spirv::StorageClass::Function:
|
||||
AddrSpace = SemaRef.LangOpts.isSYCL() ? LangAS::sycl_private
|
||||
: LangAS::opencl_private;
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Invalid builtin function");
|
||||
}
|
||||
Qual.setAddressSpace(AddrSpace);
|
||||
Call->setType(SemaRef.getASTContext().getPointerType(
|
||||
SemaRef.getASTContext().getQualifiedType(RT.getUnqualifiedType(), Qual)));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(const TargetInfo &TI,
|
||||
unsigned BuiltinID,
|
||||
CallExpr *TheCall) {
|
||||
if (BuiltinID >= SPIRV::FirstVKBuiltin && BuiltinID <= SPIRV::LastVKBuiltin &&
|
||||
TI.getTriple().getArch() != llvm::Triple::spirv) {
|
||||
SemaRef.Diag(TheCall->getBeginLoc(), diag::err_spirv_invalid_target) << 0;
|
||||
return true;
|
||||
}
|
||||
if (BuiltinID >= SPIRV::FirstCLBuiltin && BuiltinID <= SPIRV::LastTSBuiltin &&
|
||||
TI.getTriple().getArch() != llvm::Triple::spirv32 &&
|
||||
TI.getTriple().getArch() != llvm::Triple::spirv64) {
|
||||
SemaRef.Diag(TheCall->getBeginLoc(), diag::err_spirv_invalid_target) << 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (BuiltinID) {
|
||||
case SPIRV::BI__builtin_spirv_distance: {
|
||||
if (SemaRef.checkArgCount(TheCall, 2))
|
||||
@@ -160,6 +279,9 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(unsigned BuiltinID,
|
||||
TheCall->setType(RetTy);
|
||||
break;
|
||||
}
|
||||
case SPIRV::BI__builtin_spirv_generic_cast_to_ptr_explicit: {
|
||||
return checkGenericCastToPtr(SemaRef, TheCall);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// RUN: %clang_cc1 -O1 -triple spirv64 -fsycl-is-device %s -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -O1 -triple spirv64 -cl-std=CL3.0 -x cl %s -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -O1 -triple spirv32 -cl-std=CL3.0 -x cl %s -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// CHECK: spir_func noundef ptr @test_cast_to_private(
|
||||
// CHECK-SAME: ptr addrspace(4) noundef readnone [[P:%.*]]
|
||||
// CHECK-NEXT: [[ENTRY:.*:]]
|
||||
// CHECK-NEXT: [[SPV_CAST:%.*]] = tail call noundef ptr @llvm.spv.generic.cast.to.ptr.explicit.p0(ptr addrspace(4) %p)
|
||||
// CHECK-NEXT: ret ptr [[SPV_CAST]]
|
||||
//
|
||||
__attribute__((opencl_private)) int* test_cast_to_private(int* p) {
|
||||
return __builtin_spirv_generic_cast_to_ptr_explicit(p, 7);
|
||||
}
|
||||
|
||||
// CHECK: spir_func noundef ptr addrspace(1) @test_cast_to_global(
|
||||
// CHECK-SAME: ptr addrspace(4) noundef readnone [[P:%.*]]
|
||||
// CHECK-NEXT: [[ENTRY:.*:]]
|
||||
// CHECK-NEXT: [[SPV_CAST:%.*]] = tail call noundef ptr addrspace(1) @llvm.spv.generic.cast.to.ptr.explicit.p1(ptr addrspace(4) %p)
|
||||
// CHECK-NEXT: ret ptr addrspace(1) [[SPV_CAST]]
|
||||
//
|
||||
__attribute__((opencl_global)) int* test_cast_to_global(int* p) {
|
||||
return __builtin_spirv_generic_cast_to_ptr_explicit(p, 5);
|
||||
}
|
||||
|
||||
// CHECK: spir_func noundef ptr addrspace(3) @test_cast_to_local(
|
||||
// CHECK-SAME: ptr addrspace(4) noundef readnone [[P:%.*]]
|
||||
// CHECK-NEXT: [[ENTRY:.*:]]
|
||||
// CHECK-NEXT: [[SPV_CAST:%.*]] = tail call noundef ptr addrspace(3) @llvm.spv.generic.cast.to.ptr.explicit.p3(ptr addrspace(4) %p)
|
||||
// CHECK-NEXT: ret ptr addrspace(3) [[SPV_CAST]]
|
||||
//
|
||||
__attribute__((opencl_local)) int* test_cast_to_local(int* p) {
|
||||
return __builtin_spirv_generic_cast_to_ptr_explicit(p, 4);
|
||||
}
|
||||
25
clang/test/Headers/spirv_functions.cpp
Normal file
25
clang/test/Headers/spirv_functions.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
// RUN: %clang_cc1 -Wno-unused-value -O0 -internal-isystem %S/../../lib/Headers -include __clang_spirv_builtins.h -triple spirv64 -emit-llvm %s -fsycl-is-device -o - | FileCheck %s -check-prefixes=SPV
|
||||
// RUN: %clang_cc1 -Wno-unused-value -O0 -internal-isystem %S/../../lib/Headers -include __clang_spirv_builtins.h -triple nvptx64 -emit-llvm %s -fsycl-is-device -o - | FileCheck %s -check-prefixes=NV
|
||||
|
||||
|
||||
// SPV: void @_Z9test_castPi
|
||||
// SPV: call noundef ptr addrspace(1) @llvm.spv.generic.cast.to.ptr.explicit.p1
|
||||
// SPV: call noundef ptr addrspace(3) @llvm.spv.generic.cast.to.ptr.explicit.p3
|
||||
// SPV: call noundef ptr @llvm.spv.generic.cast.to.ptr.explicit.p0
|
||||
// SPV: addrspacecast ptr addrspace(4) %{{.*}} to ptr addrspace(1)
|
||||
// SPV: addrspacecast ptr addrspace(4) %{{.*}} to ptr addrspace(3)
|
||||
// SPV: addrspacecast ptr addrspace(4) %{{.*}} to ptr
|
||||
// NV: void @_Z9test_castPi
|
||||
// NV: call noundef ptr addrspace(1) @_Z41__spirv_GenericCastToPtrExplicit_ToGlobalPvi
|
||||
// NV: call noundef ptr addrspace(3) @_Z40__spirv_GenericCastToPtrExplicit_ToLocalPvi
|
||||
// NV: call noundef ptr @_Z42__spirv_GenericCastToPtrExplicit_ToPrivatePvi
|
||||
// NV: addrspacecast ptr %{{.*}} to ptr addrspace(1)
|
||||
// NV: addrspacecast ptr %{{.*}} to ptr addrspace(3)
|
||||
void test_cast(int* p) {
|
||||
__spirv_GenericCastToPtrExplicit_ToGlobal(p, 5);
|
||||
__spirv_GenericCastToPtrExplicit_ToLocal(p, 4);
|
||||
__spirv_GenericCastToPtrExplicit_ToPrivate(p, 7);
|
||||
__spirv_GenericCastToPtr_ToGlobal(p, 5);
|
||||
__spirv_GenericCastToPtr_ToLocal(p, 4);
|
||||
__spirv_GenericCastToPtr_ToPrivate(p, 7);
|
||||
}
|
||||
25
clang/test/SemaSPIRV/BuiltIns/generic_cast_to_ptr_explicit.c
Normal file
25
clang/test/SemaSPIRV/BuiltIns/generic_cast_to_ptr_explicit.c
Normal file
@@ -0,0 +1,25 @@
|
||||
// RUN: %clang_cc1 -O1 -triple spirv64 -fsycl-is-device -verify %s -o -
|
||||
// RUN: %clang_cc1 -O1 -triple spirv64 -verify %s -cl-std=CL3.0 -x cl -o -
|
||||
// RUN: %clang_cc1 -O1 -triple spirv32 -verify %s -cl-std=CL3.0 -x cl -o -
|
||||
|
||||
void test_missing_arguments(int* p) {
|
||||
__builtin_spirv_generic_cast_to_ptr_explicit(p);
|
||||
// expected-error@-1 {{too few arguments to function call, expected 2, have 1}}
|
||||
__builtin_spirv_generic_cast_to_ptr_explicit(p, 7, p);
|
||||
// expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
|
||||
}
|
||||
|
||||
void test_wrong_flag_value(int* p) {
|
||||
__builtin_spirv_generic_cast_to_ptr_explicit(p, 14);
|
||||
// expected-error@-1 {{invalid value for storage class argument}}
|
||||
}
|
||||
|
||||
void test_wrong_address_space(__attribute__((opencl_local)) int* p) {
|
||||
__builtin_spirv_generic_cast_to_ptr_explicit(p, 14);
|
||||
// expected-error@-1 {{expecting a pointer argument to the generic address space}}
|
||||
}
|
||||
|
||||
void test_not_a_pointer(int p) {
|
||||
__builtin_spirv_generic_cast_to_ptr_explicit(p, 14);
|
||||
// expected-error@-1 {{expecting a pointer argument to the generic address space}}
|
||||
}
|
||||
15
clang/test/SemaSPIRV/BuiltIns/invalid_target_cl.c
Normal file
15
clang/test/SemaSPIRV/BuiltIns/invalid_target_cl.c
Normal file
@@ -0,0 +1,15 @@
|
||||
// RUN: %clang_cc1 -triple spirv-pc-vulkan-compute -Wno-unused-value -verify=invalid %s -o -
|
||||
// RUN: %clang_cc1 -triple spirv32 -verify=valid -Wno-unused-value %s -cl-std=CL3.0 -x cl -o -
|
||||
// RUN: %clang_cc1 -triple spirv64 -verify=valid -Wno-unused-value %s -cl-std=CL3.0 -x cl -o -
|
||||
|
||||
typedef float float2 __attribute__((ext_vector_type(2)));
|
||||
|
||||
// valid-no-diagnostics
|
||||
|
||||
void invalid_builtin_for_target(int* p) {
|
||||
__builtin_spirv_generic_cast_to_ptr_explicit(p, 7);
|
||||
// invalid-error@-1 {{builtin requires spirv32 or spirv64 target}}
|
||||
}
|
||||
|
||||
// no error
|
||||
float valid_builtin(float2 X) { return __builtin_spirv_length(X); }
|
||||
15
clang/test/SemaSPIRV/BuiltIns/invalid_target_vk.c
Normal file
15
clang/test/SemaSPIRV/BuiltIns/invalid_target_vk.c
Normal file
@@ -0,0 +1,15 @@
|
||||
// RUN: %clang_cc1 -triple spirv-pc-vulkan-compute -Wno-unused-value -verify=valid %s -o -
|
||||
// RUN: %clang_cc1 -triple spirv32 -verify=invalid -Wno-unused-value %s -cl-std=CL3.0 -x cl -o -
|
||||
// RUN: %clang_cc1 -triple spirv64 -verify=invalid -Wno-unused-value %s -cl-std=CL3.0 -x cl -o -
|
||||
|
||||
typedef float float2 __attribute__((ext_vector_type(2)));
|
||||
|
||||
// valid-no-diagnostics
|
||||
|
||||
void call(float2 X, float2 Y) {
|
||||
__builtin_spirv_reflect(X, Y);
|
||||
// invalid-error@-1 {{builtin requires spirv target}}
|
||||
}
|
||||
|
||||
// no error
|
||||
float valid_builtin(float2 X) { return __builtin_spirv_length(X); }
|
||||
Reference in New Issue
Block a user