// Copyright (c) Microsoft Open Technologies, Inc.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

module internal Microsoft.FSharp.Compiler.AbstractIL.Internal.BinaryConstants 

open Internal.Utilities
open Microsoft.FSharp.Compiler.AbstractIL 
open Microsoft.FSharp.Compiler.AbstractIL.IL 
open Microsoft.FSharp.Compiler.AbstractIL.Internal 
open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library

[<Struct>]
type TableName(idx: int) = 
    member x.Index = idx
    static member FromIndex n = TableName n 

module TableNames = 
    let Module               = TableName 0  
    let TypeRef              = TableName 1  
    let TypeDef              = TableName 2  
    let FieldPtr             = TableName 3  
    let Field                = TableName 4  
    let MethodPtr            = TableName 5  
    let Method               = TableName 6  
    let ParamPtr             = TableName 7  
    let Param                = TableName 8  
    let InterfaceImpl        = TableName 9  
    let MemberRef            = TableName 10 
    let Constant             = TableName 11 
    let CustomAttribute      = TableName 12 
    let FieldMarshal         = TableName 13 
    let Permission           = TableName 14 
    let ClassLayout          = TableName 15 
    let FieldLayout          = TableName 16 
    let StandAloneSig        = TableName 17 
    let EventMap             = TableName 18 
    let EventPtr             = TableName 19 
    let Event                = TableName 20 
    let PropertyMap          = TableName 21 
    let PropertyPtr          = TableName 22 
    let Property             = TableName 23 
    let MethodSemantics      = TableName 24 
    let MethodImpl           = TableName 25 
    let ModuleRef            = TableName 26 
    let TypeSpec             = TableName 27 
    let ImplMap              = TableName 28 
    let FieldRVA             = TableName 29 
    let ENCLog               = TableName 30 
    let ENCMap               = TableName 31 
    let Assembly             = TableName 32 
    let AssemblyProcessor    = TableName 33 
    let AssemblyOS           = TableName 34 
    let AssemblyRef          = TableName 35 
    let AssemblyRefProcessor = TableName 36 
    let AssemblyRefOS        = TableName 37 
    let File                 = TableName 38 
    let ExportedType         = TableName 39 
    let ManifestResource     = TableName 40 
    let Nested               = TableName 41 
    let GenericParam           = TableName 42 
    let MethodSpec           = TableName 43 
    let GenericParamConstraint = TableName 44

    let UserStrings           = TableName 0x70 (* Special encoding of embedded UserString tokens - See 1.9 Partition III *) 

/// Which tables are sorted and by which column 
//
// Sorted bit-vector as stored by CLR V1: 00fa 0133 0002 0000 
// But what does this mean?  The ECMA spec does not say! 
// Metainfo -schema reports sorting as shown below. 
// But some sorting, e.g. EventMap does not seem to show 
let sortedTableInfo = 
  [ (TableNames.InterfaceImpl,0); 
    (TableNames.Constant, 1);
    (TableNames.CustomAttribute, 0);
    (TableNames.FieldMarshal, 0);
    (TableNames.Permission, 1);
    (TableNames.ClassLayout, 2);
    (TableNames.FieldLayout, 1);
    (TableNames.MethodSemantics, 2);
    (TableNames.MethodImpl, 0);
    (TableNames.ImplMap, 1);
    (TableNames.FieldRVA, 1);
    (TableNames.Nested, 0);
    (TableNames.GenericParam, 2); 
    (TableNames.GenericParamConstraint, 0); ]
    
[<Struct>]
type TypeDefOrRefTag(tag: int32) = member x.Tag = tag
let tdor_TypeDef = TypeDefOrRefTag 0x00
let tdor_TypeRef = TypeDefOrRefTag 0x01
let tdor_TypeSpec = TypeDefOrRefTag 0x2
let mkTypeDefOrRefOrSpecTag x = 
    match x with 
    | 0x00 -> tdor_TypeDef // nb. avoid reallocation 
    | 0x01 -> tdor_TypeRef
    | 0x02 -> tdor_TypeSpec
    | _ -> invalidArg "x" "mkTypeDefOrRefOrSpecTag"

[<Struct>]
type HasConstantTag(tag: int32) = member x.Tag = tag
let hc_FieldDef  = HasConstantTag 0x0
let hc_ParamDef  = HasConstantTag 0x1
let hc_Property = HasConstantTag 0x2

let mkHasConstantTag x = 
    match x with 
    | 0x00 -> hc_FieldDef
    | 0x01 -> hc_ParamDef
    | 0x02 -> hc_Property
    | _ -> invalidArg "x" "mkHasConstantTag"

[<Struct>]
type HasCustomAttributeTag(tag: int32) = member x.Tag = tag
let hca_MethodDef       = HasCustomAttributeTag 0x0
let hca_FieldDef        = HasCustomAttributeTag 0x1
let hca_TypeRef         = HasCustomAttributeTag 0x2
let hca_TypeDef         = HasCustomAttributeTag 0x3
let hca_ParamDef        = HasCustomAttributeTag 0x4
let hca_InterfaceImpl   = HasCustomAttributeTag 0x5
let hca_MemberRef       = HasCustomAttributeTag 0x6
let hca_Module          = HasCustomAttributeTag 0x7
let hca_Permission      = HasCustomAttributeTag 0x8
let hca_Property        = HasCustomAttributeTag 0x9
let hca_Event           = HasCustomAttributeTag 0xa
let hca_StandAloneSig   = HasCustomAttributeTag 0xb
let hca_ModuleRef       = HasCustomAttributeTag 0xc
let hca_TypeSpec        = HasCustomAttributeTag 0xd
let hca_Assembly        = HasCustomAttributeTag 0xe
let hca_AssemblyRef     = HasCustomAttributeTag 0xf
let hca_File            = HasCustomAttributeTag 0x10
let hca_ExportedType    = HasCustomAttributeTag 0x11
let hca_ManifestResource        = HasCustomAttributeTag 0x12
let hca_GenericParam            = HasCustomAttributeTag 0x13
let hca_GenericParamConstraint  = HasCustomAttributeTag 0x14
let hca_MethodSpec              = HasCustomAttributeTag 0x15

let mkHasCustomAttributeTag x = 
    match x with 
    | 0x00 -> hca_MethodDef  
    | 0x01 -> hca_FieldDef 
    | 0x02 -> hca_TypeRef  
    | 0x03 -> hca_TypeDef 
    | 0x04 -> hca_ParamDef 
    | 0x05 -> hca_InterfaceImpl 
    | 0x06 -> hca_MemberRef 
    | 0x07 -> hca_Module 
    | 0x08 -> hca_Permission 
    | 0x09 -> hca_Property 
    | 0x0a -> hca_Event 
    | 0x0b -> hca_StandAloneSig 
    | 0x0c -> hca_ModuleRef 
    | 0x0d -> hca_TypeSpec 
    | 0x0e -> hca_Assembly 
    | 0x0f -> hca_AssemblyRef 
    | 0x10 -> hca_File 
    | 0x11 -> hca_ExportedType 
    | 0x12 -> hca_ManifestResource
    | 0x13 -> hca_GenericParam
    | 0x14 -> hca_GenericParamConstraint
    | 0x15 -> hca_MethodSpec 
    | _ -> HasCustomAttributeTag x

[<Struct>]
type HasFieldMarshalTag(tag: int32) = member x.Tag = tag
let hfm_FieldDef =  HasFieldMarshalTag 0x00
let hfm_ParamDef =  HasFieldMarshalTag 0x01

let mkHasFieldMarshalTag x = 
    match x with 
    | 0x00 -> hfm_FieldDef 
    | 0x01 -> hfm_ParamDef 
    | _ -> HasFieldMarshalTag x

[<Struct>]
type HasDeclSecurityTag(tag: int32) = member x.Tag = tag
let hds_TypeDef =  HasDeclSecurityTag 0x00
let hds_MethodDef =  HasDeclSecurityTag 0x01
let hds_Assembly =  HasDeclSecurityTag 0x02

let mkHasDeclSecurityTag x = 
    match x with 
    | 0x00 -> hds_TypeDef 
    | 0x01 -> hds_MethodDef 
    | 0x02 -> hds_Assembly 
    | _ -> HasDeclSecurityTag x

[<Struct>]
type MemberRefParentTag(tag: int32) = member x.Tag = tag
let mrp_TypeRef = MemberRefParentTag 0x01
let mrp_ModuleRef = MemberRefParentTag 0x02
let mrp_MethodDef = MemberRefParentTag 0x03
let mrp_TypeSpec  = MemberRefParentTag 0x04

let mkMemberRefParentTag x = 
    match x with 
    | 0x01 -> mrp_TypeRef 
    | 0x02 -> mrp_ModuleRef 
    | 0x03 -> mrp_MethodDef 
    | 0x04 -> mrp_TypeSpec  
    | _ -> MemberRefParentTag x

[<Struct>]
type HasSemanticsTag(tag: int32) = member x.Tag = tag
let hs_Event =  HasSemanticsTag 0x00
let hs_Property =  HasSemanticsTag 0x01

let mkHasSemanticsTag x = 
    match x with 
    | 0x00 -> hs_Event 
    | 0x01 -> hs_Property 
    | _ -> HasSemanticsTag x

[<Struct>]
type MethodDefOrRefTag(tag: int32) = member x.Tag = tag
let mdor_MethodDef =  MethodDefOrRefTag 0x00
let mdor_MemberRef =  MethodDefOrRefTag 0x01
let mdor_MethodSpec =  MethodDefOrRefTag 0x02

let mkMethodDefOrRefTag x = 
    match x with 
    | 0x00 -> mdor_MethodDef 
    | 0x01 -> mdor_MemberRef 
    | 0x02 -> mdor_MethodSpec 
    | _ -> MethodDefOrRefTag x

[<Struct>]
type MemberForwardedTag(tag: int32) = member x.Tag = tag
let mf_FieldDef =  MemberForwardedTag 0x00
let mf_MethodDef =  MemberForwardedTag 0x01

let mkMemberForwardedTag x = 
    match x with 
    | 0x00 -> mf_FieldDef 
    | 0x01 -> mf_MethodDef 
    | _ -> MemberForwardedTag x

[<Struct>]
type ImplementationTag(tag: int32) = member x.Tag = tag
let i_File =  ImplementationTag 0x00
let i_AssemblyRef =  ImplementationTag 0x01
let i_ExportedType =  ImplementationTag 0x02

let mkImplementationTag x = 
    match x with 
    | 0x00 -> i_File 
    | 0x01 -> i_AssemblyRef 
    | 0x02 -> i_ExportedType 
    | _ -> ImplementationTag x

[<Struct>]
type CustomAttributeTypeTag(tag: int32) = member x.Tag = tag
let cat_MethodDef =  CustomAttributeTypeTag 0x02
let cat_MemberRef =  CustomAttributeTypeTag 0x03

let mkILCustomAttributeTypeTag x = 
    match x with 
    | 0x02 -> cat_MethodDef 
    | 0x03 -> cat_MemberRef 
    | _ -> CustomAttributeTypeTag x

