2 * Copyright 2011 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(jscript
);
28 WINE_DECLARE_DEBUG_CHANNEL(jscript_disas
);
30 typedef struct _statement_ctx_t
{
36 unsigned continue_label
;
38 const labelled_statement_t
*labelled_stat
;
40 struct _statement_ctx_t
*next
;
54 statement_ctx_t
*stat_ctx
;
59 instr_arg_type_t arg1_type
;
60 instr_arg_type_t arg2_type
;
62 #define X(n,a,b,c) {#n,b,c},
67 static void dump_instr_arg(instr_arg_type_t type
, instr_arg_t
*arg
)
71 TRACE_(jscript_disas
)("\t%s", debugstr_w(arg
->str
));
74 TRACE_(jscript_disas
)("\t%s", debugstr_wn(arg
->bstr
, SysStringLen(arg
->bstr
)));
77 TRACE_(jscript_disas
)("\t%d", arg
->uint
);
81 TRACE_(jscript_disas
)("\t%u", arg
->uint
);
84 TRACE_(jscript_disas
)("\t%lf", *arg
->dbl
);
94 static void dump_code(compiler_ctx_t
*ctx
, unsigned off
)
98 for(instr
= ctx
->code
->instrs
+off
; instr
< ctx
->code
->instrs
+ctx
->code_off
; instr
++) {
99 TRACE_(jscript_disas
)("%d:\t%s", (int)(instr
-ctx
->code
->instrs
), instr_info
[instr
->op
].op_str
);
100 dump_instr_arg(instr_info
[instr
->op
].arg1_type
, &instr
->arg1
);
101 dump_instr_arg(instr_info
[instr
->op
].arg2_type
, &instr
->arg2
);
102 TRACE_(jscript_disas
)("\n");
106 static HRESULT
compile_expression(compiler_ctx_t
*,expression_t
*);
107 static HRESULT
compile_statement(compiler_ctx_t
*,statement_ctx_t
*,statement_t
*);
109 static inline void *compiler_alloc(bytecode_t
*code
, size_t size
)
111 return jsheap_alloc(&code
->heap
, size
);
114 static WCHAR
*compiler_alloc_string(bytecode_t
*code
, const WCHAR
*str
)
119 size
= (strlenW(str
)+1)*sizeof(WCHAR
);
120 ret
= compiler_alloc(code
, size
);
122 memcpy(ret
, str
, size
);
126 static BSTR
compiler_alloc_bstr(compiler_ctx_t
*ctx
, const WCHAR
*str
)
128 if(!ctx
->code
->bstr_pool_size
) {
129 ctx
->code
->bstr_pool
= heap_alloc(8 * sizeof(BSTR
));
130 if(!ctx
->code
->bstr_pool
)
132 ctx
->code
->bstr_pool_size
= 8;
133 }else if(ctx
->code
->bstr_pool_size
== ctx
->code
->bstr_cnt
) {
136 new_pool
= heap_realloc(ctx
->code
->bstr_pool
, ctx
->code
->bstr_pool_size
*2*sizeof(BSTR
));
140 ctx
->code
->bstr_pool
= new_pool
;
141 ctx
->code
->bstr_pool_size
*= 2;
144 ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
] = SysAllocString(str
);
145 if(!ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
])
148 return ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
++];
151 static unsigned push_instr(compiler_ctx_t
*ctx
, jsop_t op
)
153 assert(ctx
->code_size
>= ctx
->code_off
);
155 if(ctx
->code_size
== ctx
->code_off
) {
158 new_instrs
= heap_realloc(ctx
->code
->instrs
, ctx
->code_size
*2*sizeof(instr_t
));
162 ctx
->code
->instrs
= new_instrs
;
166 ctx
->code
->instrs
[ctx
->code_off
].op
= op
;
167 return ctx
->code_off
++;
170 static inline instr_t
*instr_ptr(compiler_ctx_t
*ctx
, unsigned off
)
172 assert(off
< ctx
->code_off
);
173 return ctx
->code
->instrs
+ off
;
176 static HRESULT
push_instr_int(compiler_ctx_t
*ctx
, jsop_t op
, LONG arg
)
180 instr
= push_instr(ctx
, op
);
182 return E_OUTOFMEMORY
;
184 instr_ptr(ctx
, instr
)->arg1
.lng
= arg
;
188 static HRESULT
push_instr_str(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg
)
193 str
= compiler_alloc_string(ctx
->code
, arg
);
195 return E_OUTOFMEMORY
;
197 instr
= push_instr(ctx
, op
);
199 return E_OUTOFMEMORY
;
201 instr_ptr(ctx
, instr
)->arg1
.str
= str
;
205 static HRESULT
push_instr_bstr(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg
)
210 str
= compiler_alloc_bstr(ctx
, arg
);
212 return E_OUTOFMEMORY
;
214 instr
= push_instr(ctx
, op
);
216 return E_OUTOFMEMORY
;
218 instr_ptr(ctx
, instr
)->arg1
.bstr
= str
;
222 static HRESULT
push_instr_bstr_uint(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg1
, unsigned arg2
)
227 str
= compiler_alloc_bstr(ctx
, arg1
);
229 return E_OUTOFMEMORY
;
231 instr
= push_instr(ctx
, op
);
233 return E_OUTOFMEMORY
;
235 instr_ptr(ctx
, instr
)->arg1
.bstr
= str
;
236 instr_ptr(ctx
, instr
)->arg2
.uint
= arg2
;
240 static HRESULT
push_instr_uint_str(compiler_ctx_t
*ctx
, jsop_t op
, unsigned arg1
, const WCHAR
*arg2
)
245 str
= compiler_alloc_string(ctx
->code
, arg2
);
247 return E_OUTOFMEMORY
;
249 instr
= push_instr(ctx
, op
);
251 return E_OUTOFMEMORY
;
253 instr_ptr(ctx
, instr
)->arg1
.uint
= arg1
;
254 instr_ptr(ctx
, instr
)->arg2
.str
= str
;
258 static HRESULT
push_instr_double(compiler_ctx_t
*ctx
, jsop_t op
, double arg
)
263 dbl
= compiler_alloc(ctx
->code
, sizeof(arg
));
265 return E_OUTOFMEMORY
;
268 instr
= push_instr(ctx
, op
);
270 return E_OUTOFMEMORY
;
272 instr_ptr(ctx
, instr
)->arg1
.dbl
= dbl
;
276 static HRESULT
push_instr_uint(compiler_ctx_t
*ctx
, jsop_t op
, unsigned arg
)
280 instr
= push_instr(ctx
, op
);
282 return E_OUTOFMEMORY
;
284 instr_ptr(ctx
, instr
)->arg1
.uint
= arg
;
288 static HRESULT
compile_binary_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
292 hres
= compile_expression(ctx
, expr
->expression1
);
296 hres
= compile_expression(ctx
, expr
->expression2
);
300 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
303 static HRESULT
compile_unary_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
, jsop_t op
)
307 hres
= compile_expression(ctx
, expr
->expression
);
311 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
314 /* ECMA-262 3rd Edition 11.2.1 */
315 static HRESULT
compile_member_expression(compiler_ctx_t
*ctx
, member_expression_t
*expr
)
319 hres
= compile_expression(ctx
, expr
->expression
);
323 return push_instr_bstr(ctx
, OP_member
, expr
->identifier
);
326 #define LABEL_FLAG 0x80000000
328 static unsigned alloc_label(compiler_ctx_t
*ctx
)
330 if(!ctx
->labels_size
) {
331 ctx
->labels
= heap_alloc(8 * sizeof(*ctx
->labels
));
334 ctx
->labels_size
= 8;
335 }else if(ctx
->labels_size
== ctx
->labels_cnt
) {
336 unsigned *new_labels
;
338 new_labels
= heap_realloc(ctx
->labels
, 2*ctx
->labels_size
*sizeof(*ctx
->labels
));
342 ctx
->labels
= new_labels
;
343 ctx
->labels_size
*= 2;
346 return ctx
->labels_cnt
++ | LABEL_FLAG
;
349 static void label_set_addr(compiler_ctx_t
*ctx
, unsigned label
)
351 assert(label
& LABEL_FLAG
);
352 ctx
->labels
[label
& ~LABEL_FLAG
] = ctx
->code_off
;
355 static inline BOOL
is_memberid_expr(expression_type_t type
)
357 return type
== EXPR_IDENT
|| type
== EXPR_MEMBER
|| type
== EXPR_ARRAY
;
360 static HRESULT
compile_memberid_expression(compiler_ctx_t
*ctx
, expression_t
*expr
, unsigned flags
)
366 identifier_expression_t
*ident_expr
= (identifier_expression_t
*)expr
;
368 hres
= push_instr_bstr_uint(ctx
, OP_identid
, ident_expr
->identifier
, flags
);
372 binary_expression_t
*array_expr
= (binary_expression_t
*)expr
;
374 hres
= compile_expression(ctx
, array_expr
->expression1
);
378 hres
= compile_expression(ctx
, array_expr
->expression2
);
382 hres
= push_instr_uint(ctx
, OP_memberid
, flags
);
386 member_expression_t
*member_expr
= (member_expression_t
*)expr
;
388 hres
= compile_expression(ctx
, member_expr
->expression
);
392 /* FIXME: Potential optimization */
393 hres
= push_instr_str(ctx
, OP_str
, member_expr
->identifier
);
397 hres
= push_instr_uint(ctx
, OP_memberid
, flags
);
407 static HRESULT
compile_increment_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
, jsop_t op
, int n
)
411 if(!is_memberid_expr(expr
->expression
->type
)) {
412 hres
= compile_expression(ctx
, expr
->expression
);
416 return push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
419 hres
= compile_memberid_expression(ctx
, expr
->expression
, fdexNameEnsure
);
423 return push_instr_int(ctx
, op
, n
);
426 /* ECMA-262 3rd Edition 11.14 */
427 static HRESULT
compile_comma_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
)
431 hres
= compile_expression(ctx
, expr
->expression1
);
435 if(!push_instr(ctx
, OP_pop
))
436 return E_OUTOFMEMORY
;
438 return compile_expression(ctx
, expr
->expression2
);
441 /* ECMA-262 3rd Edition 11.11 */
442 static HRESULT
compile_logical_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
447 hres
= compile_expression(ctx
, expr
->expression1
);
451 instr
= push_instr(ctx
, op
);
453 return E_OUTOFMEMORY
;
455 hres
= compile_expression(ctx
, expr
->expression2
);
459 instr_ptr(ctx
, instr
)->arg1
.uint
= ctx
->code_off
;
463 /* ECMA-262 3rd Edition 11.12 */
464 static HRESULT
compile_conditional_expression(compiler_ctx_t
*ctx
, conditional_expression_t
*expr
)
466 unsigned jmp_false
, jmp_end
;
469 hres
= compile_expression(ctx
, expr
->expression
);
473 jmp_false
= push_instr(ctx
, OP_cnd_z
);
475 return E_OUTOFMEMORY
;
477 hres
= compile_expression(ctx
, expr
->true_expression
);
481 jmp_end
= push_instr(ctx
, OP_jmp
);
483 return E_OUTOFMEMORY
;
485 instr_ptr(ctx
, jmp_false
)->arg1
.uint
= ctx
->code_off
;
486 if(!push_instr(ctx
, OP_pop
))
487 return E_OUTOFMEMORY
;
489 hres
= compile_expression(ctx
, expr
->false_expression
);
493 instr_ptr(ctx
, jmp_end
)->arg1
.uint
= ctx
->code_off
;
497 static HRESULT
compile_new_expression(compiler_ctx_t
*ctx
, call_expression_t
*expr
)
499 unsigned arg_cnt
= 0;
503 hres
= compile_expression(ctx
, expr
->expression
);
507 for(arg
= expr
->argument_list
; arg
; arg
= arg
->next
) {
508 hres
= compile_expression(ctx
, arg
->expr
);
514 return push_instr_int(ctx
, OP_new
, arg_cnt
);
517 static HRESULT
compile_call_expression(compiler_ctx_t
*ctx
, call_expression_t
*expr
, BOOL
*no_ret
)
519 unsigned arg_cnt
= 0;
525 if(is_memberid_expr(expr
->expression
->type
)) {
527 hres
= compile_memberid_expression(ctx
, expr
->expression
, 0);
530 hres
= compile_expression(ctx
, expr
->expression
);
536 for(arg
= expr
->argument_list
; arg
; arg
= arg
->next
) {
537 hres
= compile_expression(ctx
, arg
->expr
);
543 instr
= push_instr(ctx
, op
);
545 return E_OUTOFMEMORY
;
547 instr_ptr(ctx
, instr
)->arg1
.uint
= arg_cnt
;
548 instr_ptr(ctx
, instr
)->arg2
.lng
= no_ret
== NULL
;
554 static HRESULT
compile_delete_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
)
558 switch(expr
->expression
->type
) {
560 binary_expression_t
*array_expr
= (binary_expression_t
*)expr
->expression
;
562 hres
= compile_expression(ctx
, array_expr
->expression1
);
566 hres
= compile_expression(ctx
, array_expr
->expression2
);
570 if(!push_instr(ctx
, OP_delete
))
571 return E_OUTOFMEMORY
;
575 member_expression_t
*member_expr
= (member_expression_t
*)expr
->expression
;
577 hres
= compile_expression(ctx
, member_expr
->expression
);
581 /* FIXME: Potential optimization */
582 hres
= push_instr_str(ctx
, OP_str
, member_expr
->identifier
);
586 if(!push_instr(ctx
, OP_delete
))
587 return E_OUTOFMEMORY
;
591 return push_instr_bstr(ctx
, OP_delete_ident
, ((identifier_expression_t
*)expr
->expression
)->identifier
);
593 const WCHAR fixmeW
[] = {'F','I','X','M','E',0};
595 WARN("invalid delete, unimplemented exception message\n");
597 hres
= compile_expression(ctx
, expr
->expression
);
601 return push_instr_uint_str(ctx
, OP_throw_type
, JS_E_INVALID_DELETE
, fixmeW
);
608 static HRESULT
compile_assign_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
612 if(!is_memberid_expr(expr
->expression1
->type
)) {
613 hres
= compile_expression(ctx
, expr
->expression1
);
617 hres
= compile_expression(ctx
, expr
->expression2
);
621 if(op
!= OP_LAST
&& !push_instr(ctx
, op
))
622 return E_OUTOFMEMORY
;
624 return push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
627 hres
= compile_memberid_expression(ctx
, expr
->expression1
, fdexNameEnsure
);
631 if(op
!= OP_LAST
&& !push_instr(ctx
, OP_refval
))
632 return E_OUTOFMEMORY
;
634 hres
= compile_expression(ctx
, expr
->expression2
);
638 if(op
!= OP_LAST
&& !push_instr(ctx
, op
))
639 return E_OUTOFMEMORY
;
641 if(!push_instr(ctx
, OP_assign
))
642 return E_OUTOFMEMORY
;
647 static HRESULT
compile_typeof_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
)
652 if(is_memberid_expr(expr
->expression
->type
)) {
653 if(expr
->expression
->type
== EXPR_IDENT
)
654 return push_instr_str(ctx
, OP_typeofident
, ((identifier_expression_t
*)expr
->expression
)->identifier
);
657 hres
= compile_memberid_expression(ctx
, expr
->expression
, 0);
660 hres
= compile_expression(ctx
, expr
->expression
);
665 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
668 static HRESULT
compile_literal(compiler_ctx_t
*ctx
, literal_t
*literal
)
670 switch(literal
->type
) {
672 return push_instr_int(ctx
, OP_bool
, literal
->u
.bval
);
674 return push_instr_double(ctx
, OP_double
, literal
->u
.dval
);
676 return push_instr_int(ctx
, OP_int
, literal
->u
.lval
);
678 return push_instr(ctx
, OP_null
) ? S_OK
: E_OUTOFMEMORY
;
680 return push_instr_str(ctx
, OP_str
, literal
->u
.wstr
);
685 str
= compiler_alloc(ctx
->code
, (literal
->u
.regexp
.str_len
+1)*sizeof(WCHAR
));
687 return E_OUTOFMEMORY
;
688 memcpy(str
, literal
->u
.regexp
.str
, literal
->u
.regexp
.str_len
*sizeof(WCHAR
));
689 str
[literal
->u
.regexp
.str_len
] = 0;
691 instr
= push_instr(ctx
, OP_regexp
);
693 return E_OUTOFMEMORY
;
695 instr_ptr(ctx
, instr
)->arg1
.str
= str
;
696 instr_ptr(ctx
, instr
)->arg2
.lng
= literal
->u
.regexp
.flags
;
705 static HRESULT
literal_as_bstr(compiler_ctx_t
*ctx
, literal_t
*literal
, BSTR
*str
)
707 switch(literal
->type
) {
709 *str
= compiler_alloc_bstr(ctx
, literal
->u
.wstr
);
712 *str
= int_to_bstr(literal
->u
.lval
);
715 return double_to_bstr(literal
->u
.dval
, str
);
720 return *str
? S_OK
: E_OUTOFMEMORY
;
723 static HRESULT
compile_array_literal(compiler_ctx_t
*ctx
, array_literal_expression_t
*expr
)
725 unsigned i
, elem_cnt
= expr
->length
;
726 array_element_t
*iter
;
729 for(iter
= expr
->element_list
; iter
; iter
= iter
->next
) {
730 elem_cnt
+= iter
->elision
+1;
732 for(i
=0; i
< iter
->elision
; i
++) {
733 if(!push_instr(ctx
, OP_undefined
))
734 return E_OUTOFMEMORY
;
737 hres
= compile_expression(ctx
, iter
->expr
);
742 for(i
=0; i
< expr
->length
; i
++) {
743 if(!push_instr(ctx
, OP_undefined
))
744 return E_OUTOFMEMORY
;
747 return push_instr_uint(ctx
, OP_carray
, elem_cnt
);
750 static HRESULT
compile_object_literal(compiler_ctx_t
*ctx
, property_value_expression_t
*expr
)
757 if(!push_instr(ctx
, OP_new_obj
))
758 return E_OUTOFMEMORY
;
760 for(iter
= expr
->property_list
; iter
; iter
= iter
->next
) {
761 hres
= literal_as_bstr(ctx
, iter
->name
, &name
);
765 hres
= compile_expression(ctx
, iter
->value
);
769 instr
= push_instr(ctx
, OP_obj_prop
);
771 return E_OUTOFMEMORY
;
773 instr_ptr(ctx
, instr
)->arg1
.bstr
= name
;
779 static HRESULT
compile_function_expression(compiler_ctx_t
*ctx
, function_expression_t
*expr
)
783 /* FIXME: not exactly right */
785 return push_instr_bstr(ctx
, OP_ident
, expr
->identifier
);
787 instr
= push_instr(ctx
, OP_func
);
789 return E_OUTOFMEMORY
;
791 instr_ptr(ctx
, instr
)->arg1
.func
= expr
;
795 static HRESULT
compile_expression_noret(compiler_ctx_t
*ctx
, expression_t
*expr
, BOOL
*no_ret
)
799 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
801 return compile_logical_expression(ctx
, (binary_expression_t
*)expr
, OP_cnd_z
);
803 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_array
);
805 return compile_array_literal(ctx
, (array_literal_expression_t
*)expr
);
807 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_LAST
);
809 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
811 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_and
);
813 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
815 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
817 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
819 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
821 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
822 case EXPR_ASSIGNLSHIFT
:
823 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_lshift
);
824 case EXPR_ASSIGNRSHIFT
:
825 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift
);
826 case EXPR_ASSIGNRRSHIFT
:
827 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift2
);
829 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
831 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_and
);
833 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_bneg
);
835 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
837 return compile_call_expression(ctx
, (call_expression_t
*)expr
, no_ret
);
839 return compile_comma_expression(ctx
, (binary_expression_t
*)expr
);
841 return compile_conditional_expression(ctx
, (conditional_expression_t
*)expr
);
843 return compile_delete_expression(ctx
, (unary_expression_t
*)expr
);
845 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
847 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq
);
849 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq2
);
851 return compile_function_expression(ctx
, (function_expression_t
*)expr
);
853 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gt
);
855 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gteq
);
857 return push_instr_bstr(ctx
, OP_ident
, ((identifier_expression_t
*)expr
)->identifier
);
859 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_in
);
860 case EXPR_INSTANCEOF
:
861 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_instanceof
);
863 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lt
);
865 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lteq
);
867 return compile_literal(ctx
, ((literal_expression_t
*)expr
)->literal
);
869 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_neg
);
871 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lshift
);
873 return compile_member_expression(ctx
, (member_expression_t
*)expr
);
875 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_minus
);
877 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
879 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
881 return compile_new_expression(ctx
, (call_expression_t
*)expr
);
883 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq
);
885 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq2
);
887 return compile_logical_expression(ctx
, (binary_expression_t
*)expr
, OP_cnd_nz
);
889 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_tonum
);
891 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_postinc
, -1);
893 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_postinc
, 1);
895 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_preinc
, -1);
897 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_preinc
, 1);
899 return compile_object_literal(ctx
, (property_value_expression_t
*)expr
);
901 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift
);
903 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift2
);
905 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
907 return push_instr(ctx
, OP_this
) ? S_OK
: E_OUTOFMEMORY
;
909 return compile_typeof_expression(ctx
, (unary_expression_t
*)expr
);
911 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_void
);
913 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
921 static HRESULT
compile_expression(compiler_ctx_t
*ctx
, expression_t
*expr
)
923 return compile_expression_noret(ctx
, expr
, NULL
);
926 static inline BOOL
is_loop_statement(statement_type_t type
)
928 return type
== STAT_FOR
|| type
== STAT_FORIN
|| type
== STAT_WHILE
;
931 /* ECMA-262 3rd Edition 12.1 */
932 static HRESULT
compile_block_statement(compiler_ctx_t
*ctx
, statement_t
*iter
)
936 /* FIXME: do it only if needed */
938 return push_instr(ctx
, OP_undefined
) ? S_OK
: E_OUTOFMEMORY
;
941 hres
= compile_statement(ctx
, NULL
, iter
);
949 if(!push_instr(ctx
, OP_pop
))
950 return E_OUTOFMEMORY
;
956 /* ECMA-262 3rd Edition 12.2 */
957 static HRESULT
compile_variable_list(compiler_ctx_t
*ctx
, variable_declaration_t
*list
)
959 variable_declaration_t
*iter
;
962 for(iter
= list
; iter
; iter
= iter
->next
) {
966 hres
= compile_expression(ctx
, iter
->expr
);
970 hres
= push_instr_bstr(ctx
, OP_var_set
, iter
->identifier
);
978 /* ECMA-262 3rd Edition 12.2 */
979 static HRESULT
compile_var_statement(compiler_ctx_t
*ctx
, var_statement_t
*stat
)
983 hres
= compile_variable_list(ctx
, stat
->variable_list
);
987 return push_instr(ctx
, OP_undefined
) ? S_OK
: E_OUTOFMEMORY
;
990 /* ECMA-262 3rd Edition 12.4 */
991 static HRESULT
compile_expression_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
996 hres
= compile_expression_noret(ctx
, stat
->expr
, &no_ret
);
1000 /* FIXME: that's a big potential optimization */
1001 if(no_ret
&& !push_instr(ctx
, OP_undefined
))
1002 return E_OUTOFMEMORY
;
1007 /* ECMA-262 3rd Edition 12.5 */
1008 static HRESULT
compile_if_statement(compiler_ctx_t
*ctx
, if_statement_t
*stat
)
1010 unsigned jmp_else
, jmp_end
;
1013 hres
= compile_expression(ctx
, stat
->expr
);
1017 jmp_else
= push_instr(ctx
, OP_jmp_z
);
1019 return E_OUTOFMEMORY
;
1021 hres
= compile_statement(ctx
, NULL
, stat
->if_stat
);
1025 jmp_end
= push_instr(ctx
, OP_jmp
);
1027 return E_OUTOFMEMORY
;
1029 instr_ptr(ctx
, jmp_else
)->arg1
.uint
= ctx
->code_off
;
1031 if(stat
->else_stat
) {
1032 hres
= compile_statement(ctx
, NULL
, stat
->else_stat
);
1036 /* FIXME: We could sometimes avoid it */
1037 if(!push_instr(ctx
, OP_undefined
))
1038 return E_OUTOFMEMORY
;
1041 instr_ptr(ctx
, jmp_end
)->arg1
.uint
= ctx
->code_off
;
1045 /* ECMA-262 3rd Edition 12.6.2 */
1046 static HRESULT
compile_while_statement(compiler_ctx_t
*ctx
, while_statement_t
*stat
)
1048 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1052 stat_ctx
.break_label
= alloc_label(ctx
);
1053 if(!stat_ctx
.break_label
)
1054 return E_OUTOFMEMORY
;
1056 stat_ctx
.continue_label
= alloc_label(ctx
);
1057 if(!stat_ctx
.continue_label
)
1058 return E_OUTOFMEMORY
;
1060 if(!stat
->do_while
) {
1062 if(!push_instr(ctx
, OP_undefined
))
1063 return E_OUTOFMEMORY
;
1065 jmp_off
= ctx
->code_off
;
1066 label_set_addr(ctx
, stat_ctx
.continue_label
);
1067 hres
= compile_expression(ctx
, stat
->expr
);
1071 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1075 if(!push_instr(ctx
, OP_pop
))
1076 return E_OUTOFMEMORY
;
1078 jmp_off
= ctx
->code_off
;
1081 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1085 if(stat
->do_while
) {
1086 label_set_addr(ctx
, stat_ctx
.continue_label
);
1087 hres
= compile_expression(ctx
, stat
->expr
);
1091 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1095 if(!push_instr(ctx
, OP_pop
))
1096 return E_OUTOFMEMORY
;
1099 hres
= push_instr_uint(ctx
, OP_jmp
, jmp_off
);
1103 label_set_addr(ctx
, stat_ctx
.break_label
);
1107 /* ECMA-262 3rd Edition 12.6.3 */
1108 static HRESULT
compile_for_statement(compiler_ctx_t
*ctx
, for_statement_t
*stat
)
1110 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1114 if(stat
->variable_list
) {
1115 hres
= compile_variable_list(ctx
, stat
->variable_list
);
1118 }else if(stat
->begin_expr
) {
1119 BOOL no_ret
= FALSE
;
1121 hres
= compile_expression_noret(ctx
, stat
->begin_expr
, &no_ret
);
1124 if(!no_ret
&& !push_instr(ctx
, OP_pop
))
1125 return E_OUTOFMEMORY
;
1128 stat_ctx
.break_label
= alloc_label(ctx
);
1129 if(!stat_ctx
.break_label
)
1130 return E_OUTOFMEMORY
;
1132 stat_ctx
.continue_label
= alloc_label(ctx
);
1133 if(!stat_ctx
.continue_label
)
1134 return E_OUTOFMEMORY
;
1137 if(!push_instr(ctx
, OP_undefined
))
1138 return E_OUTOFMEMORY
;
1140 expr_off
= ctx
->code_off
;
1143 hres
= compile_expression(ctx
, stat
->expr
);
1147 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1152 if(!push_instr(ctx
, OP_pop
))
1153 return E_OUTOFMEMORY
;
1155 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1159 label_set_addr(ctx
, stat_ctx
.continue_label
);
1161 if(stat
->end_expr
) {
1162 BOOL no_ret
= FALSE
;
1164 hres
= compile_expression_noret(ctx
, stat
->end_expr
, &no_ret
);
1168 if(!no_ret
&& !push_instr(ctx
, OP_pop
))
1169 return E_OUTOFMEMORY
;
1172 hres
= push_instr_uint(ctx
, OP_jmp
, expr_off
);
1176 label_set_addr(ctx
, stat_ctx
.break_label
);
1180 /* ECMA-262 3rd Edition 12.6.4 */
1181 static HRESULT
compile_forin_statement(compiler_ctx_t
*ctx
, forin_statement_t
*stat
)
1183 statement_ctx_t stat_ctx
= {4, FALSE
, FALSE
};
1186 if(stat
->variable
) {
1187 hres
= compile_variable_list(ctx
, stat
->variable
);
1192 stat_ctx
.break_label
= alloc_label(ctx
);
1193 if(!stat_ctx
.break_label
)
1194 return E_OUTOFMEMORY
;
1196 stat_ctx
.continue_label
= alloc_label(ctx
);
1197 if(!stat_ctx
.continue_label
)
1198 return E_OUTOFMEMORY
;
1200 hres
= compile_expression(ctx
, stat
->in_expr
);
1204 if(stat
->variable
) {
1205 hres
= push_instr_bstr_uint(ctx
, OP_identid
, stat
->variable
->identifier
, fdexNameEnsure
);
1208 }else if(is_memberid_expr(stat
->expr
->type
)) {
1209 hres
= compile_memberid_expression(ctx
, stat
->expr
, fdexNameEnsure
);
1213 hres
= push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
1217 /* FIXME: compile statement anyways when we depend on compiler to check errors */
1221 hres
= push_instr_int(ctx
, OP_int
, DISPID_STARTENUM
);
1226 if(!push_instr(ctx
, OP_undefined
))
1227 return E_OUTOFMEMORY
;
1229 label_set_addr(ctx
, stat_ctx
.continue_label
);
1230 hres
= push_instr_uint(ctx
, OP_forin
, stat_ctx
.break_label
);
1232 return E_OUTOFMEMORY
;
1234 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1238 hres
= push_instr_uint(ctx
, OP_jmp
, stat_ctx
.continue_label
);
1242 label_set_addr(ctx
, stat_ctx
.break_label
);
1246 static HRESULT
pop_to_stat(compiler_ctx_t
*ctx
, statement_ctx_t
*stat_ctx
)
1248 unsigned stack_pop
= 0;
1249 statement_ctx_t
*iter
;
1251 for(iter
= ctx
->stat_ctx
; iter
!= stat_ctx
; iter
= iter
->next
) {
1252 if(iter
->using_scope
&& !push_instr(ctx
, OP_pop_scope
))
1253 return E_OUTOFMEMORY
;
1254 if(iter
->using_except
&& !push_instr(ctx
, OP_pop_except
))
1255 return E_OUTOFMEMORY
;
1256 stack_pop
+= iter
->stack_use
;
1259 /* FIXME: optimize */
1260 while(stack_pop
--) {
1261 if(!push_instr(ctx
, OP_pop
))
1262 return E_OUTOFMEMORY
;
1268 /* ECMA-262 3rd Edition 12.7 */
1269 static HRESULT
compile_continue_statement(compiler_ctx_t
*ctx
, branch_statement_t
*stat
)
1271 statement_ctx_t
*pop_ctx
;
1274 if(stat
->identifier
) {
1275 statement_t
*label_stat
;
1276 statement_ctx_t
*iter
;
1280 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
1281 if(iter
->continue_label
)
1283 if(iter
->labelled_stat
&& !strcmpW(iter
->labelled_stat
->identifier
, stat
->identifier
))
1288 WARN("Label not found\n");
1289 return JS_E_LABEL_NOT_FOUND
;
1292 /* Labelled continue are allowed only on loops */
1293 for(label_stat
= iter
->labelled_stat
->statement
;
1294 label_stat
->type
== STAT_LABEL
;
1295 label_stat
= ((labelled_statement_t
*)label_stat
)->statement
);
1296 if(!is_loop_statement(label_stat
->type
)) {
1297 WARN("Label is not a loop\n");
1298 return JS_E_INVALID_CONTINUE
;
1301 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1302 if(pop_ctx
->continue_label
)
1307 WARN("continue outside loop\n");
1308 return JS_E_INVALID_CONTINUE
;
1312 hres
= pop_to_stat(ctx
, pop_ctx
);
1316 if(!push_instr(ctx
, OP_undefined
))
1317 return E_OUTOFMEMORY
;
1319 return push_instr_uint(ctx
, OP_jmp
, pop_ctx
->continue_label
);
1322 /* ECMA-262 3rd Edition 12.8 */
1323 static HRESULT
compile_break_statement(compiler_ctx_t
*ctx
, branch_statement_t
*stat
)
1325 statement_ctx_t
*pop_ctx
;
1328 if(stat
->identifier
) {
1329 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1330 if(pop_ctx
->labelled_stat
&& !strcmpW(pop_ctx
->labelled_stat
->identifier
, stat
->identifier
)) {
1331 assert(pop_ctx
->break_label
);
1337 WARN("Label not found\n");
1338 return JS_E_LABEL_NOT_FOUND
;
1341 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1342 if(pop_ctx
->break_label
&& !pop_ctx
->labelled_stat
)
1347 WARN("Break outside loop\n");
1348 return JS_E_INVALID_BREAK
;
1352 hres
= pop_to_stat(ctx
, pop_ctx
->next
);
1356 if(!push_instr(ctx
, OP_undefined
))
1357 return E_OUTOFMEMORY
;
1359 return push_instr_uint(ctx
, OP_jmp
, pop_ctx
->break_label
);
1362 /* ECMA-262 3rd Edition 12.9 */
1363 static HRESULT
compile_return_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1367 hres
= pop_to_stat(ctx
, NULL
);
1372 hres
= compile_expression(ctx
, stat
->expr
);
1377 return push_instr(ctx
, OP_ret
) ? S_OK
: E_OUTOFMEMORY
;
1380 /* ECMA-262 3rd Edition 12.10 */
1381 static HRESULT
compile_with_statement(compiler_ctx_t
*ctx
, with_statement_t
*stat
)
1383 statement_ctx_t stat_ctx
= {0, TRUE
, FALSE
};
1386 hres
= compile_expression(ctx
, stat
->expr
);
1390 if(!push_instr(ctx
, OP_push_scope
))
1391 return E_OUTOFMEMORY
;
1393 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1397 if(!push_instr(ctx
, OP_pop_scope
))
1398 return E_OUTOFMEMORY
;
1403 /* ECMA-262 3rd Edition 12.10 */
1404 static HRESULT
compile_labelled_statement(compiler_ctx_t
*ctx
, labelled_statement_t
*stat
)
1406 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
, 0, 0, stat
}, *iter
;
1409 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
1410 if(iter
->labelled_stat
&& !strcmpW(iter
->labelled_stat
->identifier
, stat
->identifier
)) {
1411 WARN("Label %s redefined\n", debugstr_w(stat
->identifier
));
1412 return JS_E_LABEL_REDEFINED
;
1416 /* Labelled breaks are allowed for any labelled statements, not only loops (violating spec) */
1417 stat_ctx
.break_label
= alloc_label(ctx
);
1418 if(!stat_ctx
.break_label
)
1419 return E_OUTOFMEMORY
;
1421 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1425 label_set_addr(ctx
, stat_ctx
.break_label
);
1429 /* ECMA-262 3rd Edition 12.13 */
1430 static HRESULT
compile_switch_statement(compiler_ctx_t
*ctx
, switch_statement_t
*stat
)
1432 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1433 unsigned case_cnt
= 0, *case_jmps
, i
, default_jmp
;
1434 BOOL have_default
= FALSE
;
1435 statement_t
*stat_iter
;
1436 case_clausule_t
*iter
;
1439 hres
= compile_expression(ctx
, stat
->expr
);
1443 stat_ctx
.break_label
= alloc_label(ctx
);
1444 if(!stat_ctx
.break_label
)
1445 return E_OUTOFMEMORY
;
1447 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1452 case_jmps
= heap_alloc(case_cnt
* sizeof(*case_jmps
));
1454 return E_OUTOFMEMORY
;
1457 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1459 have_default
= TRUE
;
1463 hres
= compile_expression(ctx
, iter
->expr
);
1467 case_jmps
[i
] = push_instr(ctx
, OP_case
);
1469 hres
= E_OUTOFMEMORY
;
1475 if(SUCCEEDED(hres
)) {
1476 if(push_instr(ctx
, OP_pop
)) {
1477 default_jmp
= push_instr(ctx
, OP_jmp
);
1479 hres
= E_OUTOFMEMORY
;
1481 hres
= E_OUTOFMEMORY
;
1486 heap_free(case_jmps
);
1491 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1492 while(iter
->next
&& iter
->next
->stat
== iter
->stat
) {
1493 instr_ptr(ctx
, iter
->expr
? case_jmps
[i
++] : default_jmp
)->arg1
.uint
= ctx
->code_off
;
1497 instr_ptr(ctx
, iter
->expr
? case_jmps
[i
++] : default_jmp
)->arg1
.uint
= ctx
->code_off
;
1499 for(stat_iter
= iter
->stat
; stat_iter
&& (!iter
->next
|| iter
->next
->stat
!= stat_iter
); stat_iter
= stat_iter
->next
) {
1500 hres
= compile_statement(ctx
, &stat_ctx
, stat_iter
);
1504 if(stat_iter
->next
&& !push_instr(ctx
, OP_pop
)) {
1505 hres
= E_OUTOFMEMORY
;
1513 heap_free(case_jmps
);
1516 assert(i
== case_cnt
);
1519 instr_ptr(ctx
, default_jmp
)->arg1
.uint
= ctx
->code_off
;
1520 if(!push_instr(ctx
, OP_undefined
))
1521 return E_OUTOFMEMORY
;
1524 label_set_addr(ctx
, stat_ctx
.break_label
);
1528 /* ECMA-262 3rd Edition 12.13 */
1529 static HRESULT
compile_throw_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1533 hres
= compile_expression(ctx
, stat
->expr
);
1537 return push_instr(ctx
, OP_throw
) ? S_OK
: E_OUTOFMEMORY
;
1540 /* ECMA-262 3rd Edition 12.14 */
1541 static HRESULT
compile_try_statement(compiler_ctx_t
*ctx
, try_statement_t
*stat
)
1543 statement_ctx_t try_ctx
= {0, FALSE
, TRUE
}, catch_ctx
= {0, TRUE
, FALSE
};
1544 statement_ctx_t finally_ctx
= {2, FALSE
, FALSE
};
1545 unsigned push_except
;
1549 push_except
= push_instr(ctx
, OP_push_except
);
1551 return E_OUTOFMEMORY
;
1553 if(stat
->catch_block
) {
1554 ident
= compiler_alloc_bstr(ctx
, stat
->catch_block
->identifier
);
1556 return E_OUTOFMEMORY
;
1561 instr_ptr(ctx
, push_except
)->arg2
.bstr
= ident
;
1563 if(!stat
->catch_block
)
1564 try_ctx
.stack_use
= 2;
1566 hres
= compile_statement(ctx
, &try_ctx
, stat
->try_statement
);
1570 if(!push_instr(ctx
, OP_pop_except
))
1571 return E_OUTOFMEMORY
;
1573 if(stat
->catch_block
) {
1574 unsigned jmp_finally
;
1576 jmp_finally
= push_instr(ctx
, OP_jmp
);
1578 return E_OUTOFMEMORY
;
1580 instr_ptr(ctx
, push_except
)->arg1
.uint
= ctx
->code_off
;
1582 hres
= compile_statement(ctx
, &catch_ctx
, stat
->catch_block
->statement
);
1586 if(!push_instr(ctx
, OP_pop_scope
))
1587 return E_OUTOFMEMORY
;
1589 instr_ptr(ctx
, jmp_finally
)->arg1
.uint
= ctx
->code_off
;
1591 instr_ptr(ctx
, push_except
)->arg1
.uint
= ctx
->code_off
;
1594 if(stat
->finally_statement
) {
1596 if(!push_instr(ctx
, OP_pop
))
1597 return E_OUTOFMEMORY
;
1599 hres
= compile_statement(ctx
, stat
->catch_block
? NULL
: &finally_ctx
, stat
->finally_statement
);
1603 if(!stat
->catch_block
&& !push_instr(ctx
, OP_end_finally
))
1604 return E_OUTOFMEMORY
;
1610 static HRESULT
compile_statement(compiler_ctx_t
*ctx
, statement_ctx_t
*stat_ctx
, statement_t
*stat
)
1615 stat_ctx
->next
= ctx
->stat_ctx
;
1616 ctx
->stat_ctx
= stat_ctx
;
1619 switch(stat
->type
) {
1621 hres
= compile_block_statement(ctx
, ((block_statement_t
*)stat
)->stat_list
);
1624 hres
= compile_break_statement(ctx
, (branch_statement_t
*)stat
);
1627 hres
= compile_continue_statement(ctx
, (branch_statement_t
*)stat
);
1630 hres
= push_instr(ctx
, OP_undefined
) ? S_OK
: E_OUTOFMEMORY
; /* FIXME */
1633 hres
= compile_expression_statement(ctx
, (expression_statement_t
*)stat
);
1636 hres
= compile_for_statement(ctx
, (for_statement_t
*)stat
);
1639 hres
= compile_forin_statement(ctx
, (forin_statement_t
*)stat
);
1642 hres
= compile_if_statement(ctx
, (if_statement_t
*)stat
);
1645 hres
= compile_labelled_statement(ctx
, (labelled_statement_t
*)stat
);
1648 hres
= compile_return_statement(ctx
, (expression_statement_t
*)stat
);
1651 hres
= compile_switch_statement(ctx
, (switch_statement_t
*)stat
);
1654 hres
= compile_throw_statement(ctx
, (expression_statement_t
*)stat
);
1657 hres
= compile_try_statement(ctx
, (try_statement_t
*)stat
);
1660 hres
= compile_var_statement(ctx
, (var_statement_t
*)stat
);
1663 hres
= compile_while_statement(ctx
, (while_statement_t
*)stat
);
1666 hres
= compile_with_statement(ctx
, (with_statement_t
*)stat
);
1674 assert(ctx
->stat_ctx
== stat_ctx
);
1675 ctx
->stat_ctx
= stat_ctx
->next
;
1681 static void resolve_labels(compiler_ctx_t
*ctx
, unsigned off
)
1685 for(instr
= ctx
->code
->instrs
+off
; instr
< ctx
->code
->instrs
+ctx
->code_off
; instr
++) {
1686 if(instr_info
[instr
->op
].arg1_type
== ARG_ADDR
&& (instr
->arg1
.uint
& LABEL_FLAG
)) {
1687 assert((instr
->arg1
.uint
& ~LABEL_FLAG
) < ctx
->labels_cnt
);
1688 instr
->arg1
.uint
= ctx
->labels
[instr
->arg1
.uint
& ~LABEL_FLAG
];
1690 assert(instr_info
[instr
->op
].arg2_type
!= ARG_ADDR
);
1693 ctx
->labels_cnt
= 0;
1696 void release_bytecode(bytecode_t
*code
)
1704 parser_release(code
->parser
);
1706 for(i
=0; i
< code
->bstr_cnt
; i
++)
1707 SysFreeString(code
->bstr_pool
[i
]);
1709 heap_free(code
->source
);
1710 jsheap_free(&code
->heap
);
1711 heap_free(code
->bstr_pool
);
1712 heap_free(code
->instrs
);
1716 static HRESULT
init_code(compiler_ctx_t
*compiler
, const WCHAR
*source
)
1718 compiler
->code
= heap_alloc_zero(sizeof(bytecode_t
));
1720 return E_OUTOFMEMORY
;
1722 compiler
->code
->ref
= 1;
1723 jsheap_init(&compiler
->code
->heap
);
1725 compiler
->code
->source
= heap_strdupW(source
);
1726 if(!compiler
->code
->source
) {
1727 release_bytecode(compiler
->code
);
1728 return E_OUTOFMEMORY
;
1731 compiler
->code
->instrs
= heap_alloc(64 * sizeof(instr_t
));
1732 if(!compiler
->code
->instrs
) {
1733 release_bytecode(compiler
->code
);
1734 return E_OUTOFMEMORY
;
1737 compiler
->code_size
= 64;
1738 compiler
->code_off
= 1;
1742 static HRESULT
compile_function(compiler_ctx_t
*ctx
, source_elements_t
*source
, BOOL from_eval
)
1744 function_declaration_t
*iter
;
1750 off
= ctx
->code_off
;
1751 hres
= compile_block_statement(ctx
, source
->statement
);
1755 resolve_labels(ctx
, off
);
1757 if(!from_eval
&& !push_instr(ctx
, OP_pop
))
1758 return E_OUTOFMEMORY
;
1759 if(!push_instr(ctx
, OP_ret
))
1760 return E_OUTOFMEMORY
;
1762 if(TRACE_ON(jscript_disas
))
1763 dump_code(ctx
, off
);
1765 source
->instr_off
= off
;
1767 for(iter
= source
->functions
; iter
; iter
= iter
->next
) {
1768 hres
= compile_function(ctx
, iter
->expr
->source_elements
, FALSE
);
1776 HRESULT
compile_script(script_ctx_t
*ctx
, const WCHAR
*code
, const WCHAR
*delimiter
, BOOL from_eval
, BOOL use_decode
,
1779 compiler_ctx_t compiler
= {0};
1782 hres
= init_code(&compiler
, code
);
1787 hres
= decode_source(compiler
.code
->source
);
1789 WARN("Decoding failed\n");
1794 hres
= script_parse(ctx
, compiler
.code
->source
, delimiter
, from_eval
, &compiler
.parser
);
1796 release_bytecode(compiler
.code
);
1800 compiler
.code
->parser
= compiler
.parser
;
1802 hres
= compile_function(&compiler
, compiler
.parser
->source
, from_eval
);
1804 release_bytecode(compiler
.code
);
1808 *ret
= compiler
.code
;