ReactOS 0.4.16-dev-297-gc569aee
compile.c File Reference
#include <math.h>
#include <assert.h>
#include "jscript.h"
#include "engine.h"
#include "parser.h"
#include "wine/rbtree.h"
#include "wine/debug.h"
Include dependency graph for compile.c:

Go to the source code of this file.

Classes

struct  _statement_ctx_t
 
struct  function_local_t
 
struct  _compiler_ctx_t
 

Macros

#define X(n, a, b, c)   {#n,b,c},
 
#define LABEL_FLAG   0x80000000
 

Typedefs

typedef struct _statement_ctx_t statement_ctx_t
 
typedef struct _compiler_ctx_t compiler_ctx_t
 

Functions

 WINE_DEFAULT_DEBUG_CHANNEL (jscript)
 
 WINE_DECLARE_DEBUG_CHANNEL (jscript_disas)
 
static void dump_instr_arg (instr_arg_type_t type, instr_arg_t *arg)
 
static void dump_code (compiler_ctx_t *ctx, unsigned off)
 
static HRESULT compile_expression (compiler_ctx_t *, expression_t *, BOOL)
 
static HRESULT compile_statement (compiler_ctx_t *, statement_ctx_t *, statement_t *)
 
static voidcompiler_alloc (bytecode_t *code, size_t size)
 
jsstr_tcompiler_alloc_string_len (compiler_ctx_t *ctx, const WCHAR *str, unsigned len)
 
static jsstr_tcompiler_alloc_string (compiler_ctx_t *ctx, const WCHAR *str)
 
static BOOL ensure_bstr_slot (compiler_ctx_t *ctx)
 
static BSTR compiler_alloc_bstr (compiler_ctx_t *ctx, const WCHAR *str)
 
static BSTR compiler_alloc_bstr_len (compiler_ctx_t *ctx, const WCHAR *str, size_t len)
 
static unsigned push_instr (compiler_ctx_t *ctx, jsop_t op)
 
static instr_tinstr_ptr (compiler_ctx_t *ctx, unsigned off)
 
static HRESULT push_instr_int (compiler_ctx_t *ctx, jsop_t op, LONG arg)
 
static HRESULT push_instr_str (compiler_ctx_t *ctx, jsop_t op, jsstr_t *str)
 
static HRESULT push_instr_str_uint (compiler_ctx_t *ctx, jsop_t op, jsstr_t *str, unsigned arg2)
 
static HRESULT push_instr_bstr (compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg)
 
static HRESULT push_instr_bstr_uint (compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg1, unsigned arg2)
 
static HRESULT push_instr_uint_str (compiler_ctx_t *ctx, jsop_t op, unsigned arg1, const WCHAR *arg2)
 
static HRESULT push_instr_double (compiler_ctx_t *ctx, jsop_t op, double arg)
 
static void set_arg_uint (compiler_ctx_t *ctx, unsigned instr, unsigned arg)
 
static HRESULT push_instr_uint (compiler_ctx_t *ctx, jsop_t op, unsigned arg)
 
