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