Introduce implicit conversions between AltiVec vectors and GCC
vectors, from Anton Yartsev!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110437 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 3c94970..df96de0 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -906,6 +906,11 @@
///
Qualifiers::GC getObjCGCAttrKind(const QualType &Ty) const;
+ /// areCompatibleVectorTypes - Return true if the given vector types either
+ /// are of the same unqualified type or if one is GCC and other - equivalent
+ /// AltiVec vector type.
+ bool areCompatibleVectorTypes(QualType FirstVec, QualType SecondVec);
+
/// isObjCNSObjectType - Return true if this is an NSObject object with
/// its NSObject attribute set.
bool isObjCNSObjectType(QualType Ty) const;
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 43873a4..22e1ebf 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1540,10 +1540,7 @@
// If the element type isn't canonical, this won't be a canonical type either,
// so fill in the canonical type field.
QualType Canonical;
- if (!vecType.isCanonical() || (AltiVecSpec == VectorType::AltiVec)) {
- // pass VectorType::NotAltiVec for AltiVecSpec to make AltiVec canonical
- // vector type (except 'vector bool ...' and 'vector Pixel') the same as
- // the equivalent GCC vector types
+ if (!vecType.isCanonical()) {
Canonical = getVectorType(getCanonicalType(vecType), NumElts,
VectorType::NotAltiVec);
@@ -4170,6 +4167,28 @@
LHS->getNumElements() == RHS->getNumElements();
}
+bool ASTContext::areCompatibleVectorTypes(QualType FirstVec,
+ QualType SecondVec) {
+ assert(FirstVec->isVectorType() && "FirstVec should be a vector type");
+ assert(SecondVec->isVectorType() && "SecondVec should be a vector type");
+
+ if (hasSameUnqualifiedType(FirstVec, SecondVec))
+ return true;
+
+ // AltiVec vectors types are identical to equivalent GCC vector types
+ const VectorType *First = FirstVec->getAs<VectorType>();
+ const VectorType *Second = SecondVec->getAs<VectorType>();
+ if ((((First->getAltiVecSpecific() == VectorType::AltiVec) &&
+ (Second->getAltiVecSpecific() == VectorType::NotAltiVec)) ||
+ ((First->getAltiVecSpecific() == VectorType::NotAltiVec) &&
+ (Second->getAltiVecSpecific() == VectorType::AltiVec))) &&
+ hasSameType(First->getElementType(), Second->getElementType()) &&
+ (First->getNumElements() == Second->getNumElements()))
+ return true;
+
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's.
//===----------------------------------------------------------------------===//
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 28b2e99..46c5a65 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -4731,13 +4731,18 @@
}
if (lhsType->isVectorType() || rhsType->isVectorType()) {
- // If we are allowing lax vector conversions, and LHS and RHS are both
- // vectors, the total size only needs to be the same. This is a bitcast;
- // no bits are changed but the result type is different.
- if (getLangOptions().LaxVectorConversions &&
- lhsType->isVectorType() && rhsType->isVectorType()) {
- if (Context.getTypeSize(lhsType) == Context.getTypeSize(rhsType))
+ if (lhsType->isVectorType() && rhsType->isVectorType()) {
+ // If we are allowing lax vector conversions, and LHS and RHS are both
+ // vectors, the total size only needs to be the same. This is a bitcast;
+ // no bits are changed but the result type is different.
+ if (getLangOptions().LaxVectorConversions &&
+ (Context.getTypeSize(lhsType) == Context.getTypeSize(rhsType)))
return IncompatibleVectors;
+
+ // Allow assignments of an AltiVec vector type to an equivalent GCC
+ // vector type and vice versa
+ if (Context.areCompatibleVectorTypes(lhsType, rhsType))
+ return Compatible;
}
return Incompatible;
}
@@ -5012,6 +5017,13 @@
}
}
+ // Handle the case of equivalent AltiVec and GCC vector types
+ if (lhsType->isVectorType() && rhsType->isVectorType() &&
+ Context.areCompatibleVectorTypes(lhsType, rhsType)) {
+ ImpCastExprToType(lex, rhsType, CastExpr::CK_BitCast);
+ return rhsType;
+ }
+
// Canonicalize the ExtVector to the LHS, remember if we swapped so we can
// swap back (so that we don't reverse the inputs to a subtract, for instance.
bool swapped = false;
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 037bc7b..5dfbe09 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -850,16 +850,20 @@
return true;
}
}
-
- // If lax vector conversions are permitted and the vector types are of the
- // same size, we can perform the conversion.
- if (Context.getLangOptions().LaxVectorConversions &&
- FromType->isVectorType() && ToType->isVectorType() &&
- Context.getTypeSize(FromType) == Context.getTypeSize(ToType)) {
- ICK = ICK_Vector_Conversion;
- return true;
+
+ // We can perform the conversion between vector types in the following cases:
+ // 1)vector types are equivalent AltiVec and GCC vector types
+ // 2)lax vector conversions are permitted and the vector types are of the
+ // same size
+ if (ToType->isVectorType() && FromType->isVectorType()) {
+ if (Context.areCompatibleVectorTypes(FromType, ToType) ||
+ Context.getLangOptions().LaxVectorConversions &&
+ (Context.getTypeSize(FromType) == Context.getTypeSize(ToType))) {
+ ICK = ICK_Vector_Conversion;
+ return true;
+ }
}
-
+
return false;
}
diff --git a/test/Sema/altivec-init.c b/test/Sema/altivec-init.c
index 57abc93..b5758bc 100644
--- a/test/Sema/altivec-init.c
+++ b/test/Sema/altivec-init.c
@@ -14,3 +14,22 @@
// FIXME: test that (type)(fn)(args) still works with -faltivec
// FIXME: test that c++ overloaded commas still work -faltivec
}
+
+void __attribute__((__overloadable__)) f(v4 a)
+{
+}
+
+void __attribute__((__overloadable__)) f(int a)
+{
+}
+
+void test()
+{
+ v4 vGCC;
+ vector int vAltiVec;
+
+ f(vAltiVec);
+ vGCC = vAltiVec;
+ vGCC = vGCC > vAltiVec;
+ vAltiVec = 0 ? vGCC : vGCC;
+}
diff --git a/test/SemaCXX/altivec.cpp b/test/SemaCXX/altivec.cpp
new file mode 100644
index 0000000..cdfc00a
--- /dev/null
+++ b/test/SemaCXX/altivec.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -faltivec -fno-lax-vector-conversions -triple powerpc-unknown-unknown -verify %s
+
+typedef int V4i __attribute__((vector_size(16)));
+
+void f(V4i a)
+{
+}
+
+void test()
+{
+ V4i vGCC;
+ vector int vAltiVec;
+
+ f(vAltiVec);
+ vGCC = vAltiVec;
+ vGCC = vGCC > vAltiVec;
+ vAltiVec = 0 ? vGCC : vGCC;
+}