1 /*
2  * This file is part of DGD, https://github.com/dworkin/dgd
3  * Copyright (C) 1993-2010 Dworkin B.V.
4  * Copyright (C) 2010-2013 DGD Authors (see the commit log for details)
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Affero General Public License as
8  * published by the Free Software Foundation, either version 3 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 # define I_INSTR_MASK		0x1f	/* instruction mask */
21 
22 # define II_PUSH_ZERO		  0
23 # define II_PUSH_ONE		  1
24 # define II_PUSH_INT1		  2	/* 1 signed */
25 # define II_PUSH_INT4		  3	/* 4 signed */
26 # define II_PUSH_FLOAT		  4	/* 6 unsigned */
27 # define II_PUSH_STRING		  5	/* 1 unsigned */
28 # define II_PUSH_NEAR_STRING	  6	/* 1 unsigned, 1 unsigned */
29 # define II_PUSH_FAR_STRING	  7	/* 1 unsigned, 2 unsigned */
30 # define II_PUSH_LOCAL		  8	/* 1 signed */
31 # define II_PUSH_GLOBAL		  9	/* 1 unsigned */
32 # define II_PUSH_FAR_GLOBAL	 10	/* 1 unsigned, 1 unsigned */
33 # define II_PUSH_LOCAL_LVAL	 11	/* 1 signed */
34 # define II_PUSH_GLOBAL_LVAL	 12	/* 1 unsigned */
35 # define II_PUSH_FAR_GLOBAL_LVAL 13	/* 1 unsigned, 1 unsigned */
36 # define II_INDEX		 14
37 # define II_INDEX_LVAL		 15
38 # define II_AGGREGATE		 16	/* 1 unsigned, 2 unsigned */
39 # define II_SPREAD		 17	/* 1 signed */
40 # define II_CAST		 18	/* 1 unsigned */
41 # define II_DUP			 19
42 # define II_STORE		 20
43 # define II_JUMP		 21	/* 2 unsigned */
44 # define II_JUMP_ZERO		 22	/* 2 unsigned */
45 # define II_JUMP_NONZERO	 23	/* 2 unsigned */
46 # define II_SWITCH		 24	/* n */
47 # define II_CALL_KFUNC		 25	/* 1 unsigned (+ 1 unsigned) */
48 # define II_CALL_AFUNC		 26	/* 1 unsigned, 1 unsigned */
49 # define II_CALL_DFUNC		 27	/* 1 unsigned, 1 unsigned, 1 unsigned */
50 # define II_CALL_FUNC		 28	/* 2 unsigned, 1 unsigned */
51 # define II_CATCH		 29	/* 2 unsigned */
52 # define II_RLIMITS		 30
53 # define II_RETURN		 31
54 
55 # define I_EINSTR_MASK		0x3f	/* extended instruction mask */
56 
57 # define I_PUSH_INT1		0x00	/* 1 signed */
58 # define I_PUSH_INT2		0x20	/* 2 signed */
59 # define I_PUSH_INT4		0x01	/* 4 signed */
60 # define I_PUSH_INT8		0x21	/* reserved */
61 # define I_PUSH_FLOAT6		0x03	/* 6 unsigned */
62 # define I_PUSH_FLOAT12		0x23	/* reserved */
63 # define I_PUSH_STRING		0x04	/* 1 unsigned */
64 # define I_PUSH_NEAR_STRING	0x24	/* 1 unsigned, 1 unsigned */
65 # define I_PUSH_FAR_STRING	0x05	/* 1 unsigned, 2 unsigned */
66 # define I_PUSH_LOCAL		0x25	/* 1 signed */
67 # define I_PUSH_GLOBAL		0x06	/* 1 unsigned */
68 # define I_PUSH_FAR_GLOBAL	0x26	/* 1 unsigned, 1 unsigned */
69 # define I_INDEX		0x07
70 # define I_INDEX2		0x08
71 # define I_SPREAD		0x28	/* 1 signed (+ 1+3 unsigned) */
72 # define I_AGGREGATE		0x09	/* 1 unsigned, 2 unsigned */
73 # define I_CAST			0x0a	/* 1+3 unsigned */
74 # define I_CALL_EFUNC		0x0e	/* 2 unsigned (+ 1 unsigned) */
75 # define I_CALL_CEFUNC		0x0f	/* 2 unsigned, 1 unsigned */
76 # define I_CALL_CKFUNC		0x10	/* 1 unsigned, 1 unsigned */
77 # define I_STORE_LOCAL		0x11	/* 1 signed */
78 # define I_STORE_GLOBAL		0x12	/* 1 unsigned */
79 # define I_STORE_FAR_GLOBAL	0x13	/* 1 unsigned, 1 unsigned */
80 # define I_STORE_INDEX		0x14
81 # define I_STORE_LOCAL_INDEX	0x15	/* 1 signed */
82 # define I_STORE_GLOBAL_INDEX	0x16	/* 1 unsigned, 1 unsigned */
83 # define I_STORE_INDEX_INDEX	0x17
84 # define I_JUMP_ZERO		0x18	/* 2 unsigned */
85 # define I_JUMP_NONZERO		0x38	/* 2 unsigned */
86 # define I_JUMP			0x19	/* 2 unsigned */
87 # define I_SWITCH		0x39	/* n */
88 # define I_CALL_KFUNC		0x1a	/* 1 unsigned (+ 1 unsigned) */
89 # define I_CALL_AFUNC		0x1b	/* 1 unsigned, 1 unsigned */
90 # define I_CALL_DFUNC		0x1c	/* 1 unsigned, 1 unsigned, 1 unsigned */
91 # define I_CALL_FUNC		0x1d	/* 2 unsigned, 1 unsigned */
92 # define I_CATCH		0x1e	/* 2 unsigned */
93 # define I_RLIMITS		0x1f
94 # define I_RETURN		0x3f
95 
96 # define I_LINE_MASK		0xc0	/* line add bits */
97 # define I_POP_BIT		0x20	/* pop 1 after instruction */
98 # define I_TYPE_BIT		I_POP_BIT /* lvalue typechecks assignment */
99 # define I_LINE_SHIFT		6
100 
101 # define LVAL_LOCAL		0
102 # define LVAL_GLOBAL		1
103 # define LVAL_INDEX		2
104 # define LVAL_LOCAL_INDEX	3
105 # define LVAL_GLOBAL_INDEX	4
106 # define LVAL_INDEX_INDEX	5
107 
108 
109 # define FETCH1S(pc)	SCHAR(*(pc)++)
110 # define FETCH1U(pc)	UCHAR(*(pc)++)
111 # define FETCH2S(pc, v)	((short) (v = *(pc)++ << 8, v |= UCHAR(*(pc)++)))
112 # define FETCH2U(pc, v)	((unsigned short) (v = *(pc)++ << 8, \
113 					   v |= UCHAR(*(pc)++)))
114 # define FETCH3S(pc, v)	((Int) (v = *(pc)++ << 8, \
115 				v |= UCHAR(*(pc)++), v <<= 8, \
116 				v |= UCHAR(*(pc)++)))
117 # define FETCH3U(pc, v)	((Uint) (v = UCHAR(*(pc)++) << 8, \
118 				 v |= UCHAR(*(pc)++), v <<= 8, \
119 				 v |= UCHAR(*(pc)++)))
120 # define FETCH4S(pc, v)	((Int) (v = *(pc)++ << 8, \
121 				v |= UCHAR(*(pc)++), v <<= 8, \
122 				v |= UCHAR(*(pc)++), v <<= 8, \
123 				v |= UCHAR(*(pc)++)))
124 # define FETCH4U(pc, v)	((Uint) (v = *(pc)++ << 8, \
125 				 v |= UCHAR(*(pc)++), v <<= 8, \
126 				 v |= UCHAR(*(pc)++), v <<= 8, \
127 				 v |= UCHAR(*(pc)++)))
128 
129 
130 # define T_TYPE		0x0f	/* type mask */
131 # define T_NIL		0x00
132 # define T_INT		0x01
133 # define T_FLOAT	0x02
134 # define T_STRING	0x03
135 # define T_OBJECT	0x04
136 # define T_ARRAY	0x05	/* value type only */
137 # define T_MAPPING	0x06
138 # define T_LWOBJECT	0x07	/* runtime only */
139 # define T_CLASS	0x07	/* typechecking only */
140 # define T_MIXED	0x08	/* declaration type only */
141 # define T_VOID		0x09	/* function return type only */
142 # define T_LVALUE	0x0a	/* address of a value */
143 # define T_SLVALUE	0x0b	/* indexed string lvalue */
144 # define T_ALVALUE	0x0c	/* indexed array lvalue */
145 # define T_MLVALUE	0x0d	/* indexed mapping lvalue */
146 # define T_SALVALUE	0x0e	/* indexed string indexed array lvalue */
147 # define T_SMLVALUE	0x0f	/* indexed string indexed mapping lvalue */
148 
149 # define T_VARARGS	0x10	/* or'ed with declaration type */
150 # define T_ELLIPSIS	0x10	/* or'ed with declaration type */
151 
152 # define T_REF		0xf0	/* reference count mask */
153 # define REFSHIFT	4
154 
155 # define T_ARITHMETIC(t) ((t) <= T_FLOAT)
156 # define T_ARITHSTR(t)	((t) <= T_STRING)
157 # define T_POINTER(t)	((t) >= T_STRING)
158 # define T_INDEXED(t)	((t) >= T_ARRAY)   /* T_ARRAY, T_MAPPING, T_LWOBJECT */
159 
160 # define TYPENAMES	{ "nil", "int", "float", "string", "object", \
161 			  "array", "mapping", "object", "mixed", "void" }
162 # define TNBUFSIZE	24
163 
164 # define VAL_NIL(v)	((v)->type == nil_type && (v)->u.number == 0)
165 # define VAL_TRUE(v)	((v)->u.number != 0 || (v)->type > T_FLOAT ||	\
166 			 ((v)->type == T_FLOAT && (v)->oindex != 0))
167 
168 # define PUSH_INTVAL(f, i)	((--(f)->sp)->u.number = (i),		\
169 				 (f)->sp->type = T_INT)
170 # define PUT_INTVAL(v, i)	((v)->u.number = (i), (v)->type = T_INT)
171 # define PUT_INT(v, i)		((v)->u.number = (i))
172 # define PUSH_FLTVAL(f, fl)	((--(f)->sp)->oindex = (fl).high,	\
173 				 (f)->sp->u.objcnt = (fl).low,		\
174 				 (f)->sp->type = T_FLOAT)
175 # define PUSH_FLTCONST(f, h, l)	((--(f)->sp)->oindex = (h),		\
176 				 (f)->sp->u.objcnt = (l),		\
177 				 (f)->sp->type = T_FLOAT)
178 # define PUT_FLTVAL(v, fl)	((v)->oindex = (fl).high,		\
179 				 (v)->u.objcnt = (fl).low,		\
180 				 (v)->type = T_FLOAT)
181 # define PUT_FLT(v, fl)		((v)->oindex = (fl).high,		\
182 				 (v)->u.objcnt = (fl).low)
183 # define GET_FLT(v, fl)		((fl).high = (v)->oindex,		\
184 				 (fl).low = (v)->u.objcnt)
185 # define PUSH_STRVAL(f, s)	(str_ref((--(f)->sp)->u.string = (s)),	\
186 				 (f)->sp->type = T_STRING)
187 # define PUT_STRVAL(v, s)	(str_ref((v)->u.string = (s)),		\
188 				 (v)->type = T_STRING)
189 # define PUT_STRVAL_NOREF(v, s)	((v)->u.string = (s), (v)->type = T_STRING)
190 # define PUT_STR(v, s)		(str_ref((v)->u.string = (s)))
191 # define PUSH_OBJVAL(f, o)	((--(f)->sp)->oindex = (o)->index,	\
192 				 (f)->sp->u.objcnt = (o)->count,	\
193 				 (f)->sp->type = T_OBJECT)
194 # define PUT_OBJVAL(v, o)	((v)->oindex = (o)->index,		\
195 				 (v)->u.objcnt = (o)->count,		\
196 				 (v)->type = T_OBJECT)
197 # define PUT_OBJ(v, o)		((v)->oindex = (o)->index,		\
198 				 (v)->u.objcnt = (o)->count)
199 # define PUSH_ARRVAL(f, a)	(arr_ref((--(f)->sp)->u.array = (a)),	\
200 				 (f)->sp->type = T_ARRAY)
201 # define PUT_ARRVAL(v, a)	(arr_ref((v)->u.array = (a)),		\
202 				 (v)->type = T_ARRAY)
203 # define PUT_ARRVAL_NOREF(v, a)	((v)->u.array = (a), (v)->type = T_ARRAY)
204 # define PUT_ARR(v, a)		(arr_ref((v)->u.array = (a)))
205 # define PUSH_MAPVAL(f, m)	(arr_ref((--(f)->sp)->u.array = (m)),	\
206 				 (f)->sp->type = T_MAPPING)
207 # define PUT_MAPVAL(v, m)	(arr_ref((v)->u.array = (m)),		\
208 				 (v)->type = T_MAPPING)
209 # define PUT_MAPVAL_NOREF(v, m)	((v)->u.array = (m), (v)->type = T_MAPPING)
210 # define PUT_MAP(v, m)		(arr_ref((v)->u.array = (m)))
211 # define PUSH_LWOVAL(f, o)	(arr_ref((--(f)->sp)->u.array = (o)),	\
212 				 (f)->sp->type = T_LWOBJECT)
213 # define PUT_LWOVAL(v, o)	(arr_ref((v)->u.array = (o)),		\
214 				 (v)->type = T_LWOBJECT)
215 # define PUT_LWOVAL_NOREF(v, o)	((v)->u.array = (o), (v)->type = T_LWOBJECT)
216 # define PUT_LWO(v, o)		(arr_ref((v)->u.array = (o)))
217 
218 # define VFLT_ISZERO(v)	FLT_ISZERO((v)->oindex, (v)->u.objcnt)
219 # define VFLT_ISONE(v)	FLT_ISONE((v)->oindex, (v)->u.objcnt)
220 # define VFLT_HASH(v)	((v)->oindex ^ (v)->u.objcnt)
221 
222 # define DESTRUCTED(v)	(OBJR((v)->oindex)->count != (v)->u.objcnt)
223 
224 
225 # define C_PRIVATE	0x01
226 # define C_STATIC	0x02
227 # define C_NOMASK	0x04
228 # define C_ELLIPSIS	0x08
229 # define C_VARARGS	0x08
230 # define C_ATOMIC	0x10
231 # define C_TYPECHECKED	0x20
232 # define C_COMPILED	0x40
233 # define C_UNDEFINED	0x80
234 
235 
236 # define SWITCH_INT	0
237 # define SWITCH_RANGE	1
238 # define SWITCH_STRING	2
239 
240 
241 typedef struct _rlinfo_ {
242     Int maxdepth;		/* max stack depth */
243     Int ticks;			/* ticks left */
244     bool nodepth;		/* no stack depth checking */
245     bool noticks;		/* no ticks checking */
246     struct _rlinfo_ *next;	/* next in linked list */
247 } rlinfo;
248 
249 struct _frame_ {
250     frame *prev;		/* previous stack frame */
251     uindex oindex;		/* current object index */
252     array *lwobj;		/* lightweight object */
253     control *ctrl;		/* object control block */
254     dataspace *data;		/* dataspace of current object */
255     control *p_ctrl;		/* program control block */
256     unsigned short p_index;	/* program index */
257     unsigned short nargs;	/* # arguments */
258     bool external;		/* TRUE if it's an external call */
259     bool sos;			/* stack on stack */
260     uindex foffset;		/* program function offset */
261     struct _dfuncdef_ *func;	/* current function */
262     char *prog;			/* start of program */
263     char *pc;			/* program counter */
264     value *stack;		/* local value stack */
265     value *sp;			/* stack pointer */
266     value *lip;			/* lvalue index pointer */
267     value *argp;		/* argument pointer (previous sp) */
268     value *fp;			/* frame pointer (at end of local stack) */
269     Int depth;			/* stack depth */
270     rlinfo *rlim;		/* rlimits info */
271     Int level;			/* plane level */
272     bool atomic;		/* within uncaught atomic code */
273 };
274 
275 extern void	i_init		(char*, int);
276 extern void	i_ref_value	(value*);
277 extern void	i_del_value	(value*);
278 extern void	i_copy		(value*, value*, unsigned int);
279 extern void	i_grow_stack	(frame*, int);
280 extern void	i_push_value	(frame*, value*);
281 extern void	i_pop		(frame*, int);
282 extern value   *i_reverse	(frame*, int);
283 extern void	i_odest		(frame*, object*);
284 extern void	i_string	(frame*, int, unsigned int);
285 extern void	i_aggregate	(frame*, unsigned int);
286 extern void	i_map_aggregate	(frame*, unsigned int);
287 extern int	i_spread	(frame*, int, int, Uint);
288 extern void	i_global	(frame*, int, int);
289 extern void	i_global_lvalue	(frame*, int, int, int, Uint);
290 extern void	i_index		(frame*);
291 extern void	i_index2	(frame*, value*, value*, value*);
292 extern void	i_index_lvalue	(frame*, int, Uint);
293 extern char    *i_typename	(char*, unsigned int);
294 extern char    *i_classname	(frame*, Uint);
295 extern int	i_instanceof	(frame*, unsigned int, Uint);
296 extern void	i_cast		(frame*, value*, unsigned int, Uint);
297 extern void	i_dup		(frame*);
298 extern void	i_store_global	(frame*, int, int, value*, value*);
299 extern bool	i_store_index	(frame*, value*, value*, value*, value*);
300 extern void	i_store		(frame*);
301 extern Int	i_get_depth	(frame*);
302 extern Int	i_get_ticks	(frame*);
303 extern void	i_new_rlimits	(frame*, Int, Int);
304 extern void	i_set_rlimits	(frame*, rlinfo*);
305 extern frame   *i_set_sp	(frame*, value*);
306 extern frame   *i_prev_object	(frame*, int);
307 extern char    *i_prev_program	(frame*, int);
308 extern void	i_typecheck	(frame*, frame*, char*, char*, char*, int,
309 				   int);
310 extern void	i_catcherr	(frame*, Int);
311 extern void	i_funcall	(frame*, object*, array*, int, int, int);
312 extern bool	i_call		(frame*, object*, array*, char*, unsigned int,
313 				   int, int);
314 extern bool	i_call_tracei	(frame*, Int, value*);
315 extern array   *i_call_trace	(frame*);
316 extern bool	i_call_critical	(frame*, char*, int, int);
317 extern void	i_runtime_error	(frame*, Int);
318 extern void	i_atomic_error	(frame*, Int);
319 extern frame   *i_restore	(frame*, Int);
320 extern void	i_clear		(void);
321 
322 extern frame *cframe;
323 extern int nil_type;
324 extern value zero_int, zero_float, nil_value;
325 
326 # define i_add_ticks(f, t)	((f)->rlim->ticks -= (t))
327