static HRESULT compile_binary_expression (compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
 
static HRESULT compile_unary_expression (compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op)
 
static HRESULT compile_member_expression (compiler_ctx_t *ctx, member_expression_t *expr)
 
static unsigned alloc_label (compiler_ctx_t *ctx)
 
static void label_set_addr (compiler_ctx_t *ctx, unsigned label)
 
static BOOL is_memberid_expr (expression_type_t type)
 
static BOOL bind_local (compiler_ctx_t *ctx, const WCHAR *identifier, int *ret_ref)
 
static HRESULT emit_identifier_ref (compiler_ctx_t *ctx, const WCHAR *identifier, unsigned flags)
 
static HRESULT emit_identifier (compiler_ctx_t *ctx, const WCHAR *identifier)
 
static HRESULT compile_memberid_expression (compiler_ctx_t *ctx, expression_t *expr, unsigned flags)
 
static HRESULT compile_increment_expression (compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op, int n)
 
static HRESULT compile_comma_expression (compiler_ctx_t *ctx, binary_expression_t *expr, BOOL emit_ret)
 
static HRESULT compile_logical_expression (compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
 
static HRESULT compile_conditional_expression (compiler_ctx_t *ctx, conditional_expression_t *expr)
 
static HRESULT compile_new_expression (compiler_ctx_t *ctx, call_expression_t *expr)
 
static HRESULT compile_call_expression (compiler_ctx_t *ctx, call_expression_t *expr, BOOL emit_ret)
 
static HRESULT compile_delete_expression (compiler_ctx_t *ctx, unary_expression_t *expr)
 
static HRESULT compile_assign_expression (compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
 
static HRESULT compile_typeof_expression (compiler_ctx_t *ctx, unary_expression_t *expr)
 
static HRESULT compile_literal (compiler_ctx_t *ctx, literal_t *literal)
 
static HRESULT literal_as_string (compiler_ctx_t *ctx, literal_t *literal, jsstr_t **str)
 
static HRESULT compile_array_literal (compiler_ctx_t *ctx, array_literal_expression_t *expr)
 
static HRESULT compile_object_literal (compiler_ctx_t *ctx, property_value_expression_t *expr)
 
static HRESULT compile_function_expression (compiler_ctx_t *ctx, function_expression_t *expr, BOOL emit_ret)
 
static BOOL is_loop_statement (statement_type_t type)
 
static HRESULT compile_block_statement (compiler_ctx_t *ctx, statement_t *iter)
 
static HRESULT compile_variable_list (compiler_ctx_t *ctx, variable_declaration_t *list)
 
static HRESULT compile_var_statement (compiler_ctx_t *ctx, var_statement_t *stat)
 
static HRESULT compile_expression_statement (compiler_ctx_t *ctx, expression_statement_t *stat)
 
static HRESULT compile_if_statement (compiler_ctx_t *ctx, if_statement_t *stat)
 
static HRESULT compile_while_statement (compiler_ctx_t *ctx, while_statement_t *stat)
 
static HRESULT compile_for_statement (compiler_ctx_t *ctx, for_statement_t *stat)
 
static HRESULT compile_forin_statement (compiler_ctx_t *ctx, forin_statement_t *stat)
 
static HRESULT pop_to_stat (compiler_ctx_t *ctx, statement_ctx_t *stat_ctx)
 
static HRESULT compile_continue_statement (compiler_ctx_t *ctx, branch_statement_t *stat)
 
static HRESULT compile_break_statement (compiler_ctx_t *ctx, branch_statement_t *stat)
 
static HRESULT compile_return_statement (compiler_ctx_t *ctx, expression_statement_t *stat)
 
static HRESULT compile_with_statement (compiler_ctx_t *ctx, with_statement_t *stat)
 
static HRESULT compile_labelled_statement (compiler_ctx_t *ctx, labelled_statement_t *stat)
 
static HRESULT compile_switch_statement (compiler_ctx_t *ctx, switch_statement_t *stat)
 
static HRESULT compile_throw_statement (compiler_ctx_t *ctx, expression_statement_t *stat)
 
static HRESULT compile_try_statement (compiler_ctx_t *ctx, try_statement_t *stat)
 
static int function_local_cmp (const void *key, const struct wine_rb_entry *entry)
 
static function_local_tfind_local (compiler_ctx_t *ctx, const WCHAR *name)
 
static BOOL alloc_local (compiler_ctx_t *ctx, BSTR name, int ref)
 
static BOOL alloc_variable (compiler_ctx_t *ctx, const WCHAR *name)
 
static HRESULT visit_function_expression (compiler_ctx_t *ctx, function_expression_t *expr)
 
static HRESULT visit_expression (compiler_ctx_t *ctx, expression_t *expr)
 
static HRESULT visit_variable_list (compiler_ctx_t *ctx, variable_declaration_t *list)
 
static HRESULT visit_statement (compiler_ctx_t *, statement_t *)
 
static HRESULT visit_block_statement (compiler_ctx_t *ctx, statement_t *iter)
 
static void resolve_labels (compiler_ctx_t *ctx, unsigned off)
 
void release_bytecode (bytecode_t *code)
 
static HRESULT init_code (compiler_ctx_t *compiler, const WCHAR *source)
 
static HRESULT compile_function (compiler_ctx_t *ctx, source_elements_t *source, function_expression_t *func_expr, BOOL from_eval, function_code_t *func)
 
static HRESULT parse_arguments (compiler_ctx_t *ctx, const WCHAR *args, BSTR *arg_array, unsigned *args_size)
 
static HRESULT compile_arguments (compiler_ctx_t *ctx, const WCHAR *args)
 
HRESULT compile_script (script_ctx_t *ctx, const WCHAR *code, const WCHAR *args, const WCHAR *delimiter, BOOL from_eval, BOOL use_decode, bytecode_t **ret)
 

Variables

struct {
   const char *   op_str
 
   instr_arg_type_t   arg1_type
 
   instr_arg_type_t   arg2_type
 
instr_info []
 

Macro Definition Documentation

◆ LABEL_FLAG

#define LABEL_FLAG   0x80000000

Definition at line 393 of file compile.c.

◆ X

#define X (   n,
  a,
  b,
  c 
)    {#n,b,c},

Typedef Documentation

◆ compiler_ctx_t

◆ statement_ctx_t

Function Documentation

◆ alloc_label()

static unsigned alloc_label ( compiler_ctx_t ctx)
static

Definition at line 395 of file compile.c.

396{
397 if(!ctx->labels_size) {
398 ctx->labels = heap_alloc(8 * sizeof(*ctx->labels));
399 if(!ctx->labels)
400 return 0;
401 ctx->labels_size = 8;
402 }else if(ctx->labels_size == ctx->labels_cnt) {
403 unsigned *new_labels;
404
405 new_labels = heap_realloc(ctx->labels, 2*ctx->labels_size*sizeof(*ctx->labels));
406 if(!new_labels)
407 return 0;
408
409 ctx->labels = new_labels;
410 ctx->labels_size *= 2;
411 }
412
413 return ctx->labels_cnt++ | LABEL_FLAG;
414}
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static void * heap_realloc(void *mem, size_t len)
Definition: appwiz.h:71
#define LABEL_FLAG
Definition: compile.c:393

Referenced by compile_dowhile_statement(), compile_for_statement(), compile_foreach_statement(), compile_forin_statement(), compile_forto_statement(), compile_func(), compile_if_statement(), compile_labelled_statement(), compile_select_statement(), compile_switch_statement(), and compile_while_statement().

◆ alloc_local()

static BOOL alloc_local ( compiler_ctx_t ctx,
BSTR  name,
int  ref 
)
static

Definition at line 1848 of file compile.c.

1849{
1851
1852 local = heap_pool_alloc(&ctx->heap, sizeof(*local));
1853 if(!local)
1854 return FALSE;
1855
1856 local->name = name;
1857 local->ref = ref;
1858 wine_rb_put(&ctx->locals, name, &local->entry);
1859 ctx->locals_cnt++;
1860 return TRUE;
1861}
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define local
Definition: zutil.h:30
void * heap_pool_alloc(heap_pool_t *, DWORD) __WINE_ALLOC_SIZE(2) DECLSPEC_HIDDEN
Definition: jsutils.c:77
static int wine_rb_put(struct wine_rb_tree *tree, const void *key, struct wine_rb_entry *entry)
Definition: rbtree.h:215
char * name
Definition: compiler.c:66
Definition: name.c:39
Definition: send.c:48

Referenced by alloc_variable(), and compile_function().

◆ alloc_variable()

static BOOL alloc_variable ( compiler_ctx_t ctx,
const WCHAR name 
)
static

Definition at line 1863 of file compile.c.

1864{
1865 BSTR ident;
1866
1867 if(find_local(ctx, name))
1868 return TRUE;
1869
1871 if(!ident)
1872 return FALSE;
1873
1874 return alloc_local(ctx, ident, ctx->func->var_cnt++);
1875}
OLECHAR * BSTR
Definition: compat.h:2293
static BSTR compiler_alloc_bstr(compiler_ctx_t *ctx, const WCHAR *str)
Definition: compile.c:187
static BOOL alloc_local(compiler_ctx_t *ctx, BSTR name, int ref)
Definition: compile.c:1848
static function_local_t * find_local(compiler_ctx_t *ctx, const WCHAR *name)
Definition: compile.c:1842
_In_ ULONG _In_ ULONG_PTR ident
Definition: winddi.h:3994

Referenced by visit_function_expression(), and visit_variable_list().

◆ bind_local()

static BOOL bind_local ( compiler_ctx_t ctx,
const WCHAR identifier,
int ret_ref 
)
static

Definition at line 427 of file compile.c.

428{
429 statement_ctx_t *iter;
431
432 for(iter = ctx->stat_ctx; iter; iter = iter->next) {
433 if(iter->using_scope)
434 return FALSE;
435 }
436
437 ref = lookup_local(ctx->func, identifier);
438 if(!ref)
439 return FALSE;
440
441 *ret_ref = ref->ref;
442 return TRUE;
443}
local_ref_t * lookup_local(const function_code_t *function, const WCHAR *identifier)
Definition: engine.c:629
BOOL using_scope
Definition: compile.c:34
struct _statement_ctx_t * next
Definition: compile.c:42

Referenced by emit_identifier(), and emit_identifier_ref().

◆ compile_arguments()

static HRESULT compile_arguments ( compiler_ctx_t ctx,
const WCHAR args 
)
static

Definition at line 2445 of file compile.c.

2446{
2447 HRESULT hres;
2448
2449 hres = parse_arguments(ctx, args, NULL, &ctx->code->global_code.param_cnt);
2450 if(FAILED(hres))
2451 return hres;
2452
2453 ctx->code->global_code.params = compiler_alloc(ctx->code,
2454 ctx->code->global_code.param_cnt * sizeof(*ctx->code->global_code.params));
2455 if(!ctx->code->global_code.params)
2456 return E_OUTOFMEMORY;
2457
2458 return parse_arguments(ctx, args, ctx->code->global_code.params, NULL);
2459}
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define NULL
Definition: types.h:112
#define FAILED(hr)
Definition: intsafe.h:51
static HRESULT parse_arguments(compiler_ctx_t *ctx, const WCHAR *args, BSTR *arg_array, unsigned *args_size)
Definition: compile.c:2391
static void * compiler_alloc(bytecode_t *code, size_t size)
Definition: compile.c:128
HRESULT hres
Definition: protocol.c:465
Definition: match.c:390

Referenced by compile_script().

◆ compile_array_literal()

static HRESULT compile_array_literal ( compiler_ctx_t ctx,
array_literal_expression_t expr 
)
static

Definition at line 865 of file compile.c.

866{
867 unsigned length = 0;
868 array_element_t *iter;
869 unsigned array_instr;
871
872 array_instr = push_instr(ctx, OP_carray);
873
874 for(iter = expr->element_list; iter; iter = iter->next) {
875 length += iter->elision;
876
878 if(FAILED(hres))
879 return hres;
880
881 hres = push_instr_uint(ctx, OP_carray_set, length);
882 if(FAILED(hres))
883 return hres;
884
885 length++;
886 }
887
888 instr_ptr(ctx, array_instr)->u.arg[0].uint = length + expr->length;
889 return S_OK;
890}
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
#define S_OK
Definition: intsafe.h:52
static HRESULT compile_expression(compiler_ctx_t *, expression_t *, BOOL)
Definition: compile.c:923
static unsigned push_instr(compiler_ctx_t *ctx, jsop_t op)
Definition: compile.c:211
static HRESULT push_instr_uint(compiler_ctx_t *ctx, jsop_t op, unsigned arg)
Definition: compile.c:343
static instr_t * instr_ptr(compiler_ctx_t *ctx, unsigned off)
Definition: compile.c:230
expression_t * expr
Definition: parser.h:352
struct _array_element_t * next
Definition: parser.h:354
Definition: query.h:86
instr_arg_t arg[2]
Definition: engine.h:129
union instr_t::@439 u
unsigned uint
Definition: engine.h:112

Referenced by compile_expression().

◆ compile_assign_expression()

static HRESULT compile_assign_expression ( compiler_ctx_t ctx,
binary_expression_t expr,
jsop_t  op 
)
static

Definition at line 729 of file compile.c.

730{
731 BOOL use_throw_path = FALSE;
732 unsigned arg_cnt = 0;
734
735 if(expr->expression1->type == EXPR_CALL) {
736 call_expression_t *call_expr = (call_expression_t*)expr->expression1;
738
739 if(is_memberid_expr(call_expr->expression->type) && call_expr->argument_list) {
740 hres = compile_memberid_expression(ctx, call_expr->expression, fdexNameEnsure);
741 if(FAILED(hres))
742 return hres;
743
744 for(arg = call_expr->argument_list; arg; arg = arg->next) {
746 if(FAILED(hres))
747 return hres;
748 arg_cnt++;
749 }
750
751 if(op != OP_LAST) {
752 unsigned instr;
753
754 /* We need to call the functions twice: to get the value and to set it.
755 * JavaScript interpreted functions may to modify value on the stack,
756 * but assignment calls are allowed only on external functions, so we
757 * may reuse the stack here. */
758 instr = push_instr(ctx, OP_call_member);
759 if(!instr)
760 return E_OUTOFMEMORY;
761 instr_ptr(ctx, instr)->u.arg[0].uint = arg_cnt;
762 instr_ptr(ctx, instr)->u.arg[1].lng = 1;
763
764 if(!push_instr(ctx, OP_push_acc))
765 return E_OUTOFMEMORY;
766 }
767 }else {
768 use_throw_path = TRUE;
769 }
770 }else if(is_memberid_expr(expr->expression1->type)) {
771 hres = compile_memberid_expression(ctx, expr->expression1, fdexNameEnsure);
772 if(FAILED(hres))
773 return hres;
774 if(op != OP_LAST && !push_instr(ctx, OP_refval))
775 return E_OUTOFMEMORY;
776 }else {
777 use_throw_path = TRUE;
778 }
779
780 if(use_throw_path) {
781 /* Illegal assignment: evaluate and throw */
782 hres = compile_expression(ctx, expr->expression1, TRUE);
783 if(FAILED(hres))
784 return hres;
785
786 hres = compile_expression(ctx, expr->expression2, TRUE);
787 if(FAILED(hres))
788 return hres;
789
790 if(op != OP_LAST && !push_instr(ctx, op))
791 return E_OUTOFMEMORY;
792
793 return push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
794 }
795
796 hres = compile_expression(ctx, expr->expression2, TRUE);
797 if(FAILED(hres))
798 return hres;
799
800 if(op != OP_LAST && !push_instr(ctx, op))
801 return E_OUTOFMEMORY;
802
803 if(arg_cnt)
804 return push_instr_uint(ctx, OP_assign_call, arg_cnt);
805
806 if(!push_instr(ctx, OP_assign))
807 return E_OUTOFMEMORY;
808
809 return S_OK;
810}
UINT op
Definition: effect.c:236
@ EXPR_CALL
Definition: parser.h:268
@ OP_LAST
Definition: engine.h:105
unsigned int BOOL
Definition: ntddk_ex.h:94
static BOOL is_memberid_expr(expression_type_t type)
Definition: compile.c:422
static HRESULT compile_memberid_expression(compiler_ctx_t *ctx, expression_t *expr, unsigned flags)
Definition: compile.c:461
#define JS_E_ILLEGAL_ASSIGN
Definition: jscript.h:556
expression_type_t type
Definition: parser.h:278
expression_t * expression
Definition: parser.h:336
argument_t * argument_list
Definition: parser.h:337
int type
Definition: query.h:87
LONG lng
Definition: engine.h:110
static unsigned arg_cnt(const DISPPARAMS *dp)
Definition: vbscript.h:162

Referenced by compile_expression().

◆ compile_binary_expression()

static HRESULT compile_binary_expression ( compiler_ctx_t ctx,
binary_expression_t expr,
jsop_t  op 
)
static

Definition at line 355 of file compile.c.

356{
358
359 hres = compile_expression(ctx, expr->expression1, TRUE);
360 if(FAILED(hres))
361 return hres;
362
363 hres = compile_expression(ctx, expr->expression2, TRUE);
364 if(FAILED(hres))
365 return hres;
366
367 return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
368}

Referenced by compile_expression().

◆ compile_block_statement()

static HRESULT compile_block_statement ( compiler_ctx_t ctx,
statement_t iter 
)
static

Definition at line 1113 of file compile.c.

1114{
1115 HRESULT hres;
1116
1117 while(iter) {
1118 hres = compile_statement(ctx, NULL, iter);
1119 if(FAILED(hres))
1120 return hres;
1121
1122 iter = iter->next;
1123 }
1124
1125 return S_OK;
1126}
static HRESULT compile_statement(compiler_ctx_t *, statement_ctx_t *, statement_t *)
Definition: compile.c:1766
statement_t * next
Definition: parser.h:125

Referenced by compile_function(), and compile_statement().

◆ compile_break_statement()

static HRESULT compile_break_statement ( compiler_ctx_t ctx,
branch_statement_t stat 
)
static

Definition at line 1472 of file compile.c.

1473{
1474 statement_ctx_t *pop_ctx;
1475 HRESULT hres;
1476
1477 if(stat->identifier) {
1478 for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
1479 if(pop_ctx->labelled_stat && !wcscmp(pop_ctx->labelled_stat->identifier, stat->identifier)) {
1480 assert(pop_ctx->break_label);
1481 break;
1482 }
1483 }
1484
1485 if(!pop_ctx) {
1486 WARN("Label not found\n");
1487 return JS_E_LABEL_NOT_FOUND;
1488 }
1489 }else {
1490 for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
1491 if(pop_ctx->break_label && !pop_ctx->labelled_stat)
1492 break;
1493 }
1494
1495 if(!pop_ctx) {
1496 WARN("Break outside loop\n");
1497 return JS_E_INVALID_BREAK;
1498 }
1499 }
1500
1501 hres = pop_to_stat(ctx, pop_ctx->next);
1502 if(FAILED(hres))
1503 return hres;
1504
1505 return push_instr_uint(ctx, OP_jmp, pop_ctx->break_label);
1506}
#define WARN(fmt,...)
Definition: precomp.h:61
#define assert(x)
Definition: debug.h:53
static HRESULT pop_to_stat(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx)
Definition: compile.c:1386
#define JS_E_INVALID_BREAK
Definition: jscript.h:545
#define JS_E_LABEL_NOT_FOUND
Definition: jscript.h:548
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
const labelled_statement_t * labelled_stat
Definition: compile.c:40
unsigned break_label
Definition: compile.c:37
const WCHAR * identifier
Definition: parser.h:187
Definition: stat.h:55

Referenced by compile_statement().

◆ compile_call_expression()

static HRESULT compile_call_expression ( compiler_ctx_t ctx,
call_expression_t expr,
BOOL  emit_ret 
)
static

Definition at line 628 of file compile.c.

629{
630 unsigned arg_cnt = 0, extra_args;
632 unsigned instr;
633 jsop_t op;
635
636 if(is_memberid_expr(expr->expression->type)) {
637 op = OP_call_member;
638 extra_args = 2;
639 hres = compile_memberid_expression(ctx, expr->expression, 0);
640 }else {
641 op = OP_call;
642 extra_args = 1;
643 hres = compile_expression(ctx, expr->expression, TRUE);
644 }
645
646 if(FAILED(hres))
647 return hres;
648
649 for(arg = expr->argument_list; arg; arg = arg->next) {
651 if(FAILED(hres))
652 return hres;
653 arg_cnt++;
654 }
655
656 instr = push_instr(ctx, op);
657 if(!instr)
658 return E_OUTOFMEMORY;
659
660 instr_ptr(ctx, instr)->u.arg[0].uint = arg_cnt;
661 instr_ptr(ctx, instr)->u.arg[1].lng = emit_ret;
662
663 hres = push_instr_uint(ctx, OP_pop, arg_cnt + extra_args);
664 if(FAILED(hres))
665 return hres;
666
667 return !emit_ret || push_instr(ctx, OP_push_acc) ? S_OK : E_OUTOFMEMORY;
668}
jsop_t
Definition: engine.h:101
void * arg
Definition: msvc.h:10

Referenced by compile_expression().

◆ compile_comma_expression()

static HRESULT compile_comma_expression ( compiler_ctx_t ctx,
binary_expression_t expr,
BOOL  emit_ret 
)
static

Definition at line 532 of file compile.c.

533{
535
536 hres = compile_expression(ctx, expr->expression1, FALSE);
537 if(FAILED(hres))
538 return hres;
539
540 return compile_expression(ctx, expr->expression2, emit_ret);
541}

Referenced by compile_expression().

◆ compile_conditional_expression()

static HRESULT compile_conditional_expression ( compiler_ctx_t ctx,
conditional_expression_t expr 
)
static

Definition at line 566 of file compile.c.

567{
568 unsigned jmp_false, jmp_end;
570
571 hres = compile_expression(ctx, expr->expression, TRUE);
572 if(FAILED(hres))
573 return hres;
574
575 jmp_false = push_instr(ctx, OP_cnd_z);
576 if(!jmp_false)
577 return E_OUTOFMEMORY;
578
579 hres = compile_expression(ctx, expr->true_expression, TRUE);
580 if(FAILED(hres))
581 return hres;
582
583 jmp_end = push_instr(ctx, OP_jmp);
584 if(!jmp_end)
585 return E_OUTOFMEMORY;
586
587 set_arg_uint(ctx, jmp_false, ctx->code_off);
588 hres = push_instr_uint(ctx, OP_pop, 1);
589 if(FAILED(hres))
590 return hres;
591
592 hres = compile_expression(ctx, expr->false_expression, TRUE);
593 if(FAILED(hres))
594 return hres;
595
596 set_arg_uint(ctx, jmp_end, ctx->code_off);
597 return S_OK;
598}
static void set_arg_uint(compiler_ctx_t *ctx, unsigned instr, unsigned arg)
Definition: compile.c:338

Referenced by compile_expression().

◆ compile_continue_statement()

static HRESULT compile_continue_statement ( compiler_ctx_t ctx,
branch_statement_t stat 
)
static

Definition at line 1419 of file compile.c.

1420{
1421 statement_ctx_t *pop_ctx;
1422 HRESULT hres;
1423
1424 if(stat->identifier) {
1425 statement_t *label_stat;
1426 statement_ctx_t *iter;
1427
1428 pop_ctx = NULL;
1429
1430 for(iter = ctx->stat_ctx; iter; iter = iter->next) {
1431 if(iter->continue_label)
1432 pop_ctx = iter;
1433 if(iter->labelled_stat && !wcscmp(iter->labelled_stat->identifier, stat->identifier))
1434 break;
1435 }
1436
1437 if(!iter) {
1438 WARN("Label not found\n");
1439 return JS_E_LABEL_NOT_FOUND;
1440 }
1441
1442 /* Labelled continue are allowed only on loops */
1443 for(label_stat = iter->labelled_stat->statement;
1444 label_stat->type == STAT_LABEL;
1445 label_stat = ((labelled_statement_t*)label_stat)->statement);
1446 if(!is_loop_statement(label_stat->type)) {
1447 WARN("Label is not a loop\n");
1448 return JS_E_INVALID_CONTINUE;
1449 }
1450
1451 assert(pop_ctx != NULL);
1452 }else {
1453 for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
1454 if(pop_ctx->continue_label)
1455 break;
1456 }
1457
1458 if(!pop_ctx) {
1459 WARN("continue outside loop\n");
1460 return JS_E_INVALID_CONTINUE;
1461 }
1462 }
1463
1464 hres = pop_to_stat(ctx, pop_ctx);
1465 if(FAILED(hres))
1466 return hres;
1467
1468 return push_instr_uint(ctx, OP_jmp, pop_ctx->continue_label);
1469}
@ STAT_LABEL
Definition: parser.h:113
static BOOL is_loop_statement(statement_type_t type)
Definition: compile.c:1107
#define JS_E_INVALID_CONTINUE
Definition: jscript.h:546
unsigned continue_label
Definition: compile.c:38
statement_type_t type
Definition: parser.h:124
statement_t * statement
Definition: parser.h:188

Referenced by compile_statement().

◆ compile_delete_expression()

static HRESULT compile_delete_expression ( compiler_ctx_t ctx,
unary_expression_t expr 
)
static

Definition at line 670 of file compile.c.

671{
673
674 switch(expr->expression->type) {
675 case EXPR_ARRAY: {
676 binary_expression_t *array_expr = (binary_expression_t*)expr->expression;
677
678 hres = compile_expression(ctx, array_expr->expression1, TRUE);
679 if(FAILED(hres))
680 return hres;
681
682 hres = compile_expression(ctx, array_expr->expression2, TRUE);
683 if(FAILED(hres))
684 return hres;
685
686 if(!push_instr(ctx, OP_delete))
687 return E_OUTOFMEMORY;
688 break;
689 }
690 case EXPR_MEMBER: {
691 member_expression_t *member_expr = (member_expression_t*)expr->expression;
692 jsstr_t *jsstr;
693
694 hres = compile_expression(ctx, member_expr->expression, TRUE);
695 if(FAILED(hres))
696 return hres;
697
698 /* FIXME: Potential optimization */
699 jsstr = compiler_alloc_string(ctx, member_expr->identifier);
700 if(!jsstr)
701 return E_OUTOFMEMORY;
702
703 hres = push_instr_str(ctx, OP_str, jsstr);
704 if(FAILED(hres))
705 return hres;
706
707 if(!push_instr(ctx, OP_delete))
708 return E_OUTOFMEMORY;
709 break;
710 }
711 case EXPR_IDENT:
712 return push_instr_bstr(ctx, OP_delete_ident, ((identifier_expression_t*)expr->expression)->identifier);
713 default: {
714 static const WCHAR fixmeW[] = {'F','I','X','M','E',0};
715
716 WARN("invalid delete, unimplemented exception message\n");
717
718 hres = compile_expression(ctx, expr->expression, TRUE);
719 if(FAILED(hres))
720 return hres;
721
722 return push_instr_uint_str(ctx, OP_throw_type, JS_E_INVALID_DELETE, fixmeW);
723 }
724 }
725
726 return S_OK;
727}
@ EXPR_MEMBER
Definition: parser.h:266
@ EXPR_ARRAY
Definition: parser.h:265
@ EXPR_IDENT
Definition: parser.h:271
static HRESULT push_instr_bstr(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg)
Definition: compile.c:273
static HRESULT push_instr_uint_str(compiler_ctx_t *ctx, jsop_t op, unsigned arg1, const WCHAR *arg2)
Definition: compile.c:308
static jsstr_t * compiler_alloc_string(compiler_ctx_t *ctx, const WCHAR *str)
Definition: compile.c:161
static HRESULT push_instr_str(compiler_ctx_t *ctx, jsop_t op, jsstr_t *str)
Definition: compile.c:248
#define JS_E_INVALID_DELETE
Definition: jscript.h:560
Definition: jsstr.h:39
expression_t * expression1
Definition: parser.h:306
expression_t * expression2
Definition: parser.h:307
const WCHAR * identifier
Definition: parser.h:325
expression_t * expression
Definition: parser.h:324
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by compile_expression().

◆ compile_expression()

static HRESULT compile_expression ( compiler_ctx_t ctx,
expression_t expr,
BOOL  emit_ret 
)
static

Definition at line 923 of file compile.c.

924{
926
927 switch(expr->type) {
928 case EXPR_ADD:
930 break;
931 case EXPR_AND:
933 break;
934 case EXPR_ARRAY:
936 break;
937 case EXPR_ARRAYLIT:
939 break;
940 case EXPR_ASSIGN:
942 break;
943 case EXPR_ASSIGNADD:
945 break;
946 case EXPR_ASSIGNAND:
948 break;
949 case EXPR_ASSIGNSUB:
951 break;
952 case EXPR_ASSIGNMUL:
954 break;
955 case EXPR_ASSIGNDIV:
957 break;
958 case EXPR_ASSIGNMOD:
960 break;
961 case EXPR_ASSIGNOR:
963 break;
966 break;
969 break;
972 break;
973 case EXPR_ASSIGNXOR:
975 break;
976 case EXPR_BAND:
978 break;
979 case EXPR_BITNEG:
981 break;
982 case EXPR_BOR:
984 break;
985 case EXPR_CALL:
987 case EXPR_COMMA:
989 case EXPR_COND:
991 break;
992 case EXPR_DELETE:
994 break;
995 case EXPR_DIV:
997 break;
998 case EXPR_EQ:
1000 break;
1001 case EXPR_EQEQ:
1003 break;
1004 case EXPR_FUNC:
1006 case EXPR_GREATER:
1008 break;
1009 case EXPR_GREATEREQ:
1011 break;
1012 case EXPR_IDENT:
1014 break;
1015 case EXPR_IN:
1017 break;
1018 case EXPR_INSTANCEOF:
1020 break;
1021 case EXPR_LESS:
1023 break;
1024 case EXPR_LESSEQ:
1026 break;
1027 case EXPR_LITERAL:
1029 break;
1030 case EXPR_LOGNEG:
1032 break;
1033 case EXPR_LSHIFT:
1035 break;
1036 case EXPR_MEMBER:
1038 break;
1039 case EXPR_MINUS:
1041 break;
1042 case EXPR_MOD:
1044 break;
1045 case EXPR_MUL:
1047 break;
1048 case EXPR_NEW:
1050 break;
1051 case EXPR_NOTEQ:
1053 break;
1054 case EXPR_NOTEQEQ:
1056 break;
1057 case EXPR_OR:
1059 break;
1060 case EXPR_PLUS:
1062 break;
1063 case EXPR_POSTDEC:
1065 break;
1066 case EXPR_POSTINC:
1068 break;
1069 case EXPR_PREDEC:
1071 break;
1072 case EXPR_PREINC:
1074 break;
1075 case EXPR_PROPVAL:
1077 break;
1078 case EXPR_RSHIFT:
1080 break;
1081 case EXPR_RRSHIFT:
1083 break;
1084 case EXPR_SUB:
1086 break;
1087 case EXPR_THIS:
1088 return !emit_ret || push_instr(ctx, OP_this) ? S_OK : E_OUTOFMEMORY;
1089 case EXPR_TYPEOF:
1091 break;
1092 case EXPR_VOID:
1094 break;
1095 case EXPR_BXOR:
1097 break;
1099 }
1100
1101 if(FAILED(hres))
1102 return hres;
1103
1104 return emit_ret ? S_OK : push_instr_uint(ctx, OP_pop, 1);
1105}
@ EXPR_PREDEC
Definition: parser.h:238
@ EXPR_RSHIFT
Definition: parser.h:250
@ EXPR_LESS
Definition: parser.h:243
@ EXPR_ASSIGNADD
Definition: parser.h:256
@ EXPR_GREATER
Definition: parser.h:245
@ EXPR_THIS
Definition: parser.h:269
@ EXPR_BOR
Definition: parser.h:220
@ EXPR_LITERAL
Definition: parser.h:274
@ EXPR_EQEQ
Definition: parser.h:240
@ EXPR_ASSIGNRRSHIFT
Definition: parser.h:255
@ EXPR_ASSIGNDIV
Definition: parser.h:259
@ EXPR_ASSIGNMUL
Definition: parser.h:258
@ EXPR_BXOR
Definition: parser.h:221
@ EXPR_ASSIGNMOD
Definition: parser.h:260
@ EXPR_MOD
Definition: parser.h:229
@ EXPR_FUNC
Definition: parser.h:270
@ EXPR_BAND
Definition: parser.h:222
@ EXPR_VOID
Definition: parser.h:231
@ EXPR_NEW
Definition: parser.h:267
@ EXPR_POSTDEC
Definition: parser.h:236
@ EXPR_ASSIGNOR
Definition: parser.h:262
@ EXPR_GREATEREQ
Definition: parser.h:246
@ EXPR_ASSIGNLSHIFT
Definition: parser.h:253
@ EXPR_LSHIFT
Definition: parser.h:249
@ EXPR_LOGNEG
Definition: parser.h:248
@ EXPR_PROPVAL
Definition: parser.h:273
@ EXPR_DELETE
Definition: parser.h:230
@ EXPR_ARRAYLIT
Definition: parser.h:272
@ EXPR_DIV
Definition: parser.h:228
@ EXPR_ADD
Definition: parser.h:225
@ EXPR_ASSIGN
Definition: parser.h:252
@ EXPR_TYPEOF
Definition: parser.h:232
@ EXPR_IN
Definition: parser.h:224
@ EXPR_INSTANCEOF
Definition: parser.h:223
@ EXPR_PLUS
Definition: parser.h:234
@ EXPR_MUL
Definition: parser.h:227
@ EXPR_BITNEG
Definition: parser.h:247
@ EXPR_COND
Definition: parser.h:264
@ EXPR_PREINC
Definition: parser.h:237
@ EXPR_OR
Definition: parser.h:218
@ EXPR_NOTEQ
Definition: parser.h:241
@ EXPR_NOTEQEQ
Definition: parser.h:242
@ EXPR_POSTINC
Definition: parser.h:235
@ EXPR_ASSIGNAND
Definition: parser.h:261
@ EXPR_RRSHIFT
Definition: parser.h:251
@ EXPR_ASSIGNSUB
Definition: parser.h:257
@ EXPR_SUB
Definition: parser.h:226
@ EXPR_EQ
Definition: parser.h:239
@ EXPR_ASSIGNRSHIFT
Definition: parser.h:254
@ EXPR_LESSEQ
Definition: parser.h:244
@ EXPR_MINUS
Definition: parser.h:233
@ EXPR_COMMA
Definition: parser.h:217
@ EXPR_ASSIGNXOR
Definition: parser.h:263
@ EXPR_AND
Definition: parser.h:219
static HRESULT compile_comma_expression(compiler_ctx_t *ctx, binary_expression_t *expr, BOOL emit_ret)
Definition: compile.c:532
static HRESULT compile_new_expression(compiler_ctx_t *ctx, call_expression_t *expr)
Definition: compile.c:600
static HRESULT compile_conditional_expression(compiler_ctx_t *ctx, conditional_expression_t *expr)
Definition: compile.c:566
static HRESULT compile_member_expression(compiler_ctx_t *ctx, member_expression_t *expr)
Definition: compile.c:382
static HRESULT compile_logical_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
Definition: compile.c:544
static HRESULT compile_binary_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
Definition: compile.c:355
static HRESULT compile_typeof_expression(compiler_ctx_t *ctx, unary_expression_t *expr)
Definition: compile.c:812
static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal)
Definition: compile.c:833
static HRESULT compile_array_literal(compiler_ctx_t *ctx, array_literal_expression_t *expr)
Definition: compile.c:865
static HRESULT compile_unary_expression(compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op)
Definition: compile.c:370
static HRESULT compile_function_expression(compiler_ctx_t *ctx, function_expression_t *expr, BOOL emit_ret)
Definition: compile.c:918
static HRESULT compile_assign_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
Definition: compile.c:729
static HRESULT emit_identifier(compiler_ctx_t *ctx, const WCHAR *identifier)
Definition: compile.c:453
static HRESULT compile_increment_expression(compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op, int n)
Definition: compile.c:512
static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expression_t *expr)
Definition: compile.c:892
static HRESULT compile_call_expression(compiler_ctx_t *ctx, call_expression_t *expr, BOOL emit_ret)
Definition: compile.c:628
static HRESULT compile_delete_expression(compiler_ctx_t *ctx, unary_expression_t *expr)
Definition: compile.c:670
#define DEFAULT_UNREACHABLE