[<Struct>]
type ResolutionScopeTag(tag: int32) = member x.Tag = tag
let rs_Module =  ResolutionScopeTag 0x00
let rs_ModuleRef =  ResolutionScopeTag 0x01
let rs_AssemblyRef  =  ResolutionScopeTag 0x02
let rs_TypeRef =  ResolutionScopeTag 0x03

let mkResolutionScopeTag x = 
    match x with 
    | 0x00 -> rs_Module 
    | 0x01 -> rs_ModuleRef 
    | 0x02 -> rs_AssemblyRef  
    | 0x03 -> rs_TypeRef 
    | _ -> ResolutionScopeTag x

[<Struct>]
type TypeOrMethodDefTag(tag: int32) = member x.Tag = tag
let tomd_TypeDef = TypeOrMethodDefTag 0x00
let tomd_MethodDef = TypeOrMethodDefTag 0x01

let mkTypeOrMethodDefTag x = 
    match x with 
    | 0x00 -> tomd_TypeDef 
    | 0x01 -> tomd_MethodDef
    | _ -> TypeOrMethodDefTag x

let et_END = 0x00uy
let et_VOID = 0x01uy
let et_BOOLEAN = 0x02uy
let et_CHAR = 0x03uy
let et_I1 = 0x04uy
let et_U1 = 0x05uy
let et_I2 = 0x06uy
let et_U2 = 0x07uy
let et_I4 = 0x08uy
let et_U4 = 0x09uy
let et_I8 = 0x0Auy
let et_U8 = 0x0Buy
let et_R4 = 0x0Cuy
let et_R8 = 0x0Duy
let et_STRING = 0x0Euy
let et_PTR = 0x0Fuy
let et_BYREF = 0x10uy
let et_VALUETYPE      = 0x11uy
let et_CLASS          = 0x12uy
let et_VAR            = 0x13uy
let et_ARRAY          = 0x14uy
let et_WITH           = 0x15uy
let et_TYPEDBYREF     = 0x16uy
let et_I              = 0x18uy
let et_U              = 0x19uy
let et_FNPTR          = 0x1Buy
let et_OBJECT         = 0x1Cuy
let et_SZARRAY        = 0x1Duy
let et_MVAR           = 0x1euy
let et_CMOD_REQD      = 0x1Fuy
let et_CMOD_OPT       = 0x20uy

let et_SENTINEL       = 0x41uy // sentinel for varargs 
let et_PINNED         = 0x45uy


