Update support for vector component access on ExtVectors.

llvm-svn: 62440
This commit is contained in:
Nate Begeman 2009-01-18 01:47:54 +00:00
parent 95439108e8
commit bb70bf6dbb
5 changed files with 102 additions and 89 deletions

View File

@ -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 {

View File

@ -1173,12 +1173,15 @@ bool ExtVectorElementExpr::containsDuplicateElements() const {
/// getEncodedElementAccess - We encode the fields as a llvm ConstantArray.
void ExtVectorElementExpr::getEncodedElementAccess(
llvm::SmallVectorImpl<unsigned> &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;

View File

@ -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();

View File

@ -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'}}
}

View File

@ -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'}}
}