aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Thompson <John.Thompson.JTSoftware@gmail.com>2010-08-09 21:53:52 +0000
committerJohn Thompson <John.Thompson.JTSoftware@gmail.com>2010-08-09 21:53:52 +0000
commit35cc9627340b15232139b3c43fcde5973e7fad30 (patch)
tree75a94b73ae090ba7bd4e261910ce10f500c1f462
parent219cffcad343aef5939ca34d5abb59fbc7da1c36 (diff)
Added vecreturn attribute parsing.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110609 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/Attr.td6
-rw-r--r--include/clang/Parse/AttributeList.h1
-rw-r--r--lib/AST/AttrImpl.cpp1
-rw-r--r--lib/Parse/AttributeList.cpp1
-rw-r--r--lib/Sema/SemaDeclAttr.cpp40
-rw-r--r--test/Parser/cxx-altivec.cpp35
6 files changed, 84 insertions, 0 deletions
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 76eb9d4878..1e746c7898 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -376,6 +376,12 @@ def Visibility : Attr {
let Args = [StringArgument<"Visibility">];
}
+def VecReturn : Attr {
+ let Spellings = ["vecreturn"];
+ let Subjects = [CXXRecord];
+ let DoNotEmit = 0;
+}
+
def WarnUnusedResult : Attr {
let Spellings = ["warn_unused_result"];
}
diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h
index 2b1bd1e63d..e6bf9b6cc6 100644
--- a/include/clang/Parse/AttributeList.h
+++ b/include/clang/Parse/AttributeList.h
@@ -111,6 +111,7 @@ public:
AT_unavailable,
AT_unused,
AT_used,
+ AT_vecreturn, // PS3 PPU-specific.
AT_vector_size,
AT_visibility,
AT_warn_unused_result,
diff --git a/lib/AST/AttrImpl.cpp b/lib/AST/AttrImpl.cpp
index 8992e4823d..d9c0b5af43 100644
--- a/lib/AST/AttrImpl.cpp
+++ b/lib/AST/AttrImpl.cpp
@@ -126,6 +126,7 @@ DEF_SIMPLE_ATTR_CLONE(TransparentUnion)
DEF_SIMPLE_ATTR_CLONE(Unavailable)
DEF_SIMPLE_ATTR_CLONE(Unused)
DEF_SIMPLE_ATTR_CLONE(Used)
+DEF_SIMPLE_ATTR_CLONE(VecReturn)
DEF_SIMPLE_ATTR_CLONE(WarnUnusedResult)
DEF_SIMPLE_ATTR_CLONE(Weak)
DEF_SIMPLE_ATTR_CLONE(WeakImport)
diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp
index dc94420bef..8263923fe2 100644
--- a/lib/Parse/AttributeList.cpp
+++ b/lib/Parse/AttributeList.cpp
@@ -100,6 +100,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
.Case("format_arg", AT_format_arg)
.Case("gnu_inline", AT_gnu_inline)
.Case("weak_import", AT_weak_import)
+ .Case("vecreturn", AT_vecreturn)
.Case("vector_size", AT_vector_size)
.Case("constructor", AT_constructor)
.Case("unavailable", AT_unavailable)
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 2af3102ad7..cba5f4755d 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -687,6 +687,45 @@ static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr,
d->addAttr(::new (S.Context) AnalyzerNoReturnAttr());
}
+// PS3 PPU-specific.
+static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr,
+ Sema &S) {
+/*
+ Returning a Vector Class in Registers
+
+ According to the PPU ABI specifications, a class with a single member of vector type is returned in
+ memory when used as the return value of a function. This results in inefficient code when implementing
+ vector classes. To return the value in a single vector register, add the vecreturn attribute to the class
+ definition. This attribute is also applicable to struct types.
+
+ Example:
+
+ struct Vector
+ {
+ __vector float xyzw;
+ } __attribute__((vecreturn));
+
+ Vector Add(Vector lhs, Vector rhs)
+ {
+ Vector result;
+ result.xyzw = vec_add(lhs.xyzw, rhs.xyzw);
+ return result; // This will be returned in a register
+ }
+*/
+ if (!isa<CXXRecordDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName() << 9 /*class*/;
+ return;
+ }
+
+ if (d->getAttr<VecReturnAttr>()) {
+ S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "vecreturn";
+ return;
+ }
+
+ d->addAttr(::new (S.Context) VecReturnAttr());
+}
+
static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (!isFunctionOrMethod(d) && !isa<ParmVarDecl>(d)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
@@ -2181,6 +2220,7 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D,
case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break;
case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break;
case AttributeList::AT_override: HandleOverrideAttr (D, Attr, S); break;
+ case AttributeList::AT_vecreturn: HandleVecReturnAttr (D, Attr, S); break;
// Checker-specific.
case AttributeList::AT_ns_returns_not_retained:
diff --git a/test/Parser/cxx-altivec.cpp b/test/Parser/cxx-altivec.cpp
index a70eea077e..8f46330811 100644
--- a/test/Parser/cxx-altivec.cpp
+++ b/test/Parser/cxx-altivec.cpp
@@ -126,3 +126,38 @@ vector char v3 = (vector char)((vector int)('a', 'b', 'c', 'd'));
vector int v4 = (vector int)(1, 2, 3, 4);
vector float v5 = (vector float)(1.0f, 2.0f, 3.0f, 4.0f);
vector char v6 = (vector char)((vector int)(1+2, -2, (int)(2.0 * 3), -(5-3)));
+
+#if 0 // Not ready yet.
+// bug 7553 - Problem with '==' and vectors
+void func() {
+ vector int v10i = (vector int)(1, 2, 3, 4);
+ vector int v11i = (vector int)(1, 2, 3, 4);
+ bool r10ieq = (v10i == v11i);
+ bool r10ine = (v10i != v11i);
+ bool r10igt = (v10i > v11i);
+ bool r10ige = (v10i >= v11i);
+ bool r10ilt = (v10i < v11i);
+ bool r10ile = (v10i <= v11i);
+ vector float v10f = (vector float)(1.0f, 2.0f, 3.0f, 4.0f);
+ vector float v11f = (vector float)(1.0f, 2.0f, 3.0f, 4.0f);
+ bool r10feq = (v10f == v11f);
+ bool r10fne = (v10f != v11f);
+ bool r10fgt = (v10f > v11f);
+ bool r10fge = (v10f >= v11f);
+ bool r10flt = (v10f < v11f);
+ bool r10fle = (v10f <= v11f);
+}
+#endif
+
+// vecreturn attribute test
+struct Vector
+{
+ __vector float xyzw;
+} __attribute__((vecreturn));
+
+Vector Add(Vector lhs, Vector rhs)
+{
+ Vector result;
+ result.xyzw = vec_add(lhs.xyzw, rhs.xyzw);
+ return result; // This will (eventually) be returned in a register
+}