Index: include/clang/AST/Type.h =================================================================== --- include/clang/AST/Type.h +++ include/clang/AST/Type.h @@ -2807,7 +2807,8 @@ /// __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) {} @@ -2816,10 +2817,10 @@ 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) { @@ -2850,13 +2851,15 @@ } } - 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; } Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -7901,6 +7901,10 @@ "invalid number of arguments to function: %0">; def err_opencl_builtin_to_addr_invalid_arg : Error< "invalid argument %0 to function: %1, expecting a generic pointer argument">; + +// 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">; } // end of sema category let CategoryName = "OpenMP Issue" in { Index: lib/AST/Expr.cpp =================================================================== --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -3383,8 +3383,11 @@ void ExtVectorElementExpr::getEncodedElementAccess( SmallVectorImpl &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"; @@ -3403,7 +3406,7 @@ else if (isOdd) Index = 2 * i + 1; else - Index = ExtVectorType::getAccessorIdx(Comp[i]); + Index = ExtVectorType::getAccessorIdx(Comp[i], isNumericAccessor); Elts.push_back(Index); } Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp +++ lib/Basic/Targets.cpp @@ -7992,6 +7992,43 @@ return true; } }; + +// 32-bit RenderScript is armv7 with width and align of 'long' set to 8-bytes +class RenderScript32TargetInfo : public ARMleTargetInfo { +public: + RenderScript32TargetInfo(const llvm::Triple &Triple, + const TargetOptions &Opts) + : ARMleTargetInfo( + llvm::Triple("armv7", Triple.getVendorName(), Triple.getOSName(), + Triple.getEnvironmentName()), + Opts) + { + LongWidth = LongAlign = 64; + } + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + Builder.defineMacro("__RENDERSCRIPT__"); + ARMleTargetInfo::getTargetDefines(Opts, Builder); + } +}; + +// 64-bit RenderScript is aarch64 +class RenderScript64TargetInfo : public AArch64leTargetInfo { +public: + RenderScript64TargetInfo(const llvm::Triple &Triple, + const TargetOptions &Opts) + : AArch64leTargetInfo( + llvm::Triple("aarch64", Triple.getVendorName(), Triple.getOSName(), + Triple.getEnvironmentName()), + Opts) { } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + Builder.defineMacro("__RENDERSCRIPT__"); + AArch64leTargetInfo::getTargetDefines(Opts, Builder); + } +}; + } // end anonymous namespace //===----------------------------------------------------------------------===// @@ -8420,6 +8457,11 @@ if (!(Triple == llvm::Triple("wasm64-unknown-unknown"))) return nullptr; return new WebAssemblyOSTargetInfo(Triple, Opts); + + case llvm::Triple::renderscript32: + return new LinuxTargetInfo(Triple, Opts); + case llvm::Triple::renderscript64: + return new LinuxTargetInfo(Triple, Opts); } } Index: lib/Sema/SemaExprMember.cpp =================================================================== --- lib/Sema/SemaExprMember.cpp +++ lib/Sema/SemaExprMember.cpp @@ -268,6 +268,20 @@ 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 @@ -307,11 +321,25 @@ 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) { @@ -338,7 +366,7 @@ 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(); Index: test/CodeGen/ext-vector.c =================================================================== --- test/CodeGen/ext-vector.c +++ test/CodeGen/ext-vector.c @@ -301,3 +301,40 @@ 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 {{.*}} + vec2 = vec4.rg; + // CHECK: shufflevector {{.*}} + vec2_2 = vec4.ba; + // CHECK: extractelement {{.*}} 2 + f = vec4.b; + // CHECK: shufflevector {{.*}} + vec4_2 = vec4_2.bbbb; + + // CHECK: insertelement {{.*}} 0 + vec2.r = f; + // CHECK: shufflevector {{.*}} + vec2.gr = vec2; + + // CHECK: extractelement {{.*}} 0 + f = vec4_2.rg.r; + // CHECK: shufflevector {{.*}} + // CHECK: shufflevector {{.*}} + // CHECK: shufflevector {{.*}} + vec4.rgb = vec4.bgr; + + // CHECK: extractelement {{.*}} 11 + // CHECK: insertelement {{.*}} 2 + vec4.b = vec16.sb; + // CHECK: shufflevector {{.*}} + vec4_2 = vec16.sabcd; +} Index: test/CodeGen/renderscript.c =================================================================== --- /dev/null +++ test/CodeGen/renderscript.c @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 %s -triple=renderscript32 -emit-llvm -o - -Werror | FileCheck %s -check-prefix=CHECK-RS32 +// RUN: %clang_cc1 %s -triple=renderscript64 -emit-llvm -o - -Werror | FileCheck %s -check-prefix=CHECK-RS64 +// RUN: %clang_cc1 %s -triple=armv7-none-linux-gnueabi -emit-llvm -o - -Werror | FileCheck %s -check-prefix=CHECK-ARM + +// Ensure that the bitcode has the correct triple +// CHECK-RS32: target triple = "armv7-none-linux-gnueabi" +// CHECK-RS64: target triple = "aarch64-linux-android" +// CHECK-ARM: target triple = "armv7-none-linux-gnueabi" + +// Ensure that long data type has 8-byte size and alignment in RenderScript +#ifdef __RENDERSCRIPT__ +#define LONG_WIDTH_AND_ALIGN 8 +#else +#define LONG_WIDTH_AND_ALIGN 4 +#endif + +_Static_assert(sizeof(long) == LONG_WIDTH_AND_ALIGN, "sizeof long is wrong"); +_Static_assert(_Alignof(long) == LONG_WIDTH_AND_ALIGN, "sizeof long is wrong"); + +// CHECK-RS32: i64 @test_long(i64 %v) +// CHECK-RS64: i64 @test_long(i64 %v) +// CHECK-ARM: i32 @test_long(i32 %v) +long test_long(long v) { + return v + 1; +} Index: test/Misc/warning-flags.c =================================================================== --- test/Misc/warning-flags.c +++ test/Misc/warning-flags.c @@ -18,7 +18,7 @@ The list of warnings below should NEVER grow. It should gradually shrink to 0. -CHECK: Warnings without flags (84): +CHECK: Warnings without flags (85): CHECK-NEXT: ext_excess_initializers CHECK-NEXT: ext_excess_initializers_in_char_array_initializer CHECK-NEXT: ext_expected_semi_decl_list @@ -27,6 +27,7 @@ CHECK-NEXT: ext_missing_declspec CHECK-NEXT: ext_missing_whitespace_after_macro_name CHECK-NEXT: ext_new_paren_array_nonconst +CHECK-NEXT: ext_opencl_ext_vector_type_rgba_selector CHECK-NEXT: ext_plain_complex CHECK-NEXT: ext_template_arg_extra_parens CHECK-NEXT: ext_typecheck_comparison_of_pointer_integer Index: test/Sema/ext_vector_components.c =================================================================== --- test/Sema/ext_vector_components.c +++ test/Sema/ext_vector_components.c @@ -39,6 +39,33 @@ 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; } Index: test/SemaOpenCL/ext_vectors.cl =================================================================== --- /dev/null +++ test/SemaOpenCL/ext_vectors.cl @@ -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'}} +}