Referenced by compile_args(), compile_array_literal(), compile_assign_expression(), compile_assignment(), compile_binary_expression(), compile_call_expression(), compile_comma_expression(), compile_conditional_expression(), compile_const_statement(), compile_delete_expression(), compile_dowhile_statement(), compile_expression(), compile_expression_statement(), compile_for_statement(), compile_foreach_statement(), compile_forin_statement(), compile_forto_statement(), compile_if_statement(), compile_increment_expression(), compile_logical_expression(), compile_member_expression(), compile_memberid_expression(), compile_new_expression(), compile_object_literal(), compile_return_statement(), compile_retval_statement(), compile_select_statement(), compile_switch_statement(), compile_throw_statement(), compile_typeof_expression(), compile_unary_expression(), compile_variable_list(), compile_while_statement(), and compile_with_statement().

◆ compile_expression_statement()

static HRESULT compile_expression_statement ( compiler_ctx_t ctx,
expression_statement_t stat 
)
static

Definition at line 1166 of file compile.c.

1167{
1168 HRESULT hres;
1169
1170 hres = compile_expression(ctx, stat->expr, ctx->from_eval);
1171 if(FAILED(hres))
1172 return hres;
1173
1174 return !ctx->from_eval || push_instr(ctx, OP_setret) ? S_OK : E_OUTOFMEMORY;
1175}

Referenced by compile_statement().

◆ compile_for_statement()

static HRESULT compile_for_statement ( compiler_ctx_t ctx,
for_statement_t stat 
)
static

Definition at line 1268 of file compile.c.

1269{
1270 statement_ctx_t stat_ctx = {0, FALSE, FALSE};
1271 unsigned expr_off;
1272 HRESULT hres;
1273
1274 if(stat->variable_list) {
1275 hres = compile_variable_list(ctx, stat->variable_list);
1276 if(FAILED(hres))
1277 return hres;
1278 }else if(stat->begin_expr) {
1279 hres = compile_expression(ctx, stat->begin_expr, FALSE);
1280 if(FAILED(hres))
1281 return hres;
1282 }
1283
1284 stat_ctx.break_label = alloc_label(ctx);
1285 if(!stat_ctx.break_label)
1286 return E_OUTOFMEMORY;
1287
1288 stat_ctx.continue_label = alloc_label(ctx);
1289 if(!stat_ctx.continue_label)
1290 return E_OUTOFMEMORY;
1291
1292 expr_off = ctx->code_off;
1293
1294 if(stat->expr) {
1295 hres = compile_expression(ctx, stat->expr, TRUE);
1296 if(FAILED(hres))
1297 return hres;
1298
1299 hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
1300 if(FAILED(hres))
1301 return hres;
1302 }
1303
1304 hres = compile_statement(ctx, &stat_ctx, stat->statement);
1305 if(FAILED(hres))
1306 return hres;
1307
1309
1310 if(stat->end_expr) {
1311 hres = compile_expression(ctx, stat->end_expr, FALSE);
1312 if(FAILED(hres))
1313 return hres;
1314 }
1315
1316 hres = push_instr_uint(ctx, OP_jmp, expr_off);
1317 if(FAILED(hres))
1318 return hres;
1319
1320 label_set_addr(ctx, stat_ctx.break_label);
1321 return S_OK;
1322}
static unsigned alloc_label(compiler_ctx_t *ctx)
Definition: compile.c:395
static HRESULT compile_variable_list(compiler_ctx_t *ctx, variable_declaration_t *list)
Definition: compile.c:1129
static void label_set_addr(compiler_ctx_t *ctx, unsigned label)
Definition: compile.c:416

Referenced by compile_statement().

◆ compile_forin_statement()

static HRESULT compile_forin_statement ( compiler_ctx_t ctx,
forin_statement_t stat 
)
static

Definition at line 1325 of file compile.c.

