From d1ef913fc00c306049149e315f84bc951b476110 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Wed, 19 Dec 2018 11:52:31 +0100 Subject: [PATCH 01/12] ExpressionBuilder: Use TSAB.ConvertConstantValue in VisitLdcF4 and VisitLdcF8 --- ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 1123ba85e..53c866744 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -435,16 +435,14 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitLdcF4(LdcF4 inst, TranslationContext context) { - return new PrimitiveExpression(inst.Value) - .WithILInstruction(inst) - .WithRR(new ConstantResolveResult(compilation.FindType(KnownTypeCode.Single), inst.Value)); + var expr = astBuilder.ConvertConstantValue(compilation.FindType(KnownTypeCode.Single), inst.Value); + return new TranslatedExpression(expr.WithILInstruction(inst)); } protected internal override TranslatedExpression VisitLdcF8(LdcF8 inst, TranslationContext context) { - return new PrimitiveExpression(inst.Value) - .WithILInstruction(inst) - .WithRR(new ConstantResolveResult(compilation.FindType(KnownTypeCode.Double), inst.Value)); + var expr = astBuilder.ConvertConstantValue(compilation.FindType(KnownTypeCode.Double), inst.Value); + return new TranslatedExpression(expr.WithILInstruction(inst)); } protected internal override TranslatedExpression VisitLdcDecimal(LdcDecimal inst, TranslationContext context) From 9e71e7fe09ba8a60a019f72a054bcc9cbd8cecd5 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 21 Dec 2018 14:07:35 +0100 Subject: [PATCH 02/12] Fix #517: Try to reverse constant folding for double and float expressions containing Math.PI and Math.E as factors. --- .../TestCases/Pretty/WellKnownConstants.cs | 70 +++++ .../TestCases/Pretty/WellKnownConstants.il | 64 ++++ .../Pretty/WellKnownConstants.opt.il | 64 ++++ .../Pretty/WellKnownConstants.opt.roslyn.il | 64 ++++ .../Pretty/WellKnownConstants.roslyn.il | 64 ++++ .../CSharp/CSharpDecompiler.cs | 3 +- .../CSharp/Syntax/TypeSystemAstBuilder.cs | 273 +++++++++++++++++- 7 files changed, 599 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.cs index fe839a7f6..d01cbfa7c 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.cs @@ -16,6 +16,8 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System; + namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { public class WellKnownConstants @@ -64,5 +66,73 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public const decimal DecimalMaxValue = decimal.MaxValue; public const decimal DecimalMinValue = decimal.MinValue; + + public const float Float_PI = (float)Math.PI; + public const float Float_HalfOfPI = (float)Math.PI / 2f; + public const float Float_QuarterOfPI = (float)Math.PI / 4f; + public const float Float_PITimes2 = (float)Math.PI * 2f; + public const float Float_3QuartersOfPI = (float)Math.PI * 3f / 4f; + public const float Float_PIDiv360 = (float)Math.PI / 360f; + public const float Float_PIDiv16 = (float)Math.PI / 16f; + public const float Float_PIDiv32 = (float)Math.PI / 32f; + public const float Float_PIInverseFraction = 1f / (float)Math.PI; + public const float Float_PIInverseFraction2 = 2f / (float)Math.PI; + public const float Float_PIInverseFraction5 = 5f / (float)Math.PI; + public const float Float_PITimes90 = (float)Math.PI * 90f; + public const float Float_PITimes180 = (float)Math.PI * 180f; + public const float Float_LooksLikePI = 3.1415925f; + public const float Float_LooksLikePI2 = 3.14159f; + public const float Float_LooksLikePI3 = 3.141f; + public const float Float_Negated_PI = -(float)Math.PI; + public const float Float_Negated_HalfOfPI = -(float)Math.PI / 2f; + public const float Float_Negated_QuarterOfPI = -(float)Math.PI / 4f; + public const float Float_Negated_PITimes2 = (float)Math.PI * -2f; + public const float Float_Negated_3QuartersOfPI = (float)Math.PI * -3f / 4f; + public const float Float_Negated_PIDiv360 = -(float)Math.PI / 360f; + public const float Float_Negated_PIDiv16 = -(float)Math.PI / 16f; + public const float Float_Negated_PIDiv32 = -(float)Math.PI / 32f; + public const float Float_Negated_PIInverseFraction = -1f / (float)Math.PI; + public const float Float_Negated_PIInverseFraction2 = -2f / (float)Math.PI; + public const float Float_Negated_PIInverseFraction5 = -5f / (float)Math.PI; + public const float Float_Negated_PITimes90 = (float)Math.PI * -90f; + public const float Float_Negated_PITimes180 = (float)Math.PI * -180f; + public const float Float_Negated_LooksLikePI = -3.141f; + + public const float Float_E = (float)Math.E; + public const float Float_Negated_E = -(float)Math.E; + + public const double Double_PI = Math.PI; + public const double Double_HalfOfPI = Math.PI / 2.0; + public const double Double_QuarterOfPI = Math.PI / 4.0; + public const double Double_PITimes2 = Math.PI * 2.0; + public const double Double_3QuartersOfPI = Math.PI * 3.0 / 4.0; + public const double Double_PIDiv360 = Math.PI / 360.0; + public const double Double_PIDiv16 = Math.PI / 16.0; + public const double Double_PIDiv32 = Math.PI / 32.0; + public const double Double_PIInverseFraction = 1.0 / Math.PI; + public const double Double_PIInverseFraction2 = 2.0 / Math.PI; + public const double Double_PIInverseFraction5 = 5.0 / Math.PI; + public const double Double_PITimes90 = Math.PI * 90.0; + public const double Double_PITimes180 = Math.PI * 180.0; + public const double Double_LooksLikePI = 3.1415926; + public const double Double_LooksLikePI2 = 3.14159; + public const double Double_LooksLikePI3 = 3.141; + public const double Double_Negated_PI = -Math.PI; + public const double Double_Negated_HalfOfPI = -Math.PI / 2.0; + public const double Double_Negated_QuarterOfPI = -Math.PI / 4.0; + public const double Double_Negated_PITimes2 = Math.PI * -2.0; + public const double Double_Negated_3QuartersOfPI = Math.PI * -3.0 / 4.0; + public const double Double_Negated_PIDiv360 = -Math.PI / 360.0; + public const double Double_Negated_PIDiv16 = -Math.PI / 16.0; + public const double Double_Negated_PIDiv32 = -Math.PI / 32.0; + public const double Double_Negated_PIInverseFraction = -1.0 / Math.PI; + public const double Double_Negated_PIInverseFraction2 = -2.0 / Math.PI; + public const double Double_Negated_PIInverseFraction5 = -5.0 / Math.PI; + public const double Double_Negated_PITimes90 = Math.PI * -90.0; + public const double Double_Negated_PITimes180 = Math.PI * -180.0; + public const double Double_Negated_LooksLikePI = -3.141; + + public const double Double_E = Math.E; + public const double Double_Negated_E = -Math.E; } } \ No newline at end of file diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.il index fb0d45121..37b6ed0e8 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.il @@ -78,6 +78,70 @@ uint32, uint32) = ( 01 00 00 80 FF FF FF FF FF FF FF FF FF FF FF FF 00 00 ) + .field public static literal float32 Float_PI = float32(3.1415927) + .field public static literal float32 Float_HalfOfPI = float32(1.5707964) + .field public static literal float32 Float_QuarterOfPI = float32(0.78539819) + .field public static literal float32 Float_PITimes2 = float32(6.2831855) + .field public static literal float32 Float_3QuartersOfPI = float32(2.3561945) + .field public static literal float32 Float_PIDiv360 = float32(8.7266462e-003) + .field public static literal float32 Float_PIDiv16 = float32(0.19634955) + .field public static literal float32 Float_PIDiv32 = float32(9.8174773e-002) + .field public static literal float32 Float_PIInverseFraction = float32(0.31830987) + .field public static literal float32 Float_PIInverseFraction2 = float32(0.63661975) + .field public static literal float32 Float_PIInverseFraction5 = float32(1.5915494) + .field public static literal float32 Float_PITimes90 = float32(282.74335) + .field public static literal float32 Float_PITimes180 = float32(565.48669) + .field public static literal float32 Float_LooksLikePI = float32(3.1415925) + .field public static literal float32 Float_LooksLikePI2 = float32(3.1415901) + .field public static literal float32 Float_LooksLikePI3 = float32(3.141) + .field public static literal float32 Float_Negated_PI = float32(-3.1415927) + .field public static literal float32 Float_Negated_HalfOfPI = float32(-1.5707964) + .field public static literal float32 Float_Negated_QuarterOfPI = float32(-0.78539819) + .field public static literal float32 Float_Negated_PITimes2 = float32(-6.2831855) + .field public static literal float32 Float_Negated_3QuartersOfPI = float32(-2.3561945) + .field public static literal float32 Float_Negated_PIDiv360 = float32(-8.7266462e-003) + .field public static literal float32 Float_Negated_PIDiv16 = float32(-0.19634955) + .field public static literal float32 Float_Negated_PIDiv32 = float32(-9.8174773e-002) + .field public static literal float32 Float_Negated_PIInverseFraction = float32(-0.31830987) + .field public static literal float32 Float_Negated_PIInverseFraction2 = float32(-0.63661975) + .field public static literal float32 Float_Negated_PIInverseFraction5 = float32(-1.5915494) + .field public static literal float32 Float_Negated_PITimes90 = float32(-282.74335) + .field public static literal float32 Float_Negated_PITimes180 = float32(-565.48669) + .field public static literal float32 Float_Negated_LooksLikePI = float32(-3.141) + .field public static literal float32 Float_E = float32(2.7182817) + .field public static literal float32 Float_Negated_E = float32(-2.7182817) + .field public static literal float64 Double_PI = float64(3.1415926535897931) + .field public static literal float64 Double_HalfOfPI = float64(1.5707963267948966) + .field public static literal float64 Double_QuarterOfPI = float64(0.78539816339744828) + .field public static literal float64 Double_PITimes2 = float64(6.2831853071795862) + .field public static literal float64 Double_3QuartersOfPI = float64(2.3561944901923448) + .field public static literal float64 Double_PIDiv360 = float64(8.7266462599716477e-003) + .field public static literal float64 Double_PIDiv16 = float64(0.19634954084936207) + .field public static literal float64 Double_PIDiv32 = float64(9.8174770424681035e-002) + .field public static literal float64 Double_PIInverseFraction = float64(0.31830988618379069) + .field public static literal float64 Double_PIInverseFraction2 = float64(0.63661977236758138) + .field public static literal float64 Double_PIInverseFraction5 = float64(1.5915494309189535) + .field public static literal float64 Double_PITimes90 = float64(282.74333882308139) + .field public static literal float64 Double_PITimes180 = float64(565.48667764616278) + .field public static literal float64 Double_LooksLikePI = float64(3.1415926000000001) + .field public static literal float64 Double_LooksLikePI2 = float64(3.1415899999999999) + .field public static literal float64 Double_LooksLikePI3 = float64(3.141) + .field public static literal float64 Double_Negated_PI = float64(-3.1415926535897931) + .field public static literal float64 Double_Negated_HalfOfPI = float64(-1.5707963267948966) + .field public static literal float64 Double_Negated_QuarterOfPI = float64(-0.78539816339744828) + .field public static literal float64 Double_Negated_PITimes2 = float64(-6.2831853071795862) + .field public static literal float64 Double_Negated_3QuartersOfPI = float64(-2.3561944901923448) + .field public static literal float64 Double_Negated_PIDiv360 = float64(-8.7266462599716477e-003) + .field public static literal float64 Double_Negated_PIDiv16 = float64(-0.19634954084936207) + .field public static literal float64 Double_Negated_PIDiv32 = float64(-9.8174770424681035e-002) + .field public static literal float64 Double_Negated_PIInverseFraction = float64(-0.31830988618379069) + .field public static literal float64 Double_Negated_PIInverseFraction2 = float64(-0.63661977236758138) + .field public static literal float64 Double_Negated_PIInverseFraction5 = float64(-1.5915494309189535) + .field public static literal float64 Double_Negated_PITimes90 = float64(-282.74333882308139) + .field public static literal float64 Double_Negated_PITimes180 = float64(-565.48667764616278) + .field public static literal float64 Double_Negated_LooksLikePI = float64(-3.141) + .field public static literal float64 Double_E = float64(2.7182818284590451) + .field public static literal float64 Double_Negated_E = float64(-2.7182818284590451) .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.il index eda9ed8c1..b4623d634 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.il @@ -78,6 +78,70 @@ uint32, uint32) = ( 01 00 00 80 FF FF FF FF FF FF FF FF FF FF FF FF 00 00 ) + .field public static literal float32 Float_PI = float32(3.1415927) + .field public static literal float32 Float_HalfOfPI = float32(1.5707964) + .field public static literal float32 Float_QuarterOfPI = float32(0.78539819) + .field public static literal float32 Float_PITimes2 = float32(6.2831855) + .field public static literal float32 Float_3QuartersOfPI = float32(2.3561945) + .field public static literal float32 Float_PIDiv360 = float32(8.7266462e-003) + .field public static literal float32 Float_PIDiv16 = float32(0.19634955) + .field public static literal float32 Float_PIDiv32 = float32(9.8174773e-002) + .field public static literal float32 Float_PIInverseFraction = float32(0.31830987) + .field public static literal float32 Float_PIInverseFraction2 = float32(0.63661975) + .field public static literal float32 Float_PIInverseFraction5 = float32(1.5915494) + .field public static literal float32 Float_PITimes90 = float32(282.74335) + .field public static literal float32 Float_PITimes180 = float32(565.48669) + .field public static literal float32 Float_LooksLikePI = float32(3.1415925) + .field public static literal float32 Float_LooksLikePI2 = float32(3.1415901) + .field public static literal float32 Float_LooksLikePI3 = float32(3.141) + .field public static literal float32 Float_Negated_PI = float32(-3.1415927) + .field public static literal float32 Float_Negated_HalfOfPI = float32(-1.5707964) + .field public static literal float32 Float_Negated_QuarterOfPI = float32(-0.78539819) + .field public static literal float32 Float_Negated_PITimes2 = float32(-6.2831855) + .field public static literal float32 Float_Negated_3QuartersOfPI = float32(-2.3561945) + .field public static literal float32 Float_Negated_PIDiv360 = float32(-8.7266462e-003) + .field public static literal float32 Float_Negated_PIDiv16 = float32(-0.19634955) + .field public static literal float32 Float_Negated_PIDiv32 = float32(-9.8174773e-002) + .field public static literal float32 Float_Negated_PIInverseFraction = float32(-0.31830987) + .field public static literal float32 Float_Negated_PIInverseFraction2 = float32(-0.63661975) + .field public static literal float32 Float_Negated_PIInverseFraction5 = float32(-1.5915494) + .field public static literal float32 Float_Negated_PITimes90 = float32(-282.74335) + .field public static literal float32 Float_Negated_PITimes180 = float32(-565.48669) + .field public static literal float32 Float_Negated_LooksLikePI = float32(-3.141) + .field public static literal float32 Float_E = float32(2.7182817) + .field public static literal float32 Float_Negated_E = float32(-2.7182817) + .field public static literal float64 Double_PI = float64(3.1415926535897931) + .field public static literal float64 Double_HalfOfPI = float64(1.5707963267948966) + .field public static literal float64 Double_QuarterOfPI = float64(0.78539816339744828) + .field public static literal float64 Double_PITimes2 = float64(6.2831853071795862) + .field public static literal float64 Double_3QuartersOfPI = float64(2.3561944901923448) + .field public static literal float64 Double_PIDiv360 = float64(8.7266462599716477e-003) + .field public static literal float64 Double_PIDiv16 = float64(0.19634954084936207) + .field public static literal float64 Double_PIDiv32 = float64(9.8174770424681035e-002) + .field public static literal float64 Double_PIInverseFraction = float64(0.31830988618379069) + .field public static literal float64 Double_PIInverseFraction2 = float64(0.63661977236758138) + .field public static literal float64 Double_PIInverseFraction5 = float64(1.5915494309189535) + .field public static literal float64 Double_PITimes90 = float64(282.74333882308139) + .field public static literal float64 Double_PITimes180 = float64(565.48667764616278) + .field public static literal float64 Double_LooksLikePI = float64(3.1415926000000001) + .field public static literal float64 Double_LooksLikePI2 = float64(3.1415899999999999) + .field public static literal float64 Double_LooksLikePI3 = float64(3.141) + .field public static literal float64 Double_Negated_PI = float64(-3.1415926535897931) + .field public static literal float64 Double_Negated_HalfOfPI = float64(-1.5707963267948966) + .field public static literal float64 Double_Negated_QuarterOfPI = float64(-0.78539816339744828) + .field public static literal float64 Double_Negated_PITimes2 = float64(-6.2831853071795862) + .field public static literal float64 Double_Negated_3QuartersOfPI = float64(-2.3561944901923448) + .field public static literal float64 Double_Negated_PIDiv360 = float64(-8.7266462599716477e-003) + .field public static literal float64 Double_Negated_PIDiv16 = float64(-0.19634954084936207) + .field public static literal float64 Double_Negated_PIDiv32 = float64(-9.8174770424681035e-002) + .field public static literal float64 Double_Negated_PIInverseFraction = float64(-0.31830988618379069) + .field public static literal float64 Double_Negated_PIInverseFraction2 = float64(-0.63661977236758138) + .field public static literal float64 Double_Negated_PIInverseFraction5 = float64(-1.5915494309189535) + .field public static literal float64 Double_Negated_PITimes90 = float64(-282.74333882308139) + .field public static literal float64 Double_Negated_PITimes180 = float64(-565.48667764616278) + .field public static literal float64 Double_Negated_LooksLikePI = float64(-3.141) + .field public static literal float64 Double_E = float64(2.7182818284590451) + .field public static literal float64 Double_Negated_E = float64(-2.7182818284590451) .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.roslyn.il index ed7f96787..534c4085a 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.roslyn.il @@ -82,6 +82,70 @@ uint32, uint32) = ( 01 00 00 80 FF FF FF FF FF FF FF FF FF FF FF FF 00 00 ) + .field public static literal float32 Float_PI = float32(3.1415927) + .field public static literal float32 Float_HalfOfPI = float32(1.5707964) + .field public static literal float32 Float_QuarterOfPI = float32(0.78539819) + .field public static literal float32 Float_PITimes2 = float32(6.2831855) + .field public static literal float32 Float_3QuartersOfPI = float32(2.3561945) + .field public static literal float32 Float_PIDiv360 = float32(8.7266462e-003) + .field public static literal float32 Float_PIDiv16 = float32(0.19634955) + .field public static literal float32 Float_PIDiv32 = float32(9.8174773e-002) + .field public static literal float32 Float_PIInverseFraction = float32(0.31830987) + .field public static literal float32 Float_PIInverseFraction2 = float32(0.63661975) + .field public static literal float32 Float_PIInverseFraction5 = float32(1.5915494) + .field public static literal float32 Float_PITimes90 = float32(282.74335) + .field public static literal float32 Float_PITimes180 = float32(565.48669) + .field public static literal float32 Float_LooksLikePI = float32(3.1415925) + .field public static literal float32 Float_LooksLikePI2 = float32(3.1415901) + .field public static literal float32 Float_LooksLikePI3 = float32(3.141) + .field public static literal float32 Float_Negated_PI = float32(-3.1415927) + .field public static literal float32 Float_Negated_HalfOfPI = float32(-1.5707964) + .field public static literal float32 Float_Negated_QuarterOfPI = float32(-0.78539819) + .field public static literal float32 Float_Negated_PITimes2 = float32(-6.2831855) + .field public static literal float32 Float_Negated_3QuartersOfPI = float32(-2.3561945) + .field public static literal float32 Float_Negated_PIDiv360 = float32(-8.7266462e-003) + .field public static literal float32 Float_Negated_PIDiv16 = float32(-0.19634955) + .field public static literal float32 Float_Negated_PIDiv32 = float32(-9.8174773e-002) + .field public static literal float32 Float_Negated_PIInverseFraction = float32(-0.31830987) + .field public static literal float32 Float_Negated_PIInverseFraction2 = float32(-0.63661975) + .field public static literal float32 Float_Negated_PIInverseFraction5 = float32(-1.5915494) + .field public static literal float32 Float_Negated_PITimes90 = float32(-282.74335) + .field public static literal float32 Float_Negated_PITimes180 = float32(-565.48669) + .field public static literal float32 Float_Negated_LooksLikePI = float32(-3.141) + .field public static literal float32 Float_E = float32(2.7182817) + .field public static literal float32 Float_Negated_E = float32(-2.7182817) + .field public static literal float64 Double_PI = float64(3.1415926535897931) + .field public static literal float64 Double_HalfOfPI = float64(1.5707963267948966) + .field public static literal float64 Double_QuarterOfPI = float64(0.78539816339744828) + .field public static literal float64 Double_PITimes2 = float64(6.2831853071795862) + .field public static literal float64 Double_3QuartersOfPI = float64(2.3561944901923448) + .field public static literal float64 Double_PIDiv360 = float64(8.7266462599716477e-003) + .field public static literal float64 Double_PIDiv16 = float64(0.19634954084936207) + .field public static literal float64 Double_PIDiv32 = float64(9.8174770424681035e-002) + .field public static literal float64 Double_PIInverseFraction = float64(0.31830988618379069) + .field public static literal float64 Double_PIInverseFraction2 = float64(0.63661977236758138) + .field public static literal float64 Double_PIInverseFraction5 = float64(1.5915494309189535) + .field public static literal float64 Double_PITimes90 = float64(282.74333882308139) + .field public static literal float64 Double_PITimes180 = float64(565.48667764616278) + .field public static literal float64 Double_LooksLikePI = float64(3.1415926000000001) + .field public static literal float64 Double_LooksLikePI2 = float64(3.1415899999999999) + .field public static literal float64 Double_LooksLikePI3 = float64(3.141) + .field public static literal float64 Double_Negated_PI = float64(-3.1415926535897931) + .field public static literal float64 Double_Negated_HalfOfPI = float64(-1.5707963267948966) + .field public static literal float64 Double_Negated_QuarterOfPI = float64(-0.78539816339744828) + .field public static literal float64 Double_Negated_PITimes2 = float64(-6.2831853071795862) + .field public static literal float64 Double_Negated_3QuartersOfPI = float64(-2.3561944901923448) + .field public static literal float64 Double_Negated_PIDiv360 = float64(-8.7266462599716477e-003) + .field public static literal float64 Double_Negated_PIDiv16 = float64(-0.19634954084936207) + .field public static literal float64 Double_Negated_PIDiv32 = float64(-9.8174770424681035e-002) + .field public static literal float64 Double_Negated_PIInverseFraction = float64(-0.31830988618379069) + .field public static literal float64 Double_Negated_PIInverseFraction2 = float64(-0.63661977236758138) + .field public static literal float64 Double_Negated_PIInverseFraction5 = float64(-1.5915494309189535) + .field public static literal float64 Double_Negated_PITimes90 = float64(-282.74333882308139) + .field public static literal float64 Double_Negated_PITimes180 = float64(-565.48667764616278) + .field public static literal float64 Double_Negated_LooksLikePI = float64(-3.141) + .field public static literal float64 Double_E = float64(2.7182818284590451) + .field public static literal float64 Double_Negated_E = float64(-2.7182818284590451) .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.roslyn.il index 445c5dd16..f4f77372a 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.roslyn.il @@ -82,6 +82,70 @@ uint32, uint32) = ( 01 00 00 80 FF FF FF FF FF FF FF FF FF FF FF FF 00 00 ) + .field public static literal float32 Float_PI = float32(3.1415927) + .field public static literal float32 Float_HalfOfPI = float32(1.5707964) + .field public static literal float32 Float_QuarterOfPI = float32(0.78539819) + .field public static literal float32 Float_PITimes2 = float32(6.2831855) + .field public static literal float32 Float_3QuartersOfPI = float32(2.3561945) + .field public static literal float32 Float_PIDiv360 = float32(8.7266462e-003) + .field public static literal float32 Float_PIDiv16 = float32(0.19634955) + .field public static literal float32 Float_PIDiv32 = float32(9.8174773e-002) + .field public static literal float32 Float_PIInverseFraction = float32(0.31830987) + .field public static literal float32 Float_PIInverseFraction2 = float32(0.63661975) + .field public static literal float32 Float_PIInverseFraction5 = float32(1.5915494) + .field public static literal float32 Float_PITimes90 = float32(282.74335) + .field public static literal float32 Float_PITimes180 = float32(565.48669) + .field public static literal float32 Float_LooksLikePI = float32(3.1415925) + .field public static literal float32 Float_LooksLikePI2 = float32(3.1415901) + .field public static literal float32 Float_LooksLikePI3 = float32(3.141) + .field public static literal float32 Float_Negated_PI = float32(-3.1415927) + .field public static literal float32 Float_Negated_HalfOfPI = float32(-1.5707964) + .field public static literal float32 Float_Negated_QuarterOfPI = float32(-0.78539819) + .field public static literal float32 Float_Negated_PITimes2 = float32(-6.2831855) + .field public static literal float32 Float_Negated_3QuartersOfPI = float32(-2.3561945) + .field public static literal float32 Float_Negated_PIDiv360 = float32(-8.7266462e-003) + .field public static literal float32 Float_Negated_PIDiv16 = float32(-0.19634955) + .field public static literal float32 Float_Negated_PIDiv32 = float32(-9.8174773e-002) + .field public static literal float32 Float_Negated_PIInverseFraction = float32(-0.31830987) + .field public static literal float32 Float_Negated_PIInverseFraction2 = float32(-0.63661975) + .field public static literal float32 Float_Negated_PIInverseFraction5 = float32(-1.5915494) + .field public static literal float32 Float_Negated_PITimes90 = float32(-282.74335) + .field public static literal float32 Float_Negated_PITimes180 = float32(-565.48669) + .field public static literal float32 Float_Negated_LooksLikePI = float32(-3.141) + .field public static literal float32 Float_E = float32(2.7182817) + .field public static literal float32 Float_Negated_E = float32(-2.7182817) + .field public static literal float64 Double_PI = float64(3.1415926535897931) + .field public static literal float64 Double_HalfOfPI = float64(1.5707963267948966) + .field public static literal float64 Double_QuarterOfPI = float64(0.78539816339744828) + .field public static literal float64 Double_PITimes2 = float64(6.2831853071795862) + .field public static literal float64 Double_3QuartersOfPI = float64(2.3561944901923448) + .field public static literal float64 Double_PIDiv360 = float64(8.7266462599716477e-003) + .field public static literal float64 Double_PIDiv16 = float64(0.19634954084936207) + .field public static literal float64 Double_PIDiv32 = float64(9.8174770424681035e-002) + .field public static literal float64 Double_PIInverseFraction = float64(0.31830988618379069) + .field public static literal float64 Double_PIInverseFraction2 = float64(0.63661977236758138) + .field public static literal float64 Double_PIInverseFraction5 = float64(1.5915494309189535) + .field public static literal float64 Double_PITimes90 = float64(282.74333882308139) + .field public static literal float64 Double_PITimes180 = float64(565.48667764616278) + .field public static literal float64 Double_LooksLikePI = float64(3.1415926000000001) + .field public static literal float64 Double_LooksLikePI2 = float64(3.1415899999999999) + .field public static literal float64 Double_LooksLikePI3 = float64(3.141) + .field public static literal float64 Double_Negated_PI = float64(-3.1415926535897931) + .field public static literal float64 Double_Negated_HalfOfPI = float64(-1.5707963267948966) + .field public static literal float64 Double_Negated_QuarterOfPI = float64(-0.78539816339744828) + .field public static literal float64 Double_Negated_PITimes2 = float64(-6.2831853071795862) + .field public static literal float64 Double_Negated_3QuartersOfPI = float64(-2.3561944901923448) + .field public static literal float64 Double_Negated_PIDiv360 = float64(-8.7266462599716477e-003) + .field public static literal float64 Double_Negated_PIDiv16 = float64(-0.19634954084936207) + .field public static literal float64 Double_Negated_PIDiv32 = float64(-9.8174770424681035e-002) + .field public static literal float64 Double_Negated_PIInverseFraction = float64(-0.31830988618379069) + .field public static literal float64 Double_Negated_PIInverseFraction2 = float64(-0.63661977236758138) + .field public static literal float64 Double_Negated_PIInverseFraction5 = float64(-1.5915494309189535) + .field public static literal float64 Double_Negated_PITimes90 = float64(-282.74333882308139) + .field public static literal float64 Double_Negated_PITimes180 = float64(-565.48667764616278) + .field public static literal float64 Double_Negated_LooksLikePI = float64(-3.141) + .field public static literal float64 Double_E = float64(2.7182818284590451) + .field public static literal float64 Double_Negated_E = float64(-2.7182818284590451) .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 8f905b06c..730d30560 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -1271,7 +1271,8 @@ namespace ICSharpCode.Decompiler.CSharp enumDec.AddAnnotation(new MemberResolveResult(null, field)); return enumDec; } - typeSystemAstBuilder.UseSpecialConstants = !field.DeclaringType.Equals(field.ReturnType); + bool isMathPIOrE = ((field.Name == "PI" || field.Name == "E") && (field.DeclaringType.FullName == "System.Math" || field.DeclaringType.FullName == "System.MathF")); + typeSystemAstBuilder.UseSpecialConstants = !(field.DeclaringType.Equals(field.ReturnType) || isMathPIOrE); var fieldDecl = typeSystemAstBuilder.ConvertEntity(field); SetNewModifier(fieldDecl); if (settings.FixedBuffers && IsFixedField(field, out var elementType, out var elementCount)) { diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs index 575306478..5cc27e19e 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs @@ -713,6 +713,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } else { if (IsSpecialConstant(type, constantValue, out var expr)) return expr; + if (type.IsKnownType(KnownTypeCode.Double) || type.IsKnownType(KnownTypeCode.Single)) + return ConvertFloatingPointLiteral(type, constantValue); IType literalType = type; bool smallInteger = type.IsCSharpSmallIntegerType(); if (smallInteger) { @@ -915,9 +917,276 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } return new CastExpression(ConvertType(type), new PrimitiveExpression(CSharpPrimitiveCast.Cast(enumBaseTypeCode, val, false))); } - + + static bool IsValidFraction(long num, long den) + { + if (!(den > 0 && num != 0)) + return false; + + if (den == 1 || Math.Abs(num) == 1) + return true; + return Math.Abs(num) < den && new int[] { 2, 3, 5 }.Any(x => den % x == 0); + } + + const int MAX_DENOMINATOR = 1000; + + const double DOUBLE_THRESHOLD = 1e-10; + const float FLOAT_THRESHOLD = 1e-10f; + + Expression ConvertFloatingPointLiteral(IType type, object constantValue) + { + bool isDouble = type.IsKnownType(KnownTypeCode.Double); + ICompilation compilation = type.GetDefinition().Compilation; + Expression expr = null; + + if (isDouble) { + if ((double)constantValue >= int.MaxValue || (double)constantValue <= int.MinValue) { + expr = new PrimitiveExpression(constantValue); + } + } else { + if ((float)constantValue >= int.MaxValue || (float)constantValue <= int.MinValue) { + expr = new PrimitiveExpression(constantValue); + } + } + + if (expr == null && UseSpecialConstants) { + IType mathType; + if (isDouble) + mathType = compilation.FindType(typeof(Math)); + else + mathType = compilation.FindType(new TopLevelTypeName("System", "MathF")).GetDefinition() + ?? compilation.FindType(typeof(Math)); + + expr = TryExtractExpression(mathType, type, constantValue, "PI", isDouble) + ?? TryExtractExpression(mathType, type, constantValue, "E", isDouble); + } + + if (expr == null) { + (long num, long den) = isDouble + ? DoubleFractionApprox((double)constantValue, MAX_DENOMINATOR) + : FloatFractionApprox((float)constantValue, MAX_DENOMINATOR); + + if (IsValidFraction(num, den) && Math.Abs(num) != 1 && Math.Abs(den) != 1) { + var left = MakeConstant(type, num); + var right = MakeConstant(type, den); + return new BinaryOperatorExpression(left, BinaryOperatorType.Divide, right).WithoutILInstruction() + .WithRR(new ConstantResolveResult(type, constantValue)); + } + } + + if (expr == null) + expr = new PrimitiveExpression(constantValue); + + if (AddResolveResultAnnotations) + expr.AddAnnotation(new ConstantResolveResult(type, constantValue)); + + return expr; + } + + Expression MakeConstant(IType type, long c) + { + return new PrimitiveExpression(CSharpPrimitiveCast.Cast(type.GetTypeCode(), c, checkForOverflow: true)); + } + + const float MathF_PI = 3.14159274f; + const float MathF_E = 2.71828175f; + + Expression TryExtractExpression(IType mathType, IType type, object literalValue, string memberName, bool isDouble) + { + Expression MakeFieldReference() + { + AstType mathAstType = ConvertType(mathType); + var fieldRef = new MemberReferenceExpression(new TypeReferenceExpression(mathAstType), memberName); + if (AddResolveResultAnnotations) + fieldRef.WithRR(new MemberResolveResult(mathAstType.GetResolveResult(), mathType.GetFields(f => f.Name == memberName).Single())); + if (type.IsKnownType(KnownTypeCode.Double)) + return fieldRef; + if (mathType.Name == "MathF") + return fieldRef; + return new CastExpression(ConvertType(type), fieldRef); + } + + Expression ExtractExpression(long n, long d) + { + Expression fieldReference = MakeFieldReference(); + + Expression expr = fieldReference; + + if (n != 1) { + if (n == -1) { + expr = new UnaryOperatorExpression(UnaryOperatorType.Minus, expr); + } else { + expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Multiply, MakeConstant(type, n)); + } + } + + if (d != 1) { + expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Divide, MakeConstant(type, d)); + } + + if (isDouble) { + if (Math.Abs((double)literalValue - (memberName == "PI" ? Math.PI : Math.E) * n / d) < DOUBLE_THRESHOLD) + return expr; + } else { + float approxValue = (memberName == "PI" ? MathF_PI : MathF_E) * n / d; + float diff = (float)literalValue - approxValue; + if ((float)Math.Abs(diff) < FLOAT_THRESHOLD) + return expr; + } + + expr = fieldReference.Detach(); + expr = new BinaryOperatorExpression(MakeConstant(type, n), BinaryOperatorType.Divide, expr); + + if (d != 1) { + expr = new BinaryOperatorExpression(MakeConstant(type, d), BinaryOperatorType.Multiply, expr); + } + + if (isDouble) { + if (Math.Abs((double)literalValue - (n / (d * (memberName == "PI" ? Math.PI : Math.E)))) < DOUBLE_THRESHOLD) + return expr; + } else { + float approxValue = n / (d * (memberName == "PI" ? MathF_PI : MathF_E)); + float diff = (float)literalValue - approxValue; + if ((float)Math.Abs(diff) < FLOAT_THRESHOLD) + return expr; + } + + return null; + } + + (long num, long den) = isDouble + ? DoubleFractionApprox((double)literalValue / (memberName == "PI" ? Math.PI : Math.E), MAX_DENOMINATOR) + : FloatFractionApprox((float)literalValue / (memberName == "PI" ? MathF_PI : MathF_E), MAX_DENOMINATOR); + + if (IsValidFraction(num, den)) { + return ExtractExpression(num, den); + } + + (num, den) = isDouble + ? DoubleFractionApprox((double)literalValue * (memberName == "PI" ? Math.PI : Math.E), MAX_DENOMINATOR) + : FloatFractionApprox((float)literalValue * (memberName == "PI" ? MathF_PI : MathF_E), MAX_DENOMINATOR); + + if (IsValidFraction(num, den)) { + return ExtractExpression(num, den); + } + + return null; + } + + #region FractionApprox + // based on https://www.ics.uci.edu/~eppstein/numth/frap.c + // find rational approximation to given real number + // David Eppstein / UC Irvine / 8 Aug 1993 + // + // With corrections from Arno Formella, May 2008 + // + // usage: a.out r d + // r is real number to approx + // d is the maximum denominator allowed + // + // based on the theory of continued fractions + // if x = a1 + 1/(a2 + 1/(a3 + 1/(a4 + ...))) + // then best approximation is found by truncating this series + // (with some adjustments in the last term). + // + // Note the fraction can be recovered as the first column of the matrix + // ( a1 1 ) ( a2 1 ) ( a3 1 ) ... + // ( 1 0 ) ( 1 0 ) ( 1 0 ) + // Instead of keeping the sequence of continued fraction terms, + // we just keep the last partial product of these matrices. + static (long Num, long Den) DoubleFractionApprox(double value, int maxDenominator) + { + if (value > 0x7FFFFFFF) + return (0, 0); + + double startValue = value; + if (value < 0) + value = -value; + bool IsValid(long num, long den) => den > 0 && (double)Math.Abs(value - num / (double)den) < DOUBLE_THRESHOLD; + + long ai; + long[,] m = new long[2, 2]; + + m[0, 0] = m[1, 1] = 1; + m[0, 1] = m[1, 0] = 0; + + double v = value; + + while (m[1, 0] * (ai = (long)v) + m[1, 1] <= maxDenominator) { + long t = m[0, 0] * ai + m[0, 1]; + m[0, 1] = m[0, 0]; + m[0, 0] = t; + t = m[1, 0] * ai + m[1, 1]; + m[1, 1] = m[1, 0]; + m[1, 0] = t; + if (v - ai == 0) break; + v = 1 / (v - ai); + if (Math.Abs(v) > long.MaxValue) break; // value cannot be stored in fraction without overflow + } + + if (m[1, 0] == 0) + return (0, 0); + + if (!IsValid(num: m[0, 0], den: m[1, 0])) { + ai = (maxDenominator - m[1, 1]) / m[1, 0]; + m[0, 0] = m[0, 0] * ai + m[0, 1]; + m[1, 0] = m[1, 0] * ai + m[1, 1]; + } + + if (!IsValid(num: m[0, 0], den: m[1, 0])) + return (0, 0); + + return ((startValue < 0 ? -m[0, 0] : m[0, 0]), m[1, 0]); + } + + static (long Num, long Den) FloatFractionApprox(float value, int maxDenominator) + { + if (value > 0x7FFFFFFF) + return (0, 0); + + float startValue = value; + if (value < 0) + value = -value; + + bool IsValid(long num, long den) => den > 0 && (float)Math.Abs(value - num / (float)den) < 1e-9f; + + long ai; + long[,] m = new long[2, 2]; + + m[0, 0] = m[1, 1] = 1; + m[0, 1] = m[1, 0] = 0; + + float v = value; + + while (m[1, 0] * (ai = (long)v) + m[1, 1] <= maxDenominator) { + long t = m[0, 0] * ai + m[0, 1]; + m[0, 1] = m[0, 0]; + m[0, 0] = t; + t = m[1, 0] * ai + m[1, 1]; + m[1, 1] = m[1, 0]; + m[1, 0] = t; + if (v - ai == 0) break; + v = 1 / (v - ai); + if (Math.Abs(v) > long.MaxValue) break; // value cannot be stored in fraction without overflow + } + + if (m[1, 0] == 0) + return (0, 0); + + if (!IsValid(num: m[0, 0], den: m[1, 0])) { + ai = (maxDenominator - m[1, 1]) / m[1, 0]; + m[0, 0] = m[0, 0] * ai + m[0, 1]; + m[1, 0] = m[1, 0] * ai + m[1, 1]; + } + + if (!IsValid(num: m[0, 0], den: m[1, 0])) + return (0, 0); + + return (startValue < 0 ? -m[0, 0] : m[0, 0], m[1, 0]); + } #endregion - + #endregion + #region Convert Parameter public ParameterDeclaration ConvertParameter(IParameter parameter) { From 063c06c9c804a5a7e684100b829bb7bcf35e4650 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Wed, 2 Jan 2019 23:59:05 +0100 Subject: [PATCH 03/12] Apply suggestions from code review. --- .../TestCases/Pretty/WellKnownConstants.cs | 12 +++ .../TestCases/Pretty/WellKnownConstants.il | 8 ++ .../Pretty/WellKnownConstants.opt.il | 8 ++ .../Pretty/WellKnownConstants.opt.roslyn.il | 8 ++ .../Pretty/WellKnownConstants.roslyn.il | 8 ++ .../CSharp/Syntax/TypeSystemAstBuilder.cs | 97 +++++-------------- 6 files changed, 68 insertions(+), 73 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.cs index d01cbfa7c..d28027739 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.cs @@ -83,6 +83,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public const float Float_LooksLikePI = 3.1415925f; public const float Float_LooksLikePI2 = 3.14159f; public const float Float_LooksLikePI3 = 3.141f; + public const float Float_BeforePI = 3.1415925f; + public const float Float_AfterPI = 3.141593f; public const float Float_Negated_PI = -(float)Math.PI; public const float Float_Negated_HalfOfPI = -(float)Math.PI / 2f; public const float Float_Negated_QuarterOfPI = -(float)Math.PI / 4f; @@ -97,6 +99,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public const float Float_Negated_PITimes90 = (float)Math.PI * -90f; public const float Float_Negated_PITimes180 = (float)Math.PI * -180f; public const float Float_Negated_LooksLikePI = -3.141f; + public const float Float_Negated_BeforePI = -3.1415925f; + public const float Float_Negated_AfterPI = -3.141593f; public const float Float_E = (float)Math.E; public const float Float_Negated_E = -(float)Math.E; @@ -117,6 +121,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public const double Double_LooksLikePI = 3.1415926; public const double Double_LooksLikePI2 = 3.14159; public const double Double_LooksLikePI3 = 3.141; + public const double Double_BeforePI = 3.1415926535897927; + public const double Double_AfterPI = 3.1415926535897936; public const double Double_Negated_PI = -Math.PI; public const double Double_Negated_HalfOfPI = -Math.PI / 2.0; public const double Double_Negated_QuarterOfPI = -Math.PI / 4.0; @@ -131,8 +137,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public const double Double_Negated_PITimes90 = Math.PI * -90.0; public const double Double_Negated_PITimes180 = Math.PI * -180.0; public const double Double_Negated_LooksLikePI = -3.141; + public const double Double_Negated_BeforePI = -3.1415926535897927; + public const double Double_Negated_AfterPI = -3.1415926535897936; public const double Double_E = Math.E; + public const double Double_BeforeE = 2.7182818284590446; + public const double Double_AfterE = 2.7182818284590455; public const double Double_Negated_E = -Math.E; + public const double Double_Negated_BeforeE = -2.7182818284590446; + public const double Double_Negated_AfterE = -2.7182818284590455; } } \ No newline at end of file diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.il index 37b6ed0e8..0be442c79 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.il @@ -126,6 +126,8 @@ .field public static literal float64 Double_LooksLikePI = float64(3.1415926000000001) .field public static literal float64 Double_LooksLikePI2 = float64(3.1415899999999999) .field public static literal float64 Double_LooksLikePI3 = float64(3.141) + .field public static literal float64 Double_BeforePI = float64(3.1415926535897927) + .field public static literal float64 Double_AfterPI = float64(3.1415926535897936) .field public static literal float64 Double_Negated_PI = float64(-3.1415926535897931) .field public static literal float64 Double_Negated_HalfOfPI = float64(-1.5707963267948966) .field public static literal float64 Double_Negated_QuarterOfPI = float64(-0.78539816339744828) @@ -140,8 +142,14 @@ .field public static literal float64 Double_Negated_PITimes90 = float64(-282.74333882308139) .field public static literal float64 Double_Negated_PITimes180 = float64(-565.48667764616278) .field public static literal float64 Double_Negated_LooksLikePI = float64(-3.141) + .field public static literal float64 Double_Negated_BeforePI = float64(-3.1415926535897927) + .field public static literal float64 Double_Negated_AfterPI = float64(-3.1415926535897936) .field public static literal float64 Double_E = float64(2.7182818284590451) + .field public static literal float64 Double_BeforeE = float64(2.7182818284590446) + .field public static literal float64 Double_AfterE = float64(2.7182818284590455) .field public static literal float64 Double_Negated_E = float64(-2.7182818284590451) + .field public static literal float64 Double_Negated_BeforeE = float64(-2.7182818284590446) + .field public static literal float64 Double_Negated_AfterE = float64(-2.7182818284590455) .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.il index b4623d634..e6641ea58 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.il @@ -126,6 +126,8 @@ .field public static literal float64 Double_LooksLikePI = float64(3.1415926000000001) .field public static literal float64 Double_LooksLikePI2 = float64(3.1415899999999999) .field public static literal float64 Double_LooksLikePI3 = float64(3.141) + .field public static literal float64 Double_BeforePI = float64(3.1415926535897927) + .field public static literal float64 Double_AfterPI = float64(3.1415926535897936) .field public static literal float64 Double_Negated_PI = float64(-3.1415926535897931) .field public static literal float64 Double_Negated_HalfOfPI = float64(-1.5707963267948966) .field public static literal float64 Double_Negated_QuarterOfPI = float64(-0.78539816339744828) @@ -140,8 +142,14 @@ .field public static literal float64 Double_Negated_PITimes90 = float64(-282.74333882308139) .field public static literal float64 Double_Negated_PITimes180 = float64(-565.48667764616278) .field public static literal float64 Double_Negated_LooksLikePI = float64(-3.141) + .field public static literal float64 Double_Negated_BeforePI = float64(-3.1415926535897927) + .field public static literal float64 Double_Negated_AfterPI = float64(-3.1415926535897936) .field public static literal float64 Double_E = float64(2.7182818284590451) + .field public static literal float64 Double_BeforeE = float64(2.7182818284590446) + .field public static literal float64 Double_AfterE = float64(2.7182818284590455) .field public static literal float64 Double_Negated_E = float64(-2.7182818284590451) + .field public static literal float64 Double_Negated_BeforeE = float64(-2.7182818284590446) + .field public static literal float64 Double_Negated_AfterE = float64(-2.7182818284590455) .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.roslyn.il index 534c4085a..8b8126fd6 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.roslyn.il @@ -130,6 +130,8 @@ .field public static literal float64 Double_LooksLikePI = float64(3.1415926000000001) .field public static literal float64 Double_LooksLikePI2 = float64(3.1415899999999999) .field public static literal float64 Double_LooksLikePI3 = float64(3.141) + .field public static literal float64 Double_BeforePI = float64(3.1415926535897927) + .field public static literal float64 Double_AfterPI = float64(3.1415926535897936) .field public static literal float64 Double_Negated_PI = float64(-3.1415926535897931) .field public static literal float64 Double_Negated_HalfOfPI = float64(-1.5707963267948966) .field public static literal float64 Double_Negated_QuarterOfPI = float64(-0.78539816339744828) @@ -144,8 +146,14 @@ .field public static literal float64 Double_Negated_PITimes90 = float64(-282.74333882308139) .field public static literal float64 Double_Negated_PITimes180 = float64(-565.48667764616278) .field public static literal float64 Double_Negated_LooksLikePI = float64(-3.141) + .field public static literal float64 Double_Negated_BeforePI = float64(-3.1415926535897927) + .field public static literal float64 Double_Negated_AfterPI = float64(-3.1415926535897936) .field public static literal float64 Double_E = float64(2.7182818284590451) + .field public static literal float64 Double_BeforeE = float64(2.7182818284590446) + .field public static literal float64 Double_AfterE = float64(2.7182818284590455) .field public static literal float64 Double_Negated_E = float64(-2.7182818284590451) + .field public static literal float64 Double_Negated_BeforeE = float64(-2.7182818284590446) + .field public static literal float64 Double_Negated_AfterE = float64(-2.7182818284590455) .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.roslyn.il index f4f77372a..c1499e718 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.roslyn.il @@ -130,6 +130,8 @@ .field public static literal float64 Double_LooksLikePI = float64(3.1415926000000001) .field public static literal float64 Double_LooksLikePI2 = float64(3.1415899999999999) .field public static literal float64 Double_LooksLikePI3 = float64(3.141) + .field public static literal float64 Double_BeforePI = float64(3.1415926535897927) + .field public static literal float64 Double_AfterPI = float64(3.1415926535897936) .field public static literal float64 Double_Negated_PI = float64(-3.1415926535897931) .field public static literal float64 Double_Negated_HalfOfPI = float64(-1.5707963267948966) .field public static literal float64 Double_Negated_QuarterOfPI = float64(-0.78539816339744828) @@ -144,8 +146,14 @@ .field public static literal float64 Double_Negated_PITimes90 = float64(-282.74333882308139) .field public static literal float64 Double_Negated_PITimes180 = float64(-565.48667764616278) .field public static literal float64 Double_Negated_LooksLikePI = float64(-3.141) + .field public static literal float64 Double_Negated_BeforePI = float64(-3.1415926535897927) + .field public static literal float64 Double_Negated_AfterPI = float64(-3.1415926535897936) .field public static literal float64 Double_E = float64(2.7182818284590451) + .field public static literal float64 Double_BeforeE = float64(2.7182818284590446) + .field public static literal float64 Double_AfterE = float64(2.7182818284590455) .field public static literal float64 Double_Negated_E = float64(-2.7182818284590451) + .field public static literal float64 Double_Negated_BeforeE = float64(-2.7182818284590446) + .field public static literal float64 Double_Negated_AfterE = float64(-2.7182818284590455) .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs index 5cc27e19e..723c5a804 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs @@ -930,9 +930,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax const int MAX_DENOMINATOR = 1000; - const double DOUBLE_THRESHOLD = 1e-10; - const float FLOAT_THRESHOLD = 1e-10f; - Expression ConvertFloatingPointLiteral(IType type, object constantValue) { bool isDouble = type.IsKnownType(KnownTypeCode.Double); @@ -963,8 +960,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax if (expr == null) { (long num, long den) = isDouble - ? DoubleFractionApprox((double)constantValue, MAX_DENOMINATOR) - : FloatFractionApprox((float)constantValue, MAX_DENOMINATOR); + ? FractionApprox((double)constantValue, MAX_DENOMINATOR) + : FractionApprox((float)constantValue, MAX_DENOMINATOR); if (IsValidFraction(num, den) && Math.Abs(num) != 1 && Math.Abs(den) != 1) { var left = MakeConstant(type, num); @@ -1025,12 +1022,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } if (isDouble) { - if (Math.Abs((double)literalValue - (memberName == "PI" ? Math.PI : Math.E) * n / d) < DOUBLE_THRESHOLD) + double approxValue = n / (double)d * (memberName == "PI" ? Math.PI : Math.E); + if (approxValue == (double)literalValue) return expr; } else { - float approxValue = (memberName == "PI" ? MathF_PI : MathF_E) * n / d; - float diff = (float)literalValue - approxValue; - if ((float)Math.Abs(diff) < FLOAT_THRESHOLD) + float approxValue = n / (float)d * (memberName == "PI" ? MathF_PI : MathF_E); + if (approxValue == (float)literalValue) return expr; } @@ -1042,12 +1039,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } if (isDouble) { - if (Math.Abs((double)literalValue - (n / (d * (memberName == "PI" ? Math.PI : Math.E)))) < DOUBLE_THRESHOLD) + double approxValue = n / (d * (memberName == "PI" ? Math.PI : Math.E)); + if (approxValue == (double)literalValue) return expr; } else { float approxValue = n / (d * (memberName == "PI" ? MathF_PI : MathF_E)); - float diff = (float)literalValue - approxValue; - if ((float)Math.Abs(diff) < FLOAT_THRESHOLD) + if (approxValue == (float)literalValue) return expr; } @@ -1055,16 +1052,16 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } (long num, long den) = isDouble - ? DoubleFractionApprox((double)literalValue / (memberName == "PI" ? Math.PI : Math.E), MAX_DENOMINATOR) - : FloatFractionApprox((float)literalValue / (memberName == "PI" ? MathF_PI : MathF_E), MAX_DENOMINATOR); + ? FractionApprox((double)literalValue / (memberName == "PI" ? Math.PI : Math.E), MAX_DENOMINATOR) + : FractionApprox((float)literalValue / (memberName == "PI" ? MathF_PI : MathF_E), MAX_DENOMINATOR); if (IsValidFraction(num, den)) { return ExtractExpression(num, den); } (num, den) = isDouble - ? DoubleFractionApprox((double)literalValue * (memberName == "PI" ? Math.PI : Math.E), MAX_DENOMINATOR) - : FloatFractionApprox((float)literalValue * (memberName == "PI" ? MathF_PI : MathF_E), MAX_DENOMINATOR); + ? FractionApprox((double)literalValue * (memberName == "PI" ? Math.PI : Math.E), MAX_DENOMINATOR) + : FractionApprox((float)literalValue * (memberName == "PI" ? MathF_PI : MathF_E), MAX_DENOMINATOR); if (IsValidFraction(num, den)) { return ExtractExpression(num, den); @@ -1073,7 +1070,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return null; } - #region FractionApprox // based on https://www.ics.uci.edu/~eppstein/numth/frap.c // find rational approximation to given real number // David Eppstein / UC Irvine / 8 Aug 1993 @@ -1094,7 +1090,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax // ( 1 0 ) ( 1 0 ) ( 1 0 ) // Instead of keeping the sequence of continued fraction terms, // we just keep the last partial product of these matrices. - static (long Num, long Den) DoubleFractionApprox(double value, int maxDenominator) + static (long Num, long Den) FractionApprox(double value, int maxDenominator) { if (value > 0x7FFFFFFF) return (0, 0); @@ -1102,7 +1098,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax double startValue = value; if (value < 0) value = -value; - bool IsValid(long num, long den) => den > 0 && (double)Math.Abs(value - num / (double)den) < DOUBLE_THRESHOLD; long ai; long[,] m = new long[2, 2]; @@ -1127,65 +1122,21 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax if (m[1, 0] == 0) return (0, 0); - if (!IsValid(num: m[0, 0], den: m[1, 0])) { - ai = (maxDenominator - m[1, 1]) / m[1, 0]; - m[0, 0] = m[0, 0] * ai + m[0, 1]; - m[1, 0] = m[1, 0] * ai + m[1, 1]; - } - - if (!IsValid(num: m[0, 0], den: m[1, 0])) - return (0, 0); - - return ((startValue < 0 ? -m[0, 0] : m[0, 0]), m[1, 0]); - } - - static (long Num, long Den) FloatFractionApprox(float value, int maxDenominator) - { - if (value > 0x7FFFFFFF) - return (0, 0); - - float startValue = value; - if (value < 0) - value = -value; - - bool IsValid(long num, long den) => den > 0 && (float)Math.Abs(value - num / (float)den) < 1e-9f; - - long ai; - long[,] m = new long[2, 2]; + long firstN = m[0, 0]; + long firstD = m[1, 0]; - m[0, 0] = m[1, 1] = 1; - m[0, 1] = m[1, 0] = 0; + ai = (maxDenominator - m[1, 1]) / m[1, 0]; + long secondN = m[0, 0] * ai + m[0, 1]; + long secondD = m[1, 0] * ai + m[1, 1]; - float v = value; + double firstDelta = Math.Abs(value - firstN / (double)firstD); + double secondDelta = Math.Abs(value - secondN / (double)secondD); - while (m[1, 0] * (ai = (long)v) + m[1, 1] <= maxDenominator) { - long t = m[0, 0] * ai + m[0, 1]; - m[0, 1] = m[0, 0]; - m[0, 0] = t; - t = m[1, 0] * ai + m[1, 1]; - m[1, 1] = m[1, 0]; - m[1, 0] = t; - if (v - ai == 0) break; - v = 1 / (v - ai); - if (Math.Abs(v) > long.MaxValue) break; // value cannot be stored in fraction without overflow - } - - if (m[1, 0] == 0) - return (0, 0); - - if (!IsValid(num: m[0, 0], den: m[1, 0])) { - ai = (maxDenominator - m[1, 1]) / m[1, 0]; - m[0, 0] = m[0, 0] * ai + m[0, 1]; - m[1, 0] = m[1, 0] * ai + m[1, 1]; - } - - if (!IsValid(num: m[0, 0], den: m[1, 0])) - return (0, 0); - - return (startValue < 0 ? -m[0, 0] : m[0, 0], m[1, 0]); + if (firstDelta < secondDelta) + return (startValue < 0 ? -firstN : firstN, firstD); + return (startValue < 0 ? -secondN : secondN, secondD); } #endregion - #endregion #region Convert Parameter public ParameterDeclaration ConvertParameter(IParameter parameter) From 640964cb0ac9ff37bee96f511b1cc4906140f427 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Thu, 3 Jan 2019 00:01:09 +0100 Subject: [PATCH 04/12] #1314: do not use special constants, if literal is inside array initializer. --- .../TestCases/Pretty/InitializerTests.cs | 10 +++++++ .../TestCases/Pretty/InitializerTests.il | 29 +++++++++++++++++++ .../TestCases/Pretty/InitializerTests.opt.il | 23 +++++++++++++++ .../Pretty/InitializerTests.opt.roslyn.il | 22 ++++++++++++-- .../Pretty/InitializerTests.roslyn.il | 28 ++++++++++++++++-- .../CSharp/ExpressionBuilder.cs | 2 ++ 6 files changed, 110 insertions(+), 4 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs index f20190a4e..b97078f63 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs @@ -733,6 +733,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests } #endif + private byte[] Issue1314() + { + return new byte[4] { + 0, + 1, + 2, + 255 + }; + } + private void Issue1251_Test(List list, OtherItem otherItem) { list.Add(new Item { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.il index 58883c4d2..c066c7d83 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.il @@ -2383,6 +2383,26 @@ IL_001a: ret } // end of method TestCases::Issue1250_Test1 + .method private hidebysig instance uint8[] + Issue1314() cil managed + { + // Code size 23 (0x17) + .maxstack 3 + .locals init (uint8[] V_0) + IL_0000: nop + IL_0001: ldc.i4.4 + IL_0002: newarr [mscorlib]System.Byte + IL_0007: dup + IL_0008: ldtoken field int32 ''::'$$method0x600002e-1' + IL_000d: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, + valuetype [mscorlib]System.RuntimeFieldHandle) + IL_0012: stloc.0 + IL_0013: br.s IL_0015 + + IL_0015: ldloc.0 + IL_0016: ret + } // end of method TestCases::Issue1314 + .method private hidebysig instance void Issue1251_Test(class [mscorlib]System.Collections.Generic.List`1 list, class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests.TestCases/OtherItem otherItem) cil managed @@ -2549,7 +2569,16 @@ } // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests.TestCases +.class private auto ansi '' + extends [mscorlib]System.Object +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .field static assembly int32 '$$method0x600002e-1' at I_000029A8 +} // end of class '' + // ============================================================= +.data cil I_000029A8 = bytearray ( + 00 01 02 FF) // *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.opt.il index 2ef6a16d9..47c204974 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.opt.il @@ -2040,6 +2040,20 @@ IL_0018: ret } // end of method TestCases::Issue1250_Test1 + .method private hidebysig instance uint8[] + Issue1314() cil managed + { + // Code size 18 (0x12) + .maxstack 8 + IL_0000: ldc.i4.4 + IL_0001: newarr [mscorlib]System.Byte + IL_0006: dup + IL_0007: ldtoken field int32 ''::'$$method0x600002e-1' + IL_000c: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, + valuetype [mscorlib]System.RuntimeFieldHandle) + IL_0011: ret + } // end of method TestCases::Issue1314 + .method private hidebysig instance void Issue1251_Test(class [mscorlib]System.Collections.Generic.List`1 list, class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests.TestCases/OtherItem otherItem) cil managed @@ -2176,7 +2190,16 @@ } // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests.TestCases +.class private auto ansi '' + extends [mscorlib]System.Object +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .field static assembly int32 '$$method0x600002e-1' at I_000028A0 +} // end of class '' + // ============================================================= +.data cil I_000028A0 = bytearray ( + 00 01 02 FF) // *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.opt.roslyn.il index c4626b3f0..4e379ae68 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.opt.roslyn.il @@ -2136,6 +2136,20 @@ IL_0023: ret } // end of method TestCases::Issue1250_Test4 + .method private hidebysig instance uint8[] + Issue1314() cil managed + { + // Code size 18 (0x12) + .maxstack 8 + IL_0000: ldc.i4.4 + IL_0001: newarr [mscorlib]System.Byte + IL_0006: dup + IL_0007: ldtoken field int32 ''::C62C27924F4C967F5EDDB1850C091D54C7A2AB58 + IL_000c: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, + valuetype [mscorlib]System.RuntimeFieldHandle) + IL_0011: ret + } // end of method TestCases::Issue1314 + .method private hidebysig instance void Issue1251_Test(class [mscorlib]System.Collections.Generic.List`1 list, class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests.TestCases/OtherItem otherItem) cil managed @@ -2251,13 +2265,17 @@ .size 40 } // end of class '__StaticArrayInitTypeSize=40' - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' E0D2592373A0C161E56E266306CD8405CD719D19 at I_00005180 + .field static assembly initonly int32 C62C27924F4C967F5EDDB1850C091D54C7A2AB58 at I_000051F0 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' E0D2592373A0C161E56E266306CD8405CD719D19 at I_000051F8 } // end of class '' // ============================================================= -.data cil I_00005180 = bytearray ( +.data cil I_000051F0 = bytearray ( + 00 01 02 FF) +.data cil I_000051F4 = int8[4] +.data cil I_000051F8 = bytearray ( 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00 09 00 00 00 0A 00 00 00) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.roslyn.il index 3cbba69e2..ce855f3c5 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.roslyn.il @@ -2432,6 +2432,26 @@ IL_0026: ret } // end of method TestCases::Issue1250_Test4 + .method private hidebysig instance uint8[] + Issue1314() cil managed + { + // Code size 23 (0x17) + .maxstack 3 + .locals init (uint8[] V_0) + IL_0000: nop + IL_0001: ldc.i4.4 + IL_0002: newarr [mscorlib]System.Byte + IL_0007: dup + IL_0008: ldtoken field int32 ''::C62C27924F4C967F5EDDB1850C091D54C7A2AB58 + IL_000d: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, + valuetype [mscorlib]System.RuntimeFieldHandle) + IL_0012: stloc.0 + IL_0013: br.s IL_0015 + + IL_0015: ldloc.0 + IL_0016: ret + } // end of method TestCases::Issue1314 + .method private hidebysig instance void Issue1251_Test(class [mscorlib]System.Collections.Generic.List`1 list, class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests.TestCases/OtherItem otherItem) cil managed @@ -2575,13 +2595,17 @@ .size 40 } // end of class '__StaticArrayInitTypeSize=40' - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' E0D2592373A0C161E56E266306CD8405CD719D19 at I_0000545C + .field static assembly initonly int32 C62C27924F4C967F5EDDB1850C091D54C7A2AB58 at I_000054E8 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' E0D2592373A0C161E56E266306CD8405CD719D19 at I_000054F0 } // end of class '' // ============================================================= -.data cil I_0000545C = bytearray ( +.data cil I_000054E8 = bytearray ( + 00 01 02 FF) +.data cil I_000054EC = int8[4] +.data cil I_000054F0 = bytearray ( 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00 09 00 00 00 0A 00 00 00) diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 53c866744..fcff9fbc1 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -2270,7 +2270,9 @@ namespace ICSharpCode.Decompiler.CSharp container.Peek().Elements.Add(aie); container.Push(aie); } + astBuilder.UseSpecialConstants = !type.IsCSharpPrimitiveIntegerType(); var val = Translate(value, typeHint: type).ConvertTo(type, this, allowImplicitConversion: true); + astBuilder.UseSpecialConstants = true; container.Peek().Elements.Add(val); elementResolveResults.Add(val.ResolveResult); while (container.Count > 0 && container.Peek().Elements.Count == dimensionSizes[container.Count - 1]) { From 5b676f8edbcafc656373a24cecc896dd9f284c8b Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Thu, 3 Jan 2019 00:04:56 +0100 Subject: [PATCH 05/12] Update WellKnownConstants IL files. --- .../TestCases/Pretty/WellKnownConstants.il | 4 ++++ .../TestCases/Pretty/WellKnownConstants.opt.il | 4 ++++ .../TestCases/Pretty/WellKnownConstants.opt.roslyn.il | 4 ++++ .../TestCases/Pretty/WellKnownConstants.roslyn.il | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.il index 0be442c79..28f429981 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.il @@ -94,6 +94,8 @@ .field public static literal float32 Float_LooksLikePI = float32(3.1415925) .field public static literal float32 Float_LooksLikePI2 = float32(3.1415901) .field public static literal float32 Float_LooksLikePI3 = float32(3.141) + .field public static literal float32 Float_BeforePI = float32(3.1415925) + .field public static literal float32 Float_AfterPI = float32(3.141593) .field public static literal float32 Float_Negated_PI = float32(-3.1415927) .field public static literal float32 Float_Negated_HalfOfPI = float32(-1.5707964) .field public static literal float32 Float_Negated_QuarterOfPI = float32(-0.78539819) @@ -108,6 +110,8 @@ .field public static literal float32 Float_Negated_PITimes90 = float32(-282.74335) .field public static literal float32 Float_Negated_PITimes180 = float32(-565.48669) .field public static literal float32 Float_Negated_LooksLikePI = float32(-3.141) + .field public static literal float32 Float_Negated_BeforePI = float32(-3.1415925) + .field public static literal float32 Float_Negated_AfterPI = float32(-3.141593) .field public static literal float32 Float_E = float32(2.7182817) .field public static literal float32 Float_Negated_E = float32(-2.7182817) .field public static literal float64 Double_PI = float64(3.1415926535897931) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.il index e6641ea58..ab77fc78b 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.il @@ -94,6 +94,8 @@ .field public static literal float32 Float_LooksLikePI = float32(3.1415925) .field public static literal float32 Float_LooksLikePI2 = float32(3.1415901) .field public static literal float32 Float_LooksLikePI3 = float32(3.141) + .field public static literal float32 Float_BeforePI = float32(3.1415925) + .field public static literal float32 Float_AfterPI = float32(3.141593) .field public static literal float32 Float_Negated_PI = float32(-3.1415927) .field public static literal float32 Float_Negated_HalfOfPI = float32(-1.5707964) .field public static literal float32 Float_Negated_QuarterOfPI = float32(-0.78539819) @@ -108,6 +110,8 @@ .field public static literal float32 Float_Negated_PITimes90 = float32(-282.74335) .field public static literal float32 Float_Negated_PITimes180 = float32(-565.48669) .field public static literal float32 Float_Negated_LooksLikePI = float32(-3.141) + .field public static literal float32 Float_Negated_BeforePI = float32(-3.1415925) + .field public static literal float32 Float_Negated_AfterPI = float32(-3.141593) .field public static literal float32 Float_E = float32(2.7182817) .field public static literal float32 Float_Negated_E = float32(-2.7182817) .field public static literal float64 Double_PI = float64(3.1415926535897931) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.roslyn.il index 8b8126fd6..74a8d8c6a 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.roslyn.il @@ -98,6 +98,8 @@ .field public static literal float32 Float_LooksLikePI = float32(3.1415925) .field public static literal float32 Float_LooksLikePI2 = float32(3.1415901) .field public static literal float32 Float_LooksLikePI3 = float32(3.141) + .field public static literal float32 Float_BeforePI = float32(3.1415925) + .field public static literal float32 Float_AfterPI = float32(3.141593) .field public static literal float32 Float_Negated_PI = float32(-3.1415927) .field public static literal float32 Float_Negated_HalfOfPI = float32(-1.5707964) .field public static literal float32 Float_Negated_QuarterOfPI = float32(-0.78539819) @@ -112,6 +114,8 @@ .field public static literal float32 Float_Negated_PITimes90 = float32(-282.74335) .field public static literal float32 Float_Negated_PITimes180 = float32(-565.48669) .field public static literal float32 Float_Negated_LooksLikePI = float32(-3.141) + .field public static literal float32 Float_Negated_BeforePI = float32(-3.1415925) + .field public static literal float32 Float_Negated_AfterPI = float32(-3.141593) .field public static literal float32 Float_E = float32(2.7182817) .field public static literal float32 Float_Negated_E = float32(-2.7182817) .field public static literal float64 Double_PI = float64(3.1415926535897931) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.roslyn.il index c1499e718..81c844ce8 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.roslyn.il @@ -98,6 +98,8 @@ .field public static literal float32 Float_LooksLikePI = float32(3.1415925) .field public static literal float32 Float_LooksLikePI2 = float32(3.1415901) .field public static literal float32 Float_LooksLikePI3 = float32(3.141) + .field public static literal float32 Float_BeforePI = float32(3.1415925) + .field public static literal float32 Float_AfterPI = float32(3.141593) .field public static literal float32 Float_Negated_PI = float32(-3.1415927) .field public static literal float32 Float_Negated_HalfOfPI = float32(-1.5707964) .field public static literal float32 Float_Negated_QuarterOfPI = float32(-0.78539819) @@ -112,6 +114,8 @@ .field public static literal float32 Float_Negated_PITimes90 = float32(-282.74335) .field public static literal float32 Float_Negated_PITimes180 = float32(-565.48669) .field public static literal float32 Float_Negated_LooksLikePI = float32(-3.141) + .field public static literal float32 Float_Negated_BeforePI = float32(-3.1415925) + .field public static literal float32 Float_Negated_AfterPI = float32(-3.141593) .field public static literal float32 Float_E = float32(2.7182817) .field public static literal float32 Float_Negated_E = float32(-2.7182817) .field public static literal float64 Double_PI = float64(3.1415926535897931) From 2a571bef1a7a08f523486bb7b77e40941331c035 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 4 Jan 2019 18:17:57 +0100 Subject: [PATCH 06/12] Exclude whole numbers from "constant unfolding" for floating point literals. --- .../TestCases/Pretty/WellKnownConstants.cs | 5 +++++ .../TestCases/Pretty/WellKnownConstants.il | 4 ++++ .../TestCases/Pretty/WellKnownConstants.opt.il | 4 ++++ .../TestCases/Pretty/WellKnownConstants.opt.roslyn.il | 4 ++++ .../TestCases/Pretty/WellKnownConstants.roslyn.il | 4 ++++ ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs | 11 ++++++++--- .../CSharp/Syntax/TypeSystemAstBuilder.cs | 4 ++-- 7 files changed, 31 insertions(+), 5 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.cs index d28027739..b72dafed0 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.cs @@ -67,6 +67,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public const decimal DecimalMaxValue = decimal.MaxValue; public const decimal DecimalMinValue = decimal.MinValue; + public const float Float_One = 1f; + public const double Double_One = 1.0; + public const float Float_Two = 2f; + public const double Double_Two = 2.0; + public const float Float_PI = (float)Math.PI; public const float Float_HalfOfPI = (float)Math.PI / 2f; public const float Float_QuarterOfPI = (float)Math.PI / 4f; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.il index 28f429981..eee91fe32 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.il @@ -78,6 +78,10 @@ uint32, uint32) = ( 01 00 00 80 FF FF FF FF FF FF FF FF FF FF FF FF 00 00 ) + .field public static literal float32 Float_One = float32(1.) + .field public static literal float64 Double_One = float64(1.) + .field public static literal float32 Float_Two = float32(2.) + .field public static literal float64 Double_Two = float64(2.) .field public static literal float32 Float_PI = float32(3.1415927) .field public static literal float32 Float_HalfOfPI = float32(1.5707964) .field public static literal float32 Float_QuarterOfPI = float32(0.78539819) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.il index ab77fc78b..cdeaea1d1 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.il @@ -78,6 +78,10 @@ uint32, uint32) = ( 01 00 00 80 FF FF FF FF FF FF FF FF FF FF FF FF 00 00 ) + .field public static literal float32 Float_One = float32(1.) + .field public static literal float64 Double_One = float64(1.) + .field public static literal float32 Float_Two = float32(2.) + .field public static literal float64 Double_Two = float64(2.) .field public static literal float32 Float_PI = float32(3.1415927) .field public static literal float32 Float_HalfOfPI = float32(1.5707964) .field public static literal float32 Float_QuarterOfPI = float32(0.78539819) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.roslyn.il index 74a8d8c6a..e8bfc6b42 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.roslyn.il @@ -82,6 +82,10 @@ uint32, uint32) = ( 01 00 00 80 FF FF FF FF FF FF FF FF FF FF FF FF 00 00 ) + .field public static literal float32 Float_One = float32(1.) + .field public static literal float64 Double_One = float64(1.) + .field public static literal float32 Float_Two = float32(2.) + .field public static literal float64 Double_Two = float64(2.) .field public static literal float32 Float_PI = float32(3.1415927) .field public static literal float32 Float_HalfOfPI = float32(1.5707964) .field public static literal float32 Float_QuarterOfPI = float32(0.78539819) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.roslyn.il index 81c844ce8..4d42d3495 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.roslyn.il @@ -82,6 +82,10 @@ uint32, uint32) = ( 01 00 00 80 FF FF FF FF FF FF FF FF FF FF FF FF 00 00 ) + .field public static literal float32 Float_One = float32(1.) + .field public static literal float64 Double_One = float64(1.) + .field public static literal float32 Float_Two = float32(2.) + .field public static literal float64 Double_Two = float64(2.) .field public static literal float32 Float_PI = float32(3.1415927) .field public static literal float32 Float_HalfOfPI = float32(1.5707964) .field public static literal float32 Float_QuarterOfPI = float32(0.78539819) diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index fcff9fbc1..052095ae8 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -2270,9 +2270,14 @@ namespace ICSharpCode.Decompiler.CSharp container.Peek().Elements.Add(aie); container.Push(aie); } - astBuilder.UseSpecialConstants = !type.IsCSharpPrimitiveIntegerType(); - var val = Translate(value, typeHint: type).ConvertTo(type, this, allowImplicitConversion: true); - astBuilder.UseSpecialConstants = true; + TranslatedExpression val; + var old = astBuilder.UseSpecialConstants; + try { + astBuilder.UseSpecialConstants = !type.IsCSharpPrimitiveIntegerType(); + val = Translate(value, typeHint: type).ConvertTo(type, this, allowImplicitConversion: true); + } finally { + astBuilder.UseSpecialConstants = old; + } container.Peek().Elements.Add(val); elementResolveResults.Add(val.ResolveResult); while (container.Count > 0 && container.Peek().Elements.Count == dimensionSizes[container.Count - 1]) { diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs index 723c5a804..42e0311f3 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs @@ -937,11 +937,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax Expression expr = null; if (isDouble) { - if ((double)constantValue >= int.MaxValue || (double)constantValue <= int.MinValue) { + if (Math.Floor((double)constantValue) == (double)constantValue) { expr = new PrimitiveExpression(constantValue); } } else { - if ((float)constantValue >= int.MaxValue || (float)constantValue <= int.MinValue) { + if (Math.Floor((float)constantValue) == (float)constantValue) { expr = new PrimitiveExpression(constantValue); } } From bf5ff22b1ae41713ba36aab447f5b1050a4c91e5 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 4 Jan 2019 18:46:32 +0100 Subject: [PATCH 07/12] Add missing equality-check for fraction-only case. --- .../CSharp/Syntax/TypeSystemAstBuilder.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs index c26f59da5..fc0ead8d1 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs @@ -932,6 +932,15 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return Math.Abs(num) < den && new int[] { 2, 3, 5 }.Any(x => den % x == 0); } + static bool IsEqual(long num, long den, object constantValue, bool isDouble) + { + if (isDouble) { + return (double)constantValue == num / (double)den; + } else { + return (float)constantValue == num / (float)den; + } + } + const int MAX_DENOMINATOR = 1000; Expression ConvertFloatingPointLiteral(IType type, object constantValue) @@ -967,7 +976,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax ? FractionApprox((double)constantValue, MAX_DENOMINATOR) : FractionApprox((float)constantValue, MAX_DENOMINATOR); - if (IsValidFraction(num, den) && Math.Abs(num) != 1 && Math.Abs(den) != 1) { + if (IsValidFraction(num, den) && IsEqual(num, den, constantValue, isDouble) && Math.Abs(num) != 1 && Math.Abs(den) != 1) { var left = MakeConstant(type, num); var right = MakeConstant(type, den); return new BinaryOperatorExpression(left, BinaryOperatorType.Divide, right).WithoutILInstruction() From eb873e65d02785dda6730ac278abf8eae45de0ad Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 4 Jan 2019 18:47:00 +0100 Subject: [PATCH 08/12] Update InitializerTests after merge. --- .../TestCases/Pretty/InitializerTests.cs | 16 +-- .../TestCases/Pretty/InitializerTests.il | 30 ++++- .../TestCases/Pretty/InitializerTests.opt.il | 24 +++- .../Pretty/InitializerTests.opt.roslyn.il | 97 +++++++++------- .../Pretty/InitializerTests.roslyn.il | 108 +++++++++++------- .../CSharp/ExpressionBuilder.cs | 2 +- 6 files changed, 180 insertions(+), 97 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs index 1c71643b3..76b6a36b5 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs @@ -605,32 +605,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests 7, 8, 254, - byte.MaxValue + 255 }); } public static void ArraySByte() { X(Y(), new sbyte[8] { - sbyte.MinValue, + -128, -127, 0, 1, 2, 3, 4, - sbyte.MaxValue + 127 }); } public static void ArrayShort() { X(Y(), new short[5] { - short.MinValue, + -32768, -1, 0, 1, - short.MaxValue + 32767 }); } @@ -642,7 +642,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests 32767, 32768, 65534, - ushort.MaxValue + 65535 }); } @@ -735,8 +735,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests -100m, 0m, 100m, - decimal.MinValue, - decimal.MaxValue, + -79228162514264337593543950335m, + 79228162514264337593543950335m, 0.0000001m }); } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.il index 6bb1ae235..5056c6bd5 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.il @@ -3115,6 +3115,26 @@ IL_001a: ret } // end of method TestCases::Issue1250_Test1 + .method private hidebysig instance uint8[] + Issue1314() cil managed + { + // Code size 23 (0x17) + .maxstack 3 + .locals init (uint8[] V_0) + IL_0000: nop + IL_0001: ldc.i4.4 + IL_0002: newarr [mscorlib]System.Byte + IL_0007: dup + IL_0008: ldtoken field int32 ''::'$$method0x6000040-1' + IL_000d: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, + valuetype [mscorlib]System.RuntimeFieldHandle) + IL_0012: stloc.0 + IL_0013: br.s IL_0015 + + IL_0015: ldloc.0 + IL_0016: ret + } // end of method TestCases::Issue1314 + .method private hidebysig instance void Issue1251_Test(class [mscorlib]System.Collections.Generic.List`1 list, class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests.TestCases/OtherItem otherItem) cil managed @@ -4370,7 +4390,7 @@ IL_0787: newobj instance void int32[0...,0...]::.ctor(int32, int32) IL_078c: dup - IL_078d: ldtoken field valuetype ''/'__StaticArrayInitTypeSize=36' ''::'$$method0x600008e-1' + IL_078d: ldtoken field valuetype ''/'__StaticArrayInitTypeSize=36' ''::'$$method0x600008f-1' IL_0792: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle) IL_0797: stsfld int32[0...,0...] ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests.TestCases::Issue1336_rg2 @@ -4474,7 +4494,8 @@ .field static assembly valuetype ''/'__StaticArrayInitTypeSize=64' '$$method0x600001e-4' at I_000029A8 .field static assembly valuetype ''/'__StaticArrayInitTypeSize=72' '$$method0x600001f-1' at I_00002A58 .field static assembly valuetype ''/'__StaticArrayInitTypeSize=72' '$$method0x600001f-2' at I_00002AA0 - .field static assembly valuetype ''/'__StaticArrayInitTypeSize=36' '$$method0x600008e-1' at I_000035A0 + .field static assembly int32 '$$method0x6000040-1' at I_000032E0 + .field static assembly valuetype ''/'__StaticArrayInitTypeSize=36' '$$method0x600008f-1' at I_000035C8 } // end of class '' @@ -4583,7 +4604,10 @@ 22 00 00 00 23 00 00 00 24 00 00 00 25 00 00 00 // "...#...$...%... 26 00 00 00 27 00 00 00) // &...'... .data cil I_00002AE8 = int8[24] -.data cil I_000035A0 = bytearray ( +.data cil I_000032E0 = bytearray ( + 00 01 02 FF) +.data cil I_000032E4 = int8[4] +.data cil I_000035C8 = bytearray ( 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.opt.il index 9377b331c..093974f45 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.opt.il @@ -2733,6 +2733,20 @@ IL_0018: ret } // end of method TestCases::Issue1250_Test1 + .method private hidebysig instance uint8[] + Issue1314() cil managed + { + // Code size 18 (0x12) + .maxstack 8 + IL_0000: ldc.i4.4 + IL_0001: newarr [mscorlib]System.Byte + IL_0006: dup + IL_0007: ldtoken field int32 ''::'$$method0x6000040-1' + IL_000c: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, + valuetype [mscorlib]System.RuntimeFieldHandle) + IL_0011: ret + } // end of method TestCases::Issue1314 + .method private hidebysig instance void Issue1251_Test(class [mscorlib]System.Collections.Generic.List`1 list, class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests.TestCases/OtherItem otherItem) cil managed @@ -3938,7 +3952,7 @@ IL_07df: newobj instance void int32[0...,0...]::.ctor(int32, int32) IL_07e4: dup - IL_07e5: ldtoken field valuetype ''/'__StaticArrayInitTypeSize=36' ''::'$$method0x600008e-1' + IL_07e5: ldtoken field valuetype ''/'__StaticArrayInitTypeSize=36' ''::'$$method0x600008f-1' IL_07ea: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle) IL_07ef: stsfld int32[0...,0...] ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests.TestCases::Issue1336_rg2 @@ -4042,7 +4056,8 @@ .field static assembly valuetype ''/'__StaticArrayInitTypeSize=64' '$$method0x600001e-4' at I_00002938 .field static assembly valuetype ''/'__StaticArrayInitTypeSize=72' '$$method0x600001f-1' at I_000029E8 .field static assembly valuetype ''/'__StaticArrayInitTypeSize=72' '$$method0x600001f-2' at I_00002A30 - .field static assembly valuetype ''/'__StaticArrayInitTypeSize=36' '$$method0x600008e-1' at I_00003450 + .field static assembly int32 '$$method0x6000040-1' at I_000031D0 + .field static assembly valuetype ''/'__StaticArrayInitTypeSize=36' '$$method0x600008f-1' at I_00003470 } // end of class '' @@ -4149,7 +4164,10 @@ 22 00 00 00 23 00 00 00 24 00 00 00 25 00 00 00 // "...#...$...%... 26 00 00 00 27 00 00 00) // &...'... .data cil I_00002A78 = int8[8] -.data cil I_00003450 = bytearray ( +.data cil I_000031D0 = bytearray ( + 00 01 02 FF) +.data cil I_000031D4 = int8[12] +.data cil I_00003470 = bytearray ( 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.opt.roslyn.il index 2d3eb9af4..324e68874 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.opt.roslyn.il @@ -2684,6 +2684,20 @@ IL_0016: ret } // end of method TestCases::Issue1250_Test1 + .method private hidebysig instance uint8[] + Issue1314() cil managed + { + // Code size 18 (0x12) + .maxstack 8 + IL_0000: ldc.i4.4 + IL_0001: newarr [mscorlib]System.Byte + IL_0006: dup + IL_0007: ldtoken field int32 ''::C62C27924F4C967F5EDDB1850C091D54C7A2AB58 + IL_000c: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, + valuetype [mscorlib]System.RuntimeFieldHandle) + IL_0011: ret + } // end of method TestCases::Issue1314 + .method private hidebysig instance void Issue1251_Test(class [mscorlib]System.Collections.Generic.List`1 list, class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests.TestCases/OtherItem otherItem) cil managed @@ -3996,66 +4010,67 @@ .size 256 } // end of class '__StaticArrayInitTypeSize=256' - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=72' '1535117EC92E41D4A6B7CA00F965357B05B5DC35' at I_00006B94 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=10' '20E3FF489634E18F3F7EB292AD504DBAE9519293' at I_00006BDC - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=72' '39E94835525CF7B71CD4595742EF462642FBF1B2' at I_00006BEC - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=10' '56D9EEC8EF899644C40B9BE9D886DF2367A5D078' at I_00006C34 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=12' '735E5A21849E86F68D220F06163E8C5C6376B9C9' at I_00006C44 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=64' '7C39B7B06DD624A17F875AB8E9651554BE6E74D2' at I_00006C54 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' '8D903ECAD8D9D75B3183B23AF79F6D2E607369E3' at I_00006C94 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=80' '9B1F6E56D755443CC39C1969CE38FD41FD4EF4B7' at I_00006CBC - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=256' A1EA7DC3FE43B3A54F5B729A92B92AF54181A3EB at I_00006D0C - .field static assembly initonly int64 A6296CAC471BE2954899600137940479D8073C7C at I_00006E0C - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=36' B62E59D20E3D69F06A6D9BD5E3C518FF7093EDAB at I_00006E14 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' B9583930B842DBCEF0D7B8E57D4D3F1E8055C39E at I_00006E3C - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=24' C4E70AB31EF6C8908F896CAD1C6BC75F7FA65E27 at I_00006E64 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=48' DC7043B0114737ACE19A23DD755893795FD48A23 at I_00006E7C - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=64' DCF557B883E6FE0AEC05B7F0290F0EF47D0AC2E3 at I_00006EAC - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' E0D2592373A0C161E56E266306CD8405CD719D19 at I_00006EEC - .field static assembly initonly int64 EB0715DBB235F3F696F2C404F5839C6650640898 at I_00006F14 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' F514FF55B79BCAA2CEC9B56C062D976E45F89AB7 at I_00006F1C - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=24' FBCB49C1A244C1B5781AA1DB02C5A11F68908526 at I_00006F44 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=72' '1535117EC92E41D4A6B7CA00F965357B05B5DC35' at I_00006BF4 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=10' '20E3FF489634E18F3F7EB292AD504DBAE9519293' at I_00006C3C + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=72' '39E94835525CF7B71CD4595742EF462642FBF1B2' at I_00006C4C + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=10' '56D9EEC8EF899644C40B9BE9D886DF2367A5D078' at I_00006C94 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=12' '735E5A21849E86F68D220F06163E8C5C6376B9C9' at I_00006CA4 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=64' '7C39B7B06DD624A17F875AB8E9651554BE6E74D2' at I_00006CB4 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' '8D903ECAD8D9D75B3183B23AF79F6D2E607369E3' at I_00006CF4 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=80' '9B1F6E56D755443CC39C1969CE38FD41FD4EF4B7' at I_00006D1C + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=256' A1EA7DC3FE43B3A54F5B729A92B92AF54181A3EB at I_00006D6C + .field static assembly initonly int64 A6296CAC471BE2954899600137940479D8073C7C at I_00006E6C + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=36' B62E59D20E3D69F06A6D9BD5E3C518FF7093EDAB at I_00006E74 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' B9583930B842DBCEF0D7B8E57D4D3F1E8055C39E at I_00006E9C + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=24' C4E70AB31EF6C8908F896CAD1C6BC75F7FA65E27 at I_00006EC4 + .field static assembly initonly int32 C62C27924F4C967F5EDDB1850C091D54C7A2AB58 at I_00006EDC + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=48' DC7043B0114737ACE19A23DD755893795FD48A23 at I_00006EE4 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=64' DCF557B883E6FE0AEC05B7F0290F0EF47D0AC2E3 at I_00006F14 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' E0D2592373A0C161E56E266306CD8405CD719D19 at I_00006F54 + .field static assembly initonly int64 EB0715DBB235F3F696F2C404F5839C6650640898 at I_00006F7C + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' F514FF55B79BCAA2CEC9B56C062D976E45F89AB7 at I_00006F84 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=24' FBCB49C1A244C1B5781AA1DB02C5A11F68908526 at I_00006FAC } // end of class '' // ============================================================= -.data cil I_00006B94 = bytearray ( +.data cil I_00006BF4 = bytearray ( 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00 09 00 00 00 0B 00 00 00 0C 00 00 00 0D 00 00 00 0E 00 00 00 0F 00 00 00 10 00 00 00 11 00 00 00 12 00 00 00 13 00 00 00) -.data cil I_00006BDC = bytearray ( +.data cil I_00006C3C = bytearray ( 01 02 03 04 05 06 07 08 FE FF) -.data cil I_00006BE6 = int8[2] -.data cil I_00006BEC = bytearray ( +.data cil I_00006C46 = int8[2] +.data cil I_00006C4C = bytearray ( 15 00 00 00 16 00 00 00 17 00 00 00 18 00 00 00 19 00 00 00 1A 00 00 00 1B 00 00 00 1C 00 00 00 1D 00 00 00 1F 00 00 00 20 00 00 00 21 00 00 00 // ........ ...!... 22 00 00 00 23 00 00 00 24 00 00 00 25 00 00 00 // "...#...$...%... 26 00 00 00 27 00 00 00) // &...'... -.data cil I_00006C34 = bytearray ( +.data cil I_00006C94 = bytearray ( 00 80 FF FF 00 00 01 00 FF 7F) -.data cil I_00006C3E = int8[2] -.data cil I_00006C44 = bytearray ( +.data cil I_00006C9E = int8[2] +.data cil I_00006CA4 = bytearray ( 00 00 01 00 FF 7F 00 80 FE FF FF FF) -.data cil I_00006C54 = bytearray ( +.data cil I_00006CB4 = bytearray ( 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00) -.data cil I_00006C94 = bytearray ( +.data cil I_00006CF4 = bytearray ( 01 00 0C BB 7D 6E 9C BA FF FF FF FF FF FF FF FF // ....}n.......... 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 FF FF F3 44 82 91 63 45) // ...D..cE -.data cil I_00006CBC = bytearray ( +.data cil I_00006D1C = bytearray ( 01 00 00 00 00 00 00 00 00 94 35 77 00 00 00 00 // ..........5w.... 00 5E D0 B2 00 00 00 00 04 00 00 00 00 00 00 00 // .^.............. 05 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00 07 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 FF FF F3 44 82 91 63 45 FF FF E7 89 04 23 C7 8A) // ...D..cE.....#.. -.data cil I_00006D0C = bytearray ( +.data cil I_00006D6C = bytearray ( 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 @@ -4072,39 +4087,41 @@ 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00) -.data cil I_00006E0C = bytearray ( +.data cil I_00006E6C = bytearray ( 80 81 00 01 02 03 04 7F) -.data cil I_00006E14 = bytearray ( +.data cil I_00006E74 = bytearray ( 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00) -.data cil I_00006E3C = bytearray ( +.data cil I_00006E9C = bytearray ( 01 00 00 00 00 94 35 77 00 5E D0 B2 04 00 00 00 // ......5w.^...... 05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00 09 00 00 00 0A 00 00 00) -.data cil I_00006E64 = bytearray ( +.data cil I_00006EC4 = bytearray ( 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00) -.data cil I_00006E7C = bytearray ( +.data cil I_00006EDC = bytearray ( + 00 01 02 FF) +.data cil I_00006EE4 = bytearray ( 00 00 00 00 00 00 F8 BF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F8 3F 00 00 00 00 00 00 F0 FF // .......?........ 00 00 00 00 00 00 F0 7F 00 00 00 00 00 00 F8 FF) -.data cil I_00006EAC = bytearray ( +.data cil I_00006F14 = bytearray ( 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00) -.data cil I_00006EEC = bytearray ( +.data cil I_00006F54 = bytearray ( 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00 09 00 00 00 0A 00 00 00) -.data cil I_00006F14 = bytearray ( +.data cil I_00006F7C = bytearray ( 01 00 01 00 00 00 01 01) -.data cil I_00006F1C = bytearray ( +.data cil I_00006F84 = bytearray ( 01 00 00 00 FE FF FF FF 00 94 35 77 04 00 00 00 // ..........5w.... 05 00 00 00 FA FF FF FF 07 00 00 00 08 00 00 00 09 00 00 00 0A 00 00 00) -.data cil I_00006F44 = bytearray ( +.data cil I_00006FAC = bytearray ( 00 00 C0 BF 00 00 00 00 00 00 C0 3F 00 00 80 FF // ...........?.... 00 00 80 7F 00 00 C0 FF) // *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.roslyn.il index 0ee576f14..f38cf5265 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.roslyn.il @@ -3015,6 +3015,26 @@ IL_0018: ret } // end of method TestCases::Issue1250_Test1 + .method private hidebysig instance uint8[] + Issue1314() cil managed + { + // Code size 23 (0x17) + .maxstack 3 + .locals init (uint8[] V_0) + IL_0000: nop + IL_0001: ldc.i4.4 + IL_0002: newarr [mscorlib]System.Byte + IL_0007: dup + IL_0008: ldtoken field int32 ''::C62C27924F4C967F5EDDB1850C091D54C7A2AB58 + IL_000d: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, + valuetype [mscorlib]System.RuntimeFieldHandle) + IL_0012: stloc.0 + IL_0013: br.s IL_0015 + + IL_0015: ldloc.0 + IL_0016: ret + } // end of method TestCases::Issue1314 + .method private hidebysig instance void Issue1251_Test(class [mscorlib]System.Collections.Generic.List`1 list, class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests.TestCases/OtherItem otherItem) cil managed @@ -4421,67 +4441,68 @@ .size 256 } // end of class '__StaticArrayInitTypeSize=256' - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=72' '1535117EC92E41D4A6B7CA00F965357B05B5DC35' at I_00006F58 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=10' '20E3FF489634E18F3F7EB292AD504DBAE9519293' at I_00006FA0 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=72' '39E94835525CF7B71CD4595742EF462642FBF1B2' at I_00006FB0 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=10' '56D9EEC8EF899644C40B9BE9D886DF2367A5D078' at I_00006FF8 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=12' '735E5A21849E86F68D220F06163E8C5C6376B9C9' at I_00007008 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=64' '7C39B7B06DD624A17F875AB8E9651554BE6E74D2' at I_00007018 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' '8D903ECAD8D9D75B3183B23AF79F6D2E607369E3' at I_00007058 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=80' '9B1F6E56D755443CC39C1969CE38FD41FD4EF4B7' at I_00007080 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=256' A1EA7DC3FE43B3A54F5B729A92B92AF54181A3EB at I_000070D0 - .field static assembly initonly int64 A6296CAC471BE2954899600137940479D8073C7C at I_000071D0 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=36' B62E59D20E3D69F06A6D9BD5E3C518FF7093EDAB at I_000071D8 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' B9583930B842DBCEF0D7B8E57D4D3F1E8055C39E at I_00007200 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=24' C4E70AB31EF6C8908F896CAD1C6BC75F7FA65E27 at I_00007228 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=48' DC7043B0114737ACE19A23DD755893795FD48A23 at I_00007240 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=64' DCF557B883E6FE0AEC05B7F0290F0EF47D0AC2E3 at I_00007270 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' E0D2592373A0C161E56E266306CD8405CD719D19 at I_000072B0 - .field static assembly initonly int64 EB0715DBB235F3F696F2C404F5839C6650640898 at I_000072D8 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' F514FF55B79BCAA2CEC9B56C062D976E45F89AB7 at I_000072E0 - .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=24' FBCB49C1A244C1B5781AA1DB02C5A11F68908526 at I_00007308 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=72' '1535117EC92E41D4A6B7CA00F965357B05B5DC35' at I_00006FD8 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=10' '20E3FF489634E18F3F7EB292AD504DBAE9519293' at I_00007020 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=72' '39E94835525CF7B71CD4595742EF462642FBF1B2' at I_00007030 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=10' '56D9EEC8EF899644C40B9BE9D886DF2367A5D078' at I_00007078 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=12' '735E5A21849E86F68D220F06163E8C5C6376B9C9' at I_00007088 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=64' '7C39B7B06DD624A17F875AB8E9651554BE6E74D2' at I_00007098 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' '8D903ECAD8D9D75B3183B23AF79F6D2E607369E3' at I_000070D8 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=80' '9B1F6E56D755443CC39C1969CE38FD41FD4EF4B7' at I_00007100 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=256' A1EA7DC3FE43B3A54F5B729A92B92AF54181A3EB at I_00007150 + .field static assembly initonly int64 A6296CAC471BE2954899600137940479D8073C7C at I_00007250 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=36' B62E59D20E3D69F06A6D9BD5E3C518FF7093EDAB at I_00007258 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' B9583930B842DBCEF0D7B8E57D4D3F1E8055C39E at I_00007280 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=24' C4E70AB31EF6C8908F896CAD1C6BC75F7FA65E27 at I_000072A8 + .field static assembly initonly int32 C62C27924F4C967F5EDDB1850C091D54C7A2AB58 at I_000072C0 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=48' DC7043B0114737ACE19A23DD755893795FD48A23 at I_000072C8 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=64' DCF557B883E6FE0AEC05B7F0290F0EF47D0AC2E3 at I_000072F8 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' E0D2592373A0C161E56E266306CD8405CD719D19 at I_00007338 + .field static assembly initonly int64 EB0715DBB235F3F696F2C404F5839C6650640898 at I_00007360 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=40' F514FF55B79BCAA2CEC9B56C062D976E45F89AB7 at I_00007368 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=24' FBCB49C1A244C1B5781AA1DB02C5A11F68908526 at I_00007390 } // end of class '' // ============================================================= -.data cil I_00006F58 = bytearray ( +.data cil I_00006FD8 = bytearray ( 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00 09 00 00 00 0B 00 00 00 0C 00 00 00 0D 00 00 00 0E 00 00 00 0F 00 00 00 10 00 00 00 11 00 00 00 12 00 00 00 13 00 00 00) -.data cil I_00006FA0 = bytearray ( +.data cil I_00007020 = bytearray ( 01 02 03 04 05 06 07 08 FE FF) -.data cil I_00006FAA = int8[6] -.data cil I_00006FB0 = bytearray ( +.data cil I_0000702A = int8[6] +.data cil I_00007030 = bytearray ( 15 00 00 00 16 00 00 00 17 00 00 00 18 00 00 00 19 00 00 00 1A 00 00 00 1B 00 00 00 1C 00 00 00 1D 00 00 00 1F 00 00 00 20 00 00 00 21 00 00 00 // ........ ...!... 22 00 00 00 23 00 00 00 24 00 00 00 25 00 00 00 // "...#...$...%... 26 00 00 00 27 00 00 00) // &...'... -.data cil I_00006FF8 = bytearray ( +.data cil I_00007078 = bytearray ( 00 80 FF FF 00 00 01 00 FF 7F) -.data cil I_00007002 = int8[6] -.data cil I_00007008 = bytearray ( +.data cil I_00007082 = int8[6] +.data cil I_00007088 = bytearray ( 00 00 01 00 FF 7F 00 80 FE FF FF FF) -.data cil I_00007014 = int8[4] -.data cil I_00007018 = bytearray ( +.data cil I_00007094 = int8[4] +.data cil I_00007098 = bytearray ( 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00) -.data cil I_00007058 = bytearray ( +.data cil I_000070D8 = bytearray ( 01 00 0C BB 7D 6E 9C BA FF FF FF FF FF FF FF FF // ....}n.......... 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 FF FF F3 44 82 91 63 45) // ...D..cE -.data cil I_00007080 = bytearray ( +.data cil I_00007100 = bytearray ( 01 00 00 00 00 00 00 00 00 94 35 77 00 00 00 00 // ..........5w.... 00 5E D0 B2 00 00 00 00 04 00 00 00 00 00 00 00 // .^.............. 05 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00 07 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 FF FF F3 44 82 91 63 45 FF FF E7 89 04 23 C7 8A) // ...D..cE.....#.. -.data cil I_000070D0 = bytearray ( +.data cil I_00007150 = bytearray ( 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 @@ -4498,40 +4519,43 @@ 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00) -.data cil I_000071D0 = bytearray ( +.data cil I_00007250 = bytearray ( 80 81 00 01 02 03 04 7F) -.data cil I_000071D8 = bytearray ( +.data cil I_00007258 = bytearray ( 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00) -.data cil I_000071FC = int8[4] -.data cil I_00007200 = bytearray ( +.data cil I_0000727C = int8[4] +.data cil I_00007280 = bytearray ( 01 00 00 00 00 94 35 77 00 5E D0 B2 04 00 00 00 // ......5w.^...... 05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00 09 00 00 00 0A 00 00 00) -.data cil I_00007228 = bytearray ( +.data cil I_000072A8 = bytearray ( 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00) -.data cil I_00007240 = bytearray ( +.data cil I_000072C0 = bytearray ( + 00 01 02 FF) +.data cil I_000072C4 = int8[4] +.data cil I_000072C8 = bytearray ( 00 00 00 00 00 00 F8 BF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F8 3F 00 00 00 00 00 00 F0 FF // .......?........ 00 00 00 00 00 00 F0 7F 00 00 00 00 00 00 F8 FF) -.data cil I_00007270 = bytearray ( +.data cil I_000072F8 = bytearray ( 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00) -.data cil I_000072B0 = bytearray ( +.data cil I_00007338 = bytearray ( 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00 09 00 00 00 0A 00 00 00) -.data cil I_000072D8 = bytearray ( +.data cil I_00007360 = bytearray ( 01 00 01 00 00 00 01 01) -.data cil I_000072E0 = bytearray ( +.data cil I_00007368 = bytearray ( 01 00 00 00 FE FF FF FF 00 94 35 77 04 00 00 00 // ..........5w.... 05 00 00 00 FA FF FF FF 07 00 00 00 08 00 00 00 09 00 00 00 0A 00 00 00) -.data cil I_00007308 = bytearray ( +.data cil I_00007390 = bytearray ( 00 00 C0 BF 00 00 00 00 00 00 C0 3F 00 00 80 FF // ...........?.... 00 00 80 7F 00 00 C0 FF) // *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 58a94ba11..f2aa95a3b 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -2273,7 +2273,7 @@ namespace ICSharpCode.Decompiler.CSharp TranslatedExpression val; var old = astBuilder.UseSpecialConstants; try { - astBuilder.UseSpecialConstants = !type.IsCSharpPrimitiveIntegerType(); + astBuilder.UseSpecialConstants = !type.IsCSharpPrimitiveIntegerType() && !type.IsKnownType(KnownTypeCode.Decimal); val = Translate(value, typeHint: type).ConvertTo(type, this, allowImplicitConversion: true); } finally { astBuilder.UseSpecialConstants = old; From f8e2f5ee17e82aa125c957d11b84fc3ea134b732 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 4 Jan 2019 20:07:45 +0100 Subject: [PATCH 09/12] Try to fix unit tests on build server. --- .../CSharp/Syntax/TypeSystemAstBuilder.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs index fc0ead8d1..a75c649a6 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs @@ -1033,16 +1033,17 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax if (d != 1) { expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Divide, MakeConstant(type, d)); } - +#pragma warning disable IDE0004 if (isDouble) { - double approxValue = n / (double)d * (memberName == "PI" ? Math.PI : Math.E); + double approxValue = (double)n / (double)d * (memberName == "PI" ? Math.PI : Math.E); if (approxValue == (double)literalValue) return expr; } else { - float approxValue = n / (float)d * (memberName == "PI" ? MathF_PI : MathF_E); + float approxValue = (float)n / (float)d * (memberName == "PI" ? MathF_PI : MathF_E); if (approxValue == (float)literalValue) return expr; } +#pragma warning restore IDE0004 expr = fieldReference.Detach(); expr = new BinaryOperatorExpression(MakeConstant(type, n), BinaryOperatorType.Divide, expr); @@ -1050,17 +1051,17 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax if (d != 1) { expr = new BinaryOperatorExpression(MakeConstant(type, d), BinaryOperatorType.Multiply, expr); } - +#pragma warning disable IDE0004 if (isDouble) { - double approxValue = n / (d * (memberName == "PI" ? Math.PI : Math.E)); + double approxValue = (double)n / ((double)d * (memberName == "PI" ? Math.PI : Math.E)); if (approxValue == (double)literalValue) return expr; } else { - float approxValue = n / (d * (memberName == "PI" ? MathF_PI : MathF_E)); + float approxValue = (float)n / ((float)d * (memberName == "PI" ? MathF_PI : MathF_E)); if (approxValue == (float)literalValue) return expr; } - +#pragma warning restore IDE0004 return null; } From fa4c239d6703d17b395364b8225120f48dfdd976 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 4 Jan 2019 20:53:30 +0100 Subject: [PATCH 10/12] Fix equality checks in ExtractExpression. --- .../CSharp/Syntax/TypeSystemAstBuilder.cs | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs index a75c649a6..4b41ded1a 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs @@ -1020,48 +1020,60 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { Expression fieldReference = MakeFieldReference(); + // Math.PI or Math.E or (float)Math.PI or (float)Math.E or MathF.PI or MathF.E Expression expr = fieldReference; if (n != 1) { if (n == -1) { + // -field expr = new UnaryOperatorExpression(UnaryOperatorType.Minus, expr); } else { + // field * n expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Multiply, MakeConstant(type, n)); } } if (d != 1) { + // field * n / d or -field / d or field / d expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Divide, MakeConstant(type, d)); } -#pragma warning disable IDE0004 + if (isDouble) { - double approxValue = (double)n / (double)d * (memberName == "PI" ? Math.PI : Math.E); + double field = memberName == "PI" ? Math.PI : Math.E; + double approxValue = field * n / d; if (approxValue == (double)literalValue) return expr; } else { - float approxValue = (float)n / (float)d * (memberName == "PI" ? MathF_PI : MathF_E); + float field = memberName == "PI" ? MathF_PI : MathF_E; + float approxValue = field * n / d; if (approxValue == (float)literalValue) return expr; } -#pragma warning restore IDE0004 + // Math.PI or Math.E or (float)Math.PI or (float)Math.E or MathF.PI or MathF.E expr = fieldReference.Detach(); - expr = new BinaryOperatorExpression(MakeConstant(type, n), BinaryOperatorType.Divide, expr); - if (d != 1) { + if (d == 1) { + // n / field + expr = new BinaryOperatorExpression(MakeConstant(type, n), BinaryOperatorType.Divide, expr); + } else { + // n / (d * field) expr = new BinaryOperatorExpression(MakeConstant(type, d), BinaryOperatorType.Multiply, expr); + expr = new BinaryOperatorExpression(MakeConstant(type, n), BinaryOperatorType.Divide, expr); } -#pragma warning disable IDE0004 + if (isDouble) { - double approxValue = (double)n / ((double)d * (memberName == "PI" ? Math.PI : Math.E)); + double field = memberName == "PI" ? Math.PI : Math.E; + double approxValue = (double)n / ((double)d * field); if (approxValue == (double)literalValue) return expr; } else { - float approxValue = (float)n / ((float)d * (memberName == "PI" ? MathF_PI : MathF_E)); + float field = memberName == "PI" ? MathF_PI : MathF_E; + float approxValue = (float)n / ((float)d * field); if (approxValue == (float)literalValue) return expr; } -#pragma warning restore IDE0004 + return null; } From f0626009c1a5dc196d684a16b63bad81dd7ae6ce Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 4 Jan 2019 21:28:19 +0100 Subject: [PATCH 11/12] Prefer expressions without pi / e. --- .../CSharp/Syntax/TypeSystemAstBuilder.cs | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs index 4b41ded1a..e4527dff7 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs @@ -958,19 +958,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax expr = new PrimitiveExpression(constantValue); } } - - if (expr == null && UseSpecialConstants) { - IType mathType; - if (isDouble) - mathType = compilation.FindType(typeof(Math)); - else - mathType = compilation.FindType(new TopLevelTypeName("System", "MathF")).GetDefinition() - ?? compilation.FindType(typeof(Math)); - expr = TryExtractExpression(mathType, type, constantValue, "PI", isDouble) - ?? TryExtractExpression(mathType, type, constantValue, "E", isDouble); - } - if (expr == null) { (long num, long den) = isDouble ? FractionApprox((double)constantValue, MAX_DENOMINATOR) @@ -984,6 +972,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } } + if (expr == null && UseSpecialConstants) { + IType mathType; + if (isDouble) + mathType = compilation.FindType(typeof(Math)); + else + mathType = compilation.FindType(new TopLevelTypeName("System", "MathF")).GetDefinition() + ?? compilation.FindType(typeof(Math)); + + expr = TryExtractExpression(mathType, type, constantValue, "PI", isDouble) + ?? TryExtractExpression(mathType, type, constantValue, "E", isDouble); + } + if (expr == null) expr = new PrimitiveExpression(constantValue); From 2413eef1edeef3f6d8390748b868e6a8c0c8a3f1 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 4 Jan 2019 22:31:24 +0100 Subject: [PATCH 12/12] Do not use a fractional representation, if it has less than 6 significant digits. --- .../CSharp/Syntax/TypeSystemAstBuilder.cs | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs index e4527dff7..49d2db93a 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs @@ -949,30 +949,24 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax ICompilation compilation = type.GetDefinition().Compilation; Expression expr = null; + string str; if (isDouble) { if (Math.Floor((double)constantValue) == (double)constantValue) { expr = new PrimitiveExpression(constantValue); } + + str = ((double)constantValue).ToString("r"); } else { if (Math.Floor((float)constantValue) == (float)constantValue) { expr = new PrimitiveExpression(constantValue); } - } - if (expr == null) { - (long num, long den) = isDouble - ? FractionApprox((double)constantValue, MAX_DENOMINATOR) - : FractionApprox((float)constantValue, MAX_DENOMINATOR); - - if (IsValidFraction(num, den) && IsEqual(num, den, constantValue, isDouble) && Math.Abs(num) != 1 && Math.Abs(den) != 1) { - var left = MakeConstant(type, num); - var right = MakeConstant(type, den); - return new BinaryOperatorExpression(left, BinaryOperatorType.Divide, right).WithoutILInstruction() - .WithRR(new ConstantResolveResult(type, constantValue)); - } + str = ((float)constantValue).ToString("r"); } - if (expr == null && UseSpecialConstants) { + bool useFraction = (str.Length - (str.StartsWith("-", StringComparison.OrdinalIgnoreCase) ? 2 : 1) > 5); + + if (useFraction && expr == null && UseSpecialConstants) { IType mathType; if (isDouble) mathType = compilation.FindType(typeof(Math)); @@ -984,6 +978,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax ?? TryExtractExpression(mathType, type, constantValue, "E", isDouble); } + if (useFraction && expr == null) { + (long num, long den) = isDouble + ? FractionApprox((double)constantValue, MAX_DENOMINATOR) + : FractionApprox((float)constantValue, MAX_DENOMINATOR); + + if (IsValidFraction(num, den) && IsEqual(num, den, constantValue, isDouble) && Math.Abs(num) != 1 && Math.Abs(den) != 1) { + var left = MakeConstant(type, num); + var right = MakeConstant(type, den); + return new BinaryOperatorExpression(left, BinaryOperatorType.Divide, right).WithoutILInstruction() + .WithRR(new ConstantResolveResult(type, constantValue)); + } + } + if (expr == null) expr = new PrimitiveExpression(constantValue);