[OpenCL] Add clang extension for variadic functions.
authorAnastasia Stulova <anastasia.stulova@arm.com>
Wed, 6 Jan 2021 19:30:04 +0000 (19:30 +0000)
committerAnastasia Stulova <anastasia.stulova@arm.com>
Wed, 6 Jan 2021 20:39:57 +0000 (20:39 +0000)
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
clang/include/clang/Basic/OpenCLExtensions.def
clang/lib/Basic/Targets/AMDGPU.h
clang/lib/Basic/Targets/NVPTX.h
clang/lib/Sema/SemaType.cpp
clang/test/Misc/amdgcn.languageOptsOpenCL.cl
clang/test/Misc/nvptx.languageOptsOpenCL.cl
clang/test/Misc/r600.languageOptsOpenCL.cl
clang/test/SemaOpenCL/extension-version.cl
clang/test/SemaOpenCL/func.cl

index fd011b101b6e2545a1aabaf8cf92d5eddc63f200..0c01a2bbc52b27ce85e0e717f7585bd15400daf9 100644 (file)
@@ -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
+<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
 =================
index 149594ed40b049c0d58e0b0825bea2a6b4039797..9353be1753b08dcb365c4787ee3eedf9b51938d5 100644 (file)
@@ -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)
index 3fdbf320a329446c782a4c8db71060d23f4c419e..fba1e4288ed1327033cd80e1e6bb197825c12831 100644 (file)
@@ -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());
 
index 8e0da6554708dcef89e767b8540c5a5b3a6ce6b0..c4320e86e0dbb59ff6bf8ca74623f77207b414cb 100644 (file)
@@ -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");
index 31018dc1d0e7bb02fd2d3e8f63acf471f55c1597..f51c616169f55cdbe8fcf2004dc145a367fde3c9 100644 (file)
@@ -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)) ||
index f86195ce75ab1bbe1fcd92d422f1d981eec15ec8..1dd31029d73498a346692bea5f35d95e11db0ccb 100644 (file)
 #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
index 05aa971ca27710ecafb01fa9a1a7764538cb3b6f..2e99e4ee7337de029357c3caf70fe9ad799f1ddf 100644 (file)
 #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
index 2b93e53ee34c4e21a09076eebace33b5406544b3..253e4fdcbc595cfad06c67eb6e748160114d680f 100644 (file)
 #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
index e7a2150b9918086460f6acebbd2b6897ca1cf504..b997a00145ef03ee215bdeaae31d46de96fb70b4 100644 (file)
 #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
index 0ba5f73486fa35b970328611c7fc0af359696f62..8a9c20289f59211ee3f612c53445a42a477da92e 100644 (file)
@@ -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