let i_nop           = 0x00 
let i_break         = 0x01 
let i_ldarg_0       = 0x02 
let i_ldarg_1       = 0x03 
let i_ldarg_2       = 0x04 
let i_ldarg_3       = 0x05 
let i_ldloc_0       = 0x06 
let i_ldloc_1       = 0x07 
let i_ldloc_2       = 0x08 
let i_ldloc_3       = 0x09 
let i_stloc_0       = 0x0a 
let i_stloc_1       = 0x0b 
let i_stloc_2       = 0x0c 
let i_stloc_3       = 0x0d 
let i_ldarg_s       = 0x0e 
let i_ldarga_s      = 0x0f 
let i_starg_s       = 0x10 
let i_ldloc_s       = 0x11 
let i_ldloca_s      = 0x12 
let i_stloc_s       = 0x13 
let i_ldnull        = 0x14 
let i_ldc_i4_m1     = 0x15 
let i_ldc_i4_0      = 0x16 
let i_ldc_i4_1      = 0x17 
let i_ldc_i4_2      = 0x18 
let i_ldc_i4_3      = 0x19 
let i_ldc_i4_4      = 0x1a 
let i_ldc_i4_5      = 0x1b 
let i_ldc_i4_6      = 0x1c 
let i_ldc_i4_7      = 0x1d 
let i_ldc_i4_8      = 0x1e 
let i_ldc_i4_s      = 0x1f 
let i_ldc_i4        = 0x20 
let i_ldc_i8        = 0x21 
let i_ldc_r4        = 0x22 
let i_ldc_r8        = 0x23 
let i_dup           = 0x25 
let i_pop           = 0x26 
let i_jmp           = 0x27 
let i_call          = 0x28 
let i_calli         = 0x29 
let i_ret           = 0x2a 
let i_br_s          = 0x2b 
let i_brfalse_s     = 0x2c 
let i_brtrue_s      = 0x2d 
let i_beq_s         = 0x2e 
let i_bge_s         = 0x2f 
let i_bgt_s         = 0x30 
let i_ble_s         = 0x31 
let i_blt_s         = 0x32 
let i_bne_un_s      = 0x33 
let i_bge_un_s      = 0x34 
let i_bgt_un_s      = 0x35 
let i_ble_un_s      = 0x36 
let i_blt_un_s      = 0x37 
let i_br            = 0x38 
let i_brfalse       = 0x39 
let i_brtrue        = 0x3a 
let i_beq           = 0x3b 
let i_bge           = 0x3c 
let i_bgt           = 0x3d 
let i_ble           = 0x3e 
let i_blt           = 0x3f 
let i_bne_un        = 0x40 
let i_bge_un        = 0x41 
let i_bgt_un        = 0x42 
let i_ble_un        = 0x43 
let i_blt_un        = 0x44 
let i_switch        = 0x45 
let i_ldind_i1      = 0x46 
let i_ldind_u1      = 0x47 
let i_ldind_i2      = 0x48 
let i_ldind_u2      = 0x49 
let i_ldind_i4      = 0x4a 
let i_ldind_u4      = 0x4b 
let i_ldind_i8      = 0x4c 
let i_ldind_i       = 0x4d 
let i_ldind_r4      = 0x4e 
let i_ldind_r8      = 0x4f 
let i_ldind_ref     = 0x50 
let i_stind_ref     = 0x51 
let i_stind_i1      = 0x52 
let i_stind_i2      = 0x53 
let i_stind_i4      = 0x54 
let i_stind_i8      = 0x55 
let i_stind_r4      = 0x56 
let i_stind_r8      = 0x57 
let i_add           = 0x58 
let i_sub           = 0x59 
let i_mul           = 0x5a 
let i_div           = 0x5b 
let i_div_un        = 0x5c 
let i_rem           = 0x5d 
let i_rem_un        = 0x5e 
let i_and           = 0x5f 
let i_or            = 0x60 
let i_xor           = 0x61 
let i_shl           = 0x62 
let i_shr           = 0x63 
let i_shr_un        = 0x64 
let i_neg           = 0x65 
let i_not           = 0x66 
let i_conv_i1       = 0x67 
let i_conv_i2       = 0x68 
let i_conv_i4       = 0x69 
let i_conv_i8       = 0x6a 
let i_conv_r4       = 0x6b 
let i_conv_r8       = 0x6c 
let i_conv_u4       = 0x6d 
let i_conv_u8       = 0x6e 
let i_callvirt      = 0x6f 
let i_cpobj         = 0x70 
let i_ldobj         = 0x71 
let i_ldstr         = 0x72 
let i_newobj        = 0x73 
let i_castclass     = 0x74 
let i_isinst        = 0x75 
let i_conv_r_un     = 0x76 
let i_unbox         = 0x79 
let i_throw         = 0x7a 
let i_ldfld         = 0x7b 
let i_ldflda        = 0x7c 
let i_stfld         = 0x7d 
let i_ldsfld        = 0x7e 
let i_ldsflda       = 0x7f 
let i_stsfld        = 0x80 
let i_stobj         = 0x81 
let i_conv_ovf_i1_un= 0x82 
let i_conv_ovf_i2_un= 0x83 
let i_conv_ovf_i4_un= 0x84 
let i_conv_ovf_i8_un= 0x85 
let i_conv_ovf_u1_un= 0x86 
let i_conv_ovf_u2_un= 0x87 
let i_conv_ovf_u4_un= 0x88 
let i_conv_ovf_u8_un= 0x89 
let i_conv_ovf_i_un = 0x8a 
let i_conv_ovf_u_un = 0x8b 
let i_box           = 0x8c 
let i_newarr        = 0x8d 
let i_ldlen         = 0x8e 
let i_ldelema       = 0x8f 
let i_ldelem_i1     = 0x90 
let i_ldelem_u1     = 0x91 
let i_ldelem_i2     = 0x92 
let i_ldelem_u2     = 0x93 
let i_ldelem_i4     = 0x94 
let i_ldelem_u4     = 0x95 
let i_ldelem_i8     = 0x96 
let i_ldelem_i      = 0x97 
let i_ldelem_r4     = 0x98 
let i_ldelem_r8     = 0x99 
let i_ldelem_ref    = 0x9a 
let i_stelem_i      = 0x9b 
let i_stelem_i1     = 0x9c 
let i_stelem_i2     = 0x9d 
let i_stelem_i4     = 0x9e 
let i_stelem_i8     = 0x9f 
let i_stelem_r4     = 0xa0 
let i_stelem_r8     = 0xa1 
let i_stelem_ref    = 0xa2 
let i_conv_ovf_i1   = 0xb3 
let i_conv_ovf_u1   = 0xb4 
let i_conv_ovf_i2   = 0xb5 
let i_conv_ovf_u2   = 0xb6 
let i_conv_ovf_i4   = 0xb7 
let i_conv_ovf_u4   = 0xb8 
let i_conv_ovf_i8   = 0xb9 
let i_conv_ovf_u8   = 0xba 
let i_refanyval     = 0xc2 
let i_ckfinite      = 0xc3 
let i_mkrefany      = 0xc6 
let i_ldtoken       = 0xd0 
let i_conv_u2       = 0xd1 
let i_conv_u1       = 0xd2 
let i_conv_i        = 0xd3 
let i_conv_ovf_i    = 0xd4 
let i_conv_ovf_u    = 0xd5 
let i_add_ovf       = 0xd6 
let i_add_ovf_un    = 0xd7 
let i_mul_ovf       = 0xd8 
let i_mul_ovf_un    = 0xd9 
let i_sub_ovf       = 0xda 
let i_sub_ovf_un    = 0xdb 
let i_endfinally    = 0xdc 
let i_leave         = 0xdd 
let i_leave_s       = 0xde 
let i_stind_i       = 0xdf 
let i_conv_u        = 0xe0 
let i_arglist        = 0xfe00
let i_ceq        = 0xfe01
let i_cgt        = 0xfe02
let i_cgt_un        = 0xfe03
let i_clt        = 0xfe04
let i_clt_un        = 0xfe05
let i_ldftn        = 0xfe06 
let i_ldvirtftn    = 0xfe07 
let i_ldarg          = 0xfe09 
let i_ldarga         = 0xfe0a 
let i_starg          = 0xfe0b 
let i_ldloc          = 0xfe0c 
let i_ldloca         = 0xfe0d 
let i_stloc          = 0xfe0e 
let i_localloc     = 0xfe0f 
let i_endfilter    = 0xfe11 
let i_unaligned   = 0xfe12 
let i_volatile    = 0xfe13 
let i_constrained    = 0xfe16
let i_readonly    = 0xfe1e
let i_tail           = 0xfe14 
let i_initobj        = 0xfe15 
let i_cpblk          = 0xfe17 
let i_initblk        = 0xfe18 
let i_rethrow        = 0xfe1a 
let i_sizeof         = 0xfe1c 
let i_refanytype   = 0xfe1d 

