diff options
| author | Yong He <yonghe@outlook.com> | 2023-06-01 13:53:31 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-06-01 13:53:31 -0700 |
| commit | 16cd361dd67471bcc355d1b3b72b0b022518088f (patch) | |
| tree | fa3a7d5b77ccf09f9340b78e66610ba8b751c855 /source/slang/slang-check-conversion.cpp | |
| parent | a7ed48b2e6da9bf952aa11ec0d57acf9688bbb0e (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.cpp | 83 |
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()) { |
