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
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(jscript
);
29 WINE_DECLARE_DEBUG_CHANNEL(jscript_disas
);
31 typedef struct _statement_ctx_t
{
37 unsigned continue_label
;
39 const labelled_statement_t
*labelled_stat
;
41 struct _statement_ctx_t
*next
;
57 local_ref_t
*locals_buf
;
58 unsigned locals_buf_size
;
61 statement_ctx_t
*stat_ctx
;
62 function_code_t
*func
;
64 function_expression_t
*func_head
;
65 function_expression_t
*func_tail
;
70 instr_arg_type_t arg1_type
;
71 instr_arg_type_t arg2_type
;
73 #define X(n,a,b,c) {#n,b,c},
78 static void dump_instr_arg(instr_arg_type_t type
, instr_arg_t
*arg
)
82 TRACE_(jscript_disas
)("\t%s", debugstr_jsstr(arg
->str
));
85 TRACE_(jscript_disas
)("\t%s", debugstr_wn(arg
->bstr
, SysStringLen(arg
->bstr
)));
88 TRACE_(jscript_disas
)("\t%d", arg
->uint
);
92 TRACE_(jscript_disas
)("\t%u", arg
->uint
);
101 static void dump_code(compiler_ctx_t
*ctx
, unsigned off
)
105 for(instr
= ctx
->code
->instrs
+off
; instr
< ctx
->code
->instrs
+ctx
->code_off
; instr
++) {
106 TRACE_(jscript_disas
)("%d:\t%s", (int)(instr
-ctx
->code
->instrs
), instr_info
[instr
->op
].op_str
);
107 if(instr_info
[instr
->op
].arg1_type
== ARG_DBL
) {
108 TRACE_(jscript_disas
)("\t%lf", instr
->u
.dbl
);
110 dump_instr_arg(instr_info
[instr
->op
].arg1_type
, instr
->u
.arg
);
111 dump_instr_arg(instr_info
[instr
->op
].arg2_type
, instr
->u
.arg
+1);
113 TRACE_(jscript_disas
)("\n");
117 static HRESULT
compile_expression(compiler_ctx_t
*,expression_t
*,BOOL
);
118 static HRESULT
compile_statement(compiler_ctx_t
*,statement_ctx_t
*,statement_t
*);
120 static inline void *compiler_alloc(bytecode_t
*code
, size_t size
)
122 return heap_pool_alloc(&code
->heap
, size
);
125 static jsstr_t
*compiler_alloc_string_len(compiler_ctx_t
*ctx
, const WCHAR
*str
, unsigned len
)
129 if(!ctx
->code
->str_pool_size
) {
130 ctx
->code
->str_pool
= heap_alloc(8 * sizeof(jsstr_t
*));
131 if(!ctx
->code
->str_pool
)
133 ctx
->code
->str_pool_size
= 8;
134 }else if(ctx
->code
->str_pool_size
== ctx
->code
->str_cnt
) {
137 new_pool
= heap_realloc(ctx
->code
->str_pool
, ctx
->code
->str_pool_size
*2*sizeof(jsstr_t
*));
141 ctx
->code
->str_pool
= new_pool
;
142 ctx
->code
->str_pool_size
*= 2;
145 new_str
= jsstr_alloc_len(str
, len
);
149 ctx
->code
->str_pool
[ctx
->code
->str_cnt
++] = new_str
;
153 static jsstr_t
*compiler_alloc_string(compiler_ctx_t
*ctx
, const WCHAR
*str
)
155 return compiler_alloc_string_len(ctx
, str
, strlenW(str
));
158 static BOOL
ensure_bstr_slot(compiler_ctx_t
*ctx
)
160 if(!ctx
->code
->bstr_pool_size
) {
161 ctx
->code
->bstr_pool
= heap_alloc(8 * sizeof(BSTR
));
162 if(!ctx
->code
->bstr_pool
)
164 ctx
->code
->bstr_pool_size
= 8;
165 }else if(ctx
->code
->bstr_pool_size
== ctx
->code
->bstr_cnt
) {
168 new_pool
= heap_realloc(ctx
->code
->bstr_pool
, ctx
->code
->bstr_pool_size
*2*sizeof(BSTR
));
172 ctx
->code
->bstr_pool
= new_pool
;
173 ctx
->code
->bstr_pool_size
*= 2;
179 static BSTR
compiler_alloc_bstr(compiler_ctx_t
*ctx
, const WCHAR
*str
)
181 if(!ensure_bstr_slot(ctx
))
184 ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
] = SysAllocString(str
);
185 if(!ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
])
188 return ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
++];
191 static BSTR
compiler_alloc_bstr_len(compiler_ctx_t
*ctx
, const WCHAR
*str
, size_t len
)
193 if(!ensure_bstr_slot(ctx
))
196 ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
] = SysAllocStringLen(str
, len
);
197 if(!ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
])
200 return ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
++];
203 static unsigned push_instr(compiler_ctx_t
*ctx
, jsop_t op
)
205 assert(ctx
->code_size
>= ctx
->code_off
);
207 if(ctx
->code_size
== ctx
->code_off
) {
210 new_instrs
= heap_realloc(ctx
->code
->instrs
, ctx
->code_size
*2*sizeof(instr_t
));
214 ctx
->code
->instrs
= new_instrs
;
218 ctx
->code
->instrs
[ctx
->code_off
].op
= op
;
219 return ctx
->code_off
++;
222 static inline instr_t
*instr_ptr(compiler_ctx_t
*ctx
, unsigned off
)
224 assert(off
< ctx
->code_off
);
225 return ctx
->code
->instrs
+ off
;
228 static HRESULT
push_instr_int(compiler_ctx_t
*ctx
, jsop_t op
, LONG arg
)
232 instr
= push_instr(ctx
, op
);
234 return E_OUTOFMEMORY
;
236 instr_ptr(ctx
, instr
)->u
.arg
->lng
= arg
;
240 static HRESULT
push_instr_str(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg
)
245 str
= compiler_alloc_string(ctx
, arg
);
247 return E_OUTOFMEMORY
;
249 instr
= push_instr(ctx
, op
);
251 return E_OUTOFMEMORY
;
253 instr_ptr(ctx
, instr
)->u
.arg
->str
= str
;
257 static HRESULT
push_instr_bstr(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg
)
262 str
= compiler_alloc_bstr(ctx
, arg
);
264 return E_OUTOFMEMORY
;
266 instr
= push_instr(ctx
, op
);
268 return E_OUTOFMEMORY
;
270 instr_ptr(ctx
, instr
)->u
.arg
->bstr
= str
;
274 static HRESULT
push_instr_bstr_uint(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg1
, unsigned arg2
)
279 str
= compiler_alloc_bstr(ctx
, arg1
);
281 return E_OUTOFMEMORY
;
283 instr
= push_instr(ctx
, op
);
285 return E_OUTOFMEMORY
;
287 instr_ptr(ctx
, instr
)->u
.arg
[0].bstr
= str
;
288 instr_ptr(ctx
, instr
)->u
.arg
[1].uint
= arg2
;
292 static HRESULT
push_instr_uint_str(compiler_ctx_t
*ctx
, jsop_t op
, unsigned arg1
, const WCHAR
*arg2
)
297 str
= compiler_alloc_string(ctx
, arg2
);
299 return E_OUTOFMEMORY
;
301 instr
= push_instr(ctx
, op
);
303 return E_OUTOFMEMORY
;
305 instr_ptr(ctx
, instr
)->u
.arg
[0].uint
= arg1
;
306 instr_ptr(ctx
, instr
)->u
.arg
[1].str
= str
;
310 static HRESULT
push_instr_double(compiler_ctx_t
*ctx
, jsop_t op
, double arg
)
314 instr
= push_instr(ctx
, op
);
316 return E_OUTOFMEMORY
;
318 instr_ptr(ctx
, instr
)->u
.dbl
= arg
;
322 static inline void set_arg_uint(compiler_ctx_t
*ctx
, unsigned instr
, unsigned arg
)
324 instr_ptr(ctx
, instr
)->u
.arg
->uint
= arg
;
327 static HRESULT
push_instr_uint(compiler_ctx_t
*ctx
, jsop_t op
, unsigned arg
)
331 instr
= push_instr(ctx
, op
);
333 return E_OUTOFMEMORY
;
335 set_arg_uint(ctx
, instr
, arg
);
339 static HRESULT
compile_binary_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
343 hres
= compile_expression(ctx
, expr
->expression1
, TRUE
);
347 hres
= compile_expression(ctx
, expr
->expression2
, TRUE
);
351 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
354 static HRESULT
compile_unary_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
, jsop_t op
)
358 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
362 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
365 /* ECMA-262 3rd Edition 11.2.1 */
366 static HRESULT
compile_member_expression(compiler_ctx_t
*ctx
, member_expression_t
*expr
)
370 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
374 return push_instr_bstr(ctx
, OP_member
, expr
->identifier
);
377 #define LABEL_FLAG 0x80000000
379 static unsigned alloc_label(compiler_ctx_t
*ctx
)
381 if(!ctx
->labels_size
) {
382 ctx
->labels
= heap_alloc(8 * sizeof(*ctx
->labels
));
385 ctx
->labels_size
= 8;
386 }else if(ctx
->labels_size
== ctx
->labels_cnt
) {
387 unsigned *new_labels
;
389 new_labels
= heap_realloc(ctx
->labels
, 2*ctx
->labels_size
*sizeof(*ctx
->labels
));
393 ctx
->labels
= new_labels
;
394 ctx
->labels_size
*= 2;
397 return ctx
->labels_cnt
++ | LABEL_FLAG
;
400 static void label_set_addr(compiler_ctx_t
*ctx
, unsigned label
)
402 assert(label
& LABEL_FLAG
);
403 ctx
->labels
[label
& ~LABEL_FLAG
] = ctx
->code_off
;
406 static inline BOOL
is_memberid_expr(expression_type_t type
)
408 return type
== EXPR_IDENT
|| type
== EXPR_MEMBER
|| type
== EXPR_ARRAY
;
411 static BOOL
bind_local(compiler_ctx_t
*ctx
, const WCHAR
*identifier
, int *ret_ref
)
413 statement_ctx_t
*iter
;
416 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
417 if(iter
->using_scope
)
421 ref
= lookup_local(ctx
->func
, identifier
);
429 static HRESULT
emit_identifier_ref(compiler_ctx_t
*ctx
, const WCHAR
*identifier
, unsigned flags
)
432 if(bind_local(ctx
, identifier
, &local_ref
))
433 return push_instr_int(ctx
, OP_local_ref
, local_ref
);
434 return push_instr_bstr_uint(ctx
, OP_identid
, identifier
, flags
);
437 static HRESULT
emit_identifier(compiler_ctx_t
*ctx
, const WCHAR
*identifier
)
440 if(bind_local(ctx
, identifier
, &local_ref
))
441 return push_instr_int(ctx
, OP_local
, local_ref
);
442 return push_instr_bstr(ctx
, OP_ident
, identifier
);
445 static HRESULT
compile_memberid_expression(compiler_ctx_t
*ctx
, expression_t
*expr
, unsigned flags
)
451 identifier_expression_t
*ident_expr
= (identifier_expression_t
*)expr
;
453 hres
= emit_identifier_ref(ctx
, ident_expr
->identifier
, flags
);
457 binary_expression_t
*array_expr
= (binary_expression_t
*)expr
;
459 hres
= compile_expression(ctx
, array_expr
->expression1
, TRUE
);
463 hres
= compile_expression(ctx
, array_expr
->expression2
, TRUE
);
467 hres
= push_instr_uint(ctx
, OP_memberid
, flags
);
471 member_expression_t
*member_expr
= (member_expression_t
*)expr
;
473 hres
= compile_expression(ctx
, member_expr
->expression
, TRUE
);
477 /* FIXME: Potential optimization */
478 hres
= push_instr_str(ctx
, OP_str
, member_expr
->identifier
);
482 hres
= push_instr_uint(ctx
, OP_memberid
, flags
);
491 static HRESULT
compile_increment_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
, jsop_t op
, int n
)
495 if(!is_memberid_expr(expr
->expression
->type
)) {
496 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
500 return push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
503 hres
= compile_memberid_expression(ctx
, expr
->expression
, fdexNameEnsure
);
507 return push_instr_int(ctx
, op
, n
);
510 /* ECMA-262 3rd Edition 11.14 */
511 static HRESULT
compile_comma_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, BOOL emit_ret
)
515 hres
= compile_expression(ctx
, expr
->expression1
, FALSE
);
519 return compile_expression(ctx
, expr
->expression2
, emit_ret
);
522 /* ECMA-262 3rd Edition 11.11 */
523 static HRESULT
compile_logical_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
528 hres
= compile_expression(ctx
, expr
->expression1
, TRUE
);
532 instr
= push_instr(ctx
, op
);
534 return E_OUTOFMEMORY
;
536 hres
= compile_expression(ctx
, expr
->expression2
, TRUE
);
540 set_arg_uint(ctx
, instr
, ctx
->code_off
);
544 /* ECMA-262 3rd Edition 11.12 */
545 static HRESULT
compile_conditional_expression(compiler_ctx_t
*ctx
, conditional_expression_t
*expr
)
547 unsigned jmp_false
, jmp_end
;
550 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
554 jmp_false
= push_instr(ctx
, OP_cnd_z
);
556 return E_OUTOFMEMORY
;
558 hres
= compile_expression(ctx
, expr
->true_expression
, TRUE
);
562 jmp_end
= push_instr(ctx
, OP_jmp
);
564 return E_OUTOFMEMORY
;
566 set_arg_uint(ctx
, jmp_false
, ctx
->code_off
);
567 hres
= push_instr_uint(ctx
, OP_pop
, 1);
571 hres
= compile_expression(ctx
, expr
->false_expression
, TRUE
);
575 set_arg_uint(ctx
, jmp_end
, ctx
->code_off
);
579 static HRESULT
compile_new_expression(compiler_ctx_t
*ctx
, call_expression_t
*expr
)
581 unsigned arg_cnt
= 0;
585 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
589 for(arg
= expr
->argument_list
; arg
; arg
= arg
->next
) {
590 hres
= compile_expression(ctx
, arg
->expr
, TRUE
);
596 hres
= push_instr_uint(ctx
, OP_new
, arg_cnt
);
600 hres
= push_instr_uint(ctx
, OP_pop
, arg_cnt
+1);
604 return push_instr(ctx
, OP_push_ret
) ? S_OK
: E_OUTOFMEMORY
;
607 static HRESULT
compile_call_expression(compiler_ctx_t
*ctx
, call_expression_t
*expr
, BOOL emit_ret
)
609 unsigned arg_cnt
= 0, extra_args
;
615 if(is_memberid_expr(expr
->expression
->type
)) {
618 hres
= compile_memberid_expression(ctx
, expr
->expression
, 0);
622 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
628 for(arg
= expr
->argument_list
; arg
; arg
= arg
->next
) {
629 hres
= compile_expression(ctx
, arg
->expr
, TRUE
);
635 instr
= push_instr(ctx
, op
);
637 return E_OUTOFMEMORY
;
639 instr_ptr(ctx
, instr
)->u
.arg
[0].uint
= arg_cnt
;
640 instr_ptr(ctx
, instr
)->u
.arg
[1].lng
= emit_ret
;
642 hres
= push_instr_uint(ctx
, OP_pop
, arg_cnt
+ extra_args
);
646 return !emit_ret
|| push_instr(ctx
, OP_push_ret
) ? S_OK
: E_OUTOFMEMORY
;
649 static HRESULT
compile_delete_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
)
653 switch(expr
->expression
->type
) {
655 binary_expression_t
*array_expr
= (binary_expression_t
*)expr
->expression
;
657 hres
= compile_expression(ctx
, array_expr
->expression1
, TRUE
);
661 hres
= compile_expression(ctx
, array_expr
->expression2
, TRUE
);
665 if(!push_instr(ctx
, OP_delete
))
666 return E_OUTOFMEMORY
;
670 member_expression_t
*member_expr
= (member_expression_t
*)expr
->expression
;
672 hres
= compile_expression(ctx
, member_expr
->expression
, TRUE
);
676 /* FIXME: Potential optimization */
677 hres
= push_instr_str(ctx
, OP_str
, member_expr
->identifier
);
681 if(!push_instr(ctx
, OP_delete
))
682 return E_OUTOFMEMORY
;
686 return push_instr_bstr(ctx
, OP_delete_ident
, ((identifier_expression_t
*)expr
->expression
)->identifier
);
688 const WCHAR fixmeW
[] = {'F','I','X','M','E',0};
690 WARN("invalid delete, unimplemented exception message\n");
692 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
696 return push_instr_uint_str(ctx
, OP_throw_type
, JS_E_INVALID_DELETE
, fixmeW
);
703 static HRESULT
compile_assign_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
705 BOOL use_throw_path
= FALSE
;
706 unsigned arg_cnt
= 0;
709 if(expr
->expression1
->type
== EXPR_CALL
) {
710 call_expression_t
*call_expr
= (call_expression_t
*)expr
->expression1
;
714 FIXME("op %d not supported on parametrized assign expressions\n", op
);
718 if(is_memberid_expr(call_expr
->expression
->type
) && call_expr
->argument_list
) {
719 hres
= compile_memberid_expression(ctx
, call_expr
->expression
, fdexNameEnsure
);
723 for(arg
= call_expr
->argument_list
; arg
; arg
= arg
->next
) {
724 hres
= compile_expression(ctx
, arg
->expr
, TRUE
);
730 use_throw_path
= TRUE
;
732 }else if(is_memberid_expr(expr
->expression1
->type
)) {
733 hres
= compile_memberid_expression(ctx
, expr
->expression1
, fdexNameEnsure
);
737 use_throw_path
= TRUE
;
741 /* Illegal assignment: evaluate and throw */
742 hres
= compile_expression(ctx
, expr
->expression1
, TRUE
);
746 hres
= compile_expression(ctx
, expr
->expression2
, TRUE
);
750 if(op
!= OP_LAST
&& !push_instr(ctx
, op
))
751 return E_OUTOFMEMORY
;
753 return push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
756 if(op
!= OP_LAST
&& !push_instr(ctx
, OP_refval
))
757 return E_OUTOFMEMORY
;
759 hres
= compile_expression(ctx
, expr
->expression2
, TRUE
);
763 if(op
!= OP_LAST
&& !push_instr(ctx
, op
))
764 return E_OUTOFMEMORY
;
767 return push_instr_uint(ctx
, OP_assign_call
, arg_cnt
);
769 if(!push_instr(ctx
, OP_assign
))
770 return E_OUTOFMEMORY
;
775 static HRESULT
compile_typeof_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
)
780 if(is_memberid_expr(expr
->expression
->type
)) {
781 if(expr
->expression
->type
== EXPR_IDENT
)
782 return push_instr_bstr(ctx
, OP_typeofident
, ((identifier_expression_t
*)expr
->expression
)->identifier
);
785 hres
= compile_memberid_expression(ctx
, expr
->expression
, 0);
788 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
793 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
796 static HRESULT
compile_literal(compiler_ctx_t
*ctx
, literal_t
*literal
)
798 switch(literal
->type
) {
800 return push_instr_int(ctx
, OP_bool
, literal
->u
.bval
);
802 return push_instr_double(ctx
, OP_double
, literal
->u
.dval
);
804 return push_instr(ctx
, OP_null
) ? S_OK
: E_OUTOFMEMORY
;
806 return push_instr_str(ctx
, OP_str
, literal
->u
.wstr
);
811 str
= compiler_alloc_string_len(ctx
, literal
->u
.regexp
.str
, literal
->u
.regexp
.str_len
);
813 return E_OUTOFMEMORY
;
815 instr
= push_instr(ctx
, OP_regexp
);
817 return E_OUTOFMEMORY
;
819 instr_ptr(ctx
, instr
)->u
.arg
[0].str
= str
;
820 instr_ptr(ctx
, instr
)->u
.arg
[1].uint
= literal
->u
.regexp
.flags
;
828 static HRESULT
literal_as_bstr(compiler_ctx_t
*ctx
, literal_t
*literal
, BSTR
*str
)
830 switch(literal
->type
) {
832 *str
= compiler_alloc_bstr(ctx
, literal
->u
.wstr
);
838 hres
= double_to_string(literal
->u
.dval
, &jsstr
);
842 *str
= compiler_alloc_bstr_len(ctx
, NULL
, jsstr_length(jsstr
));
844 jsstr_flush(jsstr
, *str
);
845 jsstr_release(jsstr
);
851 return *str
? S_OK
: E_OUTOFMEMORY
;
854 static HRESULT
compile_array_literal(compiler_ctx_t
*ctx
, array_literal_expression_t
*expr
)
856 unsigned i
, elem_cnt
= expr
->length
;
857 array_element_t
*iter
;
860 for(iter
= expr
->element_list
; iter
; iter
= iter
->next
) {
861 elem_cnt
+= iter
->elision
+1;
863 for(i
=0; i
< iter
->elision
; i
++) {
864 if(!push_instr(ctx
, OP_undefined
))
865 return E_OUTOFMEMORY
;
868 hres
= compile_expression(ctx
, iter
->expr
, TRUE
);
873 for(i
=0; i
< expr
->length
; i
++) {
874 if(!push_instr(ctx
, OP_undefined
))
875 return E_OUTOFMEMORY
;
878 return push_instr_uint(ctx
, OP_carray
, elem_cnt
);
881 static HRESULT
compile_object_literal(compiler_ctx_t
*ctx
, property_value_expression_t
*expr
)
888 if(!push_instr(ctx
, OP_new_obj
))
889 return E_OUTOFMEMORY
;
891 for(iter
= expr
->property_list
; iter
; iter
= iter
->next
) {
892 hres
= literal_as_bstr(ctx
, iter
->name
, &name
);
896 hres
= compile_expression(ctx
, iter
->value
, TRUE
);
900 instr
= push_instr(ctx
, OP_obj_prop
);
902 return E_OUTOFMEMORY
;
904 instr_ptr(ctx
, instr
)->u
.arg
->bstr
= name
;
910 static HRESULT
compile_function_expression(compiler_ctx_t
*ctx
, function_expression_t
*expr
, BOOL emit_ret
)
912 return emit_ret
? push_instr_uint(ctx
, OP_func
, expr
->func_id
) : S_OK
;
915 static HRESULT
compile_expression(compiler_ctx_t
*ctx
, expression_t
*expr
, BOOL emit_ret
)
921 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
924 hres
= compile_logical_expression(ctx
, (binary_expression_t
*)expr
, OP_cnd_z
);
927 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_array
);
930 hres
= compile_array_literal(ctx
, (array_literal_expression_t
*)expr
);
933 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_LAST
);
936 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
939 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_and
);
942 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
945 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
948 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
951 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
954 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
956 case EXPR_ASSIGNLSHIFT
:
957 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_lshift
);
959 case EXPR_ASSIGNRSHIFT
:
960 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift
);
962 case EXPR_ASSIGNRRSHIFT
:
963 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift2
);
966 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
969 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_and
);
972 hres
= compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_bneg
);
975 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
978 return compile_call_expression(ctx
, (call_expression_t
*)expr
, emit_ret
);
980 return compile_comma_expression(ctx
, (binary_expression_t
*)expr
, emit_ret
);
982 hres
= compile_conditional_expression(ctx
, (conditional_expression_t
*)expr
);
985 hres
= compile_delete_expression(ctx
, (unary_expression_t
*)expr
);
988 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
991 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq
);
994 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq2
);
997 return compile_function_expression(ctx
, (function_expression_t
*)expr
, emit_ret
);
999 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gt
);
1001 case EXPR_GREATEREQ
:
1002 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gteq
);
1005 hres
= emit_identifier(ctx
, ((identifier_expression_t
*)expr
)->identifier
);
1008 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_in
);
1010 case EXPR_INSTANCEOF
:
1011 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_instanceof
);
1014 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lt
);
1017 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lteq
);
1020 hres
= compile_literal(ctx
, ((literal_expression_t
*)expr
)->literal
);
1023 hres
= compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_neg
);
1026 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lshift
);
1029 hres
= compile_member_expression(ctx
, (member_expression_t
*)expr
);
1032 hres
= compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_minus
);
1035 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
1038 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
1041 hres
= compile_new_expression(ctx
, (call_expression_t
*)expr
);
1044 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq
);
1047 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq2
);
1050 hres
= compile_logical_expression(ctx
, (binary_expression_t
*)expr
, OP_cnd_nz
);
1053 hres
= compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_tonum
);
1056 hres
= compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_postinc
, -1);
1059 hres
= compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_postinc
, 1);
1062 hres
= compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_preinc
, -1);
1065 hres
= compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_preinc
, 1);
1068 hres
= compile_object_literal(ctx
, (property_value_expression_t
*)expr
);
1071 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift
);
1074 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift2
);
1077 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
1080 return !emit_ret
|| push_instr(ctx
, OP_this
) ? S_OK
: E_OUTOFMEMORY
;
1082 hres
= compile_typeof_expression(ctx
, (unary_expression_t
*)expr
);
1085 hres
= compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_void
);
1088 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
1090 DEFAULT_UNREACHABLE
;
1096 return emit_ret
? S_OK
: push_instr_uint(ctx
, OP_pop
, 1);
1099 static inline BOOL
is_loop_statement(statement_type_t type
)
1101 return type
== STAT_FOR
|| type
== STAT_FORIN
|| type
== STAT_WHILE
;
1104 /* ECMA-262 3rd Edition 12.1 */
1105 static HRESULT
compile_block_statement(compiler_ctx_t
*ctx
, statement_t
*iter
)
1110 hres
= compile_statement(ctx
, NULL
, iter
);
1120 /* ECMA-262 3rd Edition 12.2 */
1121 static HRESULT
compile_variable_list(compiler_ctx_t
*ctx
, variable_declaration_t
*list
)
1123 variable_declaration_t
*iter
;
1126 assert(list
!= NULL
);
1128 for(iter
= list
; iter
; iter
= iter
->next
) {
1132 hres
= emit_identifier_ref(ctx
, iter
->identifier
, 0);
1136 hres
= compile_expression(ctx
, iter
->expr
, TRUE
);
1140 if(!push_instr(ctx
, OP_assign
))
1141 return E_OUTOFMEMORY
;
1143 hres
= push_instr_uint(ctx
, OP_pop
, 1);
1151 /* ECMA-262 3rd Edition 12.2 */
1152 static HRESULT
compile_var_statement(compiler_ctx_t
*ctx
, var_statement_t
*stat
)
1154 return compile_variable_list(ctx
, stat
->variable_list
);
1157 /* ECMA-262 3rd Edition 12.4 */
1158 static HRESULT
compile_expression_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1162 hres
= compile_expression(ctx
, stat
->expr
, ctx
->from_eval
);
1166 return !ctx
->from_eval
|| push_instr(ctx
, OP_setret
) ? S_OK
: E_OUTOFMEMORY
;
1169 /* ECMA-262 3rd Edition 12.5 */
1170 static HRESULT
compile_if_statement(compiler_ctx_t
*ctx
, if_statement_t
*stat
)
1175 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1179 jmp_else
= push_instr(ctx
, OP_jmp_z
);
1181 return E_OUTOFMEMORY
;
1183 hres
= compile_statement(ctx
, NULL
, stat
->if_stat
);
1187 if(stat
->else_stat
) {
1190 jmp_end
= push_instr(ctx
, OP_jmp
);
1192 return E_OUTOFMEMORY
;
1194 set_arg_uint(ctx
, jmp_else
, ctx
->code_off
);
1196 hres
= compile_statement(ctx
, NULL
, stat
->else_stat
);
1200 set_arg_uint(ctx
, jmp_end
, ctx
->code_off
);
1202 set_arg_uint(ctx
, jmp_else
, ctx
->code_off
);
1208 /* ECMA-262 3rd Edition 12.6.2 */
1209 static HRESULT
compile_while_statement(compiler_ctx_t
*ctx
, while_statement_t
*stat
)
1211 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1215 stat_ctx
.break_label
= alloc_label(ctx
);
1216 if(!stat_ctx
.break_label
)
1217 return E_OUTOFMEMORY
;
1219 stat_ctx
.continue_label
= alloc_label(ctx
);
1220 if(!stat_ctx
.continue_label
)
1221 return E_OUTOFMEMORY
;
1223 jmp_off
= ctx
->code_off
;
1225 if(!stat
->do_while
) {
1226 label_set_addr(ctx
, stat_ctx
.continue_label
);
1227 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1231 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1236 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1240 if(stat
->do_while
) {
1241 label_set_addr(ctx
, stat_ctx
.continue_label
);
1242 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1246 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1251 hres
= push_instr_uint(ctx
, OP_jmp
, jmp_off
);
1255 label_set_addr(ctx
, stat_ctx
.break_label
);
1259 /* ECMA-262 3rd Edition 12.6.3 */
1260 static HRESULT
compile_for_statement(compiler_ctx_t
*ctx
, for_statement_t
*stat
)
1262 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1266 if(stat
->variable_list
) {
1267 hres
= compile_variable_list(ctx
, stat
->variable_list
);
1270 }else if(stat
->begin_expr
) {
1271 hres
= compile_expression(ctx
, stat
->begin_expr
, FALSE
);
1276 stat_ctx
.break_label
= alloc_label(ctx
);
1277 if(!stat_ctx
.break_label
)
1278 return E_OUTOFMEMORY
;
1280 stat_ctx
.continue_label
= alloc_label(ctx
);
1281 if(!stat_ctx
.continue_label
)
1282 return E_OUTOFMEMORY
;
1284 expr_off
= ctx
->code_off
;
1287 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1291 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1296 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1300 label_set_addr(ctx
, stat_ctx
.continue_label
);
1302 if(stat
->end_expr
) {
1303 hres
= compile_expression(ctx
, stat
->end_expr
, FALSE
);
1308 hres
= push_instr_uint(ctx
, OP_jmp
, expr_off
);
1312 label_set_addr(ctx
, stat_ctx
.break_label
);
1316 /* ECMA-262 3rd Edition 12.6.4 */
1317 static HRESULT
compile_forin_statement(compiler_ctx_t
*ctx
, forin_statement_t
*stat
)
1319 statement_ctx_t stat_ctx
= {4, FALSE
, FALSE
};
1322 if(stat
->variable
) {
1323 hres
= compile_variable_list(ctx
, stat
->variable
);
1328 stat_ctx
.break_label
= alloc_label(ctx
);
1329 if(!stat_ctx
.break_label
)
1330 return E_OUTOFMEMORY
;
1332 stat_ctx
.continue_label
= alloc_label(ctx
);
1333 if(!stat_ctx
.continue_label
)
1334 return E_OUTOFMEMORY
;
1336 hres
= compile_expression(ctx
, stat
->in_expr
, TRUE
);
1340 if(stat
->variable
) {
1341 hres
= emit_identifier_ref(ctx
, stat
->variable
->identifier
, fdexNameEnsure
);
1344 }else if(is_memberid_expr(stat
->expr
->type
)) {
1345 hres
= compile_memberid_expression(ctx
, stat
->expr
, fdexNameEnsure
);
1349 hres
= push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
1353 /* FIXME: compile statement anyways when we depend on compiler to check errors */
1357 hres
= push_instr_int(ctx
, OP_int
, DISPID_STARTENUM
);
1361 label_set_addr(ctx
, stat_ctx
.continue_label
);
1362 hres
= push_instr_uint(ctx
, OP_forin
, stat_ctx
.break_label
);
1364 return E_OUTOFMEMORY
;
1366 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1370 hres
= push_instr_uint(ctx
, OP_jmp
, stat_ctx
.continue_label
);
1374 label_set_addr(ctx
, stat_ctx
.break_label
);
1378 static HRESULT
pop_to_stat(compiler_ctx_t
*ctx
, BOOL var_stack
, BOOL scope_stack
, statement_ctx_t
*stat_ctx
)
1380 unsigned stack_pop
= 0;
1381 statement_ctx_t
*iter
;
1383 for(iter
= ctx
->stat_ctx
; iter
!= stat_ctx
; iter
= iter
->next
) {
1385 if(iter
->using_scope
&& !push_instr(ctx
, OP_pop_scope
))
1386 return E_OUTOFMEMORY
;
1387 if(iter
->using_except
&& !push_instr(ctx
, OP_pop_except
))
1388 return E_OUTOFMEMORY
;
1390 stack_pop
+= iter
->stack_use
;
1393 if(var_stack
&& stack_pop
) {
1396 hres
= push_instr_uint(ctx
, OP_pop
, stack_pop
);
1404 /* ECMA-262 3rd Edition 12.7 */
1405 static HRESULT
compile_continue_statement(compiler_ctx_t
*ctx
, branch_statement_t
*stat
)
1407 statement_ctx_t
*pop_ctx
;
1410 if(stat
->identifier
) {
1411 statement_t
*label_stat
;
1412 statement_ctx_t
*iter
;
1416 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
1417 if(iter
->continue_label
)
1419 if(iter
->labelled_stat
&& !strcmpW(iter
->labelled_stat
->identifier
, stat
->identifier
))
1424 WARN("Label not found\n");
1425 return JS_E_LABEL_NOT_FOUND
;
1428 /* Labelled continue are allowed only on loops */
1429 for(label_stat
= iter
->labelled_stat
->statement
;
1430 label_stat
->type
== STAT_LABEL
;
1431 label_stat
= ((labelled_statement_t
*)label_stat
)->statement
);
1432 if(!is_loop_statement(label_stat
->type
)) {
1433 WARN("Label is not a loop\n");
1434 return JS_E_INVALID_CONTINUE
;
1437 assert(pop_ctx
!= NULL
);
1439 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1440 if(pop_ctx
->continue_label
)
1445 WARN("continue outside loop\n");
1446 return JS_E_INVALID_CONTINUE
;
1450 hres
= pop_to_stat(ctx
, TRUE
, TRUE
, pop_ctx
);
1454 return push_instr_uint(ctx
, OP_jmp
, pop_ctx
->continue_label
);
1457 /* ECMA-262 3rd Edition 12.8 */
1458 static HRESULT
compile_break_statement(compiler_ctx_t
*ctx
, branch_statement_t
*stat
)
1460 statement_ctx_t
*pop_ctx
;
1463 if(stat
->identifier
) {
1464 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1465 if(pop_ctx
->labelled_stat
&& !strcmpW(pop_ctx
->labelled_stat
->identifier
, stat
->identifier
)) {
1466 assert(pop_ctx
->break_label
);
1472 WARN("Label not found\n");
1473 return JS_E_LABEL_NOT_FOUND
;
1476 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1477 if(pop_ctx
->break_label
&& !pop_ctx
->labelled_stat
)
1482 WARN("Break outside loop\n");
1483 return JS_E_INVALID_BREAK
;
1487 hres
= pop_to_stat(ctx
, TRUE
, TRUE
, pop_ctx
->next
);
1491 return push_instr_uint(ctx
, OP_jmp
, pop_ctx
->break_label
);
1494 /* ECMA-262 3rd Edition 12.9 */
1495 static HRESULT
compile_return_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1499 if(ctx
->from_eval
) {
1500 WARN("misplaced return statement\n");
1501 return JS_E_MISPLACED_RETURN
;
1504 hres
= pop_to_stat(ctx
, TRUE
, FALSE
, NULL
);
1509 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1512 if(!push_instr(ctx
, OP_setret
))
1513 return E_OUTOFMEMORY
;
1516 hres
= pop_to_stat(ctx
, FALSE
, TRUE
, NULL
);
1520 return push_instr_uint(ctx
, OP_ret
, !stat
->expr
);
1523 /* ECMA-262 3rd Edition 12.10 */
1524 static HRESULT
compile_with_statement(compiler_ctx_t
*ctx
, with_statement_t
*stat
)
1526 statement_ctx_t stat_ctx
= {0, TRUE
, FALSE
};
1529 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1533 if(!push_instr(ctx
, OP_push_scope
))
1534 return E_OUTOFMEMORY
;
1536 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1540 if(!push_instr(ctx
, OP_pop_scope
))
1541 return E_OUTOFMEMORY
;
1546 /* ECMA-262 3rd Edition 12.10 */
1547 static HRESULT
compile_labelled_statement(compiler_ctx_t
*ctx
, labelled_statement_t
*stat
)
1549 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
, 0, 0, stat
}, *iter
;
1552 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
1553 if(iter
->labelled_stat
&& !strcmpW(iter
->labelled_stat
->identifier
, stat
->identifier
)) {
1554 WARN("Label %s redefined\n", debugstr_w(stat
->identifier
));
1555 return JS_E_LABEL_REDEFINED
;
1559 /* Labelled breaks are allowed for any labelled statements, not only loops (violating spec) */
1560 stat_ctx
.break_label
= alloc_label(ctx
);
1561 if(!stat_ctx
.break_label
)
1562 return E_OUTOFMEMORY
;
1564 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1568 label_set_addr(ctx
, stat_ctx
.break_label
);
1572 /* ECMA-262 3rd Edition 12.13 */
1573 static HRESULT
compile_switch_statement(compiler_ctx_t
*ctx
, switch_statement_t
*stat
)
1575 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1576 unsigned case_cnt
= 0, *case_jmps
, i
, default_jmp
;
1577 BOOL have_default
= FALSE
;
1578 statement_t
*stat_iter
;
1579 case_clausule_t
*iter
;
1582 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1586 stat_ctx
.break_label
= alloc_label(ctx
);
1587 if(!stat_ctx
.break_label
)
1588 return E_OUTOFMEMORY
;
1590 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1595 case_jmps
= heap_alloc(case_cnt
* sizeof(*case_jmps
));
1597 return E_OUTOFMEMORY
;
1600 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1602 have_default
= TRUE
;
1606 hres
= compile_expression(ctx
, iter
->expr
, TRUE
);
1610 case_jmps
[i
] = push_instr(ctx
, OP_case
);
1612 hres
= E_OUTOFMEMORY
;
1618 if(SUCCEEDED(hres
)) {
1619 hres
= push_instr_uint(ctx
, OP_pop
, 1);
1620 if(SUCCEEDED(hres
)) {
1621 default_jmp
= push_instr(ctx
, OP_jmp
);
1623 hres
= E_OUTOFMEMORY
;
1628 heap_free(case_jmps
);
1633 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1634 while(iter
->next
&& iter
->next
->stat
== iter
->stat
) {
1635 set_arg_uint(ctx
, iter
->expr
? case_jmps
[i
++] : default_jmp
, ctx
->code_off
);
1639 set_arg_uint(ctx
, iter
->expr
? case_jmps
[i
++] : default_jmp
, ctx
->code_off
);
1641 for(stat_iter
= iter
->stat
; stat_iter
&& (!iter
->next
|| iter
->next
->stat
!= stat_iter
);
1642 stat_iter
= stat_iter
->next
) {
1643 hres
= compile_statement(ctx
, &stat_ctx
, stat_iter
);
1651 heap_free(case_jmps
);
1654 assert(i
== case_cnt
);
1657 hres
= push_instr_uint(ctx
, OP_jmp
, stat_ctx
.break_label
);
1660 set_arg_uint(ctx
, default_jmp
, ctx
->code_off
);
1663 label_set_addr(ctx
, stat_ctx
.break_label
);
1667 /* ECMA-262 3rd Edition 12.13 */
1668 static HRESULT
compile_throw_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1672 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1676 return push_instr(ctx
, OP_throw
) ? S_OK
: E_OUTOFMEMORY
;
1679 /* ECMA-262 3rd Edition 12.14 */
1680 static HRESULT
compile_try_statement(compiler_ctx_t
*ctx
, try_statement_t
*stat
)
1682 statement_ctx_t try_ctx
= {0, FALSE
, TRUE
}, catch_ctx
= {0, TRUE
, FALSE
};
1683 statement_ctx_t finally_ctx
= {2, FALSE
, FALSE
};
1684 unsigned push_except
;
1688 push_except
= push_instr(ctx
, OP_push_except
);
1690 return E_OUTOFMEMORY
;
1692 if(stat
->catch_block
) {
1693 ident
= compiler_alloc_bstr(ctx
, stat
->catch_block
->identifier
);
1695 return E_OUTOFMEMORY
;
1700 instr_ptr(ctx
, push_except
)->u
.arg
[1].bstr
= ident
;
1702 if(!stat
->catch_block
)
1703 try_ctx
.stack_use
= 2;
1705 hres
= compile_statement(ctx
, &try_ctx
, stat
->try_statement
);
1709 if(!push_instr(ctx
, OP_pop_except
))
1710 return E_OUTOFMEMORY
;
1712 if(stat
->catch_block
) {
1713 unsigned jmp_finally
;
1715 jmp_finally
= push_instr(ctx
, OP_jmp
);
1717 return E_OUTOFMEMORY
;
1719 instr_ptr(ctx
, push_except
)->u
.arg
[0].uint
= ctx
->code_off
;
1721 hres
= compile_statement(ctx
, &catch_ctx
, stat
->catch_block
->statement
);
1725 if(!push_instr(ctx
, OP_pop_scope
))
1726 return E_OUTOFMEMORY
;
1728 set_arg_uint(ctx
, jmp_finally
, ctx
->code_off
);
1730 set_arg_uint(ctx
, push_except
, ctx
->code_off
);
1733 if(stat
->finally_statement
) {
1734 hres
= compile_statement(ctx
, stat
->catch_block
? NULL
: &finally_ctx
, stat
->finally_statement
);
1738 if(!stat
->catch_block
&& !push_instr(ctx
, OP_end_finally
))
1739 return E_OUTOFMEMORY
;
1745 static HRESULT
compile_statement(compiler_ctx_t
*ctx
, statement_ctx_t
*stat_ctx
, statement_t
*stat
)
1750 stat_ctx
->next
= ctx
->stat_ctx
;
1751 ctx
->stat_ctx
= stat_ctx
;
1754 switch(stat
->type
) {
1756 hres
= compile_block_statement(ctx
, ((block_statement_t
*)stat
)->stat_list
);
1759 hres
= compile_break_statement(ctx
, (branch_statement_t
*)stat
);
1762 hres
= compile_continue_statement(ctx
, (branch_statement_t
*)stat
);
1769 hres
= compile_expression_statement(ctx
, (expression_statement_t
*)stat
);
1772 hres
= compile_for_statement(ctx
, (for_statement_t
*)stat
);
1775 hres
= compile_forin_statement(ctx
, (forin_statement_t
*)stat
);
1778 hres
= compile_if_statement(ctx
, (if_statement_t
*)stat
);
1781 hres
= compile_labelled_statement(ctx
, (labelled_statement_t
*)stat
);
1784 hres
= compile_return_statement(ctx
, (expression_statement_t
*)stat
);
1787 hres
= compile_switch_statement(ctx
, (switch_statement_t
*)stat
);
1790 hres
= compile_throw_statement(ctx
, (expression_statement_t
*)stat
);
1793 hres
= compile_try_statement(ctx
, (try_statement_t
*)stat
);
1796 hres
= compile_var_statement(ctx
, (var_statement_t
*)stat
);
1799 hres
= compile_while_statement(ctx
, (while_statement_t
*)stat
);
1802 hres
= compile_with_statement(ctx
, (with_statement_t
*)stat
);
1804 DEFAULT_UNREACHABLE
;
1808 assert(ctx
->stat_ctx
== stat_ctx
);
1809 ctx
->stat_ctx
= stat_ctx
->next
;
1815 static int local_cmp(const void *key
, const void *ref
)
1817 return strcmpW((const WCHAR
*)key
, ((const local_ref_t
*)ref
)->name
);
1820 static inline local_ref_t
*find_local(compiler_ctx_t
*ctx
, const WCHAR
*name
)
1822 return bsearch(name
, ctx
->locals_buf
, ctx
->locals_cnt
, sizeof(*ctx
->locals_buf
), local_cmp
);
1825 static BOOL
alloc_local(compiler_ctx_t
*ctx
, BSTR name
, int ref
)
1829 if(!ctx
->locals_buf_size
) {
1830 ctx
->locals_buf
= heap_alloc(4 * sizeof(*ctx
->locals_buf
));
1831 if(!ctx
->locals_buf
)
1833 ctx
->locals_buf_size
= 4;
1834 }else if(ctx
->locals_buf_size
== ctx
->locals_cnt
) {
1835 local_ref_t
*new_buf
= heap_realloc(ctx
->locals_buf
, ctx
->locals_buf_size
* 2 * sizeof(*ctx
->locals_buf
));
1838 ctx
->locals_buf
= new_buf
;
1839 ctx
->locals_buf_size
*= 2;
1842 for(i
= 0; i
< ctx
->locals_cnt
; i
++) {
1843 if(strcmpW(ctx
->locals_buf
[i
].name
, name
) > 0) {
1844 memmove(ctx
->locals_buf
+ i
+1, ctx
->locals_buf
+ i
, (ctx
->locals_cnt
- i
) * sizeof(*ctx
->locals_buf
));
1849 ctx
->locals_buf
[i
].name
= name
;
1850 ctx
->locals_buf
[i
].ref
= ref
;
1855 static BOOL
alloc_variable(compiler_ctx_t
*ctx
, const WCHAR
*name
)
1859 if(find_local(ctx
, name
))
1862 ident
= compiler_alloc_bstr(ctx
, name
);
1866 return alloc_local(ctx
, ident
, ctx
->func
->var_cnt
++);
1869 static BOOL
visit_function_expression(compiler_ctx_t
*ctx
, function_expression_t
*expr
)
1871 expr
->func_id
= ctx
->func
->func_cnt
++;
1872 ctx
->func_tail
= ctx
->func_tail
? (ctx
->func_tail
->next
= expr
) : (ctx
->func_head
= expr
);
1874 return !expr
->identifier
|| expr
->event_target
|| alloc_variable(ctx
, expr
->identifier
);
1877 static HRESULT
visit_expression(compiler_ctx_t
*ctx
, expression_t
*expr
)
1879 HRESULT hres
= S_OK
;
1881 switch(expr
->type
) {
1886 case EXPR_ASSIGNADD
:
1887 case EXPR_ASSIGNAND
:
1888 case EXPR_ASSIGNSUB
:
1889 case EXPR_ASSIGNMUL
:
1890 case EXPR_ASSIGNDIV
:
1891 case EXPR_ASSIGNMOD
:
1893 case EXPR_ASSIGNLSHIFT
:
1894 case EXPR_ASSIGNRSHIFT
:
1895 case EXPR_ASSIGNRRSHIFT
:
1896 case EXPR_ASSIGNXOR
:
1904 case EXPR_GREATEREQ
:
1906 case EXPR_INSTANCEOF
:
1919 binary_expression_t
*binary_expr
= (binary_expression_t
*)expr
;
1921 hres
= visit_expression(ctx
, binary_expr
->expression1
);
1925 hres
= visit_expression(ctx
, binary_expr
->expression2
);
1939 hres
= visit_expression(ctx
, ((unary_expression_t
*)expr
)->expression
);
1945 case EXPR_ARRAYLIT
: {
1946 array_literal_expression_t
*array_expr
= (array_literal_expression_t
*)expr
;
1947 array_element_t
*iter
;
1949 for(iter
= array_expr
->element_list
; iter
; iter
= iter
->next
) {
1950 hres
= visit_expression(ctx
, iter
->expr
);
1958 call_expression_t
*call_expr
= (call_expression_t
*)expr
;
1961 hres
= visit_expression(ctx
, call_expr
->expression
);
1965 for(arg
= call_expr
->argument_list
; arg
; arg
= arg
->next
) {
1966 hres
= visit_expression(ctx
, arg
->expr
);
1973 conditional_expression_t
*cond_expr
= (conditional_expression_t
*)expr
;
1975 hres
= visit_expression(ctx
, cond_expr
->expression
);
1979 hres
= visit_expression(ctx
, cond_expr
->true_expression
);
1983 hres
= visit_expression(ctx
, cond_expr
->false_expression
);
1987 visit_function_expression(ctx
, (function_expression_t
*)expr
);
1990 hres
= visit_expression(ctx
, ((member_expression_t
*)expr
)->expression
);
1992 case EXPR_PROPVAL
: {
1994 for(iter
= ((property_value_expression_t
*)expr
)->property_list
; iter
; iter
= iter
->next
) {
1995 hres
= visit_expression(ctx
, iter
->value
);
2001 DEFAULT_UNREACHABLE
;
2007 static HRESULT
visit_variable_list(compiler_ctx_t
*ctx
, variable_declaration_t
*list
)
2009 variable_declaration_t
*iter
;
2012 for(iter
= list
; iter
; iter
= iter
->next
) {
2013 if(!alloc_variable(ctx
, iter
->identifier
))
2014 return E_OUTOFMEMORY
;
2017 hres
= visit_expression(ctx
, iter
->expr
);
2026 static HRESULT
visit_statement(compiler_ctx_t
*,statement_t
*);
2028 static HRESULT
visit_block_statement(compiler_ctx_t
*ctx
, statement_t
*iter
)
2033 hres
= visit_statement(ctx
, iter
);
2043 static HRESULT
visit_statement(compiler_ctx_t
*ctx
, statement_t
*stat
)
2045 HRESULT hres
= S_OK
;
2047 switch(stat
->type
) {
2049 hres
= visit_block_statement(ctx
, ((block_statement_t
*)stat
)->stat_list
);
2058 expression_statement_t
*expr_stat
= (expression_statement_t
*)stat
;
2060 hres
= visit_expression(ctx
, expr_stat
->expr
);
2064 for_statement_t
*for_stat
= (for_statement_t
*)stat
;
2066 if(for_stat
->variable_list
)
2067 hres
= visit_variable_list(ctx
, for_stat
->variable_list
);
2068 else if(for_stat
->begin_expr
)
2069 hres
= visit_expression(ctx
, for_stat
->begin_expr
);
2073 if(for_stat
->expr
) {
2074 hres
= visit_expression(ctx
, for_stat
->expr
);
2079 hres
= visit_statement(ctx
, for_stat
->statement
);
2083 if(for_stat
->end_expr
)
2084 hres
= visit_expression(ctx
, for_stat
->end_expr
);
2088 forin_statement_t
*forin_stat
= (forin_statement_t
*)stat
;
2090 if(forin_stat
->variable
) {
2091 hres
= visit_variable_list(ctx
, forin_stat
->variable
);
2096 hres
= visit_expression(ctx
, forin_stat
->in_expr
);
2100 if(forin_stat
->expr
) {
2101 hres
= visit_expression(ctx
, forin_stat
->expr
);
2106 hres
= visit_statement(ctx
, forin_stat
->statement
);
2110 if_statement_t
*if_stat
= (if_statement_t
*)stat
;
2112 hres
= visit_expression(ctx
, if_stat
->expr
);
2116 hres
= visit_statement(ctx
, if_stat
->if_stat
);
2120 if(if_stat
->else_stat
)
2121 hres
= visit_statement(ctx
, if_stat
->else_stat
);
2125 hres
= visit_statement(ctx
, ((labelled_statement_t
*)stat
)->statement
);
2128 switch_statement_t
*switch_stat
= (switch_statement_t
*)stat
;
2129 statement_t
*stat_iter
;
2130 case_clausule_t
*iter
;
2132 hres
= visit_expression(ctx
, switch_stat
->expr
);
2136 for(iter
= switch_stat
->case_list
; iter
; iter
= iter
->next
) {
2139 hres
= visit_expression(ctx
, iter
->expr
);
2144 for(iter
= switch_stat
->case_list
; iter
; iter
= iter
->next
) {
2145 while(iter
->next
&& iter
->next
->stat
== iter
->stat
)
2147 for(stat_iter
= iter
->stat
; stat_iter
&& (!iter
->next
|| iter
->next
->stat
!= stat_iter
);
2148 stat_iter
= stat_iter
->next
) {
2149 hres
= visit_statement(ctx
, stat_iter
);
2157 try_statement_t
*try_stat
= (try_statement_t
*)stat
;
2159 hres
= visit_statement(ctx
, try_stat
->try_statement
);
2163 if(try_stat
->catch_block
) {
2164 hres
= visit_statement(ctx
, try_stat
->catch_block
->statement
);
2169 if(try_stat
->finally_statement
)
2170 hres
= visit_statement(ctx
, try_stat
->finally_statement
);
2174 hres
= visit_variable_list(ctx
, ((var_statement_t
*)stat
)->variable_list
);
2177 while_statement_t
*while_stat
= (while_statement_t
*)stat
;
2179 hres
= visit_expression(ctx
, while_stat
->expr
);
2183 hres
= visit_statement(ctx
, while_stat
->statement
);
2187 with_statement_t
*with_stat
= (with_statement_t
*)stat
;
2189 hres
= visit_expression(ctx
, with_stat
->expr
);
2193 hres
= visit_statement(ctx
, with_stat
->statement
);
2196 DEFAULT_UNREACHABLE
;
2202 static void resolve_labels(compiler_ctx_t
*ctx
, unsigned off
)
2206 for(instr
= ctx
->code
->instrs
+off
; instr
< ctx
->code
->instrs
+ctx
->code_off
; instr
++) {
2207 if(instr_info
[instr
->op
].arg1_type
== ARG_ADDR
&& (instr
->u
.arg
->uint
& LABEL_FLAG
)) {
2208 assert((instr
->u
.arg
->uint
& ~LABEL_FLAG
) < ctx
->labels_cnt
);
2209 instr
->u
.arg
->uint
= ctx
->labels
[instr
->u
.arg
->uint
& ~LABEL_FLAG
];
2211 assert(instr_info
[instr
->op
].arg2_type
!= ARG_ADDR
);
2214 ctx
->labels_cnt
= 0;
2217 void release_bytecode(bytecode_t
*code
)
2224 for(i
=0; i
< code
->bstr_cnt
; i
++)
2225 SysFreeString(code
->bstr_pool
[i
]);
2226 for(i
=0; i
< code
->str_cnt
; i
++)
2227 jsstr_release(code
->str_pool
[i
]);
2229 heap_free(code
->source
);
2230 heap_pool_free(&code
->heap
);
2231 heap_free(code
->bstr_pool
);
2232 heap_free(code
->str_pool
);
2233 heap_free(code
->instrs
);
2237 static HRESULT
init_code(compiler_ctx_t
*compiler
, const WCHAR
*source
)
2239 compiler
->code
= heap_alloc_zero(sizeof(bytecode_t
));
2241 return E_OUTOFMEMORY
;
2243 compiler
->code
->ref
= 1;
2244 heap_pool_init(&compiler
->code
->heap
);
2246 compiler
->code
->source
= heap_strdupW(source
);
2247 if(!compiler
->code
->source
) {
2248 release_bytecode(compiler
->code
);
2249 return E_OUTOFMEMORY
;
2252 compiler
->code
->instrs
= heap_alloc(64 * sizeof(instr_t
));
2253 if(!compiler
->code
->instrs
) {
2254 release_bytecode(compiler
->code
);
2255 return E_OUTOFMEMORY
;
2258 compiler
->code_size
= 64;
2259 compiler
->code_off
= 1;
2263 static HRESULT
compile_function(compiler_ctx_t
*ctx
, source_elements_t
*source
, function_expression_t
*func_expr
,
2264 BOOL from_eval
, function_code_t
*func
)
2266 function_expression_t
*iter
;
2272 ctx
->func_head
= ctx
->func_tail
= NULL
;
2273 ctx
->from_eval
= from_eval
;
2275 ctx
->locals_cnt
= 0;
2278 parameter_t
*param_iter
;
2280 if(func_expr
->identifier
) {
2281 func
->name
= compiler_alloc_bstr(ctx
, func_expr
->identifier
);
2283 return E_OUTOFMEMORY
;
2286 if(func_expr
->event_target
) {
2287 func
->event_target
= compiler_alloc_bstr(ctx
, func_expr
->event_target
);
2288 if(!func
->event_target
)
2289 return E_OUTOFMEMORY
;
2292 func
->source
= func_expr
->src_str
;
2293 func
->source_len
= func_expr
->src_len
;
2295 for(param_iter
= func_expr
->parameter_list
; param_iter
; param_iter
= param_iter
->next
)
2298 func
->params
= compiler_alloc(ctx
->code
, func
->param_cnt
* sizeof(*func
->params
));
2300 return E_OUTOFMEMORY
;
2302 for(param_iter
= func_expr
->parameter_list
, i
=0; param_iter
; param_iter
= param_iter
->next
, i
++) {
2303 func
->params
[i
] = compiler_alloc_bstr(ctx
, param_iter
->identifier
);
2304 if(!func
->params
[i
])
2305 return E_OUTOFMEMORY
;
2309 for(i
= 0; i
< func
->param_cnt
; i
++) {
2310 if(!find_local(ctx
, func
->params
[i
]) && !alloc_local(ctx
, func
->params
[i
], -i
-1))
2311 return E_OUTOFMEMORY
;
2314 hres
= visit_block_statement(ctx
, source
->statement
);
2318 func
->locals
= compiler_alloc(ctx
->code
, ctx
->locals_cnt
* sizeof(*func
->locals
));
2320 return E_OUTOFMEMORY
;
2321 func
->locals_cnt
= ctx
->locals_cnt
;
2322 memcpy(func
->locals
, ctx
->locals_buf
, func
->locals_cnt
* sizeof(*func
->locals
));
2324 func
->variables
= compiler_alloc(ctx
->code
, func
->var_cnt
* sizeof(*func
->variables
));
2325 if(!func
->variables
)
2326 return E_OUTOFMEMORY
;
2328 for(i
= 0, j
= 0; i
< func
->locals_cnt
; i
++) {
2329 if(func
->locals
[i
].ref
< 0)
2330 continue; /* skip arguments */
2331 func
->variables
[func
->locals
[i
].ref
].name
= func
->locals
[i
].name
;
2332 func
->variables
[func
->locals
[i
].ref
].func_id
= -1;
2336 assert(j
== func
->var_cnt
);
2338 func
->funcs
= compiler_alloc(ctx
->code
, func
->func_cnt
* sizeof(*func
->funcs
));
2340 return E_OUTOFMEMORY
;
2341 memset(func
->funcs
, 0, func
->func_cnt
* sizeof(*func
->funcs
));
2343 off
= ctx
->code_off
;
2344 hres
= compile_block_statement(ctx
, source
->statement
);
2348 resolve_labels(ctx
, off
);
2350 hres
= push_instr_uint(ctx
, OP_ret
, !from_eval
);
2354 if(TRACE_ON(jscript_disas
))
2355 dump_code(ctx
, off
);
2357 func
->instr_off
= off
;
2359 for(iter
= ctx
->func_head
, i
=0; iter
; iter
= iter
->next
, i
++) {
2360 hres
= compile_function(ctx
, iter
->source_elements
, iter
, FALSE
, func
->funcs
+i
);
2364 TRACE("[%d] func %s\n", i
, debugstr_w(func
->funcs
[i
].name
));
2365 if(func
->funcs
[i
].name
&& !func
->funcs
[i
].event_target
) {
2366 local_ref_t
*local_ref
= lookup_local(func
, func
->funcs
[i
].name
);
2367 func
->funcs
[i
].local_ref
= local_ref
->ref
;
2368 TRACE("found ref %s %d for %s\n", debugstr_w(local_ref
->name
), local_ref
->ref
, debugstr_w(func
->funcs
[i
].name
));
2369 if(local_ref
->ref
>= 0)
2370 func
->variables
[local_ref
->ref
].func_id
= i
;
2374 assert(i
== func
->func_cnt
);
2379 static HRESULT
parse_arguments(compiler_ctx_t
*ctx
, const WCHAR
*args
, BSTR
*arg_array
, unsigned *args_size
)
2381 const WCHAR
*ptr
= args
, *ptr2
;
2382 unsigned arg_cnt
= 0;
2384 while(isspaceW(*ptr
))
2393 if(!isalphaW(*ptr
) && *ptr
!= '_') {
2394 FIXME("expected alpha or '_': %s\n", debugstr_w(ptr
));
2399 while(isalnumW(*ptr
) || *ptr
== '_')
2402 if(*ptr
&& *ptr
!= ',' && !isspaceW(*ptr
)) {
2403 FIXME("unexpected har %s\n", debugstr_w(ptr
));
2408 arg_array
[arg_cnt
] = compiler_alloc_bstr_len(ctx
, ptr2
, ptr
-ptr2
);
2409 if(!arg_array
[arg_cnt
])
2410 return E_OUTOFMEMORY
;
2414 while(isspaceW(*ptr
))
2419 FIXME("expected ',': %s\n", debugstr_w(ptr
));
2424 while(isspaceW(*ptr
))
2429 *args_size
= arg_cnt
;
2433 static HRESULT
compile_arguments(compiler_ctx_t
*ctx
, const WCHAR
*args
)
2437 hres
= parse_arguments(ctx
, args
, NULL
, &ctx
->code
->global_code
.param_cnt
);
2441 ctx
->code
->global_code
.params
= compiler_alloc(ctx
->code
,
2442 ctx
->code
->global_code
.param_cnt
* sizeof(*ctx
->code
->global_code
.params
));
2443 if(!ctx
->code
->global_code
.params
)
2444 return E_OUTOFMEMORY
;
2446 return parse_arguments(ctx
, args
, ctx
->code
->global_code
.params
, NULL
);
2449 HRESULT
compile_script(script_ctx_t
*ctx
, const WCHAR
*code
, const WCHAR
*args
, const WCHAR
*delimiter
,
2450 BOOL from_eval
, BOOL use_decode
, bytecode_t
**ret
)
2452 compiler_ctx_t compiler
= {0};
2455 hres
= init_code(&compiler
, code
);
2460 hres
= compile_arguments(&compiler
, args
);
2466 hres
= decode_source(compiler
.code
->source
);
2468 WARN("Decoding failed\n");
2473 hres
= script_parse(ctx
, compiler
.code
->source
, delimiter
, from_eval
, &compiler
.parser
);
2475 release_bytecode(compiler
.code
);
2479 hres
= compile_function(&compiler
, compiler
.parser
->source
, NULL
, from_eval
, &compiler
.code
->global_code
);
2480 parser_release(compiler
.parser
);
2481 heap_free(compiler
.locals_buf
);
2483 release_bytecode(compiler
.code
);
2487 *ret
= compiler
.code
;