Pointer fixes/improvements.
Allow <, <=, >, >= comparisons of pointers
Allow explicit type-casting of pointers to and from integers
Fix bug in handling expressions of the form "int + ptr" ("ptr + int"
was fine).
Fix a bug in TypeCastExpr where varying -> uniform typecasts
would be allowed (leading to a crash later)
This commit is contained in:
53
ctx.cpp
53
ctx.cpp
@@ -1156,19 +1156,62 @@ FunctionEmitContext::PtrToIntInst(llvm::Value *value, const char *name) {
|
|||||||
|
|
||||||
|
|
||||||
llvm::Value *
|
llvm::Value *
|
||||||
FunctionEmitContext::IntToPtrInst(llvm::Value *value, LLVM_TYPE_CONST llvm::Type *type,
|
FunctionEmitContext::PtrToIntInst(llvm::Value *value,
|
||||||
|
LLVM_TYPE_CONST llvm::Type *toType,
|
||||||
const char *name) {
|
const char *name) {
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
assert(m->errorCount > 0);
|
assert(m->errorCount > 0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (llvm::isa<LLVM_TYPE_CONST llvm::VectorType>(value->getType()))
|
LLVM_TYPE_CONST llvm::Type *fromType = value->getType();
|
||||||
// no-op for varying pointers; they're already vectors of ints
|
if (llvm::isa<LLVM_TYPE_CONST llvm::VectorType>(fromType)) {
|
||||||
return value;
|
// varying pointer
|
||||||
|
if (fromType == toType)
|
||||||
|
// already the right type--done
|
||||||
|
return value;
|
||||||
|
else if (fromType->getScalarSizeInBits() > toType->getScalarSizeInBits())
|
||||||
|
return TruncInst(value, toType, "ptr_to_int");
|
||||||
|
else {
|
||||||
|
assert(fromType->getScalarSizeInBits() <
|
||||||
|
toType->getScalarSizeInBits());
|
||||||
|
return ZExtInst(value, toType, "ptr_to_int");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
llvm::Instruction *inst =
|
llvm::Instruction *inst =
|
||||||
new llvm::IntToPtrInst(value, type, name ? name : "int2ptr", bblock);
|
new llvm::PtrToIntInst(value, toType, name ? name : "ptr2int", bblock);
|
||||||
|
AddDebugPos(inst);
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
llvm::Value *
|
||||||
|
FunctionEmitContext::IntToPtrInst(llvm::Value *value,
|
||||||
|
LLVM_TYPE_CONST llvm::Type *toType,
|
||||||
|
const char *name) {
|
||||||
|
if (value == NULL) {
|
||||||
|
assert(m->errorCount > 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVM_TYPE_CONST llvm::Type *fromType = value->getType();
|
||||||
|
if (llvm::isa<LLVM_TYPE_CONST llvm::VectorType>(fromType)) {
|
||||||
|
// varying pointer
|
||||||
|
if (fromType == toType)
|
||||||
|
// done
|
||||||
|
return value;
|
||||||
|
else if (fromType->getScalarSizeInBits() > toType->getScalarSizeInBits())
|
||||||
|
return TruncInst(value, toType, "int_to_ptr");
|
||||||
|
else {
|
||||||
|
assert(fromType->getScalarSizeInBits() <
|
||||||
|
toType->getScalarSizeInBits());
|
||||||
|
return ZExtInst(value, toType, "int_to_ptr");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Instruction *inst =
|
||||||
|
new llvm::IntToPtrInst(value, toType, name ? name : "int2ptr", bblock);
|
||||||
AddDebugPos(inst);
|
AddDebugPos(inst);
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
|
|||||||
4
ctx.h
4
ctx.h
@@ -41,9 +41,7 @@
|
|||||||
#include "ispc.h"
|
#include "ispc.h"
|
||||||
#include <llvm/InstrTypes.h>
|
#include <llvm/InstrTypes.h>
|
||||||
#include <llvm/Instructions.h>
|
#include <llvm/Instructions.h>
|
||||||
#ifndef LLVM_2_8
|
|
||||||
#include <llvm/Analysis/DIBuilder.h>
|
#include <llvm/Analysis/DIBuilder.h>
|
||||||
#endif
|
|
||||||
#include <llvm/Analysis/DebugInfo.h>
|
#include <llvm/Analysis/DebugInfo.h>
|
||||||
|
|
||||||
struct CFInfo;
|
struct CFInfo;
|
||||||
@@ -316,6 +314,8 @@ public:
|
|||||||
llvm::Value *BitCastInst(llvm::Value *value, LLVM_TYPE_CONST llvm::Type *type,
|
llvm::Value *BitCastInst(llvm::Value *value, LLVM_TYPE_CONST llvm::Type *type,
|
||||||
const char *name = NULL);
|
const char *name = NULL);
|
||||||
llvm::Value *PtrToIntInst(llvm::Value *value, const char *name = NULL);
|
llvm::Value *PtrToIntInst(llvm::Value *value, const char *name = NULL);
|
||||||
|
llvm::Value *PtrToIntInst(llvm::Value *value, LLVM_TYPE_CONST llvm::Type *type,
|
||||||
|
const char *name = NULL);
|
||||||
llvm::Value *IntToPtrInst(llvm::Value *value, LLVM_TYPE_CONST llvm::Type *type,
|
llvm::Value *IntToPtrInst(llvm::Value *value, LLVM_TYPE_CONST llvm::Type *type,
|
||||||
const char *name = NULL);
|
const char *name = NULL);
|
||||||
|
|
||||||
|
|||||||
123
expr.cpp
123
expr.cpp
@@ -1294,8 +1294,9 @@ BinaryExpr::GetType() const {
|
|||||||
// ptr - int -> ptr
|
// ptr - int -> ptr
|
||||||
return type0;
|
return type0;
|
||||||
}
|
}
|
||||||
// otherwise fall through for these two...
|
// otherwise fall through for these...
|
||||||
assert(op == Equal || op == NotEqual);
|
assert(op == Lt || op == Gt || op == Le || op == Ge ||
|
||||||
|
op == Equal || op == NotEqual);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Type *exprType = Type::MoreGeneralType(type0, type1, pos, lOpString(op));
|
const Type *exprType = Type::MoreGeneralType(type0, type1, pos, lOpString(op));
|
||||||
@@ -1648,6 +1649,7 @@ BinaryExpr::TypeCheck() {
|
|||||||
// put in canonical order with the pointer as the first operand
|
// put in canonical order with the pointer as the first operand
|
||||||
// for GetValue()
|
// for GetValue()
|
||||||
std::swap(arg0, arg1);
|
std::swap(arg0, arg1);
|
||||||
|
std::swap(type0, type1);
|
||||||
std::swap(pt0, pt1);
|
std::swap(pt0, pt1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1726,11 +1728,7 @@ BinaryExpr::TypeCheck() {
|
|||||||
case Sub:
|
case Sub:
|
||||||
case Mul:
|
case Mul:
|
||||||
case Div:
|
case Div:
|
||||||
case Mod:
|
case Mod: {
|
||||||
case Lt:
|
|
||||||
case Gt:
|
|
||||||
case Le:
|
|
||||||
case Ge: {
|
|
||||||
// Must be numeric type for these. (And mod is special--can't be float)
|
// Must be numeric type for these. (And mod is special--can't be float)
|
||||||
if (!type0->IsNumericType() || (op == Mod && type0->IsFloatType())) {
|
if (!type0->IsNumericType() || (op == Mod && type0->IsFloatType())) {
|
||||||
Error(arg0->pos, "First operand to binary operator \"%s\" is of "
|
Error(arg0->pos, "First operand to binary operator \"%s\" is of "
|
||||||
@@ -1756,6 +1754,10 @@ BinaryExpr::TypeCheck() {
|
|||||||
return NULL;
|
return NULL;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
case Lt:
|
||||||
|
case Gt:
|
||||||
|
case Le:
|
||||||
|
case Ge:
|
||||||
case Equal:
|
case Equal:
|
||||||
case NotEqual: {
|
case NotEqual: {
|
||||||
const PointerType *pt0 = dynamic_cast<const PointerType *>(type0);
|
const PointerType *pt0 = dynamic_cast<const PointerType *>(type0);
|
||||||
@@ -1763,14 +1765,14 @@ BinaryExpr::TypeCheck() {
|
|||||||
if (pt0 == NULL && pt1 == NULL) {
|
if (pt0 == NULL && pt1 == NULL) {
|
||||||
if (!type0->IsBoolType() && !type0->IsNumericType()) {
|
if (!type0->IsBoolType() && !type0->IsNumericType()) {
|
||||||
Error(arg0->pos,
|
Error(arg0->pos,
|
||||||
"First operand to equality operator \"%s\" is of "
|
"First operand to operator \"%s\" is of "
|
||||||
"non-comparable type \"%s\".", lOpString(op),
|
"non-comparable type \"%s\".", lOpString(op),
|
||||||
type0->GetString().c_str());
|
type0->GetString().c_str());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!type1->IsBoolType() && !type1->IsNumericType()) {
|
if (!type1->IsBoolType() && !type1->IsNumericType()) {
|
||||||
Error(arg1->pos,
|
Error(arg1->pos,
|
||||||
"Second operand to equality operator \"%s\" is of "
|
"Second operand to operator \"%s\" is of "
|
||||||
"non-comparable type \"%s\".", lOpString(op),
|
"non-comparable type \"%s\".", lOpString(op),
|
||||||
type1->GetString().c_str());
|
type1->GetString().c_str());
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -5132,30 +5134,46 @@ TypeCastExpr::GetValue(FunctionEmitContext *ctx) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// convert pointer to bool
|
assert(dynamic_cast<const AtomicType *>(toType) != NULL);
|
||||||
assert(dynamic_cast<const AtomicType *>(toType) &&
|
if (toType->IsBoolType()) {
|
||||||
toType->IsBoolType());
|
// convert pointer to bool
|
||||||
LLVM_TYPE_CONST llvm::Type *lfu =
|
LLVM_TYPE_CONST llvm::Type *lfu =
|
||||||
fromType->GetAsUniformType()->LLVMType(g->ctx);
|
fromType->GetAsUniformType()->LLVMType(g->ctx);
|
||||||
LLVM_TYPE_CONST llvm::PointerType *llvmFromUnifType =
|
LLVM_TYPE_CONST llvm::PointerType *llvmFromUnifType =
|
||||||
llvm::dyn_cast<LLVM_TYPE_CONST llvm::PointerType>(lfu);
|
llvm::dyn_cast<LLVM_TYPE_CONST llvm::PointerType>(lfu);
|
||||||
|
|
||||||
llvm::Value *nullPtrValue = llvm::ConstantPointerNull::get(llvmFromUnifType);
|
llvm::Value *nullPtrValue =
|
||||||
if (fromType->IsVaryingType())
|
llvm::ConstantPointerNull::get(llvmFromUnifType);
|
||||||
nullPtrValue = ctx->SmearUniform(nullPtrValue);
|
if (fromType->IsVaryingType())
|
||||||
|
nullPtrValue = ctx->SmearUniform(nullPtrValue);
|
||||||
|
|
||||||
llvm::Value *exprVal = expr->GetValue(ctx);
|
llvm::Value *exprVal = expr->GetValue(ctx);
|
||||||
llvm::Value *cmp = ctx->CmpInst(llvm::Instruction::ICmp,
|
llvm::Value *cmp =
|
||||||
llvm::CmpInst::ICMP_NE,
|
ctx->CmpInst(llvm::Instruction::ICmp, llvm::CmpInst::ICMP_NE,
|
||||||
exprVal, nullPtrValue, "ptr_ne_NULL");
|
exprVal, nullPtrValue, "ptr_ne_NULL");
|
||||||
|
|
||||||
if (toType->IsVaryingType()) {
|
if (toType->IsVaryingType()) {
|
||||||
if (fromType->IsUniformType())
|
if (fromType->IsUniformType())
|
||||||
cmp = ctx->SmearUniform(cmp);
|
cmp = ctx->SmearUniform(cmp);
|
||||||
cmp = ctx->I1VecToBoolVec(cmp);
|
cmp = ctx->I1VecToBoolVec(cmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmp;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// ptr -> int
|
||||||
|
llvm::Value *value = expr->GetValue(ctx);
|
||||||
|
if (value == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
return cmp;
|
if (toType->IsVaryingType() && fromType->IsUniformType())
|
||||||
|
value = ctx->SmearUniform(value);
|
||||||
|
|
||||||
|
LLVM_TYPE_CONST llvm::Type *llvmToType = toType->LLVMType(g->ctx);
|
||||||
|
if (llvmToType == NULL)
|
||||||
|
return NULL;
|
||||||
|
return ctx->PtrToIntInst(value, llvmToType, "ptr_typecast");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5304,6 +5322,17 @@ TypeCastExpr::GetValue(FunctionEmitContext *ctx) const {
|
|||||||
cast = ctx->InsertInst(cast, conv, i);
|
cast = ctx->InsertInst(cast, conv, i);
|
||||||
return cast;
|
return cast;
|
||||||
}
|
}
|
||||||
|
else if (toPointerType != NULL) {
|
||||||
|
// int -> ptr
|
||||||
|
if (toType->IsVaryingType() && fromType->IsUniformType())
|
||||||
|
exprVal = ctx->SmearUniform(exprVal);
|
||||||
|
|
||||||
|
LLVM_TYPE_CONST llvm::Type *llvmToType = toType->LLVMType(g->ctx);
|
||||||
|
if (llvmToType == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return ctx->IntToPtrInst(exprVal, llvmToType, "int_to_ptr");
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
const AtomicType *toAtomic = dynamic_cast<const AtomicType *>(toType);
|
const AtomicType *toAtomic = dynamic_cast<const AtomicType *>(toType);
|
||||||
// typechecking should ensure this is the case
|
// typechecking should ensure this is the case
|
||||||
@@ -5352,10 +5381,17 @@ TypeCastExpr::TypeCheck() {
|
|||||||
fromType = lDeconstifyType(fromType);
|
fromType = lDeconstifyType(fromType);
|
||||||
toType = lDeconstifyType(toType);
|
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());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// First some special cases that we allow only with an explicit type cast
|
// First some special cases that we allow only with an explicit type cast
|
||||||
const PointerType *ptFrom = dynamic_cast<const PointerType *>(fromType);
|
const PointerType *fromPtr = dynamic_cast<const PointerType *>(fromType);
|
||||||
const PointerType *ptTo = dynamic_cast<const PointerType *>(toType);
|
const PointerType *toPtr = dynamic_cast<const PointerType *>(toType);
|
||||||
if (ptFrom != NULL && ptTo != NULL)
|
if (fromPtr != NULL && toPtr != NULL)
|
||||||
// allow explicit typecasts between any two different pointer types
|
// allow explicit typecasts between any two different pointer types
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
@@ -5367,6 +5403,25 @@ TypeCastExpr::TypeCheck() {
|
|||||||
// Allow explicit casts between all of these
|
// Allow explicit casts between all of these
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
|
// ptr -> int type casts
|
||||||
|
if (fromPtr != NULL && toAtomic != NULL && toAtomic->IsIntType()) {
|
||||||
|
bool safeCast = (toAtomic->basicType == AtomicType::TYPE_INT64 ||
|
||||||
|
toAtomic->basicType == AtomicType::TYPE_UINT64);
|
||||||
|
if (g->target.is32Bit)
|
||||||
|
safeCast |= (toAtomic->basicType == AtomicType::TYPE_INT32 ||
|
||||||
|
toAtomic->basicType == AtomicType::TYPE_UINT32);
|
||||||
|
if (safeCast == false)
|
||||||
|
Warning(pos, "Pointer type cast of type \"%s\" to integer type "
|
||||||
|
"\"%s\" may lose information.",
|
||||||
|
fromType->GetString().c_str(),
|
||||||
|
toType->GetString().c_str());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// int -> ptr
|
||||||
|
if (fromAtomic != NULL && fromAtomic->IsIntType() && toPtr != NULL)
|
||||||
|
return this;
|
||||||
|
|
||||||
// And otherwise see if it's one of the conversions allowed to happen
|
// And otherwise see if it's one of the conversions allowed to happen
|
||||||
// implicitly.
|
// implicitly.
|
||||||
if (CanConvertTypes(fromType, toType, "type cast expression", pos) == false)
|
if (CanConvertTypes(fromType, toType, "type cast expression", pos) == false)
|
||||||
@@ -5483,6 +5538,12 @@ TypeCastExpr::Print() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Symbol *
|
||||||
|
TypeCastExpr::GetBaseSymbol() const {
|
||||||
|
return expr ? expr->GetBaseSymbol() : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
llvm::Constant *
|
llvm::Constant *
|
||||||
TypeCastExpr::GetConstant(const Type *constType) const {
|
TypeCastExpr::GetConstant(const Type *constType) const {
|
||||||
// We don't need to worry about most the basic cases where the type
|
// We don't need to worry about most the basic cases where the type
|
||||||
|
|||||||
1
expr.h
1
expr.h
@@ -502,6 +502,7 @@ public:
|
|||||||
Expr *TypeCheck();
|
Expr *TypeCheck();
|
||||||
Expr *Optimize();
|
Expr *Optimize();
|
||||||
int EstimateCost() const;
|
int EstimateCost() const;
|
||||||
|
Symbol *GetBaseSymbol() const;
|
||||||
llvm::Constant *GetConstant(const Type *type) const;
|
llvm::Constant *GetConstant(const Type *type) const;
|
||||||
|
|
||||||
const Type *type;
|
const Type *type;
|
||||||
|
|||||||
2
opt.cpp
2
opt.cpp
@@ -63,7 +63,7 @@
|
|||||||
#include <llvm/Support/StandardPasses.h>
|
#include <llvm/Support/StandardPasses.h>
|
||||||
#else
|
#else
|
||||||
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
|
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
|
||||||
#endif // LLVM_2_8
|
#endif // LLVM_2_9
|
||||||
#include <llvm/ADT/Triple.h>
|
#include <llvm/ADT/Triple.h>
|
||||||
#include <llvm/Transforms/Scalar.h>
|
#include <llvm/Transforms/Scalar.h>
|
||||||
#include <llvm/Transforms/IPO.h>
|
#include <llvm/Transforms/IPO.h>
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ def run_tasks_from_queue(queue):
|
|||||||
# is this a test to make sure an error is issued?
|
# is this a test to make sure an error is issued?
|
||||||
want_error = (filename.find("tests_errors") != -1)
|
want_error = (filename.find("tests_errors") != -1)
|
||||||
if want_error == True:
|
if want_error == True:
|
||||||
ispc_cmd = "ispc --nowrap --woff %s --arch=%s --target=%s" % \
|
ispc_cmd = "ispc --nowrap %s --arch=%s --target=%s" % \
|
||||||
( filename, options.arch, options.target)
|
( filename, options.arch, options.target)
|
||||||
sp = subprocess.Popen(shlex.split(ispc_cmd), stdin=None, stdout=subprocess.PIPE,
|
sp = subprocess.Popen(shlex.split(ispc_cmd), stdin=None, stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE)
|
stderr=subprocess.PIPE)
|
||||||
|
|||||||
12
tests/ptr-cmp-1.ispc
Normal file
12
tests/ptr-cmp-1.ispc
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_f(uniform float RET[], uniform float aFOO[]) {
|
||||||
|
uniform float * varying b = &aFOO[10];
|
||||||
|
uniform float * uniform c = aFOO;
|
||||||
|
RET[programIndex] = (b > c) ? 10 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 10;
|
||||||
|
}
|
||||||
12
tests/ptr-cmp-2.ispc
Normal file
12
tests/ptr-cmp-2.ispc
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_f(uniform float RET[], uniform float aFOO[]) {
|
||||||
|
uniform float * uniform b = aFOO;
|
||||||
|
uniform float * uniform c = aFOO;
|
||||||
|
RET[programIndex] = (c <= b) ? 10 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 10;
|
||||||
|
}
|
||||||
12
tests/ptr-diff-4.ispc
Normal file
12
tests/ptr-diff-4.ispc
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_f(uniform float RET[], uniform float aFOO[]) {
|
||||||
|
uniform float * varying b = aFOO;
|
||||||
|
b = 5 + b;
|
||||||
|
RET[programIndex] = b - aFOO;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 5;
|
||||||
|
}
|
||||||
12
tests/ptr-diff-5.ispc
Normal file
12
tests/ptr-diff-5.ispc
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_f(uniform float RET[], uniform float aFOO[]) {
|
||||||
|
uniform float * varying b = aFOO;
|
||||||
|
uniform float * uniform c = &aFOO[10];
|
||||||
|
RET[programIndex] = c - b;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 10;
|
||||||
|
}
|
||||||
12
tests/ptr-diff-6.ispc
Normal file
12
tests/ptr-diff-6.ispc
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_f(uniform float RET[], uniform float aFOO[]) {
|
||||||
|
uniform float * varying b = &aFOO[10];
|
||||||
|
uniform float * uniform c = aFOO;
|
||||||
|
RET[programIndex] = b - c;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 10;
|
||||||
|
}
|
||||||
14
tests/ptr-int-1.ispc
Normal file
14
tests/ptr-int-1.ispc
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
|
||||||
|
export void f_f(uniform float RET[], uniform float aFOO[]) {
|
||||||
|
uniform int a = 1;
|
||||||
|
uniform int * uniform b = &a;
|
||||||
|
int64 pi = (int64)b;
|
||||||
|
RET[programIndex] = *((uniform int * varying)pi);
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 1;
|
||||||
|
}
|
||||||
4
tests_errors/func-export-task.ispc
Normal file
4
tests_errors/func-export-task.ispc
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
// Function can't have both "task" and "export" qualifiers
|
||||||
|
|
||||||
|
export task void foo() {
|
||||||
|
}
|
||||||
6
tests_errors/ptrcast-lose-info.ispc
Normal file
6
tests_errors/ptrcast-lose-info.ispc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// Pointer type cast of type "int32 * uniform" to integer type "uniform int32" may lose information.
|
||||||
|
|
||||||
|
int32 foo(int * uniform x) {
|
||||||
|
return (int32) x;
|
||||||
|
}
|
||||||
|
|
||||||
6
tests_errors/vary-to-unif-typecast.ispc
Normal file
6
tests_errors/vary-to-unif-typecast.ispc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// Can't type cast from varying type "int32" to uniform type "uniform int32"
|
||||||
|
|
||||||
|
uniform int foo(int x) {
|
||||||
|
return (uniform int) x;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user