mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-16 13:08:42 +00:00
Recommit r289979 [OpenCL] Allow disabling types and declarations associated with extensions
Fixed undefined behavior due to cast integer to bool in initializer list. llvm-svn: 290056
This commit is contained in:
parent
2baef8f466
commit
5b74665a41
@ -968,8 +968,10 @@ def err_opencl_unroll_hint_on_non_loop : Error<
|
||||
// OpenCL EXTENSION pragma (OpenCL 1.1 [9.1])
|
||||
def warn_pragma_expected_colon : Warning<
|
||||
"missing ':' after %0 - ignoring">, InGroup<IgnoredPragmas>;
|
||||
def warn_pragma_expected_enable_disable : Warning<
|
||||
"expected 'enable' or 'disable' - ignoring">, InGroup<IgnoredPragmas>;
|
||||
def warn_pragma_expected_predicate : Warning<
|
||||
"expected %select{'enable', 'disable', 'begin' or 'end'|'disable'}0 - ignoring">, InGroup<IgnoredPragmas>;
|
||||
def warn_pragma_begin_end_mismatch : Warning<
|
||||
"OpenCL extension end directive mismatches begin directive - ignoring">, InGroup<IgnoredPragmas>;
|
||||
def warn_pragma_unknown_extension : Warning<
|
||||
"unknown OpenCL extension %0 - ignoring">, InGroup<IgnoredPragmas>;
|
||||
def warn_pragma_unsupported_extension : Warning<
|
||||
|
@ -3359,6 +3359,8 @@ def note_ovl_candidate_has_pass_object_size_params: Note<
|
||||
"pass_object_size attribute">;
|
||||
def note_ovl_candidate_disabled_by_enable_if_attr : Note<
|
||||
"candidate disabled: %0">;
|
||||
def note_ovl_candidate_disabled_by_extension : Note<
|
||||
"candidate disabled due to OpenCL extension">;
|
||||
def err_addrof_function_disabled_by_enable_if_attr : Error<
|
||||
"cannot take address of function %0 becuase it has one or more "
|
||||
"non-tautological enable_if conditions">;
|
||||
@ -7936,8 +7938,6 @@ def ext_c99_array_usage : Extension<
|
||||
def err_c99_array_usage_cxx : Error<
|
||||
"%select{qualifier in |static |}0array size %select{||'[*] '}0is a C99 "
|
||||
"feature, not permitted in C++">;
|
||||
def err_type_requires_extension : Error<
|
||||
"use of type %0 requires %1 extension to be enabled">;
|
||||
def err_type_unsupported : Error<
|
||||
"%0 is not supported on this target">;
|
||||
def err_nsconsumed_attribute_mismatch : Error<
|
||||
@ -8143,6 +8143,8 @@ def warn_opencl_attr_deprecated_ignored : Warning <
|
||||
InGroup<IgnoredAttributes>;
|
||||
def err_opencl_variadic_function : Error<
|
||||
"invalid prototype, variadic arguments are not allowed in OpenCL">;
|
||||
def err_opencl_requires_extension : Error<
|
||||
"use of %select{type |declaration}0%1 requires %2 extension to be enabled">;
|
||||
|
||||
// OpenCL v2.0 s6.13.6 -- Builtin Pipe Functions
|
||||
def err_opencl_builtin_pipe_first_arg : Error<
|
||||
|
@ -7,73 +7,79 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// This file extends builtin types database with OpenCL image singleton types.
|
||||
// Custom code should define one of those two macros:
|
||||
// GENERIC_IMAGE_TYPE(Type, Id) - a generic image with its Id without an
|
||||
// Custom code should define one of those three macros:
|
||||
// GENERIC_IMAGE_TYPE(Type, Id) - a generic image with its Id without an
|
||||
// access type
|
||||
// IMAGE_TYPE(Type, Id, SingletonId, AccessType, CGSuffix) - an image type
|
||||
// with given ID, singleton ID access type and a codegen suffix
|
||||
// with given ID, singleton ID access type and a codegen suffix
|
||||
// GENERIC_IMAGE_TYPE_EXT(Type, Id, Ext) - a generic image with its Id and
|
||||
// required extension without an access type
|
||||
|
||||
#ifdef GENERIC_IMAGE_TYPE
|
||||
|
||||
#define IMAGE_READ_TYPE(Type, Id) GENERIC_IMAGE_TYPE(Type, Id)
|
||||
#define IMAGE_WRITE_TYPE(Type, Id)
|
||||
#define IMAGE_READ_WRITE_TYPE(Type, Id)
|
||||
#define IMAGE_READ_TYPE(Type, Id, Ext) GENERIC_IMAGE_TYPE(Type, Id)
|
||||
#define IMAGE_WRITE_TYPE(Type, Id, Ext)
|
||||
#define IMAGE_READ_WRITE_TYPE(Type, Id, Ext)
|
||||
|
||||
#elif defined(GENERIC_IMAGE_TYPE_EXT)
|
||||
#define IMAGE_READ_TYPE(Type, Id, Ext) GENERIC_IMAGE_TYPE_EXT(Type, Id##ROTy, Ext)
|
||||
#define IMAGE_WRITE_TYPE(Type, Id, Ext) GENERIC_IMAGE_TYPE_EXT(Type, Id##WOTy, Ext)
|
||||
#define IMAGE_READ_WRITE_TYPE(Type, Id, Ext) GENERIC_IMAGE_TYPE_EXT(Type, Id##RWTy, Ext)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef IMAGE_READ_TYPE
|
||||
#define IMAGE_READ_TYPE(Type, Id) \
|
||||
#define IMAGE_READ_TYPE(Type, Id, Ext) \
|
||||
IMAGE_TYPE(Type, Id##RO, Id##ROTy, read_only, ro)
|
||||
#endif
|
||||
#ifndef IMAGE_WRITE_TYPE
|
||||
#define IMAGE_WRITE_TYPE(Type, Id) \
|
||||
#define IMAGE_WRITE_TYPE(Type, Id, Ext) \
|
||||
IMAGE_TYPE(Type, Id##WO, Id##WOTy, write_only, wo)
|
||||
#endif
|
||||
#ifndef IMAGE_READ_WRITE_TYPE
|
||||
#define IMAGE_READ_WRITE_TYPE(Type, Id) \
|
||||
#define IMAGE_READ_WRITE_TYPE(Type, Id, Ext) \
|
||||
IMAGE_TYPE(Type, Id##RW, Id##RWTy, read_write, rw)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
IMAGE_READ_TYPE(image1d, OCLImage1d)
|
||||
IMAGE_READ_TYPE(image1d_array, OCLImage1dArray)
|
||||
IMAGE_READ_TYPE(image1d_buffer, OCLImage1dBuffer)
|
||||
IMAGE_READ_TYPE(image2d, OCLImage2d)
|
||||
IMAGE_READ_TYPE(image2d_array, OCLImage2dArray)
|
||||
IMAGE_READ_TYPE(image2d_depth, OCLImage2dDepth)
|
||||
IMAGE_READ_TYPE(image2d_array_depth, OCLImage2dArrayDepth)
|
||||
IMAGE_READ_TYPE(image2d_msaa, OCLImage2dMSAA)
|
||||
IMAGE_READ_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA)
|
||||
IMAGE_READ_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth)
|
||||
IMAGE_READ_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth)
|
||||
IMAGE_READ_TYPE(image3d, OCLImage3d)
|
||||
IMAGE_READ_TYPE(image1d, OCLImage1d, "")
|
||||
IMAGE_READ_TYPE(image1d_array, OCLImage1dArray, "")
|
||||
IMAGE_READ_TYPE(image1d_buffer, OCLImage1dBuffer, "")
|
||||
IMAGE_READ_TYPE(image2d, OCLImage2d, "")
|
||||
IMAGE_READ_TYPE(image2d_array, OCLImage2dArray, "")
|
||||
IMAGE_READ_TYPE(image2d_depth, OCLImage2dDepth, "")
|
||||
IMAGE_READ_TYPE(image2d_array_depth, OCLImage2dArrayDepth, "")
|
||||
IMAGE_READ_TYPE(image2d_msaa, OCLImage2dMSAA, "cl_khr_gl_msaa_sharing")
|
||||
IMAGE_READ_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA, "cl_khr_gl_msaa_sharing")
|
||||
IMAGE_READ_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth, "cl_khr_gl_msaa_sharing")
|
||||
IMAGE_READ_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth, "cl_khr_gl_msaa_sharing")
|
||||
IMAGE_READ_TYPE(image3d, OCLImage3d, "")
|
||||
|
||||
IMAGE_WRITE_TYPE(image1d, OCLImage1d)
|
||||
IMAGE_WRITE_TYPE(image1d_array, OCLImage1dArray)
|
||||
IMAGE_WRITE_TYPE(image1d_buffer, OCLImage1dBuffer)
|
||||
IMAGE_WRITE_TYPE(image2d, OCLImage2d)
|
||||
IMAGE_WRITE_TYPE(image2d_array, OCLImage2dArray)
|
||||
IMAGE_WRITE_TYPE(image2d_depth, OCLImage2dDepth)
|
||||
IMAGE_WRITE_TYPE(image2d_array_depth, OCLImage2dArrayDepth)
|
||||
IMAGE_WRITE_TYPE(image2d_msaa, OCLImage2dMSAA)
|
||||
IMAGE_WRITE_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA)
|
||||
IMAGE_WRITE_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth)
|
||||
IMAGE_WRITE_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth)
|
||||
IMAGE_WRITE_TYPE(image3d, OCLImage3d)
|
||||
IMAGE_WRITE_TYPE(image1d, OCLImage1d, "")
|
||||
IMAGE_WRITE_TYPE(image1d_array, OCLImage1dArray, "")
|
||||
IMAGE_WRITE_TYPE(image1d_buffer, OCLImage1dBuffer, "")
|
||||
IMAGE_WRITE_TYPE(image2d, OCLImage2d, "")
|
||||
IMAGE_WRITE_TYPE(image2d_array, OCLImage2dArray, "")
|
||||
IMAGE_WRITE_TYPE(image2d_depth, OCLImage2dDepth, "")
|
||||
IMAGE_WRITE_TYPE(image2d_array_depth, OCLImage2dArrayDepth, "")
|
||||
IMAGE_WRITE_TYPE(image2d_msaa, OCLImage2dMSAA, "cl_khr_gl_msaa_sharing")
|
||||
IMAGE_WRITE_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA, "cl_khr_gl_msaa_sharing")
|
||||
IMAGE_WRITE_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth, "cl_khr_gl_msaa_sharing")
|
||||
IMAGE_WRITE_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth, "cl_khr_gl_msaa_sharing")
|
||||
IMAGE_WRITE_TYPE(image3d, OCLImage3d, "")
|
||||
|
||||
IMAGE_READ_WRITE_TYPE(image1d, OCLImage1d)
|
||||
IMAGE_READ_WRITE_TYPE(image1d_array, OCLImage1dArray)
|
||||
IMAGE_READ_WRITE_TYPE(image1d_buffer, OCLImage1dBuffer)
|
||||
IMAGE_READ_WRITE_TYPE(image2d, OCLImage2d)
|
||||
IMAGE_READ_WRITE_TYPE(image2d_array, OCLImage2dArray)
|
||||
IMAGE_READ_WRITE_TYPE(image2d_depth, OCLImage2dDepth)
|
||||
IMAGE_READ_WRITE_TYPE(image2d_array_depth, OCLImage2dArrayDepth)
|
||||
IMAGE_READ_WRITE_TYPE(image2d_msaa, OCLImage2dMSAA)
|
||||
IMAGE_READ_WRITE_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA)
|
||||
IMAGE_READ_WRITE_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth)
|
||||
IMAGE_READ_WRITE_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth)
|
||||
IMAGE_READ_WRITE_TYPE(image3d, OCLImage3d)
|
||||
IMAGE_READ_WRITE_TYPE(image1d, OCLImage1d, "")
|
||||
IMAGE_READ_WRITE_TYPE(image1d_array, OCLImage1dArray, "")
|
||||
IMAGE_READ_WRITE_TYPE(image1d_buffer, OCLImage1dBuffer, "")
|
||||
IMAGE_READ_WRITE_TYPE(image2d, OCLImage2d, "")
|
||||
IMAGE_READ_WRITE_TYPE(image2d_array, OCLImage2dArray, "")
|
||||
IMAGE_READ_WRITE_TYPE(image2d_depth, OCLImage2dDepth, "")
|
||||
IMAGE_READ_WRITE_TYPE(image2d_array_depth, OCLImage2dArrayDepth, "")
|
||||
IMAGE_READ_WRITE_TYPE(image2d_msaa, OCLImage2dMSAA, "cl_khr_gl_msaa_sharing")
|
||||
IMAGE_READ_WRITE_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA, "cl_khr_gl_msaa_sharing")
|
||||
IMAGE_READ_WRITE_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth, "cl_khr_gl_msaa_sharing")
|
||||
IMAGE_READ_WRITE_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth, "cl_khr_gl_msaa_sharing")
|
||||
IMAGE_READ_WRITE_TYPE(image3d, OCLImage3d, "")
|
||||
|
||||
#undef IMAGE_TYPE
|
||||
#undef GENERIC_IMAGE_TYPE
|
||||
|
@ -15,81 +15,122 @@
|
||||
#ifndef LLVM_CLANG_BASIC_OPENCLOPTIONS_H
|
||||
#define LLVM_CLANG_BASIC_OPENCLOPTIONS_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
/// \brief OpenCL supported extensions and optional core features
|
||||
class OpenCLOptions {
|
||||
struct Info {
|
||||
bool Supported; // Is this option supported
|
||||
bool Enabled; // Is this option enabled
|
||||
unsigned Avail; // Option starts to be available in this OpenCL version
|
||||
unsigned Core; // Option becomes (optional) core feature in this OpenCL
|
||||
// version
|
||||
Info(bool S = false, bool E = false, unsigned A = 100, unsigned C = ~0U)
|
||||
:Supported(S), Enabled(E), Avail(A), Core(C){}
|
||||
};
|
||||
llvm::StringMap<Info> OptMap;
|
||||
public:
|
||||
#define OPENCLEXT(nm) unsigned nm : 1;
|
||||
#include "clang/Basic/OpenCLExtensions.def"
|
||||
|
||||
OpenCLOptions() {
|
||||
#define OPENCLEXT(nm) nm = 0;
|
||||
#include "clang/Basic/OpenCLExtensions.def"
|
||||
bool isKnown(StringRef Ext) const {
|
||||
return OptMap.find(Ext) != OptMap.end();
|
||||
}
|
||||
|
||||
// Enable or disable all options.
|
||||
void setAll(bool Enable = true) {
|
||||
#define OPENCLEXT(nm) nm = Enable;
|
||||
#include "clang/Basic/OpenCLExtensions.def"
|
||||
bool isEnabled(StringRef Ext) const {
|
||||
return OptMap.find(Ext)->second.Enabled;
|
||||
}
|
||||
|
||||
// Is supported as either an extension or an (optional) core feature for
|
||||
// OpenCL version \p CLVer.
|
||||
bool isSupported(StringRef Ext, unsigned CLVer) const {
|
||||
auto I = OptMap.find(Ext)->getValue();
|
||||
return I.Supported && I.Avail <= CLVer;
|
||||
}
|
||||
|
||||
// Is supported (optional) OpenCL core features for OpenCL version \p CLVer.
|
||||
// For supported extension, return false.
|
||||
bool isSupportedCore(StringRef Ext, unsigned CLVer) const {
|
||||
auto I = OptMap.find(Ext)->getValue();
|
||||
return I.Supported && I.Avail <= CLVer &&
|
||||
I.Core != ~0U && CLVer >= I.Core;
|
||||
}
|
||||
|
||||
// Is supported OpenCL extension for OpenCL version \p CLVer.
|
||||
// For supported (optional) core feature, return false.
|
||||
bool isSupportedExtension(StringRef Ext, unsigned CLVer) const {
|
||||
auto I = OptMap.find(Ext)->getValue();
|
||||
return I.Supported && I.Avail <= CLVer &&
|
||||
(I.Core == ~0U || CLVer < I.Core);
|
||||
}
|
||||
|
||||
void enable(StringRef Ext, bool V = true) {
|
||||
OptMap[Ext].Enabled = V;
|
||||
}
|
||||
|
||||
/// \brief Enable or disable support for OpenCL extensions
|
||||
/// \param Ext name of the extension optionally prefixed with
|
||||
/// '+' or '-'
|
||||
/// \param Enable used when \p Ext is not prefixed by '+' or '-'
|
||||
void set(llvm::StringRef Ext, bool Enable = true) {
|
||||
void support(StringRef Ext, bool V = true) {
|
||||
assert(!Ext.empty() && "Extension is empty.");
|
||||
|
||||
switch (Ext[0]) {
|
||||
case '+':
|
||||
Enable = true;
|
||||
V = true;
|
||||
Ext = Ext.drop_front();
|
||||
break;
|
||||
case '-':
|
||||
Enable = false;
|
||||
V = false;
|
||||
Ext = Ext.drop_front();
|
||||
break;
|
||||
}
|
||||
|
||||
if (Ext.equals("all")) {
|
||||
setAll(Enable);
|
||||
supportAll(V);
|
||||
return;
|
||||
}
|
||||
OptMap[Ext].Supported = V;
|
||||
}
|
||||
|
||||
#define OPENCLEXT(nm) \
|
||||
if (Ext.equals(#nm)) { \
|
||||
nm = Enable; \
|
||||
}
|
||||
OpenCLOptions(){
|
||||
#define OPENCLEXT_INTERNAL(Ext, AvailVer, CoreVer) \
|
||||
OptMap[#Ext].Avail = AvailVer; \
|
||||
OptMap[#Ext].Core = CoreVer;
|
||||
#include "clang/Basic/OpenCLExtensions.def"
|
||||
}
|
||||
|
||||
// Is supported with OpenCL version \p OCLVer.
|
||||
#define OPENCLEXT_INTERNAL(Ext, Avail, ...) \
|
||||
bool is_##Ext##_supported(unsigned OCLVer) const { \
|
||||
return Ext && OCLVer >= Avail; \
|
||||
void addSupport(const OpenCLOptions &Opts) {
|
||||
for (auto &I:Opts.OptMap)
|
||||
if (I.second.Supported)
|
||||
OptMap[I.getKey()].Supported = true;
|
||||
}
|
||||
#include "clang/Basic/OpenCLExtensions.def"
|
||||
|
||||
|
||||
// Is supported OpenCL extension with OpenCL version \p OCLVer.
|
||||
// For supported optional core feature, return false.
|
||||
#define OPENCLEXT_INTERNAL(Ext, Avail, Core) \
|
||||
bool is_##Ext##_supported_extension(unsigned CLVer) const { \
|
||||
return is_##Ext##_supported(CLVer) && (Core == ~0U || CLVer < Core); \
|
||||
void copy(const OpenCLOptions &Opts) {
|
||||
OptMap = Opts.OptMap;
|
||||
}
|
||||
#include "clang/Basic/OpenCLExtensions.def"
|
||||
|
||||
// Is supported OpenCL core features with OpenCL version \p OCLVer.
|
||||
// For supported extension, return false.
|
||||
#define OPENCLEXT_INTERNAL(Ext, Avail, Core) \
|
||||
bool is_##Ext##_supported_core(unsigned CLVer) const { \
|
||||
return is_##Ext##_supported(CLVer) && Core != ~0U && CLVer >= Core; \
|
||||
// Turn on or off support of all options.
|
||||
void supportAll(bool On = true) {
|
||||
for (llvm::StringMap<Info>::iterator I = OptMap.begin(),
|
||||
E = OptMap.end(); I != E; ++I)
|
||||
I->second.Supported = On;
|
||||
}
|
||||
#include "clang/Basic/OpenCLExtensions.def"
|
||||
|
||||
void disableAll() {
|
||||
for (llvm::StringMap<Info>::iterator I = OptMap.begin(),
|
||||
E = OptMap.end(); I != E; ++I)
|
||||
I->second.Enabled = false;
|
||||
}
|
||||
|
||||
void enableSupportedCore(unsigned CLVer) {
|
||||
for (llvm::StringMap<Info>::iterator I = OptMap.begin(),
|
||||
E = OptMap.end(); I != E; ++I)
|
||||
if (isSupportedCore(I->getKey(), CLVer))
|
||||
I->second.Enabled = true;
|
||||
}
|
||||
|
||||
friend class ASTWriter;
|
||||
friend class ASTReader;
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
@ -1005,7 +1005,7 @@ public:
|
||||
/// \brief Set supported OpenCL extensions as written on command line
|
||||
virtual void setOpenCLExtensionOpts() {
|
||||
for (const auto &Ext : getTargetOpts().OpenCLExtensionsAsWritten) {
|
||||
getTargetOpts().SupportedOpenCLOptions.set(Ext);
|
||||
getTargetOpts().SupportedOpenCLOptions.support(Ext);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -592,7 +592,10 @@ namespace clang {
|
||||
ovl_fail_enable_if,
|
||||
|
||||
/// This candidate was not viable because its address could not be taken.
|
||||
ovl_fail_addr_not_available
|
||||
ovl_fail_addr_not_available,
|
||||
|
||||
/// This candidate was not viable because its OpenCL extension is disabled.
|
||||
ovl_fail_ext_disabled,
|
||||
};
|
||||
|
||||
/// OverloadCandidate - A single candidate in an overload set (C++ 13.3).
|
||||
|
@ -8050,6 +8050,58 @@ public:
|
||||
|
||||
void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// OpenCL extensions.
|
||||
//
|
||||
private:
|
||||
std::string CurrOpenCLExtension;
|
||||
/// Extensions required by an OpenCL type.
|
||||
llvm::DenseMap<const Type*, std::set<std::string>> OpenCLTypeExtMap;
|
||||
/// Extensions required by an OpenCL declaration.
|
||||
llvm::DenseMap<const Decl*, std::set<std::string>> OpenCLDeclExtMap;
|
||||
public:
|
||||
llvm::StringRef getCurrentOpenCLExtension() const {
|
||||
return CurrOpenCLExtension;
|
||||
}
|
||||
void setCurrentOpenCLExtension(llvm::StringRef Ext) {
|
||||
CurrOpenCLExtension = Ext;
|
||||
}
|
||||
|
||||
/// \brief Set OpenCL extensions for a type which can only be used when these
|
||||
/// OpenCL extensions are enabled. If \p Exts is empty, do nothing.
|
||||
/// \param Exts A space separated list of OpenCL extensions.
|
||||
void setOpenCLExtensionForType(QualType T, llvm::StringRef Exts);
|
||||
|
||||
/// \brief Set OpenCL extensions for a declaration which can only be
|
||||
/// used when these OpenCL extensions are enabled. If \p Exts is empty, do
|
||||
/// nothing.
|
||||
/// \param Exts A space separated list of OpenCL extensions.
|
||||
void setOpenCLExtensionForDecl(Decl *FD, llvm::StringRef Exts);
|
||||
|
||||
/// \brief Set current OpenCL extensions for a type which can only be used
|
||||
/// when these OpenCL extensions are enabled. If current OpenCL extension is
|
||||
/// empty, do nothing.
|
||||
void setCurrentOpenCLExtensionForType(QualType T);
|
||||
|
||||
/// \brief Set current OpenCL extensions for a declaration which
|
||||
/// can only be used when these OpenCL extensions are enabled. If current
|
||||
/// OpenCL extension is empty, do nothing.
|
||||
void setCurrentOpenCLExtensionForDecl(Decl *FD);
|
||||
|
||||
bool isOpenCLDisabledDecl(Decl *FD);
|
||||
|
||||
/// \brief Check if type \p T corresponding to declaration specifier \p DS
|
||||
/// is disabled due to required OpenCL extensions being disabled. If so,
|
||||
/// emit diagnostics.
|
||||
/// \return true if type is disabled.
|
||||
bool checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType T);
|
||||
|
||||
/// \brief Check if declaration \p D used by expression \p E
|
||||
/// is disabled due to required OpenCL extensions being disabled. If so,
|
||||
/// emit diagnostics.
|
||||
/// \return true if type is disabled.
|
||||
bool checkOpenCLDisabledDecl(const Decl &D, const Expr &E);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// OpenMP directives and clauses.
|
||||
//
|
||||
@ -8066,6 +8118,21 @@ private:
|
||||
/// Returns OpenMP nesting level for current directive.
|
||||
unsigned getOpenMPNestingLevel() const;
|
||||
|
||||
/// Checks if a type or a declaration is disabled due to the owning extension
|
||||
/// being disabled, and emits diagnostic messages if it is disabled.
|
||||
/// \param D type or declaration to be checked.
|
||||
/// \param DiagLoc source location for the diagnostic message.
|
||||
/// \param DiagInfo information to be emitted for the diagnostic message.
|
||||
/// \param SrcRange source range of the declaration.
|
||||
/// \param Map maps type or declaration to the extensions.
|
||||
/// \param Selector selects diagnostic message: 0 for type and 1 for
|
||||
/// declaration.
|
||||
/// \return true if the type or declaration is disabled.
|
||||
template <typename T, typename DiagLocT, typename DiagInfoT, typename MapT>
|
||||
bool checkOpenCLDisabledTypeOrDecl(T D, DiagLocT DiagLoc, DiagInfoT DiagInfo,
|
||||
MapT &Map, unsigned Selector = 0,
|
||||
SourceRange SrcRange = SourceRange());
|
||||
|
||||
public:
|
||||
/// \brief Return true if the provided declaration \a VD should be captured by
|
||||
/// reference.
|
||||
|
@ -344,7 +344,7 @@ namespace clang {
|
||||
///
|
||||
/// The TYPE_OFFSET constant describes the record that occurs
|
||||
/// within the AST block. The record itself is an array of offsets that
|
||||
/// point into the declarations and types block (identified by
|
||||
/// point into the declarations and types block (identified by
|
||||
/// DECLTYPES_BLOCK_ID). The index into the array is based on the ID
|
||||
/// of a type. For a given type ID @c T, the lower three bits of
|
||||
/// @c T are its qualifiers (const, volatile, restrict), as in
|
||||
@ -446,10 +446,10 @@ namespace clang {
|
||||
|
||||
/// \brief Record code for the set of ext_vector type names.
|
||||
EXT_VECTOR_DECLS = 16,
|
||||
|
||||
|
||||
/// \brief Record code for the array of unused file scoped decls.
|
||||
UNUSED_FILESCOPED_DECLS = 17,
|
||||
|
||||
|
||||
/// \brief Record code for the table of offsets to entries in the
|
||||
/// preprocessing record.
|
||||
PPD_ENTITIES_OFFSETS = 18,
|
||||
@ -465,7 +465,7 @@ namespace clang {
|
||||
/// \brief Record code for an update to the TU's lexically contained
|
||||
/// declarations.
|
||||
TU_UPDATE_LEXICAL = 22,
|
||||
|
||||
|
||||
// ID 23 used to be for a list of local redeclarations.
|
||||
|
||||
/// \brief Record code for declarations that Sema keeps references of.
|
||||
@ -490,7 +490,7 @@ namespace clang {
|
||||
|
||||
// ID 30 used to be a decl update record. These are now in the DECLTYPES
|
||||
// block.
|
||||
|
||||
|
||||
// ID 31 used to be a list of offsets to DECL_CXX_BASE_SPECIFIERS records.
|
||||
|
||||
/// \brief Record code for \#pragma diagnostic mappings.
|
||||
@ -498,7 +498,7 @@ namespace clang {
|
||||
|
||||
/// \brief Record code for special CUDA declarations.
|
||||
CUDA_SPECIAL_DECL_REFS = 33,
|
||||
|
||||
|
||||
/// \brief Record code for header search information.
|
||||
HEADER_SEARCH_TABLE = 34,
|
||||
|
||||
@ -516,7 +516,7 @@ namespace clang {
|
||||
KNOWN_NAMESPACES = 38,
|
||||
|
||||
/// \brief Record code for the remapping information used to relate
|
||||
/// loaded modules to the various offsets and IDs(e.g., source location
|
||||
/// loaded modules to the various offsets and IDs(e.g., source location
|
||||
/// offests, declaration and type IDs) that are used in that module to
|
||||
/// refer to other modules.
|
||||
MODULE_OFFSET_MAP = 39,
|
||||
@ -525,20 +525,20 @@ namespace clang {
|
||||
/// which stores information about \#line directives.
|
||||
SOURCE_MANAGER_LINE_TABLE = 40,
|
||||
|
||||
/// \brief Record code for map of Objective-C class definition IDs to the
|
||||
/// \brief Record code for map of Objective-C class definition IDs to the
|
||||
/// ObjC categories in a module that are attached to that class.
|
||||
OBJC_CATEGORIES_MAP = 41,
|
||||
|
||||
/// \brief Record code for a file sorted array of DeclIDs in a module.
|
||||
FILE_SORTED_DECLS = 42,
|
||||
|
||||
|
||||
/// \brief Record code for an array of all of the (sub)modules that were
|
||||
/// imported by the AST file.
|
||||
IMPORTED_MODULES = 43,
|
||||
|
||||
|
||||
// ID 44 used to be a table of merged canonical declarations.
|
||||
// ID 45 used to be a list of declaration IDs of local redeclarations.
|
||||
|
||||
|
||||
/// \brief Record code for the array of Objective-C categories (including
|
||||
/// extensions).
|
||||
///
|
||||
@ -585,6 +585,12 @@ namespace clang {
|
||||
/// \brief Number of unmatched #pragma clang cuda_force_host_device begin
|
||||
/// directives we've seen.
|
||||
CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH = 57,
|
||||
|
||||
/// \brief Record code for types associated with OpenCL extensions.
|
||||
OPENCL_EXTENSION_TYPES = 58,
|
||||
|
||||
/// \brief Record code for declarations associated with OpenCL extensions.
|
||||
OPENCL_EXTENSION_DECLS = 59,
|
||||
};
|
||||
|
||||
/// \brief Record types used within a source manager block.
|
||||
|
@ -807,7 +807,13 @@ private:
|
||||
SourceLocation PointersToMembersPragmaLocation;
|
||||
|
||||
/// \brief The OpenCL extension settings.
|
||||
SmallVector<uint64_t, 1> OpenCLExtensions;
|
||||
OpenCLOptions OpenCLExtensions;
|
||||
|
||||
/// \brief Extensions required by an OpenCL type.
|
||||
llvm::DenseMap<const Type *, std::set<std::string>> OpenCLTypeExtMap;
|
||||
|
||||
/// \brief Extensions required by an OpenCL declaration.
|
||||
llvm::DenseMap<const Decl *, std::set<std::string>> OpenCLDeclExtMap;
|
||||
|
||||
/// \brief A list of the namespaces we've seen.
|
||||
SmallVector<uint64_t, 4> KnownNamespaces;
|
||||
|
@ -459,6 +459,8 @@ private:
|
||||
void WriteDeclContextVisibleUpdate(const DeclContext *DC);
|
||||
void WriteFPPragmaOptions(const FPOptions &Opts);
|
||||
void WriteOpenCLExtensions(Sema &SemaRef);
|
||||
void WriteOpenCLExtensionTypes(Sema &SemaRef);
|
||||
void WriteOpenCLExtensionDecls(Sema &SemaRef);
|
||||
void WriteCUDAPragmas(Sema &SemaRef);
|
||||
void WriteObjCCategories();
|
||||
void WriteLateParsedTemplates(Sema &SemaRef);
|
||||
|
@ -1924,16 +1924,16 @@ public:
|
||||
}
|
||||
void setSupportedOpenCLOpts() override {
|
||||
auto &Opts = getSupportedOpenCLOpts();
|
||||
Opts.cl_clang_storage_class_specifiers = 1;
|
||||
Opts.cl_khr_gl_sharing = 1;
|
||||
Opts.cl_khr_icd = 1;
|
||||
Opts.support("cl_clang_storage_class_specifiers");
|
||||
Opts.support("cl_khr_gl_sharing");
|
||||
Opts.support("cl_khr_icd");
|
||||
|
||||
Opts.cl_khr_fp64 = 1;
|
||||
Opts.cl_khr_byte_addressable_store = 1;
|
||||
Opts.cl_khr_global_int32_base_atomics = 1;
|
||||
Opts.cl_khr_global_int32_extended_atomics = 1;
|
||||
Opts.cl_khr_local_int32_base_atomics = 1;
|
||||
Opts.cl_khr_local_int32_extended_atomics = 1;
|
||||
Opts.support("cl_khr_fp64");
|
||||
Opts.support("cl_khr_byte_addressable_store");
|
||||
Opts.support("cl_khr_global_int32_base_atomics");
|
||||
Opts.support("cl_khr_global_int32_extended_atomics");
|
||||
Opts.support("cl_khr_local_int32_base_atomics");
|
||||
Opts.support("cl_khr_local_int32_extended_atomics");
|
||||
}
|
||||
};
|
||||
|
||||
@ -2208,27 +2208,27 @@ public:
|
||||
|
||||
void setSupportedOpenCLOpts() override {
|
||||
auto &Opts = getSupportedOpenCLOpts();
|
||||
Opts.cl_clang_storage_class_specifiers = 1;
|
||||
Opts.cl_khr_icd = 1;
|
||||
Opts.support("cl_clang_storage_class_specifiers");
|
||||
Opts.support("cl_khr_icd");
|
||||
|
||||
if (hasFP64)
|
||||
Opts.cl_khr_fp64 = 1;
|
||||
Opts.support("cl_khr_fp64");
|
||||
if (GPU >= GK_EVERGREEN) {
|
||||
Opts.cl_khr_byte_addressable_store = 1;
|
||||
Opts.cl_khr_global_int32_base_atomics = 1;
|
||||
Opts.cl_khr_global_int32_extended_atomics = 1;
|
||||
Opts.cl_khr_local_int32_base_atomics = 1;
|
||||
Opts.cl_khr_local_int32_extended_atomics = 1;
|
||||
Opts.support("cl_khr_byte_addressable_store");
|
||||
Opts.support("cl_khr_global_int32_base_atomics");
|
||||
Opts.support("cl_khr_global_int32_extended_atomics");
|
||||
Opts.support("cl_khr_local_int32_base_atomics");
|
||||
Opts.support("cl_khr_local_int32_extended_atomics");
|
||||
}
|
||||
if (GPU >= GK_GFX6) {
|
||||
Opts.cl_khr_fp16 = 1;
|
||||
Opts.cl_khr_int64_base_atomics = 1;
|
||||
Opts.cl_khr_int64_extended_atomics = 1;
|
||||
Opts.cl_khr_mipmap_image = 1;
|
||||
Opts.cl_khr_subgroups = 1;
|
||||
Opts.cl_khr_3d_image_writes = 1;
|
||||
Opts.cl_amd_media_ops = 1;
|
||||
Opts.cl_amd_media_ops2 = 1;
|
||||
Opts.support("cl_khr_fp16");
|
||||
Opts.support("cl_khr_int64_base_atomics");
|
||||
Opts.support("cl_khr_int64_extended_atomics");
|
||||
Opts.support("cl_khr_mipmap_image");
|
||||
Opts.support("cl_khr_subgroups");
|
||||
Opts.support("cl_khr_3d_image_writes");
|
||||
Opts.support("cl_amd_media_ops");
|
||||
Opts.support("cl_amd_media_ops2");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2932,7 +2932,7 @@ public:
|
||||
}
|
||||
|
||||
void setSupportedOpenCLOpts() override {
|
||||
getSupportedOpenCLOpts().setAll();
|
||||
getSupportedOpenCLOpts().supportAll();
|
||||
}
|
||||
};
|
||||
|
||||
@ -8188,7 +8188,7 @@ public:
|
||||
void setSupportedOpenCLOpts() override {
|
||||
// Assume all OpenCL extensions and optional core features are supported
|
||||
// for SPIR since it is a generic target.
|
||||
getSupportedOpenCLOpts().setAll();
|
||||
getSupportedOpenCLOpts().supportAll();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -988,7 +988,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
|
||||
// OpenCL definitions.
|
||||
if (LangOpts.OpenCL) {
|
||||
#define OPENCLEXT(Ext) \
|
||||
if (TI.getSupportedOpenCLOpts().is_##Ext##_supported( \
|
||||
if (TI.getSupportedOpenCLOpts().isSupported(#Ext, \
|
||||
LangOpts.OpenCLVersion)) \
|
||||
Builder.defineMacro(#Ext);
|
||||
#include "clang/Basic/OpenCLExtensions.def"
|
||||
|
@ -15490,6 +15490,10 @@ int printf(__constant const char* st, ...);
|
||||
#define CLK_FILTER_NEAREST 0x10
|
||||
#define CLK_FILTER_LINEAR 0x20
|
||||
|
||||
#ifdef cl_khr_gl_msaa_sharing
|
||||
#pragma OPENCL EXTENSION cl_khr_gl_msaa_sharing : enable
|
||||
#endif //cl_khr_gl_msaa_sharing
|
||||
|
||||
/**
|
||||
* Use the coordinate (coord.xy) to do an element lookup in
|
||||
* the 2D image object specified by image.
|
||||
|
@ -486,42 +486,48 @@ StmtResult Parser::HandlePragmaCaptured()
|
||||
}
|
||||
|
||||
namespace {
|
||||
typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
|
||||
enum OpenCLExtState : char {
|
||||
Disable, Enable, Begin, End
|
||||
};
|
||||
typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
|
||||
}
|
||||
|
||||
void Parser::HandlePragmaOpenCLExtension() {
|
||||
assert(Tok.is(tok::annot_pragma_opencl_extension));
|
||||
OpenCLExtData data =
|
||||
OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
|
||||
unsigned state = data.getInt();
|
||||
IdentifierInfo *ename = data.getPointer();
|
||||
OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
|
||||
auto State = Data->second;
|
||||
auto Ident = Data->first;
|
||||
SourceLocation NameLoc = Tok.getLocation();
|
||||
ConsumeToken(); // The annotation token.
|
||||
|
||||
OpenCLOptions &f = Actions.getOpenCLOptions();
|
||||
auto CLVer = getLangOpts().OpenCLVersion;
|
||||
auto &Supp = getTargetInfo().getSupportedOpenCLOpts();
|
||||
auto &Opt = Actions.getOpenCLOptions();
|
||||
auto Name = Ident->getName();
|
||||
// OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
|
||||
// overriding all previously issued extension directives, but only if the
|
||||
// behavior is set to disable."
|
||||
if (state == 0 && ename->isStr("all")) {
|
||||
#define OPENCLEXT(nm) \
|
||||
if (Supp.is_##nm##_supported_extension(CLVer)) \
|
||||
f.nm = 0;
|
||||
#include "clang/Basic/OpenCLExtensions.def"
|
||||
}
|
||||
#define OPENCLEXT(nm) else if (ename->isStr(#nm)) \
|
||||
if (Supp.is_##nm##_supported_extension(CLVer)) \
|
||||
f.nm = state; \
|
||||
else if (Supp.is_##nm##_supported_core(CLVer)) \
|
||||
PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << ename; \
|
||||
else \
|
||||
PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << ename;
|
||||
#include "clang/Basic/OpenCLExtensions.def"
|
||||
else {
|
||||
PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
|
||||
return;
|
||||
}
|
||||
if (Name == "all") {
|
||||
if (State == Disable)
|
||||
Opt.disableAll();
|
||||
else
|
||||
PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
|
||||
} else if (State == Begin) {
|
||||
if (!Opt.isKnown(Name) ||
|
||||
!Opt.isSupported(Name, getLangOpts().OpenCLVersion)) {
|
||||
Opt.support(Name);
|
||||
}
|
||||
Actions.setCurrentOpenCLExtension(Name);
|
||||
} else if (State == End) {
|
||||
if (Name != Actions.getCurrentOpenCLExtension())
|
||||
PP.Diag(NameLoc, diag::warn_pragma_begin_end_mismatch);
|
||||
Actions.setCurrentOpenCLExtension("");
|
||||
} else if (!Opt.isKnown(Name))
|
||||
PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
|
||||
else if (Opt.isSupportedExtension(Name, getLangOpts().OpenCLVersion))
|
||||
Opt.enable(Name, State == Enable);
|
||||
else if (Opt.isSupportedCore(Name, getLangOpts().OpenCLVersion))
|
||||
PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
|
||||
else
|
||||
PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
|
||||
}
|
||||
|
||||
void Parser::HandlePragmaMSPointersToMembers() {
|
||||
@ -1441,29 +1447,34 @@ PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
|
||||
"OPENCL";
|
||||
return;
|
||||
}
|
||||
IdentifierInfo *ename = Tok.getIdentifierInfo();
|
||||
IdentifierInfo *Ext = Tok.getIdentifierInfo();
|
||||
SourceLocation NameLoc = Tok.getLocation();
|
||||
|
||||
PP.Lex(Tok);
|
||||
if (Tok.isNot(tok::colon)) {
|
||||
PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
|
||||
PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
|
||||
return;
|
||||
}
|
||||
|
||||
PP.Lex(Tok);
|
||||
if (Tok.isNot(tok::identifier)) {
|
||||
PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
|
||||
PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
|
||||
return;
|
||||
}
|
||||
IdentifierInfo *op = Tok.getIdentifierInfo();
|
||||
IdentifierInfo *Pred = Tok.getIdentifierInfo();
|
||||
|
||||
unsigned state;
|
||||
if (op->isStr("enable")) {
|
||||
state = 1;
|
||||
} else if (op->isStr("disable")) {
|
||||
state = 0;
|
||||
} else {
|
||||
PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
|
||||
OpenCLExtState State;
|
||||
if (Pred->isStr("enable")) {
|
||||
State = Enable;
|
||||
} else if (Pred->isStr("disable")) {
|
||||
State = Disable;
|
||||
} else if (Pred->isStr("begin"))
|
||||
State = Begin;
|
||||
else if (Pred->isStr("end"))
|
||||
State = End;
|
||||
else {
|
||||
PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
|
||||
<< Ext->isStr("all");
|
||||
return;
|
||||
}
|
||||
SourceLocation StateLoc = Tok.getLocation();
|
||||
@ -1475,19 +1486,21 @@ PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
|
||||
return;
|
||||
}
|
||||
|
||||
OpenCLExtData data(ename, state);
|
||||
auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
|
||||
Info->first = Ext;
|
||||
Info->second = State;
|
||||
MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
|
||||
1);
|
||||
Toks[0].startToken();
|
||||
Toks[0].setKind(tok::annot_pragma_opencl_extension);
|
||||
Toks[0].setLocation(NameLoc);
|
||||
Toks[0].setAnnotationValue(data.getOpaqueValue());
|
||||
Toks[0].setAnnotationValue(static_cast<void*>(Info));
|
||||
Toks[0].setAnnotationEndLoc(StateLoc);
|
||||
PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
|
||||
|
||||
if (PP.getPPCallbacks())
|
||||
PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
|
||||
StateLoc, state);
|
||||
PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
|
||||
StateLoc, State);
|
||||
}
|
||||
|
||||
/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
|
||||
|
@ -934,6 +934,8 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
|
||||
Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none,
|
||||
DS, AnonRecord);
|
||||
DS.complete(TheDecl);
|
||||
if (getLangOpts().OpenCL)
|
||||
Actions.setCurrentOpenCLExtensionForDecl(TheDecl);
|
||||
if (AnonRecord) {
|
||||
Decl* decls[] = {AnonRecord, TheDecl};
|
||||
return Actions.BuildDeclaratorGroup(decls, /*TypeMayContainAuto=*/false);
|
||||
|
@ -558,7 +558,7 @@ bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc,
|
||||
// OpenCL v1.2 s6.8 changes this to "The auto and register storage-class
|
||||
// specifiers are not supported."
|
||||
if (S.getLangOpts().OpenCL &&
|
||||
!S.getOpenCLOptions().cl_clang_storage_class_specifiers) {
|
||||
!S.getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers")) {
|
||||
switch (SC) {
|
||||
case SCS_extern:
|
||||
case SCS_private_extern:
|
||||
|
@ -207,14 +207,11 @@ void Sema::Initialize() {
|
||||
addImplicitTypedef("size_t", Context.getSizeType());
|
||||
}
|
||||
|
||||
// Initialize predefined OpenCL types and supported optional core features.
|
||||
// Initialize predefined OpenCL types and supported extensions and (optional)
|
||||
// core features.
|
||||
if (getLangOpts().OpenCL) {
|
||||
#define OPENCLEXT(Ext) \
|
||||
if (Context.getTargetInfo().getSupportedOpenCLOpts().is_##Ext##_supported_core( \
|
||||
getLangOpts().OpenCLVersion)) \
|
||||
getOpenCLOptions().Ext = 1;
|
||||
#include "clang/Basic/OpenCLExtensions.def"
|
||||
|
||||
getOpenCLOptions().addSupport(Context.getTargetInfo().getSupportedOpenCLOpts());
|
||||
getOpenCLOptions().enableSupportedCore(getLangOpts().OpenCLVersion);
|
||||
addImplicitTypedef("sampler_t", Context.OCLSamplerTy);
|
||||
addImplicitTypedef("event_t", Context.OCLEventTy);
|
||||
if (getLangOpts().OpenCLVersion >= 200) {
|
||||
@ -225,26 +222,60 @@ void Sema::Initialize() {
|
||||
addImplicitTypedef("atomic_int", Context.getAtomicType(Context.IntTy));
|
||||
addImplicitTypedef("atomic_uint",
|
||||
Context.getAtomicType(Context.UnsignedIntTy));
|
||||
addImplicitTypedef("atomic_long", Context.getAtomicType(Context.LongTy));
|
||||
addImplicitTypedef("atomic_ulong",
|
||||
Context.getAtomicType(Context.UnsignedLongTy));
|
||||
auto AtomicLongT = Context.getAtomicType(Context.LongTy);
|
||||
addImplicitTypedef("atomic_long", AtomicLongT);
|
||||
auto AtomicULongT = Context.getAtomicType(Context.UnsignedLongTy);
|
||||
addImplicitTypedef("atomic_ulong", AtomicULongT);
|
||||
addImplicitTypedef("atomic_float",
|
||||
Context.getAtomicType(Context.FloatTy));
|
||||
addImplicitTypedef("atomic_double",
|
||||
Context.getAtomicType(Context.DoubleTy));
|
||||
auto AtomicDoubleT = Context.getAtomicType(Context.DoubleTy);
|
||||
addImplicitTypedef("atomic_double", AtomicDoubleT);
|
||||
// OpenCLC v2.0, s6.13.11.6 requires that atomic_flag is implemented as
|
||||
// 32-bit integer and OpenCLC v2.0, s6.1.1 int is always 32-bit wide.
|
||||
addImplicitTypedef("atomic_flag", Context.getAtomicType(Context.IntTy));
|
||||
addImplicitTypedef("atomic_intptr_t",
|
||||
Context.getAtomicType(Context.getIntPtrType()));
|
||||
addImplicitTypedef("atomic_uintptr_t",
|
||||
Context.getAtomicType(Context.getUIntPtrType()));
|
||||
addImplicitTypedef("atomic_size_t",
|
||||
Context.getAtomicType(Context.getSizeType()));
|
||||
addImplicitTypedef("atomic_ptrdiff_t",
|
||||
Context.getAtomicType(Context.getPointerDiffType()));
|
||||
auto AtomicIntPtrT = Context.getAtomicType(Context.getIntPtrType());
|
||||
addImplicitTypedef("atomic_intptr_t", AtomicIntPtrT);
|
||||
auto AtomicUIntPtrT = Context.getAtomicType(Context.getUIntPtrType());
|
||||
addImplicitTypedef("atomic_uintptr_t", AtomicUIntPtrT);
|
||||
auto AtomicSizeT = Context.getAtomicType(Context.getSizeType());
|
||||
addImplicitTypedef("atomic_size_t", AtomicSizeT);
|
||||
auto AtomicPtrDiffT = Context.getAtomicType(Context.getPointerDiffType());
|
||||
addImplicitTypedef("atomic_ptrdiff_t", AtomicPtrDiffT);
|
||||
|
||||
// OpenCL v2.0 s6.13.11.6:
|
||||
// - The atomic_long and atomic_ulong types are supported if the
|
||||
// cl_khr_int64_base_atomics and cl_khr_int64_extended_atomics
|
||||
// extensions are supported.
|
||||
// - The atomic_double type is only supported if double precision
|
||||
// is supported and the cl_khr_int64_base_atomics and
|
||||
// cl_khr_int64_extended_atomics extensions are supported.
|
||||
// - If the device address space is 64-bits, the data types
|
||||
// atomic_intptr_t, atomic_uintptr_t, atomic_size_t and
|
||||
// atomic_ptrdiff_t are supported if the cl_khr_int64_base_atomics and
|
||||
// cl_khr_int64_extended_atomics extensions are supported.
|
||||
std::vector<QualType> Atomic64BitTypes;
|
||||
Atomic64BitTypes.push_back(AtomicLongT);
|
||||
Atomic64BitTypes.push_back(AtomicULongT);
|
||||
Atomic64BitTypes.push_back(AtomicDoubleT);
|
||||
if (Context.getTypeSize(AtomicSizeT) == 64) {
|
||||
Atomic64BitTypes.push_back(AtomicSizeT);
|
||||
Atomic64BitTypes.push_back(AtomicIntPtrT);
|
||||
Atomic64BitTypes.push_back(AtomicUIntPtrT);
|
||||
Atomic64BitTypes.push_back(AtomicPtrDiffT);
|
||||
}
|
||||
for (auto &I : Atomic64BitTypes)
|
||||
setOpenCLExtensionForType(I,
|
||||
"cl_khr_int64_base_atomics cl_khr_int64_extended_atomics");
|
||||
|
||||
setOpenCLExtensionForType(AtomicDoubleT, "cl_khr_fp64");
|
||||
}
|
||||
}
|
||||
|
||||
setOpenCLExtensionForType(Context.DoubleTy, "cl_khr_fp64");
|
||||
|
||||
#define GENERIC_IMAGE_TYPE_EXT(Type, Id, Ext) \
|
||||
setOpenCLExtensionForType(Context.Id, Ext);
|
||||
#include "clang/Basic/OpenCLImageTypes.def"
|
||||
};
|
||||
|
||||
if (Context.getTargetInfo().hasBuiltinMSVaList()) {
|
||||
DeclarationName MSVaList = &Context.Idents.get("__builtin_ms_va_list");
|
||||
@ -1542,3 +1573,85 @@ const llvm::MapVector<FieldDecl *, Sema::DeleteLocs> &
|
||||
Sema::getMismatchingDeleteExpressions() const {
|
||||
return DeleteExprs;
|
||||
}
|
||||
|
||||
void Sema::setOpenCLExtensionForType(QualType T, llvm::StringRef ExtStr) {
|
||||
if (ExtStr.empty())
|
||||
return;
|
||||
llvm::SmallVector<StringRef, 1> Exts;
|
||||
ExtStr.split(Exts, " ", /* limit */ -1, /* keep empty */ false);
|
||||
auto CanT = T.getCanonicalType().getTypePtr();
|
||||
for (auto &I : Exts)
|
||||
OpenCLTypeExtMap[CanT].insert(I.str());
|
||||
}
|
||||
|
||||
void Sema::setOpenCLExtensionForDecl(Decl *FD, StringRef ExtStr) {
|
||||
llvm::SmallVector<StringRef, 1> Exts;
|
||||
ExtStr.split(Exts, " ", /* limit */ -1, /* keep empty */ false);
|
||||
if (Exts.empty())
|
||||
return;
|
||||
for (auto &I : Exts)
|
||||
OpenCLDeclExtMap[FD].insert(I.str());
|
||||
}
|
||||
|
||||
void Sema::setCurrentOpenCLExtensionForType(QualType T) {
|
||||
if (CurrOpenCLExtension.empty())
|
||||
return;
|
||||
setOpenCLExtensionForType(T, CurrOpenCLExtension);
|
||||
}
|
||||
|
||||
void Sema::setCurrentOpenCLExtensionForDecl(Decl *D) {
|
||||
if (CurrOpenCLExtension.empty())
|
||||
return;
|
||||
setOpenCLExtensionForDecl(D, CurrOpenCLExtension);
|
||||
}
|
||||
|
||||
bool Sema::isOpenCLDisabledDecl(Decl *FD) {
|
||||
auto Loc = OpenCLDeclExtMap.find(FD);
|
||||
if (Loc == OpenCLDeclExtMap.end())
|
||||
return false;
|
||||
for (auto &I : Loc->second) {
|
||||
if (!getOpenCLOptions().isEnabled(I))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T, typename DiagLocT, typename DiagInfoT, typename MapT>
|
||||
bool Sema::checkOpenCLDisabledTypeOrDecl(T D, DiagLocT DiagLoc,
|
||||
DiagInfoT DiagInfo, MapT &Map,
|
||||
unsigned Selector,
|
||||
SourceRange SrcRange) {
|
||||
auto Loc = Map.find(D);
|
||||
if (Loc == Map.end())
|
||||
return false;
|
||||
bool Disabled = false;
|
||||
for (auto &I : Loc->second) {
|
||||
if (I != CurrOpenCLExtension && !getOpenCLOptions().isEnabled(I)) {
|
||||
Diag(DiagLoc, diag::err_opencl_requires_extension) << Selector << DiagInfo
|
||||
<< I << SrcRange;
|
||||
Disabled = true;
|
||||
}
|
||||
}
|
||||
return Disabled;
|
||||
}
|
||||
|
||||
bool Sema::checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType QT) {
|
||||
// Check extensions for declared types.
|
||||
Decl *Decl = nullptr;
|
||||
if (auto TypedefT = dyn_cast<TypedefType>(QT.getTypePtr()))
|
||||
Decl = TypedefT->getDecl();
|
||||
if (auto TagT = dyn_cast<TagType>(QT.getCanonicalType().getTypePtr()))
|
||||
Decl = TagT->getDecl();
|
||||
auto Loc = DS.getTypeSpecTypeLoc();
|
||||
if (checkOpenCLDisabledTypeOrDecl(Decl, Loc, QT, OpenCLDeclExtMap))
|
||||
return true;
|
||||
|
||||
// Check extensions for builtin types.
|
||||
return checkOpenCLDisabledTypeOrDecl(QT.getCanonicalType().getTypePtr(), Loc,
|
||||
QT, OpenCLTypeExtMap);
|
||||
}
|
||||
|
||||
bool Sema::checkOpenCLDisabledDecl(const Decl &D, const Expr &E) {
|
||||
return checkOpenCLDisabledTypeOrDecl(&D, E.getLocStart(), "",
|
||||
OpenCLDeclExtMap, 1, D.getSourceRange());
|
||||
}
|
||||
|
@ -2529,7 +2529,8 @@ void CastOperation::CheckCStyleCast() {
|
||||
}
|
||||
}
|
||||
|
||||
if (Self.getLangOpts().OpenCL && !Self.getOpenCLOptions().cl_khr_fp16) {
|
||||
if (Self.getLangOpts().OpenCL &&
|
||||
!Self.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
|
||||
if (DestType->isHalfType()) {
|
||||
Self.Diag(SrcExpr.get()->getLocStart(), diag::err_opencl_cast_to_half)
|
||||
<< DestType << SrcExpr.get()->getSourceRange();
|
||||
|
@ -4838,6 +4838,9 @@ Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) {
|
||||
Dcl && Dcl->getDeclContext()->isFileContext())
|
||||
Dcl->setTopLevelDeclInObjCContainer();
|
||||
|
||||
if (getLangOpts().OpenCL)
|
||||
setCurrentOpenCLExtensionForDecl(Dcl);
|
||||
|
||||
return Dcl;
|
||||
}
|
||||
|
||||
@ -5939,7 +5942,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
|
||||
NR = NR->getPointeeType();
|
||||
}
|
||||
|
||||
if (!getOpenCLOptions().cl_khr_fp16) {
|
||||
if (!getOpenCLOptions().isEnabled("cl_khr_fp16")) {
|
||||
// OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and
|
||||
// half array type (unless the cl_khr_fp16 extension is enabled).
|
||||
if (Context.getBaseElementType(R)->isHalfType()) {
|
||||
@ -6909,7 +6912,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
|
||||
// OpenCL v1.2 s6.8 - The static qualifier is valid only in program
|
||||
// scope.
|
||||
if (getLangOpts().OpenCLVersion == 120 &&
|
||||
!getOpenCLOptions().cl_clang_storage_class_specifiers &&
|
||||
!getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers") &&
|
||||
NewVD->isStaticLocal()) {
|
||||
Diag(NewVD->getLocation(), diag::err_static_function_scope);
|
||||
NewVD->setInvalidDecl();
|
||||
@ -7617,7 +7620,7 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
|
||||
// OpenCL extension spec v1.2 s9.5:
|
||||
// This extension adds support for half scalar and vector types as built-in
|
||||
// types that can be used for arithmetic operations, conversions etc.
|
||||
if (!S.getOpenCLOptions().cl_khr_fp16 && PT->isHalfType())
|
||||
if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16") && PT->isHalfType())
|
||||
return InvalidKernelParam;
|
||||
|
||||
if (PT->isRecordType())
|
||||
|
@ -657,7 +657,7 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
|
||||
return E;
|
||||
|
||||
// OpenCL usually rejects direct accesses to values of 'half' type.
|
||||
if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16 &&
|
||||
if (getLangOpts().OpenCL && !getOpenCLOptions().isEnabled("cl_khr_fp16") &&
|
||||
T->isHalfType()) {
|
||||
Diag(E->getExprLoc(), diag::err_opencl_half_load_store)
|
||||
<< 0 << T;
|
||||
@ -819,7 +819,7 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
|
||||
if (BTy && (BTy->getKind() == BuiltinType::Half ||
|
||||
BTy->getKind() == BuiltinType::Float)) {
|
||||
if (getLangOpts().OpenCL &&
|
||||
!(getOpenCLOptions().cl_khr_fp64)) {
|
||||
!getOpenCLOptions().isEnabled("cl_khr_fp64")) {
|
||||
if (BTy->getKind() == BuiltinType::Half) {
|
||||
E = ImpCastExprToType(E, Context.FloatTy, CK_FloatingCast).get();
|
||||
}
|
||||
@ -3386,7 +3386,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
|
||||
if (Literal.isFloatingLiteral()) {
|
||||
QualType Ty;
|
||||
if (Literal.isHalf){
|
||||
if (getOpenCLOptions().cl_khr_fp16)
|
||||
if (getOpenCLOptions().isEnabled("cl_khr_fp16"))
|
||||
Ty = Context.HalfTy;
|
||||
else {
|
||||
Diag(Tok.getLocation(), diag::err_half_const_requires_fp16);
|
||||
@ -3410,7 +3410,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
|
||||
Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
|
||||
}
|
||||
} else if (getLangOpts().OpenCL &&
|
||||
!(getOpenCLOptions().cl_khr_fp64)) {
|
||||
!getOpenCLOptions().isEnabled("cl_khr_fp64")) {
|
||||
// Impose single-precision float type when cl_khr_fp64 is not enabled.
|
||||
Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64);
|
||||
Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
|
||||
@ -5289,6 +5289,9 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
|
||||
Fn->getLocStart()))
|
||||
return ExprError();
|
||||
|
||||
if (getLangOpts().OpenCL && checkOpenCLDisabledDecl(*FD, *Fn))
|
||||
return ExprError();
|
||||
|
||||
// CheckEnableIf assumes that the we're passing in a sane number of args for
|
||||
// FD, but that doesn't always hold true here. This is because, in some
|
||||
// cases, we'll emit a diag about an ill-formed function call, but then
|
||||
@ -10186,7 +10189,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
|
||||
// OpenCL v1.2 s6.1.1.1 p2:
|
||||
// The half data type can only be used to declare a pointer to a buffer that
|
||||
// contains half values
|
||||
if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16 &&
|
||||
if (getLangOpts().OpenCL && !getOpenCLOptions().isEnabled("cl_khr_fp16") &&
|
||||
LHSType->isHalfType()) {
|
||||
Diag(Loc, diag::err_opencl_half_load_store) << 1
|
||||
<< LHSType.getUnqualifiedType();
|
||||
|
@ -5949,6 +5949,12 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
|
||||
Candidate.DeductionFailure.Data = FailedAttr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (LangOpts.OpenCL && isOpenCLDisabledDecl(Function)) {
|
||||
Candidate.Viable = false;
|
||||
Candidate.FailureKind = ovl_fail_ext_disabled;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ObjCMethodDecl *
|
||||
@ -9798,6 +9804,13 @@ static void DiagnoseFailedEnableIfAttr(Sema &S, OverloadCandidate *Cand) {
|
||||
<< Attr->getCond()->getSourceRange() << Attr->getMessage();
|
||||
}
|
||||
|
||||
static void DiagnoseOpenCLExtensionDisabled(Sema &S, OverloadCandidate *Cand) {
|
||||
FunctionDecl *Callee = Cand->Function;
|
||||
|
||||
S.Diag(Callee->getLocation(),
|
||||
diag::note_ovl_candidate_disabled_by_extension);
|
||||
}
|
||||
|
||||
/// Generates a 'note' diagnostic for an overload candidate. We've
|
||||
/// already generated a primary error at the call site.
|
||||
///
|
||||
@ -9875,6 +9888,9 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
|
||||
case ovl_fail_enable_if:
|
||||
return DiagnoseFailedEnableIfAttr(S, Cand);
|
||||
|
||||
case ovl_fail_ext_disabled:
|
||||
return DiagnoseOpenCLExtensionDisabled(S, Cand);
|
||||
|
||||
case ovl_fail_addr_not_available: {
|
||||
bool Available = checkAddressOfCandidateIsAvailable(S, Cand->Function);
|
||||
(void)Available;
|
||||
|
@ -1401,13 +1401,6 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
|
||||
Result = Context.LongDoubleTy;
|
||||
else
|
||||
Result = Context.DoubleTy;
|
||||
|
||||
if (S.getLangOpts().OpenCL &&
|
||||
!(S.getOpenCLOptions().cl_khr_fp64)) {
|
||||
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
|
||||
<< Result << "cl_khr_fp64";
|
||||
declarator.setInvalidType(true);
|
||||
}
|
||||
break;
|
||||
case DeclSpec::TST_float128:
|
||||
if (!S.Context.getTargetInfo().hasFloat128Type())
|
||||
@ -1459,48 +1452,6 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
|
||||
Result = S.GetTypeFromParser(DS.getRepAsType());
|
||||
if (Result.isNull()) {
|
||||
declarator.setInvalidType(true);
|
||||
} else if (S.getLangOpts().OpenCL) {
|
||||
if (Result->getAs<AtomicType>()) {
|
||||
StringRef TypeName = Result.getBaseTypeIdentifier()->getName();
|
||||
bool NoExtTypes =
|
||||
llvm::StringSwitch<bool>(TypeName)
|
||||
.Cases("atomic_int", "atomic_uint", "atomic_float",
|
||||
"atomic_flag", true)
|
||||
.Default(false);
|
||||
if (!S.getOpenCLOptions().cl_khr_int64_base_atomics && !NoExtTypes) {
|
||||
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
|
||||
<< Result << "cl_khr_int64_base_atomics";
|
||||
declarator.setInvalidType(true);
|
||||
}
|
||||
if (!S.getOpenCLOptions().cl_khr_int64_extended_atomics &&
|
||||
!NoExtTypes) {
|
||||
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
|
||||
<< Result << "cl_khr_int64_extended_atomics";
|
||||
declarator.setInvalidType(true);
|
||||
}
|
||||
if (!S.getOpenCLOptions().cl_khr_fp64 &&
|
||||
!TypeName.compare("atomic_double")) {
|
||||
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
|
||||
<< Result << "cl_khr_fp64";
|
||||
declarator.setInvalidType(true);
|
||||
}
|
||||
} else if (!S.getOpenCLOptions().cl_khr_gl_msaa_sharing &&
|
||||
(Result->isOCLImage2dArrayMSAADepthROType() ||
|
||||
Result->isOCLImage2dArrayMSAADepthWOType() ||
|
||||
Result->isOCLImage2dArrayMSAADepthRWType() ||
|
||||
Result->isOCLImage2dArrayMSAAROType() ||
|
||||
Result->isOCLImage2dArrayMSAARWType() ||
|
||||
Result->isOCLImage2dArrayMSAAWOType() ||
|
||||
Result->isOCLImage2dMSAADepthROType() ||
|
||||
Result->isOCLImage2dMSAADepthRWType() ||
|
||||
Result->isOCLImage2dMSAADepthWOType() ||
|
||||
Result->isOCLImage2dMSAAROType() ||
|
||||
Result->isOCLImage2dMSAARWType() ||
|
||||
Result->isOCLImage2dMSAAWOType())) {
|
||||
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
|
||||
<< Result << "cl_khr_gl_msaa_sharing";
|
||||
declarator.setInvalidType(true);
|
||||
}
|
||||
}
|
||||
|
||||
// TypeQuals handled by caller.
|
||||
@ -1636,6 +1587,10 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (S.getLangOpts().OpenCL &&
|
||||
S.checkOpenCLDisabledTypeDeclSpec(DS, Result))
|
||||
declarator.setInvalidType(true);
|
||||
|
||||
// Handle complex types.
|
||||
if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) {
|
||||
if (S.getLangOpts().Freestanding)
|
||||
@ -4185,7 +4140,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
// FIXME: This really should be in BuildFunctionType.
|
||||
if (T->isHalfType()) {
|
||||
if (S.getLangOpts().OpenCL) {
|
||||
if (!S.getOpenCLOptions().cl_khr_fp16) {
|
||||
if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
|
||||
S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return)
|
||||
<< T << 0 /*pointer hint*/;
|
||||
D.setInvalidType(true);
|
||||
@ -4418,7 +4373,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
// Disallow half FP parameters.
|
||||
// FIXME: This really should be in BuildFunctionType.
|
||||
if (S.getLangOpts().OpenCL) {
|
||||
if (!S.getOpenCLOptions().cl_khr_fp16) {
|
||||
if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
|
||||
S.Diag(Param->getLocation(),
|
||||
diag::err_opencl_half_param) << ParamTy;
|
||||
D.setInvalidType();
|
||||
|
@ -3164,8 +3164,38 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
|
||||
break;
|
||||
|
||||
case OPENCL_EXTENSIONS:
|
||||
// Later tables overwrite earlier ones.
|
||||
OpenCLExtensions.swap(Record);
|
||||
for (unsigned I = 0, E = Record.size(); I != E; ) {
|
||||
auto Name = ReadString(Record, I);
|
||||
auto &Opt = OpenCLExtensions.OptMap[Name];
|
||||
Opt.Supported = Record[I++];
|
||||
Opt.Enabled = Record[I++];
|
||||
Opt.Avail = Record[I++];
|
||||
Opt.Core = Record[I++];
|
||||
}
|
||||
break;
|
||||
|
||||
case OPENCL_EXTENSION_TYPES:
|
||||
for (unsigned I = 0, E = Record.size(); I != E;) {
|
||||
auto TypeID = static_cast<::TypeID>(Record[I++]);
|
||||
auto *Type = GetType(TypeID).getTypePtr();
|
||||
auto NumExt = static_cast<unsigned>(Record[I++]);
|
||||
for (unsigned II = 0; II != NumExt; ++II) {
|
||||
auto Ext = ReadString(Record, I);
|
||||
OpenCLTypeExtMap[Type].insert(Ext);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OPENCL_EXTENSION_DECLS:
|
||||
for (unsigned I = 0, E = Record.size(); I != E;) {
|
||||
auto DeclID = static_cast<::DeclID>(Record[I++]);
|
||||
auto *Decl = GetDecl(DeclID);
|
||||
auto NumExt = static_cast<unsigned>(Record[I++]);
|
||||
for (unsigned II = 0; II != NumExt; ++II) {
|
||||
auto Ext = ReadString(Record, I);
|
||||
OpenCLDeclExtMap[Decl].insert(Ext);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TENTATIVE_DEFINITIONS:
|
||||
@ -7091,14 +7121,9 @@ void ASTReader::InitializeSema(Sema &S) {
|
||||
SemaObj->FPFeatures.fp_contract = FPPragmaOptions[0];
|
||||
}
|
||||
|
||||
// FIXME: What happens if these are changed by a module import?
|
||||
if (!OpenCLExtensions.empty()) {
|
||||
unsigned I = 0;
|
||||
#define OPENCLEXT(nm) SemaObj->OpenCLFeatures.nm = OpenCLExtensions[I++];
|
||||
#include "clang/Basic/OpenCLExtensions.def"
|
||||
|
||||
assert(OpenCLExtensions.size() == I && "Wrong number of OPENCL_EXTENSIONS");
|
||||
}
|
||||
SemaObj->OpenCLFeatures.copy(OpenCLExtensions);
|
||||
SemaObj->OpenCLTypeExtMap = OpenCLTypeExtMap;
|
||||
SemaObj->OpenCLDeclExtMap = OpenCLDeclExtMap;
|
||||
|
||||
UpdateSema();
|
||||
}
|
||||
|
@ -1053,6 +1053,8 @@ void ASTWriter::WriteBlockInfoBlock() {
|
||||
RECORD(HEADER_SEARCH_TABLE);
|
||||
RECORD(FP_PRAGMA_OPTIONS);
|
||||
RECORD(OPENCL_EXTENSIONS);
|
||||
RECORD(OPENCL_EXTENSION_TYPES);
|
||||
RECORD(OPENCL_EXTENSION_DECLS);
|
||||
RECORD(DELEGATING_CTORS);
|
||||
RECORD(KNOWN_NAMESPACES);
|
||||
RECORD(MODULE_OFFSET_MAP);
|
||||
@ -3939,11 +3941,46 @@ void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) {
|
||||
|
||||
const OpenCLOptions &Opts = SemaRef.getOpenCLOptions();
|
||||
RecordData Record;
|
||||
#define OPENCLEXT(nm) Record.push_back(Opts.nm);
|
||||
#include "clang/Basic/OpenCLExtensions.def"
|
||||
for (const auto &I:Opts.OptMap) {
|
||||
AddString(I.getKey(), Record);
|
||||
auto V = I.getValue();
|
||||
Record.push_back(V.Supported);
|
||||
Record.push_back(V.Enabled);
|
||||
Record.push_back(V.Avail);
|
||||
Record.push_back(V.Core);
|
||||
}
|
||||
Stream.EmitRecord(OPENCL_EXTENSIONS, Record);
|
||||
}
|
||||
|
||||
void ASTWriter::WriteOpenCLExtensionTypes(Sema &SemaRef) {
|
||||
if (!SemaRef.Context.getLangOpts().OpenCL)
|
||||
return;
|
||||
|
||||
RecordData Record;
|
||||
for (const auto &I : SemaRef.OpenCLTypeExtMap) {
|
||||
Record.push_back(
|
||||
static_cast<unsigned>(getTypeID(I.first->getCanonicalTypeInternal())));
|
||||
Record.push_back(I.second.size());
|
||||
for (auto Ext : I.second)
|
||||
AddString(Ext, Record);
|
||||
}
|
||||
Stream.EmitRecord(OPENCL_EXTENSION_TYPES, Record);
|
||||
}
|
||||
|
||||
void ASTWriter::WriteOpenCLExtensionDecls(Sema &SemaRef) {
|
||||
if (!SemaRef.Context.getLangOpts().OpenCL)
|
||||
return;
|
||||
|
||||
RecordData Record;
|
||||
for (const auto &I : SemaRef.OpenCLDeclExtMap) {
|
||||
Record.push_back(getDeclID(I.first));
|
||||
Record.push_back(static_cast<unsigned>(I.second.size()));
|
||||
for (auto Ext : I.second)
|
||||
AddString(Ext, Record);
|
||||
}
|
||||
Stream.EmitRecord(OPENCL_EXTENSION_DECLS, Record);
|
||||
}
|
||||
|
||||
void ASTWriter::WriteCUDAPragmas(Sema &SemaRef) {
|
||||
if (SemaRef.ForceCUDAHostDeviceDepth > 0) {
|
||||
RecordData::value_type Record[] = {SemaRef.ForceCUDAHostDeviceDepth};
|
||||
@ -4628,6 +4665,8 @@ uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
|
||||
WriteIdentifierTable(PP, SemaRef.IdResolver, isModule);
|
||||
WriteFPPragmaOptions(SemaRef.getFPOptions());
|
||||
WriteOpenCLExtensions(SemaRef);
|
||||
WriteOpenCLExtensionTypes(SemaRef);
|
||||
WriteOpenCLExtensionDecls(SemaRef);
|
||||
WriteCUDAPragmas(SemaRef);
|
||||
WritePragmaDiagnosticMappings(Context.getDiagnostics(), isModule);
|
||||
|
||||
|
25
clang/test/CodeGenOpenCL/extension-begin.cl
Normal file
25
clang/test/CodeGenOpenCL/extension-begin.cl
Normal file
@ -0,0 +1,25 @@
|
||||
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -emit-llvm -o - | FileCheck %s
|
||||
|
||||
__attribute__((overloadable)) void f(int x);
|
||||
|
||||
#pragma OPENCL EXTENSION my_ext : begin
|
||||
|
||||
__attribute__((overloadable)) void f(long x);
|
||||
|
||||
#pragma OPENCL EXTENSION my_ext : end
|
||||
|
||||
#pragma OPENCL EXTENSION my_ext : enable
|
||||
|
||||
//CHECK: define spir_func void @test_f1(i64 %x)
|
||||
//CHECK: call spir_func void @_Z1fl(i64 %{{.*}})
|
||||
void test_f1(long x) {
|
||||
f(x);
|
||||
}
|
||||
|
||||
#pragma OPENCL EXTENSION my_ext : disable
|
||||
|
||||
//CHECK: define spir_func void @test_f2(i64 %x)
|
||||
//CHECK: call spir_func void @_Z1fi(i32 %{{.*}})
|
||||
void test_f2(long x) {
|
||||
f(x);
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only
|
||||
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -fsyntax-only -cl-std=CL2.0 -DCL20
|
||||
// RUN: %clang_cc1 %s -triple spir64-unknown-unknown -verify -fsyntax-only -cl-std=CL2.0 -DCL20
|
||||
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -fsyntax-only -cl-std=CL2.0 -DCL20 -DEXT -Wpedantic-core-features
|
||||
|
||||
#ifdef EXT
|
||||
@ -47,14 +48,16 @@ void atomic_types_test() {
|
||||
// expected-error@-28 {{use of type 'atomic_ulong' (aka '_Atomic(unsigned long)') requires cl_khr_int64_extended_atomics extension to be enabled}}
|
||||
// expected-error@-27 {{use of type 'atomic_double' (aka '_Atomic(double)') requires cl_khr_int64_base_atomics extension to be enabled}}
|
||||
// expected-error@-28 {{use of type 'atomic_double' (aka '_Atomic(double)') requires cl_khr_int64_extended_atomics extension to be enabled}}
|
||||
// expected-error-re@-27 {{use of type 'atomic_intptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
|
||||
// expected-error-re@-28 {{use of type 'atomic_intptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
|
||||
// expected-error-re@-28 {{use of type 'atomic_uintptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
|
||||
// expected-error-re@-29 {{use of type 'atomic_uintptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
|
||||
// expected-error-re@-29 {{use of type 'atomic_size_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
|
||||
// expected-error-re@-30 {{use of type 'atomic_size_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
|
||||
// expected-error-re@-30 {{use of type 'atomic_ptrdiff_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
|
||||
// expected-error-re@-31 {{use of type 'atomic_ptrdiff_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
|
||||
#if __LP64__
|
||||
// expected-error-re@-28 {{use of type 'atomic_intptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
|
||||
// expected-error-re@-29 {{use of type 'atomic_intptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
|
||||
// expected-error-re@-29 {{use of type 'atomic_uintptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
|
||||
// expected-error-re@-30 {{use of type 'atomic_uintptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
|
||||
// expected-error-re@-30 {{use of type 'atomic_size_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
|
||||
// expected-error-re@-31 {{use of type 'atomic_size_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
|
||||
// expected-error-re@-31 {{use of type 'atomic_ptrdiff_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
|
||||
// expected-error-re@-32 {{use of type 'atomic_ptrdiff_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CL20
|
||||
|
@ -5,9 +5,9 @@
|
||||
#pragma OPENCL EXTENSION cl_no_such_extension : disable /* expected-warning {{unknown OpenCL extension 'cl_no_such_extension' - ignoring}} */
|
||||
|
||||
#pragma OPENCL EXTENSION all : disable
|
||||
#pragma OPENCL EXTENSION all : enable /* expected-warning {{unknown OpenCL extension 'all' - ignoring}} */
|
||||
#pragma OPENCL EXTENSION all : enable /* expected-warning {{expected 'disable' - ignoring}} */
|
||||
|
||||
#pragma OPENCL EXTENSION cl_khr_fp64 : on /* expected-warning {{expected 'enable' or 'disable' - ignoring}} */
|
||||
#pragma OPENCL EXTENSION cl_khr_fp64 : on /* expected-warning {{expected 'enable', 'disable', 'begin' or 'end' - ignoring}} */
|
||||
|
||||
#pragma OPENCL FP_CONTRACT ON
|
||||
#pragma OPENCL FP_CONTRACT OFF
|
||||
|
56
clang/test/SemaOpenCL/extension-begin.cl
Normal file
56
clang/test/SemaOpenCL/extension-begin.cl
Normal file
@ -0,0 +1,56 @@
|
||||
// Test this without pch.
|
||||
// RUN: %clang_cc1 %s -DHEADER -DHEADER_USER -triple spir-unknown-unknown -verify -pedantic -fsyntax-only
|
||||
|
||||
// Test with pch.
|
||||
// RUN: %clang_cc1 %s -DHEADER -triple spir-unknown-unknown -emit-pch -o %t -verify -pedantic
|
||||
// RUN: %clang_cc1 %s -DHEADER_USER -triple spir-unknown-unknown -include-pch %t -fsyntax-only -verify -pedantic
|
||||
|
||||
#if defined(HEADER) && !defined(INCLUDED)
|
||||
#define INCLUDED
|
||||
|
||||
#pragma OPENCL EXTENSION all : begin // expected-warning {{expected 'disable' - ignoring}}
|
||||
#pragma OPENCL EXTENSION all : end // expected-warning {{expected 'disable' - ignoring}}
|
||||
|
||||
#pragma OPENCL EXTENSION my_ext : begin
|
||||
|
||||
struct A {
|
||||
int a;
|
||||
};
|
||||
|
||||
typedef struct A TypedefOfA;
|
||||
typedef const TypedefOfA* PointerOfA;
|
||||
|
||||
void f(void);
|
||||
|
||||
__attribute__((overloadable)) void g(long x);
|
||||
|
||||
#pragma OPENCL EXTENSION my_ext : end
|
||||
#pragma OPENCL EXTENSION my_ext : end // expected-warning {{OpenCL extension end directive mismatches begin directive - ignoring}}
|
||||
|
||||
__attribute__((overloadable)) void g(void);
|
||||
|
||||
#endif // defined(HEADER) && !defined(INCLUDED)
|
||||
|
||||
#ifdef HEADER_USER
|
||||
|
||||
#pragma OPENCL EXTENSION my_ext : enable
|
||||
void test_f1(void) {
|
||||
struct A test_A1;
|
||||
f();
|
||||
g(0);
|
||||
}
|
||||
|
||||
#pragma OPENCL EXTENSION my_ext : disable
|
||||
void test_f2(void) {
|
||||
struct A test_A2; // expected-error {{use of type 'struct A' requires my_ext extension to be enabled}}
|
||||
const struct A test_A_local; // expected-error {{use of type 'struct A' requires my_ext extension to be enabled}}
|
||||
TypedefOfA test_typedef_A; // expected-error {{use of type 'TypedefOfA' (aka 'struct A') requires my_ext extension to be enabled}}
|
||||
PointerOfA test_A_pointer; // expected-error {{use of type 'PointerOfA' (aka 'const struct A *') requires my_ext extension to be enabled}}
|
||||
f(); // expected-error {{use of declaration requires my_ext extension to be enabled}}
|
||||
g(0); // expected-error {{no matching function for call to 'g'}}
|
||||
// expected-note@-26 {{candidate disabled due to OpenCL extension}}
|
||||
// expected-note@-22 {{candidate function not viable: requires 0 arguments, but 1 was provided}}
|
||||
}
|
||||
|
||||
#endif // HEADER_USER
|
||||
|
@ -22,8 +22,6 @@
|
||||
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-all -cl-ext=+cl_khr_fp64 -cl-ext=+cl_khr_fp16 -cl-ext=-cl_khr_fp64 -DNOFP64
|
||||
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-all -cl-ext=+cl_khr_fp64,-cl_khr_fp64,+cl_khr_fp16 -DNOFP64
|
||||
|
||||
|
||||
|
||||
#ifdef FP64
|
||||
// expected-no-diagnostics
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user