Skip to content

Commit

Permalink
Add .rgba syntax extension to ext_vector_type types
Browse files Browse the repository at this point in the history
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

llvm-svn: 276455
  • Loading branch information
pirama-arumuga-nainar committed Jul 22, 2016
1 parent ff3ea5f commit 98eaa62
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 13 deletions.
23 changes: 13 additions & 10 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -2812,7 +2812,8 @@ class VectorType : public Type, public llvm::FoldingSetNode {
/// __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
/// 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 {
ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) :
VectorType(ExtVector, vecType, nElements, canonType, GenericVector) {}
Expand All @@ -2821,10 +2822,10 @@ class ExtVectorType : public VectorType {
static int getPointAccessorIdx(char c) {
switch (c) {
default: return -1;
case 'x': return 0;
case 'y': return 1;
case 'z': return 2;
case 'w': return 3;
case 'x': case 'r': return 0;
case 'y': case 'g': return 1;
case 'z': case 'b': return 2;
case 'w': case 'a': return 3;
}
}
static int getNumericAccessorIdx(char c) {
Expand Down Expand Up @@ -2855,13 +2856,15 @@ class ExtVectorType : public VectorType {
}
}

static int getAccessorIdx(char c) {
if (int idx = getPointAccessorIdx(c)+1) return idx-1;
return getNumericAccessorIdx(c);
static int getAccessorIdx(char c, bool isNumericAccessor) {
if (isNumericAccessor)
return getNumericAccessorIdx(c);
else
return getPointAccessorIdx(c);
}

bool isAccessorWithinNumElements(char c) const {
if (int idx = getAccessorIdx(c)+1)
bool isAccessorWithinNumElements(char c, bool isNumericAccessor) const {
if (int idx = getAccessorIdx(c, isNumericAccessor)+1)
return unsigned(idx-1) < getNumElements();
return false;
}
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ def ObjCRootClass : DiagGroup<"objc-root-class">;
def ObjCPointerIntrospectPerformSelector : DiagGroup<"deprecated-objc-pointer-introspection-performSelector">;
def ObjCPointerIntrospect : DiagGroup<"deprecated-objc-pointer-introspection", [ObjCPointerIntrospectPerformSelector]>;
def ObjCMultipleMethodNames : DiagGroup<"objc-multiple-method-names">;
def OpenCLUnsupportedRGBA: DiagGroup<"opencl-unsupported-rgba">;
def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">;
def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">;
def Packed : DiagGroup<"packed">;
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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*'">;
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">;

// 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

let CategoryName = "OpenMP Issue" in {
Expand Down
7 changes: 5 additions & 2 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3395,8 +3395,11 @@ bool ExtVectorElementExpr::containsDuplicateElements() const {
void ExtVectorElementExpr::getEncodedElementAccess(
SmallVectorImpl<uint32_t> &Elts) const {
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);
isNumericAccessor = true;
}

bool isHi = Comp == "hi";
bool isLo = Comp == "lo";
Expand All @@ -3415,7 +3418,7 @@ void ExtVectorElementExpr::getEncodedElementAccess(
else if (isOdd)
Index = 2 * i + 1;
else
Index = ExtVectorType::getAccessorIdx(Comp[i]);
Index = ExtVectorType::getAccessorIdx(Comp[i], isNumericAccessor);

Elts.push_back(Index);
}
Expand Down
30 changes: 29 additions & 1 deletion clang/lib/Sema/SemaExprMember.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,20 @@ Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
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.
///
/// VK should be set in advance to the value kind of the base
Expand Down Expand Up @@ -308,11 +322,25 @@ CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK,
HalvingSwizzle = true;
} else if (!HexSwizzle &&
(Idx = vecType->getPointAccessorIdx(*compStr)) != -1) {
bool HasRGBA = IsRGBA(*compStr);
do {
// Ensure that xyzw and rgba components don't intermingle.
if (HasRGBA != IsRGBA(*compStr))
break;
if (HasIndex[Idx]) HasRepeated = true;
HasIndex[Idx] = true;
compStr++;
} 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 {
if (HexSwizzle) compStr++;
while ((Idx = vecType->getNumericAccessorIdx(*compStr)) != -1) {
Expand All @@ -339,7 +367,7 @@ CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK,
compStr++;

while (*compStr) {
if (!vecType->isAccessorWithinNumElements(*compStr++)) {
if (!vecType->isAccessorWithinNumElements(*compStr++, HexSwizzle)) {
S.Diag(OpLoc, diag::err_ext_vector_component_exceeds_length)
<< baseType << SourceRange(CompLoc);
return QualType();
Expand Down
37 changes: 37 additions & 0 deletions clang/test/CodeGen/ext-vector.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,3 +301,40 @@ void test17(void) {
char valC;
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;
}
27 changes: 27 additions & 0 deletions clang/test/Sema/ext_vector_components.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,33 @@ static void test() {
vec4.x = vec16.sF;

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; }
Expand Down
11 changes: 11 additions & 0 deletions clang/test/SemaOpenCL/ext_vectors.cl
Original file line number Diff line number Diff line change
@@ -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'}}
}

0 comments on commit 98eaa62

Please sign in to comment.