Introduction
To call a method, push its arguments in order (for an instance method the object comes first, as argument 0) and then use one of the call instructions. The instruction pops as many values as the method’s signature has parameters (plus the object, if there is one) and, if the method returns something, pushes the result. The stack effect of a call therefore depends on a signature, which is why the opcode table records it as variable.
The operand is a token. A call to a method in the same assembly uses a MethodDef token; to a method in another assembly, a MemberRef (a name and a signature
under a TypeRef or TypeSpec); to a generic method with type arguments, a MethodSpec. A call to a vararg method names the extra arguments after a
sentinel in the signature of its MemberRef, so the signature at the call site tells how many extra values to pop.
Exceptions and verifiability, for the whole page. Any exception the called method throws passes through. The loader may also fail to find the method or type
(MissingMethodException, MissingFieldException, TypeLoadException) and a stack that is too deep ends in StackOverflowException. Verification
checks that the arguments on the stack match the signature.
Calls and returns
| Opcode | Instruction | Stack | What it does | Exceptions · verifiability |
|---|---|---|---|---|
28 token | call method | …, args → …, result | Calls the named method directly: no virtual lookup, so the method named is the method run, even if it is virtual. This is how a base-class method or a constructor is called, and how static methods are called. | The callee’s exceptions. It does not itself test this for null (callvirt does, which is why C# uses it for ordinary instance calls). Verifiable. |
6F token | callvirt method | …, object, args → …, result | Calls the named instance method on the object, choosing the override that fits the object’s runtime type. For a non-virtual method it is a call that checks the object for null first. It may be preceded by constrained. for a value type or a generic type. | NullReferenceException if the object is null. Verifiable. |
29 token | calli signature | …, args, pointer → …, result | Calls through a function pointer on top of the stack (from ldftn, ldvirtftn or native code), with the calling convention and parameter types of the StandAloneSig the token names. The signature may be a managed or an unmanaged convention (cdecl, stdcall, thiscall, fastcall) or vararg. | As for call; a bad pointer is a crash. Not verifiable in general. |
73 token | newobj ctor | …, args → …, object | Allocates a new object of the constructor’s type, calls the constructor named by the token on it with the arguments (the new object is passed as this and is not on the stack before), and pushes the object. For a value type the new value is pushed instead of a reference. | OutOfMemoryException; the constructor’s exceptions; MissingMethodException. Verifiable. |
2A | ret | …, value → (empty) | Returns to the caller. If the method returns a value it must be the only item on the stack, and is popped and passed back; a void method must return with an empty stack. A ret cannot be inside a try block or a handler; code there uses leave to a ret outside. | None. Verifiable when the return value matches the method’s return type. |
27 token | jmp method | (empty) → (empty) | Transfers control to the named method, passing it the current method’s arguments unchanged; the current method’s frame ends. The signatures must match, the stack must be empty, and the instruction cannot be in a try block or a handler. | As for call. Not verifiable. |
Function pointers and variable arguments
| Opcode | Instruction | Stack | What it does | Exceptions · verifiability |
|---|---|---|---|---|
FE 06 token | ldftn method | … → …, native int | Pushes a pointer to the machine-code entry of the named method. It is the argument a delegate constructor receives (newobj of a delegate type takes an object and an ldftn pointer), and the pointer for calli. | MissingMethodException. Verifiable only in the delegate-creation pattern. |
FE 07 token | ldvirtftn method | …, object → …, native int | Pops an object and pushes a pointer to the entry of the named virtual method as the object’s runtime type implements it. | NullReferenceException if the object is null; MissingMethodException. |
FE 00 | arglist | … → …, handle | Pushes a RuntimeArgumentHandle that stands for the list of extra arguments of the current method. It is valid only inside a vararg method and is how C# __arglist is read. | None. Valid only in a vararg method. |
The tail. prefix before a call, callvirt or calli asks the runtime to reuse the caller’s frame; the call must then be followed by ret.
Not described
Known, not yet covered
- Calling conventions in detail: how arguments and results travel in registers and on the stack for each platform is not described; only the IL-level effect is.
Unknown
- Which exact exception each runtime raises for a call to a method that cannot be found, beyond the names the specification lists.
Links
Reference
- ECMA-335 – partition III, section 3: call, callvirt, calli, newobj, ret, jmp; section 4: ldftn, ldvirtftn, arglist
- .NET signatures – the method signature blobs these tokens lead to