1326{
1327 statement_ctx_t stat_ctx = {4, FALSE, FALSE};
1328 HRESULT hres;
1329
1330 if(stat->variable) {
1331 hres = compile_variable_list(ctx, stat->variable);
1332 if(FAILED(hres))
1333 return hres;
1334 }
1335
1336 stat_ctx.break_label = alloc_label(ctx);
1337 if(!stat_ctx.break_label)
1338 return E_OUTOFMEMORY;
1339
1340 stat_ctx.continue_label = alloc_label(ctx);
1341 if(!stat_ctx.continue_label)
1342 return E_OUTOFMEMORY;
1343
1344 hres = compile_expression(ctx, stat->in_expr, TRUE);
1345 if(FAILED(hres))
1346 return hres;
1347
1348 if(stat->variable) {
1349 hres = emit_identifier_ref(ctx, stat->variable->identifier, fdexNameEnsure);
1350 if(FAILED(hres))
1351 return hres;
1352 }else if(is_memberid_expr(stat->expr->type)) {
1353 hres = compile_memberid_expression(ctx, stat->expr, fdexNameEnsure);
1354 if(FAILED(hres))
1355 return hres;
1356 }else {
1357 hres = push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
1358 if(FAILED(hres))
1359 return hres;
1360
1361 /* FIXME: compile statement anyways when we depend on compiler to check errors */
1362 return S_OK;
1363 }
1364
1365 hres = push_instr_int(ctx, OP_int, DISPID_STARTENUM);
1366 if(FAILED(hres))
1367 return hres;
1368
1370 hres = push_instr_uint(ctx, OP_forin, stat_ctx.break_label);
1371 if(FAILED(hres))
1372 return E_OUTOFMEMORY;
1373
1374 hres = compile_statement(ctx, &stat_ctx, stat->statement);
1375 if(FAILED(hres))
1376 return hres;
1377
1378 hres = push_instr_uint(ctx, OP_jmp, stat_ctx.continue_label);
1379 if(FAILED(hres))
1380 return hres;
1381
1382 label_set_addr(ctx, stat_ctx.break_label);
1383 return S_OK;
1384}
static HRESULT emit_identifier_ref(compiler_ctx_t *ctx, const WCHAR *identifier, unsigned flags)
Definition: compile.c:445
static HRESULT push_instr_int(compiler_ctx_t *ctx, jsop_t op, LONG arg)
Definition: compile.c:236

Referenced by compile_statement().

◆ compile_function()

static HRESULT compile_function ( compiler_ctx_t ctx,
source_elements_t source,
function_expression_t func_expr,
BOOL  from_eval,
function_code_t func 
)
static

Definition at line 2272 of file compile.c.

2274{
2277 unsigned off, i;
2278 HRESULT hres;
2279
2280 TRACE("\n");
2281
2282 ctx->func_head = ctx->func_tail = NULL;
2283 ctx->from_eval = from_eval;
2284 ctx->func = func;
2285 ctx->locals_cnt = 0;
2287
2288 if(func_expr) {
2289 parameter_t *param_iter;
2290
2291 if(func_expr->identifier) {
2292 func->name = compiler_alloc_bstr(ctx, func_expr->identifier);
2293 if(!func->name)
2294 return E_OUTOFMEMORY;
2295 }
2296
2297 if(func_expr->event_target) {
2298 func->event_target = compiler_alloc_bstr(ctx, func_expr->event_target);
2299 if(!func->event_target)
2300 return E_OUTOFMEMORY;
2301 }
2302
2303 func->source = func_expr->src_str;
2304 func->source_len = func_expr->src_len;
2305
2306 for(param_iter = func_expr->parameter_list; param_iter; param_iter = param_iter->next)
2307 func->param_cnt++;
2308
2309 func->params = compiler_alloc(ctx->code, func->param_cnt * sizeof(*func->params));
2310 if(!func->params)
2311 return E_OUTOFMEMORY;
2312
2313 for(param_iter = func_expr->parameter_list, i=0; param_iter; param_iter = param_iter->next, i++) {
2314 func->params[i] = compiler_alloc_bstr(ctx, param_iter->identifier);
2315 if(!func->params[i])
2316 return E_OUTOFMEMORY;
2317 }
2318 }
2319
2320 for(i = 0; i < func->param_cnt; i++) {
2321 if(!find_local(ctx, func->params[i]) && !alloc_local(ctx, func->params[i], -i-1))
2322 return E_OUTOFMEMORY;
2323 }
2324
2325 hres = visit_block_statement(ctx, source->statement);
2326 if(FAILED(hres))
2327 return hres;
2328
2329 func->locals = compiler_alloc(ctx->code, ctx->locals_cnt * sizeof(*func->locals));
2330 if(!func->locals)
2331 return E_OUTOFMEMORY;
2332 func->locals_cnt = ctx->locals_cnt;
2333
2334 func->variables = compiler_alloc(ctx->code, func->var_cnt * sizeof(*func->variables));
2335 if(!func->variables)
2336 return E_OUTOFMEMORY;
2337
2338 i = 0;
2340 func->locals[i].name = local->name;
2341 func->locals[i].ref = local->ref;
2342 if(local->ref >= 0) {
2343 func->variables[local->ref].name = local->name;
2344 func->variables[local->ref].func_id = -1;
2345 }
2346 i++;
2347 }
2348 assert(i == ctx->locals_cnt);
2349
2350 func->funcs = compiler_alloc(ctx->code, func->func_cnt * sizeof(*func->funcs));
2351 if(!func->funcs)
2352 return E_OUTOFMEMORY;
2353 memset(func->funcs, 0, func->func_cnt * sizeof(*func->funcs));
2354
2355 off = ctx->code_off;
2356 hres = compile_block_statement(ctx, source->statement);
2357 if(FAILED(hres))
2358 return hres;
2359
2360 resolve_labels(ctx, off);
2361
2362 hres = push_instr_uint(ctx, OP_ret, !from_eval);
2363 if(FAILED(hres))
2364 return hres;
2365
2366 if(TRACE_ON(jscript_disas))
2367 dump_code(ctx, off);
2368
2369 func->instr_off = off;
2370
2371 for(iter = ctx->func_head, i=0; iter; iter = iter->next, i++) {
2372 hres = compile_function(ctx, iter->source_elements, iter, FALSE, func->funcs+i);
2373 if(FAILED(hres))
2374 return hres;
2375
2376 TRACE("[%d] func %s\n", i, debugstr_w(func->funcs[i].name));
2377 if(func->funcs[i].name && !func->funcs[i].event_target) {
2378 local_ref_t *local_ref = lookup_local(func, func->funcs[i].name);
2379 func->funcs[i].local_ref = local_ref->ref;
2380 TRACE("found ref %s %d for %s\n", debugstr_w(local_ref->name), local_ref->ref, debugstr_w(func->funcs[i].name));
2381 if(local_ref->ref >= 0)
2382 func->variables[local_ref->ref].func_id = i;
2383 }
2384 }
2385
2386 assert(i == func->func_cnt);
2387
2388 return S_OK;
2389}
#define TRACE_ON(x)
Definition: compat.h:75
GLenum func
Definition: glext.h:6028
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
uint32_t entry
Definition: isohybrid.c:63
static void dump_code(compiler_ctx_t *ctx, unsigned off)
Definition: compile.c:109
static void resolve_labels(compiler_ctx_t *ctx, unsigned off)
Definition: compile.c:2211
static HRESULT compile_block_statement(compiler_ctx_t *ctx, statement_t *iter)
Definition: compile.c:1113
static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source, function_expression_t *func_expr, BOOL from_eval, function_code_t *func)
Definition: compile.c:2272
static HRESULT visit_block_statement(compiler_ctx_t *ctx, statement_t *iter)
Definition: compile.c:2037
static int function_local_cmp(const void *key, const struct wine_rb_entry *entry)
Definition: compile.c:1836
#define debugstr_w
Definition: kernel32.h:32
#define WINE_RB_FOR_EACH_ENTRY(elem, tree, type, field)
Definition: rbtree.h:154
static void wine_rb_init(struct wine_rb_tree *tree, wine_rb_compare_func_t compare)
Definition: rbtree.h:179
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
const WCHAR * event_target
Definition: parser.h:294
parameter_t * parameter_list
Definition: parser.h:295
const WCHAR * src_str
Definition: parser.h:297
struct _function_expression_t * next
Definition: parser.h:301
source_elements_t * source_elements
Definition: parser.h:296
const WCHAR * identifier
Definition: parser.h:293
struct _parameter_t * next
Definition: parser.h:283
const WCHAR * identifier
Definition: parser.h:282
int ref
Definition: engine.h:142
BSTR name
Definition: engine.h:141

Referenced by compile_function(), and compile_script().

◆ compile_function_expression()

static HRESULT compile_function_expression ( compiler_ctx_t ctx,
function_expression_t expr,
BOOL  emit_ret 
)
static

Definition at line 918 of file compile.c.

919{
920 return emit_ret ? push_instr_uint(ctx, OP_func, expr->func_id) : S_OK;
921}

Referenced by compile_expression().

◆ compile_if_statement()

static HRESULT compile_if_statement ( compiler_ctx_t ctx,
if_statement_t stat 
)
static

Definition at line 1178 of file compile.c.

1179{
1180 unsigned jmp_else;
1181 HRESULT hres;
1182
1183 hres = compile_expression(ctx, stat->expr, TRUE);
1184 if(FAILED(hres))
1185 return hres;
1186
1187 jmp_else = push_instr(ctx, OP_jmp_z);
1188 if(!jmp_else)
1189 return E_OUTOFMEMORY;
1190
1191 hres = compile_statement(ctx, NULL, stat->if_stat);
1192 if(FAILED(hres))
1193 return hres;
1194
1195 if(stat->else_stat) {
1196 unsigned jmp_end;
1197
1198 jmp_end = push_instr(ctx, OP_jmp);
1199 if(!jmp_end)
1200 return E_OUTOFMEMORY;
1201
1202 set_arg_uint(ctx, jmp_else, ctx->code_off);
1203
1204 hres = compile_statement(ctx, NULL, stat->else_stat);
1205 if(FAILED(hres))
1206 return hres;
1207
1208 set_arg_uint(ctx, jmp_end, ctx->code_off);
1209 }else {
1210 set_arg_uint(ctx, jmp_else, ctx->code_off);
1211 }
1212
1213 return S_OK;
1214}

Referenced by compile_statement().

◆ compile_increment_expression()

static HRESULT compile_increment_expression ( compiler_ctx_t ctx,
unary_expression_t expr,
jsop_t  op,
int  n 
)
static

Definition at line 512 of file compile.c.

513{
515
516 if(!is_memberid_expr(expr->expression->type)) {
517 hres = compile_expression(ctx, expr->expression, TRUE);
518 if(FAILED(hres))
519 return hres;
520
521 return push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
522 }
523
524 hres = compile_memberid_expression(ctx, expr->expression, fdexNameEnsure);
525 if(FAILED(hres))
526 return hres;
527
528 return push_instr_int(ctx, op, n);
529}
GLdouble n
Definition: glext.h:7729

Referenced by compile_expression().

◆ compile_labelled_statement()

static HRESULT compile_labelled_statement ( compiler_ctx_t ctx,
labelled_statement_t stat 
)
static

Definition at line 1557 of file compile.c.

1558{
1559 statement_ctx_t stat_ctx = {0, FALSE, FALSE, 0, 0, stat}, *iter;
1560 HRESULT hres;
1561
1562 for(iter = ctx->stat_ctx; iter; iter = iter->next) {
1563 if(iter->labelled_stat && !wcscmp(iter->labelled_stat->identifier, stat->identifier)) {
1564 WARN("Label %s redefined\n", debugstr_w(stat->identifier));
1565 return JS_E_LABEL_REDEFINED;
1566 }
1567 }
1568
1569 /* Labelled breaks are allowed for any labelled statements, not only loops (violating spec) */
1570 stat_ctx.break_label = alloc_label(ctx);
1571 if(!stat_ctx.break_label)
1572 return E_OUTOFMEMORY;
1573
1574 hres = compile_statement(ctx, &stat_ctx, stat->statement);
1575 if(FAILED(hres))
1576 return hres;
1577
1578 label_set_addr(ctx, stat_ctx.break_label);
1579 return S_OK;
1580}
#define JS_E_LABEL_REDEFINED
Definition: jscript.h:547

Referenced by compile_statement().

◆ compile_literal()

static HRESULT compile_literal ( compiler_ctx_t ctx,
literal_t literal 
)
static

Definition at line 833 of file compile.c.

834{
835 switch(literal->type) {
836 case LT_BOOL:
837 return push_instr_int(ctx, OP_bool, literal->u.bval);
838 case LT_DOUBLE:
839 return push_instr_double(ctx, OP_double, literal->u.dval);
840 case LT_NULL:
841 return push_instr(ctx, OP_null) ? S_OK : E_OUTOFMEMORY;
842 case LT_STRING:
843 return push_instr_str(ctx, OP_str, literal->u.str);
844 case LT_REGEXP:
845 return push_instr_str_uint(ctx, OP_regexp, literal->u.regexp.str, literal->u.regexp.flags);
847 }
848 return E_FAIL;
849}
#define E_FAIL
Definition: ddrawi.h:102
@ LT_BOOL
Definition: parser.h:75
@ LT_STRING
Definition: parser.h:74
@ LT_NULL
Definition: parser.h:76
@ LT_REGEXP
Definition: parser.h:77
@ LT_DOUBLE
Definition: parser.h:73
static HRESULT push_instr_str_uint(compiler_ctx_t *ctx, jsop_t op, jsstr_t *str, unsigned arg2)
Definition: compile.c:260
static HRESULT push_instr_double(compiler_ctx_t *ctx, jsop_t op, double arg)
Definition: compile.c:326
BOOL bval
Definition: parser.h:85
struct literal_t::@445::@446 regexp
union literal_t::@445 u
double dval
Definition: parser.h:83
literal_type_t type
Definition: parser.h:81
jsstr_t * str
Definition: parser.h:84

Referenced by compile_expression().

◆ compile_logical_expression()

static HRESULT compile_logical_expression ( compiler_ctx_t ctx,
binary_expression_t expr,
jsop_t  op 
)
static

Definition at line 544 of file compile.c.

545{
546 unsigned instr;
548
549 hres = compile_expression(ctx, expr->expression1, TRUE);
550 if(FAILED(hres))
551 return hres;
552
553 instr = push_instr(ctx, op);
554 if(!instr)
555 return E_OUTOFMEMORY;
556
557 hres = compile_expression(ctx, expr->expression2, TRUE);
558 if(FAILED(hres))
559 return hres;
560
561 set_arg_uint(ctx, instr, ctx->code_off);
562 return S_OK;
563}

Referenced by compile_expression().

◆ compile_member_expression()

static HRESULT compile_member_expression ( compiler_ctx_t ctx,
member_expression_t expr 
)
static

Definition at line 382 of file compile.c.

383{
385
386 hres = compile_expression(ctx, expr->expression, TRUE);
387 if(FAILED(hres))
388 return hres;
389
390 return push_instr_bstr(ctx, OP_member, expr->identifier);
391}

Referenced by compile_call_statement(), and compile_expression().

◆ compile_memberid_expression()

static HRESULT compile_memberid_expression ( compiler_ctx_t ctx,
expression_t expr,
unsigned  flags 
)
static

Definition at line 461 of file compile.c.

