Skip to content

Commit f8d5b49

Browse files
committed
Fix missing error for use of 128-bit integer inside SPIR64 device code.
Emit error for use of 128-bit integer inside device code had been already implemented in https://reviews.llvm.org/D74387. However, the error is not emitted for SPIR64, because for SPIR64, hasInt128Type return true. hasInt128Type: is also used to control generation of certain 128-bit predefined macros, initializer predefined 128-bit integer types and build 128-bit ArithmeticTypes. Except predefined macros, only the device target is considered, since error only emit when 128-bit integer is used inside device code, the host target (auxtarget) also needs to be considered. The change address: 1. (SPIR.h) Correct hasInt128Type() for SPIR targets. 2. Sema.cpp and SemaOverload.cpp: Add additional check to consider host target(auxtarget) when call to hasInt128Type. So that __int128_t and __int128() are allowed to avoid error when they used outside device code. 3. SemaType.cpp: add check for SYCLIsDevice to delay the error message. The error will be emitted if the use of 128-bit integer in the device code. Reviewed By: Johannes Doerfert and Aaron Ballman Differential Revision: https://reviews.llvm.org/D92439
1 parent 49921d1 commit f8d5b49

File tree

6 files changed

+134
-7
lines changed

6 files changed

+134
-7
lines changed

clang/lib/Basic/Targets/SPIR.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ class LLVM_LIBRARY_VISIBILITY SPIRTargetInfo : public TargetInfo {
104104
}
105105

