The functions that are defined in <jit/jit-type.h> allow the library user to create and manipulate objects that represent native system types.  For example, jit_type_int represents the signed 32-bit integer type.

Each jit_type_t object represents a basic system type, be it a primitive, a struct, a union, a pointer, or a function signature. The library uses this information to lay out values in memory.

The following pre-defined types are available:

jit_type_void
     Represents the void type.

jit_type_sbyte
     Represents a signed 8-bit integer type.

jit_type_ubyte
     Represents an unsigned 8-bit integer type.

jit_type_short
     Represents a signed 16-bit integer type.

jit_type_ushort
     Represents an unsigned 16-bit integer type.

jit_type_int
     Represents a signed 32-bit integer type.

jit_type_uint
     Represents an unsigned 32-bit integer type.

jit_type_nint
     Represents a signed integer type that has the same size and alignment as a native pointer.

jit_type_nuint
     Represents an unsigned integer type that has the same size and alignment as a native pointer.

jit_type_long
     Represents a signed 64-bit integer type.

jit_type_ulong
     Represents an unsigned 64-bit integer type.

jit_type_float32
     Represents a 32-bit floating point type.

jit_type_float64
     Represents a 64-bit floating point type.

jit_type_nfloat
     Represents a floating point type that represents the greatest precision supported on the native platform.

jit_type_void_ptr
     Represents the system's void * type.  This can be used wherever a native pointer type is required.

Type descriptors are reference counted.  You can make a copy of a type descriptor using the jit_type_copy function, and free the copy with jit_type_free.

Some languages have special versions of the primitive numeric types (e.g. boolean types, 16-bit Unicode character types, enumerations, etc). If it is important to distinguish these special versions from the numeric types, then you should use the jit_type_create_tagged function below.

The following types correspond to the system types on the local platform.  i.e. jit_type_sys_int will be the same size as long on the local platform, whereas jit_type_long is always 64 bits in size.  These types should not be used to compile code that is intended to work identically on all platforms:

jit_type_sys_bool
     Corresponds to the system bool type.

jit_type_sys_char
     Corresponds to the system char type.  This may be either signed or unsigned, depending upon the underlying system.

jit_type_sys_schar
     Corresponds to the system signed char type.

jit_type_sys_uchar
     Corresponds to the system unsigned char type.

jit_type_sys_short
     Corresponds to the system short type.

jit_type_sys_ushort
     Corresponds to the system unsigned short type.

jit_type_sys_int
     Corresponds to the system int type.

jit_type_sys_uint
     Corresponds to the system unsigned int type.

jit_type_sys_long
     Corresponds to the system long type.

jit_type_sys_ulong
     Corresponds to the system unsigned long type.

jit_type_sys_longlong
     Corresponds to the system long long type (__int64 under Win32).

jit_type_sys_ulonglong
     Corresponds to the system unsigned long long type (unsigned __int64 under Win32).

jit_type_sys_float
     Corresponds to the system float type.

jit_type_sys_double
     Corresponds to the system double type.

