MSIL (or CIL) uses a stack based model.  To make sure that Type-safe code to be secure, it can only access the meory locations it is authorized to acess.
We verify the type on the stack. If the data type on the stack does not match the expection of an opcode, we will treat it as unverifiable code. Take below code as an example


.method public static void foo() cil managed
{
    .maxstack 8
    L_0000: ldc.r4 0
    L_0005: ldc.i4 0
    L_000a: add
    L_000b: pop
    L_000c: ret
}

The opcode "add" expects the two numbers on the stack of the same type. Since they are not (r4 and i4 are pushed on the stack), at runtime JIT will throw exception, unless SkipVerification is specified.
 

The PEVerify output looks like this
[IL]: Error: [xxx.dll : Test::foo][mdToken=0x6000001][offset 0x0000000A][found Double][expected Int32] Unexpected type on the stack.(Error: 0x80131854)