462{
463 HRESULT hres = S_OK;
464
465 switch(expr->type) {
466 case EXPR_IDENT: {
468
470 break;
471 }
472 case EXPR_ARRAY: {
474
475 hres = compile_expression(ctx, array_expr->expression1, TRUE);
476 if(FAILED(hres))
477 return hres;
478
479 hres = compile_expression(ctx, array_expr->expression2, TRUE);
480 if(FAILED(hres))
481 return hres;
482
483 hres = push_instr_uint(ctx, OP_memberid, flags);
484 break;
485 }
486 case EXPR_MEMBER: {
488 jsstr_t *jsstr;
489
490 hres = compile_expression(ctx, member_expr->expression, TRUE);
491 if(FAILED(hres))
492 return hres;
493
494 /* FIXME: Potential optimization */
495 jsstr = compiler_alloc_string(ctx, member_expr->identifier);
496 if(!jsstr)
497 return E_OUTOFMEMORY;
498
499 hres = push_instr_str(ctx, OP_str, jsstr);
500 if(FAILED(hres))
501 return hres;
502
503 hres = push_instr_uint(ctx, OP_memberid, flags);
504 break;
505 }
507 }
508
509 return hres;
510}
GLbitfield flags
Definition: glext.h:7161
const WCHAR * identifier
Definition: parser.h:342

Referenced by compile_assign_expression(), compile_call_expression(), compile_forin_statement(), compile_increment_expression(), and compile_typeof_expression().

◆ compile_new_expression()

static HRESULT compile_new_expression ( compiler_ctx_t ctx,
call_expression_t expr 
)
static

Definition at line 600 of file compile.c.

601{
602 unsigned arg_cnt = 0;
605
606 hres = compile_expression(ctx, expr->expression, TRUE);
607 if(FAILED(hres))
608 return hres;
609
610 for(arg = expr->argument_list; arg; arg = arg->next) {
612 if(FAILED(hres))
613 return hres;
614 arg_cnt++;
615 }
616
617 hres = push_instr_uint(ctx, OP_new, arg_cnt);
618 if(FAILED(hres))
619 return hres;
620
621 hres = push_instr_uint(ctx, OP_pop, arg_cnt+1);
622 if(FAILED(hres))
623 return hres;
624
625 return push_instr(ctx, OP_push_acc) ? S_OK : E_OUTOFMEMORY;
626}

Referenced by compile_expression().

◆ compile_object_literal()

static HRESULT compile_object_literal ( compiler_ctx_t ctx,
property_value_expression_t expr 
)
static

Definition at line 892 of file compile.c.

893{
895 jsstr_t *name;
897
898 if(!push_instr(ctx, OP_new_obj))
899 return E_OUTOFMEMORY;
900
901 for(iter = expr->property_list; iter; iter = iter->next) {
902 hres = literal_as_string(ctx, iter->name, &name);
903 if(FAILED(hres))
904 return hres;
905
907 if(FAILED(hres))
908 return hres;
909
910 hres = push_instr_str_uint(ctx, OP_obj_prop, name, iter->type);
911 if(FAILED(hres))
912 return hres;
913 }
914
915 return S_OK;
916}
static HRESULT literal_as_string(compiler_ctx_t *ctx, literal_t *literal, jsstr_t **str)
Definition: compile.c:851
struct _property_definition_t * next
Definition: parser.h:368
literal_t * name
Definition: parser.h:365
expression_t * value
Definition: parser.h:366

Referenced by compile_expression().

◆ compile_return_statement()

static HRESULT compile_return_statement ( compiler_ctx_t ctx,
expression_statement_t stat 
)
static

Definition at line 1509 of file compile.c.

1510{
1511 HRESULT hres;
1512
1513 if(ctx->from_eval) {
1514 WARN("misplaced return statement\n");
1515 return JS_E_MISPLACED_RETURN;
1516 }
1517
1518 if(stat->expr) {
1519 hres = compile_expression(ctx, stat->expr, TRUE);
1520 if(FAILED(hres))
1521 return hres;
1522 if(!push_instr(ctx, OP_setret))
1523 return E_OUTOFMEMORY;
1524 }
1525
1527 if(FAILED(hres))
1528 return hres;
1529
1530 return push_instr_uint(ctx, OP_ret, !stat->expr);
1531}
#define JS_E_MISPLACED_RETURN
Definition: jscript.h:544

Referenced by compile_statement().

◆ compile_script()

HRESULT compile_script ( script_ctx_t ctx,
const WCHAR code,
const WCHAR args,
const WCHAR delimiter,
BOOL  from_eval,
BOOL  use_decode,
bytecode_t **  ret 
)

Definition at line 2461 of file compile.c.

2463{
2464 compiler_ctx_t compiler = {0};
2465 HRESULT hres;
2466
2467 hres = init_code(&compiler, code);
2468 if(FAILED(hres))
2469 return hres;
2470
2471 if(args) {
2472 hres = compile_arguments(&compiler, args);
2473 if(FAILED(hres))
2474 return hres;
2475 }
2476
2477 if(use_decode) {
2478 hres = decode_source(compiler.code->source);
2479 if(FAILED(hres)) {
2480 WARN("Decoding failed\n");
2481 return hres;
2482 }
2483 }
2484
2485 hres = script_parse(ctx, &compiler, compiler.code->source, delimiter, from_eval, &compiler.parser);
2486 if(FAILED(hres)) {
2487 release_bytecode(compiler.code);
2488 return hres;
2489 }
2490
2491 heap_pool_init(&compiler.heap);
2492 hres = compile_function(&compiler, compiler.parser->source, NULL, from_eval, &compiler.code->global_code);
2493 heap_pool_free(&compiler.heap);
2494 parser_release(compiler.parser);
2495 if(FAILED(hres)) {
2496 release_bytecode(compiler.code);
2497 return hres;
2498 }
2499
2500 *ret = compiler.code;
2501 return S_OK;
2502}
void parser_release(parser_ctx_t *) DECLSPEC_HIDDEN
HRESULT script_parse(script_ctx_t *, struct _compiler_ctx_t *, const WCHAR *, const WCHAR *, BOOL, parser_ctx_t **) DECLSPEC_HIDDEN
void release_bytecode(bytecode_t *code)
Definition: compile.c:2226
static HRESULT compile_arguments(compiler_ctx_t *ctx, const WCHAR *args)
Definition: compile.c:2445
static HRESULT init_code(compiler_ctx_t *compiler, const WCHAR *source)
Definition: compile.c:2246
HRESULT decode_source(WCHAR *code)
Definition: decode.c:111
void heap_pool_free(heap_pool_t *) DECLSPEC_HIDDEN
Definition: jsutils.c:169
void heap_pool_init(heap_pool_t *) DECLSPEC_HIDDEN
Definition: jsutils.c:71
const char * delimiter
Definition: string.c:1566
WCHAR * source
Definition: engine.h:180
function_code_t global_code
Definition: engine.h:178
bytecode_t * code
Definition: compile.c:53
heap_pool_t heap
Definition: compile.c:73
parser_ctx_t * parser
Definition: compile.c:52
Definition: inflate.c:139
int ret

Referenced by compile_procedure(), construct_function(), JScriptParse_ParseScriptText(), JScriptParseProcedure_ParseProcedureText(), JSGlobal_eval(), and VBScriptParse_ParseScriptText().

◆ compile_statement()

static HRESULT compile_statement ( compiler_ctx_t ctx,
statement_ctx_t stat_ctx,
statement_t stat 
)
static

Definition at line 1766 of file compile.c.

1767{
1768 HRESULT hres;
1769
1770 if(stat_ctx) {
1771 stat_ctx->next = ctx->stat_ctx;
1772 ctx->stat_ctx = stat_ctx;
1773 }
1774
1775 switch(stat->type) {
1776 case STAT_BLOCK:
1778 break;
1779 case STAT_BREAK:
1781 break;
1782 case STAT_CONTINUE:
1784 break;
1785 case STAT_EMPTY:
1786 /* nothing to do */
1787 hres = S_OK;
1788 break;
1789 case STAT_EXPR:
1791 break;
1792 case STAT_FOR:
1794 break;
1795 case STAT_FORIN:
1797 break;
1798 case STAT_IF:
1800 break;
1801 case STAT_LABEL:
1803 break;
1804 case STAT_RETURN:
1806 break;
1807 case STAT_SWITCH:
1809 break;
1810 case STAT_THROW:
1812 break;
1813 case STAT_TRY:
1815 break;
1816 case STAT_VAR:
1818 break;
1819 case STAT_WHILE:
1821 break;
1822 case STAT_WITH:
1824 break;
1826 }
1827
1828 if(stat_ctx) {
1829 assert(ctx->stat_ctx == stat_ctx);
1830 ctx->stat_ctx = stat_ctx->next;
1831 }
1832
1833 return hres;
1834}
@ STAT_CONTINUE
Definition: parser.h:107
@ STAT_FOR
Definition: parser.h:110
@ STAT_EMPTY
Definition: parser.h:108
@ STAT_THROW
Definition: parser.h:116
@ STAT_SWITCH
Definition: parser.h:115
@ STAT_VAR
Definition: parser.h:118
@ STAT_EXPR
Definition: parser.h:109
@ STAT_TRY
Definition: parser.h:117
@ STAT_RETURN
Definition: parser.h:114
@ STAT_BLOCK
Definition: parser.h:105
@ STAT_WITH
Definition: parser.h:120
@ STAT_IF
Definition: parser.h:112
@ STAT_FORIN
Definition: parser.h:111
@ STAT_BREAK
Definition: parser.h:106
@ STAT_WHILE
Definition: parser.h:119
static HRESULT compile_for_statement(compiler_ctx_t *ctx, for_statement_t *stat)
Definition: compile.c:1268
static HRESULT compile_forin_statement(compiler_ctx_t *ctx, forin_statement_t *stat)
Definition: compile.c:1325
static HRESULT compile_continue_statement(compiler_ctx_t *ctx, branch_statement_t *stat)
Definition: compile.c:1419
static HRESULT compile_return_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
Definition: compile.c:1509
static HRESULT compile_while_statement(compiler_ctx_t *ctx, while_statement_t *stat)
Definition: compile.c:1217
static HRESULT compile_labelled_statement(compiler_ctx_t *ctx, labelled_statement_t *stat)
Definition: compile.c:1557
static HRESULT compile_throw_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
Definition: compile.c:1678
static HRESULT compile_if_statement(compiler_ctx_t *ctx, if_statement_t *stat)
Definition: compile.c:1178
static HRESULT compile_var_statement(compiler_ctx_t *ctx, var_statement_t *stat)
Definition: compile.c:1160
static HRESULT compile_expression_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
Definition: compile.c:1166
static HRESULT compile_break_statement(compiler_ctx_t *ctx, branch_statement_t *stat)
Definition: compile.c:1472
static HRESULT compile_switch_statement(compiler_ctx_t *ctx, switch_statement_t *stat)
Definition: compile.c:1583
static HRESULT compile_try_statement(compiler_ctx_t *ctx, try_statement_t *stat)
Definition: compile.c:1690
static HRESULT compile_with_statement(compiler_ctx_t *ctx, with_statement_t *stat)
Definition: compile.c:1534

Referenced by compile_block_statement(), compile_dowhile_statement(), compile_for_statement(), compile_foreach_statement(), compile_forin_statement(), compile_forto_statement(), compile_func(), compile_if_statement(), compile_labelled_statement(), compile_select_statement(), compile_switch_statement(), compile_try_statement(), compile_while_statement(), and compile_with_statement().

◆ compile_switch_statement()

static HRESULT compile_switch_statement ( compiler_ctx_t ctx,
switch_statement_t stat 
)
static

Definition at line 1583 of file compile.c.

1584{
1585 statement_ctx_t stat_ctx = {0, FALSE, FALSE};
1586 unsigned case_cnt = 0, *case_jmps, i, default_jmp;
1587 BOOL have_default = FALSE;
1588 statement_t *stat_iter;
1589 case_clausule_t *iter;
1590 HRESULT hres;
1591
1592 hres = compile_expression(ctx, stat->expr, TRUE);
1593 if(FAILED(hres))
1594 return hres;
1595
1596 stat_ctx.break_label = alloc_label(ctx);
1597 if(!stat_ctx.break_label)
1598 return E_OUTOFMEMORY;
1599
1600 for(iter = stat->case_list; iter; iter = iter->next) {
1601 if(iter->expr)
1602 case_cnt++;
1603 }
1604
1605 case_jmps = heap_alloc(case_cnt * sizeof(*case_jmps));
1606 if(!case_jmps)
1607 return E_OUTOFMEMORY;
1608
1609 i = 0;
1610 for(iter = stat->case_list; iter; iter = iter->next) {
1611 if(!iter->expr) {
1612 have_default = TRUE;
1613 continue;
1614 }
1615
1616 hres = compile_expression(ctx, iter->expr, TRUE);
1617 if(FAILED(hres))
1618 break;
1619
1620 case_jmps[i] = push_instr(ctx, OP_case);
1621 if(!case_jmps[i]) {
1623 break;
1624 }
1625 i++;
1626 }
1627
1628 if(SUCCEEDED(hres)) {
1629 hres = push_instr_uint(ctx, OP_pop, 1);
1630 if(SUCCEEDED(hres)) {
1631 default_jmp = push_instr(ctx, OP_jmp);
1632 if(!default_jmp)
1634 }
1635 }
1636
1637 if(FAILED(hres)) {
1638 heap_free(case_jmps);
1639 return hres;
1640 }
1641
1642 i = 0;
1643 for(iter = stat->case_list; iter; iter = iter->next) {
1644 while(iter->next && iter->next->stat == iter->stat) {
1645 set_arg_uint(ctx, iter->expr ? case_jmps[i++] : default_jmp, ctx->code_off);
1646 iter = iter->next;
1647 }
1648
1649 set_arg_uint(ctx, iter->expr ? case_jmps[i++] : default_jmp, ctx->code_off);
1650
1651 for(stat_iter = iter->stat; stat_iter && (!iter->next || iter->next->stat != stat_iter);
1652 stat_iter = stat_iter->next) {
1653 hres = compile_statement(ctx, &stat_ctx, stat_iter);
1654 if(FAILED(hres))
1655 break;
1656 }
1657 if(FAILED(hres))
1658 break;
1659 }
1660
1661 heap_free(case_jmps);
1662 if(FAILED(hres))
1663 return hres;
1664 assert(i == case_cnt);
1665
1666 if(!have_default) {
1667 hres = push_instr_uint(ctx, OP_jmp, stat_ctx.break_label);
1668 if(FAILED(hres))
1669 return hres;
1670 set_arg_uint(ctx, default_jmp, ctx->code_off);
1671 }
1672
1673 label_set_addr(ctx, stat_ctx.break_label);
1674 return S_OK;
1675}
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
#define SUCCEEDED(hr)
Definition: intsafe.h:50
struct _case_clausule_t * next
Definition: parser.h:195
statement_t * stat
Definition: parser.h:193
expression_t * expr
Definition: parser.h:192

