diff --git a/docs/ispc.rst b/docs/ispc.rst index e3138760..ad364396 100644 --- a/docs/ispc.rst +++ b/docs/ispc.rst @@ -2938,23 +2938,28 @@ Function Overloading -------------------- Functions can be overloaded by parameter type. Given multiple definitions -of a function, ``ispc`` uses the following methods to try to find a match. -If a single match of a given type is found, it is used; if multiple matches -of a given type are found, an error is issued. +of a function, ``ispc`` uses the following model to choose the best function: +each conversion of two types has its cost. ``ispc`` tries to find conversion +with the smallest cost. When ``ispc`` can't find any conversion it means that +this function is not suitable. Then ``ispc`` sums costs for all arguments and +chooses the function with the smallest final cost. If the chosen function +has some arguments which costs are bigger than their costs in other function +this treats as ambiguous. +Costs of type conversions placed from small to big: -* All parameter types match exactly. -* All parameter types match exactly, where any reference-type - parameters are considered equivalent to their underlying type. -* Parameters match with only type conversions that don't risk losing any - information (for example, converting an ``int16`` value to an ``int32`` - parameter value.) -* Parameters match with only promotions from ``uniform`` to ``varying`` - types. -* Parameters match using arbitrary type conversion, without changing - variability from ``uniform`` to ``varying`` (e.g., ``int`` to ``float``, - ``float`` to ``int``.) -* Parameters match using arbitrary type conversion, including also changing - variability from ``uniform`` to ``varying`` as needed. +1. Parameter types match exactly. +2. Function parameter type is reference and parameters match when any reference-type parameter are considered equivalent to their underlying type. +3. Function parameter type is const-reference and parameters match when any reference-type parameter are considered equivalent to their underlying type ignoring const attributes. +4. Parameters match exactly, except constant attributes. [NO CONSTANT ATTRIBUTES LATER] +5. Parameters match exactly, except reference attributes. [NO REFERENCES ATTRIBUTES LATER] +6. Parameters match with only type conversions that don't risk losing any information (for example, converting an int16 value to an int32 parameter value.) +7. Parameters match with only promotions from uniform to varying types. +8. Parameters match using arbitrary type conversion, without changing variability from uniform to varying (e.g., int to float, float to int.) +9. Parameters match with widening and promotions from uniform to varying types. (combination of "6" and "7") +10. Parameters match using arbitrary type conversion, including also changing variability from uniform to varying. + +* If function parameter type is reference and neither "2" nor "3" aren't suitable, function is not suitable +* If "10" isn't suitable, function is not suitable Re-establishing The Execution Mask diff --git a/expr.cpp b/expr.cpp index cb1f8dcc..57c140cc 100644 --- a/expr.cpp +++ b/expr.cpp @@ -8097,23 +8097,6 @@ lGetOverloadCandidateMessage(const std::vector &funcs, } -static bool -lIsMatchToNonConstReference(const Type *callType, const Type *funcArgType) { - return (CastType(funcArgType) && - (funcArgType->IsConstType() == false) && - Type::Equal(callType, funcArgType->GetReferenceTarget())); -} - - -static bool -lIsMatchToNonConstReferenceUnifToVarying(const Type *callType, - const Type *funcArgType) { - return (CastType(funcArgType) && - (funcArgType->IsConstType() == false) && - Type::Equal(callType->GetAsVaryingType(), - funcArgType->GetReferenceTarget())); -} - /** Helper function used for function overload resolution: returns true if converting the argument to the call type only requires a type conversion that won't lose information. Otherwise return false. @@ -8160,31 +8143,6 @@ lIsMatchWithTypeWidening(const Type *callType, const Type *funcArgType) { } -/** Helper function used for function overload resolution: returns true if - the call argument type and the function argument type match if we only - do a uniform -> varying type conversion but otherwise have exactly the - same type. - */ -static bool -lIsMatchWithUniformToVarying(const Type *callType, const Type *funcArgType) { - return (callType->IsUniformType() && - funcArgType->IsVaryingType() && - Type::EqualIgnoringConst(callType->GetAsVaryingType(), funcArgType)); -} - - -/** Helper function used for function overload resolution: returns true if - we can type convert from the call argument type to the function - argument type, but without doing a uniform -> varying conversion. - */ -static bool -lIsMatchWithTypeConvSameVariability(const Type *callType, - const Type *funcArgType) { - return (CanConvertTypes(callType, funcArgType) && - (callType->GetVariability() == funcArgType->GetVariability())); -} - - /* Returns the set of function overloads that are potential matches, given argCount values being passed as arguments to the function call. */ @@ -8236,13 +8194,15 @@ int FunctionSymbolExpr::computeOverloadCost(const FunctionType *ftype, const std::vector &argTypes, const std::vector *argCouldBeNULL, - const std::vector *argIsConstant) { + const std::vector *argIsConstant, + int * cost) { int costSum = 0; // In computing the cost function, we only worry about the actual // argument types--using function default parameter values is free for // the purposes here... for (int i = 0; i < (int)argTypes.size(); ++i) { + cost[i] = 0; // The cost imposed by this argument will be a multiple of // costScale, which has a value set so that for each of the cost // buckets, even if all of the function arguments undergo the next @@ -8255,51 +8215,105 @@ FunctionSymbolExpr::computeOverloadCost(const FunctionType *ftype, if (Type::Equal(callType, fargType)) // Perfect match: no cost - costSum += 0; + // Step "1" from documentation + cost[i] += 0; else if (argCouldBeNULL && (*argCouldBeNULL)[i] && lArgIsPointerType(fargType)) - // Passing NULL to a pointer-typed parameter is also a no-cost - // operation - costSum += 0; + // Passing NULL to a pointer-typed parameter is also a no-cost operation + // Step "1" from documentation + cost[i] += 0; else { // If the argument is a compile-time constant, we'd like to // count the cost of various conversions as much lower than the // cost if it wasn't--so scale up the cost when this isn't the // case.. if (argIsConstant == NULL || (*argIsConstant)[i] == false) - costScale *= 128; + costScale *= 512; - // For convenience, normalize to non-const types (except for - // references, where const-ness matters). For all other types, - // we're passing by value anyway, so const doesn't matter. - const Type *callTypeNC = callType, *fargTypeNC = fargType; - if (CastType(callType) == NULL) - callTypeNC = callType->GetAsNonConstType(); - if (CastType(fargType) == NULL) - fargTypeNC = fargType->GetAsNonConstType(); + if (CastType(fargType)) { + // Here we completely handle the case where fargType is reference. + if (callType->IsConstType() && !fargType->IsConstType()) { + // It is forbidden to pass const object to non-const reference (cvf -> vfr) + return -1; + } + if (!callType->IsConstType() && fargType->IsConstType()) { + // It is possible to pass (vf -> cvfr) + // but it is worse than (vf -> vfr) or (cvf -> cvfr) + // Step "3" from documentation + cost[i] += 2 * costScale; + } + if (!Type::Equal(callType->GetReferenceTarget()->GetAsNonConstType(), + fargType->GetReferenceTarget()->GetAsNonConstType())) { + // Types under references must be equal completely. + // vd -> vfr or vd -> cvfr are forbidden. (Although clang allows vd -> cvfr case.) + return -1; + } + // penalty for equal types under reference (vf -> vfr is worse than vf -> vf) + // Step "2" from documentation + cost[i] += 2 * costScale; + continue; + } + const Type *callTypeNP = callType; + if (CastType(callType)) { + callTypeNP = callType->GetReferenceTarget(); + // we can treat vfr as vf for callType with some penalty + // Step "5" from documentation + cost[i] += 2 * costScale; + } - if (Type::Equal(callTypeNC, fargTypeNC)) - // Exact match (after dealing with references, above) - costSum += 1 * costScale; - // note: orig fargType for the next two... - else if (lIsMatchToNonConstReference(callTypeNC, fargType)) - costSum += 2 * costScale; - else if (lIsMatchToNonConstReferenceUnifToVarying(callTypeNC, fargType)) - costSum += 4 * costScale; - else if (lIsMatchWithTypeWidening(callTypeNC, fargTypeNC)) - costSum += 8 * costScale; - else if (lIsMatchWithUniformToVarying(callTypeNC, fargTypeNC)) - costSum += 16 * costScale; - else if (lIsMatchWithTypeConvSameVariability(callTypeNC, fargTypeNC)) - costSum += 32 * costScale; - else if (CanConvertTypes(callTypeNC, fargTypeNC)) - costSum += 64 * costScale; + // Now we deal with references, so we can normalize to non-const types + // because we're passing by value anyway, so const doesn't matter. + const Type *callTypeNC = callTypeNP, *fargTypeNC = fargType; + callTypeNC = callTypeNP->GetAsNonConstType(); + fargTypeNC = fargType->GetAsNonConstType(); + + // Now we forget about constants and references! + if (Type::Equal(callTypeNC, fargTypeNC)) { + // The best case: vf -> vf. + // Step "4" from documentation + cost[i] += 1 * costScale; + continue; + } + if (lIsMatchWithTypeWidening(callTypeNC, fargTypeNC)) { + // A little bit worse case: vf -> vd. + // Step "6" from documentation + cost[i] += 8 * costScale; + continue; + } + if (fargType->IsVaryingType() && callType->IsUniformType()) { + // Here we deal with brodcasting uniform to varying. + // callType - varying and fargType - uniform is forbidden. + if (Type::Equal(callTypeNC->GetAsVaryingType(), fargTypeNC)) { + // uf -> vf is better than uf -> ui or uf -> ud + // Step "7" from documentation + cost[i] += 16 * costScale; + continue; + } + if (lIsMatchWithTypeWidening(callTypeNC->GetAsVaryingType(), fargTypeNC)) { + // uf -> vd is better than uf -> vi (128 < 128 + 64) + // but worse than uf -> ui (128 > 64) + // Step "9" from documentation + cost[i] += 128 * costScale; + continue; + } + // 128 + 64 is the max. uf -> vi is the worst case. + // Step "10" from documentation + cost[i] += 128 * costScale; + } + if (CanConvertTypes(callTypeNC, fargTypeNC)) + // two cases: the worst is 128 + 64: uf -> vi and + // the only 64: (64 < 128) uf -> ui worse than uf -> vd + // Step "8" from documentation + cost[i] += 64 * costScale; else // Failure--no type conversion possible... return -1; } } + for (int i = 0; i < (int)argTypes.size(); ++i) { + costSum = costSum + cost[i]; + } return costSum; } @@ -8334,6 +8348,7 @@ FunctionSymbolExpr::ResolveOverloads(SourcePos argPos, int bestMatchCost = 1<<30; std::vector matches; std::vector candidateCosts; + std::vector candidateExpandCosts; if (actualCandidates.size() == 0) goto failure; @@ -8343,9 +8358,12 @@ FunctionSymbolExpr::ResolveOverloads(SourcePos argPos, const FunctionType *ft = CastType(actualCandidates[i]->type); AssertPos(pos, ft != NULL); + int * cost = new int[argTypes.size()]; candidateCosts.push_back(computeOverloadCost(ft, argTypes, argCouldBeNULL, - argIsConstant)); + argIsConstant, + cost)); + candidateExpandCosts.push_back(cost); } // Find the best cost, and then the candidate or candidates that have @@ -8358,8 +8376,28 @@ FunctionSymbolExpr::ResolveOverloads(SourcePos argPos, if (bestMatchCost == (1<<30)) goto failure; for (int i = 0; i < (int)candidateCosts.size(); ++i) { - if (candidateCosts[i] == bestMatchCost) + if (candidateCosts[i] == bestMatchCost) { + for (int j = 0; j < (int)candidateCosts.size(); ++j) { + for (int k = 0; k < argTypes.size(); k++) { + if (candidateCosts[j] != -1 && + candidateExpandCosts[j][k] < candidateExpandCosts[i][k]) { + std::vector temp; + temp.push_back(actualCandidates[i]); + temp.push_back(actualCandidates[j]); + std::string candidateMessage = + lGetOverloadCandidateMessage(temp, argTypes, argCouldBeNULL); + Warning(pos, "call to \"%s\" is ambiguous. " + "This warning will be turned into error in the next ispc release.\n" + "Please add explicit cast to arguments to have unambiguous match." + "\n%s", funName, candidateMessage.c_str()); + } + } + } matches.push_back(actualCandidates[i]); + } + } + for (int i = 0; i < (int)candidateExpandCosts.size(); ++i) { + delete [] candidateExpandCosts[i]; } if (matches.size() == 1) { diff --git a/expr.h b/expr.h index b539ff1b..7d209bba 100644 --- a/expr.h +++ b/expr.h @@ -635,7 +635,8 @@ private: static int computeOverloadCost(const FunctionType *ftype, const std::vector &argTypes, const std::vector *argCouldBeNULL, - const std::vector *argIsConstant); + const std::vector *argIsConstant, + int * cost); /** Name of the function that is being called. */ std::string name; diff --git a/module.cpp b/module.cpp index d8f165bc..db378591 100644 --- a/module.cpp +++ b/module.cpp @@ -840,7 +840,6 @@ Module::AddFunctionDeclaration(const std::string &name, // Set function attributes: we never throw exceptions function->setDoesNotThrow(); if (storageClass != SC_EXTERN_C && - !g->generateDebuggingSymbols && isInline) #ifdef LLVM_3_2 function->addFnAttr(llvm::Attributes::AlwaysInline); @@ -1273,7 +1272,12 @@ lEmitStructDecl(const StructType *st, std::vector *emittedSt for (int i = 0; i < st->GetElementCount(); ++i) { const Type *type = st->GetElementType(i)->GetAsNonConstType(); std::string d = type->GetCDeclaration(st->GetElementName(i)); - fprintf(file, " %s;\n", d.c_str()); + if (type->IsVaryingType()) { + fprintf(file, " %s[%d];\n", d.c_str(), g->target->getVectorWidth()); + } + else { + fprintf(file, " %s;\n", d.c_str()); + } } fprintf(file, "};\n"); fprintf(file, "#endif\n\n"); diff --git a/tests/array-mixed-unif-vary-indexing-2.ispc b/tests/array-mixed-unif-vary-indexing-2.ispc index 8143ca29..a885a136 100644 --- a/tests/array-mixed-unif-vary-indexing-2.ispc +++ b/tests/array-mixed-unif-vary-indexing-2.ispc @@ -16,7 +16,7 @@ export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { else x[a][b-1] = 1; - a = min(a, 46); + a = min(a, 46.f); RET[programIndex] = x[3][a]; } diff --git a/tests/array-mixed-unif-vary-indexing.ispc b/tests/array-mixed-unif-vary-indexing.ispc index 96fc0870..bd3e6919 100644 --- a/tests/array-mixed-unif-vary-indexing.ispc +++ b/tests/array-mixed-unif-vary-indexing.ispc @@ -10,7 +10,7 @@ export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { for (uniform int j = 0; j < 47; ++j) x[i][j] = 2+b-5; - a = min(a,46); + a = min(a,46.f); x[a][b-1] = 0; RET[programIndex] = x[2][a]; } diff --git a/tests/array-multidim-gather-scatter.ispc b/tests/array-multidim-gather-scatter.ispc index 1528b070..4fc59f52 100644 --- a/tests/array-multidim-gather-scatter.ispc +++ b/tests/array-multidim-gather-scatter.ispc @@ -11,7 +11,7 @@ export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { uniform int index[4] = { 0, 1, 2, 4 }; float v = index[programIndex & 0x3]; - x[min(a,39)][v] = 0; + x[min(a,39.f)][v] = 0; RET[programIndex] = x[v+1][v]; } diff --git a/tests/func-overload-max.ispc b/tests/func-overload-max.ispc index 37360030..44b20db7 100644 --- a/tests/func-overload-max.ispc +++ b/tests/func-overload-max.ispc @@ -4,7 +4,7 @@ export uniform int width() { return programCount; } export void f_f(uniform float RET[], uniform float aFOO[]) { float a = 1. / aFOO[programIndex]; - RET[programIndex] = max(0, a); + RET[programIndex] = max(0.f, a); } export void result(uniform float RET[]) { diff --git a/tests/funcptr-uniform-10.ispc b/tests/funcptr-uniform-10.ispc index 75fcbfe9..8490778f 100644 --- a/tests/funcptr-uniform-10.ispc +++ b/tests/funcptr-uniform-10.ispc @@ -16,7 +16,7 @@ export void f_f(uniform float RET[], uniform float aFOO[]) { uniform FuncType func[] = { bar, foo }; float a = aFOO[programIndex]; float b = aFOO[0]-1; // == 0 - func[min(a, 0)] = foo; + func[min(a, 0.f)] = foo; RET[programIndex] = func[0](a, b); } diff --git a/tests/goto-4.ispc b/tests/goto-4.ispc index 97c373ef..9d5bf630 100644 --- a/tests/goto-4.ispc +++ b/tests/goto-4.ispc @@ -9,7 +9,7 @@ export void f_f(uniform float RET[], uniform float aFOO[]) { encore: ++RET[programIndex]; if (any(a != 0)) { - a = max(a-1, 0); + a = max(a-1, 0.f); goto encore; } } diff --git a/tests/max-float-1.ispc b/tests/max-float-1.ispc index 24b9822d..5674a7bf 100644 --- a/tests/max-float-1.ispc +++ b/tests/max-float-1.ispc @@ -6,7 +6,7 @@ export uniform int width() { return programCount; } export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { float a = aFOO[programIndex]; RET[programIndex] = max(3 * a, 10.f); - RET[width()-1] = max(b, 100); + RET[width()-1] = max(b, 100.f); } diff --git a/tests/max-float-2.ispc b/tests/max-float-2.ispc index f990b102..16937b42 100644 --- a/tests/max-float-2.ispc +++ b/tests/max-float-2.ispc @@ -6,7 +6,7 @@ export uniform int width() { return programCount; } export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { float a = aFOO[programIndex]; RET[programIndex] = max(-10 * (a-3), .1f); - RET[width() - 1] = max(-10 * b, 2); + RET[width() - 1] = max(-10 * b, 2.f); } export void result(uniform float RET[]) { diff --git a/tests/min-float-1.ispc b/tests/min-float-1.ispc index 5b62c5c5..3a5ad5f3 100644 --- a/tests/min-float-1.ispc +++ b/tests/min-float-1.ispc @@ -6,7 +6,7 @@ export uniform int width() { return programCount; } export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { float a = aFOO[programIndex]; RET[programIndex] = min(3 * a, 10.f); - RET[width()-1] = min(b, 100); + RET[width()-1] = min(b, 100.f); } diff --git a/tests/min-float-2.ispc b/tests/min-float-2.ispc index 85c226ca..e099d64b 100644 --- a/tests/min-float-2.ispc +++ b/tests/min-float-2.ispc @@ -6,7 +6,7 @@ export uniform int width() { return programCount; } export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { float a = aFOO[programIndex]; RET[programIndex] = min(-10 * (a-3), .1f); - RET[width() - 1] = min(-10 * b, 2); + RET[width() - 1] = min(-10 * b, 2.f); } export void result(uniform float RET[]) { diff --git a/tests/ref-overloads.ispc b/tests/ref-overloads.ispc new file mode 100644 index 00000000..961af36d --- /dev/null +++ b/tests/ref-overloads.ispc @@ -0,0 +1,93 @@ +/////////////////////////VARYING +//int A011(varying float f){return 0;} int A011(varying float& f){return 1;} int A011(varying const float& f){return 2;} +//int A011(varying double f){return 3;} int A011(varying int f){return 4;} int A011(uniform float f){return 5;} +//int A011(uniform float& f){return 6;} int A011(uniform const float& f){return 7;} int A011(uniform double f){return 8;} int A011(uniform int f){return 9;} + +int A013(varying const float& f){return 2;} int A013(varying double f){return 3;} int A013(varying int f){return 4;} +int A013(uniform float f){return 5;} int A013(uniform float& f){return 6;} int A013(uniform const float& f){return 7;} +int A013(uniform double f){return 8;} int A013(uniform int f){return 9;} + +int A014(varying double f){return 3;} int A014(varying int f){return 4;} +int A014(uniform float f){return 5;} int A014(uniform float& f){return 6;} int A014(uniform const float& f){return 7;} +int A014(uniform double f){return 8;} int A014(uniform int f){return 9;} + +int A015(varying int f){return 4;} int A015(uniform float f){return 5;} +int A015(uniform float& f){return 6;} int A015(uniform const float& f){return 7;} +int A015(uniform double f){return 8;} int A015(uniform int f){return 9;} + +int A032(varying float& f){return 1;} int A032(varying double f){return 3;} int A032(varying int f){return 4;} +int A032(uniform float f){return 5;} int A032(uniform float& f){return 6;} int A032(uniform const float& f){return 7;} +int A032(uniform double f){return 8;} int A032(uniform int f){return 9;} + +int A033(varying int f){return 4;} +int A033(uniform float f){return 5;} int A033(uniform float& f){return 6;} int A033(uniform const float& f){return 7;} +int A033(uniform double f){return 8;} int A033(uniform int f){return 9;} + +/////////////////////////UNIFORM + +int A051(varying float f){return 0;} int A051(varying float& f){return 1;} int A051(varying const float& f){return 2;} +int A051(varying double f){return 3;} int A051(varying int f){return 4;} +int A051(uniform const float& f){return 7;} int A051(uniform double f){return 8;} int A051(uniform int f){return 9;} + +int A052(varying float f){return 0;} int A052(varying float& f){return 1;} int A052(varying const float& f){return 2;} +int A052(varying double f){return 3;} int A052(varying int f){return 4;} +int A052(uniform double f){return 8;} int A052(uniform int f){return 9;} + +int A053(varying float f){return 0;} int A053(varying float& f){return 1;} int A053(varying const float& f){return 2;} +int A053(varying double f){return 3;} int A053(varying int f){return 4;} int A053(uniform int f){return 9;} + +int A054(varying float& f){return 1;} int A054(varying const float& f){return 2;} +int A054(varying double f){return 3;} int A054(varying int f){return 4;} int A054(uniform int f){return 9;} + +int A055(varying float& f){return 1;} int A055(varying const float& f){return 2;} +int A055(varying double f){return 3;} int A055(varying int f){return 4;} + +int A056(varying float& f){return 1;} int A056(varying const float& f){return 2;} int A056(varying int f){return 4;} + + +export uniform int width() { return programCount; } + + + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + varying float vf = 5; + varying const float vcf = 5; + varying float& vfr = vf; + varying const float& vcfr = vf; + uniform float uf = 5; + uniform const float ucf = 5; + uniform float& ufr = uf; + uniform const float& ucfr = uf; + + if (A013(vf) != 2) {RET[programIndex] = 1; return;} + if (A014(vf) != 3) {RET[programIndex] = 2; return;} + if (A015(vf) != 4) {RET[programIndex] = 3; return;} + + if (A013(vfr) != 2) {RET[programIndex] = 4; return;} + if (A014(vfr) != 3) {RET[programIndex] = 5; return;} + if (A015(vfr) != 4) {RET[programIndex] = 6; return;} + + if (A032(vcf) != 3) {RET[programIndex] = 7; return;} + if (A033(vcf) != 4) {RET[programIndex] = 8; return;} + + if (A032(vcfr) != 3) {RET[programIndex] = 9; return;} + if (A033(vcfr) != 4) {RET[programIndex] = 10; return;} + + if (A051(uf) != 7) {RET[programIndex] = 11; return;} + if (A052(uf) != 8) {RET[programIndex] = 12; return;} + if (A053(uf) != 0) {RET[programIndex] = 13; return;} + if (A054(uf) != 9) {RET[programIndex] = 14; return;} + if (A055(uf) != 3) {RET[programIndex] = 15; return;} + if (A056(uf) != 4) {RET[programIndex] = 16; return;} + + if (A051(ufr) != 7) {RET[programIndex] = 17; return;} + if (A052(ufr) != 8) {RET[programIndex] = 18; return;} + if (A053(ufr) != 0) {RET[programIndex] = 19; return;} + if (A054(ufr) != 9) {RET[programIndex] = 20; return;} + if (A055(ufr) != 3) {RET[programIndex] = 21; return;} + if (A056(ufr) != 4) {RET[programIndex] = 22; return;} + + RET[programIndex] = 0; +} + +export void result(uniform float RET[]) { RET[programIndex] = 0; } diff --git a/tests/ref-overloads1.ispc b/tests/ref-overloads1.ispc new file mode 100644 index 00000000..114eb011 --- /dev/null +++ b/tests/ref-overloads1.ispc @@ -0,0 +1,41 @@ +void A1(float f) {} +void A2(float& f) {} +void A3(const float& f) {} +void A4(double f) {} +void A5(int f) {} +void A6(uniform float f) {} +void A7(uniform float& f) {} +void A8(uniform const float& f){} +void A9(uniform double f) {} +void A0(uniform int f) {} + + + +export uniform int width() { return programCount; } + + + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + varying float vf = 5; + varying const float vcf = 5; + varying float& vfr = vf; + varying const float& vcfr = vf; + uniform float uf = 5; + uniform const float ucf = 5; + uniform float& ufr = uf; + uniform const float& ucfr = uf; + + A1(vf); A1(vcf); A1(vfr); A1(vcfr); A1(uf); A1(ucf); A1(ufr); A1(ucfr); + A2(vf); A2(vfr); + A3(vf); A3(vcf); A3(vfr); A3(vcfr); + A4(vf); A4(vcf); A4(vfr); A4(vcfr); A4(uf); A4(ucf); A4(ufr); A4(ucfr); + A5(vf); A5(vcf); A5(vfr); A5(vcfr); A5(uf); A5(ucf); A5(ufr); A5(ucfr); + A6(uf); A6(ucf); A6(ufr); A6(ucfr); + A7(uf); A7(ufr); + A8(uf); A8(ucf); A8(ufr); A8(ucfr); + A9(uf); A9(ucf); A9(ufr); A9(ucfr); + A0(uf); A0(ucf); A0(ufr); A0(ucfr); + RET[programIndex] = 1; +} + +export void result(uniform float RET[]) { RET[programIndex] = 1; } diff --git a/tests/ref-overloads2.ispc b/tests/ref-overloads2.ispc new file mode 100644 index 00000000..a8a7152a --- /dev/null +++ b/tests/ref-overloads2.ispc @@ -0,0 +1,54 @@ +void A01(varying float f){} void A01(varying float& f){} void A01(varying const float& f){} void A01(varying double f){} void A01(varying int f){} + void A02(varying float& f){} void A02(varying const float& f){} void A02(varying double f){} void A02(varying int f){} +void A03(varying float f){} void A03(varying const float& f){} void A03(varying double f){} void A03(varying int f){} +void A04(varying float f){} void A04(varying float& f){} void A04(varying double f){} void A04(varying int f){} +void A05(varying float f){} void A05(varying float& f){} void A05(varying const float& f){} void A05(varying int f){} +void A06(varying float f){} void A06(varying float& f){} void A06(varying const float& f){} void A06(varying double f){} + +void A07(varying float f){} void A07(varying float& f){} void A07(varying const float& f){} void A07(varying double f){} void A07(varying int f){} +void A08(varying float f){} void A08(varying float& f){} void A08(varying const float& f){} void A08(varying double f){} void A08(varying int f){} +void A09(varying float f){} void A09(varying float& f){} void A09(varying const float& f){} void A09(varying double f){} void A09(varying int f){} +void A10(varying float f){} void A10(varying float& f){} void A10(varying const float& f){} void A10(varying double f){} void A10(varying int f){} +void A11(varying float f){} void A11(varying float& f){} void A11(varying const float& f){} void A11(varying double f){} void A11(varying int f){} + +void A01(uniform float f){} void A01(uniform float& f){} void A01(uniform const float& f){} void A01(uniform double f){} void A01(uniform int f){} +void A02(uniform float f){} void A02(uniform float& f){} void A02(uniform const float& f){} void A02(uniform double f){} void A02(uniform int f){} +void A03(uniform float f){} void A03(uniform float& f){} void A03(uniform const float& f){} void A03(uniform double f){} void A03(uniform int f){} +void A04(uniform float f){} void A04(uniform float& f){} void A04(uniform const float& f){} void A04(uniform double f){} void A04(uniform int f){} +void A05(uniform float f){} void A05(uniform float& f){} void A05(uniform const float& f){} void A05(uniform double f){} void A05(uniform int f){} +void A06(uniform float f){} void A06(uniform float& f){} void A06(uniform const float& f){} void A06(uniform double f){} void A06(uniform int f){} + + void A07(uniform float& f){} void A07(uniform const float& f){} void A07(uniform double f){} void A07(uniform int f){} +void A08(uniform float f){} void A08(uniform const float& f){} void A08(uniform double f){} void A08(uniform int f){} +void A09(uniform float f){} void A09(uniform float& f){} void A09(uniform double f){} void A09(uniform int f){} +void A10(uniform float f){} void A10(uniform float& f){} void A10(uniform const float& f){} void A10(uniform int f){} +void A11(uniform float f){} void A11(uniform float& f){} void A11(uniform const float& f){} void A11(uniform double f){} + +export uniform int width() { return programCount; } + + + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + varying float vf = 5; + varying const float vcf = 5; + varying float& vfr = vf; + varying const float& vcfr = vf; + uniform float uf = 5; + uniform const float ucf = 5; + uniform float& ufr = uf; + uniform const float& ucfr = uf; + + A01(vf); A01(vcf); A01(vfr); A01(vcfr); A01(uf); A01(ucf); A01(ufr); A01(ucfr); + A02(vf); A02(vcf); A02(vfr); A02(vcfr); A02(uf); A02(ucf); A02(ufr); A02(ucfr); + A03(vf); A03(vcf); A03(vfr); A03(vcfr); A03(uf); A03(ucf); A03(ufr); A03(ucfr); + A04(vf); A04(vcf); A04(vfr); A04(vcfr); A04(uf); A04(ucf); A04(ufr); A04(ucfr); + A05(vf); A05(vcf); A05(vfr); A05(vcfr); A05(uf); A05(ucf); A05(ufr); A05(ucfr); + A06(vf); A06(vcf); A06(vfr); A06(vcfr); A06(uf); A06(ucf); A06(ufr); A06(ucfr); + A07(vf); A07(vcf); A07(vfr); A07(vcfr); A07(uf); A07(ucf); A07(ufr); A07(ucfr); + A08(vf); A08(vcf); A08(vfr); A08(vcfr); A08(uf); A08(ucf); A08(ufr); A08(ucfr); + A09(vf); A09(vcf); A09(vfr); A09(vcfr); A09(uf); A09(ucf); A09(ufr); A09(ucfr); + A10(vf); A10(vcf); A10(vfr); A10(vcfr); A10(uf); A10(ucf); A10(ufr); A10(ucfr); + RET[programIndex] = 1; +} + +export void result(uniform float RET[]) { RET[programIndex] = 1; } diff --git a/tests/ref-overloads3.ispc b/tests/ref-overloads3.ispc new file mode 100644 index 00000000..b9529dd5 --- /dev/null +++ b/tests/ref-overloads3.ispc @@ -0,0 +1,99 @@ +int A01(varying float f){return 0;} int A01(varying float& f){return 1;} int A01(varying const float& f){return 2;} int A01(varying double f){return 3;} int A01(varying int f){return 4;} + int A02(varying float& f){return 1;} int A02(varying const float& f){return 2;} int A02(varying double f){return 3;} int A02(varying int f){return 4;} +int A03(varying float f){return 0;} int A03(varying const float& f){return 2;} int A03(varying double f){return 3;} int A03(varying int f){return 4;} +int A04(varying float f){return 0;} int A04(varying float& f){return 1;} int A04(varying double f){return 3;} int A04(varying int f){return 4;} + +int A07(varying float f){return 0;} int A07(varying float& f){return 1;} int A07(varying const float& f){return 2;} int A07(varying double f){return 3;} int A07(varying int f){return 4;} +int A08(varying float f){return 0;} int A08(varying float& f){return 1;} int A08(varying const float& f){return 2;} int A08(varying double f){return 3;} int A08(varying int f){return 4;} +int A09(varying float f){return 0;} int A09(varying float& f){return 1;} int A09(varying const float& f){return 2;} int A09(varying double f){return 3;} int A09(varying int f){return 4;} + +int A01(uniform float f){return 5;} int A01(uniform float& f){return 6;} int A01(uniform const float& f){return 7;} int A01(uniform double f){return 8;} int A01(uniform int f){return 9;} +int A02(uniform float f){return 5;} int A02(uniform float& f){return 6;} int A02(uniform const float& f){return 7;} int A02(uniform double f){return 8;} int A02(uniform int f){return 9;} +int A03(uniform float f){return 5;} int A03(uniform float& f){return 6;} int A03(uniform const float& f){return 7;} int A03(uniform double f){return 8;} int A03(uniform int f){return 9;} +int A04(uniform float f){return 5;} int A04(uniform float& f){return 6;} int A04(uniform const float& f){return 7;} int A04(uniform double f){return 8;} int A04(uniform int f){return 9;} + + int A07(uniform float& f){return 6;} int A07(uniform const float& f){return 7;} int A07(uniform double f){return 8;} int A07(uniform int f){return 9;} +int A08(uniform float f){return 5;} int A08(uniform const float& f){return 7;} int A08(uniform double f){return 8;} int A08(uniform int f){return 9;} +int A09(uniform float f){return 5;} int A09(uniform float& f){return 6;} int A09(uniform double f){return 8;} int A09(uniform int f){return 9;} + +export uniform int width() { return programCount; } + + + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + varying float vf = 5; + varying const float vcf = 5; + varying float& vfr = vf; + varying const float& vcfr = vf; + uniform float uf = 5; + uniform const float ucf = 5; + uniform float& ufr = uf; + uniform const float& ucfr = uf; + + if (A01(vf) != 0) {RET[programIndex] = 1; return;} + if (A01(vcf) != 0) {RET[programIndex] = 2; return;} + if (A01(vfr) != 1) {RET[programIndex] = 3; return;} + if (A01(vcfr)!= 2) {RET[programIndex] = 4; return;} + if (A01(uf) != 5) {RET[programIndex] = 5; return;} + if (A01(ucf) != 5) {RET[programIndex] = 6; return;} + if (A01(ufr) != 6) {RET[programIndex] = 7; return;} + if (A01(ucfr)!= 7) {RET[programIndex] = 8; return;} + + if (A02(vf) != 1) {RET[programIndex] = 9; return;} + if (A02(vcf) != 2) {RET[programIndex] = 10; return;} + if (A02(vfr) != 1) {RET[programIndex] = 11; return;} + if (A02(vcfr)!= 2) {RET[programIndex] = 12; return;} + if (A02(uf) != 5) {RET[programIndex] = 13; return;} + if (A02(ucf) != 5) {RET[programIndex] = 14; return;} + if (A02(ufr) != 6) {RET[programIndex] = 15; return;} + if (A02(ucfr)!= 7) {RET[programIndex] = 16; return;} + + if (A03(vf) != 0) {RET[programIndex] = 17; return;} + if (A03(vcf) != 0) {RET[programIndex] = 18; return;} + if (A03(vfr) != 0) {RET[programIndex] = 19; return;} + if (A03(vcfr)!= 2) {RET[programIndex] = 20; return;} + if (A03(uf) != 5) {RET[programIndex] = 21; return;} + if (A03(ucf) != 5) {RET[programIndex] = 22; return;} + if (A03(ufr) != 6) {RET[programIndex] = 23; return;} + if (A03(ucfr)!= 7) {RET[programIndex] = 24; return;} + + if (A04(vf) != 0) {RET[programIndex] = 25; return;} + if (A04(vcf) != 0) {RET[programIndex] = 26; return;} + if (A04(vfr) != 1) {RET[programIndex] = 27; return;} + if (A04(vcfr)!= 0) {RET[programIndex] = 28; return;} + if (A04(uf) != 5) {RET[programIndex] = 29; return;} + if (A04(ucf) != 5) {RET[programIndex] = 30; return;} + if (A04(ufr) != 6) {RET[programIndex] = 31; return;} + if (A04(ucfr)!= 7) {RET[programIndex] = 32; return;} + + if (A07(vf) != 0) {RET[programIndex] = 33; return;} + if (A07(vcf) != 0) {RET[programIndex] = 34; return;} + if (A07(vfr) != 1) {RET[programIndex] = 35; return;} + if (A07(vcfr)!= 2) {RET[programIndex] = 36; return;} + if (A07(uf) != 6) {RET[programIndex] = 37; return;} + if (A07(ucf) != 7) {RET[programIndex] = 38; return;} + if (A07(ufr) != 6) {RET[programIndex] = 39; return;} + if (A07(ucfr)!= 7) {RET[programIndex] = 40; return;} + + if (A08(vf) != 0) {RET[programIndex] = 41; return;} + if (A08(vcf) != 0) {RET[programIndex] = 42; return;} + if (A08(vfr) != 1) {RET[programIndex] = 43; return;} + if (A08(vcfr)!= 2) {RET[programIndex] = 44; return;} + if (A08(uf) != 5) {RET[programIndex] = 45; return;} + if (A08(ucf) != 5) {RET[programIndex] = 46; return;} + if (A08(ufr) != 5) {RET[programIndex] = 47; return;} + if (A08(ucfr)!= 7) {RET[programIndex] = 48; return;} + + if (A09(vf) != 0) {RET[programIndex] = 49; return;} + if (A09(vcf) != 0) {RET[programIndex] = 50; return;} + if (A09(vfr) != 1) {RET[programIndex] = 51; return;} + if (A09(vcfr)!= 2) {RET[programIndex] = 52; return;} + if (A09(uf) != 5) {RET[programIndex] = 53; return;} + if (A09(ucf) != 5) {RET[programIndex] = 54; return;} + if (A09(ufr) != 6) {RET[programIndex] = 55; return;} + if (A09(ucfr)!= 5) {RET[programIndex] = 56; return;} + + RET[programIndex] = 0; +} + +export void result(uniform float RET[]) { RET[programIndex] = 0; } diff --git a/tests/typedef-2.ispc b/tests/typedef-2.ispc index e8117dd4..af71dc6e 100644 --- a/tests/typedef-2.ispc +++ b/tests/typedef-2.ispc @@ -19,7 +19,7 @@ export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { for (uniform int i = 0; i < 16; ++i) for (uniform int j = 0; j < 16; ++j) bar.foo[i].x[j] = b; - RET[programIndex] = bar.foo[min(15, a-1)].x[min(15, a-1)]; + RET[programIndex] = bar.foo[min(15.f, a-1)].x[min(15.f, a-1)]; } export void result(uniform float RET[]) { RET[programIndex] = 5; } diff --git a/type.cpp b/type.cpp index b22f9283..c7b59592 100644 --- a/type.cpp +++ b/type.cpp @@ -1909,7 +1909,15 @@ StructType::StructType(const std::string &n, const llvm::SmallVector