[Tailcall] Bring coreclr tests for tail calls to Mono source tree (#7204)
[mono-project.git] / mono / tests / tailcall / readme.txt
blob3a9fc49eb18d9d1615795820adaaf7889f8c5d6e
1 --------------------------------------------------------------------
3 February 21 2018
5 Initial tests are imported from coreclr roughly via:
7 cd /dev2
8 git clone https://github.com/dotnet/coreclr # 66f840939e81a6e240a01edfea61976363bc51d6
9 cd /dev2/mono/mono/tests
10 mkdir -p tailcall/coreclr
11 cd tailcall/coreclr
12 cp -prv /dev2/coreclr/tests/src/* .
13 find . | grep proj$ | xargs rm
14 find . | grep -vi tail | xargs rm
15 a few times:
16 find . | xargs rmdir
18 and that this point optional:
19         for a in `find . -type f`; do if  [ ! -e $(basename $a) ] ; then mv $a $(basename $a)  ; fi done
20         a few:
21         find . | grep -vi tail | xargs rmdir
24         and then optionally pick up stragglers.
26 --------------------------------------------------------------------
28 February 21 2018
29 There a few buckets of known behavior in mono and .NET regarding tail calls.
31 Intuition is only partly correct.
33 Intuitively, a tail call can be performed when the outgoing parameters
34 match incoming parameters in "location" (specific register or stack location)
35 and count. Some wiggle room could be afforded for integer types -- signedess
36 would not matter, nor exact size, as long as fits in a regster.
38 Passing the address of a local would seem disallowed, however might be allowed
39 within the red zone? This is mentioned in ECMA.
41 Managed-pointer-ness would be helpful to match up, but this requirement
42 depends flexible details -- as long as GC info is accurate and/or GC is not
43 allowed while a location changes, ok.
45 Exception handling would likely get in the way -- you can't have a handler in scope
46 if your frame has been torn down, as exception handling needs a way
47 to know your scope is live -- either via RIP or a thread local linked list.
48 As well, this is mentioned in ECMA.
50 Mono does not tailcall virtual calls.
51   No intuition assists me here.
52   FIXME: Specific test cases that demonstrate this.
54 Mono does not tailcall "something about generics, generic value types, generic context".
55   No intuition assists me here.
56   FIXME: Specific test cases that demonstrate this.
58 .NET goes very far out of its way to allow the outgoing and incoming signatures
59 to vary arbitrarily, including growing the parameter list unboundedly.
60 This is very surprising. There is a specification (FIXME) to do this for CoreCLR/Unix,
61 however CoreCLR/Unix presently does not do this.
63 --------------------------------------------------------------------
65 February 21 2018
67 The imported CoreCLR tailcall tests have a variety of good and bad aspects.
68  - Most are .il.
69  - Some are .cs.
70  - Some have explicit tail calls.
71  - Some have non demarked but easily optimized calls.
72  - Some can be run on Unix. Some cannot -- p/invoke to user32.dll.
73  - P/invoke is a useful portably interesting variation, even if user32.dll is not portable.
74  - Most can be built stand alone, but not all.
75  - When executed:
76     Some succeeded whether or not a tailcall optimization is done.
77     Some run forever.
78     Some run out of stack, at least in the absence of tailcall.
79  - Some use generics, some do not -- at least the first F# test (citation needed).
81 These variations make for usual simple run/don't-run, or succeed/fail partitioning of the tests
82 not trivial.
84 Due to the fact that many are not runnable, it becomes desirable to
85 use mono --compile-all switch, which will not run the code, just JIT it.
87 However this switch skips generics.
89 Therefore, we must either fix this switch, and/or develop new runnable portable tests,
90 that clearly indicate their success or failure, with an exit code.
92 It is important to consider the CoreCLR tests as just a starting point, and not the
93 desired end state of tailcall tests.
95 --------------------------------------------------------------------
97 February 21 2018
99 An approximate test plan should be:
100   generate a combinatorial series of tests with the following variables
102  - tailcall in try and outside of try
103         Inside try cannot be optimized.
104  - tailcall in except and outside of except
105         Inside except cannot be optimized?
106  - tailcall with exactly matching signatures
107         Exactly matching is easier. Non-matching varies in ease.
108  - tailcall with non matching signatures, but for which all parameters are in registers
109         Same registers is easy.
110  - tailcall with all parameters in registers and tailcall using stack for registers
111         All registers should be easy, no matter the precise signature.
112         Same stack should be easy.
113         Varying stack, bigger or smaller, is very difficult but not impossible.
114  - tailcall with managed pointers and non-managed pointers (integers)
115  - tailcall with integer and tailcall with float
116  - tailcall where parameters includes a passthrough ref parameter
117  - tailcall to same function and tailcall to other function
118    - Same function is particularly trivial and less interesting.
119  - Tailcall with:
120         generic reference types
121         non-generic reference types
122         generic value types
123         non-generic value types
124         reference types
125         non-reference typess -- integer, float, value
126         virtual and non-virtual
127         static and non-static
128         varargs and non-varargs (how to construct varargs?)
129         p/invoke and non-p/invoke
130         call to same assembly and call to outside assembly (ECMA discerns this)