/** ** @file mruby/irep.h - mrb_irep structure ** ** See Copyright Notice in mruby.h */ #ifndef MRUBY_IREP_H #define MRUBY_IREP_H #include "common.h" #include /** * Compiled mruby scripts. */ MRB_BEGIN_DECL enum irep_pool_type { IREP_TT_STR = 0, /* string (need free) */ IREP_TT_SSTR = 2, /* string (static) */ IREP_TT_INT32 = 1, /* 32-bit integer */ IREP_TT_INT64 = 3, /* 64-bit integer */ IREP_TT_BIGINT = 7, /* big integer (not yet supported) */ IREP_TT_FLOAT = 5, /* float (double/float) */ }; #define IREP_TT_NFLAG 1 /* number (non string) flag */ #define IREP_TT_SFLAG 2 /* static string flag */ typedef struct mrb_irep_pool { uint32_t tt; /* packed type and length (for string) */ union { const char *str; int32_t i32; int64_t i64; #ifndef MRB_NO_FLOAT mrb_float f; #endif } u; } mrb_irep_pool; enum mrb_catch_type { MRB_CATCH_RESCUE = 0, MRB_CATCH_ENSURE = 1, }; struct mrb_irep_catch_handler { uint8_t type; /* enum mrb_catch_type */ uint8_t begin[4]; /* The starting address to match the handler. Includes this. */ uint8_t end[4]; /* The endpoint address that matches the handler. Not Includes this. */ uint8_t target[4]; /* The address to jump to if a match is made. */ }; /* Program data array struct */ struct mrb_irep { uint16_t nlocals; /* Number of local variables */ uint16_t nregs; /* Number of register variables */ uint16_t clen; /* Number of catch handlers */ uint8_t flags; const mrb_code *iseq; /* * A catch handler table is placed after the iseq entity. * The reason it doesn't add fields to the structure is to keep the mrb_irep * structure from bloating. The catch handler table can be obtained with * `mrb_irep_catch_handler_table(irep)`. */ const mrb_irep_pool *pool; const mrb_sym *syms; const struct mrb_irep *const *reps; const mrb_sym *lv; /* debug info */ struct mrb_irep_debug_info *debug_info; uint32_t ilen; uint16_t plen, slen; uint16_t rlen; uint16_t refcnt; }; #define MRB_ISEQ_NO_FREE 1 #define MRB_IREP_NO_FREE 2 #define MRB_IREP_STATIC (MRB_ISEQ_NO_FREE | MRB_IREP_NO_FREE) #define MRB_IREP_CONSOLIDATED 4 /* pool/syms/reps packed with irep struct */ MRB_API mrb_irep *mrb_add_irep(mrb_state *mrb); /** * load mruby bytecode functions * * Please note! Currently due to interactions with the GC calling these * functions will leak one RProc object per function call. To prevent this save * the current memory arena before calling and restore the arena right after, * like so * * int ai = mrb_gc_arena_save(mrb); * mrb_value status = mrb_load_irep(mrb, buffer); * mrb_gc_arena_restore(mrb, ai); * * Also, when called from a C function defined as a method, the current stack is * destroyed. If processing continues after this function, the objects obtained * from the arguments must be protected as needed before this function. */ /* @param [const uint8_t*] irep code, expected as a literal */ MRB_API mrb_value mrb_load_irep(mrb_state *, const uint8_t *); /* * @param [const void*] irep code * @param [size_t] size of irep buffer. */ MRB_API mrb_value mrb_load_irep_buf(mrb_state *, const void *, size_t); /* @param [const uint8_t*] irep code, expected as a literal */ MRB_API mrb_value mrb_load_irep_cxt(mrb_state *, const uint8_t *, mrbc_context *); /* * @param [const void*] irep code * @param [size_t] size of irep buffer. */ MRB_API mrb_value mrb_load_irep_buf_cxt(mrb_state *, const void *, size_t, mrbc_context *); struct mrb_insn_data { uint8_t insn; uint32_t a; uint16_t b; uint16_t c; const mrb_code *addr; }; #define mrb_irep_catch_handler_pack(n, v) uint32_to_bin(n, v) #define mrb_irep_catch_handler_unpack(v) bin_to_uint32(v) void mrb_irep_incref(mrb_state *, struct mrb_irep *); void mrb_irep_decref(mrb_state *, struct mrb_irep *); void mrb_irep_cutref(mrb_state *, struct mrb_irep *); MRB_END_DECL #endif /* MRUBY_IREP_H */