/* Byte code fragment construction functions */ typedef struct frag Frag; struct frag { unsigned char *start; ptrdiff_t len; ptrdiff_t size; ptrdiff_t align; }; /* Initialize a fragment: 'alignment' sets the naturual alignment of * the fragment. After any emit or fetch function is called, the * fragment is filled to the next multiple of 'alignment'. */ void iz_frag(Frag *, ptrdiff_t alignmnet); void clr_frag(Frag *); /* Generate byte offset you need to add to p so that * it is an exact multiple of size (which is a power of 2). */ #define align_o(p, size) (((size) - 1) & -(ptrdiff_t)(p)) /* Align frag to next multiple of n */ void align_frag(Frag *f, ptrdiff_t n); /* Append data to a fragment: return byte offset to data. * These do two alignments: one before and one after the emit. Before, * it fills the fragment until its size is a multiple of the size of * the emitted data. After the emit, it fills the fragment until its * size is a multiple of the natural alignment specified in iz_frag. */ ptrdiff_t emitb_noalign(Frag *f, char c); ptrdiff_t emitb(Frag *f, char c); ptrdiff_t emith(Frag *f, short n); ptrdiff_t emiti(Frag *f, int n); ptrdiff_t emitd(Frag *f, double d); ptrdiff_t emitp(Frag *f, void *p); ptrdiff_t emits(Frag *f, unsigned char *s, int len); ptrdiff_t emit_branch(Frag *f, ptrdiff_t target); void fixup_branch(Frag *f, ptrdiff_t pos); void frag_link(Frag *f, ptrdiff_t chain); /* Access data in a fragment */ #define fragc(f, ofst) (*((f)->start + (ofst))) #define fragh(f, ofst) (*(short *)((f)->start + (ofst))) #define fragi(f, ofst) (*(int *)((f)->start + (ofst))) #define fragd(f, ofst) (*(double *)((f)->start + (ofst))) #define fragp(f, ofst) (*(void **)((f)->start + (ofst))) /* Fetch an datum from a fragement and advance the "PC" */ int fetchi(Frag *f, ptrdiff_t *pc); short fetchh(Frag *f, ptrdiff_t *pc); void *fetchp(Frag *f, ptrdiff_t *pc); void fin_code(Frag *f);