Fznamznon updated this revision to Diff 253910.
Fznamznon added a comment.
Apply comments, rebase.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D74387/new/
https://reviews.llvm.org/D74387
Files:
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Sema/Sema.h
clang/lib/Sema/CMakeLists.txt
clang/lib/Sema/SemaAvailability.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclAttr.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaSYCL.cpp
clang/lib/Sema/SemaType.cpp
clang/test/SemaSYCL/float128.cpp
Index: clang/test/SemaSYCL/float128.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaSYCL/float128.cpp
@@ -0,0 +1,95 @@
+// RUN: %clang_cc1 -triple spir64 -fsycl -fsycl-is-device -verify -fsyntax-only %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsycl -fsycl-is-device -fsyntax-only %s
+
+template <class T>
+class Z {
+public:
+ // TODO: If T is __float128 This might be a problem
+ T field;
+ // expected-note@+1 2{{declaration is unavailable because it uses type '__float128' that is not supported on this target}}
+ __float128 field1;
+};
+
+void host_ok(void) {
+ __float128 A;
+ int B = sizeof(__float128);
+ Z<__float128> C;
+ C.field1 = A;
+}
+
+void usage() {
+ // expected-error@+2 {{'__float128' is not supported on this target}}
+ // expected-note@+1 4{{declaration is unavailable because it uses type '__float128' that is not supported on this target}}
+ __float128 A;
+ Z<__float128> C;
+ // expected-error@+2 {{'A' is unavailable}}
+ // expected-error@+1 {{'field1' is unavailable}}
+ C.field1 = A;
+ // expected-error@+1 {{'A' is unavailable}}
+ decltype(A) D;
+
+ // expected-error@+1 {{'A' is unavailable}}
+ auto foo1 = [=]() {
+ // expected-error@+1 {{'__float128' is not supported on this target}}
+ __float128 AA;
+ // expected-error@+1 {{'A' is unavailable}}
+ auto BB = A;
+ BB += 1;
+ };
+
+ // expected-note@+1 {{called by 'usage'}}
+ foo1();
+}
+
+template <typename t>
+void foo2(){};
+
+// expected-note@+1 {{declaration is unavailable because it uses type '__float128 (__float128)' that is not supported on this target}}
+__float128 foo(__float128 P) { return P; }
+
+template <typename Name, typename Func>
+__attribute__((sycl_kernel)) void kernel(Func kernelFunc) {
+ // expected-note@+1 5{{called by 'kernel}}
+ kernelFunc();
+ // expected-error@+1 {{'__float128' is not supported on this target}}
+ __float128 A;
+}
+
+int main() {
+ // expected-note@+1 2{{declaration is unavailable because it uses type '__float128' that is not supported on this target}}
+ __float128 CapturedToDevice = 1;
+ host_ok();
+ kernel<class variables>([=]() {
+ // expected-error@+1 {{'CapturedToDevice' is unavailable}}
+ decltype(CapturedToDevice) D;
+ // expected-error@+1 {{'CapturedToDevice' is unavailable}}
+ auto C = CapturedToDevice;
+ // expected-error@+1 {{'__float128' is not supported on this target}}
+ __float128 BBBB;
+ Z<__float128> S;
+ // expected-error@+1 {{'field1' is unavailable}}
+ S.field1 += 1;
+ S.field = 1;
+ });
+
+ kernel<class functions>([=]() {
+ // expected-note@+1 2{{called by 'operator()'}}
+ usage();
+ // expected-error@+2 {{'__float128' is not supported on this target}}
+ // expected-note@+1 {{declaration is unavailable because it uses type '__float128' that is not supported on this target}}
+ __float128 BBBB;
+ // expected-error@+2 {{'BBBB' is unavailable}}
+ // expected-error@+1 {{'foo' is unavailable}}
+ auto A = foo(BBBB);
+ });
+
+ kernel<class ok>([=]() {
+ Z<__float128> S;
+ foo2<__float128>();
+ // TODO: this shouldn't be diagnosed
+ // expected-error@+1 {{'__float128' is not supported on this target}}
+ int E = sizeof(__float128);
+ });
+
+ return 0;
+}
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -1517,10 +1517,21 @@
break;
case DeclSpec::TST_float128:
if (!S.Context.getTargetInfo().hasFloat128Type() &&
+ !S.getLangOpts().SYCLIsDevice &&
!(S.getLangOpts().OpenMP && S.getLangOpts().OpenMPIsDevice))
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
<< "__float128";
Result = Context.Float128Ty;
+ if (!S.Context.getTargetInfo().hasFloat128Type() &&
+ S.getLangOpts().SYCLIsDevice &&
+ S.DelayedDiagnostics.shouldDelayDiagnostics()) {
+ S.DelayedDiagnostics.add(sema::DelayedDiagnostic::makeForbiddenType(
+ DS.getTypeSpecTypeLoc(), diag::err_type_unsupported, Result,
+ /*ignored*/ 0));
+ S.SYCLDiagIfDeviceCode(DS.getTypeSpecTypeLoc(),
+ diag::err_type_unsupported)
+ << Result;
+ }
break;
case DeclSpec::TST_bool: Result = Context.BoolTy; break; // _Bool or bool
break;
Index: clang/lib/Sema/SemaSYCL.cpp
===================================================================
--- /dev/null
+++ clang/lib/Sema/SemaSYCL.cpp
@@ -0,0 +1,51 @@
+//===- SemaSYCL.cpp - Semantic Analysis for SYCL constructs ---------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// This implements Semantic Analysis for SYCL constructs.
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaDiagnostic.h"
+
+using namespace clang;
+
+// -----------------------------------------------------------------------------
+// SYCL device specific diagnostics implementation
+// -----------------------------------------------------------------------------
+
+Sema::DeviceDiagBuilder Sema::SYCLDiagIfDeviceCode(SourceLocation Loc,
+ unsigned DiagID) {
+ assert(getLangOpts().SYCLIsDevice &&
+ "Should only be called during SYCL compilation");
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(getCurLexicalContext());
+ DeviceDiagBuilder::Kind DiagKind = [this, FD] {
+ if (!FD)
+ return DeviceDiagBuilder::K_Nop;
+ if (getEmissionStatus(FD) == Sema::FunctionEmissionStatus::Emitted)
+ return DeviceDiagBuilder::K_ImmediateWithCallStack;
+ return DeviceDiagBuilder::K_Deferred;
+ }();
+ return DeviceDiagBuilder(DiagKind, Loc, DiagID, FD, *this);
+}
+
+bool Sema::checkSYCLDeviceFunction(SourceLocation Loc, FunctionDecl *Callee) {
+ assert(getLangOpts().SYCLIsDevice &&
+ "Should only be called during SYCL compilation");
+ assert(Callee && "Callee may not be null.");
+
+ // Errors in unevaluated context don't need to be generated,
+ // so we can safely skip them.
+ if (isUnevaluatedContext() || isConstantEvaluated())
+ return true;
+
+ FunctionDecl *Caller = dyn_cast<FunctionDecl>(getCurLexicalContext());
+
+ DeviceDiagBuilder::Kind DiagKind = DeviceDiagBuilder::K_Nop;
+
+ return DiagKind != DeviceDiagBuilder::K_Immediate &&
+ DiagKind != DeviceDiagBuilder::K_ImmediateWithCallStack;
+}
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -292,6 +292,9 @@
if (getLangOpts().CUDA && !CheckCUDACall(Loc, FD))
return true;
+
+ if (getLangOpts().SYCLIsDevice && !checkSYCLDeviceFunction(Loc, FD))
+ return true;
}
if (auto *MD = dyn_cast<CXXMethodDecl>(D)) {
@@ -16048,6 +16051,9 @@
if (getLangOpts().CUDA)
CheckCUDACall(Loc, Func);
+ if (getLangOpts().SYCLIsDevice)
+ checkSYCLDeviceFunction(Loc, Func);
+
// If we need a definition, try to create one.
if (NeedDefinition && !Func->getBody()) {
runWithSufficientStackSpace(Loc, [&] {
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -14884,6 +14884,9 @@
MarkFunctionReferenced(ConstructLoc, Constructor);
if (getLangOpts().CUDA && !CheckCUDACall(ConstructLoc, Constructor))
return ExprError();
+ if (getLangOpts().SYCLIsDevice &&
+ !checkSYCLDeviceFunction(ConstructLoc, Constructor))
+ return ExprError();
return CheckForImmediateInvocation(
CXXConstructExpr::Create(
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -7641,6 +7641,13 @@
static bool isForbiddenTypeAllowed(Sema &S, Decl *D,
const DelayedDiagnostic &diag,
UnavailableAttr::ImplicitReason &reason) {
+ // SYCL: delay the diagnostic until we know that the function will be actually
+ // emitted
+ if (S.getLangOpts().SYCLIsDevice) {
+ reason = UnavailableAttr::IR_SYCLForbiddenType;
+ return true;
+ }
+
// Private ivars are always okay. Unfortunately, people don't
// always properly make their ivars private, even in system headers.
// Plus we need to make fields okay, too.
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -14394,7 +14394,7 @@
DiscardCleanupsInEvaluationContext();
}
- if (LangOpts.OpenMP || LangOpts.CUDA) {
+ if (LangOpts.OpenMP || LangOpts.CUDA || LangOpts.SYCLIsDevice) {
auto ES = getEmissionStatus(FD);
if (ES == Sema::FunctionEmissionStatus::Emitted ||
ES == Sema::FunctionEmissionStatus::Unknown)
@@ -18070,6 +18070,11 @@
Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD,
bool Final) {
+ // Due to SYCL functions can be template we check if they have appropriate
+ // attribute prior to checking if it is a template
+ if (LangOpts.SYCLIsDevice && FD->hasAttr<SYCLKernelAttr>())
+ return FunctionEmissionStatus::Emitted;
+
// Templates are emitted when they're instantiated.
if (FD->isDependentContext())
return FunctionEmissionStatus::TemplateDiscarded;
Index: clang/lib/Sema/SemaAvailability.cpp
===================================================================
--- clang/lib/Sema/SemaAvailability.cpp
+++ clang/lib/Sema/SemaAvailability.cpp
@@ -474,6 +474,16 @@
flagARCError();
diag_available_here = diag::note_arc_field_with_ownership;
break;
+
+ case UnavailableAttr::IR_SYCLForbiddenType:
+ diag_available_here = diag::note_type_unavailable;
+ if (S.getLangOpts().SYCLIsDevice) {
+ S.SYCLDiagIfDeviceCode(Loc, diag) << ReferringDecl;
+ S.SYCLDiagIfDeviceCode(NoteLocation, diag_available_here)
+ << cast<ValueDecl>(OffendingDecl)->getType();
+ return;
+ }
+ break;
}
}
}
Index: clang/lib/Sema/CMakeLists.txt
===================================================================
--- clang/lib/Sema/CMakeLists.txt
+++ clang/lib/Sema/CMakeLists.txt
@@ -59,6 +59,7 @@
SemaStmt.cpp
SemaStmtAsm.cpp
SemaStmtAttr.cpp
+ SemaSYCL.cpp
SemaTemplate.cpp
SemaTemplateDeduction.cpp
SemaTemplateInstantiate.cpp
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -12308,6 +12308,40 @@
ConstructorDestructor,
BuiltinFunction
};
+ /// Creates a DeviceDiagBuilder that emits the diagnostic if the current
+ /// context is "used as device code".
+ ///
+ /// - If CurLexicalContext is a kernel function or it is known that the
+ /// function will be emitted for the device, emits the diagnostics
+ /// immediately.
+ /// - If CurLexicalContext is a function and we are compiling
+ /// for the device, but we don't know that this function will be codegen'ed
+ /// for devive yet, creates a diagnostic which is emitted if and when we
+ /// realize that the function will be codegen'ed.
+ ///
+ /// Example usage:
+ ///
+ /// Diagnose __float128 type usage only from SYCL device code if the current
+ /// target doesn't support it
+ /// if (!S.Context.getTargetInfo().hasFloat128Type() &&
+ /// S.getLangOpts().SYCLIsDevice)
+ /// SYCLDiagIfDeviceCode(Loc, diag::err_type_unsupported) << "__float128";
+ DeviceDiagBuilder SYCLDiagIfDeviceCode(SourceLocation Loc, unsigned DiagID);
+
+ /// Check whether we're allowed to call Callee from the current context.
+ ///
+ /// - If the call is never allowed in a semantically-correct program
+ /// emits an error and returns false.
+ ///
+ /// - If the call is allowed in semantically-correct programs, but only if
+ /// it's never codegen'ed, creates a deferred diagnostic to be emitted if
+ /// and when the caller is codegen'ed, and returns true.
+ ///
+ /// - Otherwise, returns true without emitting any diagnostics.
+ ///
+ /// Adds Callee to DeviceCallGraph if we don't know if its caller will be
+ /// codegen'ed yet.
+ bool checkSYCLDeviceFunction(SourceLocation Loc, FunctionDecl *Callee);
};
/// RAII object that enters a new expression evaluation context.
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9345,6 +9345,9 @@
"feature, not permitted in C++">;
def err_type_unsupported : Error<
"%0 is not supported on this target">;
+def note_type_unavailable : Note<
+ "declaration is unavailable because it uses type %0 that is not supported on "
+ "this target">;
def err_nsconsumed_attribute_mismatch : Error<
"overriding method has mismatched ns_consumed attribute on its"
" parameter">;
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -2374,7 +2374,8 @@
"IR_ForbiddenWeak",
"IR_ARCForbiddenConversion",
"IR_ARCInitReturnsUnrelated",
- "IR_ARCFieldWithOwnership"], 1, /*fake*/ 1>];
+ "IR_ARCFieldWithOwnership",
+ "IR_SYCLForbiddenType"], 1, /*fake*/ 1>];
let Documentation = [Undocumented];
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits