This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Initial check-in of perl compiler.
[perl5.git] / bytecode.h
1 typedef char *pvcontents;
2 typedef char *strconst;
3 typedef U32 PV;
4 typedef char *op_tr_array;
5 typedef int comment;
6 typedef SV *svindex;
7 typedef OP *opindex;
8 typedef IV IV64;
9
10 EXT int iv_overflows INIT(0);
11 void *bset_obj_store _((void *, I32));
12 void freadpv _((U32, void *));
13
14 EXT SV *sv;
15 EXT OP *op;
16 EXT XPV pv;
17
18 EXT void **obj_list;
19 EXT I32 obj_list_fill INIT(-1);
20
21 #ifdef INDIRECT_BGET_MACROS
22 #define FREAD(argp, len, nelem) bs.fread((char*)(argp),(len),(nelem),bs.data)
23 #define FGETC() bs.fgetc(bs.data)
24 #else
25 #define FREAD(argp, len, nelem) fread((argp), (len), (nelem), fp)
26 #define FGETC() getc(fp)
27 #endif /* INDIRECT_BGET_MACROS */
28
29 #define BGET_U32(arg)   FREAD(&arg, sizeof(U32), 1); arg = ntohl((U32)arg)
30 #define BGET_I32(arg)   FREAD(&arg, sizeof(I32), 1); arg = (I32)ntohl((U32)arg)
31 #define BGET_U16(arg)   FREAD(&arg, sizeof(U16), 1); arg = ntohs((U16)arg)
32 #define BGET_U8(arg)    arg = FGETC()
33
34 #if INDIRECT_BGET_MACROS
35 #define BGET_PV(arg)    do {            \
36         BGET_U32(arg);                  \
37         if (arg)                        \
38             bs.freadpv(arg, bs.data);   \
39         else {                          \
40             pv.xpv_pv = 0;              \
41             pv.xpv_len = 0;             \
42             pv.xpv_cur = 0;             \
43         }                               \
44     } while (0)
45 #else
46 #define BGET_PV(arg)    do {                    \
47         BGET_U32(arg);                          \
48         if (arg) {                              \
49             New(666, pv.xpv_pv, arg, char);     \
50             fread(pv.xpv_pv, 1, arg, fp);       \
51             pv.xpv_len = arg;                   \
52             pv.xpv_cur = arg - 1;               \
53         } else {                                \
54             pv.xpv_pv = 0;                      \
55             pv.xpv_len = 0;                     \
56             pv.xpv_cur = 0;                     \
57         }                                       \
58     } while (0)
59 #endif /* INDIRECT_BGET_MACROS */
60
61 #define BGET_comment(arg) \
62         do { arg = FGETC(); } while (arg != '\n' && arg != EOF)
63
64 /*
65  * In the following, sizeof(IV)*4 is just a way of encoding 32 on 64-bit-IV
66  * machines such that 32-bit machine compilers don't whine about the shift
67  * count being too high even though the code is never reached there.
68  */
69 #define BGET_IV64(arg) do {                             \
70         U32 hi, lo;                                     \
71         BGET_U32(hi);                                   \
72         BGET_U32(lo);                                   \
73         if (sizeof(IV) == 8)                            \
74             arg = (IV) (hi << (sizeof(IV)*4) | lo);     \
75         else if (((I32)hi == -1 && (I32)lo < 0)         \
76                  || ((I32)hi == 0 && (I32)lo >= 0)) {   \
77             arg = (I32)lo;                              \
78         }                                               \
79         else {                                          \
80             iv_overflows++;                             \
81             arg = 0;                                    \
82         }                                               \
83     } while (0)
84
85 #define BGET_op_tr_array(arg) do {      \
86         unsigned short *ary;            \
87         int i;                          \
88         New(666, ary, 256, unsigned short); \
89         FREAD(ary, 256, 2);             \
90         for (i = 0; i < 256; i++)       \
91             ary[i] = ntohs(ary[i]);     \
92         arg = (char *) ary;             \
93     } while (0)
94
95 #define BGET_pvcontents(arg)    arg = pv.xpv_pv
96 #define BGET_strconst(arg)      do {    \
97         for (arg = tokenbuf; (*arg = FGETC()); arg++) /* nothing */;    \
98         arg = tokenbuf;                 \
99     } while (0)
100
101 #define BGET_double(arg)        do {    \
102         char *str;                      \
103         BGET_strconst(str);             \
104         arg = atof(str);                \
105     } while (0)
106
107 #define BGET_objindex(arg) do { \
108         U32 ix;                 \
109         BGET_U32(ix);           \
110         arg = obj_list[ix];     \
111     } while (0)
112
113 #define BSET_ldspecsv(sv, arg) sv = specialsv_list[arg]
114                                     
115 #define BSET_sv_refcnt_add(svrefcnt, arg)       svrefcnt += arg
116 #define BSET_gp_refcnt_add(gprefcnt, arg)       gprefcnt += arg
117 #define BSET_gp_share(sv, arg)  do {    \
118         gp_free((GV*)sv);               \
119         GvGP(sv) = GvGP(arg);           \
120     } while (0)
121
122 #define BSET_gv_fetchpv(sv, arg)        sv = (SV*)gv_fetchpv(arg, TRUE, SVt_PV)
123 #define BSET_gv_stashpv(sv, arg)        sv = (SV*)gv_stashpv(arg, TRUE)
124 #define BSET_sv_magic(sv, arg)          sv_magic(sv, Nullsv, arg, 0, 0)
125 #define BSET_mg_pv(mg, arg)     mg->mg_ptr = arg; mg->mg_len = pv.xpv_cur
126 #define BSET_sv_upgrade(sv, arg)        (void)SvUPGRADE(sv, arg)
127 #define BSET_xpv(sv)    do {    \
128         SvPV_set(sv, pv.xpv_pv);        \
129         SvCUR_set(sv, pv.xpv_cur);      \
130         SvLEN_set(sv, pv.xpv_len);      \
131     } while (0)
132 #define BSET_av_extend(sv, arg) av_extend((AV*)sv, arg)
133
134 #define BSET_av_push(sv, arg)   av_push((AV*)sv, arg)
135 #define BSET_hv_store(sv, arg)  \
136         hv_store((HV*)sv, pv.xpv_pv, pv.xpv_cur, arg, 0)
137 #define BSET_pv_free(pv)        Safefree(pv.xpv_pv)
138 #define BSET_pregcomp(op, arg) \
139         cPMOP->op_pmregexp = arg ? pregcomp(arg, arg + pv.xpv_cur, cPMOP) : 0
140 #define BSET_newsv(sv, arg)     sv = NEWSV(666,0); SvUPGRADE(sv, arg)
141 #define BSET_newop(op, arg)     op = (OP*)safemalloc(optype_size[arg])
142 #define BSET_newopn(op, arg)    do {    \
143         OP *oldop = op;                 \
144         BSET_newop(op, arg);            \
145         oldop->op_next = op;            \
146     } while (0)
147
148 #define BSET_ret(foo) return
149
150 /*
151  * Kludge special-case workaround for OP_MAPSTART
152  * which needs the ppaddr for OP_GREPSTART. Blech.
153  */
154 #define BSET_op_type(op, arg)   do {    \
155         op->op_type = arg;              \
156         op->op_ppaddr = (arg != OP_MAPSTART) ? ppaddr[arg] : pp_grepstart; \
157     } while (0)
158 #define BSET_op_ppaddr(op, arg) croak("op_ppaddr not yet implemented")
159 #define BSET_curpad(pad, arg) pad = AvARRAY(arg)
160
161 #define BSET_OBJ_STORE(obj, ix)         \
162         (I32)ix > obj_list_fill ?       \
163         bset_obj_store(obj, (I32)ix) : (obj_list[ix] = obj)