jit_type_sys_long_double
     Corresponds to the system long double type.

 -- Function: jit_type_t jit_type_copy (jit_type_t TYPE)
     Make a copy of the type descriptor TYPE by increasing its reference count.

 -- Function: void jit_type_free (jit_type_t TYPE)
     Free a type descriptor by decreasing its reference count. This function is safe to use on pre-defined types, which are never actually freed.

 -- Function: jit_type_t jit_type_create_struct (jit_type_t *FIELDS, unsigned int NUM_FIELDS, int INCREF)
     Create a type descriptor for a structure.  Returns NULL if out of memory. If there are no fields, then the size of the structure will be zero. It is necessary to add a padding field if the language does not allow zero-sized structures.  The reference counts on the field types are incremented if INCREF is non-zero.

     The libjit library does not provide any special support for implementing structure inheritance, where one structure extends the definition of another.  The effect of inheritance can be achieved by always allocating the first field of a structure to be an instance of the inherited structure.  Multiple inheritance can be supported by allocating several special fields at the front of an inheriting structure.

     Similarly, no special support is provided for vtables.  The program is responsible for allocating an appropriate slot in a structure to contain the vtable pointer, and dereferencing it wherever necessary. The vtable will itself be a structure, containing signature types for each of the method slots.

     The choice not to provide special support for inheritance and vtables in libjit was deliberate.  The layout of objects and vtables is highly specific to the language and virtual machine being emulated, and no single scheme can hope to capture all possibilities.

 -- Function: jit_type_t jit_type_create_union (jit_type_t *FIELDS, unsigned int NUM_FIELDS, int INCREF)
     Create a type descriptor for a union.  Returns NULL if out of memory. If there are no fields, then the size of the union will be zero. It is necessary to add a padding field if the language does not allow zero-sized unions.  The reference counts on the field types are incremented if INCREF is non-zero.

 -- Function: jit_type_t jit_type_create_signature (jit_abi_t ABI, jit_type_t RETURN_TYPE, jit_type_t *PARAMS, unsigned int NUM_PARAMS, int INCREF)
     Create a type descriptor for a function signature.  Returns NULL if out of memory.  The reference counts on the component types are incremented if INCREF is non-zero.

     When used as a structure or union field, function signatures are laid out like pointers.  That is, they represent a pointer to a function that has the specified parameters and return type.

     The ABI parameter specifies the Application Binary Interface (ABI) that the function uses.  It may be one of the following values:

     jit_abi_cdecl
          Use the native C ABI definitions of the underlying platform.

     jit_abi_vararg
          Use the native C ABI definitions of the underlying platform, and allow for an optional list of variable argument parameters.

     jit_abi_stdcall
          Use the Win32 STDCALL ABI definitions, whereby the callee pops its arguments rather than the caller.  If the platform does not support this type of ABI, then jit_abi_stdcall will be identical to jit_abi_cdecl.

     jit_abi_fastcall
          Use the Win32 FASTCALL ABI definitions, whereby the callee pops its arguments rather than the caller, and the first two word arguments are passed in ECX and EDX.  If the platform does not support this type of ABI, then jit_abi_fastcall will be identical to jit_abi_cdecl.

 -- Function: jit_type_t jit_type_create_pointer (jit_type_t TYPE, int INCREF)
     Create a type descriptor for a pointer to another type.  Returns NULL if out of memory.  The reference count on TYPE is incremented if INCREF is non-zero.

 -- Function: jit_type_t jit_type_create_tagged (jit_type_t TYPE, int KIND, void *DATA, jit_meta_free_func FREE_FUNC, int INCREF)
     Tag a type with some additional user data.  Tagging is typically used by higher-level programs to embed extra information about a type that libjit itself does not support.

     As an example, a language might have a 16-bit Unicode character type and a 16-bit unsigned integer type that are distinct types, even though they share the same fundamental representation (jit_ushort). Tagging allows the program to distinguish these two types, when it is necessary to do so, without affecting libjit's ability to compile the code efficiently.

     The KIND is a small positive integer value that the program can use to distinguish multiple tag types.  The DATA pointer is the actual data that you wish to store.  And FREE_FUNC is a function that is used to free DATA when the type is freed with jit_type_free.

     If you need to store more than one piece of information, you can tag a type multiple times.  The order in which multiple tags are applied is irrelevant to libjit, although it may be relevant to the higher-level program.

     Tag kinds of 10000 or greater are reserved for libjit itself. The following special tag kinds are currently provided in the base implementation:

     JIT_TYPETAG_NAME
          The DATA pointer is a char * string indicating a friendly name to display for the type.

     JIT_TYPETAG_STRUCT_NAME
     JIT_TYPETAG_UNION_NAME
     JIT_TYPETAG_ENUM_NAME
          The DATA pointer is a char * string indicating a friendly name to display for a struct, union, or enum type. This is for languages like C that have separate naming scopes for typedef's and structures.

     JIT_TYPETAG_CONST
          The underlying value is assumed to have const semantics. The libjit library doesn't enforce such semantics: it is up to the front-end to only use constant values in appopriate contexts.

     JIT_TYPETAG_VOLATILE
          The underlying value is assumed to be volatile.  The libjit library will automatically call jit_value_set_volatile when a value is constructed using this type.

     JIT_TYPETAG_REFERENCE
          The underlying value is a pointer, but it is assumed to refer to a pass-by-reference parameter.

     JIT_TYPETAG_OUTPUT
          This is similar to JIT_TYPETAG_REFERENCE, except that the underlying parameter is assumed to be output-only.

     JIT_TYPETAG_RESTRICT
          The underlying type is marked as restrict.  Normally ignored.

     JIT_TYPETAG_SYS_BOOL
     JIT_TYPETAG_SYS_CHAR
     JIT_TYPETAG_SYS_SCHAR
     JIT_TYPETAG_SYS_UCHAR
     JIT_TYPETAG_SYS_SHORT
     JIT_TYPETAG_SYS_USHORT
     JIT_TYPETAG_SYS_INT
     JIT_TYPETAG_SYS_UINT
     JIT_TYPETAG_SYS_LONG
     JIT_TYPETAG_SYS_ULONG
     JIT_TYPETAG_SYS_LONGLONG
     JIT_TYPETAG_SYS_ULONGLONG
     JIT_TYPETAG_SYS_FLOAT
     JIT_TYPETAG_SYS_DOUBLE
     JIT_TYPETAG_SYS_LONGDOUBLE
          Used to mark types that we know for a fact correspond to the system C types of the corresponding names.  This is primarily used to distinguish system types like int and long types on 32-bit platforms when it is necessary to do so.  The jit_type_sys_xxx values are all tagged in this manner.

 -- Function: int jit_type_set_names (jit_type_t TYPE, char **NAMES, unsigned int NUM_NAMES)
     Set the field or parameter names for TYPE.  Returns zero if there is insufficient memory to set the names.

     Normally fields are accessed via their index.  Field names are a convenience for front ends that prefer to use names to indices.

 -- Function: void jit_type_set_size_and_alignment (jit_type_t TYPE, jit_nint SIZE, jit_nint ALIGNMENT)
     Set the size and alignment information for a structure or union type.  Use this for performing explicit type layout.  Normally the size is computed automatically.  Ignored if not a structure or union type.  Setting either value to -1 will cause that value to be computed automatically.

 -- Function: void jit_type_set_offset (jit_type_t TYPE, unsigned int FIELD_INDEX, jit_nuint OFFSET)
     Set the offset of a specific structure field.  Use this for performing explicit type layout.  Normally the offset is computed automatically.  Ignored if not a structure type, or the field index is out of range.

 -- Function: int jit_type_get_kind (jit_type_t TYPE)
     Get a value that indicates the kind of TYPE.  This allows callers to quickly classify a type to determine how it should be handled further.

     JIT_TYPE_INVALID
          The value of the TYPE parameter is NULL.

     JIT_TYPE_VOID
          The type is jit_type_void.

     JIT_TYPE_SBYTE
          The type is jit_type_sbyte.

     JIT_TYPE_UBYTE
          The type is jit_type_ubyte.

     JIT_TYPE_SHORT
          The type is jit_type_short.

     JIT_TYPE_USHORT
          The type is jit_type_ushort.

     JIT_TYPE_INT
          The type is jit_type_int.

     JIT_TYPE_UINT
          The type is jit_type_uint.

     JIT_TYPE_NINT
          The type is jit_type_nint.

     JIT_TYPE_NUINT
          The type is jit_type_nuint.

     JIT_TYPE_LONG
          The type is jit_type_long.

     JIT_TYPE_ULONG
          The type is jit_type_ulong.

     JIT_TYPE_FLOAT32
          The type is jit_type_float32.

     JIT_TYPE_FLOAT64
          The type is jit_type_float64.

     JIT_TYPE_NFLOAT
          The type is jit_type_nfloat.

     JIT_TYPE_STRUCT
          The type is the result of calling jit_type_create_struct.

     JIT_TYPE_UNION
          The type is the result of calling jit_type_create_union.

     JIT_TYPE_SIGNATURE
          The type is the result of calling jit_type_create_signature.

     JIT_TYPE_PTR
          The type is the result of calling jit_type_create_pointer.

     If this function returns JIT_TYPE_FIRST_TAGGED or higher, then the type is tagged and its tag kind is the return value minus JIT_TYPE_FIRST_TAGGED.  That is, the following two expressions will be identical if TYPE is tagged:

          jit_type_get_tagged_kind(type)
          jit_type_get_kind(type) - JIT_TYPE_FIRST_TAGGED

 -- Function: jit_nuint jit_type_get_size (jit_type_t TYPE)
     Get the size of a type in bytes.

 -- Function: jit_nuint jit_type_get_alignment (jit_type_t TYPE)
     Get the alignment of a type.  An alignment value of 2 indicates that the type should be aligned on a two-byte boundary, for example.

 -- Function: unsigned int jit_type_num_fields (jit_type_t TYPE)
     Get the number of fields in a structure or union type.

 -- Function: jit_type_t jit_type_get_field (jit_type_t TYPE, unsigned int FIELD_INDEX)
     Get the type of a specific field within a structure or union. Returns NULL if not a structure or union, or the index is out of range.

 -- Function: jit_nuint jit_type_get_offset (jit_type_t TYPE, unsigned int FIELD_INDEX)
     Get the offset of a specific field within a structure. Returns zero if not a structure, or the index is out of range, so this is safe to use on non-structure types.

 -- Function: const char * jit_type_get_name (jit_type_t TYPE, unsigned int INDEX)
     Get the name of a structure, union, or signature field/parameter. Returns NULL if not a structure, union, or signature, the index is out of range, or there is no name associated with the component.

 -- Function: unsigned int jit_type_find_name (jit_type_t TYPE, const char *NAME)
     Find the field/parameter index for a particular name.  Returns JIT_INVALID_NAME if the name was not present.

 -- Function: unsigned int jit_type_num_params (jit_type_t TYPE)
     Get the number of parameters in a signature type.

 -- Function: jit_type_t jit_type_get_return (jit_type_t TYPE)
     Get the return type from a signature type.  Returns NULL if not a signature type.

 -- Function: jit_type_t jit_type_get_param (jit_type_t TYPE, unsigned int PARAM_INDEX)
     Get a specific parameter from a signature type.  Returns NULL if not a signature type or the index is out of range.

 -- Function: jit_abi_t jit_type_get_abi (jit_type_t TYPE)
     Get the ABI code from a signature type.  Returns jit_abi_cdecl if not a signature type.

 -- Function: jit_type_t jit_type_get_ref (jit_type_t TYPE)
     Get the type that is referred to by a pointer type.  Returns NULL if not a pointer type.

 -- Function: jit_type_t jit_type_get_tagged_type (jit_type_t TYPE)
     Get the type that underlies a tagged type.  Returns NULL if not a tagged type.

 -- Function: void jit_type_set_tagged_type (jit_type_t TYPE, jit_type_t UNDERLYING, int INCREF)
     Set the type that underlies a tagged type.  Ignored if TYPE is not a tagged type.  If TYPE already has an underlying type, then the original is freed.  The reference count on UNDERLYING is incremented if INCREF is non-zero.

     This function is typically used to flesh out the body of a forward-declared type.  The tag is used as a placeholder until the definition can be located.

 -- Function: int jit_type_get_tagged_kind (jit_type_t TYPE)
     Get the kind of tag that is applied to a tagged type.  Returns -1 if not a tagged type.

 -- Function: void * jit_type_get_tagged_data (jit_type_t TYPE)
     Get the user data is associated with a tagged type.  Returns NULL if not a tagged type.

 -- Function: void jit_type_set_tagged_data (jit_type_t TYPE, void *DATA, jit_meta_free_func FREE_FUNC)
     Set the user data is associated with a tagged type.  The original data, if any, is freed.

 -- Function: int jit_type_is_primitive (jit_type_t TYPE)
     Determine if a type is primitive.

 -- Function: int jit_type_is_struct (jit_type_t TYPE)
     Determine if a type is a structure.

 -- Function: int jit_type_is_union (jit_type_t TYPE)
     Determine if a type is a union.

 -- Function: int jit_type_is_signature (jit_type_t TYPE)
     Determine if a type is a function signature.

 -- Function: int jit_type_is_pointer (jit_type_t TYPE)
     Determine if a type is a pointer.

 -- Function: int jit_type_is_tagged (jit_type_t TYPE)
     Determine if a type is a tagged type.

 -- Function: jit_nuint jit_type_best_alignment (void)
     Get the best alignment value for this platform.

 -- Function: jit_type_t jit_type_normalize (jit_type_t TYPE)
     Normalize a type to its basic numeric form.  e.g. "jit_type_nint" is turned into "jit_type_int" or "jit_type_long", depending upon the underlying platform.  Pointers are normalized like "jit_type_nint". If the type does not have a normalized form, it is left unchanged.

     Normalization is typically used prior to applying a binary numeric instruction, to make it easier to determine the common type. It will also remove tags from the specified type.

 -- Function: jit_type_t jit_type_remove_tags (jit_type_t TYPE)
     Remove tags from a type, and return the underlying type. This is different from normalization, which will also collapses native types to their basic numeric counterparts.

 -- Function: jit_type_t jit_type_promote_int (jit_type_t TYPE)
     If TYPE is jit_type_sbyte or jit_type_short, then return jit_type_int.  If TYPE is jit_type_ubyte or jit_type_ushort, then return jit_type_uint.  Otherwise return TYPE as-is.

 -- Function: int jit_type_return_via_pointer (jit_type_t TYPE)
     Determine if a type should be returned via a pointer if it appears as the return type in a signature.

 -- Function: int jit_type_has_tag (jit_type_t TYPE, int KIND)
     Determine if TYPE has a specific kind of tag.  This will resolve multiple levels of tagging.