let i_ldelem_any = 0xa3
let i_stelem_any = 0xa4
let i_unbox_any = 0xa5

let mk_ldc i = (((mkLdcInt32 (i))))
let noArgInstrs  = 
   lazy [ i_ldc_i4_0,           mk_ldc 0;
          i_ldc_i4_1,           mk_ldc 1;
          i_ldc_i4_2,           mk_ldc 2;
          i_ldc_i4_3,           mk_ldc 3;
          i_ldc_i4_4,           mk_ldc 4;
          i_ldc_i4_5,           mk_ldc 5;
          i_ldc_i4_6,           mk_ldc 6;
          i_ldc_i4_7,           mk_ldc 7;
          i_ldc_i4_8,           mk_ldc 8;
          i_ldc_i4_m1,           mk_ldc (0-1);
          0x0a,            (mkStloc (uint16 ( 0)));
          0x0b,            (mkStloc (uint16 ( 1)));
          0x0c,            (mkStloc (uint16 ( 2)));
          0x0d,            (mkStloc (uint16 ( 3)));
          0x06,            (mkLdloc (uint16 ( 0)));
          0x07,            (mkLdloc (uint16 ( 1)));
          0x08,            (mkLdloc (uint16 ( 2)));
          0x09,            (mkLdloc (uint16 ( 3)));
          0x02,            (mkLdarg (uint16 ( 0)));
          0x03,            (mkLdarg (uint16 ( 1)));
          0x04,            (mkLdarg (uint16 ( 2)));
          0x05,            (mkLdarg (uint16 ( 3)));
          0x2a,              (I_ret);
          0x58,              (AI_add);
          0xd6,        (AI_add_ovf);
          0xd7,   (AI_add_ovf_un);
          0x5f,              (AI_and);  
          0x5b,              (AI_div); 
          0x5c,         (AI_div_un);
          0xfe01,              (AI_ceq);  
          0xfe02,              (AI_cgt );
          0xfe03,         (AI_cgt_un);
          0xfe04,              (AI_clt);
          0xfe05,         (AI_clt_un);
          0x67,        ((AI_conv DT_I1));  
          0x68,   ((AI_conv DT_I2));  
          0x69,   ((AI_conv DT_I4));  
          0x6a,   ((AI_conv DT_I8));  
          0xd3,   ((AI_conv DT_I));  
          0x6b,   ((AI_conv DT_R4));  
          0x6c,   ((AI_conv DT_R8));  
          0xd2,   ((AI_conv DT_U1));  
          0xd1,   ((AI_conv DT_U2));  
          0x6d,   ((AI_conv DT_U4));  
          0x6e,   ((AI_conv DT_U8));  
          0xe0,   ((AI_conv DT_U));  
          0x76,   ((AI_conv DT_R));  
          0xb3,   ((AI_conv_ovf DT_I1));  
          0xb5,   ((AI_conv_ovf DT_I2));  
          0xb7,   ((AI_conv_ovf DT_I4));  
          0xb9,   ((AI_conv_ovf DT_I8));  
          0xd4,   ((AI_conv_ovf DT_I));  
          0xb4,   ((AI_conv_ovf DT_U1));  
          0xb6,   ((AI_conv_ovf DT_U2));  
          0xb8,   ((AI_conv_ovf DT_U4));  
          0xba,   ((AI_conv_ovf DT_U8));  
          0xd5,   ((AI_conv_ovf DT_U));  
          0x82,   ((AI_conv_ovf_un DT_I1));  
          0x83,   ((AI_conv_ovf_un DT_I2));  
          0x84,   ((AI_conv_ovf_un DT_I4));  
          0x85,   ((AI_conv_ovf_un DT_I8));  
          0x8a,   ((AI_conv_ovf_un DT_I));  
          0x86,   ((AI_conv_ovf_un DT_U1));  
          0x87,   ((AI_conv_ovf_un DT_U2));  
          0x88,   ((AI_conv_ovf_un DT_U4));  
          0x89,   ((AI_conv_ovf_un DT_U8));  
          0x8b,   ((AI_conv_ovf_un DT_U));  
          0x9c,   (I_stelem DT_I1);  
          0x9d,   (I_stelem DT_I2);  
          0x9e,   (I_stelem DT_I4);  
          0x9f,   (I_stelem DT_I8);  
          0xa0,   (I_stelem DT_R4);  
          0xa1,   (I_stelem DT_R8);  
          0x9b,   (I_stelem DT_I);  
          0xa2,   (I_stelem DT_REF);  
          0x90,   (I_ldelem DT_I1);  
          0x92,   (I_ldelem DT_I2);  
          0x94,   (I_ldelem DT_I4);  
          0x96,   (I_ldelem DT_I8);  
          0x91,   (I_ldelem DT_U1);  
          0x93,   (I_ldelem DT_U2);  
          0x95,   (I_ldelem DT_U4);  
          0x98,   (I_ldelem DT_R4);  
          0x99,   (I_ldelem DT_R8);  
          0x97,   (I_ldelem DT_I);  
          0x9a,   (I_ldelem DT_REF);  
          0x5a,   (AI_mul  );
          0xd8,   (AI_mul_ovf);
          0xd9,   (AI_mul_ovf_un);
          0x5d,   (AI_rem  );
          0x5e,   (AI_rem_un ); 
          0x62,   (AI_shl ); 
          0x63,   (AI_shr ); 
          0x64,   (AI_shr_un);
          0x59,   (AI_sub  );
          0xda,   (AI_sub_ovf);
          0xdb,   (AI_sub_ovf_un); 
          0x61,   (AI_xor);  
          0x60,   (AI_or);     
          0x65,   (AI_neg);     
          0x66,   (AI_not);     
          i_ldnull,   (AI_ldnull);   
          i_dup,   (AI_dup);   
          i_pop,   (AI_pop);
          i_ckfinite,   (AI_ckfinite);
          i_nop,   AI_nop;
          i_break,   I_break;
          i_arglist,   I_arglist;
          i_endfilter,   I_endfilter;
          i_endfinally,   I_endfinally;
          i_refanytype,   I_refanytype;
          i_localloc,   I_localloc;
          i_throw,   I_throw;
          i_ldlen,   I_ldlen;
          i_rethrow,       I_rethrow; ];;

