Search code examples
.netclrcilvalue-type

Can the CIL evaluation stack contain value types?


I'm a little confused about value types and the CIL evaluation stack. ECMA-335, Partition III, §1.1 says that the CLI deals with these "Basic CLI types":

  • A subset of the full numeric types (int32, int64, native int, and F).

  • Object references (O) without distinction between the type of object referenced.

  • Pointer types (native unsigned int and &) without distinction as to the type pointed to.

Partition II, §12.1 also provides a similar list which excludes value types, and states:

However, the CLI supports only a subset of these types in its operations upon values stored on its evaluation stack— int32 , int64 , and native int.

This makes no mention of value types other than through managed pointer types. Yet the specification for ldfld, for example, says:

The ldfld instruction pushes onto the stack the value of a field of obj. obj shall be an object (type O), a managed pointer (type &), an unmanaged pointer (type native int), or an instance of a value type.

Does this mean value types can be pushed directly on the evaluation stack (as opposed to via a managed pointer)? If so, can I assume that the value type being pushed is a memberwise copy of the original (the field value, for example)?


Solution

  • Section I.12.3.2.1 of ISO/IEC 23271:2012 (CLI Specification) states the following:

    While the CLI, in general, supports the full set of types described in §I.12.1, the CLI treats the evaluation stack in a special way. While some JIT compilers might track the types on the stack in more detail, the CLI only requires that values be one of:

    • int64, an 8-byte signed integer
    • int32, a 4-byte signed integer
    • native int, a signed integer of either 4 or 8 bytes, whichever is more convenient for the target architecture
    • F, a floating point value (float32, float64, or other representation supported by the underlying hardware)
    • &, a managed pointer
    • O, an object reference
    • *, a “transient pointer,” which can be used only within the body of a single method, that points to a value known to be in unmanaged memory (see the CIL Instruction Set specification for more details. * types are generated internally within the CLI; they are not created by the user).
    • A user-defined value type

    So, yes, the evaluation stack can contain a value type. And that value type is copied.