Skip to content

Latest commit

 

History

History
112 lines (83 loc) · 11.7 KB

iii.1.5-operand-type-table.md

File metadata and controls

112 lines (83 loc) · 11.7 KB

III.1.5 Operand type table

Many CIL operations take numeric operands on the stack. These operations fall into several categories, depending on how they deal with the types of the operands. The following tables summarize the valid kinds of operand types and the type of the result. Notice that the type referred to here is the type as tracked by the CLI rather than the more detailed types used by tools such as CIL verification. The types tracked by the CLI are: int32, int64, native int, F, O, and &.

Table III.2 shows the result type for A op B—where op is add, div, mul, rem, or sub—for each possible combination of operand types. Boxes holding simply a result type, apply to all five instructions. Boxes marked ✗ indicate an invalid CIL instruction. Shaded boxes Boxes marked with nv indicate a CIL instruction that is not verifiable. Boxes with a list of instructions are valid only for those instructions.

Table III.2: Binary Numeric Operations

A's Type B's Type          
  int32 int64 native int F & O
int32 int32 native int & (add) nv
int64 int64
native int native int native int & (add) nv
F F
& & (add, sub) nv & (add, sub) nv native int (sub) nv
O

Table III.3 shows the result type for the unary numeric operations. Used for the neg instruction. Boxes marked ✗ indicate an invalid CIL instruction. All valid uses of this instruction are verifiable.

Table III.3: Unary Numeric Operations

Operand Type Result Type
int32 int32
int64 int64
native int native int
F F
&
O

Table III.4 shows the result type for the comparison and branch instructions. The binary comparison returns a Boolean value and the branch operations branch based on the top two values on the stack. Used for beq, beq.s, bge, bge.s, bge.un, bge.un.s, bgt, bgt.s, bgt.un, bgt.un.s, ble, ble.s, ble.un, ble.un.s, blt, blt.s, blt.un, blt.un.s, bne.un, bne.un.s, ceq, cgt, cgt.un, clt, clt.un. Boxes marked ✓ indicate that all instructions are valid for that combination of operand types. Boxes marked ✗ indicate invalid CIL sequences. Shaded boxes Boxes marked nv indicate a CIL instruction that is not verifiable. Boxes with a list of instructions are valid only for those instructions.

Table III.4: Binary Comparison or Branch Operations

  int32 int64 native int F & O
int32
int64
native int beq[.s], bne.un[.s], ceq nv
F
& beq[.s], bne.un[.s], ceq nv 1
O beq[.s], bne.un[.s], ceq 2

1 Except for beq, bne.un, beq.s, bne.un.s, or ceq these combinations make sense if both operands are known to be pointers to elements of the same array. However, there is no security issue for a CLI that does not check this constraint [Note: if the two operands are not pointers into the same array, then the result is simply the distance apart in the garbage-collected heap of two unrelated data items. This distance apart will almost certainly change at the next garbage collection. Essentially, the result cannot be used to compute anything useful end note]

2 cgt.un is allowed and verifiable on ObjectRefs (O). This is commonly used when comparing an ObjectRef with null (there is no "compare-not-equal" instruction, which would otherwise be a more obvious solution)

Table III.5 shows the result type for each possible combination of operand types in integer operations. Used for and, div.un, not, or, rem.un, xor. The div.un and rem.un instructions treat their operands as unsigned integers and produce the bit pattern corresponding to the unsigned result. As described in the CLI standard, however, the CLI makes no distinction between signed and unsigned integers on the stack. The not instruction is unary and returns the same type as the input. The shl and shr instructions return the same type as their first operand, and their second operand shall be of type int32 or native int. Boxes marked ✗ indicate invalid CIL sequences. All other boxes denote verifiable combinations of operands.

Table III.5: Integer Operations

  int32 int64 native int F & O
int32 int32 native int
int64 int64
native int native int native int
F
&
O

