Skip to content

Commit 90725e8

Browse files
committed
[clang][SPIRV] Add builtin for OpGenericCastToPtrExplicit and its SPIR-V friendly binding
The patch introduce __builtin_spirv_generic_cast_to_ptr_explicit which is lowered to the llvm.spv.generic.cast.to.ptr.explicit intrinsic. 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.
1 parent 082598a commit 90725e8

File tree

15 files changed

+438
-12
lines changed

15 files changed

+438
-12
lines changed

clang/include/clang/Basic/BuiltinsSPIRV.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88

99
include "clang/Basic/BuiltinsBase.td"
1010

11+
class SPIRVBuiltin<string prototype, list<Attribute> Attr> : Builtin {
12+
let Spellings = ["__builtin_spirv_"#NAME];
13+
let Prototype = prototype;
14+
let Attributes = !listconcat([NoThrow], Attr);
15+
}
16+
1117
def SPIRVDistance : Builtin {
1218
let Spellings = ["__builtin_spirv_distance"];
1319
let Attributes = [NoThrow, Const];
@@ -37,3 +43,6 @@ def SPIRVFaceForward : Builtin {
3743
let Attributes = [NoThrow, Const, CustomTypeChecking];
3844
let Prototype = "void(...)";
3945
}
46+
47+
def generic_cast_to_ptr_explicit
48+
: SPIRVBuiltin<"void*(void*, int)", [NoThrow, Const, CustomTypeChecking]>;

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4609,7 +4609,7 @@ def err_attribute_preferred_name_arg_invalid : Error<
46094609
"argument %0 to 'preferred_name' attribute is not a typedef for "
46104610
"a specialization of %1">;
46114611
def err_attribute_builtin_alias : Error<
4612-
"%0 attribute can only be applied to a ARM, HLSL or RISC-V builtin">;
4612+
"%0 attribute can only be applied to a ARM, HLSL, SPIR-V or RISC-V builtin">;
46134613

46144614
// called-once attribute diagnostics.
46154615
def err_called_once_attribute_wrong_type : Error<
@@ -12740,6 +12740,14 @@ def err_bit_int_bad_size : Error<"%select{signed|unsigned}0 _BitInt must "
1274012740
def err_bit_int_max_size : Error<"%select{signed|unsigned}0 _BitInt of bit "
1274112741
"sizes greater than %1 not supported">;
1274212742

12743+
// SPIR-V builtins diagnostics
12744+
def err_spirv_builtin_generic_cast_invalid_arg : Error<
12745+
"expecting a pointer argument to the generic address space">;
12746+
def err_spirv_enum_not_int : Error<
12747+
"%0{storage class} argument for SPIR-V builtin is not a 32-bits integer">;
12748+
def err_spirv_enum_not_valid : Error<
12749+
"invalid value for %select{storage class}0 argument">;
12750+
1274312751
// errors of expect.with.probability
1274412752
def err_probability_not_constant_float : Error<
1274512753
"probability argument to __builtin_expect_with_probability must be constant "

clang/lib/AST/ASTContext.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10054,6 +10054,11 @@ bool ASTContext::canBuiltinBeRedeclared(const FunctionDecl *FD) const {
1005410054
if (LangOpts.HLSL && FD->getBuiltinID() != Builtin::NotBuiltin &&
1005510055
BuiltinInfo.hasCustomTypechecking(FD->getBuiltinID()))
1005610056
return true;
10057+
// Allow redecl custom type checking builtin for SPIR-V.
10058+
if (getTargetInfo().getTriple().isSPIROrSPIRV() &&
10059+
BuiltinInfo.isTSBuiltin(FD->getBuiltinID()) &&
10060+
BuiltinInfo.hasCustomTypechecking(FD->getBuiltinID()))
10061+
return true;
1005710062
return BuiltinInfo.canBeRedeclared(FD->getBuiltinID());
1005810063
}
1005910064

clang/lib/Basic/Targets/SPIR.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ static constexpr Builtin::Info BuiltinInfos[] = {
3535
static_assert(std::size(BuiltinInfos) == NumBuiltins);
3636

3737
llvm::SmallVector<Builtin::InfosShard>
38-
SPIRVTargetInfo::getTargetBuiltins() const {
39-
return {{&BuiltinStrings, BuiltinInfos}};
38+
BaseSPIRTargetInfo::getTargetBuiltins() const {
39+
if (getTriple().isSPIRV())
40+
return {{&BuiltinStrings, BuiltinInfos}};
41+
return {};
4042
}
4143

4244
void SPIRTargetInfo::getTargetDefines(const LangOptions &Opts,

clang/lib/Basic/Targets/SPIR.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,7 @@ class LLVM_LIBRARY_VISIBILITY BaseSPIRTargetInfo : public TargetInfo {
164164
// memcpy as per section 3 of the SPIR spec.
165165
bool useFP16ConversionIntrinsics() const override { return false; }
166166

167-
llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override {
168-
return {};
169-
}
167+
llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
170168

171169
std::string_view getClobbers() const override { return ""; }
172170

@@ -321,8 +319,6 @@ class LLVM_LIBRARY_VISIBILITY SPIRVTargetInfo : public BaseSPIRVTargetInfo {
321319
"v256:256-v512:512-v1024:1024-n8:16:32:64-G10");
322320
}
323321

324-
llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
325-
326322
void getTargetDefines(const LangOptions &Opts,
327323
MacroBuilder &Builder) const override;
328324
};

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,10 @@ static Value *EmitTargetArchBuiltinExpr(CodeGenFunction *CGF,
9797
case llvm::Triple::riscv64:
9898
return CGF->EmitRISCVBuiltinExpr(BuiltinID, E, ReturnValue);
9999
case llvm::Triple::spirv:
100-
return CGF->EmitSPIRVBuiltinExpr(BuiltinID, E);
100+
case llvm::Triple::spirv32:
101101
case llvm::Triple::spirv64:
102102
if (CGF->getTarget().getTriple().getOS() != llvm::Triple::OSType::AMDHSA)
103-
return nullptr;
103+
return CGF->EmitSPIRVBuiltinExpr(BuiltinID, E);
104104
return CGF->EmitAMDGPUBuiltinExpr(BuiltinID, E);
105105
default:
106106
return nullptr;

clang/lib/CodeGen/TargetBuiltins/SPIR.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,20 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID,
8383
/*ReturnType=*/N->getType(), Intrinsic::spv_faceforward,
8484
ArrayRef<Value *>{N, I, Ng}, /*FMFSource=*/nullptr, "spv.faceforward");
8585
}
86+
case SPIRV::BI__builtin_spirv_generic_cast_to_ptr_explicit: {
87+
Value *Ptr = EmitScalarExpr(E->getArg(0));
88+
assert(E->getArg(0)->getType()->hasPointerRepresentation() &&
89+
E->getArg(1)->getType()->hasIntegerRepresentation() &&
90+
"GenericCastToPtrExplicit takes a pointer and an int");
91+
llvm::Type *Res = getTypes().ConvertType(E->getType());
92+
assert(Res->isPointerTy() &&
93+
"GenericCastToPtrExplicit doesn't return a pointer");
94+
llvm::CallInst *Call = Builder.CreateIntrinsic(
95+
/*ReturnType=*/Res, Intrinsic::spv_generic_cast_to_ptr_explicit,
96+
ArrayRef<Value *>{Ptr}, nullptr, "spv.generic_cast");
97+
Call->addRetAttr(llvm::Attribute::AttrKind::NoUndef);
98+
return Call;
99+
}
86100
}
87101
return nullptr;
88102
}

clang/lib/Headers/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ set(riscv_files
129129
sifive_vector.h
130130
)
131131

132+
set(spirv_files
133+
__clang_spirv_builtins.h
134+
)
135+
132136
set(systemz_files
133137
s390intrin.h
134138
vecintrin.h
@@ -316,6 +320,7 @@ set(files
316320
${ppc_files}
317321
${ppc_htm_files}
318322
${riscv_files}
323+
${spirv_files}
319324
${systemz_files}
320325
${ve_files}
321326
${x86_files}
@@ -526,6 +531,7 @@ add_dependencies("clang-resource-headers"
526531
"ppc-resource-headers"
527532
"ppc-htm-resource-headers"
528533
"riscv-resource-headers"
534+
"spirv-resource-headers"
529535
"systemz-resource-headers"
530536
"ve-resource-headers"
531537
"webassembly-resource-headers"
@@ -559,6 +565,7 @@ add_header_target("gpu-resource-headers" "${gpu_files}")
559565

560566
# Other header groupings
561567
add_header_target("hlsl-resource-headers" ${hlsl_files})
568+
add_header_target("spirv-resource-headers" ${spirv_files})
562569
add_header_target("opencl-resource-headers" ${opencl_files})
563570
add_header_target("llvm-libc-resource-headers" ${llvm_libc_wrapper_files})
564571
add_header_target("openmp-resource-headers" ${openmp_wrapper_files})
@@ -764,6 +771,12 @@ install(
764771
${EXCLUDE_HLSL}
765772
COMPONENT hlsl-resource-headers)
766773

774+
install(
775+
FILES ${spirv_files}
776+
DESTINATION ${header_install_dir}
777+
EXCLUDE_FROM_ALL
778+
COMPONENT spirv-resource-headers)
779+
767780
install(
768781
FILES ${opencl_files}
769782
DESTINATION ${header_install_dir}
@@ -833,6 +846,9 @@ if (NOT LLVM_ENABLE_IDE)
833846
add_llvm_install_targets(install-riscv-resource-headers
834847
DEPENDS riscv-resource-headers
835848
COMPONENT riscv-resource-headers)
849+
add_llvm_install_targets(install-spirv-resource-headers
850+
DEPENDS spirv-resource-headers
851+
COMPONENT spirv-resource-headers)
836852
add_llvm_install_targets(install-systemz-resource-headers
837853
DEPENDS systemz-resource-headers
838854
COMPONENT systemz-resource-headers)
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
/*===---- spirv_builtin_vars.h - SPIR-V built-in ---------------------------===
2+
*
3+
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
* See https://llvm.org/LICENSE.txt for license information.
5+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
*
7+
*===-----------------------------------------------------------------------===
8+
*/
9+
10+
#ifndef __SPIRV_BUILTIN_VARS_H
11+
#define __SPIRV_BUILTIN_VARS_H
12+
13+
#if __cplusplus >= 201103L
14+
#define __SPIRV_NOEXCEPT noexcept
15+
#else
16+
#define __SPIRV_NOEXCEPT
17+
#endif
18+
19+
#define __SPIRV_overloadable __attribute__((overloadable))
20+
#define __SPIRV_convergent __attribute__((convergent))
21+
#define __SPIRV_inline __attribute__((always_inline))
22+
23+
#define __global __attribute__((opencl_global))
24+
#define __local __attribute__((opencl_local))
25+
#define __private __attribute__((opencl_private))
26+
#define __constant __attribute__((opencl_constant))
27+
#ifdef __SYCL_DEVICE_ONLY__
28+
#define __generic
29+
#else
30+
#define __generic __attribute__((opencl_generic))
31+
#endif
32+
33+
// Check if SPIR-V builtins are supported.
34+
// As the translator doesn't use the LLVM intrinsics (which would be emitted if
35+
// we use the SPIR-V builtins) we can't rely on the SPIRV32/SPIRV64 etc macros
36+
// to establish if we can use the builtin alias. We disable builtin altogether
37+
// if we do not intent to use the backend. So instead of use target macros, rely
38+
// on a __has_builtin test.
39+
#if (__has_builtin(__builtin_spirv_generic_cast_to_ptr_explicit))
40+
#define __SPIRV_BUILTIN_ALIAS(builtin) \
41+
__attribute__((clang_builtin_alias(builtin)))
42+
#else
43+
#define __SPIRV_BUILTIN_ALIAS(builtin)
44+
#endif
45+
46+
// OpGenericCastToPtrExplicit
47+
48+
extern __SPIRV_overloadable
49+
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
50+
__global void *__spirv_GenericCastToPtrExplicit_ToGlobal(__generic void *,
51+
int) __SPIRV_NOEXCEPT;
52+
extern __SPIRV_overloadable
53+
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
54+
__global const void *
55+
__spirv_GenericCastToPtrExplicit_ToGlobal(__generic const void *,
56+
int) __SPIRV_NOEXCEPT;
57+
extern __SPIRV_overloadable
58+
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
59+
__global volatile void *
60+
__spirv_GenericCastToPtrExplicit_ToGlobal(__generic volatile void *,
61+
int) __SPIRV_NOEXCEPT;
62+
extern __SPIRV_overloadable
63+
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
64+
__global const volatile void *
65+
__spirv_GenericCastToPtrExplicit_ToGlobal(__generic const volatile void *,
66+
int) __SPIRV_NOEXCEPT;
67+
extern __SPIRV_overloadable
68+
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
69+
__local void *__spirv_GenericCastToPtrExplicit_ToLocal(__generic void *,
70+
int) __SPIRV_NOEXCEPT;
71+
extern __SPIRV_overloadable
72+
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
73+
__local const void *
74+
__spirv_GenericCastToPtrExplicit_ToLocal(__generic const void *,
75+
int) __SPIRV_NOEXCEPT;
76+
extern __SPIRV_overloadable
77+
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
78+
__local volatile void *
79+
__spirv_GenericCastToPtrExplicit_ToLocal(__generic volatile void *,
80+
int) __SPIRV_NOEXCEPT;
81+
extern __SPIRV_overloadable
82+
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
83+
__local const volatile void *
84+
__spirv_GenericCastToPtrExplicit_ToLocal(__generic const volatile void *,
85+
int) __SPIRV_NOEXCEPT;
86+
extern __SPIRV_overloadable
87+
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
88+
__private void *
89+
__spirv_GenericCastToPtrExplicit_ToPrivate(__generic void *,
90+
int) __SPIRV_NOEXCEPT;
91+
extern __SPIRV_overloadable
92+
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
93+
__private const void *
94+
__spirv_GenericCastToPtrExplicit_ToPrivate(__generic const void *,
95+
int) __SPIRV_NOEXCEPT;
96+
extern __SPIRV_overloadable
97+
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
98+
__private volatile void *
99+
__spirv_GenericCastToPtrExplicit_ToPrivate(__generic volatile void *,
100+
int) __SPIRV_NOEXCEPT;
101+
extern __SPIRV_overloadable
102+
__SPIRV_BUILTIN_ALIAS(__builtin_spirv_generic_cast_to_ptr_explicit)
103+
__private const volatile void *
104+
__spirv_GenericCastToPtrExplicit_ToPrivate(__generic const volatile void *,
105+
int) __SPIRV_NOEXCEPT;
106+
107+
// OpGenericCastToPtr
108+
109+
static __SPIRV_overloadable __SPIRV_inline __global void *
110+
__spirv_GenericCastToPtr_ToGlobal(__generic void *p, int) __SPIRV_NOEXCEPT {
111+
return (__global void *)p;
112+
}
113+
static __SPIRV_overloadable __SPIRV_inline __global const void *
114+
__spirv_GenericCastToPtr_ToGlobal(__generic const void *p,
115+
int) __SPIRV_NOEXCEPT {
116+
return (__global const void *)p;
117+
}
118+
static __SPIRV_overloadable __SPIRV_inline __global volatile void *
119+
__spirv_GenericCastToPtr_ToGlobal(__generic volatile void *p,
120+
int) __SPIRV_NOEXCEPT {
121+
return (__global volatile void *)p;
122+
}
123+
static __SPIRV_overloadable __SPIRV_inline __global const volatile void *
124+
__spirv_GenericCastToPtr_ToGlobal(__generic const volatile void *p,
125+
int) __SPIRV_NOEXCEPT {
126+
return (__global const volatile void *)p;
127+
}
128+
static __SPIRV_overloadable __SPIRV_inline __local void *
129+
__spirv_GenericCastToPtr_ToLocal(__generic void *p, int) __SPIRV_NOEXCEPT {
130+
return (__local void *)p;
131+
}
132+
static __SPIRV_overloadable __SPIRV_inline __local const void *
133+
__spirv_GenericCastToPtr_ToLocal(__generic const void *p,
134+
int) __SPIRV_NOEXCEPT {
135+
return (__local const void *)p;
136+
}
137+
static __SPIRV_overloadable __SPIRV_inline __local volatile void *
138+
__spirv_GenericCastToPtr_ToLocal(__generic volatile void *p,
139+
int) __SPIRV_NOEXCEPT {
140+
return (__local volatile void *)p;
141+
}
142+
static __SPIRV_overloadable __SPIRV_inline __local const volatile void *
143+
__spirv_GenericCastToPtr_ToLocal(__generic const volatile void *p,
144+
int) __SPIRV_NOEXCEPT {
145+
return (__local const volatile void *)p;
146+
}
147+
static __SPIRV_overloadable __SPIRV_inline __private void *
148+
__spirv_GenericCastToPtr_ToPrivate(__generic void *p, int) __SPIRV_NOEXCEPT {
149+
return (__private void *)p;
150+
}
151+
static __SPIRV_overloadable __SPIRV_inline __private const void *
152+
__spirv_GenericCastToPtr_ToPrivate(__generic const void *p,
153+
int) __SPIRV_NOEXCEPT {
154+
return (__private const void *)p;
155+
}
156+
static __SPIRV_overloadable __SPIRV_inline __private volatile void *
157+
__spirv_GenericCastToPtr_ToPrivate(__generic volatile void *p,
158+
int) __SPIRV_NOEXCEPT {
159+
return (__private volatile void *)p;
160+
}
161+
static __SPIRV_overloadable __SPIRV_inline __private const volatile void *
162+
__spirv_GenericCastToPtr_ToPrivate(__generic const volatile void *p,
163+
int) __SPIRV_NOEXCEPT {
164+
return (__private const volatile void *)p;
165+
}
166+
167+
#undef __SPIRV_overloadable
168+
#undef __SPIRV_convergent
169+
#undef __SPIRV_inline
170+
171+
#undef __global
172+
#undef __local
173+
#undef __constant
174+
#undef __generic
175+
176+
#undef __SPIRV_BUILTIN_ALIAS
177+
#undef __SPIRV_NOEXCEPT
178+
179+
#endif /* __SPIRV_BUILTIN_VARS_H */

clang/lib/Sema/SemaChecking.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1983,7 +1983,11 @@ bool Sema::CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
19831983
case llvm::Triple::mips64el:
19841984
return MIPS().CheckMipsBuiltinFunctionCall(TI, BuiltinID, TheCall);
19851985
case llvm::Triple::spirv:
1986-
return SPIRV().CheckSPIRVBuiltinFunctionCall(BuiltinID, TheCall);
1986+
case llvm::Triple::spirv32:
1987+
case llvm::Triple::spirv64:
1988+
if (TI.getTriple().getOS() != llvm::Triple::OSType::AMDHSA)
1989+
return SPIRV().CheckSPIRVBuiltinFunctionCall(BuiltinID, TheCall);
1990+
return false;
19871991
case llvm::Triple::systemz:
19881992
return SystemZ().CheckSystemZBuiltinFunctionCall(BuiltinID, TheCall);
19891993
case llvm::Triple::x86:

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include "clang/Sema/SemaOpenCL.h"
5454
#include "clang/Sema/SemaOpenMP.h"
5555
#include "clang/Sema/SemaRISCV.h"
56+
#include "clang/Sema/SemaSPIRV.h"
5657
#include "clang/Sema/SemaSYCL.h"
5758
#include "clang/Sema/SemaSwift.h"
5859
#include "clang/Sema/SemaWasm.h"
@@ -5837,12 +5838,13 @@ static void handleBuiltinAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
58375838
bool IsAArch64 = S.Context.getTargetInfo().getTriple().isAArch64();
58385839
bool IsARM = S.Context.getTargetInfo().getTriple().isARM();
58395840
bool IsRISCV = S.Context.getTargetInfo().getTriple().isRISCV();
5841+
bool IsSPIRV = S.Context.getTargetInfo().getTriple().isSPIRV();
58405842
bool IsHLSL = S.Context.getLangOpts().HLSL;
58415843
if ((IsAArch64 && !S.ARM().SveAliasValid(BuiltinID, AliasName)) ||
58425844
(IsARM && !S.ARM().MveAliasValid(BuiltinID, AliasName) &&
58435845
!S.ARM().CdeAliasValid(BuiltinID, AliasName)) ||
58445846
(IsRISCV && !S.RISCV().isAliasValid(BuiltinID, AliasName)) ||
5845-
(!IsAArch64 && !IsARM && !IsRISCV && !IsHLSL)) {
5847+
(!IsAArch64 && !IsARM && !IsRISCV && !IsHLSL && !IsSPIRV)) {
58465848
S.Diag(AL.getLoc(), diag::err_attribute_builtin_alias) << AL;
58475849
return;
58485850
}

0 commit comments

Comments
 (0)