forked from OSchip/llvm-project
[OpenCL] Guard 64-bit atomic types
Until now, overloads with a 64-bit atomic type argument were always made available with `-fdeclare-opencl-builtins`. Ensure these overloads are only available when both the `cl_khr_int64_base_atomics` and `cl_khr_int64_extended_atomics` extensions have been enabled, as required by the OpenCL specification. Differential Revision: https://reviews.llvm.org/D119858
This commit is contained in:
parent
889317d47b
commit
9798b33d1d
|
@ -78,6 +78,8 @@ class concatExtension<FunctionExtension Base, string NewExts> {
|
|||
def NoTypeExt : TypeExtension<"">;
|
||||
def Fp16TypeExt : TypeExtension<"cl_khr_fp16">;
|
||||
def Fp64TypeExt : TypeExtension<"cl_khr_fp64">;
|
||||
def Atomic64TypeExt : TypeExtension<"cl_khr_int64_base_atomics cl_khr_int64_extended_atomics">;
|
||||
def AtomicFp64TypeExt : TypeExtension<"cl_khr_int64_base_atomics cl_khr_int64_extended_atomics cl_khr_fp64">;
|
||||
|
||||
// FunctionExtension definitions.
|
||||
def FuncExtNone : FunctionExtension<"">;
|
||||
|
@ -389,10 +391,14 @@ def NDRange : TypedefType<"ndrange_t">;
|
|||
// OpenCL v2.0 s6.13.11: Atomic integer and floating-point types.
|
||||
def AtomicInt : Type<"atomic_int", QualType<"Context.getAtomicType(Context.IntTy)">>;
|
||||
def AtomicUInt : Type<"atomic_uint", QualType<"Context.getAtomicType(Context.UnsignedIntTy)">>;
|
||||
def AtomicLong : Type<"atomic_long", QualType<"Context.getAtomicType(Context.LongTy)">>;
|
||||
def AtomicULong : Type<"atomic_ulong", QualType<"Context.getAtomicType(Context.UnsignedLongTy)">>;
|
||||
let Extension = Atomic64TypeExt in {
|
||||
def AtomicLong : Type<"atomic_long", QualType<"Context.getAtomicType(Context.LongTy)">>;
|
||||
def AtomicULong : Type<"atomic_ulong", QualType<"Context.getAtomicType(Context.UnsignedLongTy)">>;
|
||||
}
|
||||
def AtomicFloat : Type<"atomic_float", QualType<"Context.getAtomicType(Context.FloatTy)">>;
|
||||
def AtomicDouble : Type<"atomic_double", QualType<"Context.getAtomicType(Context.DoubleTy)">>;
|
||||
let Extension = AtomicFp64TypeExt in {
|
||||
def AtomicDouble : Type<"atomic_double", QualType<"Context.getAtomicType(Context.DoubleTy)">>;
|
||||
}
|
||||
def AtomicHalf : Type<"atomic_half", QualType<"Context.getAtomicType(Context.HalfTy)">>;
|
||||
def AtomicIntPtr : Type<"atomic_intptr_t", QualType<"Context.getAtomicType(Context.getIntPtrType())">>;
|
||||
def AtomicUIntPtr : Type<"atomic_uintptr_t", QualType<"Context.getAtomicType(Context.getUIntPtrType())">>;
|
||||
|
|
|
@ -163,6 +163,25 @@ void test_atomic_fetch_with_address_space(volatile __generic atomic_float *a_flo
|
|||
}
|
||||
#endif // !defined(NO_HEADER) && __OPENCL_C_VERSION__ >= 200
|
||||
|
||||
#if !defined(NO_HEADER) && __OPENCL_C_VERSION__ == 200 && defined(__opencl_c_generic_address_space)
|
||||
|
||||
// Test that overloads that use atomic_double are not available when the fp64
|
||||
// extension is disabled. Test this by counting the number of notes about
|
||||
// candidate functions.
|
||||
void test_atomic_double_reporting(volatile __generic atomic_int *a) {
|
||||
atomic_init(a);
|
||||
// expected-error@-1{{no matching function for call to 'atomic_init'}}
|
||||
#if defined(NO_FP64)
|
||||
// Expecting 5 candidates: int, uint, long, ulong, float
|
||||
// expected-note@-4 5 {{candidate function not viable: requires 2 arguments, but 1 was provided}}
|
||||
#else
|
||||
// Expecting 6 candidates: int, uint, long, ulong, float, double
|
||||
// expected-note@-7 6 {{candidate function not viable: requires 2 arguments, but 1 was provided}}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(NO_ATOMSCOPE) && __OPENCL_C_VERSION__ >= 300
|
||||
// Disable the feature by undefining the feature macro.
|
||||
#undef __opencl_c_atomic_scope_device
|
||||
|
|
|
@ -733,6 +733,20 @@ static std::pair<unsigned, unsigned> isOpenCLBuiltin(llvm::StringRef Name) {
|
|||
OS << "} // isOpenCLBuiltin\n";
|
||||
}
|
||||
|
||||
// Emit an if-statement with an isMacroDefined call for each extension in
|
||||
// the space-separated list of extensions.
|
||||
static void EmitMacroChecks(raw_ostream &OS, StringRef Extensions) {
|
||||
SmallVector<StringRef, 2> ExtVec;
|
||||
Extensions.split(ExtVec, " ");
|
||||
OS << " if (";
|
||||
for (StringRef Ext : ExtVec) {
|
||||
if (Ext != ExtVec.front())
|
||||
OS << " && ";
|
||||
OS << "S.getPreprocessor().isMacroDefined(\"" << Ext << "\")";
|
||||
}
|
||||
OS << ") {\n ";
|
||||
}
|
||||
|
||||
void BuiltinNameEmitter::EmitQualTypeFinder() {
|
||||
OS << R"(
|
||||
|
||||
|
@ -825,15 +839,14 @@ static void OCL2Qual(Sema &S, const OpenCLTypeStruct &Ty,
|
|||
// Collect all QualTypes for a single vector size into TypeList.
|
||||
OS << " SmallVector<QualType, " << BaseTypes.size() << "> TypeList;\n";
|
||||
for (const auto *T : BaseTypes) {
|
||||
StringRef Ext =
|
||||
StringRef Exts =
|
||||
T->getValueAsDef("Extension")->getValueAsString("ExtName");
|
||||
if (!Ext.empty()) {
|
||||
OS << " if (S.getPreprocessor().isMacroDefined(\"" << Ext
|
||||
<< "\")) {\n ";
|
||||
if (!Exts.empty()) {
|
||||
EmitMacroChecks(OS, Exts);
|
||||
}
|
||||
OS << " TypeList.push_back("
|
||||
<< T->getValueAsDef("QTExpr")->getValueAsString("TypeExpr") << ");\n";
|
||||
if (!Ext.empty()) {
|
||||
if (!Exts.empty()) {
|
||||
OS << " }\n";
|
||||
}
|
||||
}
|
||||
|
@ -877,15 +890,14 @@ static void OCL2Qual(Sema &S, const OpenCLTypeStruct &Ty,
|
|||
// Emit the cases for non generic, non image types.
|
||||
OS << " case OCLT_" << T->getValueAsString("Name") << ":\n";
|
||||
|
||||
StringRef Ext = T->getValueAsDef("Extension")->getValueAsString("ExtName");
|
||||
// If this type depends on an extension, ensure the extension macro is
|
||||
StringRef Exts = T->getValueAsDef("Extension")->getValueAsString("ExtName");
|
||||
// If this type depends on an extension, ensure the extension macros are
|
||||
// defined.
|
||||
if (!Ext.empty()) {
|
||||
OS << " if (S.getPreprocessor().isMacroDefined(\"" << Ext
|
||||
<< "\")) {\n ";
|
||||
if (!Exts.empty()) {
|
||||
EmitMacroChecks(OS, Exts);
|
||||
}
|
||||
OS << " QT.push_back(" << QT->getValueAsString("TypeExpr") << ");\n";
|
||||
if (!Ext.empty()) {
|
||||
if (!Exts.empty()) {
|
||||
OS << " }\n";
|
||||
}
|
||||
OS << " break;\n";
|
||||
|
|
Loading…
Reference in New Issue