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
;
55 function_code_t
*func
;
60 instr_arg_type_t arg1_type
;
61 instr_arg_type_t arg2_type
;
63 #define X(n,a,b,c) {#n,b,c},
68 static void dump_instr_arg(instr_arg_type_t type
, instr_arg_t
*arg
)
72 TRACE_(jscript_disas
)("\t%s", debugstr_w(arg
->str
));
75 TRACE_(jscript_disas
)("\t%s", debugstr_wn(arg
->bstr
, SysStringLen(arg
->bstr
)));
78 TRACE_(jscript_disas
)("\t%d", arg
->uint
);
82 TRACE_(jscript_disas
)("\t%u", arg
->uint
);
85 TRACE_(jscript_disas
)("\t%lf", *arg
->dbl
);
95 static void dump_code(compiler_ctx_t
*ctx
, unsigned off
)
99 for(instr
= ctx
->code
->instrs
+off
; instr
< ctx
->code
->instrs
+ctx
->code_off
; instr
++) {
100 TRACE_(jscript_disas
)("%d:\t%s", (int)(instr
-ctx
->code
->instrs
), instr_info
[instr
->op
].op_str
);
101 dump_instr_arg(instr_info
[instr
->op
].arg1_type
, &instr
->arg1
);
102 dump_instr_arg(instr_info
[instr
->op
].arg2_type
, &instr
->arg2
);
103 TRACE_(jscript_disas
)("\n");
107 static HRESULT
compile_expression(compiler_ctx_t
*,expression_t
*);
108 static HRESULT
compile_statement(compiler_ctx_t
*,statement_ctx_t
*,statement_t
*);
110 static inline void *compiler_alloc(bytecode_t
*code
, size_t size
)
112 return jsheap_alloc(&code
->heap
, size
);
115 static WCHAR
*compiler_alloc_string(bytecode_t
*code
, const WCHAR
*str
)
120 size
= (strlenW(str
)+1)*sizeof(WCHAR
);
121 ret
= compiler_alloc(code
, size
);
123 memcpy(ret
, str
, size
);
127 static BSTR
compiler_alloc_bstr(compiler_ctx_t
*ctx
, const WCHAR
*str
)
129 if(!ctx
->code
->bstr_pool_size
) {
130 ctx
->code
->bstr_pool
= heap_alloc(8 * sizeof(BSTR
));
131 if(!ctx
->code
->bstr_pool
)
133 ctx
->code
->bstr_pool_size
= 8;
134 }else if(ctx
->code
->bstr_pool_size
== ctx
->code
->bstr_cnt
) {
137 new_pool
= heap_realloc(ctx
->code
->bstr_pool
, ctx
->code
->bstr_pool_size
*2*sizeof(BSTR
));
141 ctx
->code
->bstr_pool
= new_pool
;
142 ctx
->code
->bstr_pool_size
*= 2;
145 ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
] = SysAllocString(str
);
146 if(!ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
])
149 return ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
++];
152 static unsigned push_instr(compiler_ctx_t
*ctx
, jsop_t op
)
154 assert(ctx
->code_size
>= ctx
->code_off
);
156 if(ctx
->code_size
== ctx
->code_off
) {
159 new_instrs
= heap_realloc(ctx
->code
->instrs
, ctx
->code_size
*2*sizeof(instr_t
));
163 ctx
->code
->instrs
= new_instrs
;
167 ctx
->code
->instrs
[ctx
->code_off
].op
= op
;
168 return ctx
->code_off
++;
171 static inline instr_t
*instr_ptr(compiler_ctx_t
*ctx
, unsigned off
)
173 assert(off
< ctx
->code_off
);
174 return ctx
->code
->instrs
+ off
;
177 static HRESULT
push_instr_int(compiler_ctx_t
*ctx
, jsop_t op
, LONG arg
)
181 instr
= push_instr(ctx
, op
);
183 return E_OUTOFMEMORY
;
185 instr_ptr(ctx
, instr
)->arg1
.lng
= arg
;
189 static HRESULT
push_instr_str(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg
)
194 str
= compiler_alloc_string(ctx
->code
, arg
);
196 return E_OUTOFMEMORY
;
198 instr
= push_instr(ctx
, op
);
200 return E_OUTOFMEMORY
;
202 instr_ptr(ctx
, instr
)->arg1
.str
= str
;
206 static HRESULT
push_instr_bstr(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg
)
211 str
= compiler_alloc_bstr(ctx
, arg
);
213 return E_OUTOFMEMORY
;
215 instr
= push_instr(ctx
, op
);
217 return E_OUTOFMEMORY
;
219 instr_ptr(ctx
, instr
)->arg1
.bstr
= str
;
223 static HRESULT
push_instr_bstr_uint(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg1
, unsigned arg2
)
228 str
= compiler_alloc_bstr(ctx
, arg1
);
230 return E_OUTOFMEMORY
;
232 instr
= push_instr(ctx
, op
);
234 return E_OUTOFMEMORY
;
236 instr_ptr(ctx
, instr
)->arg1
.bstr
= str
;
237 instr_ptr(ctx
, instr
)->arg2
.uint
= arg2
;
241 static HRESULT
push_instr_uint_str(compiler_ctx_t
*ctx
, jsop_t op
, unsigned arg1
, const WCHAR
*arg2
)
246 str
= compiler_alloc_string(ctx
->code
, arg2
);
248 return E_OUTOFMEMORY
;
250 instr
= push_instr(ctx
, op
);
252 return E_OUTOFMEMORY
;
254 instr_ptr(ctx
, instr
)->arg1
.uint
= arg1
;
255 instr_ptr(ctx
, instr
)->arg2
.str
= str
;
259 static HRESULT
push_instr_double(compiler_ctx_t
*ctx
, jsop_t op
, double arg
)
264 dbl
= compiler_alloc(ctx
->code
, sizeof(arg
));
266 return E_OUTOFMEMORY
;
269 instr
= push_instr(ctx
, op
);
271 return E_OUTOFMEMORY
;
273 instr_ptr(ctx
, instr
)->arg1
.dbl
= dbl
;
277 static HRESULT
push_instr_uint(compiler_ctx_t
*ctx
, jsop_t op
, unsigned arg
)
281 instr
= push_instr(ctx
, op
);
283 return E_OUTOFMEMORY
;
285 instr_ptr(ctx
, instr
)->arg1
.uint
= arg
;
289 static HRESULT
compile_binary_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
293 hres
= compile_expression(ctx
, expr
->expression1
);
297 hres
= compile_expression(ctx
, expr
->expression2
);
301 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
304 static HRESULT
compile_unary_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
, jsop_t op
)
308 hres
= compile_expression(ctx
, expr
->expression
);
312 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
315 /* ECMA-262 3rd Edition 11.2.1 */
316 static HRESULT
compile_member_expression(compiler_ctx_t
*ctx
, member_expression_t
*expr
)
320 hres
= compile_expression(ctx
, expr
->expression
);
324 return push_instr_bstr(ctx
, OP_member
, expr
->identifier
);
327 #define LABEL_FLAG 0x80000000
329 static unsigned alloc_label(compiler_ctx_t
*ctx
)
331 if(!ctx
->labels_size
) {
332 ctx
->labels
= heap_alloc(8 * sizeof(*ctx
->labels
));
335 ctx
->labels_size
= 8;
336 }else if(ctx
->labels_size
== ctx
->labels_cnt
) {
337 unsigned *new_labels
;
339 new_labels
= heap_realloc(ctx
->labels
, 2*ctx
->labels_size
*sizeof(*ctx
->labels
));
343 ctx
->labels
= new_labels
;
344 ctx
->labels_size
*= 2;
347 return ctx
->labels_cnt
++ | LABEL_FLAG
;
350 static void label_set_addr(compiler_ctx_t
*ctx
, unsigned label
)
352 assert(label
& LABEL_FLAG
);
353 ctx
->labels
[label
& ~LABEL_FLAG
] = ctx
->code_off
;
356 static inline BOOL
is_memberid_expr(expression_type_t type
)
358 return type
== EXPR_IDENT
|| type
== EXPR_MEMBER
|| type
== EXPR_ARRAY
;
361 static HRESULT
compile_memberid_expression(compiler_ctx_t
*ctx
, expression_t
*expr
, unsigned flags
)
367 identifier_expression_t
*ident_expr
= (identifier_expression_t
*)expr
;
369 hres
= push_instr_bstr_uint(ctx
, OP_identid
, ident_expr
->identifier
, flags
);
373 binary_expression_t
*array_expr
= (binary_expression_t
*)expr
;
375 hres
= compile_expression(ctx
, array_expr
->expression1
);
379 hres
= compile_expression(ctx
, array_expr
->expression2
);
383 hres
= push_instr_uint(ctx
, OP_memberid
, flags
);
387 member_expression_t
*member_expr
= (member_expression_t
*)expr
;
389 hres
= compile_expression(ctx
, member_expr
->expression
);
393 /* FIXME: Potential optimization */
394 hres
= push_instr_str(ctx
, OP_str
, member_expr
->identifier
);
398 hres
= push_instr_uint(ctx
, OP_memberid
, flags
);
408 static HRESULT
compile_increment_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
, jsop_t op
, int n
)
412 if(!is_memberid_expr(expr
->expression
->type
)) {
413 hres
= compile_expression(ctx
, expr
->expression
);
417 return push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
420 hres
= compile_memberid_expression(ctx
, expr
->expression
, fdexNameEnsure
);
424 return push_instr_int(ctx
, op
, n
);
427 /* ECMA-262 3rd Edition 11.14 */
428 static HRESULT
compile_comma_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
)
432 hres
= compile_expression(ctx
, expr
->expression1
);
436 if(!push_instr(ctx
, OP_pop
))
437 return E_OUTOFMEMORY
;
439 return compile_expression(ctx
, expr
->expression2
);
442 /* ECMA-262 3rd Edition 11.11 */
443 static HRESULT
compile_logical_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
448 hres
= compile_expression(ctx
, expr
->expression1
);
452 instr
= push_instr(ctx
, op
);
454 return E_OUTOFMEMORY
;
456 hres
= compile_expression(ctx
, expr
->expression2
);
460 instr_ptr(ctx
, instr
)->arg1
.uint
= ctx
->code_off
;
464 /* ECMA-262 3rd Edition 11.12 */
465 static HRESULT
compile_conditional_expression(compiler_ctx_t
*ctx
, conditional_expression_t
*expr
)
467 unsigned jmp_false
, jmp_end
;
470 hres
= compile_expression(ctx
, expr
->expression
);
474 jmp_false
= push_instr(ctx
, OP_cnd_z
);
476 return E_OUTOFMEMORY
;
478 hres
= compile_expression(ctx
, expr
->true_expression
);
482 jmp_end
= push_instr(ctx
, OP_jmp
);
484 return E_OUTOFMEMORY
;
486 instr_ptr(ctx
, jmp_false
)->arg1
.uint
= ctx
->code_off
;
487 if(!push_instr(ctx
, OP_pop
))
488 return E_OUTOFMEMORY
;
490 hres
= compile_expression(ctx
, expr
->false_expression
);
494 instr_ptr(ctx
, jmp_end
)->arg1
.uint
= ctx
->code_off
;
498 static HRESULT
compile_new_expression(compiler_ctx_t
*ctx
, call_expression_t
*expr
)
500 unsigned arg_cnt
= 0;
504 hres
= compile_expression(ctx
, expr
->expression
);
508 for(arg
= expr
->argument_list
; arg
; arg
= arg
->next
) {
509 hres
= compile_expression(ctx
, arg
->expr
);
515 return push_instr_int(ctx
, OP_new
, arg_cnt
);
518 static HRESULT
compile_call_expression(compiler_ctx_t
*ctx
, call_expression_t
*expr
, BOOL
*no_ret
)
520 unsigned arg_cnt
= 0;
526 if(is_memberid_expr(expr
->expression
->type
)) {
528 hres
= compile_memberid_expression(ctx
, expr
->expression
, 0);
531 hres
= compile_expression(ctx
, expr
->expression
);
537 for(arg
= expr
->argument_list
; arg
; arg
= arg
->next
) {
538 hres
= compile_expression(ctx
, arg
->expr
);
544 instr
= push_instr(ctx
, op
);
546 return E_OUTOFMEMORY
;
548 instr_ptr(ctx
, instr
)->arg1
.uint
= arg_cnt
;
549 instr_ptr(ctx
, instr
)->arg2
.lng
= no_ret
== NULL
;
555 static HRESULT
compile_delete_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
)
559 switch(expr
->expression
->type
) {
561 binary_expression_t
*array_expr
= (binary_expression_t
*)expr
->expression
;
563 hres
= compile_expression(ctx
, array_expr
->expression1
);
567 hres
= compile_expression(ctx
, array_expr
->expression2
);
571 if(!push_instr(ctx
, OP_delete
))
572 return E_OUTOFMEMORY
;
576 member_expression_t
*member_expr
= (member_expression_t
*)expr
->expression
;
578 hres
= compile_expression(ctx
, member_expr
->expression
);
582 /* FIXME: Potential optimization */
583 hres
= push_instr_str(ctx
, OP_str
, member_expr
->identifier
);
587 if(!push_instr(ctx
, OP_delete
))
588 return E_OUTOFMEMORY
;
592 return push_instr_bstr(ctx
, OP_delete_ident
, ((identifier_expression_t
*)expr
->expression
)->identifier
);
594 const WCHAR fixmeW
[] = {'F','I','X','M','E',0};
596 WARN("invalid delete, unimplemented exception message\n");
598 hres
= compile_expression(ctx
, expr
->expression
);
602 return push_instr_uint_str(ctx
, OP_throw_type
, JS_E_INVALID_DELETE
, fixmeW
);
609 static HRESULT
compile_assign_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
611 BOOL use_throw_path
= FALSE
;
612 unsigned arg_cnt
= 0;
615 if(expr
->expression1
->type
== EXPR_CALL
) {
616 call_expression_t
*call_expr
= (call_expression_t
*)expr
->expression1
;
620 FIXME("op %d not supported on parametrized assign expressions\n", op
);
624 if(is_memberid_expr(call_expr
->expression
->type
) && call_expr
->argument_list
) {
625 hres
= compile_memberid_expression(ctx
, call_expr
->expression
, fdexNameEnsure
);
629 for(arg
= call_expr
->argument_list
; arg
; arg
= arg
->next
) {
630 hres
= compile_expression(ctx
, arg
->expr
);
636 use_throw_path
= TRUE
;
638 }else if(is_memberid_expr(expr
->expression1
->type
)) {
639 hres
= compile_memberid_expression(ctx
, expr
->expression1
, fdexNameEnsure
);
643 use_throw_path
= TRUE
;
647 /* Illegal assignment: evaluate and throw */
648 hres
= compile_expression(ctx
, expr
->expression1
);
652 hres
= compile_expression(ctx
, expr
->expression2
);
656 if(op
!= OP_LAST
&& !push_instr(ctx
, op
))
657 return E_OUTOFMEMORY
;
659 return push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
662 if(op
!= OP_LAST
&& !push_instr(ctx
, OP_refval
))
663 return E_OUTOFMEMORY
;
665 hres
= compile_expression(ctx
, expr
->expression2
);
669 if(op
!= OP_LAST
&& !push_instr(ctx
, op
))
670 return E_OUTOFMEMORY
;
673 return push_instr_uint(ctx
, OP_assign_call
, arg_cnt
);
675 if(!push_instr(ctx
, OP_assign
))
676 return E_OUTOFMEMORY
;
681 static HRESULT
compile_typeof_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
)
686 if(is_memberid_expr(expr
->expression
->type
)) {
687 if(expr
->expression
->type
== EXPR_IDENT
)
688 return push_instr_str(ctx
, OP_typeofident
, ((identifier_expression_t
*)expr
->expression
)->identifier
);
691 hres
= compile_memberid_expression(ctx
, expr
->expression
, 0);
694 hres
= compile_expression(ctx
, expr
->expression
);
699 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
702 static HRESULT
compile_literal(compiler_ctx_t
*ctx
, literal_t
*literal
)
704 switch(literal
->type
) {
706 return push_instr_int(ctx
, OP_bool
, literal
->u
.bval
);
708 return push_instr_double(ctx
, OP_double
, literal
->u
.dval
);
710 return push_instr_int(ctx
, OP_int
, literal
->u
.lval
);
712 return push_instr(ctx
, OP_null
) ? S_OK
: E_OUTOFMEMORY
;
714 return push_instr_str(ctx
, OP_str
, literal
->u
.wstr
);
719 str
= compiler_alloc(ctx
->code
, (literal
->u
.regexp
.str_len
+1)*sizeof(WCHAR
));
721 return E_OUTOFMEMORY
;
722 memcpy(str
, literal
->u
.regexp
.str
, literal
->u
.regexp
.str_len
*sizeof(WCHAR
));
723 str
[literal
->u
.regexp
.str_len
] = 0;
725 instr
= push_instr(ctx
, OP_regexp
);
727 return E_OUTOFMEMORY
;
729 instr_ptr(ctx
, instr
)->arg1
.str
= str
;
730 instr_ptr(ctx
, instr
)->arg2
.lng
= literal
->u
.regexp
.flags
;
739 static HRESULT
literal_as_bstr(compiler_ctx_t
*ctx
, literal_t
*literal
, BSTR
*str
)
741 switch(literal
->type
) {
743 *str
= compiler_alloc_bstr(ctx
, literal
->u
.wstr
);
746 *str
= int_to_bstr(literal
->u
.lval
);
749 return double_to_bstr(literal
->u
.dval
, str
);
754 return *str
? S_OK
: E_OUTOFMEMORY
;
757 static HRESULT
compile_array_literal(compiler_ctx_t
*ctx
, array_literal_expression_t
*expr
)
759 unsigned i
, elem_cnt
= expr
->length
;
760 array_element_t
*iter
;
763 for(iter
= expr
->element_list
; iter
; iter
= iter
->next
) {
764 elem_cnt
+= iter
->elision
+1;
766 for(i
=0; i
< iter
->elision
; i
++) {
767 if(!push_instr(ctx
, OP_undefined
))
768 return E_OUTOFMEMORY
;
771 hres
= compile_expression(ctx
, iter
->expr
);
776 for(i
=0; i
< expr
->length
; i
++) {
777 if(!push_instr(ctx
, OP_undefined
))
778 return E_OUTOFMEMORY
;
781 return push_instr_uint(ctx
, OP_carray
, elem_cnt
);
784 static HRESULT
compile_object_literal(compiler_ctx_t
*ctx
, property_value_expression_t
*expr
)
791 if(!push_instr(ctx
, OP_new_obj
))
792 return E_OUTOFMEMORY
;
794 for(iter
= expr
->property_list
; iter
; iter
= iter
->next
) {
795 hres
= literal_as_bstr(ctx
, iter
->name
, &name
);
799 hres
= compile_expression(ctx
, iter
->value
);
803 instr
= push_instr(ctx
, OP_obj_prop
);
805 return E_OUTOFMEMORY
;
807 instr_ptr(ctx
, instr
)->arg1
.bstr
= name
;
813 static HRESULT
compile_function_expression(compiler_ctx_t
*ctx
, function_expression_t
*expr
)
815 /* FIXME: not exactly right */
816 if(expr
->identifier
) {
817 ctx
->func
->func_cnt
++;
818 return push_instr_bstr(ctx
, OP_ident
, expr
->identifier
);
821 return push_instr_uint(ctx
, OP_func
, ctx
->func
->func_cnt
++);
824 static HRESULT
compile_expression_noret(compiler_ctx_t
*ctx
, expression_t
*expr
, BOOL
*no_ret
)
828 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
830 return compile_logical_expression(ctx
, (binary_expression_t
*)expr
, OP_cnd_z
);
832 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_array
);
834 return compile_array_literal(ctx
, (array_literal_expression_t
*)expr
);
836 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_LAST
);
838 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
840 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_and
);
842 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
844 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
846 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
848 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
850 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
851 case EXPR_ASSIGNLSHIFT
:
852 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_lshift
);
853 case EXPR_ASSIGNRSHIFT
:
854 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift
);
855 case EXPR_ASSIGNRRSHIFT
:
856 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift2
);
858 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
860 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_and
);
862 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_bneg
);
864 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
866 return compile_call_expression(ctx
, (call_expression_t
*)expr
, no_ret
);
868 return compile_comma_expression(ctx
, (binary_expression_t
*)expr
);
870 return compile_conditional_expression(ctx
, (conditional_expression_t
*)expr
);
872 return compile_delete_expression(ctx
, (unary_expression_t
*)expr
);
874 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
876 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq
);
878 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq2
);
880 return compile_function_expression(ctx
, (function_expression_t
*)expr
);
882 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gt
);
884 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gteq
);
886 return push_instr_bstr(ctx
, OP_ident
, ((identifier_expression_t
*)expr
)->identifier
);
888 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_in
);
889 case EXPR_INSTANCEOF
:
890 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_instanceof
);
892 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lt
);
894 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lteq
);
896 return compile_literal(ctx
, ((literal_expression_t
*)expr
)->literal
);
898 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_neg
);
900 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lshift
);
902 return compile_member_expression(ctx
, (member_expression_t
*)expr
);
904 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_minus
);
906 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
908 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
910 return compile_new_expression(ctx
, (call_expression_t
*)expr
);
912 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq
);
914 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq2
);
916 return compile_logical_expression(ctx
, (binary_expression_t
*)expr
, OP_cnd_nz
);
918 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_tonum
);
920 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_postinc
, -1);
922 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_postinc
, 1);
924 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_preinc
, -1);
926 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_preinc
, 1);
928 return compile_object_literal(ctx
, (property_value_expression_t
*)expr
);
930 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift
);
932 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift2
);
934 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
936 return push_instr(ctx
, OP_this
) ? S_OK
: E_OUTOFMEMORY
;
938 return compile_typeof_expression(ctx
, (unary_expression_t
*)expr
);
940 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_void
);
942 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
950 static HRESULT
compile_expression(compiler_ctx_t
*ctx
, expression_t
*expr
)
952 return compile_expression_noret(ctx
, expr
, NULL
);
955 static inline BOOL
is_loop_statement(statement_type_t type
)
957 return type
== STAT_FOR
|| type
== STAT_FORIN
|| type
== STAT_WHILE
;
960 /* ECMA-262 3rd Edition 12.1 */
961 static HRESULT
compile_block_statement(compiler_ctx_t
*ctx
, statement_t
*iter
)
965 /* FIXME: do it only if needed */
967 return push_instr(ctx
, OP_undefined
) ? S_OK
: E_OUTOFMEMORY
;
970 hres
= compile_statement(ctx
, NULL
, iter
);
978 if(!push_instr(ctx
, OP_pop
))
979 return E_OUTOFMEMORY
;
985 /* ECMA-262 3rd Edition 12.2 */
986 static HRESULT
compile_variable_list(compiler_ctx_t
*ctx
, variable_declaration_t
*list
)
988 variable_declaration_t
*iter
;
991 for(iter
= list
; iter
; iter
= iter
->next
) {
995 hres
= compile_expression(ctx
, iter
->expr
);
999 hres
= push_instr_bstr(ctx
, OP_var_set
, iter
->identifier
);
1007 /* ECMA-262 3rd Edition 12.2 */
1008 static HRESULT
compile_var_statement(compiler_ctx_t
*ctx
, var_statement_t
*stat
)
1012 hres
= compile_variable_list(ctx
, stat
->variable_list
);
1016 return push_instr(ctx
, OP_undefined
) ? S_OK
: E_OUTOFMEMORY
;
1019 /* ECMA-262 3rd Edition 12.4 */
1020 static HRESULT
compile_expression_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1022 BOOL no_ret
= FALSE
;
1025 hres
= compile_expression_noret(ctx
, stat
->expr
, &no_ret
);
1029 /* FIXME: that's a big potential optimization */
1030 if(no_ret
&& !push_instr(ctx
, OP_undefined
))
1031 return E_OUTOFMEMORY
;
1036 /* ECMA-262 3rd Edition 12.5 */
1037 static HRESULT
compile_if_statement(compiler_ctx_t
*ctx
, if_statement_t
*stat
)
1039 unsigned jmp_else
, jmp_end
;
1042 hres
= compile_expression(ctx
, stat
->expr
);
1046 jmp_else
= push_instr(ctx
, OP_jmp_z
);
1048 return E_OUTOFMEMORY
;
1050 hres
= compile_statement(ctx
, NULL
, stat
->if_stat
);
1054 jmp_end
= push_instr(ctx
, OP_jmp
);
1056 return E_OUTOFMEMORY
;
1058 instr_ptr(ctx
, jmp_else
)->arg1
.uint
= ctx
->code_off
;
1060 if(stat
->else_stat
) {
1061 hres
= compile_statement(ctx
, NULL
, stat
->else_stat
);
1065 /* FIXME: We could sometimes avoid it */
1066 if(!push_instr(ctx
, OP_undefined
))
1067 return E_OUTOFMEMORY
;
1070 instr_ptr(ctx
, jmp_end
)->arg1
.uint
= ctx
->code_off
;
1074 /* ECMA-262 3rd Edition 12.6.2 */
1075 static HRESULT
compile_while_statement(compiler_ctx_t
*ctx
, while_statement_t
*stat
)
1077 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1081 stat_ctx
.break_label
= alloc_label(ctx
);
1082 if(!stat_ctx
.break_label
)
1083 return E_OUTOFMEMORY
;
1085 stat_ctx
.continue_label
= alloc_label(ctx
);
1086 if(!stat_ctx
.continue_label
)
1087 return E_OUTOFMEMORY
;
1089 if(!stat
->do_while
) {
1091 if(!push_instr(ctx
, OP_undefined
))
1092 return E_OUTOFMEMORY
;
1094 jmp_off
= ctx
->code_off
;
1095 label_set_addr(ctx
, stat_ctx
.continue_label
);
1096 hres
= compile_expression(ctx
, stat
->expr
);
1100 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1104 if(!push_instr(ctx
, OP_pop
))
1105 return E_OUTOFMEMORY
;
1107 jmp_off
= ctx
->code_off
;
1110 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1114 if(stat
->do_while
) {
1115 label_set_addr(ctx
, stat_ctx
.continue_label
);
1116 hres
= compile_expression(ctx
, stat
->expr
);
1120 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1124 if(!push_instr(ctx
, OP_pop
))
1125 return E_OUTOFMEMORY
;
1128 hres
= push_instr_uint(ctx
, OP_jmp
, jmp_off
);
1132 label_set_addr(ctx
, stat_ctx
.break_label
);
1136 /* ECMA-262 3rd Edition 12.6.3 */
1137 static HRESULT
compile_for_statement(compiler_ctx_t
*ctx
, for_statement_t
*stat
)
1139 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1143 if(stat
->variable_list
) {
1144 hres
= compile_variable_list(ctx
, stat
->variable_list
);
1147 }else if(stat
->begin_expr
) {
1148 BOOL no_ret
= FALSE
;
1150 hres
= compile_expression_noret(ctx
, stat
->begin_expr
, &no_ret
);
1153 if(!no_ret
&& !push_instr(ctx
, OP_pop
))
1154 return E_OUTOFMEMORY
;
1157 stat_ctx
.break_label
= alloc_label(ctx
);
1158 if(!stat_ctx
.break_label
)
1159 return E_OUTOFMEMORY
;
1161 stat_ctx
.continue_label
= alloc_label(ctx
);
1162 if(!stat_ctx
.continue_label
)
1163 return E_OUTOFMEMORY
;
1166 if(!push_instr(ctx
, OP_undefined
))
1167 return E_OUTOFMEMORY
;
1169 expr_off
= ctx
->code_off
;
1172 hres
= compile_expression(ctx
, stat
->expr
);
1176 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1181 if(!push_instr(ctx
, OP_pop
))
1182 return E_OUTOFMEMORY
;
1184 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1188 label_set_addr(ctx
, stat_ctx
.continue_label
);
1190 if(stat
->end_expr
) {
1191 BOOL no_ret
= FALSE
;
1193 hres
= compile_expression_noret(ctx
, stat
->end_expr
, &no_ret
);
1197 if(!no_ret
&& !push_instr(ctx
, OP_pop
))
1198 return E_OUTOFMEMORY
;
1201 hres
= push_instr_uint(ctx
, OP_jmp
, expr_off
);
1205 label_set_addr(ctx
, stat_ctx
.break_label
);
1209 /* ECMA-262 3rd Edition 12.6.4 */
1210 static HRESULT
compile_forin_statement(compiler_ctx_t
*ctx
, forin_statement_t
*stat
)
1212 statement_ctx_t stat_ctx
= {4, FALSE
, FALSE
};
1215 if(stat
->variable
) {
1216 hres
= compile_variable_list(ctx
, stat
->variable
);
1221 stat_ctx
.break_label
= alloc_label(ctx
);
1222 if(!stat_ctx
.break_label
)
1223 return E_OUTOFMEMORY
;
1225 stat_ctx
.continue_label
= alloc_label(ctx
);
1226 if(!stat_ctx
.continue_label
)
1227 return E_OUTOFMEMORY
;
1229 hres
= compile_expression(ctx
, stat
->in_expr
);
1233 if(stat
->variable
) {
1234 hres
= push_instr_bstr_uint(ctx
, OP_identid
, stat
->variable
->identifier
, fdexNameEnsure
);
1237 }else if(is_memberid_expr(stat
->expr
->type
)) {
1238 hres
= compile_memberid_expression(ctx
, stat
->expr
, fdexNameEnsure
);
1242 hres
= push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
1246 /* FIXME: compile statement anyways when we depend on compiler to check errors */
1250 hres
= push_instr_int(ctx
, OP_int
, DISPID_STARTENUM
);
1255 if(!push_instr(ctx
, OP_undefined
))
1256 return E_OUTOFMEMORY
;
1258 label_set_addr(ctx
, stat_ctx
.continue_label
);
1259 hres
= push_instr_uint(ctx
, OP_forin
, stat_ctx
.break_label
);
1261 return E_OUTOFMEMORY
;
1263 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1267 hres
= push_instr_uint(ctx
, OP_jmp
, stat_ctx
.continue_label
);
1271 label_set_addr(ctx
, stat_ctx
.break_label
);
1275 static HRESULT
pop_to_stat(compiler_ctx_t
*ctx
, statement_ctx_t
*stat_ctx
)
1277 unsigned stack_pop
= 0;
1278 statement_ctx_t
*iter
;
1280 for(iter
= ctx
->stat_ctx
; iter
!= stat_ctx
; iter
= iter
->next
) {
1281 if(iter
->using_scope
&& !push_instr(ctx
, OP_pop_scope
))
1282 return E_OUTOFMEMORY
;
1283 if(iter
->using_except
&& !push_instr(ctx
, OP_pop_except
))
1284 return E_OUTOFMEMORY
;
1285 stack_pop
+= iter
->stack_use
;
1288 /* FIXME: optimize */
1289 while(stack_pop
--) {
1290 if(!push_instr(ctx
, OP_pop
))
1291 return E_OUTOFMEMORY
;
1297 /* ECMA-262 3rd Edition 12.7 */
1298 static HRESULT
compile_continue_statement(compiler_ctx_t
*ctx
, branch_statement_t
*stat
)
1300 statement_ctx_t
*pop_ctx
;
1303 if(stat
->identifier
) {
1304 statement_t
*label_stat
;
1305 statement_ctx_t
*iter
;
1309 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
1310 if(iter
->continue_label
)
1312 if(iter
->labelled_stat
&& !strcmpW(iter
->labelled_stat
->identifier
, stat
->identifier
))
1317 WARN("Label not found\n");
1318 return JS_E_LABEL_NOT_FOUND
;
1321 /* Labelled continue are allowed only on loops */
1322 for(label_stat
= iter
->labelled_stat
->statement
;
1323 label_stat
->type
== STAT_LABEL
;
1324 label_stat
= ((labelled_statement_t
*)label_stat
)->statement
);
1325 if(!is_loop_statement(label_stat
->type
)) {
1326 WARN("Label is not a loop\n");
1327 return JS_E_INVALID_CONTINUE
;
1330 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1331 if(pop_ctx
->continue_label
)
1336 WARN("continue outside loop\n");
1337 return JS_E_INVALID_CONTINUE
;
1341 hres
= pop_to_stat(ctx
, pop_ctx
);
1345 if(!push_instr(ctx
, OP_undefined
))
1346 return E_OUTOFMEMORY
;
1348 return push_instr_uint(ctx
, OP_jmp
, pop_ctx
->continue_label
);
1351 /* ECMA-262 3rd Edition 12.8 */
1352 static HRESULT
compile_break_statement(compiler_ctx_t
*ctx
, branch_statement_t
*stat
)
1354 statement_ctx_t
*pop_ctx
;
1357 if(stat
->identifier
) {
1358 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1359 if(pop_ctx
->labelled_stat
&& !strcmpW(pop_ctx
->labelled_stat
->identifier
, stat
->identifier
)) {
1360 assert(pop_ctx
->break_label
);
1366 WARN("Label not found\n");
1367 return JS_E_LABEL_NOT_FOUND
;
1370 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1371 if(pop_ctx
->break_label
&& !pop_ctx
->labelled_stat
)
1376 WARN("Break outside loop\n");
1377 return JS_E_INVALID_BREAK
;
1381 hres
= pop_to_stat(ctx
, pop_ctx
->next
);
1385 if(!push_instr(ctx
, OP_undefined
))
1386 return E_OUTOFMEMORY
;
1388 return push_instr_uint(ctx
, OP_jmp
, pop_ctx
->break_label
);
1391 /* ECMA-262 3rd Edition 12.9 */
1392 static HRESULT
compile_return_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1396 hres
= pop_to_stat(ctx
, NULL
);
1401 hres
= compile_expression(ctx
, stat
->expr
);
1406 return push_instr(ctx
, OP_ret
) ? S_OK
: E_OUTOFMEMORY
;
1409 /* ECMA-262 3rd Edition 12.10 */
1410 static HRESULT
compile_with_statement(compiler_ctx_t
*ctx
, with_statement_t
*stat
)
1412 statement_ctx_t stat_ctx
= {0, TRUE
, FALSE
};
1415 hres
= compile_expression(ctx
, stat
->expr
);
1419 if(!push_instr(ctx
, OP_push_scope
))
1420 return E_OUTOFMEMORY
;
1422 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1426 if(!push_instr(ctx
, OP_pop_scope
))
1427 return E_OUTOFMEMORY
;
1432 /* ECMA-262 3rd Edition 12.10 */
1433 static HRESULT
compile_labelled_statement(compiler_ctx_t
*ctx
, labelled_statement_t
*stat
)
1435 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
, 0, 0, stat
}, *iter
;
1438 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
1439 if(iter
->labelled_stat
&& !strcmpW(iter
->labelled_stat
->identifier
, stat
->identifier
)) {
1440 WARN("Label %s redefined\n", debugstr_w(stat
->identifier
));
1441 return JS_E_LABEL_REDEFINED
;
1445 /* Labelled breaks are allowed for any labelled statements, not only loops (violating spec) */
1446 stat_ctx
.break_label
= alloc_label(ctx
);
1447 if(!stat_ctx
.break_label
)
1448 return E_OUTOFMEMORY
;
1450 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1454 label_set_addr(ctx
, stat_ctx
.break_label
);
1458 /* ECMA-262 3rd Edition 12.13 */
1459 static HRESULT
compile_switch_statement(compiler_ctx_t
*ctx
, switch_statement_t
*stat
)
1461 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1462 unsigned case_cnt
= 0, *case_jmps
, i
, default_jmp
;
1463 BOOL have_default
= FALSE
;
1464 statement_t
*stat_iter
;
1465 case_clausule_t
*iter
;
1468 hres
= compile_expression(ctx
, stat
->expr
);
1472 stat_ctx
.break_label
= alloc_label(ctx
);
1473 if(!stat_ctx
.break_label
)
1474 return E_OUTOFMEMORY
;
1476 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1481 case_jmps
= heap_alloc(case_cnt
* sizeof(*case_jmps
));
1483 return E_OUTOFMEMORY
;
1486 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1488 have_default
= TRUE
;
1492 hres
= compile_expression(ctx
, iter
->expr
);
1496 case_jmps
[i
] = push_instr(ctx
, OP_case
);
1498 hres
= E_OUTOFMEMORY
;
1504 if(SUCCEEDED(hres
)) {
1505 if(push_instr(ctx
, OP_pop
)) {
1506 default_jmp
= push_instr(ctx
, OP_jmp
);
1508 hres
= E_OUTOFMEMORY
;
1510 hres
= E_OUTOFMEMORY
;
1515 heap_free(case_jmps
);
1520 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1521 while(iter
->next
&& iter
->next
->stat
== iter
->stat
) {
1522 instr_ptr(ctx
, iter
->expr
? case_jmps
[i
++] : default_jmp
)->arg1
.uint
= ctx
->code_off
;
1526 instr_ptr(ctx
, iter
->expr
? case_jmps
[i
++] : default_jmp
)->arg1
.uint
= ctx
->code_off
;
1528 for(stat_iter
= iter
->stat
; stat_iter
&& (!iter
->next
|| iter
->next
->stat
!= stat_iter
); stat_iter
= stat_iter
->next
) {
1529 hres
= compile_statement(ctx
, &stat_ctx
, stat_iter
);
1533 if(stat_iter
->next
&& !push_instr(ctx
, OP_pop
)) {
1534 hres
= E_OUTOFMEMORY
;
1542 heap_free(case_jmps
);
1545 assert(i
== case_cnt
);
1548 hres
= push_instr_uint(ctx
, OP_jmp
, stat_ctx
.break_label
);
1551 instr_ptr(ctx
, default_jmp
)->arg1
.uint
= ctx
->code_off
;
1552 if(!push_instr(ctx
, OP_undefined
))
1553 return E_OUTOFMEMORY
;
1556 label_set_addr(ctx
, stat_ctx
.break_label
);
1560 /* ECMA-262 3rd Edition 12.13 */
1561 static HRESULT
compile_throw_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1565 hres
= compile_expression(ctx
, stat
->expr
);
1569 return push_instr(ctx
, OP_throw
) ? S_OK
: E_OUTOFMEMORY
;
1572 /* ECMA-262 3rd Edition 12.14 */
1573 static HRESULT
compile_try_statement(compiler_ctx_t
*ctx
, try_statement_t
*stat
)
1575 statement_ctx_t try_ctx
= {0, FALSE
, TRUE
}, catch_ctx
= {0, TRUE
, FALSE
};
1576 statement_ctx_t finally_ctx
= {2, FALSE
, FALSE
};
1577 unsigned push_except
;
1581 push_except
= push_instr(ctx
, OP_push_except
);
1583 return E_OUTOFMEMORY
;
1585 if(stat
->catch_block
) {
1586 ident
= compiler_alloc_bstr(ctx
, stat
->catch_block
->identifier
);
1588 return E_OUTOFMEMORY
;
1593 instr_ptr(ctx
, push_except
)->arg2
.bstr
= ident
;
1595 if(!stat
->catch_block
)
1596 try_ctx
.stack_use
= 2;
1598 hres
= compile_statement(ctx
, &try_ctx
, stat
->try_statement
);
1602 if(!push_instr(ctx
, OP_pop_except
))
1603 return E_OUTOFMEMORY
;
1605 if(stat
->catch_block
) {
1606 unsigned jmp_finally
;
1608 jmp_finally
= push_instr(ctx
, OP_jmp
);
1610 return E_OUTOFMEMORY
;
1612 instr_ptr(ctx
, push_except
)->arg1
.uint
= ctx
->code_off
;
1614 hres
= compile_statement(ctx
, &catch_ctx
, stat
->catch_block
->statement
);
1618 if(!push_instr(ctx
, OP_pop_scope
))
1619 return E_OUTOFMEMORY
;
1621 instr_ptr(ctx
, jmp_finally
)->arg1
.uint
= ctx
->code_off
;
1623 instr_ptr(ctx
, push_except
)->arg1
.uint
= ctx
->code_off
;
1626 if(stat
->finally_statement
) {
1628 if(!push_instr(ctx
, OP_pop
))
1629 return E_OUTOFMEMORY
;
1631 hres
= compile_statement(ctx
, stat
->catch_block
? NULL
: &finally_ctx
, stat
->finally_statement
);
1635 if(!stat
->catch_block
&& !push_instr(ctx
, OP_end_finally
))
1636 return E_OUTOFMEMORY
;
1642 static HRESULT
compile_statement(compiler_ctx_t
*ctx
, statement_ctx_t
*stat_ctx
, statement_t
*stat
)
1647 stat_ctx
->next
= ctx
->stat_ctx
;
1648 ctx
->stat_ctx
= stat_ctx
;
1651 switch(stat
->type
) {
1653 hres
= compile_block_statement(ctx
, ((block_statement_t
*)stat
)->stat_list
);
1656 hres
= compile_break_statement(ctx
, (branch_statement_t
*)stat
);
1659 hres
= compile_continue_statement(ctx
, (branch_statement_t
*)stat
);
1662 hres
= push_instr(ctx
, OP_undefined
) ? S_OK
: E_OUTOFMEMORY
; /* FIXME */
1665 hres
= compile_expression_statement(ctx
, (expression_statement_t
*)stat
);
1668 hres
= compile_for_statement(ctx
, (for_statement_t
*)stat
);
1671 hres
= compile_forin_statement(ctx
, (forin_statement_t
*)stat
);
1674 hres
= compile_if_statement(ctx
, (if_statement_t
*)stat
);
1677 hres
= compile_labelled_statement(ctx
, (labelled_statement_t
*)stat
);
1680 hres
= compile_return_statement(ctx
, (expression_statement_t
*)stat
);
1683 hres
= compile_switch_statement(ctx
, (switch_statement_t
*)stat
);
1686 hres
= compile_throw_statement(ctx
, (expression_statement_t
*)stat
);
1689 hres
= compile_try_statement(ctx
, (try_statement_t
*)stat
);
1692 hres
= compile_var_statement(ctx
, (var_statement_t
*)stat
);
1695 hres
= compile_while_statement(ctx
, (while_statement_t
*)stat
);
1698 hres
= compile_with_statement(ctx
, (with_statement_t
*)stat
);
1706 assert(ctx
->stat_ctx
== stat_ctx
);
1707 ctx
->stat_ctx
= stat_ctx
->next
;
1713 static void resolve_labels(compiler_ctx_t
*ctx
, unsigned off
)
1717 for(instr
= ctx
->code
->instrs
+off
; instr
< ctx
->code
->instrs
+ctx
->code_off
; instr
++) {
1718 if(instr_info
[instr
->op
].arg1_type
== ARG_ADDR
&& (instr
->arg1
.uint
& LABEL_FLAG
)) {
1719 assert((instr
->arg1
.uint
& ~LABEL_FLAG
) < ctx
->labels_cnt
);
1720 instr
->arg1
.uint
= ctx
->labels
[instr
->arg1
.uint
& ~LABEL_FLAG
];
1722 assert(instr_info
[instr
->op
].arg2_type
!= ARG_ADDR
);
1725 ctx
->labels_cnt
= 0;
1728 void release_bytecode(bytecode_t
*code
)
1736 parser_release(code
->parser
);
1738 for(i
=0; i
< code
->bstr_cnt
; i
++)
1739 SysFreeString(code
->bstr_pool
[i
]);
1741 heap_free(code
->source
);
1742 jsheap_free(&code
->heap
);
1743 heap_free(code
->bstr_pool
);
1744 heap_free(code
->instrs
);
1748 static HRESULT
init_code(compiler_ctx_t
*compiler
, const WCHAR
*source
)
1750 compiler
->code
= heap_alloc_zero(sizeof(bytecode_t
));
1752 return E_OUTOFMEMORY
;
1754 compiler
->code
->ref
= 1;
1755 jsheap_init(&compiler
->code
->heap
);
1757 compiler
->code
->source
= heap_strdupW(source
);
1758 if(!compiler
->code
->source
) {
1759 release_bytecode(compiler
->code
);
1760 return E_OUTOFMEMORY
;
1763 compiler
->code
->instrs
= heap_alloc(64 * sizeof(instr_t
));
1764 if(!compiler
->code
->instrs
) {
1765 release_bytecode(compiler
->code
);
1766 return E_OUTOFMEMORY
;
1769 compiler
->code_size
= 64;
1770 compiler
->code_off
= 1;
1774 static HRESULT
compile_function(compiler_ctx_t
*ctx
, source_elements_t
*source
, BOOL from_eval
, function_code_t
*func
)
1776 function_declaration_t
*iter
;
1782 off
= ctx
->code_off
;
1784 hres
= compile_block_statement(ctx
, source
->statement
);
1788 resolve_labels(ctx
, off
);
1790 if(!from_eval
&& !push_instr(ctx
, OP_pop
))
1791 return E_OUTOFMEMORY
;
1792 if(!push_instr(ctx
, OP_ret
))
1793 return E_OUTOFMEMORY
;
1795 if(TRACE_ON(jscript_disas
))
1796 dump_code(ctx
, off
);
1798 func
->instr_off
= off
;
1799 func
->source_elements
= source
;
1801 func
->funcs
= heap_alloc_zero(func
->func_cnt
* sizeof(*func
->funcs
));
1803 return E_OUTOFMEMORY
;
1805 for(iter
= source
->functions
, i
=0; iter
; iter
= iter
->next
, i
++) {
1806 hres
= compile_function(ctx
, iter
->expr
->source_elements
, FALSE
, func
->funcs
+i
);
1809 func
->funcs
[i
].expr
= iter
->expr
;
1812 assert(i
== func
->func_cnt
);
1816 HRESULT
compile_script(script_ctx_t
*ctx
, const WCHAR
*code
, const WCHAR
*delimiter
, BOOL from_eval
, BOOL use_decode
,
1819 compiler_ctx_t compiler
= {0};
1822 hres
= init_code(&compiler
, code
);
1827 hres
= decode_source(compiler
.code
->source
);
1829 WARN("Decoding failed\n");
1834 hres
= script_parse(ctx
, compiler
.code
->source
, delimiter
, from_eval
, &compiler
.parser
);
1836 release_bytecode(compiler
.code
);
1840 compiler
.code
->parser
= compiler
.parser
;
1842 hres
= compile_function(&compiler
, compiler
.parser
->source
, from_eval
, &compiler
.code
->global_code
);
1844 release_bytecode(compiler
.code
);
1848 *ret
= compiler
.code
;