mirror of https://github.com/microsoft/clang.git
Add .rgba syntax extension to ext_vector_type types
Summary: This patch enables .rgba accessors to ext_vector_type types and adds tests for syntax validation and code generation. 'a' and 'b' can appear either in the point access mode or the numeric access mode (for indices 10 and 11). To disambiguate between the two usages, the accessor type is explicitly passed to relevant methods. Reviewers: rsmith Subscribers: Anastasia, bader, srhines, cfe-commits Differential Revision: http://reviews.llvm.org/D20602 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@276455 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f9fef1ef2e
commit
459f422c55
|
@ -2812,7 +2812,8 @@ public:
|
||||||
/// __attribute__((ext_vector_type(n)), where "n" is the number of elements.
|
/// __attribute__((ext_vector_type(n)), where "n" is the number of elements.
|
||||||
/// Unlike vector_size, ext_vector_type is only allowed on typedef's. This
|
/// Unlike vector_size, ext_vector_type is only allowed on typedef's. This
|
||||||
/// class enables syntactic extensions, like Vector Components for accessing
|
/// class enables syntactic extensions, like Vector Components for accessing
|
||||||
/// points, colors, and textures (modeled after OpenGL Shading Language).
|
/// points (as .xyzw), colors (as .rgba), and textures (modeled after OpenGL
|
||||||
|
/// Shading Language).
|
||||||
class ExtVectorType : public VectorType {
|
class ExtVectorType : public VectorType {
|
||||||
ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) :
|
ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) :
|
||||||
VectorType(ExtVector, vecType, nElements, canonType, GenericVector) {}
|
VectorType(ExtVector, vecType, nElements, canonType, GenericVector) {}
|
||||||
|
@ -2821,10 +2822,10 @@ public:
|
||||||
static int getPointAccessorIdx(char c) {
|
static int getPointAccessorIdx(char c) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
default: return -1;
|
default: return -1;
|
||||||
case 'x': return 0;
|
case 'x': case 'r': return 0;
|
||||||
case 'y': return 1;
|
case 'y': case 'g': return 1;
|
||||||
case 'z': return 2;
|
case 'z': case 'b': return 2;
|
||||||
case 'w': return 3;
|
case 'w': case 'a': return 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static int getNumericAccessorIdx(char c) {
|
static int getNumericAccessorIdx(char c) {
|
||||||
|
@ -2855,13 +2856,15 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getAccessorIdx(char c) {
|
static int getAccessorIdx(char c, bool isNumericAccessor) {
|
||||||
if (int idx = getPointAccessorIdx(c)+1) return idx-1;
|
if (isNumericAccessor)
|
||||||
return getNumericAccessorIdx(c);
|
return getNumericAccessorIdx(c);
|
||||||
|
else
|
||||||
|
return getPointAccessorIdx(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isAccessorWithinNumElements(char c) const {
|
bool isAccessorWithinNumElements(char c, bool isNumericAccessor) const {
|
||||||
if (int idx = getAccessorIdx(c)+1)
|
if (int idx = getAccessorIdx(c, isNumericAccessor)+1)
|
||||||
return unsigned(idx-1) < getNumElements();
|
return unsigned(idx-1) < getNumElements();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -316,6 +316,7 @@ def ObjCRootClass : DiagGroup<"objc-root-class">;
|
||||||
def ObjCPointerIntrospectPerformSelector : DiagGroup<"deprecated-objc-pointer-introspection-performSelector">;
|
def ObjCPointerIntrospectPerformSelector : DiagGroup<"deprecated-objc-pointer-introspection-performSelector">;
|
||||||
def ObjCPointerIntrospect : DiagGroup<"deprecated-objc-pointer-introspection", [ObjCPointerIntrospectPerformSelector]>;
|
def ObjCPointerIntrospect : DiagGroup<"deprecated-objc-pointer-introspection", [ObjCPointerIntrospectPerformSelector]>;
|
||||||
def ObjCMultipleMethodNames : DiagGroup<"objc-multiple-method-names">;
|
def ObjCMultipleMethodNames : DiagGroup<"objc-multiple-method-names">;
|
||||||
|
def OpenCLUnsupportedRGBA: DiagGroup<"opencl-unsupported-rgba">;
|
||||||
def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">;
|
def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">;
|
||||||
def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">;
|
def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">;
|
||||||
def Packed : DiagGroup<"packed">;
|
def Packed : DiagGroup<"packed">;
|
||||||
|
|
|
@ -7980,6 +7980,11 @@ def err_opencl_enqueue_kernel_blocks_non_local_void_args : Error<
|
||||||
"blocks used in device side enqueue are expected to have parameters of type 'local void*'">;
|
"blocks used in device side enqueue are expected to have parameters of type 'local void*'">;
|
||||||
def err_opencl_enqueue_kernel_blocks_no_args : Error<
|
def err_opencl_enqueue_kernel_blocks_no_args : Error<
|
||||||
"blocks in this form of device side enqueue call are expected to have have no parameters">;
|
"blocks in this form of device side enqueue call are expected to have have no parameters">;
|
||||||
|
|
||||||
|
// OpenCL v2.2 s2.1.2.3 - Vector Component Access
|
||||||
|
def ext_opencl_ext_vector_type_rgba_selector: ExtWarn<
|
||||||
|
"vector component name '%0' is an OpenCL version 2.2 feature">,
|
||||||
|
InGroup<OpenCLUnsupportedRGBA>;
|
||||||
} // end of sema category
|
} // end of sema category
|
||||||
|
|
||||||
let CategoryName = "OpenMP Issue" in {
|
let CategoryName = "OpenMP Issue" in {
|
||||||
|
|
|
@ -3395,8 +3395,11 @@ bool ExtVectorElementExpr::containsDuplicateElements() const {
|
||||||
void ExtVectorElementExpr::getEncodedElementAccess(
|
void ExtVectorElementExpr::getEncodedElementAccess(
|
||||||
SmallVectorImpl<uint32_t> &Elts) const {
|
SmallVectorImpl<uint32_t> &Elts) const {
|
||||||
StringRef Comp = Accessor->getName();
|
StringRef Comp = Accessor->getName();
|
||||||
if (Comp[0] == 's' || Comp[0] == 'S')
|
bool isNumericAccessor = false;
|
||||||
|
if (Comp[0] == 's' || Comp[0] == 'S') {
|
||||||
Comp = Comp.substr(1);
|
Comp = Comp.substr(1);
|
||||||
|
isNumericAccessor = true;
|
||||||
|
}
|
||||||
|
|
||||||
bool isHi = Comp == "hi";
|
bool isHi = Comp == "hi";
|
||||||
bool isLo = Comp == "lo";
|
bool isLo = Comp == "lo";
|
||||||
|
@ -3415,7 +3418,7 @@ void ExtVectorElementExpr::getEncodedElementAccess(
|
||||||
else if (isOdd)
|
else if (isOdd)
|
||||||
Index = 2 * i + 1;
|
Index = 2 * i + 1;
|
||||||
else
|
else
|
||||||
Index = ExtVectorType::getAccessorIdx(Comp[i]);
|
Index = ExtVectorType::getAccessorIdx(Comp[i], isNumericAccessor);
|
||||||
|
|
||||||
Elts.push_back(Index);
|
Elts.push_back(Index);
|
||||||
}
|
}
|
||||||
|
|
|
@ -269,6 +269,20 @@ Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
|
||||||
llvm_unreachable("unexpected instance member access kind");
|
llvm_unreachable("unexpected instance member access kind");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Determine whether input char is from rgba component set.
|
||||||
|
static bool
|
||||||
|
IsRGBA(char c) {
|
||||||
|
switch (c) {
|
||||||
|
case 'r':
|
||||||
|
case 'g':
|
||||||
|
case 'b':
|
||||||
|
case 'a':
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Check an ext-vector component access expression.
|
/// Check an ext-vector component access expression.
|
||||||
///
|
///
|
||||||
/// VK should be set in advance to the value kind of the base
|
/// VK should be set in advance to the value kind of the base
|
||||||
|
@ -308,11 +322,25 @@ CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK,
|
||||||
HalvingSwizzle = true;
|
HalvingSwizzle = true;
|
||||||
} else if (!HexSwizzle &&
|
} else if (!HexSwizzle &&
|
||||||
(Idx = vecType->getPointAccessorIdx(*compStr)) != -1) {
|
(Idx = vecType->getPointAccessorIdx(*compStr)) != -1) {
|
||||||
|
bool HasRGBA = IsRGBA(*compStr);
|
||||||
do {
|
do {
|
||||||
|
// Ensure that xyzw and rgba components don't intermingle.
|
||||||
|
if (HasRGBA != IsRGBA(*compStr))
|
||||||
|
break;
|
||||||
if (HasIndex[Idx]) HasRepeated = true;
|
if (HasIndex[Idx]) HasRepeated = true;
|
||||||
HasIndex[Idx] = true;
|
HasIndex[Idx] = true;
|
||||||
compStr++;
|
compStr++;
|
||||||
} while (*compStr && (Idx = vecType->getPointAccessorIdx(*compStr)) != -1);
|
} while (*compStr && (Idx = vecType->getPointAccessorIdx(*compStr)) != -1);
|
||||||
|
|
||||||
|
// Emit a warning if an rgba selector is used earlier than OpenCL 2.2
|
||||||
|
if (HasRGBA || (*compStr && IsRGBA(*compStr))) {
|
||||||
|
if (S.getLangOpts().OpenCL && S.getLangOpts().OpenCLVersion < 220) {
|
||||||
|
const char *DiagBegin = HasRGBA ? CompName->getNameStart() : compStr;
|
||||||
|
S.Diag(OpLoc, diag::ext_opencl_ext_vector_type_rgba_selector)
|
||||||
|
<< StringRef(DiagBegin, 1)
|
||||||
|
<< S.getLangOpts().OpenCLVersion << SourceRange(CompLoc);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (HexSwizzle) compStr++;
|
if (HexSwizzle) compStr++;
|
||||||
while ((Idx = vecType->getNumericAccessorIdx(*compStr)) != -1) {
|
while ((Idx = vecType->getNumericAccessorIdx(*compStr)) != -1) {
|
||||||
|
@ -339,7 +367,7 @@ CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK,
|
||||||
compStr++;
|
compStr++;
|
||||||
|
|
||||||
while (*compStr) {
|
while (*compStr) {
|
||||||
if (!vecType->isAccessorWithinNumElements(*compStr++)) {
|
if (!vecType->isAccessorWithinNumElements(*compStr++, HexSwizzle)) {
|
||||||
S.Diag(OpLoc, diag::err_ext_vector_component_exceeds_length)
|
S.Diag(OpLoc, diag::err_ext_vector_component_exceeds_length)
|
||||||
<< baseType << SourceRange(CompLoc);
|
<< baseType << SourceRange(CompLoc);
|
||||||
return QualType();
|
return QualType();
|
||||||
|
|
|
@ -301,3 +301,40 @@ void test17(void) {
|
||||||
char valC;
|
char valC;
|
||||||
char16 destVal = valC ? valA : valB;
|
char16 destVal = valC ? valA : valB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef __attribute__(( ext_vector_type(16) )) float float16;
|
||||||
|
|
||||||
|
float16 vec16, vec16_2;
|
||||||
|
|
||||||
|
// CHECK: @test_rgba
|
||||||
|
void test_rgba() {
|
||||||
|
// CHECK: fadd <4 x float>
|
||||||
|
vec4_2 = vec4.abgr + vec4;
|
||||||
|
|
||||||
|
// CHECK: shufflevector {{.*}} <i32 0, i32 1>
|
||||||
|
vec2 = vec4.rg;
|
||||||
|
// CHECK: shufflevector {{.*}} <i32 2, i32 3>
|
||||||
|
vec2_2 = vec4.ba;
|
||||||
|
// CHECK: extractelement {{.*}} 2
|
||||||
|
f = vec4.b;
|
||||||
|
// CHECK: shufflevector {{.*}} <i32 2, i32 2, i32 2, i32 2>
|
||||||
|
vec4_2 = vec4_2.bbbb;
|
||||||
|
|
||||||
|
// CHECK: insertelement {{.*}} 0
|
||||||
|
vec2.r = f;
|
||||||
|
// CHECK: shufflevector {{.*}} <i32 1, i32 0>
|
||||||
|
vec2.gr = vec2;
|
||||||
|
|
||||||
|
// CHECK: extractelement {{.*}} 0
|
||||||
|
f = vec4_2.rg.r;
|
||||||
|
// CHECK: shufflevector {{.*}} <i32 2, i32 1, i32 0>
|
||||||
|
// CHECK: shufflevector {{.*}} <i32 0, i32 1, i32 2, i32 undef>
|
||||||
|
// CHECK: shufflevector {{.*}} <i32 4, i32 5, i32 6, i32 3>
|
||||||
|
vec4.rgb = vec4.bgr;
|
||||||
|
|
||||||
|
// CHECK: extractelement {{.*}} 11
|
||||||
|
// CHECK: insertelement {{.*}} 2
|
||||||
|
vec4.b = vec16.sb;
|
||||||
|
// CHECK: shufflevector {{.*}} <i32 10, i32 11, i32 12, i32 13>
|
||||||
|
vec4_2 = vec16.sabcd;
|
||||||
|
}
|
||||||
|
|
|
@ -39,6 +39,33 @@ static void test() {
|
||||||
vec4.x = vec16.sF;
|
vec4.x = vec16.sF;
|
||||||
|
|
||||||
vec4p->yz = vec4p->xy;
|
vec4p->yz = vec4p->xy;
|
||||||
|
|
||||||
|
vec2.a; // expected-error {{vector component access exceeds type 'float2'}}
|
||||||
|
vec2.rgba; // expected-error {{vector component access exceeds type 'float2'}}
|
||||||
|
vec4.rgba; // expected-warning {{expression result unused}}
|
||||||
|
vec4.rgbz; // expected-error {{illegal vector component name 'z'}}
|
||||||
|
vec4.rgbc; // expected-error {{illegal vector component name 'c'}}
|
||||||
|
vec4.xyzr; // expected-error {{illegal vector component name 'r'}}
|
||||||
|
vec4.s01b; // expected-error {{vector component access exceeds type 'float4'}}
|
||||||
|
|
||||||
|
vec3 = vec4.rgb; // legal, shorten
|
||||||
|
f = vec2.r; // legal, shorten
|
||||||
|
f = vec4.rg.r; // legal, shorten
|
||||||
|
vec4_2.rgba = vec4.xyzw; // legal, no intermingling
|
||||||
|
|
||||||
|
vec4_2.rgbr = vec4.rgba; // expected-error {{vector is not assignable (contains duplicate components)}}
|
||||||
|
vec4_2.rgbb = vec4.rgba; // expected-error {{vector is not assignable (contains duplicate components)}}
|
||||||
|
vec4_2.rgga = vec4.rgba; // expected-error {{vector is not assignable (contains duplicate components)}}
|
||||||
|
vec2.x = f;
|
||||||
|
vec2.rr = vec2_2.rg; // expected-error {{vector is not assignable (contains duplicate components)}}
|
||||||
|
vec2.gr = vec2_2.rg;
|
||||||
|
vec2.gr.g = vec2_2.r;
|
||||||
|
vec4 = (float4){ 1,2,3,4 };
|
||||||
|
vec4.rg.b; // expected-error {{vector component access exceeds type 'float2'}}
|
||||||
|
vec4.r = vec16.sf;
|
||||||
|
vec4.g = vec16.sF;
|
||||||
|
|
||||||
|
vec4p->gb = vec4p->rg;
|
||||||
}
|
}
|
||||||
|
|
||||||
float2 lo(float3 x) { return x.lo; }
|
float2 lo(float3 x) { return x.lo; }
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL1.1
|
||||||
|
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0
|
||||||
|
|
||||||
|
typedef float float4 __attribute__((ext_vector_type(4)));
|
||||||
|
|
||||||
|
void test_ext_vector_accessors(float4 V) {
|
||||||
|
V = V.wzyx;
|
||||||
|
V = V.abgr; // expected-warning {{vector component name 'a' is an OpenCL version 2.2 feature}}
|
||||||
|
V = V.xyzr; // expected-warning {{vector component name 'r' is an OpenCL version 2.2 feature}} \
|
||||||
|
// expected-error {{illegal vector component name 'r'}}
|
||||||
|
}
|
Loading…
Reference in New Issue