summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-check-conversion.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2023-06-01 13:53:31 -0700
committerGitHub <noreply@github.com>2023-06-01 13:53:31 -0700
commit16cd361dd67471bcc355d1b3b72b0b022518088f (patch)
treefa3a7d5b77ccf09f9340b78e66610ba8b751c855 /source/slang/slang-check-conversion.cpp
parenta7ed48b2e6da9bf952aa11ec0d57acf9688bbb0e (diff)
Be lenient on same-size unsigend->signed conversion. (#2913)
* Be lenient on same-size unsigend->signed conversion. * Fix tests. * Use 250. * wip * Fix. * Fix tests. * Fix. --------- Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'source/slang/slang-check-conversion.cpp')
-rw-r--r--source/slang/slang-check-conversion.cpp83
1 files changed, 78 insertions, 5 deletions
diff --git a/source/slang/slang-check-conversion.cpp b/source/slang/slang-check-conversion.cpp
index 639ae7939..9ee5bca1f 100644
--- a/source/slang/slang-check-conversion.cpp
+++ b/source/slang/slang-check-conversion.cpp
@@ -628,6 +628,79 @@ namespace Slang
}
}
+ static bool isSigned(Type* t)
+ {
+ auto basicType = as<BasicExpressionType>(t);
+ if (!basicType) return false;
+ switch (basicType->baseType)
+ {
+ case BaseType::Int8:
+ case BaseType::Int16:
+ case BaseType::Int:
+ case BaseType::Int64:
+ case BaseType::IntPtr:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ static int getTypeBitSize(Type* t)
+ {
+ auto basicType = as<BasicExpressionType>(t);
+ if (!basicType) return 0;
+
+ switch (basicType->baseType)
+ {
+ case BaseType::Int8:
+ case BaseType::UInt8:
+ return 8;
+ case BaseType::Int16:
+ case BaseType::UInt16:
+ return 16;
+ case BaseType::Int:
+ case BaseType::UInt:
+ return 32;
+ case BaseType::Int64:
+ case BaseType::UInt64:
+ return 64;
+ case BaseType::IntPtr:
+ case BaseType::UIntPtr:
+#if SLANG_PTR_IS_32
+ return 32;
+#else
+ return 64;
+#endif
+ default:
+ return 0;
+ }
+ }
+
+ ConversionCost SemanticsVisitor::getImplicitConversionCostWithKnownArg(Decl* decl, Type* toType, Expr* arg)
+ {
+ ConversionCost candidateCost = getImplicitConversionCost(decl);
+
+ // Fix up the cost if the operand is a const lit.
+ if (isScalarIntegerType(toType))
+ {
+ auto knownVal = as<IntegerLiteralExpr>(arg);
+ if (!knownVal)
+ return candidateCost;
+ if (getIntValueBitSize(knownVal->value) <= getTypeBitSize(toType))
+ {
+ bool toTypeIsSigned = isSigned(toType);
+ bool fromTypeIsSigned = isSigned(knownVal->type);
+ if (toTypeIsSigned == fromTypeIsSigned)
+ candidateCost = kConversionCost_InRangeIntLitConversion;
+ else if (toTypeIsSigned)
+ candidateCost = kConversionCost_InRangeIntLitUnsignedToSignedConversion;
+ else
+ candidateCost = kConversionCost_InRangeIntLitSignedToUnsignedConversion;
+ }
+ }
+ return candidateCost;
+ }
+
bool SemanticsVisitor::_coerce(
CoercionSite site,
Type* toType,
@@ -989,8 +1062,8 @@ namespace Slang
ConversionCost bestCost = kConversionCost_Explicit;
for(auto candidate : overloadContext.bestCandidates)
{
- ConversionCost candidateCost = getImplicitConversionCost(
- candidate.item.declRef.getDecl());
+ ConversionCost candidateCost = getImplicitConversionCostWithKnownArg(
+ candidate.item.declRef.getDecl(), toType, fromExpr);
if(candidateCost < bestCost)
bestCost = candidateCost;
@@ -1027,8 +1100,8 @@ namespace Slang
// Next, we need to look at the implicit conversion
// cost associated with the initializer we are invoking.
//
- ConversionCost cost = getImplicitConversionCost(
- overloadContext.bestCandidate->item.declRef.getDecl());
+ ConversionCost cost = getImplicitConversionCostWithKnownArg(
+ overloadContext.bestCandidate->item.declRef.getDecl(), toType, fromExpr);
// If the cost is too high to be usable as an
// implicit conversion, then we will report the
@@ -1149,7 +1222,7 @@ namespace Slang
BasicTypeKeyPair cacheKey;
cacheKey.type1 = makeBasicTypeKey(toType);
- cacheKey.type2 = makeBasicTypeKey(fromType);
+ cacheKey.type2 = makeBasicTypeKey(fromType, fromExpr);
if( cacheKey.isValid())
{