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