Implement OpenCL event_t as Clang builtin type, including event_t related OpenCL restrictions (OpenCL 1.2 spec 6.9)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172973 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index 35b0736..6d30b89 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -286,6 +286,7 @@
case TST_image2d_t:
case TST_image2d_array_t:
case TST_image3d_t:
+ case TST_event_t:
return false;
case TST_decltype:
@@ -427,6 +428,7 @@
case DeclSpec::TST_image2d_t: return "image2d_t";
case DeclSpec::TST_image2d_array_t: return "image2d_array_t";
case DeclSpec::TST_image3d_t: return "image3d_t";
+ case DeclSpec::TST_event_t: return "event_t";
case DeclSpec::TST_error: return "(error)";
}
llvm_unreachable("Unknown typespec!");
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index dbdbc3d..7936efa 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -4401,6 +4401,22 @@
SC = SC_OpenCLWorkGroupLocal;
SCAsWritten = SC_OpenCLWorkGroupLocal;
}
+
+ // OpenCL 1.2 spec, p6.9 r:
+ // The event type cannot be used to declare a program scope variable.
+ // The event type cannot be used with the __local, __constant and __global
+ // address space qualifiers.
+ if (R->isEventT()) {
+ if (S->getParent() == 0) {
+ Diag(D.getLocStart(), diag::err_event_t_global_var);
+ D.setInvalidType();
+ }
+
+ if (R.getAddressSpace()) {
+ Diag(D.getLocStart(), diag::err_event_t_addr_space_qual);
+ D.setInvalidType();
+ }
+ }
}
bool isExplicitSpecialization = false;
@@ -6136,12 +6152,26 @@
}
}
- // OpenCL v1.2 s6.8 static is invalid for kernel functions.
- if ((getLangOpts().OpenCLVersion >= 120)
- && NewFD->hasAttr<OpenCLKernelAttr>()
- && (SC == SC_Static)) {
- Diag(D.getIdentifierLoc(), diag::err_static_kernel);
- D.setInvalidType();
+ if (NewFD->hasAttr<OpenCLKernelAttr>()) {
+
+ // OpenCL v1.2 s6.8 static is invalid for kernel functions.
+ if ((getLangOpts().OpenCLVersion >= 120)
+ && (SC == SC_Static)) {
+ Diag(D.getIdentifierLoc(), diag::err_static_kernel);
+ D.setInvalidType();
+ }
+
+ // OpenCL v1.2 s6.8 n:
+ // Arguments to kernel functions in a program cannot be declared to be of
+ // type event_t.
+ for (FunctionDecl::param_iterator PI = NewFD->param_begin(),
+ PE = NewFD->param_end(); PI != PE; ++PI) {
+ if ((*PI)->getType()->isEventT()) {
+ Diag((*PI)->getLocation(), diag::err_event_t_kernel_arg);
+ D.setInvalidType();
+ }
+ }
+
}
MarkUnusedFileScopedDecl(NewFD);
@@ -9776,6 +9806,14 @@
}
}
+ // OpenCL 1.2 spec, s6.9 r:
+ // The event type cannot be used to declare a structure or union field.
+ if (LangOpts.OpenCL && T->isEventT()) {
+ Diag(Loc, diag::err_event_t_struct_field);
+ D.setInvalidType();
+ }
+
+
DiagnoseFunctionSpecifiers(D);
if (D.getDeclSpec().isThreadSpecified())
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 26bb6ef..e661110 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -2424,6 +2424,7 @@
case SK_PassByIndirectRestore:
case SK_ProduceObjCObject:
case SK_StdInitializerList:
+ case SK_OCLZeroEvent:
break;
case SK_ConversionSequence:
@@ -2652,6 +2653,13 @@
Steps.push_back(S);
}
+void InitializationSequence::AddOCLZeroEventStep(QualType T) {
+ Step S;
+ S.Kind = SK_OCLZeroEvent;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
void InitializationSequence::RewrapReferenceInitList(QualType T,
InitListExpr *Syntactic) {
assert(Syntactic->getNumInits() == 1 &&
@@ -4009,6 +4017,27 @@
return true;
}
+//
+// OpenCL 1.2 spec, s6.12.10
+//
+// The event argument can also be used to associate the
+// async_work_group_copy with a previous async copy allowing
+// an event to be shared by multiple async copies; otherwise
+// event should be zero.
+//
+static bool TryOCLZeroEventInitialization(Sema &S,
+ InitializationSequence &Sequence,
+ QualType DestType,
+ Expr *Initializer) {
+ if (!S.getLangOpts().OpenCL || !DestType->isEventT() ||
+ !Initializer->isIntegerConstantExpr(S.getASTContext()) ||
+ (Initializer->EvaluateKnownConstInt(S.getASTContext()) != 0))
+ return false;
+
+ Sequence.AddOCLZeroEventStep(DestType);
+ return true;
+}
+
InitializationSequence::InitializationSequence(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -4152,6 +4181,10 @@
return;
}
+
+ if (TryOCLZeroEventInitialization(S, *this, DestType, Initializer))
+ return;
+
// Handle initialization in C
AddCAssignmentStep(DestType);
MaybeProduceObjCObject(S, *this, Entity);
@@ -4940,7 +4973,8 @@
case SK_PassByIndirectCopyRestore:
case SK_PassByIndirectRestore:
case SK_ProduceObjCObject:
- case SK_StdInitializerList: {
+ case SK_StdInitializerList:
+ case SK_OCLZeroEvent: {
assert(Args.size() == 1);
CurInit = Args[0];
if (!CurInit.get()) return ExprError();
@@ -5453,6 +5487,15 @@
CurInit = S.Owned(Semantic);
break;
}
+ case SK_OCLZeroEvent: {
+ assert(Step->Type->isEventT() &&
+ "Event initialization on non event type.");
+
+ CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type,
+ CK_ZeroToOCLEvent,
+ CurInit.get()->getValueKind());
+ break;
+ }
}
}
@@ -6139,6 +6182,10 @@
case SK_StdInitializerList:
OS << "std::initializer_list from initializer list";
break;
+
+ case SK_OCLZeroEvent:
+ OS << "OpenCL event_t from zero";
+ break;
}
}
}
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 6c70320..bb20913 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -737,6 +737,7 @@
case TST_image2d_t:
case TST_image2d_array_t:
case TST_image3d_t:
+ case TST_event_t:
case TST_error:
break;
}
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 35816a4..a3b0c45 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -952,6 +952,10 @@
Result = Context.OCLImage3dTy;
break;
+ case DeclSpec::TST_event_t:
+ Result = Context.OCLEventTy;
+ break;
+
case DeclSpec::TST_error:
Result = Context.IntTy;
declarator.setInvalidType(true);