Convert arrays to pointers in expressions like (a+5)
This was one instance of the C-style array/pointer duality that was missed the first time around.
This commit is contained in:
55
expr.cpp
55
expr.cpp
@@ -135,6 +135,21 @@ lMaybeIssuePrecisionWarning(const AtomicType *toAtomicType,
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static Expr *
|
||||||
|
lArrayToPointer(Expr *expr) {
|
||||||
|
assert(expr && dynamic_cast<const ArrayType *>(expr->GetType()));
|
||||||
|
|
||||||
|
Expr *zero = new ConstExpr(AtomicType::UniformInt32, 0, expr->pos);
|
||||||
|
Expr *index = new IndexExpr(expr, zero, expr->pos);
|
||||||
|
Expr *addr = new AddressOfExpr(index, expr->pos);
|
||||||
|
addr = addr->TypeCheck();
|
||||||
|
assert(addr != NULL);
|
||||||
|
addr = addr->Optimize();
|
||||||
|
assert(addr != NULL);
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
lIsAllIntZeros(Expr *expr) {
|
lIsAllIntZeros(Expr *expr) {
|
||||||
const Type *type = expr->GetType();
|
const Type *type = expr->GetType();
|
||||||
@@ -1652,6 +1667,16 @@ BinaryExpr::TypeCheck() {
|
|||||||
assert(type1 != NULL);
|
assert(type1 != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert arrays to pointers to their first elements
|
||||||
|
if (dynamic_cast<const ArrayType *>(type0) != NULL) {
|
||||||
|
arg0 = lArrayToPointer(arg0);
|
||||||
|
type0 = arg0->GetType();
|
||||||
|
}
|
||||||
|
if (dynamic_cast<const ArrayType *>(type1) != NULL) {
|
||||||
|
arg1 = lArrayToPointer(arg1);
|
||||||
|
type1 = arg1->GetType();
|
||||||
|
}
|
||||||
|
|
||||||
const PointerType *pt0 = dynamic_cast<const PointerType *>(type0);
|
const PointerType *pt0 = dynamic_cast<const PointerType *>(type0);
|
||||||
const PointerType *pt1 = dynamic_cast<const PointerType *>(type1);
|
const PointerType *pt1 = dynamic_cast<const PointerType *>(type1);
|
||||||
if (pt0 != NULL && pt1 != NULL && op == Sub) {
|
if (pt0 != NULL && pt1 != NULL && op == Sub) {
|
||||||
@@ -5241,24 +5266,18 @@ TypeCastExpr::GetValue(FunctionEmitContext *ctx) const {
|
|||||||
|
|
||||||
if (fromArrayType != NULL && toPointerType != NULL) {
|
if (fromArrayType != NULL && toPointerType != NULL) {
|
||||||
// implicit array to pointer to first element
|
// implicit array to pointer to first element
|
||||||
Expr *zero = new ConstExpr(AtomicType::UniformInt32, 0, pos);
|
Expr *arrayAsPtr = lArrayToPointer(expr);
|
||||||
Expr *index = new IndexExpr(expr, zero, pos);
|
if (Type::EqualIgnoringConst(arrayAsPtr->GetType(), toPointerType) == false) {
|
||||||
Expr *addr = new AddressOfExpr(index, pos);
|
assert(Type::EqualIgnoringConst(arrayAsPtr->GetType()->GetAsVaryingType(),
|
||||||
addr = addr->TypeCheck();
|
|
||||||
assert(addr != NULL);
|
|
||||||
addr = addr->Optimize();
|
|
||||||
assert(addr != NULL);
|
|
||||||
if (Type::EqualIgnoringConst(addr->GetType(), toPointerType) == false) {
|
|
||||||
assert(Type::EqualIgnoringConst(addr->GetType()->GetAsVaryingType(),
|
|
||||||
toPointerType) == true);
|
toPointerType) == true);
|
||||||
addr = new TypeCastExpr(toPointerType, addr, false, pos);
|
arrayAsPtr = new TypeCastExpr(toPointerType, arrayAsPtr, false, pos);
|
||||||
addr = addr->TypeCheck();
|
arrayAsPtr = arrayAsPtr->TypeCheck();
|
||||||
assert(addr != NULL);
|
assert(arrayAsPtr != NULL);
|
||||||
addr = addr->Optimize();
|
arrayAsPtr = arrayAsPtr->Optimize();
|
||||||
assert(addr != NULL);
|
assert(arrayAsPtr != NULL);
|
||||||
}
|
}
|
||||||
assert(Type::EqualIgnoringConst(addr->GetType(), toPointerType));
|
assert(Type::EqualIgnoringConst(arrayAsPtr->GetType(), toPointerType));
|
||||||
return addr->GetValue(ctx);
|
return arrayAsPtr->GetValue(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This also should be caught during typechecking
|
// This also should be caught during typechecking
|
||||||
@@ -5738,8 +5757,8 @@ DereferenceExpr::GetValue(FunctionEmitContext *ctx) const {
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Symbol *baseSym = expr->GetBaseSymbol();
|
Symbol *baseSym = expr->GetBaseSymbol();
|
||||||
assert(baseSym != NULL);
|
llvm::Value *mask = baseSym ? lMaskForSymbol(baseSym, ctx) :
|
||||||
llvm::Value *mask = lMaskForSymbol(baseSym, ctx);
|
ctx->GetFullMask();
|
||||||
|
|
||||||
ctx->SetDebugPos(pos);
|
ctx->SetDebugPos(pos);
|
||||||
return ctx->LoadInst(ptr, mask, type, "deref_load");
|
return ctx->LoadInst(ptr, mask, type, "deref_load");
|
||||||
|
|||||||
15
tests/array-pointer-duality-1.ispc
Normal file
15
tests/array-pointer-duality-1.ispc
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
|
||||||
|
export void f_f(uniform float RET[], uniform float aFOO[]) {
|
||||||
|
uniform float a[programCount];
|
||||||
|
for (unsigned int i = 0; i < programCount; ++i)
|
||||||
|
a[i] = aFOO[i];
|
||||||
|
|
||||||
|
RET[programIndex] = *(a + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 3;
|
||||||
|
}
|
||||||
17
tests/array-pointer-duality-2.ispc
Normal file
17
tests/array-pointer-duality-2.ispc
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
uniform int a[4][4][4];
|
||||||
|
for (uniform int i = 0; i < 4; ++i)
|
||||||
|
for (uniform int j = 0; j < 4; ++j)
|
||||||
|
for (uniform int k = 0; k < 4; ++k)
|
||||||
|
a[i][j][k] = 100*i+10*j+k;
|
||||||
|
|
||||||
|
RET[programIndex] = *(a[2][3] + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 231;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user