CLI calling conventions [IN ECMA-335]
The CLI function call protocol accurately describes the managedCodeHow does the caller of the function caller and callee of the called party use the stack to pass the call parameters. Because CLI uses a simple virtual machine model that is fully stack-based, all real parameters in managed function calls are passed through the CLI stack. The following describes how to construct a stack frame before calling the call command:
1. |
This references the pressure stack, if it is a method call |
2. |
Function call arguments are pushed from left to right to the stack. |
3. |
If the last real parameter is a variable quantity parameter, you only need to reference its array into the stack. |
4. |
Call/calli/callvirt |
JIT calling conventions of x86[In rotor 1.x]
The JIT function call protocol is mainly applicable to the parameter transfer process between local code (jitted native code) generated by JIT and between it and the internal functions of the execution engine. In fact, there is no beautiful and simple CLI virtual stack in the real local code execution process. During real-time compilation, JIT compiler needs to convert the abstract CLI function call Protocol into a specific JIT function call Method for x86 local code. Different JIT call protocols are used in rotor 1.x and rotor 2.0, which are more concise and efficient than the former. Rotor 1. the JIT call agreement in X is not only confusing, but also confusing. Its designer David Stutz mentioned this many times in a public speech. He pointed out: this confusing parameter transfer method is mainly used to avoid and reduce modifications to the existing unmanaged code section of the execution engine (such as stub/JIT prestub) as much as possible, seems to be a bit lazy...
The JIT function call protocol in rotor 1.x is mainly divided into two types. The steps and examples are as follows:
A. When no variable quantity parameter exists: |
1. |
Function call arguments are pushed from left to right to the stack. |
2. |
Reordering) |
|
2.1 |
Select the two leftmost real parameters in the call parameter list that can be placed in the 4-byte register (for example, a variable of the byte/INT type) |
|
2.2 |
Store the values in the ECX and EDX registers respectively. |
|
2.3 |
Delete the selected real parameters from the stack and compress the stack. |
|
2.4 |
EdX is added to the stack, and ECx is then added to the stack. |
3. |
The function returns the buffer pointer (return buffer PTR) to the stack. If necessary |
B. When there are variable quantity parameters: |
1. |
Function call arguments are pushed from left to right to the stack. |
2. |
Reordering is not required for parameters in the stack. |
3. |
Apply a variable number of real parameters to the stack. |
4. |
Stack a metadata type token of a variable number of real parameters |
5. |
Return buffer PTR to stack, if necessary |
6. |
This pointer goes into the stack, if it is an object method call |
JIT calling conventions of x86[In rotor 2.0]
Rotor 2.0 sorts out the JIT function call protocol again, and its parameter passing method is similar to the revision of _ fastcall, registers and floating-point stacks are also used to return integer and floating-point data. The use of relatively clean procedures and registers further optimizes the entire JIT function call process. The basic process and two instances are as follows:
1. |
This pointer goes into the stack (if it is a method call), and then return buffer PTR to the stack (if needed) |
2. |
All non-mutable arguments are pushed to the stack in the order of left to right. |
3. |
If a variable number of parameters exist, all the variable arguments go from left to right into the stack, and then the type token of the variable arguments is pushed to the stack. |
4. |
Select the first two parameters that can be placed in the 4-byte register from the above pressure stack order, store them in ECx and EDX, delete them from the stack, and compress the stack. |
5. |
If the returned value is a floating point number, the returned value is placed at the top of the FP stack and returned (not the top of the Call Stack !) |
6. |
If the returned value is a 32-bit integer (or a 32-bit integer type that can be expanded ), |
7. |
If the returned value is a 64-bit integer, it is returned through the eax: edX register. |
8. |
All other return types are returned through return buffer PTR. |