1 #include "schpriv.h"
2 #include "schrunst.h"
3 #include "schmach.h"
4 
5 /* Bytecode validation (now off by default!) is an abstract
6    interpretation on the stack, where the abstract values are "not
7    available", "value", "boxed value", "syntax object", or "global
8    array". */
9 
10 /* FIXME: validation doesn't check LAMBDA_SINGLE_RESULT or
11    LAMBDA_PRESERVES_MARKS. (Maybe check them in the JIT pass?) */
12 
13 static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
14                          char *stack, Validate_TLS tls,
15                          int depth, int letlimit, int delta,
16                          int num_toplevels, int num_lifts, void *tl_use_map,
17                          mzshort *tl_state, mzshort tl_timestamp,
18                          Scheme_Object *app_rator, int proc_with_refs_ok,
19                          int result_ignored, struct Validate_Clearing *vc,
20                          int tailpos, int need_local_type, Scheme_Hash_Tree *procs,
21                          int expected_results,
22                          Scheme_Hash_Table **_st_ht);
23 static int validate_rator_wants_box(Scheme_Object *app_rator, int pos,
24                                     int hope,
25                                     Validate_TLS tls,
26                                     int num_toplevels, int num_lifts, void *tl_use_map);
27 
28 #ifdef MZ_PRECISE_GC
29 static void register_traversers(void);
30 #endif
31 
scheme_init_validate()32 void scheme_init_validate()
33 {
34 #ifdef MZ_PRECISE_GC
35   register_traversers();
36 #endif
37 }
38 
39 #define VALID_NOT 0
40 #define VALID_UNINIT 1
41 #define VALID_VAL 2
42 #define VALID_BOX 3
43 #define VALID_TOPLEVELS 4
44 #define VALID_VAL_NOCLEAR 5
45 #define VALID_BOX_NOCLEAR 6
46 #define VALID_TYPED 7
47 
48 typedef struct Validate_Clearing {
49   MZTAG_IF_REQUIRED
50   int stackpos, stacksize;
51   int *stack;
52   int ncstackpos, ncstacksize;
53   int *ncstack;
54   int self_pos, self_count, self_start;
55 } Validate_Clearing;
56 
make_clearing_stack()57 static struct Validate_Clearing *make_clearing_stack()
58 {
59   Validate_Clearing *vc;
60   vc = MALLOC_ONE_RT(Validate_Clearing);
61   SET_REQUIRED_TAG(vc->type = scheme_rt_validate_clearing);
62   vc->self_pos = -1;
63   return vc;
64 }
65 
reset_clearing(struct Validate_Clearing * vc)66 static void reset_clearing(struct Validate_Clearing *vc)
67 {
68   vc->stackpos = 0;
69   vc->ncstackpos = 0;
70 }
71 
clearing_stack_push(struct Validate_Clearing * vc,int pos,int val)72 static void clearing_stack_push(struct Validate_Clearing *vc, int pos, int val)
73 {
74   if (vc->stackpos + 2 > vc->stacksize) {
75     int *a, sz;
76     sz = (vc->stacksize ? 2 * vc->stacksize : 32);
77     a = (int *)scheme_malloc_atomic(sizeof(int) * sz);
78     if (vc->stacksize)
79       memcpy(a, vc->stack, vc->stacksize * sizeof(int));
80     vc->stacksize = sz;
81     vc->stack = a;
82   }
83   vc->stack[vc->stackpos] = pos;
84   vc->stack[vc->stackpos + 1] = val;
85   vc->stackpos += 2;
86 }
87 
noclear_stack_push(struct Validate_Clearing * vc,int pos)88 static void noclear_stack_push(struct Validate_Clearing *vc, int pos)
89 {
90   if (vc->ncstackpos + 1 > vc->ncstacksize) {
91     int *a, sz;
92     sz = (vc->ncstacksize ? 2 * vc->ncstacksize : 32);
93     a = (int *)scheme_malloc_atomic(sizeof(int) * sz);
94     if (vc->ncstacksize)
95       memcpy(a, vc->ncstack, vc->ncstacksize * sizeof(int));
96     vc->ncstacksize = sz;
97     vc->ncstack = a;
98   }
99   vc->ncstack[vc->ncstackpos] = pos;
100   vc->ncstackpos += 1;
101 }
102 
103 
add_struct_mapping(Scheme_Hash_Table ** _st_ht,int pos,int shape,int for_property)104 static void add_struct_mapping(Scheme_Hash_Table **_st_ht, int pos, int shape, int for_property)
105 {
106   if (!*_st_ht) {
107     Scheme_Hash_Table *ht;
108     ht = scheme_make_hash_table_eqv();
109     *_st_ht = ht;
110   }
111 
112   if (for_property) {
113     /* negative value is for a structure type property: */
114     shape = -(shape+1);
115   }
116 
117   scheme_hash_set(*_st_ht,
118                   scheme_make_integer(pos),
119                   scheme_make_integer(shape));
120 }
121 
scheme_validate_linklet(Mz_CPort * port,Scheme_Linklet * linklet)122 void scheme_validate_linklet(Mz_CPort *port, Scheme_Linklet *linklet)
123 {
124   char *stack;
125   int depth, delta, num_toplevels, i, j, pos;
126   int cnt, tl_timestamp = 1;
127   struct Validate_Clearing *vc;
128   Validate_TLS tls;
129   mzshort *tl_state;
130   Scheme_Hash_Table **_st_ht = NULL;
131   Scheme_Object *form, *shape;
132 
133   depth = linklet->max_let_depth + 1; /* +1 is for prefix */
134 
135   stack = scheme_malloc_atomic(depth);
136   memset(stack, VALID_NOT, depth);
137 
138   stack[depth - 1] = VALID_TOPLEVELS;
139   delta = depth - 1;
140 
141   tls = MALLOC_N(mzshort*, linklet->num_lifts);
142   _st_ht = MALLOC_N(Scheme_Hash_Table*, 1);
143 
144   num_toplevels = SCHEME_LINKLET_PREFIX_PREFIX + linklet->num_total_imports + SCHEME_VEC_SIZE(linklet->defns);
145 
146   tl_state = MALLOC_N_ATOMIC(mzshort, num_toplevels);
147   memset(tl_state, 0, sizeof(mzshort) * num_toplevels);
148 
149   if (linklet->need_instance_access)
150     tl_state[0] = 1;
151 
152   pos = SCHEME_LINKLET_PREFIX_PREFIX;
153   for (i = 0; i < SCHEME_VEC_SIZE(linklet->importss); i++) {
154     for (j = 0; j < SCHEME_VEC_SIZE(SCHEME_VEC_ELS(linklet->importss)[i]); j++, pos++) {
155       shape = (linklet->import_shapes ? SCHEME_VEC_ELS(linklet->import_shapes)[pos-SCHEME_LINKLET_PREFIX_PREFIX] : scheme_false);
156       if (SCHEME_TRUEP(shape)) {
157         if (SAME_OBJ(shape, scheme_void))
158           tl_state[pos] = SCHEME_TOPLEVEL_FIXED;
159         else {
160           intptr_t k;
161           tl_state[pos] = SCHEME_TOPLEVEL_CONST;
162           if (scheme_decode_struct_shape(shape, &k))
163             add_struct_mapping(_st_ht, pos, k, 0);
164           else if (scheme_decode_struct_prop_shape(shape, &k))
165             add_struct_mapping(_st_ht, pos, k, 1);
166         }
167       } else
168         tl_state[pos] = SCHEME_TOPLEVEL_READY;
169     }
170   }
171 
172   vc = make_clearing_stack();
173 
174   cnt = SCHEME_VEC_SIZE(linklet->bodies);
175   for (i = 0; i < cnt; i++) {
176     form = SCHEME_VEC_ELS(linklet->bodies)[i];
177     reset_clearing(vc);
178     if (!validate_expr(port, form,
179                        stack, tls,
180                        depth, delta, delta,
181                        num_toplevels, linklet->num_lifts, NULL,
182                        tl_state, tl_timestamp,
183                        NULL, 0, 0,
184                        vc, 1, 0, NULL, -1, _st_ht)) {
185       tl_timestamp++;
186       if (0) {
187         printf("increment to %d for %d %p\n", tl_timestamp,
188                SCHEME_TYPE(SCHEME_VEC_ELS(linklet->bodies)[i]),
189                SCHEME_VEC_ELS(linklet->bodies)[i]);
190       }
191     }
192   }
193 }
194 
validate_join(int r1,int r2)195 static int validate_join(int r1, int r2)
196 /* both r1 and r2 is result */
197 {
198   if (!r1 || !r2) return 0;
199   if ((r1 == 2) && (r2 == 2)) return 2;
200   return 1;
201 }
202 
validate_join_seq(int r1,int r2)203 static int validate_join_seq(int r1, int r2)
204 /* only r2 is result */
205 {
206   if (!r1 || !r2) return 0;
207   return r2;
208 }
209 
210 /*========================================================================*/
211 /*                            other syntax                                */
212 /*========================================================================*/
213 
validate_toplevel(Scheme_Object * expr,Mz_CPort * port,char * stack,Validate_TLS tls,int depth,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int skip_refs_check)214 static int validate_toplevel(Scheme_Object *expr, Mz_CPort *port,
215                              char *stack, Validate_TLS tls,
216                              int depth, int delta,
217                              int num_toplevels, int num_lifts, void *tl_use_map,
218                              mzshort *tl_state, mzshort tl_timestamp,
219                              int skip_refs_check)
220 {
221   if (!SAME_TYPE(scheme_toplevel_type, SCHEME_TYPE(expr)))
222     scheme_ill_formed_code(port);
223 
224   return validate_expr(port, expr, stack, tls,
225                        depth, delta, delta,
226                        num_toplevels, num_lifts, tl_use_map,
227                        tl_state, tl_timestamp,
228                        NULL, skip_refs_check ? 1 : 0, 0,
229                        make_clearing_stack(), 0, 0, NULL, 1, NULL);
230 }
231 
define_values_validate(Scheme_Object * data,Mz_CPort * port,char * stack,Validate_TLS tls,int depth,int letlimit,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int result_ignored,struct Validate_Clearing * vc,int tailpos,Scheme_Hash_Tree * procs,Scheme_Hash_Table ** _st_ht)232 static int define_values_validate(Scheme_Object *data, Mz_CPort *port,
233                                   char *stack,  Validate_TLS tls,
234                                   int depth, int letlimit, int delta,
235                                   int num_toplevels, int num_lifts,
236                                   void *tl_use_map,
237                                   mzshort *tl_state, mzshort tl_timestamp,
238                                   int result_ignored,
239                                   struct Validate_Clearing *vc, int tailpos,
240                                   Scheme_Hash_Tree *procs,
241                                   Scheme_Hash_Table **_st_ht)
242 {
243   int i, size, flags, result, is_struct, is_struct_prop, has_guard;
244   Simple_Struct_Type_Info stinfo;
245   Scheme_Object *val, *only_var;
246 
247   val = SCHEME_VEC_ELS(data)[0];
248   size = SCHEME_VEC_SIZE(data);
249 
250   if (size == 2)
251     only_var = SCHEME_VEC_ELS(data)[1];
252   else
253     only_var = NULL;
254 
255   for (i = 1; i < size; i++) {
256     validate_toplevel(SCHEME_VEC_ELS(data)[i], port, stack, tls, depth, delta,
257                       num_toplevels, num_lifts, tl_use_map,
258                       NULL, tl_timestamp,
259                       1);
260   }
261 
262   if (only_var) {
263     int pos;
264     pos = SCHEME_TOPLEVEL_POS(only_var);
265     if (pos >= (num_toplevels - num_lifts)) {
266       /* It's a lift. Check whether it needs to take reference arguments
267          and/or install reference info. */
268       Scheme_Object *app_rator;
269       Scheme_Lambda *data = NULL;
270       int tp = pos - (num_toplevels - num_lifts);
271       mzshort *a, *new_a = NULL;
272 
273       /* Make sure that no one has tried to register information. */
274       a = tls[tp];
275       if (a && (a != (mzshort *)0x1) && (a[0] < 1))
276         scheme_ill_formed_code(port);
277 
278       /* Convert rator to ref-arg info: */
279       app_rator = val;
280       while (1) {
281         if (SAME_TYPE(SCHEME_TYPE(app_rator), scheme_closure_type)) {
282           data = SCHEME_CLOSURE_CODE(app_rator);
283           break;
284         } else if (SAME_TYPE(SCHEME_TYPE(app_rator), scheme_lambda_type)) {
285           data = (Scheme_Lambda *)app_rator;
286           break;
287         } else if (SAME_TYPE(SCHEME_TYPE(app_rator), scheme_toplevel_type)) {
288           /* Record an indirection */
289           data = NULL;
290           new_a = MALLOC_N_ATOMIC(mzshort, 2);
291           new_a[0] = 0;
292           new_a[1] = SCHEME_TOPLEVEL_POS(app_rator);
293           break;
294         } else {
295           /* Not a procedure */
296           data = NULL;
297           new_a = (mzshort *)0x1;
298           break;
299         }
300       }
301       if (data) {
302         if (SCHEME_LAMBDA_FLAGS(data) & LAMBDA_HAS_TYPED_ARGS) {
303           int sz;
304           sz = data->num_params;
305           new_a = MALLOC_N_ATOMIC(mzshort, (sz + 2));
306           new_a[0] = -sz;
307           new_a[sz+1] = !!(SCHEME_LAMBDA_FLAGS(data) & LAMBDA_HAS_REST);
308           for (i = 0; i < sz; i++) {
309             int ct;
310             ct = scheme_boxmap_get(data->closure_map, i, data->closure_size);
311             if (ct == LAMBDA_TYPE_BOXED)
312               new_a[i + 1] = 1;
313             else
314               new_a[i + 1] = 0;
315           }
316         } else {
317           new_a = (mzshort *)0x1;
318         }
319       }
320 
321       /* Install info: */
322       tls[tp] = new_a;
323 
324       /* Check old hopes against actual */
325       if (a == (mzshort *)0x1) {
326         if (new_a != (mzshort *)0x1)
327           scheme_ill_formed_code(port);
328       } else if (a) {
329         int cnt = a[0], i;
330 
331         for (i = 0; i < cnt; i++) {
332           if (a[i + 1]) {
333             int is;
334             is = validate_rator_wants_box(val, i,
335                                           a[i + 1] == 2,
336                                           tls, num_toplevels, num_lifts, tl_use_map);
337             if ((is && (a[i + 1] == 1))
338                 || (!is && (a[i + 1] == 2)))
339               scheme_ill_formed_code(port);
340           }
341         }
342       }
343     } else
344       only_var = NULL;
345   }
346 
347   if (scheme_is_simple_make_struct_type(val, size-1, CHECK_STRUCT_TYPE_RESOLVED,
348                                         NULL,
349                                         &stinfo, NULL,
350                                         NULL, (_st_ht ? *_st_ht : NULL),
351                                         NULL, 0, NULL, NULL, 5)) {
352     /* This set of bindings is constant across invocations, but
353        if `uses_super', we need to increment tl_timestamp for
354        subtype-defining `struct' sequences. */
355     is_struct = 1;
356   } else {
357     is_struct = 0;
358   }
359 
360   has_guard = 0;
361   if (scheme_is_simple_make_struct_type_property(val, size-1, CHECK_STRUCT_TYPE_RESOLVED,
362                                                  &has_guard,
363                                                  NULL, (_st_ht ? *_st_ht : NULL),
364                                                  NULL, 0, NULL, 5)) {
365     is_struct_prop = 1;
366   } else {
367     is_struct_prop = 0;
368   }
369 
370   result = validate_expr(port, val, stack, tls,
371                          depth, letlimit, delta,
372                          num_toplevels, num_lifts, tl_use_map,
373                          tl_state, tl_timestamp + ((is_struct && stinfo.uses_super) ? 1 : 0),
374                          NULL, !!only_var, 0, vc, 0, 0, NULL,
375                          size-1, _st_ht);
376 
377   if (is_struct) {
378     if (_st_ht) {
379       /* Record `struct:' binding as constant across invocations,
380          so that it can be recognized for sub-struct declarations,
381          and so on: */
382       for (i = 1; i < size; i++) {
383         /* For the struct:, we need the init and field counts to be the
384            same, otherwise anything is fine: */
385         if ((i > 1)
386             || (stinfo.field_count == stinfo.init_field_count))
387           add_struct_mapping(_st_ht,
388                              SCHEME_TOPLEVEL_POS(SCHEME_VEC_ELS(data)[i]),
389                              scheme_get_struct_proc_shape(i-1, &stinfo),
390                              0);
391       }
392     }
393     /* In any case, treat the bindings as constant */
394     result = 2;
395   } else if (is_struct_prop) {
396     if (_st_ht) {
397       /* Record `prop:' binding as constant across invocations,
398          so that it can be recognized for struct declarations,
399          and so on: */
400       for (i = 1; i < size; i++) {
401         add_struct_mapping(_st_ht,
402                            SCHEME_TOPLEVEL_POS(SCHEME_VEC_ELS(data)[i]),
403                            scheme_get_struct_property_proc_shape(i-1, has_guard),
404                            1);
405       }
406     }
407     /* In any case, treat the bindings as constant */
408     result = 2;
409   }
410 
411   flags = SCHEME_TOPLEVEL_READY;
412   if (result == 2) {
413     /* We may treat more things as constant (more than fixed)
414        than the compiler would in terms of copyable literals, but
415        that's good enough for ensuring safety. */
416     flags = SCHEME_TOPLEVEL_CONST;
417   }
418 
419   for (i = 1; i < size; i++) {
420     int ts = (tl_timestamp + (result ? 0 : 1));
421     if (tl_state) {
422       int p = SCHEME_TOPLEVEL_POS(SCHEME_VEC_ELS(data)[i]);
423       if (p < (num_toplevels - num_lifts)) {
424         int s = -tl_state[p];
425         int expected_flags = s & SCHEME_TOPLEVEL_FLAGS_MASK;
426         int this_flags = flags;
427         if ((this_flags == SCHEME_TOPLEVEL_READY)
428             && (SCHEME_TOPLEVEL_FLAGS(SCHEME_VEC_ELS(data)[i]) & SCHEME_TOPLEVEL_SEAL))
429           this_flags = SCHEME_TOPLEVEL_FIXED;
430         if (0) {
431           printf("%d is %d for %d %p; at %d\n", p, this_flags, SCHEME_TYPE(val), val, ts);
432         }
433         if (tl_state[p] > 0)
434           scheme_ill_formed_code(port);
435         if ((expected_flags > this_flags)
436             || (expected_flags
437                 /* Use "<=" instead of "<" to prevent things like
438                    `(define x x)' with `x' claimed as constant. The
439                    `tl_timestamp++' before checking a closure body
440                    allows things like `(define x (lambda () x))'. */
441                 && ((s >> 2) <= ts))) {
442           scheme_ill_formed_code(port);
443         }
444         tl_state[p] = (ts << 2) | this_flags;
445       }
446     }
447   }
448 
449   return result;
450 }
451 
set_validate(Scheme_Object * data,Mz_CPort * port,char * stack,Validate_TLS tls,int depth,int letlimit,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int result_ignored,struct Validate_Clearing * vc,int tailpos,Scheme_Hash_Tree * procs,Scheme_Hash_Table ** _st_ht)452 static int set_validate(Scheme_Object *data, Mz_CPort *port,
453                         char *stack, Validate_TLS tls,
454                         int depth, int letlimit, int delta,
455                         int num_toplevels, int num_lifts,
456                         void *tl_use_map,
457                         mzshort *tl_state, mzshort tl_timestamp,
458                         int result_ignored,
459                         struct Validate_Clearing *vc, int tailpos,
460                         Scheme_Hash_Tree *procs,
461                         Scheme_Hash_Table **_st_ht)
462 {
463   Scheme_Set_Bang *sb = (Scheme_Set_Bang *)data;
464   int r1, r2;
465 
466   r1 = validate_expr(port, sb->val, stack, tls, depth, letlimit, delta,
467                      num_toplevels, num_lifts, tl_use_map,
468                      tl_state, tl_timestamp,
469                      NULL, 0, 0, vc, 0, 0, procs, 1, _st_ht);
470   r2 = validate_toplevel(sb->var, port, stack, tls, depth, delta,
471                          num_toplevels, num_lifts, tl_use_map,
472                          tl_state, tl_timestamp,
473                          0);
474 
475   return validate_join(validate_join_seq(r1, r2), 2);
476 }
477 
ref_validate(Scheme_Object * data,Mz_CPort * port,char * stack,Validate_TLS tls,int depth,int letlimit,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int result_ignored,struct Validate_Clearing * vc,int tailpos,Scheme_Hash_Tree * procs)478 static void ref_validate(Scheme_Object *data, Mz_CPort *port,
479 			 char *stack, Validate_TLS tls,
480                          int depth, int letlimit, int delta,
481                          int num_toplevels, int num_lifts,
482                          void *tl_use_map,
483                          mzshort *tl_state, mzshort tl_timestamp,
484                          int result_ignored,
485                          struct Validate_Clearing *vc, int tailpos,
486                          Scheme_Hash_Tree *procs)
487 {
488   tl_timestamp = tl_timestamp + 1; /* allows (define x (#%variable-reference x)) */
489 
490   if (!SCHEME_FALSEP(SCHEME_PTR1_VAL(data)))
491     validate_toplevel(SCHEME_PTR1_VAL(data), port, stack, tls, depth, delta,
492                       num_toplevels, num_lifts, tl_use_map,
493                       tl_state, tl_timestamp,
494                       0);
495 
496   if (!SCHEME_FALSEP(SCHEME_PTR2_VAL(data))) {
497     /* must reference  */
498     int p;
499     data = SCHEME_PTR2_VAL(data);
500     if (!SAME_TYPE(scheme_toplevel_type, SCHEME_TYPE(data)))
501       scheme_ill_formed_code(port);
502     p = SCHEME_TOPLEVEL_POS(data);
503     if (p != 0)
504       scheme_ill_formed_code(port);
505 
506     validate_toplevel(data, port, stack, tls, depth, delta,
507                       num_toplevels, num_lifts, tl_use_map,
508                       tl_state, tl_timestamp,
509                       0);
510   }
511 }
512 
apply_values_validate(Scheme_Object * data,Mz_CPort * port,char * stack,Validate_TLS tls,int depth,int letlimit,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int result_ignored,struct Validate_Clearing * vc,int tailpos,Scheme_Hash_Tree * procs,Scheme_Hash_Table ** _st_ht)513 static int apply_values_validate(Scheme_Object *data, Mz_CPort *port,
514                                  char *stack, Validate_TLS tls,
515                                  int depth, int letlimit, int delta,
516                                  int num_toplevels, int num_lifts,
517                                  void *tl_use_map,
518                                  mzshort *tl_state, mzshort tl_timestamp,
519                                  int result_ignored,
520                                  struct Validate_Clearing *vc, int tailpos,
521                                  Scheme_Hash_Tree *procs,
522                                  Scheme_Hash_Table **_st_ht)
523 {
524   Scheme_Object *f, *e;
525   int r1, r2;
526 
527   f = SCHEME_PTR1_VAL(data);
528   e = SCHEME_PTR2_VAL(data);
529 
530   r1 = validate_expr(port, f, stack, tls,
531                      depth, letlimit, delta,
532                      num_toplevels, num_lifts, tl_use_map,
533                      tl_state, tl_timestamp,
534                      NULL, 0, 0, vc, 0, 0, procs, 1, _st_ht);
535   r2 = validate_expr(port, e, stack, tls,
536                      depth, letlimit, delta,
537                      num_toplevels, num_lifts, tl_use_map,
538                      tl_state, tl_timestamp,
539                      NULL, 0, 0, vc, 0, 0, procs, -1, _st_ht);
540 
541   return validate_join(r1, r2);
542 }
543 
inline_variant_validate(Scheme_Object * data,Mz_CPort * port,char * stack,Validate_TLS tls,int depth,int letlimit,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int result_ignored,struct Validate_Clearing * vc,int tailpos,Scheme_Hash_Tree * procs,Scheme_Hash_Table ** _st_ht)544 static void inline_variant_validate(Scheme_Object *data, Mz_CPort *port,
545                                     char *stack, Validate_TLS tls,
546                                     int depth, int letlimit, int delta,
547                                     int num_toplevels, int num_lifts,
548                                     void *tl_use_map,
549                                     mzshort *tl_state, mzshort tl_timestamp,
550                                     int result_ignored,
551                                     struct Validate_Clearing *vc, int tailpos,
552                                     Scheme_Hash_Tree *procs,
553                                     Scheme_Hash_Table **_st_ht)
554 {
555   Scheme_Object *f1, *f2;
556 
557   f1 = SCHEME_VEC_ELS(data)[0];
558   f2 = SCHEME_VEC_ELS(data)[1];
559 
560   validate_expr(port, f1, stack, tls,
561                 depth, letlimit, delta,
562                 num_toplevels, num_lifts, tl_use_map,
563                 tl_state, tl_timestamp,
564                 NULL, 0, 0, vc, 0, 0, procs, 1, _st_ht);
565   validate_expr(port, f2, stack, tls,
566                 depth, letlimit, delta,
567                 num_toplevels, num_lifts, tl_use_map,
568                 tl_state, tl_timestamp,
569                 NULL, 0, 0, vc, 0, 0, procs, 1, _st_ht);
570 }
571 
case_lambda_validate(Scheme_Object * data,Mz_CPort * port,char * stack,Validate_TLS tls,int depth,int letlimit,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int result_ignored,struct Validate_Clearing * vc,int tailpos,Scheme_Hash_Tree * procs,Scheme_Hash_Table ** _st_ht)572 static void case_lambda_validate(Scheme_Object *data, Mz_CPort *port, char *stack, Validate_TLS tls,
573 				 int depth, int letlimit, int delta,
574                                  int num_toplevels, int num_lifts,
575                                  void *tl_use_map,
576                                  mzshort *tl_state, mzshort tl_timestamp,
577                                  int result_ignored,
578                                  struct Validate_Clearing *vc, int tailpos,
579                                  Scheme_Hash_Tree *procs,
580                                  Scheme_Hash_Table **_st_ht)
581 {
582   Scheme_Case_Lambda *seq = (Scheme_Case_Lambda *)data;
583   Scheme_Object *e;
584   int i;
585 
586   if (!SAME_TYPE(SCHEME_TYPE(data), scheme_case_lambda_sequence_type))
587     scheme_ill_formed_code(port);
588 
589   for (i = 0; i < seq->count; i++) {
590     e = seq->array[i];
591     if (!SAME_TYPE(SCHEME_TYPE(e), scheme_lambda_type)
592         && !SAME_TYPE(SCHEME_TYPE(e), scheme_closure_type))
593       scheme_ill_formed_code(port);
594     validate_expr(port, e, stack, tls, depth, letlimit, delta,
595                   num_toplevels, num_lifts, tl_use_map,
596                   tl_state, tl_timestamp,
597                   NULL, 0, 0, vc, 0, 0, procs, 1, _st_ht);
598   }
599 }
600 
validate_boxenv(int p,Mz_CPort * port,char * stack,int depth,int delta,int letlimit)601 static void validate_boxenv(int p, Mz_CPort *port, char *stack, int depth, int delta, int letlimit)
602 {
603   if (p >= 0)
604     p += delta;
605 
606   if ((p < 0) || (p >= letlimit) || (stack[p] != VALID_VAL))
607     scheme_ill_formed_code(port);
608 
609   stack[p] = VALID_BOX;
610 }
611 
bangboxenv_validate(Scheme_Object * data,Mz_CPort * port,char * stack,Validate_TLS tls,int depth,int letlimit,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int result_ignored,struct Validate_Clearing * vc,int tailpos,Scheme_Hash_Tree * procs,Scheme_Hash_Table ** _st_ht,int expected_results)612 static int bangboxenv_validate(Scheme_Object *data, Mz_CPort *port,
613                                char *stack, Validate_TLS tls,
614                                int depth, int letlimit, int delta,
615                                int num_toplevels, int num_lifts,
616                                void *tl_use_map,
617                                mzshort *tl_state, mzshort tl_timestamp,
618                                int result_ignored,
619                                struct Validate_Clearing *vc, int tailpos,
620                                Scheme_Hash_Tree *procs,
621                                Scheme_Hash_Table **_st_ht,
622                                int expected_results)
623 {
624   validate_boxenv(SCHEME_INT_VAL(SCHEME_PTR1_VAL(data)), port, stack, depth, delta, letlimit);
625 
626   return validate_expr(port, SCHEME_PTR2_VAL(data), stack, tls, depth, letlimit, delta,
627                        num_toplevels, num_lifts, tl_use_map,
628                        tl_state, tl_timestamp,
629                        NULL, 0, result_ignored, vc, tailpos, 0, procs, expected_results, _st_ht);
630 }
631 
begin0_validate(Scheme_Object * data,Mz_CPort * port,char * stack,Validate_TLS tls,int depth,int letlimit,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int result_ignored,struct Validate_Clearing * vc,int tailpos,Scheme_Hash_Tree * procs,Scheme_Hash_Table ** _st_ht,int expected_results)632 static int begin0_validate(Scheme_Object *data, Mz_CPort *port,
633                            char *stack, Validate_TLS tls,
634                            int depth, int letlimit, int delta,
635                            int num_toplevels, int num_lifts,
636                            void *tl_use_map,
637                            mzshort *tl_state, mzshort tl_timestamp,
638                            int result_ignored,
639                            struct Validate_Clearing *vc, int tailpos,
640                            Scheme_Hash_Tree *procs,
641                            Scheme_Hash_Table **_st_ht,
642                            int expected_results)
643 {
644   Scheme_Sequence *seq = (Scheme_Sequence *)data;
645   int i, r, result = 2;
646 
647   if (!SAME_TYPE(SCHEME_TYPE(seq), scheme_begin0_sequence_type)
648       && !SAME_TYPE(SCHEME_TYPE(seq), scheme_sequence_type))
649     scheme_ill_formed_code(port);
650 
651   for (i = 0; i < seq->count; i++) {
652     r = validate_expr(port, seq->array[i], stack, tls,
653                       depth, letlimit, delta,
654                       num_toplevels, num_lifts, tl_use_map,
655                       tl_state, tl_timestamp,
656                       NULL, 0, i > 0, vc, 0, 0, procs,
657                       (i > 0) ? -1 : expected_results, _st_ht);
658     result = validate_join_seq(r, result);
659   }
660 
661   return result;
662 }
663 
664 /*========================================================================*/
665 /*                            expressions                                 */
666 /*========================================================================*/
667 
validate_k(void)668 static Scheme_Object *validate_k(void)
669 {
670   Scheme_Thread *p = scheme_current_thread;
671   Mz_CPort *port = (Mz_CPort *)p->ku.k.p1;
672   Scheme_Object *expr = (Scheme_Object *)p->ku.k.p2;
673   char *stack = (char *)p->ku.k.p3;
674   int *args = (int *)(((void **)p->ku.k.p5)[0]);
675   Scheme_Object *app_rator = (Scheme_Object *)(((void **)p->ku.k.p5)[1]);
676   Validate_TLS tls = (Validate_TLS)(((void **)p->ku.k.p5)[2]);
677   Scheme_Hash_Tree *procs = (Scheme_Hash_Tree *)(((void **)p->ku.k.p5)[3]);
678   struct Validate_Clearing *vc = (struct Validate_Clearing *)p->ku.k.p4;
679   void *tl_use_map = (((void **)p->ku.k.p5)[4]);
680   mzshort *tl_state = (((void **)p->ku.k.p5)[5]);
681   Scheme_Hash_Table **_st_ht = (((void **)p->ku.k.p5)[6]);
682   int r;
683 
684   p->ku.k.p1 = NULL;
685   p->ku.k.p2 = NULL;
686   p->ku.k.p3 = NULL;
687   p->ku.k.p4 = NULL;
688   p->ku.k.p5 = NULL;
689 
690   r = validate_expr(port, expr, stack, tls,
691                     args[0], args[1], args[2],
692                     args[3], args[5], tl_use_map,
693                     tl_state, args[10],
694                     app_rator, args[6], args[7], vc, args[8],
695                     args[9], procs, args[11],
696                     _st_ht);
697 
698   return scheme_make_integer(r);
699 }
700 
701 /* FIXME: need to validate that a flonum is provided when a
702    procedure expects a flonum */
703 
validate_rator_wants_box(Scheme_Object * app_rator,int pos,int hope,Validate_TLS tls,int num_toplevels,int num_lifts,void * tl_use_map)704 int validate_rator_wants_box(Scheme_Object *app_rator, int pos,
705                              int hope,
706                              Validate_TLS tls,
707                              int num_toplevels, int num_lifts, void *tl_use_map)
708 {
709   Scheme_Lambda *data = NULL;
710   Scheme_Type ty;
711 
712   while (1) {
713     ty = SCHEME_TYPE(app_rator);
714     if (SAME_TYPE(ty, scheme_closure_type)) {
715       data = SCHEME_CLOSURE_CODE(app_rator);
716       break;
717     } else if (SAME_TYPE(ty, scheme_lambda_type)) {
718       data = (Scheme_Lambda *)app_rator;
719       break;
720     } else if (SAME_TYPE(ty, scheme_toplevel_type)) {
721       int p;
722       p = SCHEME_TOPLEVEL_POS(app_rator);
723       while (1) {
724         if (p >= (num_toplevels - num_lifts)) {
725           /* It's a lift. Check that the lift is defined, and that it
726              doesn't want reference arguments. */
727           mzshort *a; /* 0x1 => no ref args,
728                          ptr with pos length => expected (0 => don't care, 1 => want not, 2 => want is),
729                          ptr with neg length => actual
730                          ptr with 0 => another top-level */
731           int tp;
732 
733           tp = (p - (num_toplevels - num_lifts));
734           if (tp >= num_lifts)
735             return 0;
736 
737           a = tls[tp];
738           if (a == (mzshort *)0x1) {
739             return 0;
740           } else if (!a || (a[0] > 0)) {
741             /* The lift isn't ready.
742                Record what we expect to find when it is ready. */
743             if (!a || (a[0] < (pos + 1))) {
744               mzshort *naya;
745               int sz;
746               if (a)
747                 sz = a[0];
748               else
749                 sz = 3;
750               sz *= 2;
751               if (sz <= pos)
752                 sz = pos + 1;
753               naya = scheme_malloc_atomic((sz + 1) * sizeof(mzshort));
754               memset(naya, 0, (sz + 1) * sizeof(mzshort));
755               if (a)
756                 memcpy(naya, a, (a[0] + 1) * sizeof(mzshort));
757               naya[0] = sz;
758               a = naya;
759               tls[tp] = a;
760             }
761 
762             if (!a[pos + 1]) {
763               a[pos + 1] = hope ? 2 : 1;
764               return hope;
765             } else if (a[pos + 1] == 2)
766               return 1;
767             else
768               return 0;
769           } else if (!a[0]) {
770             /* try again */
771             p = a[1];
772           } else {
773             if (pos >= -a[0]) {
774               /* last slot indicates whether rest args are allowed */
775               return (a[-a[0]+1] ? hope : !hope);
776             } else
777               return a[pos + 1];
778           }
779         } else
780           return 0;
781       }
782     } else
783       return 0;
784   }
785 
786   if (SCHEME_LAMBDA_FLAGS(data) & LAMBDA_HAS_TYPED_ARGS) {
787     if (pos < data->num_params) {
788       int ct;
789       ct = scheme_boxmap_get(data->closure_map, pos, data->closure_size);
790       if (ct == LAMBDA_TYPE_BOXED)
791         return 1;
792     }
793   }
794 
795   return 0;
796 }
797 
argument_to_arity_error(Scheme_Object * app_rator,int proc_with_refs_ok)798 static int argument_to_arity_error(Scheme_Object *app_rator, int proc_with_refs_ok)
799 {
800   /* Since `raise-arity-error' doesn't actually apply its argument,
801      it's ok to pass any procedure. In particular, the compiler generates
802      calls to converted procedures. */
803   return ((proc_with_refs_ok == 2)
804           && SAME_OBJ(app_rator, scheme_raise_arity_error_proc));
805 }
806 
scheme_validate_closure(Mz_CPort * port,Scheme_Object * expr,char * closure_stack,Validate_TLS tls,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int self_pos_in_closure,Scheme_Hash_Tree * procs,Scheme_Hash_Table ** _st_ht)807 void scheme_validate_closure(Mz_CPort *port, Scheme_Object *expr,
808                              char *closure_stack, Validate_TLS tls,
809                              int num_toplevels, int num_lifts, void *tl_use_map,
810                              mzshort *tl_state, mzshort tl_timestamp,
811                              int self_pos_in_closure, Scheme_Hash_Tree *procs,
812                              Scheme_Hash_Table **_st_ht)
813 {
814   Scheme_Lambda *data = (Scheme_Lambda *)expr;
815   int i, sz, cnt, base, base2;
816   char *new_stack;
817   struct Validate_Clearing *vc;
818 
819   if (data->max_let_depth < (data->num_params + data->closure_size))
820     scheme_ill_formed_code(port);
821 
822   sz = data->max_let_depth;
823   new_stack = scheme_malloc_atomic(sz);
824   memset(new_stack, VALID_NOT, sz - data->num_params - data->closure_size);
825 
826   cnt = data->num_params;
827   base = sz - cnt;
828 
829   if (SCHEME_LAMBDA_FLAGS(data) & LAMBDA_HAS_TYPED_ARGS) {
830     base2 = data->closure_size;
831     for (i = 0; i < cnt; i++) {
832       new_stack[base + i] = closure_stack[base2 + i];
833     }
834   } else {
835     for (i = 0; i < cnt; i++) {
836       new_stack[i + base] = VALID_VAL;
837     }
838   }
839 
840   cnt = data->closure_size;
841   base = base - cnt;
842   for (i = 0; i < cnt; i++) {
843     new_stack[i + base] = closure_stack[i];
844   }
845 
846   vc = make_clearing_stack();
847   if (self_pos_in_closure >= 0) {
848     vc->self_pos = base + self_pos_in_closure;
849     vc->self_count = data->closure_size;
850     vc->self_start = base;
851   }
852 
853   if (data->tl_map) {
854     if (tl_use_map) {
855       /* check that data->tl_use_map => tl_use_map */
856       int *a, a_buf[2], len;
857 
858       if ((uintptr_t)tl_use_map & 0x1) {
859         len = 1;
860         a_buf[1] = (((uintptr_t)data->tl_map) >> 1) & 0x7FFFFFFF;
861         a = a_buf;
862       } else {
863         len = ((int *)tl_use_map)[0];
864         a = (int *)tl_use_map;
865       }
866 
867       if (tl_use_map) {
868         if ((uintptr_t)data->tl_map & 0x1) {
869           int map = (((uintptr_t)data->tl_map) >> 1) & 0x7FFFFFFF;
870           if ((len < 1) || ((a[1] & map) != map))
871             scheme_ill_formed_code(port);
872         } else {
873           int *b = ((int *)data->tl_map);
874           for (i = b[0]; i--; ) {
875             if ((len <= i) || ((a[i+1] & b[i+1]) != b[i+1]))
876               scheme_ill_formed_code(port);
877           }
878         }
879       }
880     }
881     tl_use_map = data->tl_map;
882   }
883 
884   validate_expr(port, data->body, new_stack, tls, sz, sz, base,
885                 num_toplevels, num_lifts, tl_use_map,
886                 tl_state, tl_timestamp,
887                 NULL, 0, 0, vc, 1, 0, procs, -1, _st_ht);
888 }
889 
as_nonempty_procs(Scheme_Hash_Tree * procs)890 static Scheme_Hash_Tree *as_nonempty_procs(Scheme_Hash_Tree *procs)
891 {
892   if (!procs)
893     procs = scheme_make_hash_tree(SCHEME_hashtr_eq);
894   return procs;
895 }
896 
validate_lambda(Mz_CPort * port,Scheme_Object * expr,char * stack,Validate_TLS tls,int depth,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,Scheme_Object * app_rator,int proc_with_refs_ok,int self_pos,Scheme_Hash_Tree * procs,Scheme_Hash_Table ** _st_ht)897 static void validate_lambda(Mz_CPort *port, Scheme_Object *expr,
898                             char *stack, Validate_TLS tls,
899                             int depth, int delta,
900                             int num_toplevels, int num_lifts, void *tl_use_map,
901                             mzshort *tl_state, mzshort tl_timestamp,
902                             Scheme_Object *app_rator, int proc_with_refs_ok,
903                             int self_pos, Scheme_Hash_Tree *procs,
904                             Scheme_Hash_Table **_st_ht)
905 {
906   Scheme_Lambda *data = (Scheme_Lambda *)expr;
907   int i, cnt, q, p, sz, base, stack_delta, vld, self_pos_in_closure = -1, typed_arg = 0;
908   mzshort *map;
909   char *closure_stack;
910   Scheme_Object *proc;
911   Scheme_Hash_Tree *new_procs = NULL;
912 
913   if (SCHEME_LAMBDA_FLAGS(data) & LAMBDA_HAS_TYPED_ARGS) {
914     sz = data->closure_size + data->num_params;
915   } else {
916     sz = data->closure_size;
917   }
918   map = data->closure_map;
919 
920   if (sz)
921     closure_stack = scheme_malloc_atomic(sz);
922   else
923     closure_stack = NULL;
924 
925   if (SCHEME_LAMBDA_FLAGS(data) & LAMBDA_HAS_TYPED_ARGS) {
926     cnt = data->num_params;
927     base = sz - cnt;
928     for (i = 0; i < cnt; i++) {
929       int ct;
930       ct = scheme_boxmap_get(map, i, data->closure_size);
931       if (ct == LAMBDA_TYPE_BOXED) {
932         vld = VALID_BOX;
933         typed_arg = 1;
934       } else if (ct) {
935         if ((ct - LAMBDA_TYPE_TYPE_OFFSET) > SCHEME_MAX_LOCAL_TYPE)
936           scheme_ill_formed_code(port);
937         vld = (VALID_TYPED + (ct - LAMBDA_TYPE_TYPE_OFFSET));
938         typed_arg = 1;
939       } else
940         vld = VALID_VAL;
941       closure_stack[i + base] = vld;
942     }
943   } else {
944     base = sz;
945   }
946 
947   cnt = data->closure_size;
948   base = base - cnt;
949   stack_delta = data->max_let_depth - sz;
950 
951   for (i = 0; i < cnt; i++) {
952     q = map[i];
953     if (q == self_pos)
954       self_pos_in_closure = i;
955     p = q + delta;
956     if ((q < 0) || (p < 0) || (p >= depth) || (stack[p] <= VALID_UNINIT))
957       scheme_ill_formed_code(port);
958     vld = stack[p];
959     if (vld == VALID_VAL_NOCLEAR)
960       vld = VALID_VAL;
961     else if (vld == VALID_BOX_NOCLEAR)
962       vld = VALID_BOX;
963 
964     if (SCHEME_LAMBDA_FLAGS(data) & LAMBDA_HAS_TYPED_ARGS) {
965       int pos = data->num_params + i;
966       int ct;
967       ct = scheme_boxmap_get(map, pos, data->closure_size);
968       if (ct == LAMBDA_TYPE_BOXED)
969         scheme_ill_formed_code(port);
970       if (ct > LAMBDA_TYPE_TYPE_OFFSET) {
971         if (vld != (VALID_TYPED + (ct - LAMBDA_TYPE_TYPE_OFFSET)))
972           vld = VALID_NOT;
973       } else if (vld > VALID_TYPED)
974         vld = VALID_NOT;
975     } else if (vld > VALID_TYPED)
976       vld = VALID_NOT;
977 
978     closure_stack[i + base] = vld;
979 
980     if (procs) {
981       proc = scheme_hash_tree_get(procs, scheme_make_integer(p));
982       if (proc)
983         new_procs = scheme_hash_tree_set(as_nonempty_procs(new_procs),
984                                          scheme_make_integer(i + base + stack_delta),
985                                          proc);
986     }
987   }
988 
989   if (typed_arg) {
990     if ((proc_with_refs_ok != 1)
991         && !argument_to_arity_error(app_rator, proc_with_refs_ok))
992       scheme_ill_formed_code(port);
993   }
994 
995   tl_timestamp++; /* closure delays use; needed for self-use <= check */
996 
997   if (SCHEME_RPAIRP(data->body)) {
998     /* Delay validation */
999     Scheme_Object *vec;
1000     vec = scheme_make_vector(12, NULL);
1001     SCHEME_VEC_ELS(vec)[0] = SCHEME_CAR(data->body);
1002     SCHEME_VEC_ELS(vec)[1] = (Scheme_Object *)closure_stack;
1003     SCHEME_VEC_ELS(vec)[2] = (Scheme_Object *)tls;
1004     SCHEME_VEC_ELS(vec)[3] = scheme_make_integer(num_toplevels);
1005     SCHEME_VEC_ELS(vec)[4] = scheme_make_integer(0); /* not used anymore */
1006     SCHEME_VEC_ELS(vec)[5] = scheme_make_integer(num_lifts);
1007     SCHEME_VEC_ELS(vec)[6] = scheme_make_integer(self_pos_in_closure);
1008     SCHEME_VEC_ELS(vec)[7] = new_procs ? (Scheme_Object *)new_procs : scheme_false;
1009     SCHEME_VEC_ELS(vec)[8] = tl_use_map ? tl_use_map : scheme_false;
1010     SCHEME_VEC_ELS(vec)[9] = tl_state ? (Scheme_Object *)tl_state : scheme_false;
1011     SCHEME_VEC_ELS(vec)[10] = scheme_make_integer(tl_timestamp);
1012     SCHEME_VEC_ELS(vec)[11] = (Scheme_Object *)_st_ht;
1013     SCHEME_CAR(data->body) = vec;
1014   } else
1015     scheme_validate_closure(port, expr, closure_stack, tls,
1016                             num_toplevels, num_lifts, tl_use_map,
1017                             tl_state, tl_timestamp,
1018                             self_pos_in_closure, new_procs, _st_ht);
1019 }
1020 
check_self_call_valid(Scheme_Object * rator,Mz_CPort * port,struct Validate_Clearing * vc,int delta,char * stack)1021 static void check_self_call_valid(Scheme_Object *rator, Mz_CPort *port, struct Validate_Clearing *vc,
1022                                   int delta, char *stack)
1023 {
1024   if ((vc->self_pos >= 0)
1025       && SAME_TYPE(SCHEME_TYPE(rator), scheme_local_type)
1026       && !SCHEME_GET_LOCAL_FLAGS(rator)
1027       && ((SCHEME_LOCAL_POS(rator) + delta) == vc->self_pos)) {
1028     /* For a self call, the JIT needs the closure data to be intact. */
1029     int i, pos;
1030     for (i = vc->self_count; i--; ) {
1031       pos = i + vc->self_start;
1032       if (stack[pos] <= VALID_UNINIT)
1033         scheme_ill_formed_code(port);
1034     }
1035   }
1036 }
1037 
no_typed(int need_local_type,Mz_CPort * port)1038 static void no_typed(int need_local_type, Mz_CPort *port)
1039 {
1040   if (need_local_type) scheme_ill_formed_code(port);
1041 }
1042 
check_typed(Scheme_Object * expr,int need_local_type,Mz_CPort * port)1043 static void check_typed(Scheme_Object *expr, int need_local_type, Mz_CPort *port)
1044 {
1045   if (need_local_type) {
1046     if (scheme_expr_produces_local_type(expr, NULL) != need_local_type)
1047       scheme_ill_formed_code(port);
1048   }
1049 }
1050 
validate_join_const(int result,int expected_results)1051 static int validate_join_const(int result, int expected_results)
1052 {
1053   return validate_join_seq(result,
1054                            (((expected_results == 1) || (expected_results == -1))
1055                             ? 2
1056                             : 0));
1057 }
1058 
is_functional_nonfailing_rator(Scheme_Object * rator,int num_args,int expected_results,Scheme_Hash_Table ** _st_ht)1059 static int is_functional_nonfailing_rator(Scheme_Object *rator, int num_args, int expected_results,
1060                                           Scheme_Hash_Table **_st_ht)
1061 {
1062   if (_st_ht && *_st_ht && SAME_TYPE(SCHEME_TYPE(rator), scheme_toplevel_type)) {
1063     int flags = (SCHEME_TOPLEVEL_FLAGS(rator) & SCHEME_TOPLEVEL_FLAGS_MASK);
1064     if (flags == SCHEME_TOPLEVEL_CONST) {
1065       /* could be a struct operation... */
1066       int pos = SCHEME_TOPLEVEL_POS(rator);
1067       Scheme_Object *v;
1068       v = scheme_hash_get(*_st_ht, scheme_make_integer(pos));
1069       if (v) {
1070         int k = SCHEME_INT_VAL(v);
1071         if (((k & STRUCT_PROC_SHAPE_MASK) == STRUCT_PROC_SHAPE_CONSTR)
1072             && (k & STRUCT_PROC_SHAPE_NONFAIL_CONSTR)) {
1073           if (num_args == (k >> STRUCT_PROC_SHAPE_SHIFT))
1074             return 1;
1075         } else if ((k & STRUCT_PROC_SHAPE_MASK) == STRUCT_PROC_SHAPE_PRED) {
1076           if (num_args == 1)
1077             return 1;
1078         }
1079       }
1080     }
1081   }
1082 
1083   return scheme_is_functional_nonfailing_primitive(rator, num_args, expected_results);
1084 }
1085 
1086 #define CAN_RESET_STACK_SLOT 0
1087 #if !CAN_RESET_STACK_SLOT
1088 # define WHEN_CAN_RESET_STACK_SLOT(x) 0
1089 #else
1090 # define WHEN_CAN_RESET_STACK_SLOT(x) (x)
1091 #endif
1092 
validate_expr(Mz_CPort * port,Scheme_Object * expr,char * stack,Validate_TLS tls,int depth,int letlimit,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,Scheme_Object * app_rator,int proc_with_refs_ok,int result_ignored,struct Validate_Clearing * vc,int tailpos,int need_local_type,Scheme_Hash_Tree * procs,int expected_results,Scheme_Hash_Table ** _st_ht)1093 static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
1094                          char *stack, Validate_TLS tls,
1095                          int depth, int letlimit, int delta,
1096                          int num_toplevels, int num_lifts, void *tl_use_map,
1097                          mzshort *tl_state, mzshort tl_timestamp,
1098                          Scheme_Object *app_rator, int proc_with_refs_ok,
1099                          int result_ignored,
1100                          struct Validate_Clearing *vc, int tailpos,
1101                          int need_local_type, Scheme_Hash_Tree *procs,
1102                          int expected_results,
1103                          Scheme_Hash_Table **_st_ht)
1104 /* result is 1 if result is `expected_results' values with no
1105    exceptions and no use of any non-ready binding; it's 2 if the
1106    result is furthermore a "constant" (i.e., the same shape result for
1107    every instantiation) */
1108 {
1109   Scheme_Type type;
1110   int did_one = 0, vc_merge = 0, vc_merge_start = 0, result = 2;
1111 
1112 #ifdef DO_STACK_CHECK
1113 # include "mzstkchk.h"
1114   {
1115     Scheme_Thread *p = scheme_current_thread;
1116     Scheme_Object *r;
1117     void **pr;
1118     int *args;
1119 
1120     args = MALLOC_N_ATOMIC(int, 12);
1121 
1122     p->ku.k.p1 = (void *)port;
1123     p->ku.k.p2 = (void *)expr;
1124     p->ku.k.p3 = (void *)stack;
1125     p->ku.k.p4 = (void *)vc;
1126 
1127     args[0] = depth;
1128     args[1] = letlimit;
1129     args[2] = delta;
1130     args[3] = num_toplevels;
1131     args[4] = 0; /* not used anymore */
1132     args[5] = num_lifts;
1133     args[6] = proc_with_refs_ok;
1134     args[7] = result_ignored;
1135     args[8] = tailpos;
1136     args[9] = need_local_type;
1137     args[10] = tl_timestamp;
1138     args[11] = expected_results;
1139 
1140     pr = MALLOC_N(void*, 7);
1141     pr[0] = (void *)args;
1142     pr[1] = (void *)app_rator;
1143     pr[2] = (void *)tls;
1144     pr[3] = (void *)procs;
1145     pr[4] = tl_use_map;
1146     pr[5] = tl_state;
1147     pr[6] = _st_ht;
1148 
1149     p->ku.k.p5 = (void *)pr;
1150 
1151     r = scheme_handle_stack_overflow(validate_k);
1152 
1153     return SCHEME_INT_VAL(r);
1154   }
1155 #endif
1156 
1157  top:
1158   if (did_one) {
1159     if (app_rator) {
1160       if (validate_rator_wants_box(app_rator, proc_with_refs_ok - 2, 0,
1161                                    tls, num_toplevels, num_lifts,
1162                                    tl_use_map))
1163         scheme_ill_formed_code(port);
1164       app_rator = NULL;
1165     }
1166     proc_with_refs_ok = 0;
1167   } else
1168     did_one = 1;
1169 
1170   type = SCHEME_TYPE(expr);
1171 
1172   switch (type) {
1173   case scheme_toplevel_type:
1174     {
1175       int c = SCHEME_TOPLEVEL_DEPTH(expr);
1176       int d = c + delta;
1177       int p = SCHEME_TOPLEVEL_POS(expr);
1178       int flags = (SCHEME_TOPLEVEL_FLAGS(expr) & SCHEME_TOPLEVEL_FLAGS_MASK);
1179 
1180       no_typed(need_local_type, port);
1181 
1182       if ((c < 0) || (p < 0) || (d < 0) || (d >= depth)
1183 	  || (stack[d] != VALID_TOPLEVELS)
1184 	  || (p >= num_toplevels))
1185 	scheme_ill_formed_code(port);
1186 
1187       if (tl_use_map) {
1188         if ((uintptr_t)tl_use_map & 0x1) {
1189           if (p >= 31)
1190             scheme_ill_formed_code(port);
1191           if (!((uintptr_t)tl_use_map & ((unsigned int)1 << (p + 1))))
1192             scheme_ill_formed_code(port);
1193         } else {
1194           if (p >= (*(int *)tl_use_map * 32))
1195             scheme_ill_formed_code(port);
1196           if (!(((int *)tl_use_map)[1 + (p / 32)] & ((unsigned int)1 << (p & 31))))
1197             scheme_ill_formed_code(port);
1198         }
1199       }
1200 
1201       if ((flags > SCHEME_TOPLEVEL_UNKNOWN) && tl_state && (p < num_toplevels)) {
1202         if (p < SCHEME_LINKLET_PREFIX_PREFIX) {
1203           /* instance-access toplevel available? */
1204           if (!tl_state[p])
1205             scheme_ill_formed_code(port);
1206         } else if (tl_state[p] <= 0) {
1207           /* record expectation */
1208           int s = -tl_state[p];
1209           int new_flags;
1210           new_flags = ((flags > (s & SCHEME_TOPLEVEL_FLAGS_MASK))
1211                        ? flags
1212                        : (s & SCHEME_TOPLEVEL_FLAGS_MASK));
1213           s >>= 2;
1214           if (!s || (tl_timestamp < s))
1215             s = tl_timestamp;
1216           tl_state[p] = -((s << 2) | new_flags);
1217         } else {
1218           /* check expectation */
1219           if (((tl_state[p] & SCHEME_TOPLEVEL_FLAGS_MASK) < flags)
1220               || ((tl_state[p] >> 2) > tl_timestamp)) {
1221             scheme_ill_formed_code(port);
1222           }
1223         }
1224       }
1225 
1226       if ((proc_with_refs_ok != 1)
1227           && !argument_to_arity_error(app_rator, proc_with_refs_ok)) {
1228         if (p >= (num_toplevels - num_lifts)) {
1229           /* It's a lift. Check that the lift is defined, and that it
1230              doesn't want reference arguments. */
1231           int tp;
1232           mzshort *a;
1233           tp = p - (num_toplevels - num_lifts);
1234           a = tls[tp];
1235           if (a) {
1236             if (a == (mzshort *)0x1) {
1237               /* Ok */
1238             } else if (a[0] > 0) {
1239               int i, cnt;
1240               cnt = a[0];
1241               for (i = 0; i < cnt; i++) {
1242                 if (a[i] == 2)
1243                   scheme_ill_formed_code(port);
1244               }
1245               tls[tp] = (mzshort *)0x1;
1246             } else {
1247               /* a[0] is either 0 (top-level ref; shouldn't happen) or < 0 (wants some ref args) */
1248               scheme_ill_formed_code(port);
1249             }
1250           } else {
1251             tls[tp] = (mzshort *)0x1; /* means "no ref args anywhere" */
1252           }
1253         }
1254       }
1255 
1256       if (flags == SCHEME_TOPLEVEL_UNKNOWN)
1257         result = validate_join_seq(result, 0);
1258       else {
1259         result = validate_join_const(result, expected_results);
1260         if (flags < SCHEME_TOPLEVEL_CONST)
1261           result = validate_join_seq(result, 1);
1262       }
1263     }
1264     break;
1265   case scheme_local_type:
1266     {
1267       int q = SCHEME_LOCAL_POS(expr);
1268       int p = q + delta;
1269       int ct;
1270 
1271       if ((q < 0) || (p >= depth) || (p < 0))
1272 	scheme_ill_formed_code(port);
1273 
1274       ct = SCHEME_GET_LOCAL_TYPE(expr);
1275       if (!ct)
1276         no_typed(need_local_type, port);
1277 
1278       if (ct) {
1279         if (stack[p] != (VALID_TYPED + ct))
1280           scheme_ill_formed_code(port);
1281       } else if ((stack[p] != VALID_VAL) && (stack[p] != VALID_VAL_NOCLEAR)) {
1282         if (result_ignored && ((stack[p] == VALID_BOX)
1283                                || (stack[p] == VALID_BOX_NOCLEAR)
1284                                || (stack[p] >= VALID_TYPED))) {
1285           /* ok to look up and ignore box or typed */
1286         } else if ((proc_with_refs_ok >= 2)
1287                    && ((stack[p] == VALID_BOX) || (stack[p] == VALID_BOX_NOCLEAR))
1288                    && validate_rator_wants_box(app_rator, proc_with_refs_ok - 2, 1,
1289                                                tls, num_toplevels, num_lifts,
1290                                                tl_use_map)) {
1291           /* It's ok - the function wants us to pass it a box, and
1292              we did. */
1293           app_rator = NULL;
1294         } else
1295           scheme_ill_formed_code(port);
1296       }
1297 
1298       if (SCHEME_GET_LOCAL_FLAGS(expr) == SCHEME_LOCAL_CLEAR_ON_READ) {
1299         if ((stack[p] == VALID_VAL_NOCLEAR)
1300             || (stack[p] == VALID_BOX_NOCLEAR)
1301             || (stack[p] >= VALID_TYPED))
1302           scheme_ill_formed_code(port);
1303         if (p >= letlimit)
1304           clearing_stack_push(vc, p, stack[p]);
1305         stack[p] = VALID_NOT;
1306       } else if (!(SCHEME_GET_LOCAL_FLAGS(expr) == SCHEME_LOCAL_OTHER_CLEARS)) {
1307         if (stack[p] == VALID_BOX) {
1308           if (p >= letlimit)
1309             noclear_stack_push(vc, p);
1310           stack[p] = VALID_BOX_NOCLEAR;
1311         } else if (stack[p] == VALID_VAL) {
1312           if (p >= letlimit)
1313             noclear_stack_push(vc, p);
1314           stack[p] = VALID_VAL_NOCLEAR;
1315         }
1316       }
1317 
1318       if (procs && !proc_with_refs_ok && !result_ignored) {
1319         if (scheme_hash_tree_get(procs, scheme_make_integer(p)))
1320           scheme_ill_formed_code(port);
1321       }
1322 
1323       result = validate_join_const(result, expected_results);
1324     }
1325     break;
1326   case scheme_local_unbox_type:
1327     {
1328       int q = SCHEME_LOCAL_POS(expr);
1329       int p = q + delta;
1330 
1331       no_typed(need_local_type, port);
1332 
1333       if ((q < 0) || (p >= depth) || (p < 0)
1334           || ((stack[p] != VALID_BOX)
1335               && (stack[p] != VALID_BOX_NOCLEAR)))
1336 	scheme_ill_formed_code(port);
1337 
1338       if (SCHEME_GET_LOCAL_FLAGS(expr) == SCHEME_LOCAL_CLEAR_ON_READ) {
1339         if (stack[p] == VALID_BOX_NOCLEAR)
1340           scheme_ill_formed_code(port);
1341         if (p >= letlimit)
1342           clearing_stack_push(vc, p, stack[p]);
1343         stack[p] = VALID_NOT;
1344       } else if (!(SCHEME_GET_LOCAL_FLAGS(expr) == SCHEME_LOCAL_OTHER_CLEARS)) {
1345         if (stack[p] == VALID_BOX) {
1346           if (p >= letlimit)
1347             noclear_stack_push(vc, p);
1348           stack[p] = VALID_BOX_NOCLEAR;
1349         }
1350       }
1351 
1352       result = validate_join_const(result, expected_results);
1353     }
1354     break;
1355   case scheme_application_type:
1356     {
1357       Scheme_App_Rec *app = (Scheme_App_Rec *)expr;
1358       int i, n, r;
1359 
1360       check_typed(expr, need_local_type, port);
1361 
1362       n = app->num_args + 1;
1363 
1364       delta -= (n - 1);
1365       if (delta < 0)
1366 	scheme_ill_formed_code(port);
1367       memset(stack + delta, VALID_NOT, n - 1);
1368 
1369       for (i = 0; i < n; i++) {
1370 	r = validate_expr(port, app->args[i], stack, tls, depth, letlimit, delta,
1371                           num_toplevels, num_lifts, tl_use_map,
1372                           tl_state, tl_timestamp,
1373                           i ? app->args[0] : NULL, i + 1, 0, vc, 0, 0, procs, 1, _st_ht);
1374         result = validate_join(result, r);
1375       }
1376 
1377       if (tailpos)
1378         check_self_call_valid(app->args[0], port, vc, delta, stack);
1379 
1380       if (result) {
1381         r = is_functional_nonfailing_rator(app->args[0], app->num_args, expected_results, _st_ht);
1382         result = validate_join(result, r);
1383       }
1384     }
1385     break;
1386   case scheme_application2_type:
1387     {
1388       Scheme_App2_Rec *app = (Scheme_App2_Rec *)expr;
1389       int r;
1390 
1391       check_typed(expr, need_local_type, port);
1392 
1393       delta -= 1;
1394       if (delta < 0)
1395 	scheme_ill_formed_code(port);
1396       stack[delta] = VALID_NOT;
1397 
1398       r = validate_expr(port, app->rator, stack, tls, depth, letlimit, delta,
1399                         num_toplevels, num_lifts, tl_use_map,
1400                         tl_state, tl_timestamp,
1401                         NULL, 1, 0, vc, 0, 0, procs, 1, _st_ht);
1402       result = validate_join(r, result);
1403       r = validate_expr(port, app->rand, stack, tls, depth, letlimit, delta,
1404                         num_toplevels, num_lifts, tl_use_map,
1405                         tl_state, tl_timestamp,
1406                         app->rator, 2, 0, vc, 0, 0, procs, 1, _st_ht);
1407       result = validate_join(r, result);
1408 
1409       if (tailpos)
1410         check_self_call_valid(app->rator, port, vc, delta, stack);
1411 
1412       if (result) {
1413         r = is_functional_nonfailing_rator(app->rator, 1, expected_results, _st_ht);
1414         if (!r
1415             && SAME_OBJ(app->rator, scheme_make_vector_proc)
1416             && (expected_results == 1 || expected_results == -1)
1417             && (SCHEME_INTP(app->rand)
1418                 && (SCHEME_INT_VAL(app->rand) >= 0)
1419                 && IN_FIXNUM_RANGE_ON_ALL_PLATFORMS(SCHEME_INT_VAL(app->rand)))) {
1420           r = 1;
1421         }
1422         result = validate_join(result, r);
1423       }
1424     }
1425     break;
1426   case scheme_application3_type:
1427     {
1428       Scheme_App3_Rec *app = (Scheme_App3_Rec *)expr;
1429       int r;
1430 
1431       check_typed(expr, need_local_type, port);
1432 
1433       delta -= 2;
1434       if (delta < 0)
1435 	scheme_ill_formed_code(port);
1436       stack[delta] = VALID_NOT;
1437       stack[delta+1] = VALID_NOT;
1438 
1439       r = validate_expr(port, app->rator, stack, tls, depth, letlimit, delta,
1440                         num_toplevels, num_lifts, tl_use_map,
1441                         tl_state, tl_timestamp,
1442                         NULL, 1, 0, vc, 0, 0, procs, 1, _st_ht);
1443       result = validate_join(r, result);
1444       r = validate_expr(port, app->rand1, stack, tls, depth, letlimit, delta,
1445                         num_toplevels, num_lifts, tl_use_map,
1446                         tl_state, tl_timestamp,
1447                         app->rator, 2, 0, vc, 0, 0, procs, 1, _st_ht);
1448       result = validate_join(r, result);
1449       r = validate_expr(port, app->rand2, stack, tls, depth, letlimit, delta,
1450                         num_toplevels, num_lifts, tl_use_map,
1451                         tl_state, tl_timestamp,
1452                         app->rator, 3, 0, vc, 0, 0, procs, 1, _st_ht);
1453       result = validate_join(r, result);
1454 
1455       if (tailpos)
1456         check_self_call_valid(app->rator, port, vc, delta, stack);
1457 
1458       if (result) {
1459         r = is_functional_nonfailing_rator(app->rator, 2, expected_results, _st_ht);
1460         if (!r
1461             && SAME_OBJ(app->rator, scheme_make_vector_proc)
1462             && (expected_results == 1 || expected_results == -1)
1463             && (SCHEME_INTP(app->rand1)
1464                 && (SCHEME_INT_VAL(app->rand1) >= 0)
1465                 && IN_FIXNUM_RANGE_ON_ALL_PLATFORMS(SCHEME_INT_VAL(app->rand1)))) {
1466           r = 1;
1467         }
1468          result = validate_join(r, result);
1469       }
1470     }
1471     break;
1472   case scheme_sequence_type:
1473     {
1474       Scheme_Sequence *seq = (Scheme_Sequence *)expr;
1475       int cnt;
1476       int i, r;
1477 
1478       if (type != scheme_sequence_type)
1479         no_typed(need_local_type, port);
1480 
1481       cnt = seq->count;
1482 
1483       for (i = 0; i < cnt - 1; i++) {
1484 	r = validate_expr(port, seq->array[i], stack, tls, depth, letlimit, delta,
1485                           num_toplevels, num_lifts, tl_use_map,
1486                           tl_state, tl_timestamp,
1487                           NULL, 0, 1, vc, 0, 0, procs, -1, _st_ht);
1488         result = validate_join_seq(result, r);
1489       }
1490 
1491       expr = seq->array[cnt - 1];
1492       goto top;
1493     }
1494     break;
1495   case scheme_branch_type:
1496     {
1497       Scheme_Branch_Rec *b;
1498       int vc_pos, vc_ncpos, r;
1499 
1500       b = (Scheme_Branch_Rec *)expr;
1501       r = validate_expr(port, b->test, stack, tls, depth, letlimit, delta,
1502                         num_toplevels, num_lifts, tl_use_map,
1503                         tl_state, tl_timestamp,
1504                         NULL, 0, 0, vc, 0, 0, procs, 1, _st_ht);
1505       result = validate_join(r, result);
1506 
1507       /* This is where letlimit is useful. It prevents let-assignment in the
1508 	 "then" branch that could permit bad code in the "else" branch (or the
1509 	 same thing with either branch affecting later code in a sequence). */
1510       letlimit = delta;
1511       vc_pos = vc->stackpos;
1512       vc_ncpos = vc->ncstackpos;
1513       r = validate_expr(port, b->tbranch, stack, tls, depth, letlimit, delta,
1514                         num_toplevels, num_lifts, tl_use_map,
1515                         tl_state, tl_timestamp,
1516                         NULL, 0, result_ignored, vc, tailpos, need_local_type, procs,
1517                         expected_results, _st_ht);
1518       result = validate_join_seq(result, r);
1519 
1520       /* since we're branchig, the result isn't constant: */
1521       result = validate_join(1, result);
1522 
1523       /* Rewind clears and noclears, but also save the clears,
1524          so that the branches' effects can be merged. */
1525       {
1526         int i, j;
1527 
1528         if (!vc_merge) {
1529           vc_merge = 1;
1530           vc_merge_start = vc_pos;
1531         }
1532 
1533         for (i = vc->stackpos - 2; i >= vc_pos; i -= 2) {
1534           stack[vc->stack[i]] = vc->stack[i + 1];
1535         }
1536 
1537         for (i = vc->ncstackpos - 1; i >= vc_ncpos; i--) {
1538           j = vc->ncstack[i];
1539           if (stack[j] == VALID_VAL_NOCLEAR)
1540             stack[j] = VALID_VAL;
1541           else if (stack[j] == VALID_BOX_NOCLEAR)
1542             stack[j] = VALID_BOX;
1543         }
1544         vc->ncstackpos = vc_ncpos;
1545       }
1546 
1547       expr = b->fbranch;
1548       goto top;
1549     }
1550     break;
1551   case scheme_with_cont_mark_type:
1552     {
1553       Scheme_With_Continuation_Mark *wcm = (Scheme_With_Continuation_Mark *)expr;
1554       int r;
1555 
1556       r = validate_expr(port, wcm->key, stack, tls, depth, letlimit, delta,
1557                         num_toplevels, num_lifts, tl_use_map,
1558                         tl_state, tl_timestamp,
1559                         NULL, 0, 0, vc, 0, 0, procs, 1, _st_ht);
1560       result = validate_join_seq(result, r);
1561       r = validate_expr(port, wcm->val, stack, tls, depth, letlimit, delta,
1562                         num_toplevels, num_lifts, tl_use_map,
1563                         tl_state, tl_timestamp,
1564                         NULL, 0, 0, vc, 0, 0, procs, 1, _st_ht);
1565       result = validate_join_seq(result, r);
1566 
1567       expr = wcm->body;
1568       goto top;
1569     }
1570     break;
1571   case scheme_lambda_type:
1572     {
1573       no_typed(need_local_type, port);
1574       validate_lambda(port, expr, stack, tls, depth, delta,
1575                                   num_toplevels, num_lifts, tl_use_map,
1576                                   tl_state, tl_timestamp,
1577                       app_rator, proc_with_refs_ok, -1, procs, _st_ht);
1578 
1579       result = validate_join_const(result, expected_results);
1580     }
1581     break;
1582   case scheme_let_value_type:
1583     {
1584       Scheme_Let_Value *lv = (Scheme_Let_Value *)expr;
1585       int q, p, c, i, r;
1586 
1587       r = validate_expr(port, lv->value, stack, tls, depth, letlimit, delta,
1588                         num_toplevels, num_lifts, tl_use_map,
1589                         tl_state, tl_timestamp,
1590                         NULL, 0, 0, vc, 0, 0, procs, lv->count, _st_ht);
1591       result = validate_join_seq(r, result);
1592 
1593       /* memset(stack, VALID_NOT, delta);  <-- seems unnecessary (and slow) */
1594 
1595       c = lv->count;
1596       q = lv->position;
1597       p = q + delta;
1598 
1599       for (i = 0; i < c; i++, p++) {
1600 	if ((q < 0)
1601             || (p < 0)
1602 	    || (SCHEME_LET_VALUE_AUTOBOX(lv) && ((p >= depth)
1603 					   || ((stack[p] != VALID_BOX)
1604                                                && (stack[p] != VALID_BOX_NOCLEAR))))
1605 	    || (!SCHEME_LET_VALUE_AUTOBOX(lv) && ((p >= letlimit)
1606 					    || !(WHEN_CAN_RESET_STACK_SLOT(stack[p] == VALID_VAL)
1607                                                  || WHEN_CAN_RESET_STACK_SLOT(stack[p] == VALID_VAL_NOCLEAR)
1608                                                  || (stack[p] == VALID_UNINIT)))))
1609 	  scheme_ill_formed_code(port);
1610 
1611 	if (!SCHEME_LET_VALUE_AUTOBOX(lv)) {
1612           if (stack[p] != VALID_VAL_NOCLEAR)
1613             stack[p] = VALID_VAL;
1614 	}
1615       }
1616 
1617       expr = lv->body;
1618       goto top;
1619     }
1620     break;
1621   case scheme_let_void_type:
1622     {
1623       Scheme_Let_Void *lv = (Scheme_Let_Void *)expr;
1624       int c, i;
1625 
1626       c = lv->count;
1627 
1628       if ((c < 0) || (c > delta))
1629 	scheme_ill_formed_code(port);
1630 
1631       if (SCHEME_LET_VOID_AUTOBOX(lv)) {
1632 	for (i = 0; i < c; i++) {
1633 	  stack[--delta] = VALID_BOX;
1634 	}
1635       } else {
1636 	delta -= c;
1637 	memset(stack + delta, VALID_UNINIT, c);
1638       }
1639 
1640       expr = lv->body;
1641       goto top;
1642     }
1643     break;
1644   case scheme_letrec_type:
1645     {
1646       Scheme_Letrec *l = (Scheme_Letrec *)expr;
1647       Scheme_Lambda *data;
1648       int i, c;
1649 
1650       c = l->count;
1651 
1652       if ((c < 0) || (c + delta > depth))
1653 	scheme_ill_formed_code(port);
1654 
1655       for (i = 0; i < c; i++) {
1656 	if (!SAME_TYPE(SCHEME_TYPE(l->procs[i]), scheme_lambda_type))
1657 	  scheme_ill_formed_code(port);
1658       }
1659 
1660       for (i = 0; i < c; i++) {
1661 #if !CAN_RESET_STACK_SLOT
1662         if (stack[delta + i] != VALID_UNINIT)
1663           scheme_ill_formed_code(port);
1664 #endif
1665 	stack[delta + i] = VALID_VAL;
1666         data = (Scheme_Lambda *)l->procs[i];
1667         if (SCHEME_LAMBDA_FLAGS(data) & LAMBDA_HAS_TYPED_ARGS) {
1668           /* If any arguments (as opposed to closure slots) are typed, then
1669              add the procedure to `procs': */
1670           int j;
1671           for (j = data->num_params; j--; ) {
1672             if (scheme_boxmap_get(data->closure_map, j, data->closure_size))
1673               break;
1674           }
1675           if (j >= 0) {
1676             procs = scheme_hash_tree_set(as_nonempty_procs(procs),
1677                                          scheme_make_integer(delta + i),
1678                                          l->procs[i]);
1679           }
1680         }
1681       }
1682 
1683       for (i = 0; i < c; i++) {
1684 	validate_lambda(port, l->procs[i], stack, tls, depth, delta,
1685                                     num_toplevels, num_lifts, tl_use_map,
1686                                     tl_state, tl_timestamp,
1687                                     NULL, 1, i, procs, _st_ht);
1688       }
1689 
1690       expr = l->body;
1691       goto top;
1692     }
1693     break;
1694   case scheme_let_one_type:
1695     {
1696       Scheme_Let_One *lo = (Scheme_Let_One *)expr;
1697       int r;
1698 
1699       --delta;
1700       if (delta < 0)
1701 	scheme_ill_formed_code(port);
1702       stack[delta] = VALID_UNINIT;
1703 
1704       r = validate_expr(port, lo->value, stack, tls, depth, letlimit, delta,
1705                         num_toplevels, num_lifts, tl_use_map,
1706                         tl_state, tl_timestamp,
1707                         NULL, 0, 0, vc, 0, SCHEME_LET_ONE_TYPE(lo), procs,
1708                         1, _st_ht);
1709       result = validate_join_seq(r, result);
1710 
1711 #if !CAN_RESET_STACK_SLOT
1712       if (stack[delta] != VALID_UNINIT)
1713         scheme_ill_formed_code(port);
1714 #endif
1715 
1716       if (SCHEME_LET_EVAL_TYPE(lo) & LET_ONE_UNUSED) {
1717         stack[delta] = VALID_NOT;
1718       } else if (SCHEME_LET_ONE_TYPE(lo)) {
1719         stack[delta] = (VALID_TYPED + SCHEME_LET_ONE_TYPE(lo));
1720         /* FIXME: need to check that lo->value produces a flonum */
1721       } else
1722         stack[delta] = VALID_VAL;
1723 
1724       expr = lo->body;
1725       goto top;
1726     }
1727     break;
1728 
1729   case scheme_define_values_type:
1730     no_typed(need_local_type, port);
1731     result = validate_join_seq(result,
1732                                define_values_validate(expr, port, stack, tls, depth, letlimit, delta,
1733                                                       num_toplevels, num_lifts, tl_use_map,
1734                                                       tl_state, tl_timestamp,
1735                                                       result_ignored, vc, tailpos, procs,
1736                                                       _st_ht));
1737     break;
1738   case scheme_set_bang_type:
1739     no_typed(need_local_type, port);
1740     result = validate_join_seq(result,
1741                                set_validate(expr, port, stack, tls, depth, letlimit, delta,
1742                                             num_toplevels, num_lifts, tl_use_map,
1743                                             tl_state, tl_timestamp,
1744                                             result_ignored, vc, tailpos, procs, _st_ht));
1745     break;
1746   case scheme_boxenv_type:
1747     no_typed(need_local_type, port);
1748     result = validate_join_seq(result,
1749                                bangboxenv_validate(expr, port, stack, tls, depth, letlimit, delta,
1750                                                    num_toplevels, num_lifts, tl_use_map,
1751                                                    tl_state, tl_timestamp,
1752                                                    result_ignored, vc, tailpos, procs, _st_ht, expected_results));
1753     break;
1754   case scheme_begin0_sequence_type:
1755     no_typed(need_local_type, port);
1756     result = validate_join_seq(result,
1757                                begin0_validate(expr, port, stack, tls, depth, letlimit, delta,
1758                                                num_toplevels, num_lifts, tl_use_map,
1759                                                tl_state, tl_timestamp,
1760                                                result_ignored, vc, tailpos, procs, _st_ht, expected_results));
1761     break;
1762   case scheme_varref_form_type:
1763     no_typed(need_local_type, port);
1764     ref_validate(expr, port, stack, tls, depth, letlimit, delta,
1765                  num_toplevels, num_lifts, tl_use_map,
1766                  tl_state, tl_timestamp,
1767                  result_ignored, vc, tailpos, procs);
1768     result = validate_join_const(result, expected_results);
1769     break;
1770   case scheme_apply_values_type:
1771     no_typed(need_local_type, port);
1772     apply_values_validate(expr, port, stack, tls, depth, letlimit, delta,
1773                           num_toplevels, num_lifts, tl_use_map,
1774                           tl_state, tl_timestamp,
1775                           result_ignored, vc, tailpos, procs, _st_ht);
1776     result = validate_join(0, result);
1777     break;
1778   case scheme_with_immed_mark_type:
1779     {
1780       Scheme_With_Continuation_Mark *wcm = (Scheme_With_Continuation_Mark *)expr;
1781       int r;
1782 
1783       no_typed(need_local_type, port);
1784 
1785       r = validate_expr(port, wcm->key, stack, tls, depth, letlimit, delta,
1786                         num_toplevels, num_lifts, tl_use_map,
1787                         tl_state, tl_timestamp,
1788                         NULL, 0, 0, vc, 0, 0, procs,
1789                         1, _st_ht);
1790       result = validate_join_seq(r, result);
1791 
1792       r = validate_expr(port, wcm->val, stack, tls, depth, letlimit, delta,
1793                         num_toplevels, num_lifts, tl_use_map,
1794                         tl_state, tl_timestamp,
1795                         NULL, 0, 0, vc, 0, 0, procs,
1796                         1, _st_ht);
1797       result = validate_join_seq(r, result);
1798 
1799       --delta;
1800       if (delta < 0)
1801 	scheme_ill_formed_code(port);
1802       stack[delta] = VALID_VAL;
1803 
1804       expr = wcm->body;
1805       goto top;
1806     }
1807     break;
1808   case scheme_case_lambda_sequence_type:
1809     no_typed(need_local_type, port);
1810     case_lambda_validate(expr, port, stack, tls, depth, letlimit, delta,
1811                          num_toplevels, num_lifts, tl_use_map,
1812                          tl_state, tl_timestamp,
1813                          result_ignored, vc, tailpos, procs, _st_ht);
1814     result = validate_join_const(result, expected_results);
1815     break;
1816   case scheme_inline_variant_type:
1817     no_typed(need_local_type, port);
1818     inline_variant_validate(expr, port, stack, tls, depth, letlimit, delta,
1819                             num_toplevels, num_lifts, tl_use_map,
1820                             tl_state, tl_timestamp,
1821                             result_ignored, vc, tailpos, procs, _st_ht);
1822     result = validate_join_const(result, expected_results);
1823     break;
1824   case scheme_ir_local_type:
1825     {
1826       scheme_ill_formed_code(port);
1827     }
1828   default:
1829     /* All values are definitely ok, except pre-closed closures.
1830        Such a closure can refer back to itself, so we use a flag
1831        to track cycles. Also check need_local_type. */
1832     result = validate_join_const(result, expected_results);
1833     if (SAME_TYPE(type, scheme_closure_type)
1834         /* If the closure is not empty, then it must be from 3-D code
1835            (where PLT_VALIDATE_COMPILE is set), and validation is not
1836            our responsibility here: */
1837         && (SCHEME_CLOSURE_CODE(expr)->closure_size == 0)) {
1838       Scheme_Lambda *data;
1839       no_typed(need_local_type, port);
1840       expr = (Scheme_Object *)SCHEME_CLOSURE_CODE(expr);
1841       data = (Scheme_Lambda *)expr;
1842       if ((SCHEME_LAMBDA_FLAGS(data) & LAMBDA_STATUS_MASK) == LAMBDA_STATUS_VALIDATED) {
1843         /* Done with this one. */
1844       } else {
1845         SCHEME_LAMBDA_FLAGS(data) = (SCHEME_LAMBDA_FLAGS(data) & ~LAMBDA_STATUS_MASK) | LAMBDA_STATUS_VALIDATED;
1846         did_one = 0;
1847         goto top;
1848       }
1849     } else if (SAME_TYPE(type, scheme_case_closure_type)) {
1850       Scheme_Case_Lambda *seq;
1851       int i;
1852       seq = (Scheme_Case_Lambda *)expr;
1853       for (i = 0; i < seq->count; i++) {
1854         validate_expr(port, seq->array[i], stack, tls, depth, letlimit, delta,
1855                       num_toplevels, num_lifts, tl_use_map,
1856                       tl_state, tl_timestamp,
1857                       NULL, 0, 0, vc, 0, 0, procs, 1, _st_ht);
1858       }
1859     } else if (need_local_type) {
1860       if (SCHEME_DBLP(expr) && (need_local_type == SCHEME_LOCAL_TYPE_FLONUM))
1861         need_local_type = 0;
1862 #ifdef MZ_LONG_DOUBLE
1863       if (SCHEME_LONG_DBLP(expr) && (need_local_type == SCHEME_LOCAL_TYPE_EXTFLONUM))
1864         need_local_type = 0;
1865 #endif
1866       if (SCHEME_INTP(expr) && (need_local_type == SCHEME_LOCAL_TYPE_FIXNUM))
1867         need_local_type = 0;
1868       no_typed(need_local_type, port);
1869     }
1870     break;
1871   }
1872 
1873   if (app_rator)
1874     if (validate_rator_wants_box(app_rator, proc_with_refs_ok - 2, 0,
1875                                  tls, num_toplevels, num_lifts, tl_use_map))
1876       scheme_ill_formed_code(port);
1877 
1878   if (vc_merge) {
1879     /* Re-clear to merge effects from branches */
1880     int i, p;
1881     for (i = vc_merge_start; i < vc->stackpos; i += 2) {
1882       p = vc->stack[i];
1883       stack[p] = VALID_NOT;
1884     }
1885   }
1886 
1887   return result;
1888 }
1889 
1890 /*========================================================================*/
1891 /*                         precise GC traversers                          */
1892 /*========================================================================*/
1893 
1894 #ifdef MZ_PRECISE_GC
1895 
1896 START_XFORM_SKIP;
1897 
1898 #include "mzmark_validate.inc"
1899 
register_traversers(void)1900 static void register_traversers(void)
1901 {
1902   GC_REG_TRAV(scheme_rt_validate_clearing, mark_validate_clearing);
1903 }
1904 
1905 END_XFORM_SKIP;
1906 
1907 #endif
1908