fsharp/tests/FSharp.Compiler.ComponentTests/TailCalls.fs

238 строки
9.1 KiB
Forth

// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
namespace EmittedIL
open Xunit
open FSharp.Test.Compiler
module ``Tail Calls`` =
// Regression test for DevDiv:72571
let private compileWithTailCalls opts =
opts |> ignoreWarnings |> withOptions ["-g"; "--optimize-"; "--tailcalls+"] |> compile
[<Fact>]
let ``TailCall 01``() =
FSharp """
module TailCall01
let foo(x:int, y) = printfn "%d" x
let run() = let x = 0 in foo(x,5)
"""
|> compileWithTailCalls
|> shouldSucceed
|> verifyIL [
"""
.method public static void foo<a>(int32 x,
!!a y) cil managed
{
.maxstack 8
IL_0000: ldstr "%d"
IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,class [FSharp.Core]Microsoft.FSharp.Core.Unit>,class [runtime]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::.ctor(string)
IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,class [FSharp.Core]Microsoft.FSharp.Core.Unit>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<!!0,class [runtime]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit>)
IL_000f: ldarg.0
IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,class [FSharp.Core]Microsoft.FSharp.Core.Unit>::Invoke(!0)
IL_0015: pop
IL_0016: ret
}
"""
"""
.method public static void run() cil managed
{
.maxstack 4
.locals init (int32 V_0)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: ldc.i4.5
IL_0004: tail.
IL_0006: call void TailCall01::foo<int32>(int32,
!!0)
IL_000b: ret
}
"""]
[<Fact>]
let ``TailCall 02``() =
FSharp """
module TailCall02
let foo(x:int byref) = x
let run() = let mutable x = 0 in foo(&x)
"""
|> compileWithTailCalls
|> shouldSucceed
|> verifyIL [
"""
.method public static int32 foo(int32& x) cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldobj [runtime]System.Int32
IL_0006: ret
}
"""
"""
.method public static int32 run() cil managed
{
.maxstack 3
.locals init (int32 V_0)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldloca.s V_0
IL_0004: call int32 TailCall02::foo(int32&)
IL_0009: ret
}
"""
]
[<Fact>]
let ``TailCall 03``() =
FSharp """
module TailCall03
let foo (x:int byref) (y:int byref) z = printfn "%d" (x+y)
let run() = let mutable x = 0 in foo &x &x 5
"""
|> compileWithTailCalls
|> shouldSucceed
|> verifyIL [
"""
.method public static void foo<a>(int32& x,
int32& y,
!!a z) cil managed
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00
00 00 00 00 )
.maxstack 8
IL_0000: ldstr "%d"
IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,class [FSharp.Core]Microsoft.FSharp.Core.Unit>,class [runtime]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::.ctor(string)
IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,class [FSharp.Core]Microsoft.FSharp.Core.Unit>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<!!0,class [runtime]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit>)
IL_000f: ldarg.0
IL_0010: ldobj [runtime]System.Int32
IL_0015: ldarg.1
IL_0016: ldobj [runtime]System.Int32
IL_001b: add
IL_001c: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,class [FSharp.Core]Microsoft.FSharp.Core.Unit>::Invoke(!0)
IL_0021: pop
IL_0022: ret
}
"""
"""
.method public static void run() cil managed
{
.maxstack 5
.locals init (int32 V_0)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldloca.s V_0
IL_0004: ldloca.s V_0
IL_0006: ldc.i4.5
IL_0007: call void TailCall03::foo<int32>(int32&,
int32&,
!!0)
IL_000c: nop
IL_000d: ret
}
"""
]
[<Fact>]
let ``TailCall 04``() =
FSharp """
module TailCall04
let foo(x:int byref, y) = printfn "%d" x
let run() = let mutable x = 0 in foo(&x,5)
"""
|> compileWithTailCalls
|> shouldSucceed
|> verifyIL [
"""
.method public static void foo<a>(int32& x,
!!a y) cil managed
{
.maxstack 8
IL_0000: ldstr "%d"
IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,class [FSharp.Core]Microsoft.FSharp.Core.Unit>,class [runtime]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::.ctor(string)
IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,class [FSharp.Core]Microsoft.FSharp.Core.Unit>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<!!0,class [runtime]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit>)
IL_000f: ldarg.0
IL_0010: ldobj [runtime]System.Int32
IL_0015: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,class [FSharp.Core]Microsoft.FSharp.Core.Unit>::Invoke(!0)
IL_001a: pop
IL_001b: ret
}
"""
"""
.method public static void run() cil managed
{
.maxstack 4
.locals init (int32 V_0)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldloca.s V_0
IL_0004: ldc.i4.5
IL_0005: call void TailCall04::foo<int32>(int32&,
!!0)
IL_000a: nop
IL_000b: ret
"""
]
[<Fact>]
let ``TailCall 05``() =
FSharp """
module TailCall05
let foo(x:int byref, y:int byref, z) = printfn "%d" (x+y)
let run() = let mutable x = 0 in foo(&x,&x,5)
"""
|> compileWithTailCalls
|> shouldSucceed
|> verifyIL [
"""
.method public static void foo<a>(int32& x,
int32& y,
!!a z) cil managed
{
.maxstack 8
IL_0000: ldstr "%d"
IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,class [FSharp.Core]Microsoft.FSharp.Core.Unit>,class [runtime]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::.ctor(string)
IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,class [FSharp.Core]Microsoft.FSharp.Core.Unit>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<!!0,class [runtime]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit>)
IL_000f: ldarg.0
IL_0010: ldobj [runtime]System.Int32
IL_0015: ldarg.1
IL_0016: ldobj [runtime]System.Int32
IL_001b: add
IL_001c: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,class [FSharp.Core]Microsoft.FSharp.Core.Unit>::Invoke(!0)
IL_0021: pop
IL_0022: ret
}
"""
"""
.method public static void run() cil managed
{
.maxstack 5
.locals init (int32 V_0)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldloca.s V_0
IL_0004: ldloca.s V_0
IL_0006: ldc.i4.5
IL_0007: call void TailCall05::foo<int32>(int32&,
int32&,
!!0)
IL_000c: nop
IL_000d: ret
}
"""
]