diff --git a/expr.cpp b/expr.cpp index 8b9e7042..e67cb814 100644 --- a/expr.cpp +++ b/expr.cpp @@ -135,6 +135,21 @@ lMaybeIssuePrecisionWarning(const AtomicType *toAtomicType, /////////////////////////////////////////////////////////////////////////// +static Expr * +lArrayToPointer(Expr *expr) { + assert(expr && dynamic_cast(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 lIsAllIntZeros(Expr *expr) { const Type *type = expr->GetType(); @@ -1652,6 +1667,16 @@ BinaryExpr::TypeCheck() { assert(type1 != NULL); } + // Convert arrays to pointers to their first elements + if (dynamic_cast(type0) != NULL) { + arg0 = lArrayToPointer(arg0); + type0 = arg0->GetType(); + } + if (dynamic_cast(type1) != NULL) { + arg1 = lArrayToPointer(arg1); + type1 = arg1->GetType(); + } + const PointerType *pt0 = dynamic_cast(type0); const PointerType *pt1 = dynamic_cast(type1); if (pt0 != NULL && pt1 != NULL && op == Sub) { @@ -5241,24 +5266,18 @@ TypeCastExpr::GetValue(FunctionEmitContext *ctx) const { if (fromArrayType != NULL && toPointerType != NULL) { // implicit array to pointer to first element - Expr *zero = new ConstExpr(AtomicType::UniformInt32, 0, pos); - Expr *index = new IndexExpr(expr, zero, pos); - Expr *addr = new AddressOfExpr(index, pos); - 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(), + Expr *arrayAsPtr = lArrayToPointer(expr); + if (Type::EqualIgnoringConst(arrayAsPtr->GetType(), toPointerType) == false) { + assert(Type::EqualIgnoringConst(arrayAsPtr->GetType()->GetAsVaryingType(), toPointerType) == true); - addr = new TypeCastExpr(toPointerType, addr, false, pos); - addr = addr->TypeCheck(); - assert(addr != NULL); - addr = addr->Optimize(); - assert(addr != NULL); + arrayAsPtr = new TypeCastExpr(toPointerType, arrayAsPtr, false, pos); + arrayAsPtr = arrayAsPtr->TypeCheck(); + assert(arrayAsPtr != NULL); + arrayAsPtr = arrayAsPtr->Optimize(); + assert(arrayAsPtr != NULL); } - assert(Type::EqualIgnoringConst(addr->GetType(), toPointerType)); - return addr->GetValue(ctx); + assert(Type::EqualIgnoringConst(arrayAsPtr->GetType(), toPointerType)); + return arrayAsPtr->GetValue(ctx); } // This also should be caught during typechecking @@ -5738,8 +5757,8 @@ DereferenceExpr::GetValue(FunctionEmitContext *ctx) const { return NULL; Symbol *baseSym = expr->GetBaseSymbol(); - assert(baseSym != NULL); - llvm::Value *mask = lMaskForSymbol(baseSym, ctx); + llvm::Value *mask = baseSym ? lMaskForSymbol(baseSym, ctx) : + ctx->GetFullMask(); ctx->SetDebugPos(pos); return ctx->LoadInst(ptr, mask, type, "deref_load"); diff --git a/tests/array-pointer-duality-1.ispc b/tests/array-pointer-duality-1.ispc new file mode 100644 index 00000000..4982897e --- /dev/null +++ b/tests/array-pointer-duality-1.ispc @@ -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; +} diff --git a/tests/array-pointer-duality-2.ispc b/tests/array-pointer-duality-2.ispc new file mode 100644 index 00000000..784e14bb --- /dev/null +++ b/tests/array-pointer-duality-2.ispc @@ -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; +}