let isNoArgInstr i = 
  match i with 
  | (AI_ldc (DT_I4, ILConst.I4 n)) when (-1) <= n && n <= 8 -> true
  | I_stloc n | I_ldloc n | I_ldarg n when n <= 3us -> true
  | I_ret
  | AI_add
  | AI_add_ovf
  | AI_add_ovf_un
  | AI_and  
  | AI_div 
  | AI_div_un
  | AI_ceq  
  | AI_cgt 
  | AI_cgt_un
  | AI_clt
  | AI_clt_un
  | AI_conv DT_I1  
  | AI_conv DT_I2  
  | AI_conv DT_I4  
  | AI_conv DT_I8  
  | AI_conv DT_I  
  | AI_conv DT_R4  
  | AI_conv DT_R8  
  | AI_conv DT_U1  
  | AI_conv DT_U2  
  | AI_conv DT_U4  
  | AI_conv DT_U8  
  | AI_conv DT_U  
  | AI_conv DT_R  
  | AI_conv_ovf DT_I1  
  | AI_conv_ovf DT_I2  
  | AI_conv_ovf DT_I4  
  | AI_conv_ovf DT_I8  
  | AI_conv_ovf DT_I  
  | AI_conv_ovf DT_U1  
  | AI_conv_ovf DT_U2  
  | AI_conv_ovf DT_U4  
  | AI_conv_ovf DT_U8  
  | AI_conv_ovf DT_U  
  | AI_conv_ovf_un DT_I1  
  | AI_conv_ovf_un DT_I2  
  | AI_conv_ovf_un DT_I4  
  | AI_conv_ovf_un DT_I8  
  | AI_conv_ovf_un DT_I  
  | AI_conv_ovf_un DT_U1  
  | AI_conv_ovf_un DT_U2  
  | AI_conv_ovf_un DT_U4  
  | AI_conv_ovf_un DT_U8  
  | AI_conv_ovf_un DT_U  
  | I_stelem DT_I1  
  | I_stelem DT_I2  
  | I_stelem DT_I4  
  | I_stelem DT_I8  
  | I_stelem DT_R4  
  | I_stelem DT_R8  
  | I_stelem DT_I  
  | I_stelem DT_REF  
  | I_ldelem DT_I1  
  | I_ldelem DT_I2  
  | I_ldelem DT_I4  
  | I_ldelem DT_I8  
  | I_ldelem DT_U1  
  | I_ldelem DT_U2  
  | I_ldelem DT_U4  
  | I_ldelem DT_R4  
  | I_ldelem DT_R8  
  | I_ldelem DT_I  
  | I_ldelem DT_REF  
  | AI_mul  
  | AI_mul_ovf
  | AI_mul_ovf_un
  | AI_rem  
  | AI_rem_un  
  | AI_shl  
  | AI_shr  
  | AI_shr_un
  | AI_sub  
  | AI_sub_ovf
  | AI_sub_ovf_un 
  | AI_xor  
  | AI_or     
  | AI_neg     
  | AI_not     
  | AI_ldnull   
  | AI_dup   
  | AI_pop
  | AI_ckfinite
  | AI_nop
  | I_break
  | I_arglist
  | I_endfilter
  | I_endfinally
  | I_refanytype
  | I_localloc
  | I_throw
  | I_ldlen
  | I_rethrow -> true
  | _ -> false

let ILCmpInstrMap = 
   lazy
    (Dictionary.ofList
        [ BI_beq , i_beq
          BI_bgt , i_bgt
          BI_bgt_un , i_bgt_un
          BI_bge , i_bge
          BI_bge_un , i_bge_un
          BI_ble , i_ble
          BI_ble_un , i_ble_un
          BI_blt , i_blt
          BI_blt_un , i_blt_un
          BI_bne_un , i_bne_un
          BI_brfalse , i_brfalse
          BI_brtrue , i_brtrue ])

let ILCmpInstrRevMap = 
  lazy
    (Dictionary.ofList
        [ BI_beq , i_beq_s
          BI_bgt , i_bgt_s
          BI_bgt_un , i_bgt_un_s
          BI_bge , i_bge_s
          BI_bge_un , i_bge_un_s
          BI_ble , i_ble_s
          BI_ble_un , i_ble_un_s
          BI_blt , i_blt_s
          BI_blt_un , i_blt_un_s
          BI_bne_un , i_bne_un_s
          BI_brfalse , i_brfalse_s
          BI_brtrue , i_brtrue_s ])

(* From corhdr.h *)

