From 63b03f90f3afdefd220f9b7fbb181b558070f5d8 Mon Sep 17 00:00:00 2001 From: kerams Date: Thu, 17 Jun 2021 16:04:00 +0200 Subject: [PATCH 1/3] Zero init values on demand despite SkipLocalsInit being set --- src/fsharp/IlxGen.fs | 2 +- .../EmittedIL/SkipLocalsInit.fs | 22 ++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 6cefacd50c3..2e24a1cf74b 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -4351,7 +4351,7 @@ and GenDefaultValue cenv cgbuf eenv (ty, m) = // "initobj" (Generated by EmitInitLocal) doesn't work on byref types // But ilzero(&ty) only gets generated in the built-in get-address function so // we can just rely on zeroinit of all IL locals. - if realloc then + if realloc || not eenv.initLocals then match ilTy with | ILType.Byref _ -> () | _ -> EmitInitLocal cgbuf ilTy locIdx diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/SkipLocalsInit.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/SkipLocalsInit.fs index cd484f2cfe7..493050ac3b3 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/SkipLocalsInit.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/SkipLocalsInit.fs @@ -129,5 +129,25 @@ type X () = .maxstack 6 .locals (int32 V_0) -"""] +""" ] + + [] + let ``Zero init performed to get defaults despite the attribute``() = + FSharp """ +module SkipLocalsInit + +[] +let z () = + let mutable a = Unchecked.defaultof + a + """ + |> compile + |> shouldSucceed + |> verifyIL [""" +.locals (valuetype [runtime]System.DateTime V_0) +IL_0000: ldloca.s V_0 +IL_0002: initobj [runtime]System.DateTime +IL_0008: ldloc.0 +IL_0009: ret + """] #endif \ No newline at end of file From a0eaab34a56f96aa455c724493cfb57cd0dad65a Mon Sep 17 00:00:00 2001 From: kerams Date: Mon, 6 Sep 2021 21:14:53 +0200 Subject: [PATCH 2/3] Add extra SkipLocalsInit test --- .../EmittedIL/SkipLocalsInit.fs | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/SkipLocalsInit.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/SkipLocalsInit.fs index f98b01e0c24..7ef15ecf7f8 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/SkipLocalsInit.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/SkipLocalsInit.fs @@ -135,11 +135,17 @@ type X () = let ``Zero init performed to get defaults despite the attribute``() = FSharp """ module SkipLocalsInit +open System [] let z () = let mutable a = Unchecked.defaultof a + +[] +let x f = + let a = if 1 / 1 = 1 then Nullable () else Nullable 5L + printfn "%A" (f a) """ |> compile |> shouldSucceed @@ -149,5 +155,33 @@ IL_0000: ldloca.s V_0 IL_0002: initobj [runtime]System.DateTime IL_0008: ldloc.0 IL_0009: ret - """] + """ + + """ +.locals (valuetype [runtime]System.Nullable`1 V_0, + valuetype [runtime]System.Nullable`1 V_1) +IL_0000: ldc.i4.1 +IL_0001: ldc.i4.1 +IL_0002: div +IL_0003: ldc.i4.1 +IL_0004: bne.un.s IL_0011 + +IL_0006: ldloca.s V_1 +IL_0008: initobj valuetype [runtime]System.Nullable`1 +IL_000e: ldloc.1 +IL_000f: br.s IL_0018 + +IL_0011: ldc.i4.5 +IL_0012: conv.i8 +IL_0013: newobj instance void valuetype [runtime]System.Nullable`1::.ctor(!0) +IL_0018: stloc.0 +IL_0019: ldstr "%A" +IL_001e: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [runtime]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,!!a>::.ctor(string) +IL_0023: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) +IL_0028: ldarg.0 +IL_0029: ldloc.0 +IL_002a: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,!!a>::Invoke(!0) +IL_002f: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) +IL_0034: pop +IL_0035: ret"""] #endif \ No newline at end of file From d03bf7206b222da4296eeeb0cfe18a10697583cc Mon Sep 17 00:00:00 2001 From: kerams Date: Mon, 6 Sep 2021 22:19:10 +0200 Subject: [PATCH 3/3] Fix test --- .../EmittedIL/SkipLocalsInit.fs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/SkipLocalsInit.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/SkipLocalsInit.fs index 7ef15ecf7f8..8b69fa73281 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/SkipLocalsInit.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/SkipLocalsInit.fs @@ -145,7 +145,7 @@ let z () = [] let x f = let a = if 1 / 1 = 1 then Nullable () else Nullable 5L - printfn "%A" (f a) + f a |> ignore """ |> compile |> shouldSucceed @@ -159,7 +159,8 @@ IL_0009: ret """ .locals (valuetype [runtime]System.Nullable`1 V_0, - valuetype [runtime]System.Nullable`1 V_1) + valuetype [runtime]System.Nullable`1 V_1, + !!a V_2) IL_0000: ldc.i4.1 IL_0001: ldc.i4.1 IL_0002: div @@ -175,13 +176,9 @@ IL_0011: ldc.i4.5 IL_0012: conv.i8 IL_0013: newobj instance void valuetype [runtime]System.Nullable`1::.ctor(!0) IL_0018: stloc.0 -IL_0019: ldstr "%A" -IL_001e: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [runtime]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,!!a>::.ctor(string) -IL_0023: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) -IL_0028: ldarg.0 -IL_0029: ldloc.0 -IL_002a: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,!!a>::Invoke(!0) -IL_002f: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) -IL_0034: pop -IL_0035: ret"""] +IL_0019: ldarg.0 +IL_001a: ldloc.0 +IL_001b: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,!!a>::Invoke(!0) +IL_0020: stloc.2 +IL_0021: ret"""] #endif \ No newline at end of file