Table III.6 shows the valid combinations of operands and result for the shift instructions: shl, shr, shr.un. Boxes marked ✗ indicate invalid CIL sequences. All other boxes denote verifiable combinations of operand. If the "Shift-By" operand is larger than the width of the "To-Be-Shifted" operand, then the results are unspecified. (e.g., shift an int32 integer left by 37 bits)

Table III.6: Shift Operations

To Be Shifted Shift-By          
  int32 int64 native int F & O
int32 int32 int32
int64 int64 int64
native int native int native int
F
&
O

Table III.7 shows the result type for each possible combination of operand types in the arithmetic operations with overflow checking. An exception shall be thrown if the result cannot be represented in the result type. Used for add.ovf, add.ovf.un, mul.ovf, mul.ovf.un, sub.ovf, and sub.ovf.un. For details of the exceptions thrown, see the descriptions of the specific instructions. The shaded uses marked nv are not verifiable, while boxes marked ✗ indicate invalid CIL sequences.

Table III.7: Overflow Arithmetic Operations

  int32 int64 native int F & O
int32 int32 native int & add.ovf.un nv
int64 int64
native int native int native int & add.ovf.un nv
F
& & add.ovf.un, sub.ovf.un nv & add.ovf.un, sub.ovf.un nv native int sub.ovf.un nv
O

Table III.8 shows the result type for the conversion operations. Conversion operations convert the top item on the evaluation stack from one numeric type to another. While converting, truncation or extension occurs as shown in the table. The result type is guaranteed to be representable as the data type specified as part of the operation (i.e., the conv.u2 instruction returns a value that can be stored in an unsigned int16). The stack, however, can only store values that are a minimum of 4 bytes wide. Used for the conv.<to type>, conv.ovf.<to type>, and conv.ovf.<to type>.un instructions. The shaded uses marked nv are not verifiable, while boxes marked ✗ indicate invalid CIL sequences.

Table III.8: Conversion Operations

Convert-To Input (from evaluation stack)          
  int32 int64 native int F & O
int8,
unsigned int8,
int16,
unsigned int16
Truncate1 Truncate1 Truncate1 Truncate to zero2
int32,
unsigned int32
Nop Truncate1 Truncate1 Truncate to zero2
int64 Sign extend Nop Sign extend Truncate to zero2 Stop GC trackingnv Stop GC trackingnv
unsigned int64 Zero extend Nop Zero extend Truncate to zero2 Stop GC tracking4,nv Stop GC tracking4,nv
native int Sign extend Truncate1 Nop Truncate to zero2 Stop GC tracking4,nv Stop GC tracking4,nv
native unsigned int Zero extend Truncate1 Nop Truncate to zero2 Stop GC tracking4,nv Stop GC tracking4,nv
All Float Types To Float To Float To Float Change precision3

1 "Truncate" means that the number is truncated to the desired size (i.e., the most significant bytes of the input value are simply ignored). If the result is narrower than the minimum stack width of 4 bytes, then this result is zero extended (if the result type is unsigned) or sign-extended (if the result type is signed). Thus, converting the value 0x1234 ABCD from the evaluation stack to an 8-bit datum yields the result 0xCD; if the result type were int8, this is sign-extended to give 0xFFFF FFCD; if, instead, the result type were unsigned int8, this is zero-extended to give 0x0000 00CD.

2 "Truncate to zero" means that the floating-point number will be converted to an integer by truncation toward zero. Thus 1.1 is converted to 1, and -1.1 is converted to -1.

3 Converts from the current precision available on the evaluation stack to the precision specified by the instruction. If the stack has more precision than the output size the conversion is performed using the IEC 60559:1989 "round-to-nearest" mode to compute the low order bit of the result.

4 "Stop GC Tracking" means that, following the conversion, the item's value will not be reported to subsequent garbage-collection operations (and therefore will not be updated by such operations).

Rounding mode for integer to and from F conversions is the same as for arithmetic.