From 0e874fc014be818a9c6782729f2c8e8273a7a906 Mon Sep 17 00:00:00 2001 From: Anastasia Stulova Date: Wed, 6 Jan 2021 19:30:04 +0000 Subject: [PATCH] [OpenCL] Add clang extension for variadic functions. With the internal clang extension '__cl_clang_variadic_functions' variadic functions are accepted by the frontend. This is not a fully supported vendor/Khronos extension as it can only be used on targets with variadic prototype support or in metaprogramming to represent functions with generic prototype without calling such functions in the kernel code. Tags: #clang Differential Revision: https://reviews.llvm.org/D94027 --- clang/docs/LanguageExtensions.rst | 25 +++++++++++++++++++++++++ clang/include/clang/Basic/OpenCLExtensions.def | 1 + clang/lib/Basic/Targets/AMDGPU.h | 1 + clang/lib/Basic/Targets/NVPTX.h | 1 + clang/lib/Sema/SemaType.cpp | 1 + clang/test/Misc/amdgcn.languageOptsOpenCL.cl | 5 +++++ clang/test/Misc/nvptx.languageOptsOpenCL.cl | 5 +++++ clang/test/Misc/r600.languageOptsOpenCL.cl | 5 +++++ clang/test/SemaOpenCL/extension-version.cl | 5 +++++ clang/test/SemaOpenCL/func.cl | 21 +++++++++++++++++---- 10 files changed, 66 insertions(+), 4 deletions(-) diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index fd011b1..0c01a2b 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1773,6 +1773,31 @@ correctly in any circumstances. It can be used if: 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 +`_. + +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 ================= diff --git a/clang/include/clang/Basic/OpenCLExtensions.def b/clang/include/clang/Basic/OpenCLExtensions.def index 149594e..9353be1 100644 --- a/clang/include/clang/Basic/OpenCLExtensions.def +++ b/clang/include/clang/Basic/OpenCLExtensions.def @@ -70,6 +70,7 @@ 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) diff --git a/clang/lib/Basic/Targets/AMDGPU.h b/clang/lib/Basic/Targets/AMDGPU.h index 3fdbf32..fba1e42 100644 --- a/clang/lib/Basic/Targets/AMDGPU.h +++ b/clang/lib/Basic/Targets/AMDGPU.h @@ -286,6 +286,7 @@ public: 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()); diff --git a/clang/lib/Basic/Targets/NVPTX.h b/clang/lib/Basic/Targets/NVPTX.h index 8e0da65..c4320e8 100644 --- a/clang/lib/Basic/Targets/NVPTX.h +++ b/clang/lib/Basic/Targets/NVPTX.h @@ -129,6 +129,7 @@ public: 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"); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 31018dc..f51c616 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -5019,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)) || diff --git a/clang/test/Misc/amdgcn.languageOptsOpenCL.cl b/clang/test/Misc/amdgcn.languageOptsOpenCL.cl index f86195c..1dd3102 100644 --- a/clang/test/Misc/amdgcn.languageOptsOpenCL.cl +++ b/clang/test/Misc/amdgcn.languageOptsOpenCL.cl @@ -19,6 +19,11 @@ #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" #endif diff --git a/clang/test/Misc/nvptx.languageOptsOpenCL.cl b/clang/test/Misc/nvptx.languageOptsOpenCL.cl index 05aa971..2e99e4e 100644 --- a/clang/test/Misc/nvptx.languageOptsOpenCL.cl +++ b/clang/test/Misc/nvptx.languageOptsOpenCL.cl @@ -27,6 +27,11 @@ #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" #endif diff --git a/clang/test/Misc/r600.languageOptsOpenCL.cl b/clang/test/Misc/r600.languageOptsOpenCL.cl index 2b93e53..253e4fd 100644 --- a/clang/test/Misc/r600.languageOptsOpenCL.cl +++ b/clang/test/Misc/r600.languageOptsOpenCL.cl @@ -35,6 +35,11 @@ #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" #endif diff --git a/clang/test/SemaOpenCL/extension-version.cl b/clang/test/SemaOpenCL/extension-version.cl index e7a2150..b997a00 100644 --- a/clang/test/SemaOpenCL/extension-version.cl +++ b/clang/test/SemaOpenCL/extension-version.cl @@ -24,6 +24,11 @@ #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" #endif diff --git a/clang/test/SemaOpenCL/func.cl b/clang/test/SemaOpenCL/func.cl index 0ba5f73..8a9c202 100644 --- a/clang/test/SemaOpenCL/func.cl +++ b/clang/test/SemaOpenCL/func.cl @@ -1,18 +1,31 @@ // 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}} +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@-2 {{pointers to functions are not allowed}} +// 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 -int printf(__constant const char *st, ...); // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}} // Struct type with function pointer field typedef struct s -- 2.7.4