let nt_VOID        = 0x1uy
let nt_BOOLEAN     = 0x2uy
let nt_I1          = 0x3uy
let nt_U1          = 0x4uy
let nt_I2          = 0x5uy
let nt_U2          = 0x6uy
let nt_I4          = 0x7uy
let nt_U4          = 0x8uy
let nt_I8          = 0x9uy
let nt_U8          = 0xAuy
let nt_R4          = 0xBuy
let nt_R8          = 0xCuy
let nt_SYSCHAR     = 0xDuy
let nt_VARIANT     = 0xEuy
let nt_CURRENCY    = 0xFuy
let nt_PTR         = 0x10uy
let nt_DECIMAL     = 0x11uy
let nt_DATE        = 0x12uy
let nt_BSTR        = 0x13uy
let nt_LPSTR       = 0x14uy
let nt_LPWSTR      = 0x15uy
let nt_LPTSTR      = 0x16uy
let nt_FIXEDSYSSTRING  = 0x17uy
let nt_OBJECTREF   = 0x18uy
let nt_IUNKNOWN    = 0x19uy
let nt_IDISPATCH   = 0x1Auy
let nt_STRUCT      = 0x1Buy
let nt_INTF        = 0x1Cuy
let nt_SAFEARRAY   = 0x1Duy
let nt_FIXEDARRAY  = 0x1Euy
let nt_INT         = 0x1Fuy
let nt_UINT        = 0x20uy
let nt_NESTEDSTRUCT  = 0x21uy
let nt_BYVALSTR    = 0x22uy
let nt_ANSIBSTR    = 0x23uy
let nt_TBSTR       = 0x24uy
let nt_VARIANTBOOL = 0x25uy
let nt_FUNC        = 0x26uy
let nt_ASANY       = 0x28uy
let nt_ARRAY       = 0x2Auy
let nt_LPSTRUCT    = 0x2Buy
let nt_CUSTOMMARSHALER = 0x2Cuy
let nt_ERROR       = 0x2Duy
let nt_MAX = 0x50uy

(* From c:/clrenv.i386/Crt/Inc/i386/hs.h *)

let vt_EMPTY = 0
let vt_NULL = 1
let vt_I2 = 2
let vt_I4 = 3
let vt_R4 = 4
let vt_R8 = 5
let vt_CY = 6
let vt_DATE = 7
let vt_BSTR = 8
let vt_DISPATCH = 9
let vt_ERROR = 10
let vt_BOOL = 11
let vt_VARIANT = 12
let vt_UNKNOWN = 13
let vt_DECIMAL = 14
let vt_I1 = 16
let vt_UI1 = 17
let vt_UI2 = 18
let vt_UI4 = 19
let vt_I8 = 20
let vt_UI8 = 21
let vt_INT = 22
let vt_UINT = 23
let vt_VOID = 24
let vt_HRESULT  = 25
let vt_PTR = 26
let vt_SAFEARRAY = 27
let vt_CARRAY = 28
let vt_USERDEFINED = 29
let vt_LPSTR = 30
let vt_LPWSTR = 31
let vt_RECORD = 36
let vt_FILETIME = 64
let vt_BLOB = 65
let vt_STREAM = 66
let vt_STORAGE = 67
let vt_STREAMED_OBJECT = 68
let vt_STORED_OBJECT = 69
let vt_BLOB_OBJECT = 70
let vt_CF = 71
let vt_CLSID = 72
let vt_VECTOR = 0x1000
let vt_ARRAY = 0x2000
let vt_BYREF = 0x4000

 
let ILNativeTypeMap = 
 lazy [ nt_CURRENCY , ILNativeType.Currency
        nt_BSTR , (* COM interop *) ILNativeType.BSTR
        nt_LPSTR , ILNativeType.LPSTR
        nt_LPWSTR , ILNativeType.LPWSTR
        nt_LPTSTR, ILNativeType.LPTSTR
        nt_IUNKNOWN , (* COM interop *) ILNativeType.IUnknown
        nt_IDISPATCH , (* COM interop *) ILNativeType.IDispatch
        nt_BYVALSTR , ILNativeType.ByValStr
        nt_TBSTR , ILNativeType.TBSTR
        nt_LPSTRUCT , ILNativeType.LPSTRUCT
        nt_INTF , (* COM interop *) ILNativeType.Interface
        nt_STRUCT , ILNativeType.Struct
        nt_ERROR , (* COM interop *) ILNativeType.Error               
        nt_VOID , ILNativeType.Void 
        nt_BOOLEAN , ILNativeType.Bool
        nt_I1 , ILNativeType.Int8
        nt_I2 , ILNativeType.Int16
        nt_I4 , ILNativeType.Int32
        nt_I8, ILNativeType.Int64
        nt_R4 , ILNativeType.Single
        nt_R8 , ILNativeType.Double
        nt_U1 , ILNativeType.Byte
        nt_U2 , ILNativeType.UInt16
        nt_U4 , ILNativeType.UInt32
        nt_U8, ILNativeType.UInt64
        nt_INT , ILNativeType.Int
        nt_UINT, ILNativeType.UInt
        nt_ANSIBSTR, (* COM interop *) ILNativeType.ANSIBSTR
        nt_VARIANTBOOL, (* COM interop *) ILNativeType.VariantBool
        nt_FUNC , ILNativeType.Method
        nt_ASANY, ILNativeType.AsAny ]

let ILNativeTypeRevMap = lazy (List.map (fun (x,y) -> (y,x)) (Lazy.force ILNativeTypeMap))
    
let ILVariantTypeMap = 
 lazy [ ILNativeVariant.Empty                 , vt_EMPTY
        ILNativeVariant.Null                  , vt_NULL 
        ILNativeVariant.Variant               , vt_VARIANT       
        ILNativeVariant.Currency              , vt_CY         
        ILNativeVariant.Decimal               , vt_DECIMAL   
        ILNativeVariant.Date                  , vt_DATE       
        ILNativeVariant.BSTR                  , vt_BSTR       
        ILNativeVariant.LPSTR                 , vt_LPSTR     
        ILNativeVariant.LPWSTR                , vt_LPWSTR    
        ILNativeVariant.IUnknown              , vt_UNKNOWN   
        ILNativeVariant.IDispatch             , vt_DISPATCH    
        ILNativeVariant.SafeArray             , vt_SAFEARRAY 
        ILNativeVariant.Error                 ,  vt_ERROR         
        ILNativeVariant.HRESULT               , vt_HRESULT   
        ILNativeVariant.CArray                , vt_CARRAY    
        ILNativeVariant.UserDefined           , vt_USERDEFINED 
        ILNativeVariant.Record                , vt_RECORD
        ILNativeVariant.FileTime              , vt_FILETIME  
        ILNativeVariant.Blob                  , vt_BLOB       
        ILNativeVariant.Stream                , vt_STREAM     
        ILNativeVariant.Storage               , vt_STORAGE          
        ILNativeVariant.StreamedObject       , vt_STREAMED_OBJECT
        ILNativeVariant.StoredObject         , vt_STORED_OBJECT 
        ILNativeVariant.BlobObject           , vt_BLOB_OBJECT 
        ILNativeVariant.CF                    , vt_CF        
        ILNativeVariant.CLSID                 , vt_CLSID                    
        ILNativeVariant.Void                  , vt_VOID          
        ILNativeVariant.Bool                  , vt_BOOL        
        ILNativeVariant.Int8                  , vt_I1            
        ILNativeVariant.Int16                 , vt_I2  
        ILNativeVariant.Int32                 , vt_I4         
        ILNativeVariant.Int64                 , vt_I8        
        ILNativeVariant.Single               , vt_R4         
        ILNativeVariant.Double               , vt_R8         
        ILNativeVariant.UInt8         , vt_UI1       
        ILNativeVariant.UInt16        , vt_UI2       
        ILNativeVariant.UInt32        , vt_UI4       
        ILNativeVariant.UInt64        , vt_UI8       
        ILNativeVariant.PTR                   , vt_PTR       
        ILNativeVariant.Int                   , vt_INT               
        ILNativeVariant.UInt                , vt_UINT            ]

let ILVariantTypeRevMap = lazy (List.map (fun (x,y) -> (y,x)) (Lazy.force ILVariantTypeMap))

let ILSecurityActionMap =
  lazy
    [ ILSecurityAction.Request , 0x0001
      ILSecurityAction.Demand , 0x0002
      ILSecurityAction.Assert , 0x0003
      ILSecurityAction.Deny , 0x0004
      ILSecurityAction.PermitOnly  , 0x0005
      ILSecurityAction.LinkCheck  , 0x0006
      ILSecurityAction.InheritCheck , 0x0007
      ILSecurityAction.ReqMin , 0x0008
      ILSecurityAction.ReqOpt , 0x0009
      ILSecurityAction.ReqRefuse , 0x000a
      ILSecurityAction.PreJitGrant , 0x000b
      ILSecurityAction.PreJitDeny , 0x000c
      ILSecurityAction.NonCasDemand , 0x000d
      ILSecurityAction.NonCasLinkDemand , 0x000e
      ILSecurityAction.NonCasInheritance , 0x000f
      ILSecurityAction.LinkDemandChoice , 0x0010
      ILSecurityAction.InheritanceDemandChoice , 0x0011
      ILSecurityAction.DemandChoice , 0x0012 ]

let ILSecurityActionRevMap = lazy (List.map (fun (x,y) -> (y,x)) (Lazy.force ILSecurityActionMap))

let e_CorILMethod_TinyFormat = 0x02uy
let e_CorILMethod_FatFormat = 0x03uy
let e_CorILMethod_FormatMask = 0x03uy
let e_CorILMethod_MoreSects = 0x08uy
let e_CorILMethod_InitLocals = 0x10uy


let e_CorILMethod_Sect_EHTable = 0x1uy
let e_CorILMethod_Sect_FatFormat = 0x40uy
let e_CorILMethod_Sect_MoreSects = 0x80uy

let e_COR_ILEXCEPTION_CLAUSE_EXCEPTION = 0x0
let e_COR_ILEXCEPTION_CLAUSE_FILTER = 0x1
let e_COR_ILEXCEPTION_CLAUSE_FINALLY = 0x2
let e_COR_ILEXCEPTION_CLAUSE_FAULT = 0x4

let e_IMAGE_CEE_CS_CALLCONV_FASTCALL = 0x04uy
let e_IMAGE_CEE_CS_CALLCONV_STDCALL = 0x02uy
let e_IMAGE_CEE_CS_CALLCONV_THISCALL = 0x03uy
let e_IMAGE_CEE_CS_CALLCONV_CDECL = 0x01uy
let e_IMAGE_CEE_CS_CALLCONV_VARARG = 0x05uy
let e_IMAGE_CEE_CS_CALLCONV_FIELD = 0x06uy
let e_IMAGE_CEE_CS_CALLCONV_LOCAL_SIG = 0x07uy
let e_IMAGE_CEE_CS_CALLCONV_PROPERTY = 0x08uy

let e_IMAGE_CEE_CS_CALLCONV_GENERICINST = 0x0auy
let e_IMAGE_CEE_CS_CALLCONV_GENERIC = 0x10uy
let e_IMAGE_CEE_CS_CALLCONV_INSTANCE = 0x20uy
let e_IMAGE_CEE_CS_CALLCONV_INSTANCE_EXPLICIT = 0x40uy


