From: Nate Begeman Date: Sun, 18 Jan 2009 01:47:54 +0000 (+0000) Subject: Update support for vector component access on ExtVectors. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=353417af9d254d4fd0eb7d0a3ff71c4d8594ac58;p=clang Update support for vector component access on ExtVectors. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62440 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index a74ac95324..9c9c5af69a 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -900,7 +900,7 @@ protected: Type(Vector, canonType, vecType->isDependentType()), ElementType(vecType), NumElements(nElements) {} VectorType(TypeClass tc, QualType vecType, unsigned nElements, - QualType canonType) + QualType canonType) : Type(tc, canonType, vecType->isDependentType()), ElementType(vecType), NumElements(nElements) {} friend class ASTContext; // ASTContext creates these. @@ -945,29 +945,31 @@ public: case 'w': return 3; } } - static int getColorAccessorIdx(char c) { + static int getNumericAccessorIdx(char c) { switch (c) { - default: return -1; - case 'r': return 0; - case 'g': return 1; - case 'b': return 2; - case 'a': return 3; + default: return -1; + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + case 'a': return 10; + case 'b': return 11; + case 'c': return 12; + case 'd': return 13; + case 'e': return 14; + case 'f': return 15; } } - static int getTextureAccessorIdx(char c) { - switch (c) { - default: return -1; - case 's': return 0; - case 't': return 1; - case 'p': return 2; - case 'q': return 3; - } - }; static int getAccessorIdx(char c) { if (int idx = getPointAccessorIdx(c)+1) return idx-1; - if (int idx = getColorAccessorIdx(c)+1) return idx-1; - return getTextureAccessorIdx(c); + return getNumericAccessorIdx(c); } bool isAccessorWithinNumElements(char c) const { diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 89cad41979..6540b2ccc3 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1173,12 +1173,15 @@ bool ExtVectorElementExpr::containsDuplicateElements() const { /// getEncodedElementAccess - We encode the fields as a llvm ConstantArray. void ExtVectorElementExpr::getEncodedElementAccess( llvm::SmallVectorImpl &Elts) const { - bool isHi = Accessor.isStr("hi"); - bool isLo = Accessor.isStr("lo"); - bool isEven = Accessor.isStr("e"); - bool isOdd = Accessor.isStr("o"); - const char *compStr = Accessor.getName(); + if (*compStr == 's') + compStr++; + + bool isHi = !strcmp(compStr, "hi"); + bool isLo = !strcmp(compStr, "lo"); + bool isEven = !strcmp(compStr, "even"); + bool isOdd = !strcmp(compStr, "odd"); + for (unsigned i = 0, e = getNumElements(); i != e; ++i) { uint64_t Index; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 7a6c36416b..7d08132cd6 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1325,64 +1325,61 @@ CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc, IdentifierInfo &CompName, SourceLocation CompLoc) { const ExtVectorType *vecType = baseType->getAsExtVectorType(); - // This flag determines whether or not the component is to be treated as a - // special name, or a regular GLSL-style component access. - bool SpecialComponent = false; - // The vector accessor can't exceed the number of elements. const char *compStr = CompName.getName(); - if (strlen(compStr) > vecType->getNumElements()) { - Diag(OpLoc, diag::err_ext_vector_component_exceeds_length) - << baseType << SourceRange(CompLoc); - return QualType(); - } + + // This flag determines whether or not the component is one of the four + // special names that indicate a subset of exactly half the elements are + // to be selected. + bool HalvingSwizzle = false; + + // This flag determines whether or not CompName has an 's' char prefix, + // indicating that it is a string of hex values to be used as vector indices. + bool HexSwizzle = *compStr == 's'; // Check that we've found one of the special components, or that the component // names must come from the same set. if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") || - !strcmp(compStr, "e") || !strcmp(compStr, "o")) { - SpecialComponent = true; + !strcmp(compStr, "even") || !strcmp(compStr, "odd")) { + HalvingSwizzle = true; } else if (vecType->getPointAccessorIdx(*compStr) != -1) { do compStr++; while (*compStr && vecType->getPointAccessorIdx(*compStr) != -1); - } else if (vecType->getColorAccessorIdx(*compStr) != -1) { + } else if (HexSwizzle || vecType->getNumericAccessorIdx(*compStr) != -1) { do compStr++; - while (*compStr && vecType->getColorAccessorIdx(*compStr) != -1); - } else if (vecType->getTextureAccessorIdx(*compStr) != -1) { - do - compStr++; - while (*compStr && vecType->getTextureAccessorIdx(*compStr) != -1); + while (*compStr && vecType->getNumericAccessorIdx(*compStr) != -1); } - - if (!SpecialComponent && *compStr) { + + if (!HalvingSwizzle && *compStr) { // We didn't get to the end of the string. This means the component names // didn't come from the same set *or* we encountered an illegal name. Diag(OpLoc, diag::err_ext_vector_component_name_illegal) << std::string(compStr,compStr+1) << SourceRange(CompLoc); return QualType(); } - // Each component accessor can't exceed the vector type. - compStr = CompName.getName(); - while (*compStr) { - if (vecType->isAccessorWithinNumElements(*compStr)) + + // Ensure no component accessor exceeds the width of the vector type it + // operates on. + if (!HalvingSwizzle) { + compStr = CompName.getName(); + + if (HexSwizzle) compStr++; - else - break; - } - if (!SpecialComponent && *compStr) { - // We didn't get to the end of the string. This means a component accessor - // exceeds the number of elements in the vector. - Diag(OpLoc, diag::err_ext_vector_component_exceeds_length) - << baseType << SourceRange(CompLoc); - return QualType(); + + while (*compStr) { + if (!vecType->isAccessorWithinNumElements(*compStr++)) { + Diag(OpLoc, diag::err_ext_vector_component_exceeds_length) + << baseType << SourceRange(CompLoc); + return QualType(); + } + } } - // If we have a special component name, verify that the current vector length - // is an even number, since all special component names return exactly half - // the elements. - if (SpecialComponent && (vecType->getNumElements() & 1U)) { + // If this is a halving swizzle, verify that the base type has an even + // number of elements. + if (HalvingSwizzle && (vecType->getNumElements() & 1U)) { Diag(OpLoc, diag::err_ext_vector_component_requires_even) << baseType << SourceRange(CompLoc); return QualType(); @@ -1391,9 +1388,13 @@ CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc, // The component accessor looks fine - now we need to compute the actual type. // The vector type is implied by the component accessor. For example, // vec4.b is a float, vec4.xy is a vec2, vec4.rgb is a vec3, etc. + // vec4.s0 is a float, vec4.s23 is a vec3, etc. // vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2. - unsigned CompSize = SpecialComponent ? vecType->getNumElements() / 2 - : CompName.getLength(); + unsigned CompSize = HalvingSwizzle ? vecType->getNumElements() / 2 + : CompName.getLength(); + if (HexSwizzle) + CompSize--; + if (CompSize == 1) return vecType->getElementType(); diff --git a/test/Parser/ext_vector_components.c b/test/Parser/ext_vector_components.c deleted file mode 100644 index ec54631e7b..0000000000 --- a/test/Parser/ext_vector_components.c +++ /dev/null @@ -1,28 +0,0 @@ -// RUN: clang -fsyntax-only -verify %s - -typedef __attribute__(( ext_vector_type(2) )) float float2; -typedef __attribute__(( ext_vector_type(3) )) float float3; -typedef __attribute__(( ext_vector_type(4) )) float float4; - -static void test() { - float2 vec2, vec2_2; - float3 vec3; - float4 vec4, vec4_2; - float f; - - vec2.z; // 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.rgbc; // expected-error {{illegal vector component name 'c'}} - vec3 = vec4.rgb; // legal, shorten - f = vec2.x; // legal, shorten - - 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.xx = vec2_2.xy; // expected-error {{vector is not assignable (contains duplicate components)}} - vec2.yx = vec2_2.xy; - vec4 = (float4){ 1,2,3,4 }; - vec4.rg.a; // expected-error {{vector component access exceeds type 'float2'}} -} diff --git a/test/Sema/ext_vector_components.c b/test/Sema/ext_vector_components.c new file mode 100644 index 0000000000..d827c1e075 --- /dev/null +++ b/test/Sema/ext_vector_components.c @@ -0,0 +1,35 @@ +// RUN: clang -fsyntax-only -verify %s + +typedef __attribute__(( ext_vector_type(2) )) float float2; +typedef __attribute__(( ext_vector_type(3) )) float float3; +typedef __attribute__(( ext_vector_type(4) )) float float4; + +static void test() { + float2 vec2, vec2_2; + float3 vec3; + float4 vec4, vec4_2; + float f; + + vec2.z; // expected-error {{vector component access exceeds type 'float2'}} + vec2.xyzw; // expected-error {{vector component access exceeds type 'float2'}} + vec4.xyzw; // expected-warning {{expression result unused}} + vec4.xyzc; // expected-error {{illegal vector component name 'c'}} + vec4.s01z; // expected-error {{illegal vector component name 'z'}} + vec2 = vec4.s01; // legal, shorten + + vec3 = vec4.xyz; // legal, shorten + f = vec2.x; // legal, shorten + f = vec4.xy.x; // legal, shorten + + vec2 = vec3.hi; // expected-error {{vector component access invalid for odd-sized type 'float3'}} + + vec4_2.xyzx = vec4.xyzw; // expected-error {{vector is not assignable (contains duplicate components)}} + vec4_2.xyzz = vec4.xyzw; // expected-error {{vector is not assignable (contains duplicate components)}} + vec4_2.xyyw = vec4.xyzw; // expected-error {{vector is not assignable (contains duplicate components)}} + vec2.x = f; + vec2.xx = vec2_2.xy; // expected-error {{vector is not assignable (contains duplicate components)}} + vec2.yx = vec2_2.xy; + vec4 = (float4){ 1,2,3,4 }; + vec4.xy.w; // expected-error {{vector component access exceeds type 'float2'}} + vec4.s06; // expected-error {{vector component access exceeds type 'float4'}} +}