this system allows dialects to register named interfaces, which are collections of function
pointers. an op can then implement this interface, providing callbacks for the interface's
virtual function pointers.
C code can request a pointer to an op's implementation of a given interface and call
virtual functions with no knowledge required about the op itself. this functonality
will also be extended to types, attributes, and dialects themselves.
under this new system, dialects can define their own custom attributes,
complete with their own print() and parse() callbacks, which can then be
used as values in an op's attribute dictionary.
alongside custom dialect attributes, the former int, float, and string
constant values have been converted to attributes provided by the
arith and builtin dialects respectively. the caches for these attributes
have also been moved from mie_ctx to their respective dialect data
structures.
this system will allow new types of attributes to be implemented,
including dictionaries, arrays, and references to types themselves
(rather than just particular values of a given type).
any struct that contains a mie_name cannot be stored in movable memory
(i.e. any memory that may be re-allocated using realloc(), or whose
contents may be moved to a different buffer).
mie_names form part of a bst when they are added to a mie_name_map,
and moving them after this happens will result in the bst pointers
being invalidated. this causes some obscure and hard-to-debug
memory errors.
all structs that contain a mie_name (including named IR objects like
mie_register and mie_block) are no longer stored directly in vectors.
rather, vectors of pointers are used instead.
unlike values, type-instances represent specialisations of parametised types.
they behave like concrete implementations of C++ template types.
for example: arith.int represents an integer type of unspecified bit-width.
a type-instance of this type would be arith.int<32> (or i32 for short) which
has a defined width of 32 bits.
rather than a traditional dictionary or hashmap, this data structure supports a one-to-one
mapping between a UUID and a value. this is an intrusive data structure like mie_name_map
(a value struct must include an instance of mie_id), but this one does not support name collisions.
mie_id_map generates and issues UUIDs based on a name provided by the caller. All UUIDs are v5,
meaning they are generated using a SHA1 hash of a namespace UUID (specified when the mie_id_map
is initialised), and a unique name provided by the caller.
mie_id can also be used standalone to generate, store, and stringify UUIDs.