- optype_t exists on all architectures, but is arch specific. There must be fewer than 32 values in it. (This may be bumped to 64 on all arches if 32 is not enough). - op_t exists on all architectures. It is always a 64 bit integer, where the low 8 bits contain an op_type. The rest of the integer is machine specific - inst_t is a struct that has three mandatory fields: - name - number of ops - for each op, a bit field describing which optypes are acceptable (remember there are only 32 different optypes). It will typically have additional fields describing the encoding of the instruction. Files: - pixman-assembler.h: - includes pixman-arch-assembler.h - declaration of machine_spec_t, which is a struct that describes the machine in question. - declaration of general assembler methods: pixman_assembler_t *_pixman_assembler_create (const machine_spec_t *machine); uint8_t *_pixman_assembler_link (pixman_assembler_t *assembler, pixman_fragment_t *fragment, ...); pixman_fragment_t *_pixman_fragment_new (const machine_spec_t *machine); void pixman_fragment_assemble (fragment_t *fragment, ...); - declaration of stack manager and register allocator void pixman_reg_alloc_init (reg_alloc_t *alloc, stack_man_t *stack_man, const machine_spec *spec, const reg_pool_t *pool); - pixman-assembler.c: - includes pixman-assembler.h - has code to: - based on instruction name, it will find the entry in inst_t that matches the given ops. - locate labels, based on their names - fix up jumps and other relocations it will call out to methods defined in the machine spec. - implementation of register allcoator and stack manager. - pixman--assembler.h contains: - definition of op_type_t, inst_t for the arch in question - definition of op_t for the architecture in question - macros to construct op_t for the architecture in question - declaration of pixman_assembler_create_ - pixman-arch-assembler.c contains - definition of inst_t table - definition of pixman_assembler__create() - definition of machine_spec_t for the architecture, with methods for - how to spill to the stack - how to patch up jumps - definition of register pools - user code will - include pixman-assembler.h - define pixman_reg_pools as it sees fit - call pixman_assembler_create_ - call pixman_reg_alloc_init_ Should all the machine_spec stuff go in the user code? Is there any real difference? Where should the current code-manager.c go? This is platform specific, not machine specific. pixman-assembler.c is tempting. Also, pixman-assembler.[ch] should probably be pixman-jit.[ch] Notes about x86: How to call a statically known function (e.g, memcpy() or malloc()) from JIT compiled code: - In 64 bit mode: The JIT compiled code can end up more than 4GB away from the function, which means a standard call with 32-bit offset is not good enough. Instead we have to do "call RIP_REL(label)", where label refers to a place where the address of the function in question is stored. It might be possible to detect at compile time whether the final generated code would be less than 4GB away, which would allow a call rel32 to be used. It gets a little bit tricky though because the rel32 has a different length, and in general we don't know the final address of the jit compiled code until later. - In 32 bit mode: This is easy: Just do and have the linker fix it up before generating the final code.