Referenced by compile_statement().

◆ compile_throw_statement()

static HRESULT compile_throw_statement ( compiler_ctx_t ctx,
expression_statement_t stat 
)
static

Definition at line 1678 of file compile.c.

1679{
1680 HRESULT hres;
1681
1682 hres = compile_expression(ctx, stat->expr, TRUE);
1683 if(FAILED(hres))
1684 return hres;
1685
1686 return push_instr(ctx, OP_throw) ? S_OK : E_OUTOFMEMORY;
1687}

Referenced by compile_statement().

◆ compile_try_statement()

static HRESULT compile_try_statement ( compiler_ctx_t ctx,
try_statement_t stat 
)
static

Definition at line 1690 of file compile.c.

1691{
1692 statement_ctx_t try_ctx = {0, FALSE, TRUE}, finally_ctx = {2, FALSE, FALSE};
1693 unsigned push_except, finally_off = 0, catch_off = 0, pop_except, catch_pop_except = 0;
1694 BSTR ident;
1695 HRESULT hres;
1696
1697 push_except = push_instr(ctx, OP_push_except);
1698 if(!push_except)
1699 return E_OUTOFMEMORY;
1700
1701 if(stat->catch_block) {
1702 ident = compiler_alloc_bstr(ctx, stat->catch_block->identifier);
1703 if(!ident)
1704 return E_OUTOFMEMORY;
1705 }else {
1706 ident = NULL;
1707 }
1708
1709 hres = compile_statement(ctx, &try_ctx, stat->try_statement);
1710 if(FAILED(hres))
1711 return hres;
1712
1713 pop_except = push_instr(ctx, OP_pop_except);
1714 if(!pop_except)
1715 return E_OUTOFMEMORY;
1716
1717 if(stat->catch_block) {
1718 statement_ctx_t catch_ctx = {0, TRUE, stat->finally_statement != NULL};
1719
1720 if(stat->finally_statement)
1721 catch_ctx.using_except = TRUE;
1722
1723 catch_off = ctx->code_off;
1724
1725 hres = push_instr_bstr(ctx, OP_enter_catch, ident);
1726 if(FAILED(hres))
1727 return hres;
1728
1729 hres = compile_statement(ctx, &catch_ctx, stat->catch_block->statement);
1730 if(FAILED(hres))
1731 return hres;
1732
1733 if(!push_instr(ctx, OP_pop_scope))
1734 return E_OUTOFMEMORY;
1735
1736 if(stat->finally_statement) {
1737 catch_pop_except = push_instr(ctx, OP_pop_except);
1738 if(!catch_pop_except)
1739 return E_OUTOFMEMORY;
1740 }
1741 }
1742
1743 if(stat->finally_statement) {
1744 /*
1745 * finally block expects two elements on the stack, which may be:
1746 * - (true, return_addr) set by OP_pop_except, OP_end_finally jumps back to passed address
1747 * - (false, exception_value) set when unwinding an exception, which OP_end_finally rethrows
1748 */
1749 finally_off = ctx->code_off;
1750 hres = compile_statement(ctx, &finally_ctx, stat->finally_statement);
1751 if(FAILED(hres))
1752 return hres;
1753
1754 if(!push_instr(ctx, OP_end_finally))
1755 return E_OUTOFMEMORY;
1756 }
1757
1758 instr_ptr(ctx, pop_except)->u.arg[0].uint = ctx->code_off;
1759 if(catch_pop_except)
1760 instr_ptr(ctx, catch_pop_except)->u.arg[0].uint = ctx->code_off;
1761 instr_ptr(ctx, push_except)->u.arg[0].uint = catch_off;
1762 instr_ptr(ctx, push_except)->u.arg[1].uint = finally_off;
1763 return S_OK;
1764}
BOOL using_except
Definition: compile.c:35

Referenced by compile_statement().

◆ compile_typeof_expression()

static HRESULT compile_typeof_expression ( compiler_ctx_t ctx,
unary_expression_t expr 
)
static

Definition at line 812 of file compile.c.

813{
814 jsop_t op;
816
817 if(is_memberid_expr(expr->expression->type)) {
818 if(expr->expression->type == EXPR_IDENT)
819 return push_instr_bstr(ctx, OP_typeofident, ((identifier_expression_t*)expr->expression)->identifier);
820
821 op = OP_typeofid;
822 hres = compile_memberid_expression(ctx, expr->expression, 0);
823 }else {
824 op = OP_typeof;
825 hres = compile_expression(ctx, expr->expression, TRUE);
826 }
827 if(FAILED(hres))
828 return hres;
829
830 return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
831}

Referenced by compile_expression().

◆ compile_unary_expression()

static HRESULT compile_unary_expression ( compiler_ctx_t ctx,
unary_expression_t expr,
jsop_t  op 
)
static

Definition at line 370 of file compile.c.

371{
373
374 hres = compile_expression(ctx, expr->expression, TRUE);
375 if(FAILED(hres))
376 return hres;
377
378 return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
379}

Referenced by compile_expression().

◆ compile_var_statement()

static HRESULT compile_var_statement ( compiler_ctx_t ctx,
var_statement_t stat 
)
static

Definition at line 1160 of file compile.c.

1161{
1162 return compile_variable_list(ctx, stat->variable_list);
1163}

Referenced by compile_statement().

◆ compile_variable_list()

static HRESULT compile_variable_list ( compiler_ctx_t ctx,
variable_declaration_t list 
)
static

Definition at line 1129 of file compile.c.

1130{
1132 HRESULT hres;
1133
1134 assert(list != NULL);
1135
1136 for(iter = list; iter; iter = iter->next) {
1137 if(!iter->expr)
1138 continue;
1139
1141 if(FAILED(hres))
1142 return hres;
1143
1144 hres = compile_expression(ctx, iter->expr, TRUE);
1145 if(FAILED(hres))
1146 return hres;
1147
1148 if(!push_instr(ctx, OP_assign))
1149 return E_OUTOFMEMORY;
1150
1151 hres = push_instr_uint(ctx, OP_pop, 1);
1152 if(FAILED(hres))
1153 return hres;
1154 }
1155
1156 return S_OK;
1157}
Definition: list.h:37
const WCHAR * identifier
Definition: parser.h:97
expression_t * expr
Definition: parser.h:98
struct _variable_declaration_t * next
Definition: parser.h:100

Referenced by compile_for_statement(), compile_forin_statement(), and compile_var_statement().

◆ compile_while_statement()

static HRESULT compile_while_statement ( compiler_ctx_t ctx,
while_statement_t stat 
)
static

Definition at line 1217 of file compile.c.

1218{
1219 statement_ctx_t stat_ctx = {0, FALSE, FALSE};
1220 unsigned jmp_off;
1221 HRESULT hres;
1222
1223 stat_ctx.break_label = alloc_label(ctx);
1224 if(!stat_ctx.break_label)
1225 return E_OUTOFMEMORY;
1226
1227 stat_ctx.continue_label = alloc_label(ctx);
1228 if(!stat_ctx.continue_label)
1229 return E_OUTOFMEMORY;
1230
1231 jmp_off = ctx->code_off;
1232
1233 if(!stat->do_while) {
1235 hres = compile_expression(ctx, stat->expr, TRUE);
1236 if(FAILED(hres))
1237 return hres;
1238
1239 hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
1240 if(FAILED(hres))
1241 return hres;
1242 }
1243
1244 hres = compile_statement(ctx, &stat_ctx, stat->statement);
1245 if(FAILED(hres))
1246 return hres;
1247
1248 if(stat->do_while) {
1250 hres = compile_expression(ctx, stat->expr, TRUE);
1251 if(FAILED(hres))
1252 return hres;
1253
1254 hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
1255 if(FAILED(hres))
1256 return hres;
1257 }
1258
1259 hres = push_instr_uint(ctx, OP_jmp, jmp_off);
1260 if(FAILED(hres))
1261 return hres;
1262
1263 label_set_addr(ctx, stat_ctx.break_label);
1264 return S_OK;
1265}

Referenced by compile_statement().

◆ compile_with_statement()

static HRESULT compile_with_statement ( compiler_ctx_t ctx,
with_statement_t stat 
)
static

Definition at line 1534 of file compile.c.

1535{
1536 statement_ctx_t stat_ctx = {0, TRUE, FALSE};
1537 HRESULT hres;
1538
1539 hres = compile_expression(ctx, stat->expr, TRUE);
1540 if(FAILED(hres))
1541 return hres;
1542
1543 if(!push_instr(ctx, OP_push_scope))
1544 return E_OUTOFMEMORY;
1545
1546 hres = compile_statement(ctx, &stat_ctx, stat->statement);
1547 if(FAILED(hres))
1548 return hres;
1549
1550 if(!push_instr(ctx, OP_pop_scope))
1551 return E_OUTOFMEMORY;
1552
1553 return S_OK;
1554}

Referenced by compile_statement().

◆ compiler_alloc()

static void * compiler_alloc ( bytecode_t code,
size_t  size 
)
inlinestatic

◆ compiler_alloc_bstr()

static BSTR compiler_alloc_bstr ( compiler_ctx_t ctx,
const WCHAR str 
)
static

Definition at line 187 of file compile.c.

188{
190 return NULL;
191
192 ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocString(str);
193 if(!ctx->code->bstr_pool[ctx->code->bstr_cnt])
194 return NULL;
195
196 return ctx->code->bstr_pool[ctx->code->bstr_cnt++];
197}
static BOOL ensure_bstr_slot(compiler_ctx_t *ctx)
Definition: compile.c:166
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:238
const WCHAR * str

Referenced by alloc_variable(), compile_function(), compile_try_statement(), push_instr_bstr(), and push_instr_bstr_uint().

◆ compiler_alloc_bstr_len()

static BSTR compiler_alloc_bstr_len ( compiler_ctx_t ctx,
const WCHAR str,
size_t  len 
)
static

Definition at line 199 of file compile.c.

200{
202 return NULL;
203
204 ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocStringLen(str, len);
205 if(!ctx->code->bstr_pool[ctx->code->bstr_cnt])
206 return NULL;
207
208 return ctx->code->bstr_pool[ctx->code->bstr_cnt++];
209}
GLenum GLsizei len
Definition: glext.h:6722
BSTR WINAPI SysAllocStringLen(const OLECHAR *str, unsigned int len)
Definition: oleaut.c:339

Referenced by parse_arguments().

◆ compiler_alloc_string()

static jsstr_t * compiler_alloc_string ( compiler_ctx_t ctx,
const WCHAR str 
)
static

Definition at line 161 of file compile.c.

162{
164}
#define lstrlenW
Definition: compat.h:750
jsstr_t * compiler_alloc_string_len(compiler_ctx_t *ctx, const WCHAR *str, unsigned len)
Definition: compile.c:133

Referenced by compile_class(), compile_delete_expression(), compile_func(), compile_memberid_expression(), create_class_funcprop(), create_function(), push_instr_str(), and push_instr_uint_str().

◆ compiler_alloc_string_len()

jsstr_t * compiler_alloc_string_len ( compiler_ctx_t ctx,
const WCHAR str,
unsigned  len 
)

Definition at line 133 of file compile.c.

134{
135 jsstr_t *new_str;
136
137 if(!ctx->code->str_pool_size) {
138 ctx->code->str_pool = heap_alloc(8 * sizeof(jsstr_t*));
139 if(!ctx->code->str_pool)
140 return NULL;
141 ctx->code->str_pool_size = 8;
142 }else if(ctx->code->str_pool_size == ctx->code->str_cnt) {
143 jsstr_t **new_pool;
144
145 new_pool = heap_realloc(ctx->code->str_pool, ctx->code->str_pool_size*2*sizeof(jsstr_t*));
146 if(!new_pool)
147 return NULL;
148
149 ctx->code->str_pool = new_pool;
150 ctx->code->str_pool_size *= 2;
151 }
152
153 new_str = jsstr_alloc_len(str, len);
154 if(!new_str)
155 return NULL;
156
157 ctx->code->str_pool[ctx->code->str_cnt++] = new_str;
158 return new_str;
159}
jsstr_t * jsstr_alloc_len(const WCHAR *buf, unsigned len)
Definition: jsstr.c:86

Referenced by compiler_alloc_string(), parse_regexp(), and parse_string_literal().

◆ dump_code()

static void dump_code ( compiler_ctx_t ctx,
unsigned  off 
)
static

Definition at line 109 of file compile.c.

110{
111 instr_t *instr;
112
113 for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->code_off; instr++) {
114 TRACE_(jscript_disas)("%d:\t%s", (int)(instr-ctx->code->instrs), instr_info[instr->op].op_str);
115 if(instr_info[instr->op].arg1_type == ARG_DBL) {
116 TRACE_(jscript_disas)("\t%lf", instr->u.dbl);
117 }else {
118 dump_instr_arg(instr_info[instr->op].arg1_type, instr->u.arg);
119 dump_instr_arg(instr_info[instr->op].arg2_type, instr->u.arg+1);
120 }
121 TRACE_(jscript_disas)("\n");
122 }
123}
#define TRACE_(x)
Definition: compat.h:76
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
@ ARG_DBL
Definition: engine.h:119
static void dump_instr_arg(instr_arg_type_t type, instr_arg_t *arg)
Definition: compile.c:86
jsop_t op
Definition: engine.h:127
double dbl
Definition: engine.h:130

Referenced by compile_function(), and compile_script().

◆ dump_instr_arg()

static void dump_instr_arg ( instr_arg_type_t  type,
instr_arg_t arg 
)
static

Definition at line 86 of file compile.c.

87{
88 switch(type) {
89 case ARG_STR:
90 TRACE_(jscript_disas)("\t%s", debugstr_jsstr(arg->str));
91 break;
92 case ARG_BSTR:
93 TRACE_(jscript_disas)("\t%s", debugstr_wn(arg->bstr, SysStringLen(arg->bstr)));
94 break;
95 case ARG_INT:
96 TRACE_(jscript_disas)("\t%d", arg->uint);
97 break;
98 case ARG_UINT:
99 case ARG_ADDR:
100 TRACE_(jscript_disas)("\t%u", arg->uint);
101 break;
102 case ARG_FUNC:
103 case ARG_NONE:
104 break;
106 }
107}
#define ARG_NONE
Definition: amlcode.h:216
@ ARG_INT
Definition: engine.h:121
@ ARG_ADDR
Definition: engine.h:117
@ ARG_BSTR
Definition: engine.h:118
@ ARG_FUNC
Definition: engine.h:120
@ ARG_STR
Definition: engine.h:122
@ ARG_UINT
Definition: engine.h:123
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
const char * debugstr_jsstr(jsstr_t *str)
Definition: jsstr.c:37
#define debugstr_wn
Definition: kernel32.h:33
UINT WINAPI SysStringLen(BSTR str)
Definition: oleaut.c:196

