Skip to content

Commit

Permalink
Merged main:0e874fc014be into amd-gfx:abefc15690ba
Browse files Browse the repository at this point in the history
Local branch amd-gfx abefc15 Merged main:1ca5e68aa07e into amd-gfx:8b5343c48207
Remote branch main 0e874fc [OpenCL] Add clang extension for variadic functions.
  • Loading branch information
Sw authored and Sw committed Jan 6, 2021
2 parents abefc15 + 0e874fc commit 8a4e249
Show file tree
Hide file tree
Showing 62 changed files with 1,580 additions and 342 deletions.
7 changes: 4 additions & 3 deletions clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1042,7 +1042,7 @@ TEST_F(TUSchedulerTests, CommandLineWarnings) {

TEST(DebouncePolicy, Compute) {
namespace c = std::chrono;
std::vector<DebouncePolicy::clock::duration> History = {
DebouncePolicy::clock::duration History[] = {
c::seconds(0),
c::seconds(5),
c::seconds(10),
Expand All @@ -1053,8 +1053,9 @@ TEST(DebouncePolicy, Compute) {
Policy.Max = c::seconds(25);
// Call Policy.compute(History) and return seconds as a float.
auto Compute = [&](llvm::ArrayRef<DebouncePolicy::clock::duration> History) {
using FloatingSeconds = c::duration<float, c::seconds::period>;
return static_cast<float>(Policy.compute(History) / FloatingSeconds(1));
return c::duration_cast<c::duration<float, c::seconds::period>>(
Policy.compute(History))
.count();
};
EXPECT_NEAR(10, Compute(History), 0.01) << "(upper) median = 10";
Policy.RebuildRatio = 1.5;
Expand Down
77 changes: 77 additions & 0 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1722,6 +1722,83 @@ syntax to be used with ``std::complex`` with the same meaning.)
For GCC compatibility, ``__builtin_complex(re, im)`` can also be used to
construct a complex number from the given real and imaginary components.
OpenCL Features
===============
Clang supports internal OpenCL extensions documented below.
``__cl_clang_function_pointers``
--------------------------------
With this extension it is possible to enable various language features that
are relying on function pointers using regular OpenCL extension pragma
mechanism detailed in `the OpenCL Extension Specification,
section 1.2
<https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#extensions-overview>`_.
In C++ for OpenCL this also enables:
- Use of member function pointers;
- Unrestricted use of references to functions;
- Virtual member functions.
Such functionality is not conformant and does not guarantee to compile
correctly in any circumstances. It can be used if:
- the kernel source does not contain call expressions to (member-) function
pointers, or virtual functions. For example this extension can be used in
metaprogramming algorithms to be able to specify/detect types generically.
- the generated kernel binary does not contain indirect calls because they
are eliminated using compiler optimizations e.g. devirtualization.
- the selected target supports the function pointer like functionality e.g.
most CPU targets.
**Example of Use**:
.. code-block:: c++
#pragma OPENCL EXTENSION __cl_clang_function_pointers : enable
void foo()
{
void (*fp)(); // compiled - no diagnostic generated
}
#pragma OPENCL EXTENSION __cl_clang_function_pointers : disable
void bar()
{
void (*fp)(); // error - pointers to function are not allowed
}
``__cl_clang_variadic_functions``
---------------------------------
With this extension it is possible to enable variadic arguments in functions
using regular OpenCL extension pragma mechanism detailed in `the OpenCL
Extension Specification, section 1.2
<https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#extensions-overview>`_.
This is not conformant behavior and it can only be used portably when the
functions with variadic prototypes do not get generated in binary e.g. the
variadic prototype is used to spesify a function type with any number of
arguments in metaprogramming algorithms in C++ for OpenCL.
This extensions can also be used when the kernel code is intended for targets
supporting the variadic arguments e.g. majority of CPU targets.
**Example of Use**:
.. code-block:: c++
#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
void foo(int a, ...); // compiled - no diagnostic generated
#pragma OPENCL EXTENSION __cl_clang_variadic_functions : disable
void bar(int a, ...); // error - variadic prototype is not allowed
Builtin Functions
=================
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/OpenCLExtensions.def
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ OPENCLEXT_INTERNAL(cl_khr_subgroups, 200, ~0U)

// Clang Extensions.
OPENCLEXT_INTERNAL(cl_clang_storage_class_specifiers, 100, ~0U)
OPENCLEXT_INTERNAL(__cl_clang_function_pointers, 100, ~0U)
OPENCLEXT_INTERNAL(__cl_clang_variadic_functions, 100, ~0U)

// AMD OpenCL extensions
OPENCLEXT_INTERNAL(cl_amd_media_ops, 100, ~0U)
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Basic/Targets/AMDGPU.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo {
void setSupportedOpenCLOpts() override {
auto &Opts = getSupportedOpenCLOpts();
Opts.support("cl_clang_storage_class_specifiers");
Opts.support("__cl_clang_function_pointers");
Opts.support("__cl_clang_variadic_functions");

bool IsAMDGCN = isAMDGCN(getTriple());

Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Basic/Targets/NVPTX.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo {
void setSupportedOpenCLOpts() override {
auto &Opts = getSupportedOpenCLOpts();
Opts.support("cl_clang_storage_class_specifiers");
Opts.support("__cl_clang_function_pointers");
Opts.support("__cl_clang_variadic_functions");

Opts.support("cl_khr_fp64");
Opts.support("cl_khr_byte_addressable_store");
Expand Down
7 changes: 4 additions & 3 deletions clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3630,12 +3630,13 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
case tok::kw_virtual:
// C++ for OpenCL does not allow virtual function qualifier, to avoid
// function pointers restricted in OpenCL v2.0 s6.9.a.
if (getLangOpts().OpenCLCPlusPlus) {
if (getLangOpts().OpenCLCPlusPlus &&
!getActions().getOpenCLOptions().isEnabled(
"__cl_clang_function_pointers")) {
DiagID = diag::err_openclcxx_virtual_function;
PrevSpec = Tok.getIdentifierInfo()->getNameStart();
isInvalid = true;
}
else {
} else {
isInvalid = DS.setFunctionSpecVirtual(Loc, PrevSpec, DiagID);
}
break;
Expand Down
16 changes: 9 additions & 7 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6748,14 +6748,16 @@ static bool diagnoseOpenCLTypes(Scope *S, Sema &Se, Declarator &D,
}

// OpenCL v1.0 s6.8.a.3: Pointers to functions are not allowed.
QualType NR = R;
while (NR->isPointerType() || NR->isMemberFunctionPointerType()) {
if (NR->isFunctionPointerType() || NR->isMemberFunctionPointerType()) {
Se.Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer);
D.setInvalidType();
return false;
if (!Se.getOpenCLOptions().isEnabled("__cl_clang_function_pointers")) {
QualType NR = R;
while (NR->isPointerType() || NR->isMemberFunctionPointerType()) {
if (NR->isFunctionPointerType() || NR->isMemberFunctionPointerType()) {
Se.Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer);
D.setInvalidType();
return false;
}
NR = NR->getPointeeType();
}
NR = NR->getPointeeType();
}

if (!Se.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2089,7 +2089,8 @@ QualType Sema::BuildPointerType(QualType T,
return QualType();
}

if (T->isFunctionType() && getLangOpts().OpenCL) {
if (T->isFunctionType() && getLangOpts().OpenCL &&
!getOpenCLOptions().isEnabled("__cl_clang_function_pointers")) {
Diag(Loc, diag::err_opencl_function_pointer);
return QualType();
}
Expand Down Expand Up @@ -5018,6 +5019,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// (s6.9.e and s6.12.5 OpenCL v2.0) except for printf.
// We also allow here any toolchain reserved identifiers.
if (FTI.isVariadic &&
!S.getOpenCLOptions().isEnabled("__cl_clang_variadic_functions") &&
!(D.getIdentifier() &&
((D.getIdentifier()->getName() == "printf" &&
(LangOpts.OpenCLCPlusPlus || LangOpts.OpenCLVersion >= 120)) ||
Expand Down
12 changes: 11 additions & 1 deletion clang/test/Misc/amdgcn.languageOptsOpenCL.cl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,17 @@
#ifndef cl_clang_storage_class_specifiers
#error "Missing cl_clang_storage_class_specifiers define"
#endif
#pragma OPENCL EXTENSION cl_clang_storage_class_specifiers: enable
#pragma OPENCL EXTENSION cl_clang_storage_class_specifiers : enable

#ifndef __cl_clang_function_pointers
#error "Missing __cl_clang_function_pointers define"
#endif
#pragma OPENCL EXTENSION __cl_clang_function_pointers : enable

#ifndef __cl_clang_variadic_functions
#error "Missing __cl_clang_variadic_functions define"
#endif
#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable

#ifndef cl_khr_fp16
#error "Missing cl_khr_fp16 define"
Expand Down
12 changes: 11 additions & 1 deletion clang/test/Misc/nvptx.languageOptsOpenCL.cl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,17 @@
#ifndef cl_clang_storage_class_specifiers
#error "Missing cl_clang_storage_class_specifiers define"
#endif
#pragma OPENCL EXTENSION cl_clang_storage_class_specifiers: enable
#pragma OPENCL EXTENSION cl_clang_storage_class_specifiers : enable

#ifndef __cl_clang_function_pointers
#error "Missing __cl_clang_function_pointers define"
#endif
#pragma OPENCL EXTENSION __cl_clang_function_pointers : enable

#ifndef __cl_clang_variadic_functions
#error "Missing __cl_clang_variadic_functions define"
#endif
#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable

#ifdef cl_khr_fp16
#error "Incorrect cl_khr_fp16 define"
Expand Down
12 changes: 11 additions & 1 deletion clang/test/Misc/r600.languageOptsOpenCL.cl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,17 @@
#ifndef cl_clang_storage_class_specifiers
#error "Missing cl_clang_storage_class_specifiers define"
#endif
#pragma OPENCL EXTENSION cl_clang_storage_class_specifiers: enable
#pragma OPENCL EXTENSION cl_clang_storage_class_specifiers : enable

#ifndef __cl_clang_function_pointers
#error "Missing __cl_clang_function_pointers define"
#endif
#pragma OPENCL EXTENSION __cl_clang_function_pointers : enable

#ifndef __cl_clang_variadic_functions
#error "Missing __cl_clang_variadic_functions define"
#endif
#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable

#ifdef cl_khr_fp16
#error "Incorrect cl_khr_fp16 define"
Expand Down
23 changes: 18 additions & 5 deletions clang/test/Parser/opencl-cxx-virtual.cl
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -fsyntax-only -verify
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -fsyntax-only -verify -DFUNCPTREXT

// Test that virtual functions and abstract classes are rejected.
#ifdef FUNCPTREXT
#pragma OPENCL EXTENSION __cl_clang_function_pointers : enable
//expected-no-diagnostics
#endif

// Test that virtual functions and abstract classes are rejected
// unless specific clang extension is used.
class virtual_functions {
virtual void bad1() {}
//expected-error@-1 {{virtual functions are not supported in C++ for OpenCL}}
#ifndef FUNCPTREXT
//expected-error@-2 {{virtual functions are not supported in C++ for OpenCL}}
#endif

virtual void bad2() = 0;
//expected-error@-1 {{virtual functions are not supported in C++ for OpenCL}}
//expected-error@-2 {{'bad2' is not virtual and cannot be declared pure}}
#ifndef FUNCPTREXT
//expected-error@-2 {{virtual functions are not supported in C++ for OpenCL}}
//expected-error@-3 {{'bad2' is not virtual and cannot be declared pure}}
#endif
};

template <typename T>
class X {
virtual T f();
//expected-error@-1 {{virtual functions are not supported in C++ for OpenCL}}
#ifndef FUNCPTREXT
//expected-error@-2 {{virtual functions are not supported in C++ for OpenCL}}
#endif
};

// Test that virtual base classes are allowed.
Expand Down
12 changes: 11 additions & 1 deletion clang/test/SemaOpenCL/extension-version.cl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,17 @@
#ifndef cl_clang_storage_class_specifiers
#error "Missing cl_clang_storage_class_specifiers define"
#endif
#pragma OPENCL EXTENSION cl_clang_storage_class_specifiers: enable
#pragma OPENCL EXTENSION cl_clang_storage_class_specifiers : enable

#ifndef __cl_clang_function_pointers
#error "Missing __cl_clang_function_pointers define"
#endif
#pragma OPENCL EXTENSION __cl_clang_function_pointers : enable

#ifndef __cl_clang_variadic_functions
#error "Missing __cl_clang_variadic_functions define"
#endif
#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable

#ifndef cl_khr_fp16
#error "Missing cl_khr_fp16 define"
Expand Down
38 changes: 32 additions & 6 deletions clang/test/SemaOpenCL/func.cl
Original file line number Diff line number Diff line change
@@ -1,16 +1,39 @@
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -triple spir-unknown-unknown
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -triple spir-unknown-unknown -DFUNCPTREXT
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -triple spir-unknown-unknown -DVARARG

#ifdef FUNCPTREXT
#pragma OPENCL EXTENSION __cl_clang_function_pointers : enable
#endif
#ifdef VARARGEXT
#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
#endif

// Variadic functions
void vararg_f(int, ...); // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}}
void vararg_f(int, ...);
#ifndef VARARGEXT
// expected-error@-2 {{invalid prototype, variadic arguments are not allowed in OpenCL}}
#endif
void __vararg_f(int, ...);
typedef void (*vararg_fptr_t)(int, ...); // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}}
// expected-error@-1{{pointers to functions are not allowed}}
int printf(__constant const char *st, ...); // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}}
typedef void (*vararg_fptr_t)(int, ...);
#ifndef VARARGEXT
// expected-error@-2 {{invalid prototype, variadic arguments are not allowed in OpenCL}}
#endif
#ifndef FUNCPTREXT
// expected-error@-5 {{pointers to functions are not allowed}}
#endif
int printf(__constant const char *st, ...);
#ifndef VARARGEXT
// expected-error@-2 {{invalid prototype, variadic arguments are not allowed in OpenCL}}
#endif

// Struct type with function pointer field
typedef struct s
{
void (*f)(struct s *self, int *i); // expected-error{{pointers to functions are not allowed}}
void (*f)(struct s *self, int *i);
#ifndef FUNCPTREXT
// expected-error@-2 {{pointers to functions are not allowed}}
#endif
} s_t;

//Function pointer
Expand All @@ -22,7 +45,10 @@ void bar();
void bar()
{
// declaring a function pointer is an error
void (*fptr)(int); // expected-error{{pointers to functions are not allowed}}
void (*fptr)(int);
#ifndef FUNCPTREXT
// expected-error@-2 {{pointers to functions are not allowed}}
#endif

// taking the address of a function is an error
foo((void*)foo); // expected-error{{taking address of function is not allowed}}
Expand Down
Loading

0 comments on commit 8a4e249

Please sign in to comment.