parent
685cb32d2b
commit
cdb847ba16
|
@ -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"];
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue