Update defaults for variability of pointed-to types.

Now, if rate qualifiers aren't used to specify otherwise, varying
pointers point to uniform types by default.  As before, uniform
pointers point to varying types by default.

   float *foo;  // varying pointer to uniform float
   float * uniform foo;  // uniform pointer to varying float

These defaults seem to require the least amount of explicit
uniform/varying qualifiers for most common cases, though TBD if it
would be easier to have a single rule that e.g. the pointed-to type
is always uniform by default.
This commit is contained in:
Matt Pharr
2012-02-17 16:52:03 -08:00
parent ad429db7e8
commit 6d7ff7eba2
54 changed files with 187 additions and 131 deletions

View File

@@ -408,7 +408,11 @@ Declarator::GetType(const Type *base, DeclSpecs *ds) const {
return NULL;
}
sym->type = PointerType::GetUniform(at->GetElementType());
const Type *targetType = at->GetElementType();
targetType =
targetType->ResolveUnboundVariability(Type::Varying);
sym->type = PointerType::GetUniform(targetType);
// Make sure there are no unsized arrays (other than the
// first dimension) in function parameter lists.
at = dynamic_cast<const ArrayType *>(at->GetElementType());

View File

@@ -1499,38 +1499,46 @@ Pointer Types
It is possible to have pointers to data in memory; pointer arithmetic,
changing values in memory with pointers, and so forth is supported as in C.
::
float a = 0;
float *pa = &a;
*pa = 1; // now a == 1
Also as in C, arrays are silently converted into pointers:
::
float a[10] = { ... };
float *pa = a; // pointer to first element of a
float *pb = a + 5; // pointer to 5th element of a
As with other basic types, pointers can be both ``uniform`` and
``varying``. By default, they are varying. The placement of the
``uniform`` qualifier to declare a ``uniform`` pointer may be initially
surprising, but it matches the form of how for example a pointer that is
itself ``const`` (as opposed to pointing to a ``const`` type) is declared
in C.
``varying``.
** Like other types in ``ispc``, pointers are ``varying`` by default, if an
explicit ``uniform`` qualifier isn't provided. However, the default
variability of the pointed-to type (``uniform`` or ``varying``) is the
opposite of the pointer variability. ** This rule will be illustrated and
explained in examples below.
For example, the ``ptr`` variable in the code below is a varying pointer to
``uniform float`` values. Each program instance has a separate pointer
value and the assignment to ``*ptr`` generally represents a scatter to
memory.
::
uniform float f = 0;
uniform float * uniform pf = &f;
uniform float a[] = ...;
int index = ...;
float * ptr = &a[index];
*ptr = 1;
A ``uniform`` pointer can be declared with an appropriately-placed
qualifier:
::
float f = 0;
float * uniform pf = &f; // uniform pointer to a varying float
*pf = 1;
A subtlety comes in when a uniform pointer points to a varying datatype.
In this case, each program instance accesses a distinct location in memory
(because the underlying varying datatype is itself laid out with a separate
location in memory for each program instance.)
The placement of the ``uniform`` qualifier to declare a ``uniform`` pointer
may be initially surprising, but it matches the form of how, for example, a
pointer that is itself ``const`` (as opposed to pointing to a ``const``
type) is declared in C. (Reading the declaration from right to left gives
its meaning: a uniform pointer to a float that is varying.)
A subtlety comes in in cases like the where a uniform pointer points to a
varying datatype. In this case, each program instance accesses a distinct
location in memory (because the underlying varying datatype is itself laid
out with a separate location in memory for each program instance.)
::
@@ -1538,17 +1546,26 @@ location in memory for each program instance.)
float * uniform pa = &a;
*pa = programIndex; // same as (a = programIndex)
Also as in C, arrays are silently converted into pointers:
::
float a[10] = { ... };
float * uniform pa = a; // pointer to first element of a
float * uniform pb = a + 5; // pointer to 5th element of a
Any pointer type can be explicitly typecast to another pointer type, as
long as the source type isn't a ``varying`` pointer when the destination
type is a ``uniform`` pointer. Like other types, ``uniform`` pointers can
be typecast to be ``varying`` pointers, however.
type is a ``uniform`` pointer.
::
float *pa = ...;
int *pb = (int *)pa; // legal, but beware
Like other types, ``uniform`` pointers can be typecast to be ``varying``
pointers, however.
Any pointer type can be assigned to a ``void`` pointer without a type cast:
::
@@ -1992,7 +2009,7 @@ based on C++'s ``new`` and ``delete`` operators:
::
int count = ...;
int *ptr = new uniform int[count];
int *ptr = new int[count];
// use ptr...
delete[] ptr;
@@ -2002,13 +2019,22 @@ that memory. Uses of ``new`` and ``delete`` in ``ispc`` programs are
serviced by corresponding calls the system C library's ``malloc()`` and
``free()`` functions.
Note that the rules for ``uniform`` and ``varying`` for ``new`` are
analogous to the corresponding rules are for pointers (as described in
`Pointer Types`_.) Specifically, if a specific rate qualifier isn't
provided with the ``new`` expression, then the default is that a "varying"
``new`` is performed, where each program instance performs a unique
allocation. The allocated type, in turn, is by default ``uniform`` for
``varying`` ``new`` expressions, and ``varying`` for ``uniform`` new
expressions.
After a pointer has been deleted, it is illegal to access the memory it
points to. However, note that deletion happens on a per-program-instance
basis. In other words, consider the following code:
points to. However, that deletion happens on a per-program-instance basis.
In other words, consider the following code:
::
int *ptr = new uniform int[count];
int *ptr = new int[count];
// use ptr
if (count > 1000)
delete[] ptr;
@@ -2033,7 +2059,9 @@ gang of program instances. A ``new`` statement can be qualified with
While a regular call to ``new`` returns a ``varying`` pointer (i.e. a
distinct pointer to separately-allocated memory for each program instance),
a ``uniform new`` performs a single allocation and returns a ``uniform``
pointer.
pointer. Recall that with a ``uniform`` ``new``, the default variability
of the allocated type is ``varying``, so the above code is allocating an
array of ten ``varying float`` values.
When using ``uniform new``, it's important to be aware of a subtlety; if
the returned pointer is stored in a varying pointer variable (as may be
@@ -2043,7 +2071,7 @@ statement, which is an error: effectively
::
float *ptr = uniform new float[10];
varying float * ptr = uniform new float[10];
// use ptr...
delete ptr; // ERROR: varying pointer is deleted
@@ -2052,28 +2080,31 @@ executing program instance, which is an error (unless it happens that only
a single program instance is active in the above code.)
When using ``new`` statements, it's important to make an appropriate choice
of ``uniform`` or ``varying`` (as always, the default), for both the
``new`` operator itself as well as the type of data being allocated, based
on the program's needs. Consider the following four memory allocations:
of ``uniform`` or ``varying``, for both the ``new`` operator itself as well
as the type of data being allocated, based on the program's needs.
Consider the following four memory allocations:
::
uniform float * uniform p1 = uniform new uniform float[10];
float * uniform p2 = uniform new float[10];
uniform float * p3 = new uniform float[10];
float * p4 = new float[10];
float * p3 = new float[10];
varying float * p4 = new varying float[10];
Assuming that a ``float`` is 4 bytes in memory and if the gang size is 8
program instances, then the first allocation represents a single allocation
of 40 bytes, the second is a single allocation of 8*4*10 = 320 bytes, the
third is 8 allocations of 40 bytes, and the last performs 8 allocations of
80 bytes each.
of 10 ``uniform float`` values (40 bytes), the second is a single
allocation of 10 ``varying float`` values (8*4*10 = 320 bytes), the third
is 8 allocations of 10 ``uniform float`` values (8 allocations of 40 bytes
each), and the last performs 8 allocations of 320 bytes each.
Note in particular that varying allocations of varying data types are rarely
desirable in practice. In that case, each program instance is performing a
separate allocation of ``varying float`` memory. In this case, it's likely
that the program instances will only access a single element of each
``varying float``, which is wasteful.
``varying float``, which is wasteful. (This in turn is partially why the
allocated type is uniform by default with both pointers and ``new``
statements.)
Although ``ispc`` doesn't support constructors or destructors like C++, it
is possible to provide initializer values with ``new`` statements:

View File

@@ -264,9 +264,9 @@ lDoTypeConv(const Type *fromType, const Type *toType, Expr **expr,
if (toType->IsUniformType() && fromType->IsVaryingType()) {
if (!failureOk)
Error(pos, "Can't convert from varying type \"%s\" to uniform "
"type \"%s\" for %s.", fromType->GetString().c_str(),
toType->GetString().c_str(), errorMsgBase);
Error(pos, "Can't convert from type \"%s\" to type \"%s\" for %s.",
fromType->GetString().c_str(), toType->GetString().c_str(),
errorMsgBase);
return false;
}
@@ -5238,7 +5238,10 @@ ConstExpr::GetConstant(const Type *type) const {
int64_t iv[ISPC_MAX_NVEC];
AsInt64(iv, type->IsVaryingType());
for (int i = 0; i < Count(); ++i)
Assert(iv[i] == 0);
if (iv[i] != 0)
// We'll issue an error about this later--trying to assign
// a constant int to a pointer, without a typecast.
return NULL;
return llvm::Constant::getNullValue(llvmType);
}
@@ -6152,9 +6155,8 @@ TypeCastExpr::TypeCheck() {
toType = lDeconstifyType(toType);
if (fromType->IsVaryingType() && toType->IsUniformType()) {
Error(pos, "Can't type cast from varying type \"%s\" to uniform "
"type \"%s\"", fromType->GetString().c_str(),
toType->GetString().c_str());
Error(pos, "Can't type cast from type \"%s\" to type \"%s\"",
fromType->GetString().c_str(), toType->GetString().c_str());
return NULL;
}
@@ -7310,8 +7312,6 @@ NewExpr::NewExpr(int typeQual, const Type *t, Expr *init, Expr *count,
SourcePos tqPos, SourcePos p)
: Expr(p) {
allocType = t;
if (allocType != NULL && allocType->HasUnboundVariability())
allocType = allocType->ResolveUnboundVariability(Type::Varying);
initExpr = init;
countExpr = count;
@@ -7333,6 +7333,18 @@ NewExpr::NewExpr(int typeQual, const Type *t, Expr *init, Expr *count,
// If no type qualifier is given before the 'new', treat it as a
// varying new.
isVarying = (typeQual == 0) || (typeQual & TYPEQUAL_VARYING);
if (allocType != NULL && allocType->HasUnboundVariability()) {
Type::Variability childVariability = isVarying ?
Type::Uniform : Type::Varying;
if (dynamic_cast<const StructType *>(allocType) != NULL)
// FIXME: yet another place where the "structs are varying"
// wart pops up..
childVariability = Type::Varying;
allocType = allocType->ResolveUnboundVariability(childVariability);
}
}

View File

@@ -484,7 +484,8 @@ static inline void
aos_to_soa4(uniform int32 a[], int32 * uniform v0, int32 * uniform v1,
int32 * uniform v2, int32 * uniform v3) {
aos_to_soa4((uniform float * uniform)a, (float * uniform )v0,
(float * uniform)v1, (float * uniform)v2, (float * uniform)v3);
(float * uniform)v1, (float * uniform)v2,
(float * uniform)v3);
}
static inline void
@@ -763,24 +764,24 @@ static unsigned int64 exclusive_scan_or(unsigned int64 v) {
// packed load, store
static inline uniform int
packed_load_active(uniform unsigned int * uniform a,
packed_load_active(uniform unsigned int a[],
unsigned int * uniform vals) {
return __packed_load_active(a, vals, (UIntMaskType)__mask);
}
static inline uniform int
packed_store_active(uniform unsigned int * uniform a,
packed_store_active(uniform unsigned int a[],
unsigned int vals) {
return __packed_store_active(a, vals, (UIntMaskType)__mask);
}
static inline uniform int
packed_load_active(uniform int * uniform a, int * uniform vals) {
packed_load_active(uniform int a[], int * uniform vals) {
return __packed_load_active(a, vals, (IntMaskType)__mask);
}
static inline uniform int
packed_store_active(uniform int * uniform a, int vals) {
packed_store_active(uniform int a[], int vals) {
return __packed_store_active(a, vals, (IntMaskType)__mask);
}
@@ -1630,7 +1631,7 @@ static inline uniform float ldexp(uniform float x, uniform int n) {
return floatbits(ix);
}
static inline float frexp(float x, int * uniform pw2) {
static inline float frexp(float x, varying int * uniform pw2) {
unsigned int ex = 0x7F800000u; // exponent mask
unsigned int ix = intbits(x);
ex &= ix;
@@ -1909,8 +1910,8 @@ static inline uniform float cos(uniform float x_full) {
}
static inline void sincos(float x_full, float * uniform sin_result,
float * uniform cos_result) {
static inline void sincos(float x_full, varying float * uniform sin_result,
varying float * uniform cos_result) {
if (__math_lib == __math_lib_svml) {
__svml_sincos(x_full, sin_result, cos_result);
}
@@ -2507,8 +2508,8 @@ static inline uniform float exp(uniform float x_full) {
// Range reduction for logarithms takes log(x) -> log(2^n * y) -> n
// * log(2) + log(y) where y is the reduced range (usually in [1/2,
// 1)).
static inline void __range_reduce_log(float input, float * uniform reduced,
int * uniform exponent) {
static inline void __range_reduce_log(float input, varying float * uniform reduced,
varying int * uniform exponent) {
int int_version = intbits(input);
// single precision = SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM
// exponent mask = 0111 1111 1000 0000 0000 0000 0000 0000
@@ -2785,7 +2786,7 @@ static inline uniform double ldexp(uniform double x, uniform int n) {
return doublebits(ix);
}
static inline double frexp(double x, int * uniform pw2) {
static inline double frexp(double x, varying int * uniform pw2) {
unsigned int64 ex = 0x7ff0000000000000; // exponent mask
unsigned int64 ix = intbits(x);
ex &= ix;
@@ -2851,8 +2852,8 @@ static inline uniform double cos(uniform double x) {
return __stdlib_cos(x);
}
static inline void sincos(double x, double * uniform sin_result,
double * uniform cos_result) {
static inline void sincos(double x, varying double * uniform sin_result,
varying double * uniform cos_result) {
if (__math_lib == __math_lib_ispc_fast) {
float sr, cr;
sincos((float)x, &sr, &cr);
@@ -3391,7 +3392,7 @@ struct RNGState {
unsigned int z1, z2, z3, z4;
};
static inline unsigned int random(RNGState * uniform state)
static inline unsigned int random(varying RNGState * uniform state)
{
unsigned int b;
@@ -3406,14 +3407,14 @@ static inline unsigned int random(RNGState * uniform state)
return (state->z1 ^ state->z2 ^ state->z3 ^ state->z4);
}
static inline float frandom(RNGState * uniform state)
static inline float frandom(varying RNGState * uniform state)
{
unsigned int irand = random(state);
irand &= (1<<23)-1;
return floatbits(0x3F800000 | irand)-1.0f;
}
static inline uniform unsigned int __seed4(RNGState * uniform state,
static inline uniform unsigned int __seed4(varying RNGState * uniform state,
uniform int start,
uniform unsigned int seed) {
uniform unsigned int c1 = 0xf0f0f0f0;
@@ -3447,7 +3448,7 @@ static inline uniform unsigned int __seed4(RNGState * uniform state,
return seed;
}
static inline void seed_rng(uniform RNGState * uniform state, uniform unsigned int seed) {
static inline void seed_rng(varying RNGState * uniform state, uniform unsigned int seed) {
if (programCount == 1) {
state->z1 = seed;
state->z2 = seed ^ 0xbeeff00d;

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
void foo(float * uniform a) {
void foo(varying float * uniform a) {
*a = 0;
}

View File

@@ -4,7 +4,7 @@ export uniform int width() { return programCount; }
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float a = aFOO[programIndex];
float * uniform buf = uniform new float[programCount+1];
varying float * uniform buf = uniform new varying float[programCount+1];
for (uniform int i = 0; i < programCount+1; ++i) {
buf[i] = i+a;
}

View File

@@ -7,7 +7,7 @@ struct Point {
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float a = aFOO[programIndex];
Point * varying buf = new Point(0., b, a);
uniform Point * buf = new Point(0., b, a);
RET[programIndex] = buf->z;
delete buf;
}

View File

@@ -3,9 +3,9 @@ export uniform int width() { return programCount; }
export void f_f(uniform float RET[], uniform float aFOO[]) {
float a = aFOO[programIndex];
float * uniform pa = &a;
int * uniform pb = (int *)pa;
float *uniform pc = (float *)pb;
varying float * uniform pa = &a;
varying int * uniform pb = (varying int *)pa;
varying float *uniform pc = (varying float *)pb;
*pc = programIndex;
RET[programIndex] = *pc;
}

View File

@@ -4,7 +4,7 @@ export uniform int width() { return programCount; }
export void f_f(uniform float RET[], uniform float aFOO[]) {
int a = aFOO[programIndex];
int * uniform b = &a;
varying int * uniform b = &a;
RET[programIndex] = *b;
}

View File

@@ -6,14 +6,14 @@ struct Foo {
uniform float b;
};
void update(Foo * varying fp) {
void update(uniform Foo * varying fp) {
++fp;
fp->a -= 1;
fp->b = 1;
}
export void f_f(uniform float RET[], uniform float aFOO[]) {
Foo f[2] = { { 1234, 4321 }, { aFOO[programIndex], 5 } };
uniform Foo f[2] = { { 1234, 4321 }, { aFOO[programIndex], 5 } };
update(f);
RET[programIndex] = f[1].a;
}

View File

@@ -6,7 +6,7 @@ struct Foo {
uniform float b;
};
void update(float<3> * uniform vp) {
void update(varying float<3> * uniform vp) {
vp->x = 0;
}

View File

@@ -1,7 +1,7 @@
export uniform int width() { return programCount; }
void update(float<2> * varying vp) {
void update(varying float<2> * vp) {
vp->y = 0;
}

View File

@@ -4,7 +4,7 @@ export uniform int width() { return programCount; }
export void f_f(uniform float RET[], uniform float aFOO[]) {
int a = aFOO[programIndex];
int * uniform b = &a;
varying int * uniform b = &a;
*b = 2;
RET[programIndex] = *b;
}

View File

@@ -4,7 +4,7 @@ export uniform int width() { return programCount; }
export void f_f(uniform float RET[], uniform float aFOO[]) {
int a = aFOO[programIndex];
int * uniform b = &a;
varying int * uniform b = &a;
++*b;
RET[programIndex] = *b;
}

View File

@@ -4,7 +4,7 @@ export uniform int width() { return programCount; }
export void f_f(uniform float RET[], uniform float aFOO[]) {
int a = aFOO[programIndex];
int * uniform b = &a;
varying int * uniform b = &a;
(*b)++;
RET[programIndex] = *b;
}

View File

@@ -1,13 +1,13 @@
export uniform int width() { return programCount; }
void inc(int * uniform v) {
void inc(varying int * uniform v) {
++*v;
}
export void f_f(uniform float RET[], uniform float aFOO[]) {
int a = aFOO[programIndex];
int * uniform b = &a;
varying int * uniform b = &a;
if (a <= 2)
inc(b);
RET[programIndex] = a;

View File

@@ -1,15 +1,15 @@
export uniform int width() { return programCount; }
void inc(int * uniform v) {
void inc(varying int * uniform v) {
++*v;
}
export void f_f(uniform float RET[], uniform float aFOO[]) {
int a = aFOO[programIndex];
int * uniform b = &a;
varying int * uniform b = &a;
void * uniform vp = b;
int * uniform c = (int * uniform)vp;
varying int * uniform c = (varying int * uniform)vp;
RET[programIndex] = *c;
}

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
float foo(float * uniform a) {
float foo(varying float * uniform a) {
*a = 0;
}

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
float foo(float * uniform a) {
float foo(varying float * uniform a) {
*a = 0;
}

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
void foo(float * uniform a) {
void foo(varying float * uniform a) {
*a = 0;
}

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
void foo(float * uniform a) {
void foo(varying float * uniform a) {
*a = 0;
}

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
void foo(float * uniform a) {
void foo(varying float * uniform a) {
*a = 0;
}

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
void foo(float * uniform x, int y) {
void foo(varying float * uniform x, int y) {
*x = y;
}

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
void foo(float * uniform x, float y) {
void foo(varying float * uniform x, float y) {
*x = y;
}

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
void foo(float * uniform x) {
void foo(varying float * uniform x) {
if ((*x) <= 2)
++(*x);
}

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
float foo(float * uniform a) {
float foo(varying float * uniform a) {
*a = 0;
}

View File

@@ -3,7 +3,7 @@ typedef int<4> int4;
export uniform int width() { return programCount; }
void inc(int4 * uniform v) {
void inc(varying int4 * uniform v) {
int4 delta = { 1, 1, 1, 1 };
(*v) += delta;
}

View File

@@ -3,7 +3,7 @@ typedef int<4> int4;
export uniform int width() { return programCount; }
void incXY(int4 * uniform v) {
void incXY(varying int4 * uniform v) {
++(*v).x;
++(*v).y;
}

View File

@@ -1,4 +1,4 @@
// Illegal to assign to array type "float[5]"
// Illegal to assign to array type "varying float[5]"
void foo(float *x) {
float a[5] = { 1,2,3,4,5};

View File

@@ -1,4 +1,4 @@
// Illegal to assign to array type "float[5]"
// Illegal to assign to array type "varying float[5]"
void foo(float *x) {
float a[5] = { 1,2,3,4,5};

View File

@@ -1,4 +1,4 @@
// Illegal to assign to type "uniform struct Bar" in type "uniform struct Foo" due to element "a" with type "const int32"
// Illegal to assign to type "uniform struct Bar" in type "uniform struct Foo" due to element "a" with type "const varying int32"
struct Bar {
const int a;

View File

@@ -1,4 +1,4 @@
// Illegal to assign to type "uniform struct Foo" due to element "a" with type "const int32"
// Illegal to assign to type "uniform struct Foo" due to element "a" with type "const varying int32"
struct Foo {
const int a;

View File

@@ -1,4 +1,4 @@
// Can't assign to type "const int32" on left-hand
// Can't assign to type "const varying int32" on left-hand
int func() {
const int x = 2;

View File

@@ -1,4 +1,4 @@
// Can't assign to type "const int32" on left-hand side
// Can't assign to type "const varying int32" on left-hand side
const int x = 0;

View File

@@ -1,4 +1,4 @@
// operator "." can't be used with expression of "int32" type
// operator "." can't be used with expression of "uniform int32" type
int func(int *a) {
a.x = 0;

View File

@@ -1,4 +1,4 @@
// Illegal to dereference non-pointer or reference type "float"
// Illegal to dereference non-pointer or reference type "varying float"
float func(float a) {
*a = 0;

View File

@@ -1,4 +1,4 @@
// Member operator "->" can't be used with expression of "int32" type
// Member operator "->" can't be used with expression of "uniform int32" type
int func(int *a) {
a->x = 0;

View File

@@ -1,4 +1,4 @@
// Can't assign to type "const int32"
// Can't assign to type "const varying int32"
int foo() {
foreach (i = 0 ... 10) {

View File

@@ -1,4 +1,4 @@
// Can't convert argument of type "void * uniform" to type "float" for function call argument.
// Can't convert argument of type "void * uniform" to type "varying float" for function call argument.
float bar(float a, float b);

View File

@@ -1,3 +1,3 @@
// Initializer list for array "int32[2][4]" must have no more than 2 elements (has 3)
// Initializer list for array "varying int32[2][4]" must have no more than 2 elements (has 3)
int a[2][4] = { { 1, 2, 3 }, { 1, 2, 3, 4 }, 1 };

View File

@@ -1,4 +1,4 @@
// Can't convert from varying type "int32 *" to uniform type "int32 * uniform" for return
// Can't convert from type "uniform int32 * varying" to type "uniform int32 * uniform" for return
int * uniform func(int x) {
return new int[x];

View File

@@ -1,4 +1,4 @@
// Can't convert from varying type "float" to uniform type "uniform float" for initializer
// Can't convert from type "varying float" to type "uniform float" for initializer
struct Point {
uniform float x, y, z;

View File

@@ -1,4 +1,4 @@
// Can't assign to type "const int32 * const"
// Can't assign to type "const uniform int32 * const varying"
void foo(const int * const p) {
++p;

View File

@@ -1,4 +1,4 @@
// Can't assign to type "const int32" on left-hand side
// Can't assign to type "const varying int32" on left-hand side
void foo(const int * p) {
*p = 0;

View File

@@ -1,4 +1,4 @@
// Pointer type cast of type "int32 * uniform" to integer type "uniform int32" may lose information.
// Pointer type cast of type "varying int32 * uniform" to integer type "uniform int32" may lose information.
int32 foo(int * uniform x) {
return (int32) x;

View File

@@ -1,4 +1,4 @@
// Can't assign to type "const int32" on left-hand side of expression
// Can't assign to type "const varying int32" on left-hand side of expression
const int x[20];

View File

@@ -1,4 +1,4 @@
// Can't assign to type "const int32" on left-hand side of expression
// Can't assign to type "const varying int32" on left-hand side of expression
struct Foo {
int x;

View File

@@ -1,4 +1,4 @@
// Can't assign to type "const int32" on left-hand side of expression
// Can't assign to type "const varying int32" on left-hand side of expression
struct Foo {
int x;

View File

@@ -1,4 +1,4 @@
// Can't apply "signed" qualifier to "float" type
// Can't apply "signed" qualifier to "varying float" type
struct Foo {
signed float x;

View File

@@ -1,4 +1,4 @@
// "signed" qualifier is illegal with non-integer type "float"
// "signed" qualifier is illegal with non-integer type "varying float"
int foo() {
signed float x;

View File

@@ -1,4 +1,4 @@
// Can't apply "unsigned" qualifier to "float" type
// Can't apply "unsigned" qualifier to "varying float" type
struct Foo {
unsigned float x;

View File

@@ -1,3 +1,3 @@
// "unsigned" qualifier is illegal with "float" type
// "unsigned" qualifier is illegal with "varying float" type
unsigned float foo = 1;

View File

@@ -1,4 +1,4 @@
// Can't type cast from varying type "int32" to uniform type "uniform int32"
// Can't type cast from type "varying int32" to type "uniform int32"
uniform int foo(int x) {
return (uniform int) x;

View File

@@ -427,7 +427,7 @@ AtomicType::GetString() const {
if (isConst) ret += "const ";
switch (variability) {
case Uniform: ret += "uniform "; break;
case Varying: /*ret += "varying ";*/ break;
case Varying: ret += "varying "; break;
case Unbound: ret += "/*unbound*/ "; break;
}
}
@@ -986,9 +986,17 @@ PointerType::ResolveUnboundVariability(Variability v) const {
Assert(m->errorCount > 0);
return NULL;
}
return new PointerType(baseType->ResolveUnboundVariability(v),
(variability == Unbound) ? v : variability,
isConst);
Assert(v != Unbound);
Variability ptrVariability = (variability == Unbound) ? v : variability;
Variability childVariability = (ptrVariability == Varying) ?
Uniform : Varying;
if (dynamic_cast<const StructType *>(baseType))
// struct members are varying by default.. (FIXME!!!)
childVariability = Varying;
return new PointerType(baseType->ResolveUnboundVariability(childVariability),
ptrVariability, isConst);
}
@@ -1030,7 +1038,7 @@ PointerType::GetString() const {
if (isConst) ret += " const";
switch (variability) {
case Uniform: ret += " uniform"; break;
case Varying: /*ret += " varying";*/ break;
case Varying: ret += " varying"; break;
case Unbound: ret += " /*unbound*/"; break;
}
@@ -1964,7 +1972,7 @@ StructType::GetString() const {
switch (variability) {
case Uniform: ret += "uniform "; break;
case Varying: /*ret += "varying ";*/ break;
case Varying: ret += "varying "; break;
case Unbound: ret += "/*unbound*/ "; break;
}