106106
bool hasExtIntType() const override { return true; }
107+
108+
bool hasInt128Type() const override { return false; }
107109
};
108110
class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public SPIRTargetInfo {
109111
public:

clang/lib/Sema/Sema.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,9 @@ void Sema::Initialize() {
236236
return;
237237

238238
// Initialize predefined 128-bit integer types, if needed.
239-
if (Context.getTargetInfo().hasInt128Type()) {
239+
if (Context.getTargetInfo().hasInt128Type() ||
240+
(Context.getAuxTargetInfo() &&
241+
Context.getAuxTargetInfo()->hasInt128Type())) {
240242
// If either of the 128-bit integer types are unavailable to name lookup,
241243
// define them now.
242244
DeclarationName Int128 = &Context.Idents.get("__int128_t");

clang/lib/Sema/SemaOverload.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8187,12 +8187,16 @@ class BuiltinOperatorOverloadBuilder {
81878187
ArithmeticTypes.push_back(S.Context.IntTy);
81888188
ArithmeticTypes.push_back(S.Context.LongTy);
81898189
ArithmeticTypes.push_back(S.Context.LongLongTy);
8190-
if (S.Context.getTargetInfo().hasInt128Type())
8190+
if (S.Context.getTargetInfo().hasInt128Type() ||
8191+
(S.Context.getAuxTargetInfo() &&
8192+
S.Context.getAuxTargetInfo()->hasInt128Type()))
81918193
ArithmeticTypes.push_back(S.Context.Int128Ty);
81928194
ArithmeticTypes.push_back(S.Context.UnsignedIntTy);
81938195
ArithmeticTypes.push_back(S.Context.UnsignedLongTy);
81948196
ArithmeticTypes.push_back(S.Context.UnsignedLongLongTy);
8195-
if (S.Context.getTargetInfo().hasInt128Type())
8197+
if (S.Context.getTargetInfo().hasInt128Type() ||
8198+
(S.Context.getAuxTargetInfo() &&
8199+
S.Context.getAuxTargetInfo()->hasInt128Type()))
81968200
ArithmeticTypes.push_back(S.Context.UnsignedInt128Ty);
81978201
LastPromotedIntegralType = ArithmeticTypes.size();
81988202
LastPromotedArithmeticType = ArithmeticTypes.size();

clang/lib/Sema/SemaType.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,6 +1515,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
15151515
}
15161516
case DeclSpec::TST_int128:
15171517
if (!S.Context.getTargetInfo().hasInt128Type() &&
1518+
!S.getLangOpts().SYCLIsDevice &&
15181519
!(S.getLangOpts().OpenMP && S.getLangOpts().OpenMPIsDevice))
15191520
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
15201521
<< "__int128";

clang/test/CodeGen/ext-int-cc.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ void ParamPassing(_ExtInt(129) a, _ExtInt(128) b, _ExtInt(64) c) {}
4343
// SPARC: define void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128* byval(i128) align 8 %{{.+}}, i64 %{{.+}})
4444
// MIPS64: define void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128 signext %{{.+}}, i64 signext %{{.+}})
4545
// MIPS: define void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128* byval(i128) align 8 %{{.+}}, i64 signext %{{.+}})
46-
// SPIR64: define spir_func void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128 %{{.+}}, i64 %{{.+}})
46+
// SPIR64: define spir_func void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128* byval(i128) align 8 %{{.+}}, i64 %{{.+}})
4747
// SPIR: define spir_func void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128* byval(i128) align 8 %{{.+}}, i64 %{{.+}})
4848
// HEX: define void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128* byval(i128) align 8 %{{.+}}, i64 %{{.+}})
4949
// LANAI: define void @ParamPassing(i129* byval(i129) align 4 %{{.+}}, i128* byval(i128) align 4 %{{.+}}, i64 %{{.+}})
@@ -72,7 +72,7 @@ void ParamPassing2(_ExtInt(129) a, _ExtInt(127) b, _ExtInt(63) c) {}
7272
// SPARC: define void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127* byval(i127) align 8 %{{.+}}, i63 %{{.+}})
7373
// MIPS64: define void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127 signext %{{.+}}, i63 signext %{{.+}})
7474
// MIPS: define void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127* byval(i127) align 8 %{{.+}}, i63 signext %{{.+}})
75-
// SPIR64: define spir_func void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127 %{{.+}}, i63 %{{.+}})
75+
// SPIR64: define spir_func void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127* byval(i127) align 8 %{{.+}}, i63 %{{.+}})
7676
// SPIR: define spir_func void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127* byval(i127) align 8 %{{.+}}, i63 %{{.+}})
7777
// HEX: define void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127* byval(i127) align 8 %{{.+}}, i63 %{{.+}})
7878
// LANAI: define void @ParamPassing2(i129* byval(i129) align 4 %{{.+}}, i127* byval(i127) align 4 %{{.+}}, i63 %{{.+}})
@@ -191,7 +191,7 @@ _ExtInt(127) ReturnPassing3(){}
191191
// SPARC: define void @ReturnPassing3(i127* noalias sret
192192
// MIPS64: define i127 @ReturnPassing3(
193193
// MIPS: define void @ReturnPassing3(i127* noalias sret
194-
// SPIR64: define spir_func i127 @ReturnPassing3(
194+
// SPIR64: define spir_func void @ReturnPassing3(i127* noalias sret
195195
// SPIR: define spir_func void @ReturnPassing3(i127* noalias sret
196196
// HEX: define void @ReturnPassing3(i127* noalias sret
197197
// LANAI: define void @ReturnPassing3(i127* noalias sret
@@ -220,7 +220,7 @@ _ExtInt(128) ReturnPassing4(){}
220220
// SPARC: define void @ReturnPassing4(i128* noalias sret
221221
// MIPS64: define i128 @ReturnPassing4(
222222
// MIPS: define void @ReturnPassing4(i128* noalias sret
223-
// SPIR64: define spir_func i128 @ReturnPassing4(
223+
// SPIR64: define spir_func void @ReturnPassing4(i128* noalias sret
224224
// SPIR: define spir_func void @ReturnPassing4(i128* noalias sret
225225
// HEX: define void @ReturnPassing4(i128* noalias sret
226226
// LANAI: define void @ReturnPassing4(i128* noalias sret

clang/test/SemaSYCL/int128.cpp

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// RUN: %clang_cc1 -triple spir64 -aux-triple x86_64-unknown-linux-gnu \
2+
// RUN: -fsycl -fsycl-is-device -verify -fsyntax-only %s
3+
4+
typedef __uint128_t BIGTY;
5+
6+
template <class T>
7+
class Z {
8+
public:
9+
// expected-note@+1 {{'field' defined here}}
10+
T field;
11+
// expected-note@+1 2{{'field1' defined here}}
12+
__int128 field1;
13+
using BIGTYPE = __int128;
14+
// expected-note@+1 {{'bigfield' defined here}}
15+
BIGTYPE bigfield;
16+
};
17+
18+
void host_ok(void) {
19+
__int128 A;
20+
int B = sizeof(__int128);
21+
Z<__int128> C;
22+
C.field1 = A;
23+
}
24+
25+
void usage() {
26+
// expected-note@+1 3{{'A' defined here}}
27+
__int128 A;
28+
Z<__int128> C;
29+
// expected-error@+2 {{'A' requires 128 bit size '__int128' type support, but device 'spir64' does not support it}}
30+
// expected-error@+1 {{'field1' requires 128 bit size '__int128' type support, but device 'spir64' does not support it}}
31+
C.field1 = A;
32+
// expected-error@+1 {{'bigfield' requires 128 bit size 'Z::BIGTYPE' (aka '__int128') type support, but device 'spir64' does not support it}}
33+
C.bigfield += 1.0;
34+
35+
// expected-error@+1 {{'A' requires 128 bit size '__int128' type support, but device 'spir64' does not support it}}
36+
auto foo1 = [=]() {
37+
__int128 AA;
38+
// expected-note@+2 {{'BB' defined here}}
39+
// expected-error@+1 {{'A' requires 128 bit size '__int128' type support, but device 'spir64' does not support it}}
40+
auto BB = A;
41+
// expected-error@+1 {{'BB' requires 128 bit size '__int128' type support, but device 'spir64' does not support it}}
42+
BB += 1;
43+
};
44+
45+
// expected-note@+1 {{called by 'usage'}}
46+
foo1();
47+
}
48+
49+
template <typename t>
50+
void foo2(){};
51+
52+
// expected-note@+3 {{'P' defined here}}
53+
// expected-error@+2 {{'P' requires 128 bit size '__int128' type support, but device 'spir64' does not support it}}
54+
// expected-note@+1 2{{'foo' defined here}}
55+
__int128 foo(__int128 P) { return P; }
56+
57+
void foobar() {
58+
// expected-note@+1 {{'operator __int128' defined here}}
59+
struct X { operator __int128() const; } x;
60+
bool a = false;
61+
// expected-error@+1 {{'operator __int128' requires 128 bit size '__int128' type support, but device 'spir64' does not support it}}
62+
a = x == __int128(0);
63+
}
64+
65+
template <typename Name, typename Func>
66+
__attribute__((sycl_kernel)) void kernel(Func kernelFunc) {
67+
// expected-note@+1 6{{called by 'kernel}}
68+
kernelFunc();
69+
}
70+
71+
int main() {
72+
// expected-note@+1 {{'CapturedToDevice' defined here}}
73+
__int128 CapturedToDevice = 1;
74+
host_ok();
75+
kernel<class variables>([=]() {
76+
decltype(CapturedToDevice) D;
77+
// expected-error@+1 {{'CapturedToDevice' requires 128 bit size '__int128' type support, but device 'spir64' does not support it}}
78+
auto C = CapturedToDevice;
79+
Z<__int128> S;
80+
// expected-error@+1 {{'field1' requires 128 bit size '__int128' type support, but device 'spir64' does not support it}}
81+
S.field1 += 1;
82+
// expected-error@+1 {{'field' requires 128 bit size '__int128' type support, but device 'spir64' does not support it}}
83+
S.field = 1;
84+
});
85+
86+
kernel<class functions>([=]() {
87+
// expected-note@+1 2{{called by 'operator()'}}
88+
usage();
89+
// expected-note@+1 {{'BBBB' defined here}}
90+
BIGTY BBBB;
91+
// expected-error@+3 {{'BBBB' requires 128 bit size 'BIGTY' (aka 'unsigned __int128') type support, but device 'spir64' does not support it}}
92+
// expected-error@+2 2{{'foo' requires 128 bit size '__int128' type support, but device 'spir64' does not support it}}
93+
// expected-note@+1 1{{called by 'operator()'}}
94+
auto A = foo(BBBB);
95+
// expected-note@+1 {{called by 'operator()'}}
96+
foobar();
97+
});
98+
99+
kernel<class ok>([=]() {
100+
Z<__int128> S;
101+
foo2<__int128>();
102+
auto A = sizeof(CapturedToDevice);
103+
});
104+
105+
return 0;
106+
}
107+
108+
// no error expected
109+
BIGTY zoo(BIGTY h) {
110+
h = 1;
111+
return h;
112+
}
113+
114+
namespace PR12964 {
115+
struct X { operator __int128() const; } x;
116+
bool a = x == __int128(0);
117+
}
118+

0 commit comments

Comments
 (0)