Referenced by dump_code().

◆ emit_identifier()

static HRESULT emit_identifier ( compiler_ctx_t ctx,
const WCHAR identifier 
)
static

Definition at line 453 of file compile.c.

454{
455 int local_ref;
456 if(bind_local(ctx, identifier, &local_ref))
457 return push_instr_int(ctx, OP_local, local_ref);
458 return push_instr_bstr(ctx, OP_ident, identifier);
459}
static BOOL bind_local(compiler_ctx_t *ctx, const WCHAR *identifier, int *ret_ref)
Definition: compile.c:427

Referenced by compile_expression().

◆ emit_identifier_ref()

static HRESULT emit_identifier_ref ( compiler_ctx_t ctx,
const WCHAR identifier,
unsigned  flags 
)
static

Definition at line 445 of file compile.c.

446{
447 int local_ref;
448 if(bind_local(ctx, identifier, &local_ref))
449 return push_instr_int(ctx, OP_local_ref, local_ref);
450 return push_instr_bstr_uint(ctx, OP_identid, identifier, flags);
451}
static HRESULT push_instr_bstr_uint(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg1, unsigned arg2)
Definition: compile.c:290

Referenced by compile_forin_statement(), compile_memberid_expression(), and compile_variable_list().

◆ ensure_bstr_slot()

static BOOL ensure_bstr_slot ( compiler_ctx_t ctx)
static

Definition at line 166 of file compile.c.

167{
168 if(!ctx->code->bstr_pool_size) {
169 ctx->code->bstr_pool = heap_alloc(8 * sizeof(BSTR));
170 if(!ctx->code->bstr_pool)
171 return FALSE;
172 ctx->code->bstr_pool_size = 8;
173 }else if(ctx->code->bstr_pool_size == ctx->code->bstr_cnt) {
174 BSTR *new_pool;
175
176 new_pool = heap_realloc(ctx->code->bstr_pool, ctx->code->bstr_pool_size*2*sizeof(BSTR));
177 if(!new_pool)
178 return FALSE;
179
180 ctx->code->bstr_pool = new_pool;
181 ctx->code->bstr_pool_size *= 2;
182 }
183
184 return TRUE;
185}

Referenced by compiler_alloc_bstr(), and compiler_alloc_bstr_len().

◆ find_local()

static function_local_t * find_local ( compiler_ctx_t ctx,
const WCHAR name 
)
inlinestatic

Definition at line 1842 of file compile.c.

1843{
1844 struct wine_rb_entry *entry = wine_rb_get(&ctx->locals, name);
1846}
#define WINE_RB_ENTRY_VALUE(element, type, field)
Definition: rbtree.h:31
static struct wine_rb_entry * wine_rb_get(const struct wine_rb_tree *tree, const void *key)
Definition: rbtree.h:203
Definition: rbtree.h:36

Referenced by alloc_variable(), and compile_function().

◆ function_local_cmp()

static int function_local_cmp ( const void key,
const struct wine_rb_entry entry 
)
static

Definition at line 1836 of file compile.c.

1837{
1839 return wcscmp(key, local->name);
1840}
Definition: copy.c:22

Referenced by compile_function().

◆ init_code()

static HRESULT init_code ( compiler_ctx_t compiler,
const WCHAR source 
)
static

Definition at line 2246 of file compile.c.

2247{
2248 compiler->code = heap_alloc_zero(sizeof(bytecode_t));
2249 if(!compiler->code)
2250 return E_OUTOFMEMORY;
2251
2252 compiler->code->ref = 1;
2253 heap_pool_init(&compiler->code->heap);
2254
2255 compiler->code->source = heap_strdupW(source);
2256 if(!compiler->code->source) {
2257 release_bytecode(compiler->code);
2258 return E_OUTOFMEMORY;
2259 }
2260
2261 compiler->code->instrs = heap_alloc(64 * sizeof(instr_t));
2262 if(!compiler->code->instrs) {
2263 release_bytecode(compiler->code);
2264 return E_OUTOFMEMORY;
2265 }
2266
2267 compiler->code_size = 64;
2268 compiler->code_off = 1;
2269 return S_OK;
2270}
static WCHAR * heap_strdupW(const WCHAR *str)
Definition: edit.c:4312
instr_t * instrs
Definition: engine.h:175
LONG ref
Definition: engine.h:173
heap_pool_t heap
Definition: engine.h:176
unsigned code_size
Definition: compile.c:58
unsigned code_off
Definition: compile.c:57

Referenced by compile_script().

◆ instr_ptr()

◆ is_loop_statement()

static BOOL is_loop_statement ( statement_type_t  type)
inlinestatic

Definition at line 1107 of file compile.c.

1108{
1109 return type == STAT_FOR || type == STAT_FORIN || type == STAT_WHILE;
1110}

Referenced by compile_continue_statement().

◆ is_memberid_expr()

static BOOL is_memberid_expr ( expression_type_t  type)
inlinestatic

◆ label_set_addr()

◆ literal_as_string()

static HRESULT literal_as_string ( compiler_ctx_t ctx,
literal_t literal,
jsstr_t **  str 
)
static

Definition at line 851 of file compile.c.

852{
853 switch(literal->type) {
854 case LT_STRING:
855 *str = literal->u.str;
856 break;
857 case LT_DOUBLE:
858 return double_to_string(literal->u.dval, str);
860 }
861
862 return *str ? S_OK : E_OUTOFMEMORY;
863}
HRESULT double_to_string(double, jsstr_t **) DECLSPEC_HIDDEN
Definition: jsutils.c:727

Referenced by compile_object_literal().

◆ parse_arguments()

static HRESULT parse_arguments ( compiler_ctx_t ctx,
const WCHAR args,
BSTR arg_array,
unsigned args_size 
)
static

Definition at line 2391 of file compile.c.

2392{
2393 const WCHAR *ptr = args, *ptr2;
2394 unsigned arg_cnt = 0;
2395
2396 while(iswspace(*ptr))
2397 ptr++;
2398 if(!*ptr) {
2399 if(args_size)
2400 *args_size = 0;
2401 return S_OK;
2402 }
2403
2404 while(1) {
2405 if(!iswalpha(*ptr) && *ptr != '_') {
2406 FIXME("expected alpha or '_': %s\n", debugstr_w(ptr));
2407 return E_FAIL;
2408 }
2409
2410 ptr2 = ptr;
2411 while(iswalnum(*ptr) || *ptr == '_')
2412 ptr++;
2413
2414 if(*ptr && *ptr != ',' && !iswspace(*ptr)) {
2415 FIXME("unexpected har %s\n", debugstr_w(ptr));
2416 return E_FAIL;
2417 }
2418
2419 if(arg_array) {
2420 arg_array[arg_cnt] = compiler_alloc_bstr_len(ctx, ptr2, ptr-ptr2);
2421 if(!arg_array[arg_cnt])
2422 return E_OUTOFMEMORY;
2423 }
2424 arg_cnt++;
2425
2426 while(iswspace(*ptr))
2427 ptr++;
2428 if(!*ptr)
2429 break;
2430 if(*ptr != ',') {
2431 FIXME("expected ',': %s\n", debugstr_w(ptr));
2432 return E_FAIL;
2433 }
2434
2435 ptr++;
2436 while(iswspace(*ptr))
2437 ptr++;
2438 }
2439
2440 if(args_size)
2441 *args_size = arg_cnt;
2442 return S_OK;
2443}
#define FIXME(fmt,...)
Definition: precomp.h:53
#define iswspace(_c)
Definition: ctype.h:669
#define iswalnum(_c)
Definition: ctype.h:671
#define iswalpha(_c)
Definition: ctype.h:664
static BSTR compiler_alloc_bstr_len(compiler_ctx_t *ctx, const WCHAR *str, size_t len)
Definition: compile.c:199
static PVOID ptr
Definition: dispmode.c:27
#define args
Definition: format.c:66

Referenced by compile_arguments().

◆ pop_to_stat()

static HRESULT pop_to_stat ( compiler_ctx_t ctx,
statement_ctx_t stat_ctx 
)
static

Definition at line 1386 of file compile.c.

1387{
1388 unsigned stack_pop = 0;
1389 statement_ctx_t *iter;
1390 HRESULT hres;
1391
1392 for(iter = ctx->stat_ctx; iter != stat_ctx; iter = iter->next) {
1393 if(iter->using_scope && !push_instr(ctx, OP_pop_scope))
1394 return E_OUTOFMEMORY;
1395 if(iter->using_except) {
1396 if(stack_pop) {
1397 hres = push_instr_uint(ctx, OP_pop, stack_pop);
1398 if(FAILED(hres))
1399 return hres;
1400 stack_pop = 0;
1401 }
1402 hres = push_instr_uint(ctx, OP_pop_except, ctx->code_off+1);
1403 if(FAILED(hres))
1404 return hres;
1405 }
1406 stack_pop += iter->stack_use;
1407 }
1408
1409 if(stack_pop) {
1410 hres = push_instr_uint(ctx, OP_pop, stack_pop);
1411 if(FAILED(hres))
1412 return hres;
1413 }
1414
1415 return S_OK;
1416}
static jsval_t stack_pop(script_ctx_t *ctx)
Definition: engine.c:129
unsigned stack_use
Definition: compile.c:33

Referenced by compile_break_statement(), compile_continue_statement(), and compile_return_statement().

◆ push_instr()

static unsigned push_instr ( compiler_ctx_t ctx,
jsop_t  op 
)
static

◆ push_instr_bstr()

static HRESULT push_instr_bstr ( compiler_ctx_t ctx,
jsop_t  op,
const WCHAR arg 
)
static

Definition at line 273 of file compile.c.

274{
275 unsigned instr;
276 WCHAR *str;
277
279 if(!str)
280 return E_OUTOFMEMORY;
281
282 instr = push_instr(ctx, op);
283 if(!instr)
284 return E_OUTOFMEMORY;
285
286 instr_ptr(ctx, instr)->u.arg->bstr = str;
287 return S_OK;
288}
BSTR bstr
Definition: engine.h:109

Referenced by compile_const_statement(), compile_delete_expression(), compile_member_expression(), compile_try_statement(), compile_typeof_expression(), and emit_identifier().

◆ push_instr_bstr_uint()

static HRESULT push_instr_bstr_uint ( compiler_ctx_t ctx,
jsop_t  op,
const WCHAR arg1,
unsigned  arg2 
)
static

Definition at line 290 of file compile.c.

291{
292 unsigned instr;
293 WCHAR *str;
294
296 if(!str)
297 return E_OUTOFMEMORY;
298
299 instr = push_instr(ctx, op);
300 if(!instr)
301 return E_OUTOFMEMORY;
302
303 instr_ptr(ctx, instr)->u.arg[0].bstr = str;
304 instr_ptr(ctx, instr)->u.arg[1].uint = arg2;
305 return S_OK;
306}
GLuint GLuint GLuint GLuint arg1
Definition: glext.h:9513
GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg2
Definition: glext.h:9514

Referenced by compile_assignment(), compile_dim_statement(), compile_member_expression(), and emit_identifier_ref().

◆ push_instr_double()

static HRESULT push_instr_double ( compiler_ctx_t ctx,
jsop_t  op,
double  arg 
)
static

Definition at line 326 of file compile.c.

327{
328 unsigned instr;
329
330 instr = push_instr(ctx, op);
331 if(!instr)
332 return E_OUTOFMEMORY;
333
334 instr_ptr(ctx, instr)->u.dbl = arg;
335 return S_OK;
336}

Referenced by compile_expression(), and compile_literal().

◆ push_instr_int()

static HRESULT push_instr_int ( compiler_ctx_t ctx,
jsop_t  op,
LONG  arg 
)
static

Definition at line 236 of file compile.c.

237{
238 unsigned instr;
239
240 instr = push_instr(ctx, op);
241 if(!instr)
242 return E_OUTOFMEMORY;
243
244 instr_ptr(ctx, instr)->u.arg->lng = arg;
245 return S_OK;
246}

Referenced by compile_expression(), compile_forin_statement(), compile_forto_statement(), compile_increment_expression(), compile_literal(), compile_onerror_statement(), emit_identifier(), and emit_identifier_ref().

◆ push_instr_str()

static HRESULT push_instr_str ( compiler_ctx_t ctx,
jsop_t  op,
jsstr_t str 
)
static

Definition at line 248 of file compile.c.

249{
250 unsigned instr;
251
252 instr = push_instr(ctx, op);
253 if(!instr)
254 return E_OUTOFMEMORY;
255
256 instr_ptr(ctx, instr)->u.arg->str = str;
257 return S_OK;
258}
jsstr_t * str
Definition: engine.h:111

Referenced by compile_delete_expression(), compile_expression(), compile_literal(), and compile_memberid_expression().

◆ push_instr_str_uint()

static HRESULT push_instr_str_uint ( compiler_ctx_t ctx,
jsop_t  op,
jsstr_t str,
unsigned  arg2 
)
static

Definition at line 260 of file compile.c.

261{
262 unsigned instr;
263
264 instr = push_instr(ctx, op);
265 if(!instr)
266 return E_OUTOFMEMORY;
267
268 instr_ptr(ctx, instr)->u.arg[0].str = str;
269 instr_ptr(ctx, instr)->u.arg[1].uint = arg2;
270 return S_OK;
271}

Referenced by compile_literal(), and compile_object_literal().

◆ push_instr_uint()

◆ push_instr_uint_str()

static HRESULT push_instr_uint_str ( compiler_ctx_t ctx,
jsop_t  op,
unsigned  arg1,
const WCHAR arg2 
)
static

Definition at line 308 of file compile.c.

309{
310 unsigned instr;
311 jsstr_t *str;
312
314 if(!str)
315 return E_OUTOFMEMORY;
316
317 instr = push_instr(ctx, op);
318 if(!instr)
319 return E_OUTOFMEMORY;
320
321 instr_ptr(ctx, instr)->u.arg[0].uint = arg1;
322 instr_ptr(ctx, instr)->u.arg[1].str = str;
323 return S_OK;
324}

Referenced by compile_delete_expression().

◆ release_bytecode()

void release_bytecode ( bytecode_t code)

Definition at line 2226 of file compile.c.

2227{
2228 unsigned i;
2229
2230 if(--code->ref)
2231 return;
2232
2233 for(i=0; i < code->bstr_cnt; i++)
2234 SysFreeString(code->bstr_pool[i]);
2235 for(i=0; i < code->str_cnt; i++)
2236 jsstr_release(code->str_pool[i]);
2237
2238 heap_free(code->source);
2239 heap_pool_free(&code->heap);
2240 heap_free(code->bstr_pool);
2241 heap_free(code->str_pool);
2242 heap_free(code->instrs);
2243 heap_free(code);
2244}
static void jsstr_release(jsstr_t *str)
Definition: jsstr.h:110
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271

