Esempio n. 1
0
static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal)
{
    switch(literal->type) {
    case LT_BOOL:
        return push_instr_int(ctx, OP_bool, literal->u.bval);
    case LT_DOUBLE:
        return push_instr_double(ctx, OP_double, literal->u.dval);
    case LT_INT:
        return push_instr_int(ctx, OP_int, literal->u.lval);
    case LT_NULL:
        return push_instr(ctx, OP_null) ? S_OK : E_OUTOFMEMORY;
    case LT_STRING:
        return push_instr_str(ctx, OP_str, literal->u.wstr);
    case LT_REGEXP: {
        unsigned instr;
        WCHAR *str;

        str = compiler_alloc(ctx->code, (literal->u.regexp.str_len+1)*sizeof(WCHAR));
        if(!str)
            return E_OUTOFMEMORY;
        memcpy(str, literal->u.regexp.str, literal->u.regexp.str_len*sizeof(WCHAR));
        str[literal->u.regexp.str_len] = 0;

        instr = push_instr(ctx, OP_regexp);
        if(!instr)
            return E_OUTOFMEMORY;

        instr_ptr(ctx, instr)->arg1.str = str;
        instr_ptr(ctx, instr)->arg2.lng = literal->u.regexp.flags;
        return S_OK;
    }
    default:
        assert(0);
    }
}
Esempio n. 2
0
static HRESULT compile_if_statement(compile_ctx_t *ctx, if_statement_t *stat)
{
    unsigned cnd_jmp, endif_label = -1;
    elseif_decl_t *elseif_decl;
    HRESULT hres;

    hres = compile_expression(ctx, stat->expr);
    if(FAILED(hres))
        return hres;

    cnd_jmp = push_instr(ctx, OP_jmp_false);
    if(cnd_jmp == -1)
        return E_OUTOFMEMORY;

    hres = compile_statement(ctx, stat->if_stat);
    if(FAILED(hres))
        return hres;

    if(stat->else_stat || stat->elseifs) {
        endif_label = alloc_label(ctx);
        if(endif_label == -1)
            return E_OUTOFMEMORY;

        hres = push_instr_addr(ctx, OP_jmp, endif_label);
        if(FAILED(hres))
            return hres;
    }

    for(elseif_decl = stat->elseifs; elseif_decl; elseif_decl = elseif_decl->next) {
        instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt;

        hres = compile_expression(ctx, elseif_decl->expr);
        if(FAILED(hres))
            return hres;

        cnd_jmp = push_instr(ctx, OP_jmp_false);
        if(cnd_jmp == -1)
            return E_OUTOFMEMORY;

        hres = compile_statement(ctx, elseif_decl->stat);
        if(FAILED(hres))
            return hres;

        hres = push_instr_addr(ctx, OP_jmp, endif_label);
        if(FAILED(hres))
            return hres;
    }

    instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt;

    if(stat->else_stat) {
        hres = compile_statement(ctx, stat->else_stat);
        if(FAILED(hres))
            return hres;
    }

    if(endif_label != -1)
        label_set_addr(ctx, endif_label);
    return S_OK;
}
Esempio n. 3
0
static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expression_t *expr)
{
    prop_val_t *iter;
    unsigned instr;
    BSTR name;
    HRESULT hres;

    if(!push_instr(ctx, OP_new_obj))
        return E_OUTOFMEMORY;

    for(iter = expr->property_list; iter; iter = iter->next) {
        hres = literal_as_bstr(ctx, iter->name, &name);
        if(FAILED(hres))
            return hres;

        hres = compile_expression(ctx, iter->value);
        if(FAILED(hres))
            return hres;

        instr = push_instr(ctx, OP_obj_prop);
        if(!instr)
            return E_OUTOFMEMORY;

        instr_ptr(ctx, instr)->arg1.bstr = name;
    }

    return S_OK;
}
Esempio n. 4
0
/* ECMA-262 3rd Edition    11.12 */
static HRESULT compile_conditional_expression(compiler_ctx_t *ctx, conditional_expression_t *expr)
{
    unsigned jmp_false, jmp_end;
    HRESULT hres;

    hres = compile_expression(ctx, expr->expression);
    if(FAILED(hres))
        return hres;

    jmp_false = push_instr(ctx, OP_cnd_z);
    if(!jmp_false)
        return E_OUTOFMEMORY;

    hres = compile_expression(ctx, expr->true_expression);
    if(FAILED(hres))
        return hres;

    jmp_end = push_instr(ctx, OP_jmp);
    if(!jmp_end)
        return E_OUTOFMEMORY;

    instr_ptr(ctx, jmp_false)->arg1.uint = ctx->code_off;
    if(!push_instr(ctx, OP_pop))
        return E_OUTOFMEMORY;

    hres = compile_expression(ctx, expr->false_expression);
    if(FAILED(hres))
        return hres;

    instr_ptr(ctx, jmp_end)->arg1.uint = ctx->code_off;
    return S_OK;
}
Esempio n. 5
0
HRESULT compile_subscript_stat(parser_ctx_t *parser, statement_t *stat, BOOL from_eval, unsigned *ret_off)
{
    unsigned off;
    HRESULT hres;

    TRACE("\n");

    hres = init_compiler(parser);
    if(FAILED(hres))
        return hres;

    off = parser->compiler->code_off;
    if(stat->next)
        hres = compile_block_statement(parser->compiler, stat);
    else
        hres = compile_statement(parser->compiler, NULL, stat);
    if(FAILED(hres))
        return hres;

    resolve_labels(parser->compiler, off);

    if(!from_eval && !push_instr(parser->compiler, OP_pop))
        return E_OUTOFMEMORY;
    if(!push_instr(parser->compiler, OP_ret))
        return E_OUTOFMEMORY;

    if(TRACE_ON(jscript_disas))
        dump_code(parser->compiler, off);

    *ret_off = off;
    return S_OK;
}
Esempio n. 6
0
/* ECMA-262 3rd Edition    12.8 */
static HRESULT compile_break_statement(compiler_ctx_t *ctx, branch_statement_t *stat)
{
    statement_ctx_t *pop_ctx;
    HRESULT hres;

    for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
        if(pop_ctx->break_label)
            break;
    }

    if(!pop_ctx) {
        WARN("Break outside loop\n");
        return JS_E_INVALID_BREAK;
    }

    if(stat->identifier)
        return push_instr(ctx, OP_label) ? S_OK : E_OUTOFMEMORY; /* FIXME */

    hres = pop_to_stat(ctx, pop_ctx->next);
    if(FAILED(hres))
        return hres;

    if(!push_instr(ctx, OP_undefined))
        return E_OUTOFMEMORY;

    return push_instr_uint(ctx, OP_jmp, pop_ctx->break_label);
}
Esempio n. 7
0
static HRESULT compile_array_literal(compiler_ctx_t *ctx, array_literal_expression_t *expr)
{
    unsigned i, elem_cnt = expr->length;
    array_element_t *iter;
    HRESULT hres;

    for(iter = expr->element_list; iter; iter = iter->next) {
        elem_cnt += iter->elision+1;

        for(i=0; i < iter->elision; i++) {
            if(!push_instr(ctx, OP_undefined))
                return E_OUTOFMEMORY;
        }

        hres = compile_expression(ctx, iter->expr);
        if(FAILED(hres))
            return hres;
    }

    for(i=0; i < expr->length; i++) {
        if(!push_instr(ctx, OP_undefined))
            return E_OUTOFMEMORY;
    }

    return push_instr_uint(ctx, OP_carray, elem_cnt);
}
Esempio n. 8
0
/* ECMA-262 3rd Edition    12.6.2 */
static HRESULT compile_while_statement(compiler_ctx_t *ctx, while_statement_t *stat)
{
    statement_ctx_t stat_ctx = {0, FALSE, FALSE};
    unsigned jmp_off;
    HRESULT hres;

    stat_ctx.break_label = alloc_label(ctx);
    if(!stat_ctx.break_label)
        return E_OUTOFMEMORY;

    stat_ctx.continue_label = alloc_label(ctx);
    if(!stat_ctx.continue_label)
        return E_OUTOFMEMORY;

    if(!stat->do_while) {
        /* FIXME: avoid */
        if(!push_instr(ctx, OP_undefined))
            return E_OUTOFMEMORY;

        jmp_off = ctx->code_off;
        label_set_addr(ctx, stat_ctx.continue_label);
        hres = compile_expression(ctx, stat->expr);
        if(FAILED(hres))
            return hres;

        hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
        if(FAILED(hres))
            return hres;

        if(!push_instr(ctx, OP_pop))
            return E_OUTOFMEMORY;
    }else {
        jmp_off = ctx->code_off;
    }

    hres = compile_statement(ctx, &stat_ctx, stat->statement);
    if(FAILED(hres))
        return hres;

    if(stat->do_while) {
        label_set_addr(ctx, stat_ctx.continue_label);
        hres = compile_expression(ctx, stat->expr);
        if(FAILED(hres))
            return hres;

        hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
        if(FAILED(hres))
            return hres;

        if(!push_instr(ctx, OP_pop))
            return E_OUTOFMEMORY;
    }

    hres = push_instr_uint(ctx, OP_jmp, jmp_off);
    if(FAILED(hres))
        return hres;

    label_set_addr(ctx, stat_ctx.break_label);
    return S_OK;
}
Esempio n. 9
0
static HRESULT compile_delete_expression(compiler_ctx_t *ctx, unary_expression_t *expr)
{
    HRESULT hres;

    switch(expr->expression->type) {
    case EXPR_ARRAY: {
        binary_expression_t *array_expr = (binary_expression_t*)expr->expression;

        hres = compile_expression(ctx, array_expr->expression1);
        if(FAILED(hres))
            return hres;

        hres = compile_expression(ctx, array_expr->expression2);
        if(FAILED(hres))
            return hres;

        if(!push_instr(ctx, OP_delete))
            return E_OUTOFMEMORY;
        break;
    }
    case EXPR_MEMBER: {
        member_expression_t *member_expr = (member_expression_t*)expr->expression;

        hres = compile_expression(ctx, member_expr->expression);
        if(FAILED(hres))
            return hres;

        /* FIXME: Potential optimization */
        hres = push_instr_str(ctx, OP_str, member_expr->identifier);
        if(FAILED(hres))
            return hres;

        if(!push_instr(ctx, OP_delete))
            return E_OUTOFMEMORY;
        break;
    }
    case EXPR_IDENT:
        return push_instr_bstr(ctx, OP_delete_ident, ((identifier_expression_t*)expr->expression)->identifier);
    default: {
        const WCHAR fixmeW[] = {'F','I','X','M','E',0};

        WARN("invalid delete, unimplemented exception message\n");

        hres = compile_expression(ctx, expr->expression);
        if(FAILED(hres))
            return hres;

        return push_instr_uint_str(ctx, OP_throw_type, JS_E_INVALID_DELETE, fixmeW);
    }
    }

    return S_OK;
}
Esempio n. 10
0
static HRESULT compile_foreach_statement(compile_ctx_t *ctx, foreach_statement_t *stat)
{
    statement_ctx_t loop_ctx = {1};
    unsigned loop_start;
    HRESULT hres;

    hres = compile_expression(ctx, stat->group_expr);
    if(FAILED(hres))
        return hres;

    if(!push_instr(ctx, OP_newenum))
        return E_OUTOFMEMORY;

    loop_start = ctx->instr_cnt;
    if(!(loop_ctx.for_end_label = alloc_label(ctx)))
        return E_OUTOFMEMORY;

    hres = push_instr_uint_bstr(ctx, OP_enumnext, loop_ctx.for_end_label, stat->identifier);
    if(FAILED(hres))
        return hres;

    hres = compile_statement(ctx, &loop_ctx, stat->body);
    if(FAILED(hres))
        return hres;

    hres = push_instr_addr(ctx, OP_jmp, loop_start);
    if(FAILED(hres))
        return hres;

    label_set_addr(ctx, loop_ctx.for_end_label);
    return S_OK;
}
Esempio n. 11
0
File: compile.c Progetto: bpon/wine
HRESULT compile_subscript(parser_ctx_t *parser, expression_t *expr, BOOL do_ret, unsigned *ret_off)
{
    BOOL no_ret = FALSE;
    HRESULT hres;

    if(!parser->code) {
        parser->code = heap_alloc_zero(sizeof(bytecode_t));
        if(!parser->code)
            return E_OUTOFMEMORY;
        jsheap_init(&parser->code->heap);
    }

    if(!parser->compiler) {
        parser->compiler = heap_alloc_zero(sizeof(compiler_ctx_t));
        if(!parser->compiler)
            return E_OUTOFMEMORY;

        parser->compiler->parser = parser;
        parser->compiler->code = parser->code;
    }

    *ret_off = parser->compiler->code_off;
    hres = compile_expression_noret(parser->compiler, expr, do_ret ? NULL : &no_ret);
    if(FAILED(hres))
        return hres;

    return push_instr(parser->compiler, OP_ret) == -1 ? E_OUTOFMEMORY : S_OK;
}
Esempio n. 12
0
/* ECMA-262 3rd Edition    12.13 */
static HRESULT compile_throw_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
{
    HRESULT hres;

    hres = compile_expression(ctx, stat->expr);
    if(FAILED(hres))
        return hres;

    return push_instr(ctx, OP_throw) ? S_OK : E_OUTOFMEMORY;
}
Esempio n. 13
0
/* ECMA-262 3rd Edition    12.2 */
static HRESULT compile_var_statement(compiler_ctx_t *ctx, var_statement_t *stat)
{
    HRESULT hres;

    hres = compile_variable_list(ctx, stat->variable_list);
    if(FAILED(hres))
        return hres;

    return push_instr(ctx, OP_undefined) ? S_OK : E_OUTOFMEMORY;
}
Esempio n. 14
0
static HRESULT compile_unary_expression(compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op)
{
    HRESULT hres;

    hres = compile_expression(ctx, expr->expression);
    if(FAILED(hres))
        return hres;

    return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
}
Esempio n. 15
0
static HRESULT compile_unary_expression(compile_ctx_t *ctx, unary_expression_t *expr, vbsop_t op)
{
    HRESULT hres;

    hres = compile_expression(ctx, expr->subexpr);
    if(FAILED(hres))
        return hres;

    return push_instr(ctx, op) == -1 ? E_OUTOFMEMORY : S_OK;
}
Esempio n. 16
0
static HRESULT push_instr_uint(compiler_ctx_t *ctx, jsop_t op, unsigned arg)
{
    unsigned instr;

    instr = push_instr(ctx, op);
    if(!instr)
        return E_OUTOFMEMORY;

    instr_ptr(ctx, instr)->arg1.uint = arg;
    return S_OK;
}
Esempio n. 17
0
File: compile.c Progetto: bpon/wine
static HRESULT compile_interp_fallback(compiler_ctx_t *ctx, expression_t *expr)
{
    unsigned instr;

    instr = push_instr(ctx, OP_tree);
    if(instr == -1)
        return E_OUTOFMEMORY;

    instr_ptr(ctx, instr)->arg1.expr = expr;
    return S_OK;
}
Esempio n. 18
0
File: compile.c Progetto: bpon/wine
static HRESULT push_instr_int(compiler_ctx_t *ctx, jsop_t op, LONG arg)
{
    unsigned instr;

    instr = push_instr(ctx, op);
    if(instr == -1)
        return E_OUTOFMEMORY;

    instr_ptr(ctx, instr)->arg1.lng = arg;
    return S_OK;
}
Esempio n. 19
0
static HRESULT push_instr_addr(compile_ctx_t *ctx, vbsop_t op, unsigned arg)
{
    unsigned ret;

    ret = push_instr(ctx, op);
    if(ret == -1)
        return E_OUTOFMEMORY;

    instr_ptr(ctx, ret)->arg1.uint = arg;
    return S_OK;
}
Esempio n. 20
0
static HRESULT push_instr_int(compile_ctx_t *ctx, vbsop_t op, LONG arg)
{
    unsigned ret;

    ret = push_instr(ctx, op);
    if(!ret)
        return E_OUTOFMEMORY;

    instr_ptr(ctx, ret)->arg1.lng = arg;
    return S_OK;
}
Esempio n. 21
0
static HRESULT pop_to_stat(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx)
{
    unsigned stack_pop = 0;
    statement_ctx_t *iter;

    for(iter = ctx->stat_ctx; iter != stat_ctx; iter = iter->next) {
        if(iter->using_scope && !push_instr(ctx, OP_pop_scope))
            return E_OUTOFMEMORY;
        if(iter->using_except && !push_instr(ctx, OP_pop_except))
            return E_OUTOFMEMORY;
        stack_pop += iter->stack_use;
    }

    /* FIXME: optimize */
    while(stack_pop--) {
        if(!push_instr(ctx, OP_pop))
            return E_OUTOFMEMORY;
    }

    return S_OK;
}
Esempio n. 22
0
/* ECMA-262 3rd Edition    12.10 */
static HRESULT compile_with_statement(compiler_ctx_t *ctx, with_statement_t *stat)
{
    statement_ctx_t stat_ctx = {0, TRUE, FALSE};
    HRESULT hres;

    hres = compile_expression(ctx, stat->expr);
    if(FAILED(hres))
        return hres;

    if(!push_instr(ctx, OP_push_scope))
        return E_OUTOFMEMORY;

    hres = compile_statement(ctx, &stat_ctx, stat->statement);
    if(FAILED(hres))
        return hres;

    if(!push_instr(ctx, OP_pop_scope))
        return E_OUTOFMEMORY;

    return S_OK;
}
Esempio n. 23
0
/* ECMA-262 3rd Edition    11.14 */
static HRESULT compile_comma_expression(compiler_ctx_t *ctx, binary_expression_t *expr)
{
    HRESULT hres;

    hres = compile_expression(ctx, expr->expression1);
    if(FAILED(hres))
        return hres;

    if(!push_instr(ctx, OP_pop))
        return E_OUTOFMEMORY;

    return compile_expression(ctx, expr->expression2);
}
Esempio n. 24
0
static HRESULT compile_assign_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
{
    HRESULT hres;

    if(!is_memberid_expr(expr->expression1->type)) {
        hres = compile_expression(ctx, expr->expression1);
        if(FAILED(hres))
            return hres;

        hres = compile_expression(ctx, expr->expression2);
        if(FAILED(hres))
            return hres;

        if(op != OP_LAST && !push_instr(ctx, op))
            return E_OUTOFMEMORY;

        return push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
    }

    hres = compile_memberid_expression(ctx, expr->expression1, fdexNameEnsure);
    if(FAILED(hres))
        return hres;

    if(op != OP_LAST && !push_instr(ctx, OP_refval))
        return E_OUTOFMEMORY;

    hres = compile_expression(ctx, expr->expression2);
    if(FAILED(hres))
        return hres;

    if(op != OP_LAST && !push_instr(ctx, op))
        return E_OUTOFMEMORY;

    if(!push_instr(ctx, OP_assign))
        return E_OUTOFMEMORY;

    return S_OK;
}
Esempio n. 25
0
static HRESULT compile_binary_expression(compile_ctx_t *ctx, binary_expression_t *expr, vbsop_t op)
{
    HRESULT hres;

    hres = compile_expression(ctx, expr->left);
    if(FAILED(hres))
        return hres;

    hres = compile_expression(ctx, expr->right);
    if(FAILED(hres))
        return hres;

    return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
}
Esempio n. 26
0
/* ECMA-262 3rd Edition    12.1 */
static HRESULT compile_block_statement(compiler_ctx_t *ctx, statement_t *iter)
{
    HRESULT hres;

    /* FIXME: do it only if needed */
    if(!iter)
        return push_instr(ctx, OP_undefined) ? S_OK : E_OUTOFMEMORY;

    while(1) {
        hres = compile_statement(ctx, NULL, iter);
        if(FAILED(hres))
            return hres;

        iter = iter->next;
        if(!iter)
            break;

        if(!push_instr(ctx, OP_pop))
            return E_OUTOFMEMORY;
    }

    return S_OK;
}
Esempio n. 27
0
File: compile.c Progetto: bpon/wine
static HRESULT compile_binary_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
{
    HRESULT hres;

    hres = compile_expression(ctx, expr->expression1);
    if(FAILED(hres))
        return hres;

    hres = compile_expression(ctx, expr->expression2);
    if(FAILED(hres))
        return hres;

    return push_instr(ctx, op) == -1 ? E_OUTOFMEMORY : S_OK;
}
Esempio n. 28
0
/* ECMA-262 3rd Edition    12.5 */
static HRESULT compile_if_statement(compiler_ctx_t *ctx, if_statement_t *stat)
{
    unsigned jmp_else, jmp_end;
    HRESULT hres;

    hres = compile_expression(ctx, stat->expr);
    if(FAILED(hres))
        return hres;

    jmp_else = push_instr(ctx, OP_jmp_z);
    if(!jmp_else)
        return E_OUTOFMEMORY;

    hres = compile_statement(ctx, NULL, stat->if_stat);
    if(FAILED(hres))
        return hres;

    jmp_end = push_instr(ctx, OP_jmp);
    if(!jmp_end)
        return E_OUTOFMEMORY;

    instr_ptr(ctx, jmp_else)->arg1.uint = ctx->code_off;

    if(stat->else_stat) {
        hres = compile_statement(ctx, NULL, stat->else_stat);
        if(FAILED(hres))
            return hres;
    }else {
        /* FIXME: We could sometimes avoid it */
        if(!push_instr(ctx, OP_undefined))
            return E_OUTOFMEMORY;
    }

    instr_ptr(ctx, jmp_end)->arg1.uint = ctx->code_off;
    return S_OK;
}
Esempio n. 29
0
/* ECMA-262 3rd Edition    12.4 */
static HRESULT compile_expression_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
{
    BOOL no_ret = FALSE;
    HRESULT hres;

    hres = compile_expression_noret(ctx, stat->expr, &no_ret);
    if(FAILED(hres))
        return hres;

    /* FIXME: that's a big potential optimization */
    if(no_ret && !push_instr(ctx, OP_undefined))
        return E_OUTOFMEMORY;

    return S_OK;
}
Esempio n. 30
0
static HRESULT compile_function_expression(compiler_ctx_t *ctx, function_expression_t *expr)
{
    unsigned instr;

    /* FIXME: not exactly right */
    if(expr->identifier)
        return push_instr_bstr(ctx, OP_ident, expr->identifier);

    instr = push_instr(ctx, OP_func);
    if(!instr)
        return E_OUTOFMEMORY;

    instr_ptr(ctx, instr)->arg1.func = expr;
    return S_OK;
}