From 35cc9627340b15232139b3c43fcde5973e7fad30 Mon Sep 17 00:00:00 2001 From: John Thompson Date: Mon, 9 Aug 2010 21:53:52 +0000 Subject: [PATCH] Added vecreturn attribute parsing. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110609 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Attr.td | 6 +++++ include/clang/Parse/AttributeList.h | 1 + lib/AST/AttrImpl.cpp | 1 + lib/Parse/AttributeList.cpp | 1 + lib/Sema/SemaDeclAttr.cpp | 40 +++++++++++++++++++++++++++++ test/Parser/cxx-altivec.cpp | 35 +++++++++++++++++++++++++ 6 files changed, 84 insertions(+) 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(d)) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << 9 /*class*/; + return; + } + + if (d->getAttr()) { + 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(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 +} -- 2.40.0