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
);
29 struct _compiler_ctx_t
{
37 static HRESULT
compile_expression(compiler_ctx_t
*,expression_t
*);
39 static inline void *compiler_alloc(bytecode_t
*code
, size_t size
)
41 return jsheap_alloc(&code
->heap
, size
);
44 static WCHAR
*compiler_alloc_string(bytecode_t
*code
, const WCHAR
*str
)
49 size
= (strlenW(str
)+1)*sizeof(WCHAR
);
50 ret
= compiler_alloc(code
, size
);
52 memcpy(ret
, str
, size
);
56 static BSTR
compiler_alloc_bstr(compiler_ctx_t
*ctx
, const WCHAR
*str
)
58 if(!ctx
->code
->bstr_pool_size
) {
59 ctx
->code
->bstr_pool
= heap_alloc(8 * sizeof(BSTR
));
60 if(!ctx
->code
->bstr_pool
)
62 ctx
->code
->bstr_pool_size
= 8;
63 }else if(ctx
->code
->bstr_pool_size
== ctx
->code
->bstr_cnt
) {
66 new_pool
= heap_realloc(ctx
->code
->bstr_pool
, ctx
->code
->bstr_pool_size
*2*sizeof(BSTR
));
70 ctx
->code
->bstr_pool
= new_pool
;
71 ctx
->code
->bstr_pool_size
*= 2;
74 ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
] = SysAllocString(str
);
75 if(!ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
])
78 return ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
++];
81 static unsigned push_instr(compiler_ctx_t
*ctx
, jsop_t op
)
83 assert(ctx
->code_size
>= ctx
->code_off
);
86 ctx
->code
->instrs
= heap_alloc(64 * sizeof(instr_t
));
87 if(!ctx
->code
->instrs
)
90 }else if(ctx
->code_size
== ctx
->code_off
) {
93 new_instrs
= heap_realloc(ctx
->code
->instrs
, ctx
->code_size
*2*sizeof(instr_t
));
97 ctx
->code
->instrs
= new_instrs
;
101 ctx
->code
->instrs
[ctx
->code_off
].op
= op
;
102 return ctx
->code_off
++;
105 static inline instr_t
*instr_ptr(compiler_ctx_t
*ctx
, unsigned off
)
107 assert(off
< ctx
->code_off
);
108 return ctx
->code
->instrs
+ off
;
111 static HRESULT
push_instr_int(compiler_ctx_t
*ctx
, jsop_t op
, LONG arg
)
115 instr
= push_instr(ctx
, op
);
117 return E_OUTOFMEMORY
;
119 instr_ptr(ctx
, instr
)->arg1
.lng
= arg
;
123 static HRESULT
push_instr_str(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg
)
128 str
= compiler_alloc_string(ctx
->code
, arg
);
130 return E_OUTOFMEMORY
;
132 instr
= push_instr(ctx
, op
);
134 return E_OUTOFMEMORY
;
136 instr_ptr(ctx
, instr
)->arg1
.str
= str
;
140 static HRESULT
push_instr_bstr(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg
)
145 str
= compiler_alloc_bstr(ctx
, arg
);
147 return E_OUTOFMEMORY
;
149 instr
= push_instr(ctx
, op
);
151 return E_OUTOFMEMORY
;
153 instr_ptr(ctx
, instr
)->arg1
.bstr
= str
;
157 static HRESULT
push_instr_double(compiler_ctx_t
*ctx
, jsop_t op
, double arg
)
162 dbl
= compiler_alloc(ctx
->code
, sizeof(arg
));
164 return E_OUTOFMEMORY
;
167 instr
= push_instr(ctx
, op
);
169 return E_OUTOFMEMORY
;
171 instr_ptr(ctx
, instr
)->arg1
.dbl
= dbl
;
175 static HRESULT
push_instr_uint(compiler_ctx_t
*ctx
, jsop_t op
, unsigned arg
)
179 instr
= push_instr(ctx
, op
);
181 return E_OUTOFMEMORY
;
183 instr_ptr(ctx
, instr
)->arg1
.uint
= arg
;
187 static HRESULT
compile_binary_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
191 hres
= compile_expression(ctx
, expr
->expression1
);
195 hres
= compile_expression(ctx
, expr
->expression2
);
199 return push_instr(ctx
, op
) == -1 ? E_OUTOFMEMORY
: S_OK
;
202 static HRESULT
compile_unary_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
, jsop_t op
)
206 hres
= compile_expression(ctx
, expr
->expression
);
210 return push_instr(ctx
, op
) == -1 ? E_OUTOFMEMORY
: S_OK
;
213 /* ECMA-262 3rd Edition 11.2.1 */
214 static HRESULT
compile_member_expression(compiler_ctx_t
*ctx
, member_expression_t
*expr
)
218 hres
= compile_expression(ctx
, expr
->expression
);
222 return push_instr_bstr(ctx
, OP_member
, expr
->identifier
);
225 /* ECMA-262 3rd Edition 11.14 */
226 static HRESULT
compile_comma_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
)
230 hres
= compile_expression(ctx
, expr
->expression1
);
234 if(push_instr(ctx
, OP_pop
) == -1)
235 return E_OUTOFMEMORY
;
237 return compile_expression(ctx
, expr
->expression2
);
240 /* ECMA-262 3rd Edition 11.11 */
241 static HRESULT
compile_logical_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
246 hres
= compile_expression(ctx
, expr
->expression1
);
250 instr
= push_instr(ctx
, op
);
252 return E_OUTOFMEMORY
;
254 hres
= compile_expression(ctx
, expr
->expression2
);
258 instr_ptr(ctx
, instr
)->arg1
.uint
= ctx
->code_off
;
262 /* ECMA-262 3rd Edition 11.12 */
263 static HRESULT
compile_conditional_expression(compiler_ctx_t
*ctx
, conditional_expression_t
*expr
)
265 unsigned jmp_false
, jmp_end
;
268 hres
= compile_expression(ctx
, expr
->expression
);
272 jmp_false
= push_instr(ctx
, OP_jmp_z
);
274 return E_OUTOFMEMORY
;
276 hres
= compile_expression(ctx
, expr
->true_expression
);
280 jmp_end
= push_instr(ctx
, OP_jmp
);
282 return E_OUTOFMEMORY
;
284 instr_ptr(ctx
, jmp_false
)->arg1
.uint
= ctx
->code_off
;
285 if(push_instr(ctx
, OP_pop
) == -1)
286 return E_OUTOFMEMORY
;
288 hres
= compile_expression(ctx
, expr
->false_expression
);
292 instr_ptr(ctx
, jmp_end
)->arg1
.uint
= ctx
->code_off
;
296 static HRESULT
compile_new_expression(compiler_ctx_t
*ctx
, call_expression_t
*expr
)
298 unsigned arg_cnt
= 0;
302 hres
= compile_expression(ctx
, expr
->expression
);
306 for(arg
= expr
->argument_list
; arg
; arg
= arg
->next
) {
307 hres
= compile_expression(ctx
, arg
->expr
);
313 return push_instr_int(ctx
, OP_new
, arg_cnt
);
316 static HRESULT
compile_interp_fallback(compiler_ctx_t
*ctx
, expression_t
*expr
)
320 instr
= push_instr(ctx
, OP_tree
);
322 return E_OUTOFMEMORY
;
324 instr_ptr(ctx
, instr
)->arg1
.expr
= expr
;
328 static HRESULT
compile_delete_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
)
332 switch(expr
->expression
->type
) {
334 array_expression_t
*array_expr
= (array_expression_t
*)expr
->expression
;
336 hres
= compile_expression(ctx
, array_expr
->member_expr
);
340 hres
= compile_expression(ctx
, array_expr
->expression
);
344 if(push_instr(ctx
, OP_delete
) == -1)
345 return E_OUTOFMEMORY
;
349 member_expression_t
*member_expr
= (member_expression_t
*)expr
->expression
;
351 hres
= compile_expression(ctx
, member_expr
->expression
);
355 /* FIXME: Potential optimization */
356 hres
= push_instr_str(ctx
, OP_str
, member_expr
->identifier
);
360 if(push_instr(ctx
, OP_delete
) == -1)
361 return E_OUTOFMEMORY
;
365 expr
->expr
.eval
= delete_expression_eval
;
366 return compile_interp_fallback(ctx
, &expr
->expr
);
372 static HRESULT
compile_assign_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
376 switch(expr
->expression1
->type
) {
378 identifier_expression_t
*ident_expr
= (identifier_expression_t
*)expr
->expression1
;
380 hres
= push_instr_bstr(ctx
, OP_identid
, ident_expr
->identifier
);
386 array_expression_t
*array_expr
= (array_expression_t
*)expr
->expression1
;
388 hres
= compile_expression(ctx
, array_expr
->member_expr
);
392 hres
= compile_expression(ctx
, array_expr
->expression
);
396 if(push_instr(ctx
, OP_memberid
) == -1)
397 return E_OUTOFMEMORY
;
401 member_expression_t
*member_expr
= (member_expression_t
*)expr
->expression1
;
403 hres
= compile_expression(ctx
, member_expr
->expression
);
407 /* FIXME: Potential optimization */
408 hres
= push_instr_str(ctx
, OP_str
, member_expr
->identifier
);
412 if(push_instr(ctx
, OP_memberid
) == -1)
413 return E_OUTOFMEMORY
;
417 hres
= compile_expression(ctx
, expr
->expression1
);
421 hres
= compile_expression(ctx
, expr
->expression2
);
425 if(op
!= OP_LAST
&& push_instr(ctx
, op
) == -1)
426 return E_OUTOFMEMORY
;
428 return push_instr_uint(ctx
, OP_throw
, JS_E_ILLEGAL_ASSIGN
);
431 if(op
!= OP_LAST
&& push_instr(ctx
, OP_refval
) == -1)
432 return E_OUTOFMEMORY
;
434 hres
= compile_expression(ctx
, expr
->expression2
);
438 if(op
!= OP_LAST
&& push_instr(ctx
, op
) == -1)
439 return E_OUTOFMEMORY
;
441 if(push_instr(ctx
, OP_assign
) == -1)
442 return E_OUTOFMEMORY
;
447 static HRESULT
compile_literal(compiler_ctx_t
*ctx
, literal_t
*literal
)
449 switch(literal
->type
) {
451 return push_instr_int(ctx
, OP_bool
, literal
->u
.bval
);
453 return push_instr_double(ctx
, OP_double
, literal
->u
.dval
);
455 return push_instr_int(ctx
, OP_int
, literal
->u
.lval
);
457 return push_instr(ctx
, OP_null
);
459 return push_instr_str(ctx
, OP_str
, literal
->u
.wstr
);
464 str
= compiler_alloc(ctx
->code
, (literal
->u
.regexp
.str_len
+1)*sizeof(WCHAR
));
466 return E_OUTOFMEMORY
;
467 memcpy(str
, literal
->u
.regexp
.str
, literal
->u
.regexp
.str_len
*sizeof(WCHAR
));
468 str
[literal
->u
.regexp
.str_len
] = 0;
470 instr
= push_instr(ctx
, OP_regexp
);
472 return E_OUTOFMEMORY
;
474 instr_ptr(ctx
, instr
)->arg1
.str
= str
;
475 instr_ptr(ctx
, instr
)->arg2
.lng
= literal
->u
.regexp
.flags
;
483 static HRESULT
compile_expression(compiler_ctx_t
*ctx
, expression_t
*expr
)
487 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
489 return compile_logical_expression(ctx
, (binary_expression_t
*)expr
, OP_jmp_z
);
491 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_LAST
);
493 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
495 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
497 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
499 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
501 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
503 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
505 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_bneg
);
507 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
509 return compile_comma_expression(ctx
, (binary_expression_t
*)expr
);
511 return compile_conditional_expression(ctx
, (conditional_expression_t
*)expr
);
513 return compile_delete_expression(ctx
, (unary_expression_t
*)expr
);
515 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
517 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq
);
519 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq2
);
521 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gt
);
523 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gteq
);
525 return push_instr_bstr(ctx
, OP_ident
, ((identifier_expression_t
*)expr
)->identifier
);
527 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_in
);
529 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lt
);
531 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lteq
);
533 return compile_literal(ctx
, ((literal_expression_t
*)expr
)->literal
);
535 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_neg
);
537 return compile_member_expression(ctx
, (member_expression_t
*)expr
);
539 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_minus
);
541 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
543 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
545 return compile_new_expression(ctx
, (call_expression_t
*)expr
);
547 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq
);
549 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq2
);
551 return compile_logical_expression(ctx
, (binary_expression_t
*)expr
, OP_jmp_nz
);
553 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_tonum
);
555 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
557 return push_instr(ctx
, OP_this
) == -1 ? E_OUTOFMEMORY
: S_OK
;
559 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_void
);
561 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
563 assert(expr
->eval
!= compiled_expression_eval
);
564 return compile_interp_fallback(ctx
, expr
);
570 void release_bytecode(bytecode_t
*code
)
574 for(i
=0; i
< code
->bstr_cnt
; i
++)
575 SysFreeString(code
->bstr_pool
[i
]);
577 jsheap_free(&code
->heap
);
578 heap_free(code
->bstr_pool
);
579 heap_free(code
->instrs
);
583 void release_compiler(compiler_ctx_t
*ctx
)
588 HRESULT
compile_subscript(parser_ctx_t
*parser
, expression_t
*expr
, unsigned *ret_off
)
593 parser
->code
= heap_alloc_zero(sizeof(bytecode_t
));
595 return E_OUTOFMEMORY
;
596 jsheap_init(&parser
->code
->heap
);
599 if(!parser
->compiler
) {
600 parser
->compiler
= heap_alloc_zero(sizeof(compiler_ctx_t
));
601 if(!parser
->compiler
)
602 return E_OUTOFMEMORY
;
604 parser
->compiler
->parser
= parser
;
605 parser
->compiler
->code
= parser
->code
;
608 *ret_off
= parser
->compiler
->code_off
;
609 hres
= compile_expression(parser
->compiler
, expr
);
613 return push_instr(parser
->compiler
, OP_ret
) == -1 ? E_OUTOFMEMORY
: S_OK
;