Referenced by clear_script_queue(), compile_script(), construct_function(), exec_source(), init_code(), InterpretedFunction_destructor(), JScriptParse_ParseScriptText(), JScriptParseProcedure_ParseProcedureText(), JSGlobal_eval(), and pop_call_frame().

◆ resolve_labels()

static void resolve_labels ( compiler_ctx_t ctx,
unsigned  off 
)
static

Definition at line 2211 of file compile.c.

2212{
2213 instr_t *instr;
2214
2215 for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->code_off; instr++) {
2216 if(instr_info[instr->op].arg1_type == ARG_ADDR && (instr->u.arg->uint & LABEL_FLAG)) {
2217 assert((instr->u.arg->uint & ~LABEL_FLAG) < ctx->labels_cnt);
2218 instr->u.arg->uint = ctx->labels[instr->u.arg->uint & ~LABEL_FLAG];
2219 }
2220 assert(instr_info[instr->op].arg2_type != ARG_ADDR);
2221 }
2222
2223 ctx->labels_cnt = 0;
2224}

Referenced by compile_func(), and compile_function().

◆ set_arg_uint()

static void set_arg_uint ( compiler_ctx_t ctx,
unsigned  instr,
unsigned  arg 
)
inlinestatic

◆ visit_block_statement()

static HRESULT visit_block_statement ( compiler_ctx_t ctx,
statement_t iter 
)
static

Definition at line 2037 of file compile.c.

2038{
2039 HRESULT hres;
2040
2041 while(iter) {
2042 hres = visit_statement(ctx, iter);
2043 if(FAILED(hres))
2044 return hres;
2045
2046 iter = iter->next;
2047 }
2048
2049 return S_OK;
2050}
static HRESULT visit_statement(compiler_ctx_t *, statement_t *)
Definition: compile.c:2052

Referenced by compile_function(), and visit_statement().

◆ visit_expression()

static HRESULT visit_expression ( compiler_ctx_t ctx,
expression_t expr 
)
static

Definition at line 1886 of file compile.c.

1887{
1888 HRESULT hres = S_OK;
1889
1890 switch(expr->type) {
1891 case EXPR_ADD:
1892 case EXPR_AND:
1893 case EXPR_ARRAY:
1894 case EXPR_ASSIGN:
1895 case EXPR_ASSIGNADD:
1896 case EXPR_ASSIGNAND:
1897 case EXPR_ASSIGNSUB:
1898 case EXPR_ASSIGNMUL:
1899 case EXPR_ASSIGNDIV:
1900 case EXPR_ASSIGNMOD:
1901 case EXPR_ASSIGNOR:
1902 case EXPR_ASSIGNLSHIFT:
1903 case EXPR_ASSIGNRSHIFT:
1904 case EXPR_ASSIGNRRSHIFT:
1905 case EXPR_ASSIGNXOR:
1906 case EXPR_BAND:
1907 case EXPR_BOR:
1908 case EXPR_COMMA:
1909 case EXPR_DIV:
1910 case EXPR_EQ:
1911 case EXPR_EQEQ:
1912 case EXPR_GREATER:
1913 case EXPR_GREATEREQ:
1914 case EXPR_IN:
1915 case EXPR_INSTANCEOF:
1916 case EXPR_LESS:
1917 case EXPR_LESSEQ:
1918 case EXPR_LSHIFT:
1919 case EXPR_MOD:
1920 case EXPR_MUL:
1921 case EXPR_NOTEQ:
1922 case EXPR_NOTEQEQ:
1923 case EXPR_OR:
1924 case EXPR_RSHIFT:
1925 case EXPR_RRSHIFT:
1926 case EXPR_SUB:
1927 case EXPR_BXOR: {
1929
1930 hres = visit_expression(ctx, binary_expr->expression1);
1931 if(FAILED(hres))
1932 return hres;
1933
1934 hres = visit_expression(ctx, binary_expr->expression2);
1935 break;
1936 }
1937 case EXPR_BITNEG:
1938 case EXPR_DELETE:
1939 case EXPR_LOGNEG:
1940 case EXPR_MINUS:
1941 case EXPR_PLUS:
1942 case EXPR_POSTDEC:
1943 case EXPR_POSTINC:
1944 case EXPR_PREDEC:
1945 case EXPR_PREINC:
1946 case EXPR_TYPEOF:
1947 case EXPR_VOID:
1948 hres = visit_expression(ctx, ((unary_expression_t*)expr)->expression);
1949 break;
1950 case EXPR_IDENT:
1951 case EXPR_LITERAL:
1952 case EXPR_THIS:
1953 break;
1954 case EXPR_ARRAYLIT: {
1956 array_element_t *iter;
1957
1958 for(iter = array_expr->element_list; iter; iter = iter->next) {
1959 hres = visit_expression(ctx, iter->expr);
1960 if(FAILED(hres))
1961 return hres;
1962 }
1963 break;
1964 }
1965 case EXPR_CALL:
1966 case EXPR_NEW: {
1968 argument_t *arg;
1969
1970 hres = visit_expression(ctx, call_expr->expression);
1971 if(FAILED(hres))
1972 return hres;
1973
1974 for(arg = call_expr->argument_list; arg; arg = arg->next) {
1975 hres = visit_expression(ctx, arg->expr);
1976 if(FAILED(hres))
1977 return hres;
1978 }
1979 break;
1980 }
1981 case EXPR_COND: {
1983
1984 hres = visit_expression(ctx, cond_expr->expression);
1985 if(FAILED(hres))
1986 return hres;
1987
1989 if(FAILED(hres))
1990 return hres;
1991
1993 break;
1994 }
1995 case EXPR_FUNC:
1997 break;
1998 case EXPR_MEMBER:
1999 hres = visit_expression(ctx, ((member_expression_t*)expr)->expression);
2000 break;
2001 case EXPR_PROPVAL: {
2003 for(iter = ((property_value_expression_t*)expr)->property_list; iter; iter = iter->next) {
2004 hres = visit_expression(ctx, iter->value);
2005 if(FAILED(hres))
2006 return hres;
2007 }
2008 break;
2009 }
2011 }
2012
2013 return hres;
2014}
static HRESULT visit_function_expression(compiler_ctx_t *ctx, function_expression_t *expr)
Definition: compile.c:1877
static HRESULT visit_expression(compiler_ctx_t *ctx, expression_t *expr)
Definition: compile.c:1886
array_element_t * element_list
Definition: parser.h:359
expression_t * true_expression
Definition: parser.h:318
expression_t * expression
Definition: parser.h:317
expression_t * false_expression
Definition: parser.h:319

Referenced by visit_expression(), visit_statement(), and visit_variable_list().

◆ visit_function_expression()

static HRESULT visit_function_expression ( compiler_ctx_t ctx,
function_expression_t expr 
)
static

Definition at line 1877 of file compile.c.

1878{
1879 expr->func_id = ctx->func->func_cnt++;
1880 ctx->func_tail = ctx->func_tail ? (ctx->func_tail->next = expr) : (ctx->func_head = expr);
1881
1882 return !expr->identifier || expr->event_target || alloc_variable(ctx, expr->identifier)
1883 ? S_OK : E_OUTOFMEMORY;
1884}
static BOOL alloc_variable(compiler_ctx_t *ctx, const WCHAR *name)
Definition: compile.c:1863

Referenced by visit_expression().

◆ visit_statement()

static HRESULT visit_statement ( compiler_ctx_t ctx,
statement_t stat 
)
static

Definition at line 2052 of file compile.c.

2053{
2054 HRESULT hres = S_OK;
2055
2056 switch(stat->type) {
2057 case STAT_BLOCK:
2059 break;
2060 case STAT_BREAK:
2061 case STAT_CONTINUE:
2062 case STAT_EMPTY:
2063 break;
2064 case STAT_EXPR:
2065 case STAT_RETURN:
2066 case STAT_THROW: {
2068 if(expr_stat->expr)
2069 hres = visit_expression(ctx, expr_stat->expr);
2070 break;
2071 }
2072 case STAT_FOR: {
2073 for_statement_t *for_stat = (for_statement_t*)stat;
2074
2075 if(for_stat->variable_list)
2077 else if(for_stat->begin_expr)
2078 hres = visit_expression(ctx, for_stat->begin_expr);
2079 if(FAILED(hres))
2080 break;
2081
2082 if(for_stat->expr) {
2083 hres = visit_expression(ctx, for_stat->expr);
2084 if(FAILED(hres))
2085 break;
2086 }
2087
2088 hres = visit_statement(ctx, for_stat->statement);
2089 if(FAILED(hres))
2090 break;
2091
2092 if(for_stat->end_expr)
2093 hres = visit_expression(ctx, for_stat->end_expr);
2094 break;
2095 }
2096 case STAT_FORIN: {
2098
2099 if(forin_stat->variable) {
2100 hres = visit_variable_list(ctx, forin_stat->variable);
2101 if(FAILED(hres))
2102 break;
2103 }
2104
2105 hres = visit_expression(ctx, forin_stat->in_expr);
2106 if(FAILED(hres))
2107 return hres;
2108
2109 if(forin_stat->expr) {
2110 hres = visit_expression(ctx, forin_stat->expr);
2111 if(FAILED(hres))
2112 return hres;
2113 }
2114
2115 hres = visit_statement(ctx, forin_stat->statement);
2116 break;
2117 }
2118 case STAT_IF: {
2119 if_statement_t *if_stat = (if_statement_t*)stat;
2120
2121 hres = visit_expression(ctx, if_stat->expr);
2122 if(FAILED(hres))
2123 return hres;
2124
2125 hres = visit_statement(ctx, if_stat->if_stat);
2126 if(FAILED(hres))
2127 return hres;
2128
2129 if(if_stat->else_stat)
2130 hres = visit_statement(ctx, if_stat->else_stat);
2131 break;
2132 }
2133 case STAT_LABEL:
2135 break;
2136 case STAT_SWITCH: {
2138 statement_t *stat_iter;
2139 case_clausule_t *iter;
2140
2141 hres = visit_expression(ctx, switch_stat->expr);
2142 if(FAILED(hres))
2143 return hres;
2144
2145 for(iter = switch_stat->case_list; iter; iter = iter->next) {
2146 if(!iter->expr)
2147 continue;
2148 hres = visit_expression(ctx, iter->expr);
2149 if(FAILED(hres))
2150 return hres;
2151 }
2152
2153 for(iter = switch_stat->case_list; iter; iter = iter->next) {
2154 while(iter->next && iter->next->stat == iter->stat)
2155 iter = iter->next;
2156 for(stat_iter = iter->stat; stat_iter && (!iter->next || iter->next->stat != stat_iter);
2157 stat_iter = stat_iter->next) {
2158 hres = visit_statement(ctx, stat_iter);
2159 if(FAILED(hres))
2160 return hres;
2161 }
2162 }
2163 break;
2164 }
2165 case STAT_TRY: {
2166 try_statement_t *try_stat = (try_statement_t*)stat;
2167
2168 hres = visit_statement(ctx, try_stat->try_statement);
2169 if(FAILED(hres))
2170 return hres;
2171
2172 if(try_stat->catch_block) {
2174 if(FAILED(hres))
2175 return hres;
2176 }
2177
2178 if(try_stat->finally_statement)
2180 break;
2181 }
2182 case STAT_VAR:
2183 hres = visit_variable_list(ctx, ((var_statement_t*)stat)->variable_list);
2184 break;
2185 case STAT_WHILE: {
2187
2188 hres = visit_expression(ctx, while_stat->expr);
2189 if(FAILED(hres))
2190 return hres;
2191
2192 hres = visit_statement(ctx, while_stat->statement);
2193 break;
2194 }
2195 case STAT_WITH: {
2196 with_statement_t *with_stat = (with_statement_t*)stat;
2197
2198 hres = visit_expression(ctx, with_stat->expr);
2199 if(FAILED(hres))
2200 return hres;
2201
2202 hres = visit_statement(ctx, with_stat->statement);
2203 break;
2204 }
2206 }
2207
2208 return hres;
2209}
static HRESULT visit_variable_list(compiler_ctx_t *ctx, variable_declaration_t *list)
Definition: compile.c:2016
statement_t * statement
Definition: parser.h:206
expression_t * expr
Definition: parser.h:140
expression_t * expr
Definition: parser.h:161
statement_t * statement
Definition: parser.h:163
expression_t * end_expr
Definition: parser.h:162
expression_t * begin_expr
Definition: parser.h:160
variable_declaration_t * variable_list
Definition: parser.h:159
variable_declaration_t * variable
Definition: parser.h:168
statement_t * statement
Definition: parser.h:171
expression_t * in_expr
Definition: parser.h:170
expression_t * expr
Definition: parser.h:169
statement_t * if_stat
Definition: parser.h:146
expression_t * expr
Definition: parser.h:145
statement_t * else_stat
Definition: parser.h:147
expression_t * expr
Definition: parser.h:200
case_clausule_t * case_list
Definition: parser.h:201
catch_block_t * catch_block
Definition: parser.h:212
statement_t * try_statement
Definition: parser.h:211
statement_t * finally_statement
Definition: parser.h:213
expression_t * expr
Definition: parser.h:153
statement_t * statement
Definition: parser.h:154
expression_t * expr
Definition: parser.h:181
statement_t * statement
Definition: parser.h:182

Referenced by visit_block_statement(), and visit_statement().

◆ visit_variable_list()

static HRESULT visit_variable_list ( compiler_ctx_t ctx,
variable_declaration_t list 
)
static

Definition at line 2016 of file compile.c.

2017{
2019 HRESULT hres;
2020
2021 for(iter = list; iter; iter = iter->next) {
2022 if(!alloc_variable(ctx, iter->identifier))
2023 return E_OUTOFMEMORY;
2024
2025 if(iter->expr) {
2026 hres = visit_expression(ctx, iter->expr);
2027 if(FAILED(hres))
2028 return hres;
2029 }
2030 }
2031
2032 return S_OK;
2033}

Referenced by visit_statement().

◆ WINE_DECLARE_DEBUG_CHANNEL()

WINE_DECLARE_DEBUG_CHANNEL ( jscript_disas  )

◆ WINE_DEFAULT_DEBUG_CHANNEL()

WINE_DEFAULT_DEBUG_CHANNEL ( jscript  )

Variable Documentation

◆ arg1_type

instr_arg_type_t arg1_type

Definition at line 78 of file compile.c.

◆ arg2_type

instr_arg_type_t arg2_type

Definition at line 79 of file compile.c.

◆ 

const struct { ... } instr_info[]
Initial value:
= {
#define X(n,a,b,c)
}
#define OP_LIST
Definition: engine.h:21

◆ op_str

const char* op_str

Definition at line 77 of file compile.c.

Referenced by CShellDispatch::ShellExecute().