1 /* (c) 2009 David Leonard. All rights reserved. */
2 #if HAVE_CONFIG_H
3 # include <config.h>
4 #endif
5 
6 #include <see/mem.h>
7 #include <see/error.h>
8 #include <see/value.h>
9 #include <see/system.h>
10 #include <see/string.h>
11 #include <see/intern.h>
12 #include <see/try.h>
13 
14 #include "dprint.h"
15 #include "stringdefs.h"
16 #include "function.h"
17 #include "parse.h"
18 #include "parse_node.h"
19 #include "parse_const.h"
20 #include "parse_codegen.h"
21 #include "code.h"
22 #include "nmath.h"              /* MAX() */
23 
24 extern int SEE_parse_debug;
25 
26 #define MAX3(a, b, c)    MAX(MAX(a, b), c)
27 #define MAX4(a, b, c, d) MAX(MAX(a, b), MAX(c, d))
28 
29 #define PATCH_FIND_BREAK        0
30 #define PATCH_FIND_CONTINUE     1
31 #define CONTINUABLE 1
32 
33 struct code_varscope {
34 	struct SEE_string *ident;
35 	unsigned int id;
36 	int in_scope;
37 };
38 
39 struct code_context {
40 	struct SEE_code *code;
41 
42 	/* A structure used to hold the break and continue patchables */
43 	struct patchables {
44 		SEE_code_patchable_t *cont_patch;
45 		unsigned int ncont_patch;
46 		struct SEE_growable gcont_patch;
47 		SEE_code_patchable_t *break_patch;
48 		unsigned int nbreak_patch;
49 		struct SEE_growable gbreak_patch;
50 		unsigned int target;
51 		struct patchables *prev;
52 		int continuable;
53 		unsigned int block_depth;
54 	} *patchables;
55 
56 	/* The current block depth. Starts at zero. */
57 	unsigned int block_depth, max_block_depth;
58 
59 	/* True when directly in the variables scope. This
60 	 * allows us to use VREF statements instead of LOOKUP.
61 	 * It goes false inside 'with' and 'catch' blocks.
62 	 * Individual vars can be descoped;
63 	 */
64 	int in_var_scope;
65 
66 	/* True when we want to disable constant folding */
67 	int no_const;
68 
69 	struct code_varscope *varscope;
70 	unsigned int          nvarscope;
71 	struct SEE_growable   gvarscope;
72 };
73 
74 extern void (*_SEE_nodeclass_codegen[])(struct node *,
75         struct code_context *);
76         /* unsigned int node.maxstack */
77 	/* Keeps track of the maximum stack space needed
78 	 * to run the code. */
79 
80         /* unsigned int node.is */
81 	/* Represents a union of the possible types that
82 	 * are left on top of the stack when code from
83 	 * an Expression node is run */
84 # define CG_TYPE_UNDEFINED	0x01
85 # define CG_TYPE_NULL		0x02
86 # define CG_TYPE_BOOLEAN	0x04
87 # define CG_TYPE_NUMBER		0x08
88 # define CG_TYPE_STRING		0x10
89 # define CG_TYPE_OBJECT		0x20
90 # define CG_TYPE_REFERENCE	0x40
91 # define CG_TYPE_PRIMITIVE	(CG_TYPE_UNDEFINED | \
92 				 CG_TYPE_NULL | \
93 				 CG_TYPE_BOOLEAN | \
94 				 CG_TYPE_NUMBER | \
95 				 CG_TYPE_STRING)
96 # define CG_TYPE_VALUE		(CG_TYPE_PRIMITIVE | CG_TYPE_OBJECT)
97 # define CG_IS_VALUE(n)	    (!((n)->is & CG_TYPE_REFERENCE))
98 # define CG_IS_PRIMITIVE(n) (!((n)->is & (CG_TYPE_REFERENCE|CG_TYPE_OBJECT)))
99 # define CG_IS_BOOLEAN(n)   ((n)->is == CG_TYPE_BOOLEAN)
100 # define CG_IS_NUMBER(n)    ((n)->is == CG_TYPE_NUMBER)
101 # define CG_IS_STRING(n)    ((n)->is == CG_TYPE_STRING)
102 # define CG_IS_OBJECT(n)    ((n)->is == CG_TYPE_OBJECT)
103 
104 static void Arguments_codegen(struct node *na, struct code_context *cc);
105 static void push_patchables(struct code_context *cc, unsigned int target,
106 	int cont);
107 static void pop_patchables(struct code_context *cc,
108 	SEE_code_addr_t cont_addr, SEE_code_addr_t break_addr);
109 static struct patchables *patch_find(struct code_context *cc,
110 	unsigned int target, int tok);
111 static void patch_add_continue(struct code_context *cc, struct patchables *p,
112 	SEE_code_patchable_t pa);
113 static void patch_add_break(struct code_context *cc, struct patchables *p,
114 	SEE_code_patchable_t pa);
115 static void cg_init(struct SEE_interpreter *, struct code_context *, int);
116 static void cg_const_codegen(struct node *node, struct code_context *cc);
117 static struct SEE_code *cg_fini(struct SEE_interpreter *interp,
118 	struct code_context *cc, unsigned int maxstack);
119 static void cg_block_enter(struct code_context *cc);
120 static void cg_block_leave(struct code_context *cc);
121 static unsigned int cg_block_current(struct code_context *cc);
122 static unsigned int cg_var_id(struct code_context *, struct SEE_string *);
123 static int cg_var_is_in_scope(struct code_context *, struct SEE_string *);
124 static void cg_var_set_scope(struct code_context *, struct SEE_string *, int);
125 static int cg_var_set_all_scope(struct code_context *, int);
126 
127 # define CODEGENFN(node) _SEE_nodeclass_codegen[(node)->nodeclass]
128 # define CODEGEN(node)	do {				\
129 	if (!(cc)->no_const &&				\
130 	    ISCONST(node, (cc)->code->interpreter) &&	\
131 	    node->nodeclass != NODECLASS_Literal)	\
132 		cg_const_codegen(node, cc);		\
133 	else						\
134 	    (*CODEGENFN(node))(node, cc);	        \
135     } while (0)
136 
137 /* Call/construct operators */
138 # define _CG_OP1(name, n) \
139     (*cc->code->code_class->gen_op1)(cc->code, SEE_CODE_##name, n)
140 # define CG_NEW(n)		_CG_OP1(NEW, n)
141 # define CG_CALL(n)		_CG_OP1(CALL, n)
142 # define CG_END(n)		_CG_OP1(END, n)
143 # define CG_VREF(n)		_CG_OP1(VREF, n)
144 
145 /* Generic operators */
146 # define _CG_OP0(name) \
147     (*cc->code->code_class->gen_op0)(cc->code, SEE_CODE_##name)
148 # define CG_NOP()		_CG_OP0(NOP)
149 # define CG_DUP()		_CG_OP0(DUP)
150 # define CG_POP()		_CG_OP0(POP)
151 # define CG_EXCH()		_CG_OP0(EXCH)
152 # define CG_ROLL3()		_CG_OP0(ROLL3)
153 # define CG_THROW()		_CG_OP0(THROW)
154 # define CG_SETC()		_CG_OP0(SETC)
155 # define CG_GETC()		_CG_OP0(GETC)
156 # define CG_THIS()		_CG_OP0(THIS)
157 # define CG_OBJECT()		_CG_OP0(OBJECT)
158 # define CG_ARRAY()		_CG_OP0(ARRAY)
159 # define CG_REGEXP()		_CG_OP0(REGEXP)
160 # define CG_REF()		_CG_OP0(REF)
161 # define CG_GETVALUE()		_CG_OP0(GETVALUE)
162 # define CG_LOOKUP()		_CG_OP0(LOOKUP)
163 # define CG_PUTVALUE()		_CG_OP0(PUTVALUE)
164 # define CG_DELETE()		_CG_OP0(DELETE)
165 # define CG_TYPEOF()		_CG_OP0(TYPEOF)
166 # define CG_TOOBJECT()		_CG_OP0(TOOBJECT)
167 # define CG_TONUMBER()		_CG_OP0(TONUMBER)
168 # define CG_TOBOOLEAN()		_CG_OP0(TOBOOLEAN)
169 # define CG_TOSTRING()		_CG_OP0(TOSTRING)
170 # define CG_TOPRIMITIVE()	_CG_OP0(TOPRIMITIVE)
171 # define CG_NEG()		_CG_OP0(NEG)
172 # define CG_INV()		_CG_OP0(INV)
173 # define CG_NOT()		_CG_OP0(NOT)
174 # define CG_MUL()		_CG_OP0(MUL)
175 # define CG_DIV()		_CG_OP0(DIV)
176 # define CG_MOD()		_CG_OP0(MOD)
177 # define CG_ADD()		_CG_OP0(ADD)
178 # define CG_SUB()		_CG_OP0(SUB)
179 # define CG_LSHIFT()		_CG_OP0(LSHIFT)
180 # define CG_RSHIFT()		_CG_OP0(RSHIFT)
181 # define CG_URSHIFT()		_CG_OP0(URSHIFT)
182 # define CG_LT()		_CG_OP0(LT)
183 # define CG_GT()		_CG_OP0(GT)
184 # define CG_LE()		_CG_OP0(LE)
185 # define CG_GE()		_CG_OP0(GE)
186 # define CG_INSTANCEOF()	_CG_OP0(INSTANCEOF)
187 # define CG_IN()		_CG_OP0(IN)
188 # define CG_EQ()		_CG_OP0(EQ)
189 # define CG_SEQ()		_CG_OP0(SEQ)
190 # define CG_BAND()		_CG_OP0(BAND)
191 # define CG_BXOR()		_CG_OP0(BXOR)
192 # define CG_BOR()		_CG_OP0(BOR)
193 # define CG_S_ENUM()		_CG_OP0(S_ENUM)
194 # define CG_S_WITH()		_CG_OP0(S_WITH)
195 # define CG_S_CATCH()		_CG_OP0(S_CATCH)
196 # define CG_ENDF()		_CG_OP0(ENDF)
197 
198 /* Special PUTVALUE that takes attributes */
199 # define CG_PUTVALUEA(attr)	_CG_OP1(PUTVALUEA,attr)
200 
201 /* Literals */
202 # define CG_LITERAL(vp) \
203 	(*cc->code->code_class->gen_literal)(cc->code, vp)
204 
205 # define CG_UNDEFINED() do {		/* - | num */	\
206 	struct SEE_value _cgtmp;			\
207 	SEE_SET_UNDEFINED(&_cgtmp);			\
208 	CG_LITERAL(&_cgtmp);				\
209   } while (0)
210 
211 # define CG_STRING(str) do {		/* - | str */	\
212 	struct SEE_value _cgtmp;			\
213 	SEE_SET_STRING(&_cgtmp, str);\
214 	CG_LITERAL(&_cgtmp);				\
215   } while (0)
216 
217 # define CG_NUMBER(num) do {		/* - | num */	\
218 	struct SEE_value _cgtmp;			\
219 	SEE_SET_NUMBER(&_cgtmp, num);			\
220 	CG_LITERAL(&_cgtmp);				\
221   } while (0)
222 
223 # define CG_BOOLEAN(bool) do {		/* - | bool */	\
224 	struct SEE_value _cgtmp;			\
225 	SEE_SET_BOOLEAN(&_cgtmp, bool);			\
226 	CG_LITERAL(&_cgtmp);				\
227   } while (0)
228 # define CG_TRUE()   CG_BOOLEAN(1)	/* - | true */
229 # define CG_FALSE()  CG_BOOLEAN(0)	/* - | false */
230 
231 /* Function instance */
232 # define CG_FUNC(fn) \
233 	(*cc->code->code_class->gen_func)(cc->code, fn)	/* - | obj */
234 
235 /* Record source location */
236 # define CG_LOC(loc) \
237 	(*cc->code->code_class->gen_loc)(cc->code, loc)
238 
239 /* Branching and patching */
240 # define CG_HERE()						\
241 	(*cc->code->code_class->here)(cc->code)
242 
243 /* Patch a previously saved address to point to CG_HERE() */
244 # define CG_LABEL(var)						\
245 	(*cc->code->code_class->patch)(cc->code, var, CG_HERE())
246 
247 # define _CG_OPA(name, patchp, addr)				\
248     (*cc->code->code_class->gen_opa)(cc->code, SEE_CODE_##name, patchp, addr)
249 
250 /* Backward (_b) and forward (_f) branching */
251 # define CG_B_ALWAYS_b(addr)		_CG_OPA(B_ALWAYS, 0, addr)
252 # define CG_B_TRUE_b(addr)		_CG_OPA(B_TRUE, 0, addr)
253 # define CG_B_ENUM_b(addr)		_CG_OPA(B_ENUM, 0, addr)
254 # define CG_S_TRYC_b(addr)		_CG_OPA(S_TRYC, 0, addr)
255 # define CG_S_TRYF_b(addr)		_CG_OPA(S_TRYF, 0, addr)
256 
257 # define CG_B_ALWAYS_f(var)		_CG_OPA(B_ALWAYS, &(var), 0)
258 # define CG_B_TRUE_f(var)		_CG_OPA(B_TRUE, &(var), 0)
259 # define CG_B_ENUM_f(var)		_CG_OPA(B_ENUM, &(var), 0)
260 # define CG_S_TRYC_f(var)		_CG_OPA(S_TRYC, &(var), 0)
261 # define CG_S_TRYF_f(var)		_CG_OPA(S_TRYF, &(var), 0)
262 
263 /* Execute program code */
264 # define CG_EXEC(co, ctxt, res)		(*(co)->code_class->exec)(co, ctxt, res)
265 
266 /* Creates a new patchables for breaking/continuing */
267 static void
push_patchables(cc,target,continuable)268 push_patchables(cc, target, continuable)
269 	struct code_context *cc;
270 	unsigned int target;
271 	int continuable;
272 {
273 	struct patchables *p;
274 	struct SEE_interpreter *interp = cc->code->interpreter;
275 
276 	/* Initialise two empty lists of patchable locations */
277 	p = SEE_NEW(interp, struct patchables);
278 	SEE_GROW_INIT(interp, &p->gcont_patch, p->cont_patch,
279 	    p->ncont_patch);
280 	SEE_GROW_INIT(interp, &p->gbreak_patch, p->break_patch,
281 	    p->nbreak_patch);
282 	p->target = target;
283 	p->continuable = continuable;
284 	p->block_depth = cc->block_depth;
285 	p->prev = cc->patchables;
286 	cc->patchables = p;
287 }
288 
289 /* Pops a patchables, performing the previously pending patches */
290 static void
pop_patchables(cc,cont_addr,break_addr)291 pop_patchables(cc, cont_addr, break_addr)
292 	struct code_context *cc;
293 	SEE_code_addr_t cont_addr;
294 	SEE_code_addr_t break_addr;
295 {
296 	struct patchables *p = cc->patchables;
297 	unsigned int i;
298 
299 	/* Patch the continue locations with the break addresses */
300 	for (i = 0; i < p->ncont_patch; i++) {
301 #ifndef NDEBUG
302 	    if (SEE_parse_debug)
303 		dprintf("patching continue to 0x%x at 0x%x\n",
304 		    cont_addr, p->cont_patch[i]);
305 #endif
306 	    (*cc->code->code_class->patch)(cc->code, p->cont_patch[i],
307 		cont_addr);
308 	}
309 
310 	/* Patch the break locations with the break address */
311 	for (i = 0; i < p->nbreak_patch; i++) {
312 #ifndef NDEBUG
313 	    if (SEE_parse_debug)
314 		dprintf("patching break to 0x%x at 0x%x\n",
315 		    break_addr, p->break_patch[i]);
316 #endif
317 	    (*cc->code->code_class->patch)(cc->code, p->break_patch[i],
318 		break_addr);
319 	}
320 
321 	cc->patchables = p->prev;
322 }
323 
324 /* Return the right patchables when breaking/continuing */
325 static struct patchables *
patch_find(cc,target,type)326 patch_find(cc, target, type)
327 	struct code_context *cc;
328 	unsigned int target;
329 	int type;    /* PATCH_FIND_BREAK or PATCH_FIND_CONTINUE */
330 {
331 	struct patchables *p;
332 
333 	if (target == NO_TARGET && type == PATCH_FIND_CONTINUE) {
334 	    for (p = cc->patchables; p; p = p->prev)
335 		if (p->continuable)
336 		    return p;
337 	} else if (target == NO_TARGET)
338 	    return cc->patchables;
339 	else
340 	    for (p = cc->patchables; p; p = p->prev)
341 		if (p->target == target)
342 		    return p;
343 	SEE_ASSERT(cc->code->interpreter, !"lost patchable");
344 	/* UNREACHABLE */
345 	return NULL;
346 }
347 
348 /* Add a pending continue patch */
349 static void
patch_add_continue(cc,p,pa)350 patch_add_continue(cc, p, pa)
351 	struct code_context *cc;
352 	struct patchables *p;
353 	SEE_code_patchable_t pa;
354 {
355 	struct SEE_interpreter *interp = cc->code->interpreter;
356 	unsigned int n = p->ncont_patch;
357 
358 	SEE_GROW_TO(interp, &p->gcont_patch, n + 1);
359 	p->cont_patch[n] = pa;
360 }
361 
362 /* Add a pending break patch */
363 static void
patch_add_break(cc,p,pa)364 patch_add_break(cc, p, pa)
365 	struct code_context *cc;
366 	struct patchables *p;
367 	SEE_code_patchable_t pa;
368 {
369 	struct SEE_interpreter *interp = cc->code->interpreter;
370 	unsigned int n = p->nbreak_patch;
371 
372 	SEE_GROW_TO(interp, &p->gbreak_patch, n + 1);
373 	p->break_patch[n] = pa;
374 }
375 
376 static void
cg_init(interp,cc,no_const)377 cg_init(interp, cc, no_const)
378 	struct SEE_interpreter *interp;
379 	struct code_context *cc;
380 	int no_const;
381 {
382 	cc->code = (*SEE_system.code_alloc)(interp);
383 	cc->patchables = NULL;
384 	cc->block_depth = 0;
385 	cc->max_block_depth = 0;
386 	cc->in_var_scope = 1;
387 	cc->no_const = no_const;
388 	SEE_GROW_INIT(interp, &cc->gvarscope, cc->varscope, cc->nvarscope);
389 }
390 
391 static struct SEE_code *
cg_fini(interp,cc,maxstack)392 cg_fini(interp, cc, maxstack)
393 	struct SEE_interpreter *interp;
394 	struct code_context *cc;
395 	unsigned int maxstack;
396 {
397 	struct SEE_code *co = cc->code;
398 
399 	SEE_ASSERT(interp, cc->block_depth == 0);
400 	SEE_ASSERT(interp, cc->in_var_scope);
401 	(*co->code_class->maxstack)(co, maxstack);
402 	(*co->code_class->maxblock)(co, cc->max_block_depth);
403 	(*co->code_class->close)(co);
404 	cc->code = NULL;
405 	return co;
406 }
407 
408 /*
409  * Evaluates a (constant) expression node, and then generates a LITERAL
410  * instruction.
411  */
412 static void
cg_const_codegen(node,cc)413 cg_const_codegen(node, cc)
414 	struct node *node;
415 	struct code_context *cc;
416 {
417 	struct SEE_value value;
418 
419 	_SEE_const_evaluate(node, cc->code->interpreter, &value);
420 	CG_LITERAL(&value);
421 	switch (SEE_VALUE_GET_TYPE(&value)) {
422 	case SEE_UNDEFINED: node->is = CG_TYPE_UNDEFINED; break;
423 	case SEE_NULL:	    node->is = CG_TYPE_NULL;	  break;
424 	case SEE_BOOLEAN:   node->is = CG_TYPE_BOOLEAN;   break;
425 	case SEE_NUMBER:    node->is = CG_TYPE_NUMBER;    break;
426 	case SEE_STRING:    node->is = CG_TYPE_STRING;    break;
427 	case SEE_OBJECT:    node->is = CG_TYPE_OBJECT;    break;
428 	case SEE_REFERENCE: node->is = CG_TYPE_REFERENCE; break;
429 	default:	    node->is = 0;
430 	}
431 	node->maxstack = 1;
432 }
433 
434 /* Called when entering a block. Increments the block depth */
435 static void
cg_block_enter(cc)436 cg_block_enter(cc)
437 	struct code_context *cc;
438 {
439 	cc->block_depth++;
440 	if (cc->block_depth > cc->max_block_depth)
441 	    cc->max_block_depth = cc->block_depth;
442 }
443 
444 /* Called when leaving a block. Restores the block depth */
445 static void
cg_block_leave(cc)446 cg_block_leave(cc)
447 	struct code_context *cc;
448 {
449 	cc->block_depth--;
450 }
451 
452 /* Returns the current block depth, suitable for CG_END() */
453 static unsigned int
cg_block_current(cc)454 cg_block_current(cc)
455 	struct code_context *cc;
456 {
457 	return cc->block_depth;
458 }
459 
460 /* Returns the VREF ID of a identifier in the immediate variable scope */
461 static unsigned int
cg_var_id(cc,ident)462 cg_var_id(cc, ident)
463 	struct code_context *cc;
464 	struct SEE_string *ident;
465 {
466 	unsigned int i;
467 
468 	for (i = 0; i < cc->nvarscope; i++)
469 	    if (cc->varscope[i].ident == ident) {
470 #ifndef NDEBUG
471 		if (SEE_parse_debug) {
472 		    dprintf("cg_var_id(");
473 		    dprints(ident);
474 		    dprintf(") = %u\n", cc->varscope[i].id);
475 		}
476 #endif
477 		return cc->varscope[i].id;
478 	    }
479 	SEE_ASSERT(cc->code->interpreter, !"bad cg var identifier");
480 	return ~0; /* unreachable */
481 }
482 
483 /* Returns true if the identifier is a variable in the immediate scope */
484 static int
cg_var_is_in_scope(cc,ident)485 cg_var_is_in_scope(cc, ident)
486 	struct code_context *cc;
487 	struct SEE_string *ident;
488 {
489 	unsigned int i;
490 
491 	/* If in a 'with' block, then nothing is certain */
492 	if (cc->in_var_scope)
493 	    for (i = 0; i < cc->nvarscope; i++)
494 		if (cc->varscope[i].ident == ident) {
495 #ifndef NDEBUG
496 		    if (SEE_parse_debug) {
497 			dprintf("cg_var_is_in_scope(");
498 			dprints(ident);
499 			dprintf("): found, in_scope=%d\n",
500 			    cc->varscope[i].in_scope);
501 		    }
502 #endif
503 		    return cc->varscope[i].in_scope;
504 		}
505 #ifndef NDEBUG
506 	if (SEE_parse_debug) {
507 	    dprintf("cg_var_is_in_scope(");
508 	    dprints(ident);
509 	    dprintf("): not found\n");
510 	}
511 #endif
512 	return 0;
513 }
514 
515 /* Sets the scope of a variable identifier */
516 static void
cg_var_set_scope(cc,ident,in_scope)517 cg_var_set_scope(cc, ident, in_scope)
518 	struct code_context *cc;
519 	struct SEE_string *ident;
520 	int in_scope;
521 {
522 	unsigned int i;
523 
524 	for (i = 0; i < cc->nvarscope; i++)
525 	    if (cc->varscope[i].ident == ident) {
526 #ifndef NDEBUG
527 		if (SEE_parse_debug) {
528 		    dprintf("cg_var_set_scope(");
529 		    dprints(ident);
530 		    dprintf(", %d): previously %d\n",
531 			in_scope, cc->varscope[i].in_scope);
532 		}
533 #endif
534 		cc->varscope[i].in_scope = in_scope;
535 		return;
536 	    }
537 	if (in_scope) {
538 	    SEE_GROW_TO(cc->code->interpreter, &cc->gvarscope,
539 			cc->nvarscope + 1);
540 	    cc->varscope[i].ident = ident;
541 	    cc->varscope[i].id =
542 		(*cc->code->code_class->gen_var)(cc->code, ident);
543 	    cc->varscope[i].in_scope = 1;
544 #ifndef NDEBUG
545 	    if (SEE_parse_debug) {
546 		dprintf("cg_var_set_scope(");
547 		dprints(ident);
548 		dprintf(", %d): NEW (id %u)\n", in_scope, cc->varscope[i].id);
549 	    }
550 #endif
551 	}
552 }
553 
554 /* Temporarily sets the scope visibility of all var idents. Returns old value.
555  * This is used when entering a 'with' scope */
556 static int
cg_var_set_all_scope(cc,in_scope)557 cg_var_set_all_scope(cc, in_scope)
558 	struct code_context *cc;
559 	int in_scope;
560 {
561 	int old_scope = cc->in_var_scope;
562 	cc->in_var_scope = in_scope;
563 #ifndef NDEBUG
564 	if (SEE_parse_debug)
565 	    dprintf("cg_var_set_all_scope(%d) -> %d\n", in_scope, old_scope);
566 #endif
567 	return old_scope;
568 }
569 
570 /* Returns a body suitable for use by eval_functionbody() */
571 void *
_SEE_codegen_make_body(interp,node,no_const)572 _SEE_codegen_make_body(interp, node, no_const)
573 	struct SEE_interpreter *interp;
574 	struct node *node;
575 	int no_const;
576 {
577 	struct code_context ccstorage, *cc;
578 
579 	/* If there is no body, return NULL */
580 	if (_SEE_node_functionbody_isempty(interp, node))
581 	    return NULL;
582 
583 	cc = &ccstorage;
584 	cg_init(interp, cc, no_const);
585 	CODEGEN(node);
586 	return cg_fini(interp, cc, node->maxstack);
587 }
588 
589 /* 7.8 */
590 static void
Literal_codegen(na,cc)591 Literal_codegen(na, cc)
592 	struct node *na;
593 	struct code_context *cc;
594 {
595 	struct Literal_node *n = CAST_NODE(na, Literal);
596 
597 	CG_LITERAL(&n->value);		    /* val */
598 	if (SEE_VALUE_GET_TYPE(&n->value) == SEE_BOOLEAN)
599 	    n->node.is = CG_TYPE_BOOLEAN;
600 	else if (SEE_VALUE_GET_TYPE(&n->value) == SEE_NULL)
601 	    n->node.is = CG_TYPE_NULL;
602 	n->node.maxstack = 1;
603 }
604 
605 /* 7.8.4 */
606 static void
StringLiteral_codegen(na,cc)607 StringLiteral_codegen(na, cc)
608 	struct node *na;
609 	struct code_context *cc;
610 {
611 	struct StringLiteral_node *n = CAST_NODE(na, StringLiteral);
612 
613 	CG_STRING(n->string);		/* str */
614 	n->node.is = CG_TYPE_STRING;
615 	n->node.maxstack = 1;
616 }
617 
618 /* 7.8.5 */
619 static void
RegularExpressionLiteral_codegen(na,cc)620 RegularExpressionLiteral_codegen(na, cc)
621 	struct node *na;
622 	struct code_context *cc;
623 {
624 	struct RegularExpressionLiteral_node *n =
625 		CAST_NODE(na, RegularExpressionLiteral);
626 
627 	SEE_ASSERT(cc->code->interpreter,
628 	    SEE_VALUE_GET_TYPE(&n->pattern) == SEE_STRING);
629 	SEE_ASSERT(cc->code->interpreter,
630 	    SEE_VALUE_GET_TYPE(&n->flags) == SEE_STRING);
631 
632 	CG_REGEXP();			/* obj */
633 	CG_STRING(n->pattern.u.string);	/* obj str */
634 	CG_STRING(n->flags.u.string);	/* obj str str */
635 	CG_NEW(2);			/* obj */
636 
637 	n->node.is = CG_TYPE_OBJECT;
638 	n->node.maxstack = 3;
639 }
640 
641 /* 11.1.1 */
642 static void
PrimaryExpression_this_codegen(n,cc)643 PrimaryExpression_this_codegen(n, cc)
644 	struct node *n;
645 	struct code_context *cc;
646 {
647 	CG_THIS();		/* obj */
648 
649 	n->is = CG_TYPE_OBJECT;
650 	n->maxstack = 1;
651 }
652 
653 /* 11.1.2 */
654 static void
PrimaryExpression_ident_codegen(na,cc)655 PrimaryExpression_ident_codegen(na, cc)
656 	struct node *na;
657 	struct code_context *cc;
658 {
659 	struct PrimaryExpression_ident_node *n =
660 		CAST_NODE(na, PrimaryExpression_ident);
661 
662 	if (cg_var_is_in_scope(cc, n->string))
663 	    CG_VREF(cg_var_id(cc, n->string));	/* ref */
664 	else {
665 	    CG_STRING(n->string);		/* str */
666 	    CG_LOOKUP();			/* ref */
667 	}
668 
669 	n->node.is = CG_TYPE_REFERENCE;
670 	n->node.maxstack = 2;
671 }
672 
673 /* 11.1.4 */
674 static void
ArrayLiteral_codegen(na,cc)675 ArrayLiteral_codegen(na, cc)
676 	struct node *na;
677 	struct code_context *cc;
678 {
679 	struct ArrayLiteral_node *n = CAST_NODE(na, ArrayLiteral);
680 	struct ArrayLiteral_element *element;
681 	struct SEE_string *ind;
682 	struct SEE_interpreter *interp = cc->code->interpreter;
683 	unsigned int maxstack = 0;
684 
685 	ind = SEE_string_new(interp, 16);
686 
687 	CG_ARRAY();			    /* Array */
688 	CG_NEW(0);			    /* a */
689 
690 	for (element = n->first; element; element = element->next) {
691 		CG_DUP();		    /* a a */
692 		ind->length = 0;
693 		SEE_string_append_int(ind, element->index);
694 		CG_STRING(SEE_intern(interp, ind)); /* a a "element" */
695 		CG_REF();		    /* a a[element] */
696 		CODEGEN(element->expr);	    /* a a[element] ref */
697 		maxstack = MAX(maxstack, element->expr->maxstack);
698 
699 		if (!CG_IS_VALUE(element->expr))
700 		    CG_GETVALUE();	    /* a a[element] val */
701 		CG_PUTVALUE();		    /* a */
702 	}
703 
704 	CG_DUP();			    /* a a */
705 	CG_STRING(STR(length));		    /* a a "length" */
706 	CG_REF();			    /* a a.length */
707 	CG_NUMBER(n->length);		    /* a a.length num */
708 	CG_PUTVALUE();			    /* a */
709 
710 	n->node.is = CG_TYPE_OBJECT;
711 	n->node.maxstack = MAX(3, 2 + maxstack);
712 }
713 
714 /* 11.1.5 */
715 static void
ObjectLiteral_codegen(na,cc)716 ObjectLiteral_codegen(na, cc)
717 	struct node *na;
718 	struct code_context *cc;
719 {
720 	struct ObjectLiteral_node *n = CAST_NODE(na, ObjectLiteral);
721 	struct ObjectLiteral_pair *pair;
722 	unsigned int maxstack = 0;
723 
724 	CG_OBJECT();			    /* Object */
725 	CG_NEW(0);			    /* o */
726 	for (pair = n->first; pair; pair = pair->next) {
727 		CG_DUP();		    /* o o */
728 		CG_STRING(pair->name);	    /* o o name */
729 		CG_REF();		    /* o o.name */
730 		CODEGEN(pair->value);	    /* o o.name ref */
731 		maxstack = MAX(maxstack, pair->value->maxstack);
732 		if (!CG_IS_VALUE(pair->value))
733 		    CG_GETVALUE();	    /* o o.name val */
734 		CG_PUTVALUE();		    /* o */
735 	}
736 
737 	n->node.is = CG_TYPE_OBJECT;
738 	n->node.maxstack = MAX(maxstack + 2, 3);
739 }
740 
741 /* 11.2.4 */
742 static void
Arguments_codegen(na,cc)743 Arguments_codegen(na, cc)
744 	struct node *na;
745 	struct code_context *cc;
746 {
747 	struct Arguments_node *n = CAST_NODE(na, Arguments);
748 	struct Arguments_arg *arg;
749 	unsigned int maxstack = 0;
750 	unsigned int onstack = 0;
751 
752 	for (arg = n->first; arg; arg = arg->next) {
753 					    /* ... */
754 		CODEGEN(arg->expr);	    /* ... ref */
755 		maxstack = MAX(maxstack, onstack + arg->expr->maxstack);
756 		if (!CG_IS_VALUE(arg->expr))
757 		    CG_GETVALUE();	    /* ... val */
758 		onstack++;
759 	}
760 	n->node.maxstack = maxstack;
761 }
762 
763 /* 11.2.2 */
764 static void
MemberExpression_new_codegen(na,cc)765 MemberExpression_new_codegen(na, cc)
766 	struct node *na;
767 	struct code_context *cc;
768 {
769 	struct MemberExpression_new_node *n =
770 		CAST_NODE(na, MemberExpression_new);
771 	int argc;
772 	int maxstack = 0;
773 
774 	CODEGEN(n->mexp);		/* ref */
775 	maxstack = n->mexp->maxstack;
776 	if (!CG_IS_VALUE(n->mexp))
777 	    CG_GETVALUE();		/* val */
778 	if (n->args) {
779 		Arguments_codegen((struct node *)n->args, cc);
780 					/* val arg1..argn */
781 		argc = n->args->argc;
782 		maxstack = MAX(maxstack, 1+((struct node *)n->args)->maxstack);
783 	} else
784 		argc = 0;
785 	CG_NEW(argc);			/* obj */
786 
787 	/* Assume that 'new' always yields an object by s8.6.2 */
788 	n->node.is = CG_TYPE_OBJECT;
789 	n->node.maxstack = maxstack;
790 }
791 
792 /* 11.2.1 */
793 static void
MemberExpression_dot_codegen(na,cc)794 MemberExpression_dot_codegen(na, cc)
795 	struct node *na;
796 	struct code_context *cc;
797 {
798 	struct MemberExpression_dot_node *n =
799 		CAST_NODE(na, MemberExpression_dot);
800 
801 	CODEGEN(n->mexp);	    /* ref */
802 	if (!CG_IS_VALUE(n->mexp))
803 	    CG_GETVALUE();	    /* val */
804 	if (!CG_IS_OBJECT(n->mexp))
805 	    CG_TOOBJECT();	    /* obj */
806 	CG_STRING(n->name);	    /* obj "name" */
807 	CG_REF();		    /* ref */
808 
809 	n->node.is = CG_TYPE_REFERENCE;
810 	n->node.maxstack = MAX(2, n->mexp->maxstack);
811 }
812 
813 /* 11.2.1 */
814 static void
MemberExpression_bracket_codegen(na,cc)815 MemberExpression_bracket_codegen(na, cc)
816 	struct node *na;
817 	struct code_context *cc;
818 {
819 	struct MemberExpression_bracket_node *n =
820 		CAST_NODE(na, MemberExpression_bracket);
821 
822 	CODEGEN(n->mexp);	    /* ref1 */
823 	if (!CG_IS_VALUE(n->mexp))
824 	    CG_GETVALUE();	    /* val1 */
825 	CODEGEN(n->name);	    /* val1 ref2 */
826 	if (!CG_IS_VALUE(n->name))
827 	    CG_GETVALUE();	    /* val1 val2 */
828 	/* Note: we have to fritz with EXCH to match
829 	 * the semantics of 11.2.1 */
830 	if (!CG_IS_OBJECT(n->mexp)) {
831 	    CG_EXCH();		    /* val2 val1 */
832 	    CG_TOOBJECT();	    /* val2 obj1 */
833 	    CG_EXCH();		    /* obj1 val2 */
834 	}
835 	if (!CG_IS_STRING(n->name))
836 	    CG_TOSTRING();	    /* obj1 str2 */
837 	CG_REF();		    /* ref */
838 
839 	n->node.is = CG_TYPE_REFERENCE;
840 	n->node.maxstack = MAX(n->mexp->maxstack, 1 + n->name->maxstack);
841 }
842 
843 /* 11.2.3 */
844 static void
CallExpression_codegen(na,cc)845 CallExpression_codegen(na, cc)
846 	struct node *na;
847 	struct code_context *cc;
848 {
849 	struct CallExpression_node *n = CAST_NODE(na, CallExpression);
850 
851 	CODEGEN(n->exp);		/* ref */
852 	Arguments_codegen((struct node *)n->args, cc);	/* ref arg1 .. argn */
853 	CG_CALL(n->args->argc);		/* val */
854 
855 	/* Called functions only return values */
856 	n->node.is = CG_TYPE_VALUE;
857 	n->node.maxstack = MAX(n->exp->maxstack,
858 	    1 + ((struct node *)n->args)->maxstack);
859 }
860 
861 /* 11.3.1 */
862 static void
PostfixExpression_inc_codegen(na,cc)863 PostfixExpression_inc_codegen(na, cc)
864 	struct node *na;
865 	struct code_context *cc;
866 {
867 	struct Unary_node *n = CAST_NODE(na, Unary);
868 
869 	CODEGEN(n->a);		/* ref */
870 	CG_DUP();		/* ref ref */
871 	if (!CG_IS_VALUE(n->a))
872 	    CG_GETVALUE();	/* ref val */
873 	if (!CG_IS_NUMBER(n->a))
874 	    CG_TONUMBER();	/* ref num */
875 	CG_DUP();		/* ref num num */
876 	CG_ROLL3();		/* num ref num */
877 	CG_NUMBER(1);		/* num ref num   1 */
878 	CG_ADD();		/* num ref num+1 */
879 	CG_PUTVALUE();		/* num */
880 
881 	n->node.is = CG_TYPE_NUMBER;
882 	n->node.maxstack = MAX(n->a->maxstack, 4);
883 
884 	/*
885 	 * Peephole optimisation note:
886 	 *		ref num
887 	 *  DUP		ref num num
888 	 *  ROLL3       num ref num
889 	 *  LITERAL,?   num ref num ?
890 	 *  ADD|SUB     num ref ?
891 	 *  PUTVALUE    num
892 	 *  POP         -
893 	 *
894 	 * is equivalent to:
895 	 *              ref num
896 	 *  LITERAL,?   ref num ?
897 	 *  ADD|SUB     ref ?
898 	 *  PUTVALUE	-
899 	 */
900 
901 	/*
902 	 * Peephole optimisation note:
903 	 *		ref num
904 	 *  DUP		ref num num
905 	 *  ROLL3       num ref num
906 	 *  LITERAL,?   num ref num ?
907 	 *  ADD|SUB     num ref ?
908 	 *  PUTVALUE    num
909 	 *  SETC        -
910 	 *
911 	 * is equivalent to:
912 	 *              ref num
913 	 *  LITERAL,?   ref num ?
914 	 *  ADD|SUB     ref ?
915 	 *  DUP		ref ? ?
916 	 *  SETC	ref ?
917 	 *  PUTVALUE	-
918 	 */
919 
920 }
921 
922 /* 11.3.2 */
923 static void
PostfixExpression_dec_codegen(na,cc)924 PostfixExpression_dec_codegen(na, cc)
925 	struct node *na;
926 	struct code_context *cc;
927 {
928 	struct Unary_node *n = CAST_NODE(na, Unary);
929 
930 	CODEGEN(n->a);		/* aref */
931 	CG_DUP();		/* aref aref */
932 	if (!CG_IS_VALUE(n->a))
933 	    CG_GETVALUE();	/* aref aval */
934 	if (!CG_IS_NUMBER(n->a))
935 	    CG_TONUMBER();	/* aref anum */
936 	CG_DUP();		/* aref anum anum */
937 	CG_ROLL3();		/* anum aref anum */
938 	CG_NUMBER(1);		/* anum aref anum   1 */
939 	CG_SUB();		/* anum aref anum-1 */
940 	CG_PUTVALUE();		/* anum */
941 
942 	n->node.is = CG_TYPE_NUMBER;
943 	n->node.maxstack = MAX(n->a->maxstack, 4);
944 }
945 
946 /* 11.4.1 */
947 static void
UnaryExpression_delete_codegen(na,cc)948 UnaryExpression_delete_codegen(na, cc)
949 	struct node *na;
950 	struct code_context *cc;
951 {
952 	struct Unary_node *n = CAST_NODE(na, Unary);
953 
954 	CODEGEN(n->a);	/* ref */
955 	CG_DELETE();	/* bool */
956 
957 	n->node.is = CG_TYPE_BOOLEAN;
958 	n->node.maxstack = n->a->maxstack;
959 }
960 
961 /* 11.4.2 */
962 static void
UnaryExpression_void_codegen(na,cc)963 UnaryExpression_void_codegen(na, cc)
964 	struct node *na;
965 	struct code_context *cc;
966 {
967 	struct Unary_node *n = CAST_NODE(na, Unary);
968 	static const struct SEE_value cg_undefined = { SEE_UNDEFINED };
969 
970 	CODEGEN(n->a);		    /* ref */
971 	if (!CG_IS_VALUE(n->a))
972 	    CG_GETVALUE();	    /* val */
973 	CG_POP();		    /* - */
974 	CG_LITERAL(&cg_undefined);  /* undef */
975 
976 	n->node.is = CG_TYPE_UNDEFINED;
977 	n->node.maxstack = n->a->maxstack;
978 }
979 
980 /* 11.4.3 */
981 static void
UnaryExpression_typeof_codegen(na,cc)982 UnaryExpression_typeof_codegen(na, cc)
983 	struct node *na;
984 	struct code_context *cc;
985 {
986 	struct Unary_node *n = CAST_NODE(na, Unary);
987 
988 	CODEGEN(n->a);	    /* ref */
989 	CG_TYPEOF();	    /* str */
990 
991 	n->node.is = CG_TYPE_STRING;
992 	n->node.maxstack = n->a->maxstack;
993 }
994 
995 /* 11.4.4 */
996 static void
UnaryExpression_preinc_codegen(na,cc)997 UnaryExpression_preinc_codegen(na, cc)
998 	struct node *na;
999 	struct code_context *cc;
1000 {
1001 	struct Unary_node *n = CAST_NODE(na, Unary);
1002 
1003 	/* Note: Makes no sense to check n->a is already a value */
1004 	CODEGEN(n->a);	/* aref */
1005 	CG_DUP();	/* aref aref */
1006 	CG_GETVALUE();	/* aref aval */
1007 	CG_TONUMBER();	/* aref anum */
1008 	CG_NUMBER(1);	/* aref anum 1 */
1009 	CG_ADD();	/* aref anum+1 */
1010 	CG_DUP();	/* aref anum+1 anum+1 */
1011 	CG_ROLL3();	/* anum+1 aref anum+1 */
1012 	CG_PUTVALUE();	/* anum+1 */
1013 
1014 	n->node.is = CG_TYPE_NUMBER;
1015 	n->node.maxstack = MAX(n->a->maxstack, 3);
1016 }
1017 
1018 /* 11.4.5 */
1019 static void
UnaryExpression_predec_codegen(na,cc)1020 UnaryExpression_predec_codegen(na, cc)
1021 	struct node *na;
1022 	struct code_context *cc;
1023 {
1024 	struct Unary_node *n = CAST_NODE(na, Unary);
1025 
1026 	/* Note: Makes no sense to check n->a is already a value */
1027 	CODEGEN(n->a);	/* aref */
1028 	CG_DUP();	/* aref aref */
1029 	CG_GETVALUE();	/* aref aval */
1030 	CG_TONUMBER();	/* aref anum */
1031 	CG_NUMBER(1);	/* aref anum 1 */
1032 	CG_SUB();	/* aref anum-1 */
1033 	CG_DUP();	/* aref anum-1 anum-1 */
1034 	CG_ROLL3();   	/* anum-1 aref anum-1 */
1035 	CG_PUTVALUE();	/* anum-1 */
1036 
1037 	n->node.is = CG_TYPE_NUMBER;
1038 	n->node.maxstack = MAX(n->a->maxstack, 3);
1039 }
1040 
1041 /* 11.4.6 */
1042 static void
UnaryExpression_plus_codegen(na,cc)1043 UnaryExpression_plus_codegen(na, cc)
1044 	struct node *na;
1045 	struct code_context *cc;
1046 {
1047 	struct Unary_node *n = CAST_NODE(na, Unary);
1048 
1049 	CODEGEN(n->a);		/* aref */
1050 	if (!CG_IS_VALUE(n->a))
1051 	    CG_GETVALUE();	/* aval */
1052 	if (!CG_IS_NUMBER(n->a))
1053 	    CG_TONUMBER();	/* anum */
1054 
1055 	n->node.is = CG_TYPE_NUMBER;
1056 	n->node.maxstack = n->a->maxstack;
1057 }
1058 
1059 /* 11.4.7 */
1060 static void
UnaryExpression_minus_codegen(na,cc)1061 UnaryExpression_minus_codegen(na, cc)
1062 	struct node *na;
1063 	struct code_context *cc;
1064 {
1065 	struct Unary_node *n = CAST_NODE(na, Unary);
1066 
1067 	CODEGEN(n->a);		/* aref */
1068 	if (!CG_IS_VALUE(n->a))
1069 	    CG_GETVALUE();	/* aval */
1070 	if (!CG_IS_NUMBER(n->a))
1071 	    CG_TONUMBER();	/* anum */
1072 	CG_NEG();		/* -anum */
1073 
1074 	n->node.is = CG_TYPE_NUMBER;
1075 	n->node.maxstack = n->a->maxstack;
1076 }
1077 
1078 /* 11.4.8 */
1079 static void
UnaryExpression_inv_codegen(na,cc)1080 UnaryExpression_inv_codegen(na, cc)
1081 	struct node *na;
1082 	struct code_context *cc;
1083 {
1084 	struct Unary_node *n = CAST_NODE(na, Unary);
1085 
1086 	CODEGEN(n->a);		/* aref */
1087 	if (!CG_IS_VALUE(n->a))
1088 	    CG_GETVALUE();	/* aval */
1089 	CG_INV();		/* ~aval */
1090 
1091 	n->node.is = CG_TYPE_NUMBER;
1092 	n->node.maxstack = n->a->maxstack;
1093 }
1094 
1095 /* 11.4.9 */
1096 static void
UnaryExpression_not_codegen(na,cc)1097 UnaryExpression_not_codegen(na, cc)
1098 	struct node *na;
1099 	struct code_context *cc;
1100 {
1101 	struct Unary_node *n = CAST_NODE(na, Unary);
1102 
1103 	CODEGEN(n->a);		    /* aref */
1104 	if (!CG_IS_VALUE(n->a))
1105 	    CG_GETVALUE();	    /* aval */
1106 	if (!CG_IS_BOOLEAN(n->a))
1107 	    CG_TOBOOLEAN();	    /* abool */
1108 	CG_NOT();		    /* !abool */
1109 
1110 	n->node.is = CG_TYPE_BOOLEAN;
1111 	n->node.maxstack = n->a->maxstack;
1112 }
1113 
1114 static void
Binary_common_codegen(n,cc)1115 Binary_common_codegen(n, cc)
1116 	struct Binary_node *n;
1117 	struct code_context *cc;
1118 {
1119 	CODEGEN(n->a);	    /* aref */
1120 	if (!CG_IS_VALUE(n->a))
1121 	    CG_GETVALUE();  /* aval */
1122 	CODEGEN(n->b);	    /* aval bref */
1123 	if (!CG_IS_VALUE(n->b))
1124 	    CG_GETVALUE();  /* aval bval */
1125 }
1126 
1127 static void
MultiplicativeExpression_common_codegen(n,cc)1128 MultiplicativeExpression_common_codegen(n, cc)
1129 	struct Binary_node *n;
1130 	struct code_context *cc;
1131 {
1132 	Binary_common_codegen(n, cc); /* val val */
1133 	if (!CG_IS_NUMBER(n->a)) {
1134 	    /* Exchanges needed to match spec semantics */
1135 	    CG_EXCH();	    /* bval aval */
1136 	    CG_TONUMBER();  /* bval anum */
1137 	    CG_EXCH();	    /* anum bval */
1138 	}
1139 	if (!CG_IS_NUMBER(n->b))
1140 	    CG_TONUMBER();  /* anum bnum */
1141 
1142 	n->node.is = CG_TYPE_NUMBER;
1143 	n->node.maxstack = MAX(n->a->maxstack, 1 + n->b->maxstack);
1144 }
1145 
1146 /* 11.5.1 */
1147 static void
MultiplicativeExpression_mul_codegen(na,cc)1148 MultiplicativeExpression_mul_codegen(na, cc)
1149 	struct node *na;
1150 	struct code_context *cc;
1151 {
1152 	struct Binary_node *n = CAST_NODE(na, Binary);
1153 
1154 	MultiplicativeExpression_common_codegen(n, cc); /* num num */
1155 	CG_MUL();	    /* num */
1156 }
1157 
1158 /* 11.5.2 */
1159 static void
MultiplicativeExpression_div_codegen(na,cc)1160 MultiplicativeExpression_div_codegen(na, cc)
1161 	struct node *na;
1162 	struct code_context *cc;
1163 {
1164 	struct Binary_node *n = CAST_NODE(na, Binary);
1165 
1166 	MultiplicativeExpression_common_codegen(n, cc); /* num num */
1167 	CG_DIV();	    /* num */
1168 }
1169 
1170 /* 11.5.3 */
1171 static void
MultiplicativeExpression_mod_codegen(na,cc)1172 MultiplicativeExpression_mod_codegen(na, cc)
1173 	struct node *na;
1174 	struct code_context *cc;
1175 {
1176 	struct Binary_node *n = CAST_NODE(na, Binary);
1177 
1178 	MultiplicativeExpression_common_codegen(n, cc); /* num num */
1179 	CG_MOD();	    /* num */
1180 }
1181 
1182 /* 11.6.1 */
1183 static void
AdditiveExpression_add_codegen(na,cc)1184 AdditiveExpression_add_codegen(na, cc)
1185 	struct node *na;
1186 	struct code_context *cc;
1187 {
1188 	struct Binary_node *n = CAST_NODE(na, Binary);
1189 
1190 	Binary_common_codegen(n, cc); /* val val */
1191 	if (!CG_IS_PRIMITIVE(n->a)) {
1192 	    CG_EXCH();		/* bval aval */
1193 	    CG_TOPRIMITIVE();	/* bval aprim */
1194 	    CG_EXCH();		/* aprim bval */
1195 	}
1196 	if (!CG_IS_PRIMITIVE(n->b))
1197 	    CG_TOPRIMITIVE();	/* aprim bprim */
1198 	CG_ADD();		/* val */
1199 
1200 	/* Carefully figure out if the result type can be restricted */
1201 	if (CG_IS_STRING(n->a) || CG_IS_STRING(n->b))
1202 	    n->node.is = CG_TYPE_STRING;
1203 	else if (CG_IS_PRIMITIVE(n->a) && CG_IS_PRIMITIVE(n->b))
1204 	    n->node.is = CG_TYPE_NUMBER;
1205 	else
1206 	    n->node.is = CG_TYPE_STRING | CG_TYPE_NUMBER;
1207 	n->node.maxstack = MAX(n->a->maxstack, 1 + n->b->maxstack);
1208 }
1209 
1210 /* 11.6.2 */
1211 static void
AdditiveExpression_sub_codegen(na,cc)1212 AdditiveExpression_sub_codegen(na, cc)
1213 	struct node *na;
1214 	struct code_context *cc;
1215 {
1216 	struct Binary_node *n = CAST_NODE(na, Binary);
1217 
1218 	Binary_common_codegen(n, cc); /* aval bval */
1219 	if (!CG_IS_NUMBER(n->a)) {
1220 	    CG_EXCH();	    /* bval aval */
1221 	    CG_TONUMBER();  /* bval anum */
1222 	    CG_EXCH();	    /* anum bval */
1223 	}
1224 	if (!CG_IS_NUMBER(n->b))
1225 	    CG_TONUMBER();  /* anum bnum */
1226 	CG_SUB();	    /* num */
1227 
1228 	n->node.is = CG_TYPE_NUMBER;
1229 	n->node.maxstack = MAX(n->a->maxstack, 1 + n->b->maxstack);
1230 }
1231 
1232 /* 11.7.1 */
1233 static void
ShiftExpression_lshift_codegen(na,cc)1234 ShiftExpression_lshift_codegen(na, cc)
1235 	struct node *na;
1236 	struct code_context *cc;
1237 {
1238 	struct Binary_node *n = CAST_NODE(na, Binary);
1239 
1240 	Binary_common_codegen(n, cc); /* aval bval */
1241 	CG_LSHIFT();		/* num */
1242 
1243 	n->node.is = CG_TYPE_NUMBER;
1244 	n->node.maxstack = MAX(n->a->maxstack, 1 + n->b->maxstack);
1245 }
1246 
1247 /* 11.7.2 */
1248 static void
ShiftExpression_rshift_codegen(na,cc)1249 ShiftExpression_rshift_codegen(na, cc)
1250 	struct node *na;
1251 	struct code_context *cc;
1252 {
1253 	struct Binary_node *n = CAST_NODE(na, Binary);
1254 
1255 	Binary_common_codegen(n, cc); /* aval bval */
1256 	CG_RSHIFT();		/* num */
1257 
1258 	n->node.is = CG_TYPE_NUMBER;
1259 	n->node.maxstack = MAX(n->a->maxstack, 1 + n->b->maxstack);
1260 }
1261 
1262 /* 11.7.3 */
1263 static void
ShiftExpression_urshift_codegen(na,cc)1264 ShiftExpression_urshift_codegen(na, cc)
1265 	struct node *na;
1266 	struct code_context *cc;
1267 {
1268 	struct Binary_node *n = CAST_NODE(na, Binary);
1269 
1270 	Binary_common_codegen(n, cc); /* aval bval */
1271 	CG_URSHIFT();		      /* num */
1272 
1273 	n->node.is = CG_TYPE_NUMBER;
1274 	n->node.maxstack = MAX(n->a->maxstack, 1 + n->b->maxstack);
1275 }
1276 
1277 /* 11.8.1 */
1278 static void
RelationalExpression_lt_codegen(na,cc)1279 RelationalExpression_lt_codegen(na, cc)
1280 	struct node *na;
1281 	struct code_context *cc;
1282 {
1283 	struct Binary_node *n = CAST_NODE(na, Binary);
1284 
1285 	Binary_common_codegen(n, cc); /* aval bval */
1286 	CG_LT();		      /* bool */
1287 
1288 	n->node.is = CG_TYPE_BOOLEAN;
1289 	n->node.maxstack = MAX(n->a->maxstack, 1 + n->b->maxstack);
1290 }
1291 
1292 /* 11.8.2 */
1293 static void
RelationalExpression_gt_codegen(na,cc)1294 RelationalExpression_gt_codegen(na, cc)
1295 	struct node *na;
1296 	struct code_context *cc;
1297 {
1298 	struct Binary_node *n = CAST_NODE(na, Binary);
1299 
1300 	Binary_common_codegen(n, cc); /* aval bval */
1301 	CG_GT();		      /* bool */
1302 
1303 	n->node.is = CG_TYPE_BOOLEAN;
1304 	n->node.maxstack = MAX(n->a->maxstack, 1 + n->b->maxstack);
1305 }
1306 
1307 /* 11.8.3 */
1308 static void
RelationalExpression_le_codegen(na,cc)1309 RelationalExpression_le_codegen(na, cc)
1310 	struct node *na;
1311 	struct code_context *cc;
1312 {
1313 	struct Binary_node *n = CAST_NODE(na, Binary);
1314 
1315 	Binary_common_codegen(n, cc); /* aval bval */
1316 	CG_LE();		      /* bool */
1317 
1318 	n->node.is = CG_TYPE_BOOLEAN;
1319 	n->node.maxstack = MAX(n->a->maxstack, 1 + n->b->maxstack);
1320 }
1321 
1322 /* 11.8.4 */
1323 static void
RelationalExpression_ge_codegen(na,cc)1324 RelationalExpression_ge_codegen(na, cc)
1325 	struct node *na;
1326 	struct code_context *cc;
1327 {
1328 	struct Binary_node *n = CAST_NODE(na, Binary);
1329 
1330 	Binary_common_codegen(n, cc); /* aval bval */
1331 	CG_GE();		      /* bool */
1332 
1333 	n->node.is = CG_TYPE_BOOLEAN;
1334 	n->node.maxstack = MAX(n->a->maxstack, 1 + n->b->maxstack);
1335 }
1336 
1337 /* 11.8.6 */
1338 static void
RelationalExpression_instanceof_codegen(na,cc)1339 RelationalExpression_instanceof_codegen(na, cc)
1340 	struct node *na;
1341 	struct code_context *cc;
1342 {
1343 	struct Binary_node *n = CAST_NODE(na, Binary);
1344 
1345 	Binary_common_codegen(n, cc); /* aval bval */
1346 	CG_INSTANCEOF();	      /* bool */
1347 
1348 	n->node.is = CG_TYPE_BOOLEAN;
1349 	n->node.maxstack = MAX(n->a->maxstack, 1 + n->b->maxstack);
1350 }
1351 
1352 /* 11.8.7 */
1353 static void
RelationalExpression_in_codegen(na,cc)1354 RelationalExpression_in_codegen(na, cc)
1355 	struct node *na;
1356 	struct code_context *cc;
1357 {
1358 	struct Binary_node *n = CAST_NODE(na, Binary);
1359 
1360 	/* Binary_common_codegen(n, cc); */
1361 	CODEGEN(n->a);			/* aref */
1362 	if (!CG_IS_VALUE(n->a))
1363 	    CG_GETVALUE();		/* aval */
1364 	if (!CG_IS_STRING(n->a))
1365 	    CG_TOSTRING();		/* astr */
1366 	CODEGEN(n->b);			/* astr bref */
1367 	if (!CG_IS_VALUE(n->b))
1368 	    CG_GETVALUE();		/* aval bval */
1369 	CG_IN();		        /* bool */
1370 
1371 	n->node.is = CG_TYPE_BOOLEAN;
1372 	n->node.maxstack = MAX(n->a->maxstack, 1 + n->b->maxstack);
1373 }
1374 
1375 /* 11.9.1 */
1376 static void
EqualityExpression_eq_codegen(na,cc)1377 EqualityExpression_eq_codegen(na, cc)
1378 	struct node *na;
1379 	struct code_context *cc;
1380 {
1381 	struct Binary_node *n = CAST_NODE(na, Binary);
1382 
1383 	Binary_common_codegen(n, cc); /* aval bval */
1384 	CG_EQ();		      /* bool */
1385 
1386 	n->node.is = CG_TYPE_BOOLEAN;
1387 	n->node.maxstack = MAX(n->a->maxstack, 1 + n->b->maxstack);
1388 }
1389 
1390 /* 11.9.2 */
1391 static void
EqualityExpression_ne_codegen(na,cc)1392 EqualityExpression_ne_codegen(na, cc)
1393 	struct node *na;
1394 	struct code_context *cc;
1395 {
1396 	struct Binary_node *n = CAST_NODE(na, Binary);
1397 
1398 	Binary_common_codegen(n, cc); /* aval bval */
1399 	CG_EQ();		      /* bool */
1400 	CG_NOT();		      /* bool */
1401 
1402 	n->node.is = CG_TYPE_BOOLEAN;
1403 	n->node.maxstack = MAX(n->a->maxstack, 1 + n->b->maxstack);
1404 }
1405 
1406 /* 11.9.4 */
1407 static void
EqualityExpression_seq_codegen(na,cc)1408 EqualityExpression_seq_codegen(na, cc)
1409 	struct node *na;
1410 	struct code_context *cc;
1411 {
1412 	struct Binary_node *n = CAST_NODE(na, Binary);
1413 
1414 	Binary_common_codegen(n, cc); /* aval bval */
1415 	CG_SEQ();		      /* bool */
1416 
1417 	n->node.is = CG_TYPE_BOOLEAN;
1418 	n->node.maxstack = MAX(n->a->maxstack, 1 + n->b->maxstack);
1419 }
1420 
1421 /* 11.9.5 */
1422 static void
EqualityExpression_sne_codegen(na,cc)1423 EqualityExpression_sne_codegen(na, cc)
1424 	struct node *na;
1425 	struct code_context *cc;
1426 {
1427 	struct Binary_node *n = CAST_NODE(na, Binary);
1428 
1429 	Binary_common_codegen(n, cc); /* aval bval */
1430 	CG_SEQ();		      /* bool */
1431 	CG_NOT();		      /* bool */
1432 
1433 	n->node.is = CG_TYPE_BOOLEAN;
1434 	n->node.maxstack = MAX(n->a->maxstack, 1 + n->b->maxstack);
1435 }
1436 
1437 /* 11.10 */
1438 static void
BitwiseANDExpression_codegen(na,cc)1439 BitwiseANDExpression_codegen(na, cc)
1440 	struct node *na;
1441 	struct code_context *cc;
1442 {
1443 	struct Binary_node *n = CAST_NODE(na, Binary);
1444 
1445 	Binary_common_codegen(n, cc); /* aval bval */
1446 	CG_BAND();		      /* num */
1447 
1448 	n->node.is = CG_TYPE_NUMBER;
1449 	n->node.maxstack = MAX(n->a->maxstack, 1 + n->b->maxstack);
1450 }
1451 
1452 /* 11.10 */
1453 static void
BitwiseXORExpression_codegen(na,cc)1454 BitwiseXORExpression_codegen(na, cc)
1455 	struct node *na;
1456 	struct code_context *cc;
1457 {
1458 	struct Binary_node *n = CAST_NODE(na, Binary);
1459 
1460 	Binary_common_codegen(n, cc); /* aval bval */
1461 	CG_BXOR();		      /* num */
1462 
1463 	n->node.is = CG_TYPE_NUMBER;
1464 	n->node.maxstack = MAX(n->a->maxstack, 1 + n->b->maxstack);
1465 }
1466 
1467 /* 11.10 */
1468 static void
BitwiseORExpression_codegen(na,cc)1469 BitwiseORExpression_codegen(na, cc)
1470 	struct node *na;
1471 	struct code_context *cc;
1472 {
1473 	struct Binary_node *n = CAST_NODE(na, Binary);
1474 
1475 	Binary_common_codegen(n, cc); /* aval bval */
1476 	CG_BOR();		      /* num */
1477 
1478 	n->node.is = CG_TYPE_NUMBER;
1479 	n->node.maxstack = MAX(n->a->maxstack, 1 + n->b->maxstack);
1480 }
1481 
1482 /* 11.11 */
1483 static void
LogicalANDExpression_codegen(na,cc)1484 LogicalANDExpression_codegen(na, cc)
1485 	struct node *na;
1486 	struct code_context *cc;
1487 {
1488 	struct Binary_node *n = CAST_NODE(na, Binary);
1489 	SEE_code_patchable_t L1, L2;
1490 
1491 	CODEGEN(n->a);				/* ref */
1492 	if (!CG_IS_VALUE(n->a))
1493 	    CG_GETVALUE();			/* val */
1494 	if (!CG_IS_BOOLEAN(n->a))
1495 	    CG_TOBOOLEAN();			/* bool */
1496 	CG_B_TRUE_f(L1);			/* -  (L1)*/
1497 	CG_FALSE();				/* false */
1498 	CG_B_ALWAYS_f(L2);			/* false (2) */
1499 
1500 	CG_LABEL(L1);				/* 1: - */
1501 	CODEGEN(n->b);				/* ref */
1502 	if (!CG_IS_VALUE(n->b))
1503 	    CG_GETVALUE();			/* val */
1504 	if (!CG_IS_BOOLEAN(n->b))
1505 	    CG_TOBOOLEAN();			/* bool */
1506 	CG_LABEL(L2);				/* 2: bool */
1507 
1508 	n->node.is = CG_TYPE_BOOLEAN;
1509 	n->node.maxstack = MAX(n->a->maxstack, n->b->maxstack);
1510 }
1511 
1512 static void
LogicalORExpression_codegen(na,cc)1513 LogicalORExpression_codegen(na, cc)
1514 	struct node *na;
1515 	struct code_context *cc;
1516 {
1517 	struct Binary_node *n = CAST_NODE(na, Binary);
1518 	SEE_code_patchable_t L1, L2;
1519 
1520 	CODEGEN(n->a);				/* ref */
1521 	if (!CG_IS_VALUE(n->a))
1522 	    CG_GETVALUE();			/* val */
1523 	if (!CG_IS_BOOLEAN(n->a))
1524 	    CG_TOBOOLEAN();			/* bool */
1525 	CG_B_TRUE_f(L1);		 	/* -  (1)*/
1526 
1527 	CODEGEN(n->b);				/* ref */
1528 	if (!CG_IS_VALUE(n->b))
1529 	    CG_GETVALUE();			/* val */
1530 	if (!CG_IS_BOOLEAN(n->b))
1531 	    CG_TOBOOLEAN();			/* bool */
1532 
1533 	CG_B_ALWAYS_f(L2);
1534 
1535     CG_LABEL(L1);				/* 1: - */
1536 	CG_TRUE();				/* true */
1537     CG_LABEL(L2);				/* 2: bool */
1538 
1539 	n->node.is = CG_TYPE_BOOLEAN;
1540 	n->node.maxstack = MAX(n->a->maxstack, n->b->maxstack);
1541 }
1542 
1543 /* 11.12 */
1544 static void
ConditionalExpression_codegen(na,cc)1545 ConditionalExpression_codegen(na, cc)
1546 	struct node *na;
1547 	struct code_context *cc;
1548 {
1549 	struct ConditionalExpression_node *n =
1550 		CAST_NODE(na, ConditionalExpression);
1551 	SEE_code_patchable_t L1, L2;
1552 
1553 	CODEGEN(n->a);				/*     ref      */
1554 	if (!CG_IS_VALUE(n->a))
1555 	    CG_GETVALUE();			/*     val      */
1556 	if (!CG_IS_BOOLEAN(n->a))
1557 	    CG_TOBOOLEAN();			/*     bool     */
1558 	CG_B_TRUE_f(L1);			/*     -    (1) */
1559 
1560 	/* The false branch */
1561 	CODEGEN(n->c);				/*     ref      */
1562 	if (!CG_IS_VALUE(n->c))
1563 	    CG_GETVALUE();			/*     val      */
1564 	CG_B_ALWAYS_f(L2);			/*     val  (2) */
1565 
1566 	/* The true branch */
1567 	CG_LABEL(L1);				/* 1:  -        */
1568 	CODEGEN(n->b);				/*     ref      */
1569 	if (!CG_IS_VALUE(n->b))
1570 	    CG_GETVALUE();			/*     val      */
1571 
1572 	CG_LABEL(L2);				/* 2:  val      */
1573 
1574 	if (!CG_IS_VALUE(n->b) || !CG_IS_VALUE(n->c))
1575 	    n->node.is = CG_TYPE_VALUE;
1576 	else
1577 	    n->node.is = n->b->is | n->c->is;
1578 	n->node.maxstack = MAX3(n->a->maxstack, n->b->maxstack, n->c->maxstack);
1579 }
1580 
1581 static void
AssignmentExpression_common_codegen_pre(n,cc)1582 AssignmentExpression_common_codegen_pre(n, cc)	/* - | ref num num */
1583 	struct AssignmentExpression_node *n;
1584 	struct code_context *cc;
1585 {
1586 	CODEGEN(n->lhs);	/* ref */
1587 	CG_DUP();		/* ref ref */
1588 	CG_GETVALUE();		/* ref val */
1589 	CG_TONUMBER();		/* ref num */
1590 	CODEGEN(n->expr);	/* ref num ref */
1591 	if (!CG_IS_VALUE(n->expr))
1592 	    CG_GETVALUE();	/* ref num val */
1593 	if (!CG_IS_NUMBER(n->expr))
1594 	    CG_TONUMBER();	/* ref num num */
1595 }
1596 
1597 static void
AssignmentExpression_common_codegen_shiftpre(n,cc)1598 AssignmentExpression_common_codegen_shiftpre(n, cc)	/* - | ref val val */
1599 	struct AssignmentExpression_node *n;
1600 	struct code_context *cc;
1601 {
1602 	CODEGEN(n->lhs);	/* ref */
1603 	CG_DUP();		/* ref ref */
1604 	CG_GETVALUE();		/* ref val */
1605 	CODEGEN(n->expr);	/* ref num ref */
1606 	if (!CG_IS_VALUE(n->expr))
1607 	    CG_GETVALUE();	/* ref num val */
1608 }
1609 
1610 static void
AssignmentExpression_common_codegen_post(n,cc)1611 AssignmentExpression_common_codegen_post(n, cc) /* ref val | val */
1612 	struct AssignmentExpression_node *n;
1613 	struct code_context *cc;
1614 {
1615 	CG_DUP();		/* ref val val */
1616 	CG_ROLL3();   		/* val ref val */
1617 	CG_PUTVALUE();		/* val */
1618 	n->node.maxstack = MAX(n->lhs->maxstack, 2 + n->expr->maxstack);
1619 
1620 	/* Peephole optimisation note:
1621 	 *                  ref val
1622 	 *   DUP	    ref val val
1623 	 *   ROLL3   	    val ref val
1624 	 *   PUTVALUE	    val
1625 	 *   POP	    -
1626 	 *
1627 	 * is equivalent to:
1628 	 *                  ref val
1629 	 *   PUTVALUE       -
1630 	 *
1631 	 * The backend could check for this when the 'POP' instruction
1632 	 * is generated.
1633 	 */
1634 
1635 	/* Peephole optimisation note:
1636 	 *                  ref val
1637 	 *   DUP	    ref val val
1638 	 *   ROLL3   	    val ref val
1639 	 *   PUTVALUE	    val
1640 	 *   SETC	    -
1641 	 *
1642 	 * is equivalent to:
1643 	 *                  ref val
1644 	 *   DUP	    ref val val
1645 	 *   SETC	    ref val
1646 	 *   PUTVALUE       -
1647 	 *
1648 	 * The backend could check for this when the 'SETC' instruction
1649 	 * is generated.
1650 	 */
1651 
1652 }
1653 
1654 /* 11.13.2 */
1655 static void
AssignmentExpression_simple_codegen(na,cc)1656 AssignmentExpression_simple_codegen(na, cc)
1657 	struct node *na;
1658 	struct code_context *cc;
1659 {
1660 	struct AssignmentExpression_node *n =
1661 		CAST_NODE(na, AssignmentExpression);
1662 
1663 	CODEGEN(n->lhs);	/* ref */
1664 	CODEGEN(n->expr);	/* ref ref */
1665 	if (!CG_IS_VALUE(n->expr))
1666 	    CG_GETVALUE();	/* ref val */
1667 	AssignmentExpression_common_codegen_post(n, cc);/* val */
1668 	n->node.is = !CG_IS_VALUE(n->expr) ?  CG_TYPE_VALUE : n->expr->is;
1669 }
1670 
1671 /* 11.13.2 */
1672 static void
AssignmentExpression_muleq_codegen(na,cc)1673 AssignmentExpression_muleq_codegen(na, cc)
1674 	struct node *na;
1675 	struct code_context *cc;
1676 {
1677 	struct AssignmentExpression_node *n =
1678 		CAST_NODE(na, AssignmentExpression);
1679 
1680 	AssignmentExpression_common_codegen_pre(n, cc);	/* ref num num */
1681 	CG_MUL();
1682 	AssignmentExpression_common_codegen_post(n, cc);/* val */
1683 	n->node.is = CG_TYPE_NUMBER;
1684 }
1685 
1686 /* 11.13.2 */
1687 static void
AssignmentExpression_diveq_codegen(na,cc)1688 AssignmentExpression_diveq_codegen(na, cc)
1689 	struct node *na;
1690 	struct code_context *cc;
1691 {
1692 	struct AssignmentExpression_node *n =
1693 		CAST_NODE(na, AssignmentExpression);
1694 
1695 	AssignmentExpression_common_codegen_pre(n, cc);	/* ref num num */
1696 	CG_DIV();					/* ref num */
1697 	AssignmentExpression_common_codegen_post(n, cc);/* val */
1698 	n->node.is = CG_TYPE_NUMBER;
1699 }
1700 
1701 /* 11.13.2 */
1702 static void
AssignmentExpression_modeq_codegen(na,cc)1703 AssignmentExpression_modeq_codegen(na, cc)
1704 	struct node *na;
1705 	struct code_context *cc;
1706 {
1707 	struct AssignmentExpression_node *n =
1708 		CAST_NODE(na, AssignmentExpression);
1709 
1710 	AssignmentExpression_common_codegen_pre(n, cc);	/* ref num num */
1711 	CG_MOD();					/* ref num */
1712 	AssignmentExpression_common_codegen_post(n, cc);/* val */
1713 	n->node.is = CG_TYPE_NUMBER;
1714 }
1715 
1716 /* 11.13.2 */
1717 static void
AssignmentExpression_addeq_codegen(na,cc)1718 AssignmentExpression_addeq_codegen(na, cc)
1719 	struct node *na;
1720 	struct code_context *cc;
1721 {
1722 	struct AssignmentExpression_node *n =
1723 		CAST_NODE(na, AssignmentExpression);
1724 
1725 	CODEGEN(n->lhs);	/* ref1 */
1726 	CG_DUP();		/* ref1 ref1 */
1727 	CG_GETVALUE();		/* ref1 val1 */
1728 	CODEGEN(n->expr);	/* ref1 val1 ref2 */
1729 	if (!CG_IS_VALUE(n->expr))
1730 	    CG_GETVALUE();	/* ref1 val1 val2 */
1731 	CG_EXCH();		/* ref1 val2 val1 */
1732 	CG_TOPRIMITIVE();	/* ref1 val2 prim1 */
1733 	CG_EXCH();		/* ref1 prim1 val2 */
1734 	if (!CG_IS_PRIMITIVE(n->expr))
1735 	    CG_TOPRIMITIVE();	/* ref1 prim1 prim2 */
1736 	CG_ADD();		/* ref1 prim3 */
1737 	AssignmentExpression_common_codegen_post(n, cc);/* prim3 */
1738 
1739 	if (CG_IS_STRING(n->expr))
1740 	    n->node.is = CG_TYPE_STRING;
1741 	else
1742 	    n->node.is = CG_TYPE_STRING | CG_TYPE_NUMBER;
1743 }
1744 
1745 /* 11.13.2 */
1746 static void
AssignmentExpression_subeq_codegen(na,cc)1747 AssignmentExpression_subeq_codegen(na, cc)
1748 	struct node *na;
1749 	struct code_context *cc;
1750 {
1751 	struct AssignmentExpression_node *n =
1752 		CAST_NODE(na, AssignmentExpression);
1753 
1754 	AssignmentExpression_common_codegen_pre(n, cc);	/* ref num num */
1755 	CG_SUB();
1756 	AssignmentExpression_common_codegen_post(n, cc);/* val */
1757 	n->node.is = CG_TYPE_NUMBER;
1758 }
1759 
1760 /* 11.13.2 */
1761 static void
AssignmentExpression_lshifteq_codegen(na,cc)1762 AssignmentExpression_lshifteq_codegen(na, cc)
1763 	struct node *na;
1764 	struct code_context *cc;
1765 {
1766 	struct AssignmentExpression_node *n =
1767 		CAST_NODE(na, AssignmentExpression);
1768 
1769 	AssignmentExpression_common_codegen_shiftpre(n, cc);/* ref val val */
1770 	CG_LSHIFT();					    /* ref num */
1771 	AssignmentExpression_common_codegen_post(n, cc);    /* num */
1772 	n->node.is = CG_TYPE_NUMBER;
1773 }
1774 
1775 /* 11.13.2 */
1776 static void
AssignmentExpression_rshifteq_codegen(na,cc)1777 AssignmentExpression_rshifteq_codegen(na, cc)
1778 	struct node *na;
1779 	struct code_context *cc;
1780 {
1781 	struct AssignmentExpression_node *n =
1782 		CAST_NODE(na, AssignmentExpression);
1783 
1784 	AssignmentExpression_common_codegen_shiftpre(n, cc);/* ref val val */
1785 	CG_RSHIFT();					    /* ref num */
1786 	AssignmentExpression_common_codegen_post(n, cc);    /* num */
1787 	n->node.is = CG_TYPE_NUMBER;
1788 }
1789 
1790 /* 11.13.2 */
1791 static void
AssignmentExpression_urshifteq_codegen(na,cc)1792 AssignmentExpression_urshifteq_codegen(na, cc)
1793 	struct node *na;
1794 	struct code_context *cc;
1795 {
1796 	struct AssignmentExpression_node *n =
1797 		CAST_NODE(na, AssignmentExpression);
1798 
1799 	AssignmentExpression_common_codegen_shiftpre(n, cc);/* ref val val */
1800 	CG_URSHIFT();					    /* ref num */
1801 	AssignmentExpression_common_codegen_post(n, cc);    /* num */
1802 	n->node.is = CG_TYPE_NUMBER;
1803 }
1804 
1805 /* 11.13.2 */
1806 static void
AssignmentExpression_andeq_codegen(na,cc)1807 AssignmentExpression_andeq_codegen(na, cc)
1808 	struct node *na;
1809 	struct code_context *cc;
1810 {
1811 	struct AssignmentExpression_node *n =
1812 		CAST_NODE(na, AssignmentExpression);
1813 
1814 	AssignmentExpression_common_codegen_pre(n, cc);	    /* ref num num */
1815 	CG_BAND();					    /* ref num */
1816 	AssignmentExpression_common_codegen_post(n, cc);    /* num */
1817 	n->node.is = CG_TYPE_NUMBER;
1818 }
1819 
1820 /* 11.13.2 */
1821 static void
AssignmentExpression_xoreq_codegen(na,cc)1822 AssignmentExpression_xoreq_codegen(na, cc)
1823 	struct node *na;
1824 	struct code_context *cc;
1825 {
1826 	struct AssignmentExpression_node *n =
1827 		CAST_NODE(na, AssignmentExpression);
1828 
1829 	AssignmentExpression_common_codegen_pre(n, cc);	    /* ref num num */
1830 	CG_BXOR();					    /* ref num */
1831 	AssignmentExpression_common_codegen_post(n, cc);    /* num */
1832 	n->node.is = CG_TYPE_NUMBER;
1833 }
1834 
1835 /* 11.13.2 */
1836 static void
AssignmentExpression_oreq_codegen(na,cc)1837 AssignmentExpression_oreq_codegen(na, cc)
1838 	struct node *na;
1839 	struct code_context *cc;
1840 {
1841 	struct AssignmentExpression_node *n =
1842 		CAST_NODE(na, AssignmentExpression);
1843 
1844 	AssignmentExpression_common_codegen_pre(n, cc);	    /* ref num num */
1845 	CG_BOR();					    /* ref num */
1846 	AssignmentExpression_common_codegen_post(n, cc);    /* num */
1847 	n->node.is = CG_TYPE_NUMBER;
1848 
1849 }
1850 
1851 /* 11.14 */
1852 static void
Expression_comma_codegen(na,cc)1853 Expression_comma_codegen(na, cc)
1854 	struct node *na;
1855 	struct code_context *cc;
1856 {
1857 	struct Binary_node *n = CAST_NODE(na, Binary);
1858 
1859 	CODEGEN(n->a);		/* ref */
1860 	if (!CG_IS_VALUE(n->a))
1861 	    CG_GETVALUE();	/* val */
1862 	CG_POP();		/* -   */
1863 	CODEGEN(n->b);		/* ref */
1864 	if (!CG_IS_VALUE(n->b))
1865 	    CG_GETVALUE();	/* val */
1866 
1867 	n->node.is = CG_IS_VALUE(n->b) ? n->b->is : CG_TYPE_VALUE;
1868 	n->node.maxstack = MAX(n->a->maxstack, n->b->maxstack);
1869 }
1870 
1871 /* 12.1 */
1872 static void
Block_empty_codegen(n,cc)1873 Block_empty_codegen(n, cc)
1874 	struct node *n;
1875 	struct code_context *cc;
1876 {
1877 						/* - | - */
1878 	n->maxstack = 0;
1879 }
1880 
1881 /* 12.1 */
1882 static void
StatementList_codegen(na,cc)1883 StatementList_codegen(na, cc)
1884 	struct node *na;
1885 	struct code_context *cc;
1886 {
1887 	struct Binary_node *n = CAST_NODE(na, Binary);
1888 
1889 	CODEGEN(n->a);				 /*    -      */
1890 	CODEGEN(n->b);				 /*    -      */
1891 	n->node.maxstack = MAX(n->a->maxstack, n->b->maxstack);
1892 }
1893 
1894 /* 12.2 */
1895 static void
VariableStatement_codegen(na,cc)1896 VariableStatement_codegen(na, cc)
1897 	struct node *na;
1898 	struct code_context *cc;
1899 {
1900 	struct Unary_node *n = CAST_NODE(na, Unary);
1901 
1902 	/* Note: VariableDeclaration leaves nothing on the stack */
1903 	CG_LOC(&na->location);
1904 	CODEGEN(n->a);	    /* - */
1905 	n->node.maxstack = n->a->maxstack;
1906 }
1907 
1908 /* 12.2 */
1909 static void
VariableDeclarationList_codegen(na,cc)1910 VariableDeclarationList_codegen(na, cc)
1911 	struct node *na;
1912 	struct code_context *cc;
1913 {
1914 	struct Binary_node *n = CAST_NODE(na, Binary);
1915 
1916 	CODEGEN(n->a);			/* - */
1917 	CODEGEN(n->b);			/* - */
1918 	n->node.maxstack = MAX(n->a->maxstack, n->b->maxstack);
1919 }
1920 
1921 /* 12.2 */
1922 static void
VariableDeclaration_codegen(na,cc)1923 VariableDeclaration_codegen(na, cc)
1924 	struct node *na;
1925 	struct code_context *cc;
1926 {
1927 	struct VariableDeclaration_node *n =
1928 		CAST_NODE(na, VariableDeclaration);
1929 	if (n->init) {
1930 		if (cg_var_is_in_scope(cc, n->var->name))
1931 		    CG_VREF(cg_var_id(cc, n->var->name));    /* ref */
1932 		else {
1933 		    CG_STRING(n->var->name);		    /* str */
1934 		    CG_LOOKUP();			    /* ref */
1935 		}
1936 		CODEGEN(n->init);			    /* ref ref */
1937 		if (!CG_IS_VALUE(n->init))
1938 		    CG_GETVALUE();			    /* ref val */
1939 		CG_PUTVALUE();				    /* - */
1940 	}
1941 	n->node.maxstack = n->init ? 1 + n->init->maxstack : 0;
1942 }
1943 
1944 /* 12.3 */
1945 static void
EmptyStatement_codegen(na,cc)1946 EmptyStatement_codegen(na, cc)
1947 	struct node *na;
1948 	struct code_context *cc;
1949 {
1950 	CG_LOC(&na->location);
1951 	/* CG_NOP(); */		/* - */
1952 	na->maxstack = 0;
1953 }
1954 
1955 /* 12.4 */
1956 static void
ExpressionStatement_codegen(na,cc)1957 ExpressionStatement_codegen(na, cc)
1958 	struct node *na;
1959 	struct code_context *cc;
1960 {
1961 	struct Unary_node *n = CAST_NODE(na, Unary);
1962 
1963 	CG_LOC(&na->location);
1964 	CODEGEN(n->a);			/* ref */
1965 	if (!CG_IS_VALUE(n->a))
1966 	    CG_GETVALUE();		/* val */
1967 	CG_SETC();			/* -   */
1968 
1969 	n->node.maxstack = n->a->maxstack;
1970 }
1971 
1972 /* 12.5 */
1973 static void
IfStatement_codegen(na,cc)1974 IfStatement_codegen(na, cc)
1975 	struct node *na;
1976 	struct code_context *cc;
1977 {
1978 	struct IfStatement_node *n = CAST_NODE(na, IfStatement);
1979 	SEE_code_patchable_t L1, L2;
1980 
1981 	CG_LOC(&na->location);
1982 	CODEGEN(n->cond);			/*     ref      */
1983 	if (!CG_IS_VALUE(n->cond))
1984 	    CG_GETVALUE();			/*     val      */
1985 	if (!CG_IS_BOOLEAN(n->cond))
1986 	    CG_TOBOOLEAN();			/*     bool     */
1987 	CG_B_TRUE_f(L1);			/*     -   (L1) */
1988 	if (n->bfalse)
1989 	    CODEGEN(n->bfalse);			/*     -        */
1990 	CG_B_ALWAYS_f(L2);			/*     -   (L2) */
1991     CG_LABEL(L1);				/* L1: -        */
1992 	CODEGEN(n->btrue);			/*     -        */
1993     CG_LABEL(L2);				/* L2: -        */
1994 
1995 	n->node.maxstack = MAX3(n->cond->maxstack,
1996 	    n->btrue->maxstack, n->bfalse ? n->bfalse->maxstack : 0);
1997 }
1998 
1999 /* 12.6.1 */
2000 static void
IterationStatement_dowhile_codegen(na,cc)2001 IterationStatement_dowhile_codegen(na, cc)
2002 	struct node *na;
2003 	struct code_context *cc;
2004 {
2005 	struct IterationStatement_while_node *n =
2006 		CAST_NODE(na, IterationStatement_while);
2007 	SEE_code_addr_t L1, L2, L3;
2008 
2009 	push_patchables(cc, n->target, CONTINUABLE);
2010 
2011     L1 = CG_HERE();
2012 	CODEGEN(n->body);
2013     L2 = CG_HERE();			    /* continue point */
2014 	CG_LOC(&na->location);
2015 	CODEGEN(n->cond);
2016 	if (!CG_IS_VALUE(n->cond))
2017 	    CG_GETVALUE();
2018 	CG_B_TRUE_b(L1);
2019     L3 = CG_HERE();			    /* break point */
2020 
2021 	pop_patchables(cc, L2, L3);
2022 
2023 	na->maxstack = MAX(n->cond->maxstack, n->body->maxstack);
2024 }
2025 
2026 /* 12.6.2 */
2027 static void
IterationStatement_while_codegen(na,cc)2028 IterationStatement_while_codegen(na, cc)
2029 	struct node *na;
2030 	struct code_context *cc;
2031 {
2032 	struct IterationStatement_while_node *n =
2033 		CAST_NODE(na, IterationStatement_while);
2034 	SEE_code_patchable_t P1;
2035 	SEE_code_addr_t L1, L2, L3;
2036 
2037 	push_patchables(cc, n->target, CONTINUABLE);
2038 
2039 	CG_B_ALWAYS_f(P1);
2040     L1 = CG_HERE();
2041 	CODEGEN(n->body);
2042     CG_LABEL(P1);
2043     L2 = CG_HERE();			    /* continue point */
2044 	CG_LOC(&na->location);
2045 	CODEGEN(n->cond);
2046 	if (!CG_IS_VALUE(n->cond))
2047 	    CG_GETVALUE();
2048 	CG_B_TRUE_b(L1);
2049     L3 = CG_HERE();			    /* break point */
2050 
2051 	pop_patchables(cc, L2, L3);
2052 
2053 	na->maxstack = MAX(n->cond->maxstack, n->body->maxstack);
2054 }
2055 
2056 /* 12.6.3 for (init; cond; incr) body */
2057 static void
IterationStatement_for_codegen(na,cc)2058 IterationStatement_for_codegen(na, cc)
2059 	struct node *na;
2060 	struct code_context *cc;
2061 {
2062 	struct IterationStatement_for_node *n =
2063 		CAST_NODE(na, IterationStatement_for);
2064 	SEE_code_patchable_t P1;
2065 	SEE_code_addr_t L1, L2, L3;
2066 
2067 	push_patchables(cc, n->target, CONTINUABLE);
2068 
2069 	if (n->init) {
2070 		CG_LOC(&n->init->location);
2071 		CODEGEN(n->init);
2072 		if (!CG_IS_VALUE(n->init))
2073 		    CG_GETVALUE();
2074 		CG_POP();
2075 	}
2076 	CG_B_ALWAYS_f(P1);
2077     L1 = CG_HERE();
2078 	CODEGEN(n->body);
2079     L2 = CG_HERE();			    /* continue point */
2080 	if (n->incr) {
2081 		CG_LOC(&n->incr->location);
2082 		CODEGEN(n->incr);
2083 		if (!CG_IS_VALUE(n->incr))
2084 		    CG_GETVALUE();
2085 		CG_POP();
2086 	}
2087     CG_LABEL(P1);
2088 	if (n->cond) {
2089 	    CG_LOC(&n->cond->location);
2090 	    CODEGEN(n->cond);
2091 	    if (!CG_IS_VALUE(n->cond))
2092 		CG_GETVALUE();
2093 	    CG_B_TRUE_b(L1);
2094 	} else {
2095 	    CG_LOC(&na->location);
2096 	    CG_B_ALWAYS_b(L1);
2097 	}
2098     L3 = CG_HERE();			    /* break point */
2099 
2100 	pop_patchables(cc, L2, L3);
2101 
2102 	na->maxstack = MAX(
2103 	    MAX(n->incr ? n->incr->maxstack : 0,
2104 		n->init ? n->init->maxstack : 0),
2105 	    MAX(n->cond ? n->cond->maxstack : 0,
2106 		n->body->maxstack));
2107 }
2108 
2109 /* 12.6.3 for (var init; cond; incr) body */
2110 static void
IterationStatement_forvar_codegen(na,cc)2111 IterationStatement_forvar_codegen(na, cc)
2112 	struct node *na;
2113 	struct code_context *cc;
2114 {
2115 	struct IterationStatement_for_node *n =
2116 		CAST_NODE(na, IterationStatement_for);
2117 	SEE_code_patchable_t P1;
2118 	SEE_code_addr_t L1, L2, L3;
2119 
2120 	push_patchables(cc, n->target, CONTINUABLE);
2121 
2122 	CG_LOC(&n->init->location);
2123 	CODEGEN(n->init);
2124 	if (!CG_IS_VALUE(n->init))
2125 	    CG_GETVALUE();
2126 	CG_B_ALWAYS_f(P1);
2127     L1 = CG_HERE();
2128 	CODEGEN(n->body);
2129     L2 = CG_HERE();			    /* continue point */
2130 	if (n->incr) {
2131 		CG_LOC(&n->incr->location);
2132 		CODEGEN(n->incr);
2133 		if (!CG_IS_VALUE(n->incr))
2134 		    CG_GETVALUE();
2135 		CG_POP();
2136 	}
2137     CG_LABEL(P1);
2138 	if (n->cond) {
2139 	    CG_LOC(&n->cond->location);
2140 	    CODEGEN(n->cond);
2141 	    if (!CG_IS_VALUE(n->cond))
2142 		CG_GETVALUE();
2143 	    CG_B_TRUE_b(L1);
2144 	} else {
2145 	    CG_LOC(&na->location);
2146 	    CG_B_ALWAYS_b(L1);
2147 	}
2148     L3 = CG_HERE();			    /* break point */
2149 
2150 	pop_patchables(cc, L2, L3);
2151 
2152 	na->maxstack = MAX(
2153 	    MAX(n->incr ? n->incr->maxstack : 0,
2154 		n->init->maxstack),
2155 	    MAX(n->cond ? n->cond->maxstack : 0,
2156 		n->body->maxstack));
2157 }
2158 
2159 /* 12.6.3 for (lhs in list) body */
2160 static void
IterationStatement_forin_codegen(na,cc)2161 IterationStatement_forin_codegen(na, cc)
2162 	struct node *na;
2163 	struct code_context *cc;
2164 {
2165 	struct IterationStatement_forin_node *n =
2166 		CAST_NODE(na, IterationStatement_forin);
2167 	SEE_code_patchable_t P1;
2168 	SEE_code_addr_t L1, L2, L3;
2169 
2170 	CG_LOC(&na->location);
2171 	CODEGEN(n->list);		/* ref */
2172 	if (!CG_IS_VALUE(n->list))
2173 	    CG_GETVALUE();		/* val */
2174 	if (!CG_IS_OBJECT(n->list))
2175 	    CG_TOOBJECT();		/* obj */
2176 
2177 	CG_S_ENUM();			/* -  */
2178 	cg_block_enter(cc);
2179 
2180 	push_patchables(cc, n->target, CONTINUABLE);
2181 
2182 	CG_B_ALWAYS_f(P1);
2183 
2184     L1 = CG_HERE();
2185 	CODEGEN(n->lhs);		/* str ref */
2186 	CG_EXCH();			/* ref str */
2187 	CG_PUTVALUE();			/* - */
2188 
2189 	CODEGEN(n->body);
2190 
2191     L2 = CG_HERE();			/* continue point */
2192     CG_LABEL(P1);
2193 	CG_B_ENUM_b(L1);
2194 
2195     L3 = CG_HERE();			/* break point */
2196 	pop_patchables(cc, L2, L3);
2197 
2198 	CG_END(cg_block_current(cc));
2199 	cg_block_leave(cc);
2200 
2201 	na->maxstack = MAX4(
2202 	    2,
2203 	    n->list->maxstack,
2204 	    1 + n->lhs->maxstack,
2205 	    n->body->maxstack);
2206 }
2207 
2208 /* 12.6.3 for (var lhs in list) body */
2209 static void
IterationStatement_forvarin_codegen(na,cc)2210 IterationStatement_forvarin_codegen(na, cc)
2211 	struct node *na;
2212 	struct code_context *cc;
2213 {
2214 	struct IterationStatement_forin_node *n =
2215 		CAST_NODE(na, IterationStatement_forin);
2216 	struct VariableDeclaration_node *lhs
2217 		= CAST_NODE(n->lhs, VariableDeclaration);
2218 	SEE_code_patchable_t P1;
2219 	SEE_code_addr_t L1, L2, L3;
2220 
2221 	CG_LOC(&na->location);
2222 	CODEGEN(n->lhs);		/* - */
2223 	CODEGEN(n->list);		/* ref */
2224 	if (!CG_IS_VALUE(n->list))
2225 	    CG_GETVALUE();		/* val */
2226 	if (!CG_IS_OBJECT(n->list))
2227 	    CG_TOOBJECT();		/* obj */
2228 
2229 	CG_S_ENUM();			/* -  */
2230 	cg_block_enter(cc);
2231 
2232 	push_patchables(cc, n->target, CONTINUABLE);
2233 
2234 	CG_B_ALWAYS_f(P1);
2235 
2236     L1 = CG_HERE();
2237 	if (cg_var_is_in_scope(cc, lhs->var->name))
2238 	    CG_VREF(cg_var_id(cc, lhs->var->name));    /* ref */
2239 	else {
2240 	    CG_STRING(lhs->var->name);		    /* str */
2241 	    CG_LOOKUP();			    /* ref */
2242 	}
2243 	CG_EXCH();			/* ref str */
2244 	CG_PUTVALUE();			/* - */
2245 
2246 	CODEGEN(n->body);
2247 
2248     L2 = CG_HERE();			/* continue point */
2249     CG_LABEL(P1);
2250 	CG_B_ENUM_b(L1);
2251 
2252     L3 = CG_HERE();			/* break point */
2253 	pop_patchables(cc, L2, L3);
2254 	CG_END(cg_block_current(cc));
2255 	cg_block_leave(cc);
2256 
2257 	na->maxstack = MAX4(
2258 	    2,
2259 	    n->list->maxstack,
2260 	    1 + n->lhs->maxstack,
2261 	    n->body->maxstack);
2262 }
2263 
2264 /* 12.7 */
2265 static void
ContinueStatement_codegen(na,cc)2266 ContinueStatement_codegen(na, cc)
2267 	struct node *na;
2268 	struct code_context *cc;
2269 {
2270 	struct ContinueStatement_node *n = CAST_NODE(na, ContinueStatement);
2271 	struct patchables *patchables;
2272 	SEE_code_patchable_t pa;
2273 
2274 	patchables = patch_find(cc, n->target, PATCH_FIND_CONTINUE);
2275 
2276 	CG_LOC(&na->location);
2277 
2278 	/* Generate an END instruction if we are continuing to an outer block */
2279 	if (patchables->block_depth < cc->block_depth)
2280 	    CG_END(patchables->block_depth+1);
2281 
2282 	CG_B_ALWAYS_f(pa);
2283 	patch_add_continue(cc, patchables, pa);
2284 
2285 	n->node.maxstack = 0;
2286 }
2287 
2288 /* 12.8 */
2289 static void
BreakStatement_codegen(na,cc)2290 BreakStatement_codegen(na, cc)
2291 	struct node *na;
2292 	struct code_context *cc;
2293 {
2294 	struct BreakStatement_node *n = CAST_NODE(na, BreakStatement);
2295 	struct patchables *patchables;
2296 	SEE_code_patchable_t pa;
2297 
2298 	patchables = patch_find(cc, n->target, PATCH_FIND_BREAK);
2299 
2300 	CG_LOC(&na->location);
2301 
2302 	/* Generate an END instruction if we are breaking to an outer block */
2303 	if (patchables->block_depth < cc->block_depth)
2304 	    CG_END(patchables->block_depth+1);
2305 
2306 	CG_B_ALWAYS_f(pa);
2307 	patch_add_break(cc, patchables, pa);
2308 
2309 	n->node.maxstack = 0;
2310 }
2311 
2312 /* 12.9 */
2313 static void
ReturnStatement_codegen(na,cc)2314 ReturnStatement_codegen(na, cc)
2315 	struct node *na;
2316 	struct code_context *cc;
2317 {
2318 	struct ReturnStatement_node *n = CAST_NODE(na, ReturnStatement);
2319 
2320 	CG_LOC(&na->location);
2321 	CODEGEN(n->expr);			/* ref */
2322 	if (!CG_IS_VALUE(n->expr))
2323 	    CG_GETVALUE();			/* val */
2324 	CG_SETC();				/* - */
2325 	CG_END(0);				/* (halt) */
2326 
2327 	n->node.maxstack = n->expr->maxstack;
2328 }
2329 
2330 /* 12.9 */
2331 static void
ReturnStatement_undef_codegen(na,cc)2332 ReturnStatement_undef_codegen(na, cc)
2333 	struct node *na;
2334 	struct code_context *cc;
2335 {
2336 	CG_LOC(&na->location);
2337 	CG_UNDEFINED();			    /* undef */
2338 	CG_SETC();			    /* - */
2339 	CG_END(0);			    /* (halt) */
2340 
2341 	na->maxstack = 1;
2342 }
2343 
2344 /* 12.10 */
2345 static void
WithStatement_codegen(na,cc)2346 WithStatement_codegen(na, cc)
2347 	struct node *na;
2348 	struct code_context *cc;
2349 {
2350 	struct Binary_node *n = CAST_NODE(na, Binary);
2351 	int old_var_scope;
2352 
2353 	CG_LOC(&na->location);
2354 	CODEGEN(n->a);			/* ref */
2355 	if (!CG_IS_VALUE(n->a))
2356 	    CG_GETVALUE();		/* val */
2357 	if (!CG_IS_OBJECT(n->a))
2358 	    CG_TOOBJECT();		/* obj */
2359 
2360 	CG_S_WITH();			/* - */
2361 	cg_block_enter(cc);
2362 	old_var_scope = cg_var_set_all_scope(cc, 0);
2363 
2364 	CODEGEN(n->b);
2365 
2366 	CG_END(cg_block_current(cc));
2367 	cg_block_leave(cc);
2368 	cg_var_set_all_scope(cc, old_var_scope);
2369 
2370 	na->maxstack = MAX(n->a->maxstack, n->b->maxstack);
2371 }
2372 
2373 /* 12.11 */
2374 static void
SwitchStatement_codegen(na,cc)2375 SwitchStatement_codegen(na, cc)
2376 	struct node *na;
2377 	struct code_context *cc;
2378 {
2379 	struct SwitchStatement_node *n = CAST_NODE(na, SwitchStatement);
2380 	struct case_list *c;
2381 	int ncases, i;
2382 	SEE_code_patchable_t *case_patches, default_patch;
2383 	unsigned int expr_maxstack = 0, body_maxstack = 0;
2384 
2385 	for (ncases = 0, c = n->cases; c; c = c->next)
2386 	    if (c->expr)
2387 		ncases++;
2388 	case_patches = SEE_ALLOCA(cc->code->interpeter,
2389 	    SEE_code_patchable_t, ncases);
2390 
2391 	CG_LOC(&na->location);
2392 	CODEGEN(n->cond);		/* ref */
2393 	if (!CG_IS_VALUE(n->cond))
2394 	    CG_GETVALUE();		/* val */
2395 
2396 	for (i = 0, c = n->cases; c; c = c->next)
2397 	    if (c->expr) {
2398 		CG_DUP();		/* val val */
2399 		CODEGEN(c->expr);	/* val val ref */
2400 		expr_maxstack = MAX(expr_maxstack, 2 + c->expr->maxstack);
2401 		if (!CG_IS_VALUE(c->expr))
2402 		    CG_GETVALUE();	/* val val val */
2403 		CG_SEQ();		/* val bool */
2404 		CG_B_TRUE_f(case_patches[i]);	/* val */
2405 		i++;
2406 	    }
2407 	CG_B_ALWAYS_f(default_patch);
2408 
2409 	push_patchables(cc, n->target, !CONTINUABLE);
2410 
2411 	for (i = 0, c = n->cases; c; c = c->next) {
2412 	    if (!c->expr)
2413 		CG_LABEL(default_patch);
2414 	    else {
2415 		CG_LABEL(case_patches[i]);
2416 		i++;
2417 	    }
2418 	    if (c->body) {
2419 		CODEGEN(c->body);	/* val */
2420 		body_maxstack = MAX(body_maxstack, 1 + c->body->maxstack);
2421 	    }
2422 	}
2423 
2424 	/* If there was no default body, patch through to the end */
2425 	if (!n->defcase)
2426 	    CG_LABEL(default_patch);
2427 
2428 	pop_patchables(cc, 0, CG_HERE());   /* All breaks lead here */
2429 	CG_POP();
2430 
2431 	na->maxstack = MAX3(n->cond->maxstack, expr_maxstack, body_maxstack);
2432 }
2433 
2434 /* 12.12 */
2435 static void
LabelledStatement_codegen(na,cc)2436 LabelledStatement_codegen(na, cc)
2437 	struct node *na;
2438 	struct code_context *cc;
2439 {
2440 	struct LabelledStatement_node *n = CAST_NODE(na, LabelledStatement);
2441 	SEE_code_addr_t L1;
2442 
2443 	push_patchables(cc, n->target, !CONTINUABLE);
2444 	CODEGEN(n->unary.a);
2445     L1 = CG_HERE();
2446 	pop_patchables(cc, NULL, L1);
2447 	na->maxstack = n->unary.a->maxstack;
2448 }
2449 
2450 /* 12.13 */
2451 static void
ThrowStatement_codegen(na,cc)2452 ThrowStatement_codegen(na, cc)
2453 	struct node *na;
2454 	struct code_context *cc;
2455 {
2456 	struct Unary_node *n = CAST_NODE(na, Unary);
2457 
2458 	CG_LOC(&na->location);
2459 	CODEGEN(n->a);		/* ref */
2460 	if (!CG_IS_VALUE(n->a))
2461 	    CG_GETVALUE();	/* val */
2462 	CG_THROW();		/* - */
2463 
2464 	na->maxstack = n->a->maxstack;
2465 }
2466 
2467 /* 12.14 try catch */
2468 static void
TryStatement_catch_codegen(na,cc)2469 TryStatement_catch_codegen(na, cc)
2470 	struct node *na;
2471 	struct code_context *cc;
2472 {
2473 	struct TryStatement_node *n = CAST_NODE(na, TryStatement);
2474 	SEE_code_patchable_t L1, L2;
2475 	int in_scope;
2476 
2477 	CG_LOC(&na->location);
2478 	CG_STRING(n->ident);	    /* str */
2479 	CG_S_TRYC_f(L1);	    /* - */
2480 	cg_block_enter(cc);
2481 	CODEGEN(n->block);	    /* - */
2482 	CG_B_ALWAYS_f(L2);
2483     CG_LABEL(L1);
2484         /* If the catch variable was declared var then temporarily remove it
2485          * from the scope. */
2486 	in_scope = cg_var_is_in_scope(cc, n->ident);
2487 	if (in_scope)
2488 	    cg_var_set_scope(cc, n->ident, 0);
2489 	CG_S_CATCH();	            /* - */
2490 	CODEGEN(n->bcatch);	    /* - */
2491 	if (in_scope)
2492 	    cg_var_set_scope(cc, n->ident, 1);
2493     CG_LABEL(L2);
2494 	CG_END(cg_block_current(cc));
2495 	cg_block_leave(cc);
2496 
2497 	na->maxstack = MAX3(1, n->block->maxstack, n->bcatch->maxstack);
2498 
2499 }
2500 
2501 /* 12.14 try finally */
2502 static void
TryStatement_finally_codegen(na,cc)2503 TryStatement_finally_codegen(na, cc)
2504 	struct node *na;
2505 	struct code_context *cc;
2506 {
2507 	struct TryStatement_node *n = CAST_NODE(na, TryStatement);
2508 	SEE_code_patchable_t L1, L2;
2509 
2510 	CG_LOC(&na->location);
2511 	CG_S_TRYF_f(L1);	    /* - */
2512 	cg_block_enter(cc);
2513 	CODEGEN(n->block);	    /* - */
2514 	CG_B_ALWAYS_f(L2);
2515     CG_LABEL(L1);
2516 	CG_GETC();		    /* val */
2517         if (cc->max_block_depth > cg_block_current(cc))
2518             CG_END(cg_block_current(cc)+1);
2519 	CODEGEN(n->bfinally);	    /* val */
2520 	CG_SETC();		    /* - */
2521         CG_ENDF();
2522     CG_LABEL(L2);
2523 	CG_END(cg_block_current(cc));
2524 	cg_block_leave(cc);
2525 
2526 	na->maxstack = MAX3(1, n->block->maxstack, 1 + n->bfinally->maxstack);
2527 
2528 }
2529 
2530 /* 12.14 try catch finally */
2531 static void
TryStatement_catchfinally_codegen(na,cc)2532 TryStatement_catchfinally_codegen(na, cc)
2533 	struct node *na;
2534 	struct code_context *cc;
2535 {
2536 	struct TryStatement_node *n = CAST_NODE(na, TryStatement);
2537 	SEE_code_patchable_t L1, L2, L3a, L3b;
2538 	int in_scope;
2539 
2540 	CG_LOC(&na->location);
2541 	CG_S_TRYF_f(L1);	    /* - */
2542 	cg_block_enter(cc);
2543 	CG_STRING(n->ident);	    /* str */
2544 	CG_S_TRYC_f(L2);	    /* - */
2545 	cg_block_enter(cc);
2546 	CODEGEN(n->block);	    /* - */
2547 	CG_B_ALWAYS_f(L3a);
2548     CG_LABEL(L2);
2549 	in_scope = cg_var_is_in_scope(cc, n->ident);
2550 	if (in_scope)
2551 	    cg_var_set_scope(cc, n->ident, 0);
2552 	CG_S_CATCH();	            /* - */
2553 	CODEGEN(n->bcatch);	    /* - */
2554 	if (in_scope)
2555 	    cg_var_set_scope(cc, n->ident, 1);
2556 	CG_B_ALWAYS_f(L3b);
2557 	cg_block_leave(cc);
2558     CG_LABEL(L1);
2559 	CG_GETC();		    /* val */
2560         if (cc->max_block_depth > cg_block_current(cc))
2561             CG_END(cg_block_current(cc) + 1);
2562 	CODEGEN(n->bfinally);	    /* val */
2563 	CG_SETC();		    /* - */
2564         CG_ENDF();
2565     CG_LABEL(L3a);
2566     CG_LABEL(L3b);
2567 	CG_END(cg_block_current(cc));
2568 	cg_block_leave(cc);
2569 
2570 	na->maxstack = MAX4(1, n->block->maxstack,
2571 		n->bcatch->maxstack, 1 + n->bfinally->maxstack);
2572 
2573 
2574 	/*
2575 	 * Peephole optimizer note:
2576 	 * Sometimes two SETCs will be generated in a row. This
2577 	 * would be slightly faster if the first SETC were converted
2578 	 * into a POP
2579 	 */
2580 
2581 }
2582 
2583 #if 0
2584 /* 13 */
2585 static void
2586 FunctionDeclaration_codegen(na, cc)
2587 	struct node *na;
2588 	struct code_context *cc;
2589 {
2590 	struct Function_node *n = CAST_NODE(na, Function);
2591 	/* TBD - never actually called? */
2592 }
2593 #endif
2594 
2595 /* 13 */
2596 static void
FunctionExpression_codegen(na,cc)2597 FunctionExpression_codegen(na, cc)
2598 	struct node *na;
2599 	struct code_context *cc;
2600 {
2601 	struct Function_node *n = CAST_NODE(na, Function);
2602 	int in_scope;
2603 
2604 	if (n->function->name == NULL) {
2605 	    CG_FUNC(n->function);	    /* obj */
2606 
2607 	    na->maxstack = 1;
2608 	} else {
2609 	    /*
2610 	     * The following creates a new mini-scope with S.WITH.
2611 	     * The scope is inherited by the FUNC instruction. This is so
2612 	     * the function can call itself recursively by name
2613 	     */
2614 	    CG_OBJECT();		    /* obj */
2615 	    CG_DUP();			    /* obj obj */
2616 	    CG_S_WITH();		    /* obj */
2617 	    cg_block_enter(cc);
2618 	    in_scope = cg_var_is_in_scope(cc, n->function->name);
2619 	    if (in_scope)
2620 		    cg_var_set_scope(cc, n->function->name, 0);
2621 	    CG_STRING(n->function->name);   /* obj str */
2622 	    CG_REF();			    /* ref */
2623 	    CG_FUNC(n->function);	    /* ref obj */
2624 	    CG_END(cg_block_current(cc));
2625 	    cg_block_leave(cc);
2626 	    if (in_scope)
2627 		    cg_var_set_scope(cc, n->function->name, 1);
2628 	    CG_DUP();			    /* ref obj obj */
2629 	    CG_ROLL3();			    /* obj ref obj */
2630 	    CG_PUTVALUEA(SEE_ATTR_DONTDELETE | SEE_ATTR_READONLY); /* obj */
2631 
2632 	    na->maxstack = 3;
2633 	}
2634 }
2635 
2636 static void
FunctionBody_codegen(na,cc)2637 FunctionBody_codegen(na, cc)
2638 	struct node *na;
2639 	struct code_context *cc;
2640 {
2641 	struct FunctionBody_node *n = CAST_NODE(na, FunctionBody);
2642 
2643 	/* Note that SourceElements_codegen includes the fproc action */
2644 	CODEGEN(n->u.a);	/* - */
2645 
2646 	/* Non-programs convert 'normal' completion to return undefined */
2647 	if (!n->is_program) {
2648 	    CG_UNDEFINED();	/* undef */
2649 	    CG_SETC();		/* - */
2650 	}
2651 	CG_END(0);		/* explicit return */
2652 
2653 	na->maxstack = MAX(n->is_program ? 0 : 1, n->u.a->maxstack);
2654 }
2655 
2656 /* 14 */
2657 static void
SourceElements_codegen(na,cc)2658 SourceElements_codegen(na, cc)
2659 	struct node *na;
2660 	struct code_context *cc;
2661 {
2662 	struct SourceElements_node *n = CAST_NODE(na, SourceElements);
2663 	unsigned int maxstack = 0;
2664 	struct SourceElement *e;
2665 	struct var *v;
2666 	struct Function_node *fn;
2667 
2668 	/* SourceElements fproc:
2669 	 * - create function closures of the current scope
2670 	 * - initialise 'var's.
2671 	 */
2672 
2673 	for (e = n->functions; e; e = e->next) {
2674 	    fn = CAST_NODE(e->node, Function);
2675 	    cg_var_set_scope(cc, fn->function->name, 1);
2676 	    CG_VREF(cg_var_id(cc, fn->function->name)); /* ref */
2677 	    CG_FUNC(fn->function);		        /* ref obj */
2678 	    CG_PUTVALUE();			        /* - */
2679 	    maxstack = MAX(maxstack, 2);
2680 	}
2681 
2682 	for (v = n->vars; v; v = v->next) {
2683 	    cg_var_set_scope(cc, v->name, 1);
2684 	    maxstack = MAX(maxstack, 1);
2685 	}
2686 
2687 	/* SourceElements eval:
2688 	 * - execute each statement
2689 	 */
2690 	for (e = n->statements; e; e = e->next) {
2691 	    CODEGEN(e->node);
2692 	    maxstack = MAX(maxstack, e->node->maxstack);
2693 	}
2694 
2695 	na->maxstack = maxstack;
2696 }
2697 
2698 
2699 /* Returns true if the codgen function body is empty */
2700 int
_SEE_codegen_functionbody_isempty(interp,f)2701 _SEE_codegen_functionbody_isempty(interp, f)
2702 	struct SEE_interpreter *interp;
2703 	struct function *f;
2704 {
2705 	return f->body == NULL;
2706 }
2707 
2708 void
_SEE_codegen_eval_functionbody(body,context,res)2709 _SEE_codegen_eval_functionbody(body, context, res)
2710         void *body;
2711         struct SEE_context *context;
2712         struct SEE_value *res;
2713 {
2714         CG_EXEC((struct SEE_code *)body, context, res);
2715 }
2716 
2717 void (*_SEE_nodeclass_codegen[NODECLASS_MAX])(struct node *,
2718         struct code_context *) = { 0
2719     ,0                                      /*Unary*/
2720     ,0                                      /*Binary*/
2721     ,Literal_codegen                        /*Literal*/
2722     ,StringLiteral_codegen                  /*StringLiteral*/
2723     ,RegularExpressionLiteral_codegen       /*RegularExpressionLiteral*/
2724     ,PrimaryExpression_this_codegen         /*PrimaryExpression_this*/
2725     ,PrimaryExpression_ident_codegen        /*PrimaryExpression_ident*/
2726     ,ArrayLiteral_codegen                   /*ArrayLiteral*/
2727     ,ObjectLiteral_codegen                  /*ObjectLiteral*/
2728     ,Arguments_codegen                      /*Arguments*/
2729     ,MemberExpression_new_codegen           /*MemberExpression_new*/
2730     ,MemberExpression_dot_codegen           /*MemberExpression_dot*/
2731     ,MemberExpression_bracket_codegen       /*MemberExpression_bracket*/
2732     ,CallExpression_codegen                 /*CallExpression*/
2733     ,PostfixExpression_inc_codegen          /*PostfixExpression_inc*/
2734     ,PostfixExpression_dec_codegen          /*PostfixExpression_dec*/
2735     ,UnaryExpression_delete_codegen         /*UnaryExpression_delete*/
2736     ,UnaryExpression_void_codegen           /*UnaryExpression_void*/
2737     ,UnaryExpression_typeof_codegen         /*UnaryExpression_typeof*/
2738     ,UnaryExpression_preinc_codegen         /*UnaryExpression_preinc*/
2739     ,UnaryExpression_predec_codegen         /*UnaryExpression_predec*/
2740     ,UnaryExpression_plus_codegen           /*UnaryExpression_plus*/
2741     ,UnaryExpression_minus_codegen          /*UnaryExpression_minus*/
2742     ,UnaryExpression_inv_codegen            /*UnaryExpression_inv*/
2743     ,UnaryExpression_not_codegen            /*UnaryExpression_not*/
2744     ,MultiplicativeExpression_mul_codegen   /*MultiplicativeExpression_mul*/
2745     ,MultiplicativeExpression_div_codegen   /*MultiplicativeExpression_div*/
2746     ,MultiplicativeExpression_mod_codegen   /*MultiplicativeExpression_mod*/
2747     ,AdditiveExpression_add_codegen         /*AdditiveExpression_add*/
2748     ,AdditiveExpression_sub_codegen         /*AdditiveExpression_sub*/
2749     ,ShiftExpression_lshift_codegen         /*ShiftExpression_lshift*/
2750     ,ShiftExpression_rshift_codegen         /*ShiftExpression_rshift*/
2751     ,ShiftExpression_urshift_codegen        /*ShiftExpression_urshift*/
2752     ,RelationalExpression_lt_codegen        /*RelationalExpression_lt*/
2753     ,RelationalExpression_gt_codegen        /*RelationalExpression_gt*/
2754     ,RelationalExpression_le_codegen        /*RelationalExpression_le*/
2755     ,RelationalExpression_ge_codegen        /*RelationalExpression_ge*/
2756     ,RelationalExpression_instanceof_codegen/*RelationalExpression_instanceof*/
2757     ,RelationalExpression_in_codegen        /*RelationalExpression_in*/
2758     ,EqualityExpression_eq_codegen          /*EqualityExpression_eq*/
2759     ,EqualityExpression_ne_codegen          /*EqualityExpression_ne*/
2760     ,EqualityExpression_seq_codegen         /*EqualityExpression_seq*/
2761     ,EqualityExpression_sne_codegen         /*EqualityExpression_sne*/
2762     ,BitwiseANDExpression_codegen           /*BitwiseANDExpression*/
2763     ,BitwiseXORExpression_codegen           /*BitwiseXORExpression*/
2764     ,BitwiseORExpression_codegen            /*BitwiseORExpression*/
2765     ,LogicalANDExpression_codegen           /*LogicalANDExpression*/
2766     ,LogicalORExpression_codegen            /*LogicalORExpression*/
2767     ,ConditionalExpression_codegen          /*ConditionalExpression*/
2768     ,0                                      /*AssignmentExpression*/
2769     ,AssignmentExpression_simple_codegen    /*AssignmentExpression_simple*/
2770     ,AssignmentExpression_muleq_codegen     /*AssignmentExpression_muleq*/
2771     ,AssignmentExpression_diveq_codegen     /*AssignmentExpression_diveq*/
2772     ,AssignmentExpression_modeq_codegen     /*AssignmentExpression_modeq*/
2773     ,AssignmentExpression_addeq_codegen     /*AssignmentExpression_addeq*/
2774     ,AssignmentExpression_subeq_codegen     /*AssignmentExpression_subeq*/
2775     ,AssignmentExpression_lshifteq_codegen  /*AssignmentExpression_lshifteq*/
2776     ,AssignmentExpression_rshifteq_codegen  /*AssignmentExpression_rshifteq*/
2777     ,AssignmentExpression_urshifteq_codegen /*AssignmentExpression_urshifteq*/
2778     ,AssignmentExpression_andeq_codegen     /*AssignmentExpression_andeq*/
2779     ,AssignmentExpression_xoreq_codegen     /*AssignmentExpression_xoreq*/
2780     ,AssignmentExpression_oreq_codegen      /*AssignmentExpression_oreq*/
2781     ,Expression_comma_codegen               /*Expression_comma*/
2782     ,Block_empty_codegen                    /*Block_empty*/
2783     ,StatementList_codegen                  /*StatementList*/
2784     ,VariableStatement_codegen              /*VariableStatement*/
2785     ,VariableDeclarationList_codegen        /*VariableDeclarationList*/
2786     ,VariableDeclaration_codegen            /*VariableDeclaration*/
2787     ,EmptyStatement_codegen                 /*EmptyStatement*/
2788     ,ExpressionStatement_codegen            /*ExpressionStatement*/
2789     ,IfStatement_codegen                    /*IfStatement*/
2790     ,IterationStatement_dowhile_codegen     /*IterationStatement_dowhile*/
2791     ,IterationStatement_while_codegen       /*IterationStatement_while*/
2792     ,IterationStatement_for_codegen         /*IterationStatement_for*/
2793     ,IterationStatement_forvar_codegen      /*IterationStatement_forvar*/
2794     ,IterationStatement_forin_codegen       /*IterationStatement_forin*/
2795     ,IterationStatement_forvarin_codegen    /*IterationStatement_forvarin*/
2796     ,ContinueStatement_codegen              /*ContinueStatement*/
2797     ,BreakStatement_codegen                 /*BreakStatement*/
2798     ,ReturnStatement_codegen                /*ReturnStatement*/
2799     ,ReturnStatement_undef_codegen          /*ReturnStatement_undef*/
2800     ,WithStatement_codegen                  /*WithStatement*/
2801     ,SwitchStatement_codegen                /*SwitchStatement*/
2802     ,LabelledStatement_codegen              /*LabelledStatement*/
2803     ,ThrowStatement_codegen                 /*ThrowStatement*/
2804     ,0                                      /*TryStatement*/
2805     ,TryStatement_catch_codegen             /*TryStatement_catch*/
2806     ,TryStatement_finally_codegen           /*TryStatement_finally*/
2807     ,TryStatement_catchfinally_codegen      /*TryStatement_catchfinally*/
2808     ,0                                      /*Function*/
2809     ,0                                      /*FunctionDeclaration*/
2810     ,FunctionExpression_codegen             /*FunctionExpression*/
2811     ,FunctionBody_codegen                   /*FunctionBody*/
2812     ,SourceElements_codegen                 /*SourceElements*/
2813 };
2814