diff options
author | James Molloy <james.molloy@arm.com> | 2014-06-20 14:35:13 +0000 |
---|---|---|
committer | James Molloy <james.molloy@arm.com> | 2014-06-20 14:35:13 +0000 |
commit | 9eef2659bf60af09e06e4e65f97cd34fb207cae9 (patch) | |
tree | 535d173efd37254113a712b0ad45a70c36ca753c /clang/lib/Sema/SemaInit.cpp | |
parent | 454ac7c6f34daee3f27e0271d234ad529843cd24 (diff) | |
download | bcm5719-llvm-9eef2659bf60af09e06e4e65f97cd34fb207cae9.tar.gz bcm5719-llvm-9eef2659bf60af09e06e4e65f97cd34fb207cae9.zip |
The ability to use vector initializer lists is a GNU vector extension
and is unrelated to the NEON intrinsics in arm_neon.h. On little
endian machines it works fine, however on big endian machines it
exhibits surprising behaviour:
uint32x2_t x = {42, 64};
return vget_lane_u32(x, 0); // Will return 64.
Because of this, explicitly call out that it is unsupported on big
endian machines.
This patch will emit the following warning in big-endian mode:
test.c:3:15: warning: vector initializers are a GNU extension and are not compatible with NEON intrinsics [-Wgnu]
int32x4_t x = {0, 1, 2, 3};
^
test.c:3:15: note: consider using vld1q_s32() to initialize a vector from memory, or vcombine_s32(vcreate_s32(), vcreate_s32()) to initialize from integer constants
1 warning generated.
llvm-svn: 211362
Diffstat (limited to 'clang/lib/Sema/SemaInit.cpp')
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 3dfeb8ecd30..606108c127e 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -17,6 +17,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/TypeLoc.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Sema/Designator.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/SemaInternal.h" @@ -1204,6 +1205,46 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity, CheckSubElementType(ElementEntity, IList, elementType, Index, StructuredList, StructuredIndex); } + + if (VerifyOnly) + return; + + bool isBigEndian = SemaRef.Context.getTargetInfo().isBigEndian(); + const VectorType *T = Entity.getType()->getAs<VectorType>(); + if (isBigEndian && (T->getVectorKind() == VectorType::NeonVector || + T->getVectorKind() == VectorType::NeonPolyVector)) { + // The ability to use vector initializer lists is a GNU vector extension + // and is unrelated to the NEON intrinsics in arm_neon.h. On little + // endian machines it works fine, however on big endian machines it + // exhibits surprising behaviour: + // + // uint32x2_t x = {42, 64}; + // return vget_lane_u32(x, 0); // Will return 64. + // + // Because of this, explicitly call out that it is non-portable. + // + SemaRef.Diag(IList->getLocStart(), + diag::warn_neon_vector_initializer_non_portable); + + const char *typeCode; + unsigned typeSize = SemaRef.Context.getTypeSize(elementType); + + if (elementType->isFloatingType()) + typeCode = "f"; + else if (elementType->isSignedIntegerType()) + typeCode = "s"; + else if (elementType->isUnsignedIntegerType()) + typeCode = "u"; + else + llvm_unreachable("Invalid element type!"); + + SemaRef.Diag(IList->getLocStart(), + SemaRef.Context.getTypeSize(VT) > 64 ? + diag::note_neon_vector_initializer_non_portable_q : + diag::note_neon_vector_initializer_non_portable) + << typeCode << typeSize; + } + return; } |