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:
6
decl.cpp
6
decl.cpp
@@ -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());
|
||||
|
||||
117
docs/ispc.rst
117
docs/ispc.rst
@@ -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:
|
||||
|
||||
30
expr.cpp
30
expr.cpp
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
35
stdlib.ispc
35
stdlib.ispc
@@ -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;
|
||||
|
||||
@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
|
||||
|
||||
|
||||
|
||||
void foo(float * uniform a) {
|
||||
void foo(varying float * uniform a) {
|
||||
*a = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
|
||||
|
||||
|
||||
|
||||
float foo(float * uniform a) {
|
||||
float foo(varying float * uniform a) {
|
||||
*a = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
|
||||
|
||||
|
||||
|
||||
float foo(float * uniform a) {
|
||||
float foo(varying float * uniform a) {
|
||||
*a = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
|
||||
|
||||
|
||||
|
||||
void foo(float * uniform a) {
|
||||
void foo(varying float * uniform a) {
|
||||
*a = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
|
||||
|
||||
|
||||
|
||||
void foo(float * uniform a) {
|
||||
void foo(varying float * uniform a) {
|
||||
*a = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
|
||||
|
||||
|
||||
|
||||
void foo(float * uniform a) {
|
||||
void foo(varying float * uniform a) {
|
||||
*a = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
|
||||
|
||||
|
||||
|
||||
float foo(float * uniform a) {
|
||||
float foo(varying float * uniform a) {
|
||||
*a = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
// "unsigned" qualifier is illegal with "float" type
|
||||
// "unsigned" qualifier is illegal with "varying float" type
|
||||
|
||||
unsigned float foo = 1;
|
||||
|
||||
@@ -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;
|
||||
|
||||
20
type.cpp
20
type.cpp
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user