1 #ifndef SVALUE_H__
2 #define SVALUE_H__ 1
3 
4 /*---------------------------------------------------------------------------
5  * Stack-value datatypes used by the virtual machine.
6  *
7  *---------------------------------------------------------------------------
8  * This file refers to, but does not define 'basic' types like mappings,
9  * arrays or lambdas.
10  */
11 
12 #include "driver.h"
13 #include "typedefs.h"
14 
15 /* --- Types --- */
16 
17 /* --- union u: the hold-all type ---
18  *
19  * This union is used to hold the data referenced by a svalue.
20  * It contains no type information, which must be provided by the
21  * containing svalue.
22  *
23  * Lots of code assumes that '.number' is big enough to contain the whole
24  * union regardless of its actual content, therefore it is of type 'p_int'.
25  */
26 union u {
27     string_t *str;
28       /* T_STRING: pointer to the string.
29        * T_SYMBOL: pointer to the (shared) symbol string.
30        * T_(PROTECTED_)STRING_RANGE_LVALUE: the target string holding
31        *   the range.
32        */
33     char     *charp;
34       /* T_(PROTECTED_)CHAR_LVALUE: pointer to the referenced character
35        *           (referenced from a T_LVALUE).
36        */
37     p_int number;
38       /* T_NUMBER: the number.
39        */
40     object_t *ob;
41       /* T_OBJECT: pointer to the object structure.
42        * T_CLOSURE: efun-, simul_efun-, operator closures: the object
43        *            the closure is bound to.
44        */
45     vector_t *vec;
46       /* T_POINTER, T_QUOTED_ARRAY: pointer to the vector structure.
47        * T_(PROTECTED_)POINTER_RANGE_LVALUE: the target vector holding
48        *   the range.
49        */
50 #ifdef USE_STRUCTS
51      struct_t *strct;
52       /* T_STRUCT: pointer to the structure instance.
53        */
54 #endif
55     mapping_t *map;
56       /* T_MAPPING: pointer to the mapping structure.
57        * T_PROTECTOR_MAPPING: TODO: ???
58        */
59     lambda_t *lambda;
60       /* T_CLOSURE: allocated closures: the closure structure.
61        */
62     p_int mantissa;
63       /* T_FLOAT: The mantissa (or at least one half of the float bitpattern).
64        */
65     callback_t *cb;
66       /* T_CALLBACK: A callback structure referenced from the stack
67        *   to allow proper cleanup during error recoveries. The interpreter
68        *   knows how to free it, but that's all.
69        */
70 
71     void *generic;
72       /* Use read-only, this member is used to read the svalue generically
73        * as "a pointer". It is mostly used in comparisons.
74        */
75 
76     svalue_t *lvalue;
77       /* T_LVALUE: pointer to a (usually 'normal') svalue which
78        *   this lvalue references. Also, lvalues may be chained through
79        *   this pointer so that only the last lvalue points to the real
80        *   svalue, and the others point to the next lvalue in the chain.
81        *   This is necessary when lvalues are passed around as lfun args.
82        *
83        * For T_LVALUE this may point to one of the protector
84        * structures (see interpret.c) which just 'happen' to have a svalue
85        * as first element. The actual type of the protected svalue is given
86        * by the .type of the referenced protector structure.
87        *
88        * When creating such a protected T_LVALUE, this .lvalue field is set
89        * by assigning one of the following aliases:
90        */
91     struct protected_lvalue *protected_lvalue;
92     struct protected_char_lvalue *protected_char_lvalue;
93     struct protected_range_lvalue *protected_range_lvalue;
94 
95       /* The following fields are used only in svalues referenced by
96        * T_LVALUE svalues:
97        */
98     void (*error_handler) (svalue_t *);
99       /* T_ERROR_HANDLER: this function is
100        * executed on a free_svalue(), receiving the T_ERROR_HANDLER svalue*
101        * as argument. This allows the transparent implemention of cleanup
102        * functions which are called even after runtime errors. In order
103        * to pass additional information to the error_handler(), embed
104        * the T_ERROR_HANDLER svalue into a larger structure (possible since
105        * it has to be referenced by pointer) and let the error_handler()
106        * execute the appropriate casts.
107        */
108 };
109 
110 /* --- struct svalue_s: the LPC data structure ---
111  *
112  * svalues ('stack values)' are used throughout the driver to hold LPC
113  * values. One svalue consists of an instance of union u to hold the
114  * actual value, and a type field describing the type of the value.
115  *
116  * Some values need specific, additional information (e.g. string values
117  * distinguish shared from allocated strings), which is stored in the
118  * union 'x'.
119  *
120  * The T_LVALUE type family is special in that the svalue instance does
121  * not contain the actual value, but instead a reference to another
122  * svalue. lvalues are necessary whenever existing svalue instance
123  * are to be assigned. A special case are protected lvalues where the
124  * svalue referenced by the T_LVALUE.u.lvalue is not the target svalue,
125  * but instead a T_PROTECTED_xxx_LVALUE which then points to the target
126  * and its protector. Similar, indexed and range-indexed lvalues don't
127  * point to the data itself, but instead to one of the dedicated T_xxx_LVALUE
128  * types which contain the necessary information to perform the indexing
129  * operation; effectively limiting the access to the target value to
130  * the view specified by the index/range bounds.
131  *
132  * T_LVALUEs are also used to reference meta data, like T_ERROR_HANDLER
133  * svalues. TODO: Maybe they should get the T_META type.
134  */
135 struct svalue_s
136 {
137     ph_int type;  /* Primary type information */
138     union {       /* Secondary type information */
139         ph_int exponent;     /* Exponent of a T_FLOAT */
140         ph_int closure_type; /* Type of a T_CLOSURE */
141         ph_int quotes;       /* Number of quotes of a quoted array or symbol */
142         ph_int num_arg;      /* used by call_out.c to for vararg callouts */
143         ph_int extern_args;  /* Callbacks: true if the argument memory was
144                               * allocated externally */
145         ph_int generic;
146           /* For types without secondary type information, this is set to
147            * a fixed value, usually (u.number << 1).
148            * Also, this field is also used as generic 'secondary type field'
149            * handle, e.g. when comparing svalues.
150            */
151     } x;
152     union u u;  /* The value */
153 };
154 
155 #define SVALUE_FULLTYPE(svp) ((p_int *)(svp))
156   /* Return a pointer to an integer with the primary and secondary type
157    * information.
158    */
159 /* TODO: Sanity test: sizeof struct { ph_int, ph_int } <= sizeof p_int */
160 
161 
162 /* struct svalue_s.type: Primary types.
163  *   There must be no more than 16 different primary types, as some
164  *   type tables (prolang.y::hook_type_map[] for example) store
165  *   them as bitflags in shorts.
166  * TODO: Create these constants, plus the names in
167  * TODO:: interpret.c::svalue_typename[] from a descriptive _spec file.
168  */
169 
170 #define T_INVALID       0x0  /* empty svalue */
171 #define T_LVALUE        0x1  /* a lvalue */
172 #define T_NUMBER        0x2  /* an integer number */
173 #define T_STRING        0x3  /* a string */
174 #define T_POINTER       0x4  /* a vector */
175 #define T_OBJECT        0x5  /* an object */
176 #define T_MAPPING       0x6  /* a mapping */
177 #define T_FLOAT         0x7  /* a float number */
178 #define T_CLOSURE       0x8  /* a closure */
179 #define T_SYMBOL        0x9  /* a symbol */
180 #define T_QUOTED_ARRAY  0xa  /* a quoted array */
181 #ifdef USE_STRUCTS
182 #define T_STRUCT        0xb  /* a struct */
183 #endif /* USE_STRUCTS */
184 
185 #define T_CHAR_LVALUE                     0xc
186   /* .u.string points to the referenced character in a string */
187 
188   /* The following types must be used only in svalues referenced
189    * by a T_LVALUE svalue.
190    */
191 #define T_STRING_RANGE_LVALUE             0x0d /* TODO: ??? */
192 #define T_POINTER_RANGE_LVALUE            0x0e /* TODO: ??? */
193 #define T_PROTECTED_CHAR_LVALUE           0x0f
194   /* A protected character lvalue */
195 #define T_PROTECTED_STRING_RANGE_LVALUE   0x10
196   /* A protected string range lvalue */
197 #define T_PROTECTED_POINTER_RANGE_LVALUE  0x11
198   /* A protected pointer/mapping range lvalue */
199 #define T_PROTECTED_LVALUE                0x12
200   /* A protected lvalue */
201 #define T_PROTECTOR_MAPPING               0x13 /* TODO: ??? */
202 
203 #define T_CALLBACK                        0x14
204   /* A callback structure referenced from the stack to allow
205    * proper cleanup during error recoveries. The interpreter
206    * knows how to free it, but that's all.
207    */
208 
209 #define T_ERROR_HANDLER                   0x15
210   /* Not an actual value, this is used internally for cleanup
211    * operations. See the description of the error_handler() member
212    * for details.
213    */
214 
215 #define T_NULL                            0x16
216   /* Not an actual type, this is used in the efun_lpc_types[] table
217    * to encode the acceptance of '0' instead of the real datatype.
218    */
219 
220 #define T_MOD_SWAPPED    0x80
221   /* This flag is |-ed to the swapped-out type value if the value
222    * data has been swapped out.
223    */
224 
225 /* T_CLOSURE secondary information. */
226 
227   /* For closures of operators (internal machine codes), efuns and
228    * simul_efuns, the x.closure_type is a negative number defining
229    * which operator/efun/simul_efun to call.
230    * The values given here are just the limits of the usable number
231    * ranges.
232    * The relations are:
233    *   Operator-closure index = CLOSURE_OPERATOR_OFFS + instruction index
234    *   Efun-closure index     = CLOSURE_EFUN_OFFS + instruction index
235    *   Simul_efun index       = CLOSURE_SIMUL_EFUN_OFFS + function index
236    * Yes, the operator range can be overlaid onto the efun range without
237    * collision, distinguishing them by the struct instr[].Default fields
238    * (the 'closure' instruction does that to save space), but this way they
239    * are easier to distinguish.
240    * TODO: Note: Some code interprets these values as unsigned shorts.
241    */
242 
243 #define CLOSURE_OPERATOR        (-0x1800)  /* == 0xe800 */
244 #define CLOSURE_EFUN            (-0x1000)  /* == 0xf000 */
245 #define CLOSURE_SIMUL_EFUN      (-0x0800)  /* == 0xf800 */
246 
247 #define CLOSURE_OPERATOR_OFFS   (CLOSURE_OPERATOR & 0xffff)
248 #define CLOSURE_EFUN_OFFS       (CLOSURE_EFUN & 0xffff)
249 #define CLOSURE_SIMUL_EFUN_OFFS (CLOSURE_SIMUL_EFUN & 0xffff)
250 
251   /* The other closure types are created from actual objects and lambdas,
252    * the detailed information is stored in the u.lambda field.
253    * The first types are 'just' references to existing lfuns and variables,
254    * the others actually point to code.
255    */
256 
257 #define CLOSURE_LFUN            0  /* lfun in an object */
258 
259     /* Code 1 was used for ALIEN_LFUNs - some mudlibs however rely on the
260      * old code values.
261      */
262 
263 #define CLOSURE_IDENTIFIER      2  /* variable in this object */
264 
265 #define CLOSURE_PRELIMINARY     3
266     /* Efun closure used in a static initialization */
267 
268 #define CLOSURE_BOUND_LAMBDA    4  /* Bound unbound-lambda closure */
269 #define CLOSURE_LAMBDA          5  /* normal lambda closure */
270 #define CLOSURE_UNBOUND_LAMBDA  6  /* unbound lambda closure. */
271 
272 
273 #define CLOSURE_IDENTIFIER_OFFS 0xe800
274   /* When creating lfun/variable closures, the lfun/variable to bind
275    * is given as unsigned number:
276    *   number < C_I_OFFS:  number is index into function table
277    *   number >= C_I_OFFS: (number-C_I_OFFS) is index into variable table.
278    */
279 
280 /* Predicates operating on T_CLOSURE secondary information */
281 
282 #define CLOSURE_MALLOCED(c) ((c) >= 0)
283   /* TRUE if the closure was created at LPC runtime, ie is not an operator,
284    * efun or simul_efun.
285    */
286 
287 #define CLOSURE_IS_LFUN(c)        ((c) == CLOSURE_LFUN)
288   /* TRUE if the closure is of the #'<lfun> type.
289    */
290 
291 #define CLOSURE_REFERENCES_CODE(c) ((c) > CLOSURE_PRELIMINARY)
292   /* TRUE if the closure may have or reference code.
293    */
294 
295 #define CLOSURE_HAS_CODE(c) ((c) > CLOSURE_BOUND_LAMBDA)
296   /* TRUE if the closure points to actual code.
297    */
298 
299 #define CLOSURE_CALLABLE(c) ((c) >= CLOSURE_EFUN && (c) <= CLOSURE_LAMBDA)
300   /* TRUE if the closure is callable.
301    */
302 
303 /* --- The primary types in bit-flag encoding ---
304  *
305  * This flag encoding is used for the runtime typetests.
306  * Not all svalue types have a corresponding bitflag.
307  */
308 
309 #define TF_INVALID       (1 << T_INVALID)
310 #define TF_LVALUE        (1 << T_LVALUE)
311 #define TF_NUMBER        (1 << T_NUMBER)
312 #define TF_STRING        (1 << T_STRING)
313 #define TF_POINTER       (1 << T_POINTER)
314 #define TF_OBJECT        (1 << T_OBJECT)
315 #define TF_MAPPING       (1 << T_MAPPING)
316 #define TF_FLOAT         (1 << T_FLOAT)
317 #define TF_CLOSURE       (1 << T_CLOSURE)
318 #define TF_SYMBOL        (1 << T_SYMBOL)
319 #define TF_QUOTED_ARRAY  (1 << T_QUOTED_ARRAY)
320 #define TF_NULL          (1 << T_NULL)
321 #ifdef USE_STRUCTS
322 #define TF_STRUCT        (1 << T_STRUCT)
323 #endif /* USE_STRUCTS */
324 
325 #define TF_ANYTYPE       (~0)
326   /* This is used in the efun_lpc_types[]
327    * table to encode the acceptance of any type.
328    */
329 
330 /* --- Float Support --- */
331 
332 /* The driver uses a 48-Bit floating point format with a 32 bit mantissa
333  * and a 16 bit exponent, stored in u.mantissa and x.exponent. This should
334  * be well below all existing host floating point formats so that we get
335  * the same accuracy on all platforms.
336  *
337  * To keep the implementation transparent, the following macros/functions are
338  * defined:
339  *
340  *   int FLOAT_FORMAT:
341  *     0 for the portable format, 1 for the fast format.
342  *     Additional numbers may be defined for more formats.
343  *
344  *   double READ_DOUBLE(struct svalue * sp)
345  *     Return the floating point number stored in *sp.
346  *
347  *   long SPLIT_DOUBLE (double d, int * p)
348  *     Store the bytes 4..5 of <d> to the address given in <p>, and
349  *     return the bytes 0..3 of <d> as a long.
350  *     Used by the compiler to generate F_FLOAT instructions.
351  *     TODO: This code makes heave assumptions about data sizes and layout
352  *     TODO:: of integral types.
353  *
354  *   unknown STORE_DOUBLE (struct svalue * dest, double d)
355  *     Store the float <d> into the svalue *dest.
356  *
357  *   STORE_DOUBLE_USED
358  *     Declaration of a local variable which STORE_DOUBLE needs.
359  */
360 
361 
362 /* --- The portable format, used if no other format is defined */
363 
364 #ifndef STORE_DOUBLE
365 
366 #define FLOAT_FORMAT_0
367 
READ_DOUBLE(svalue_t * sv)368 static INLINE double READ_DOUBLE(svalue_t *sv) {
369     return ldexp( (double)(sv->u.mantissa), sv->x.exponent - 31 );
370 }
371 /* if your machine doesn't use the exponent to designate powers of two,
372    the use of ldexp in SPLIT_DOUBLE won't work; you'll have to multiply
373    with 32768. in this case */
374 
SPLIT_DOUBLE(double doublevalue,int * int_p)375 static INLINE p_int SPLIT_DOUBLE(double doublevalue, int *int_p) {
376     return (p_int)ldexp( frexp( doublevalue, int_p ), 31);
377 }
378 
379 // STORE_DOUBLE_USED is not needed anymore and defined empty.
380 #define STORE_DOUBLE_USED
STORE_DOUBLE(svalue_t * dest,double doublevalue)381 static INLINE void STORE_DOUBLE(svalue_t *dest, double doublevalue) {
382     int exponent;
383     dest->u.mantissa = SPLIT_DOUBLE(doublevalue, &exponent);
384     dest->x.exponent = (ph_int)exponent;
385 }
386 
387 #endif /* ifndef STORE_DOUBLE */
388 
389 /* --- svalue macros --- */
390 
391 #define addref_closure(sp, from) \
392   MACRO( svalue_t * p = sp; \
393          if (CLOSURE_MALLOCED(p->x.closure_type)) \
394              p->u.lambda->ref++; \
395          else \
396              (void)ref_object(p->u.ob, from); \
397   )
398   /* void addref_closure(sp, from): Add one ref to the closure svalue <sp>
399    *   in the function <from>.
400    */
401 
402 
403 /* void put_<type>(sp, value): Initialise svalue *sp with value of <type>.
404  *   'sp' is evaluated several times and must point to an otherwise
405  *   empty svalue. If <value> is a refcounted value, its refcount is
406  *   NOT incremented.
407  *
408  * void put_ref_<type>(sp, value): Initialise svalue *sp with value
409  *   of <type>. 'sp' is evaluated several times and must point to an
410  *   otherwise empty svalue. <value> must be a refcounted value, and
411  *   its refcount is incremented.
412  *
413  * void push_<type>(), void push_ref_<type>()
414  *   As the put_() macros, but <sp> is incremented once first.
415  *
416  * As a rule, all arguments must not have sideeffects!
417  *
418  * The psh_ macros are not in use (yet) - they have been renamed from push_
419  * so that the first use stands out.
420  *
421  * TODO: Add push_xxx() macros, see MudOS:interpret.h. In general, get
422  * TODO:: rid of the local sp/pc copies since they make error handling
423  * TODO:: very difficult.
424  * TODO: Also add 'adopt_<type>()' and 'pop_<type>()'macros, e.g.
425  * TODO:: 'adopt_object(sp)', which
426  * TODO:: retrieve the type from the *sp and set sp->type to T_INVALID.
427  */
428 
429 #define put_number(sp,num) \
430     ( (sp)->type = T_NUMBER, (sp)->u.number = (num) )
431 
432 #define put_float(sp,fnum) \
433     do { STORE_DOUBLE_USED; (sp)->type = T_FLOAT; STORE_DOUBLE((sp), fnum); }while(0)
434 
435 #define put_ref_array(sp,arr) \
436     ( (sp)->type = T_POINTER, (sp)->u.vec = ref_array(arr) )
437 #define put_array(sp,arr) \
438     ( (sp)->type = T_POINTER, (sp)->u.vec = arr )
439 
440 #ifdef USE_STRUCTS
441 #define put_ref_struct(sp,st) \
442     ( (sp)->type = T_STRUCT, (sp)->u.strct = ref_struct(st) )
443 #define put_struct(sp,st) \
444     ( (sp)->type = T_STRUCT, (sp)->u.strct = st )
445 #endif /* USE_STRUCTS */
446 
447 #define put_ref_mapping(sp,val) \
448     ( (sp)->type = T_MAPPING, (sp)->u.map = ref_mapping(val) )
449 #define put_mapping(sp,val) \
450     ( (sp)->type = T_MAPPING, (sp)->u.map = val )
451 
452 #define put_ref_object(sp,val,from) \
453     ( (sp)->type = T_OBJECT, (sp)->u.ob = ref_object(val, from) )
454 #define put_object(sp,val) \
455     ( (sp)->type = T_OBJECT, (sp)->u.ob = val )
456 
457 #define put_ref_valid_object(sp,val,from) \
458     ( ((val) && !((val)->flags & O_DESTRUCTED)) \
459       ? (put_ref_object(sp,val,from), 0) : put_number(sp, 0))
460 
461 #define put_valid_object(sp,val) \
462     ( ((val) && !((val)->flags & O_DESTRUCTED)) \
463       ? (put_object(sp,val), 0) : put_number(sp, 0))
464 
465 #define put_ref_string(sp,val) \
466     ( (sp)->type = T_STRING, (sp)->u.str = ref_mstring(val) )
467 #define put_string(sp,val) \
468     ( (sp)->type = T_STRING, (sp)->u.str = val )
469 
470 #define put_callback(sp,val) \
471     ( (sp)->type = T_CALLBACK, (sp)->u.cb = val )
472 
473 #define push_number(sp,num) \
474     ( (sp)++, put_number(sp, num) )
475 
476 #define push_float(sp,fnum) \
477     ( (sp)++, put_float(sp, fnum) )
478 
479 #define push_ref_array(sp,arr) \
480     ( (sp)++, put_ref_array(sp, arr) )
481 #define push_array(sp,arr) \
482     ( (sp)++, put_array(sp, arr) )
483 
484 #ifdef USE_STRUCTS
485 #define push_ref_struct(sp,st) \
486     ( (sp)++, put_ref_struct(sp, st) )
487 #define push_struct(sp,st) \
488     ( (sp)++, put_struct(sp, st) )
489 #endif /* USE_STRUCTS */
490 
491 #define psh_ref_mapping(sp,val) \
492     ( (sp)++, put_ref_mapping(sp,val) )
493 #define push_mapping(sp,val) \
494     ( (sp)++, put_mapping(sp,val) )
495 
496 #define push_ref_object(sp,val,from) \
497     ( (sp)++, put_ref_object(sp,val,from) )
498 #define push_object(sp,val) \
499     ( (sp)++, put_object(sp,val) )
500 
501 #define push_ref_valid_object(sp,val,from) \
502     ( (sp)++, put_ref_valid_object(sp,val,from) )
503 #define push_valid_object(sp,val) \
504     ( (sp)++, put_valid_object(sp,val) )
505 
506 #define push_ref_string(sp,val) \
507     ( (sp)++, put_ref_string(sp,val) )
508 #define push_string(sp,val) \
509     ( (sp)++, put_string(sp,val) )
510 #define push_c_string(sp,txt) \
511     ( (sp)++, put_c_string(sp, txt) )
512 #define push_c_n_string(sp,txt,len) \
513     ( (sp)++, put_c_n_string(sp, txt, len) )
514 
515 
516 #define psh_callback(sp,val) \
517     ( (sp)++, put_callback(sp,val) )
518 
519 /* The following macros implement the dynamic cost evaluations:
520  *
521  *   DYN_STRING_COST(l):  increase eval_cost depending on string length <l>.
522  *   DYN_ARRAY_COST(l):   increase eval_cost depending on array length <l>.
523  *   DYN_MAPPING_COST(l): increase eval_cost depending on mapping length <l>.
524  *
525  * Covered so far are:
526  *   F_ALLOCATE, F_ADD, F_ADD_EQ, F_VOID_ADD_EQ, F_MULTIPLY,
527  *   F_MULT_EQ of strings
528  *
529  * TODO: Expand this to all datatypes and sizes.
530  */
531 
532 #if defined(DYNAMIC_COSTS)
533 
534 #define DYN_STRING_COST(l)  eval_cost += (l) / 1000;
535 #define DYN_ARRAY_COST(l)  eval_cost += (l) / 1000;
536 #define DYN_MAPPING_COST(l)  eval_cost += (l) / 1000;
537 
538 #else
539 
540 #define DYN_STRING_COST(l)
541 #define DYN_ARRAY_COST(l)
542 #define DYN_MAPPING_COST(l)
543 
544 #endif
545 
546 /* --- Prototypes (in interpret.c) --- */
547 
548 extern void free_string_svalue(svalue_t *v);
549 extern void free_object_svalue(svalue_t *v);
550 extern void zero_object_svalue(svalue_t *v);
551 extern void free_svalue(svalue_t *v);
552 extern void assign_svalue_no_free(svalue_t *to, svalue_t *from);
553 extern void assign_svalue(svalue_t *dest, svalue_t *v);
554 extern void transfer_svalue_no_free(svalue_t *dest, svalue_t *v);
555 extern void transfer_svalue(svalue_t *dest, svalue_t *v);
556 extern svalue_t *pop_n_elems (int n, svalue_t *sp);
557 
558 #endif /* SVALUE_H__ */
559