2 * Copyright 2011 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
29 struct _compiler_ctx_t {
37 static HRESULT compile_expression(compiler_ctx_t*,expression_t*);
39 static inline void *compiler_alloc(bytecode_t *code, size_t size)
41 return jsheap_alloc(&code->heap, size);
44 static WCHAR *compiler_alloc_string(bytecode_t *code, const WCHAR *str)
49 size = (strlenW(str)+1)*sizeof(WCHAR);
50 ret = compiler_alloc(code, size);
52 memcpy(ret, str, size);
56 static unsigned push_instr(compiler_ctx_t *ctx, jsop_t op)
58 assert(ctx->code_size >= ctx->code_off);
61 ctx->code->instrs = heap_alloc(64 * sizeof(instr_t));
62 if(!ctx->code->instrs)
65 }else if(ctx->code_size == ctx->code_off) {
68 new_instrs = heap_realloc(ctx->code->instrs, ctx->code_size*2*sizeof(instr_t));
72 ctx->code->instrs = new_instrs;
76 ctx->code->instrs[ctx->code_off].op = op;
77 return ctx->code_off++;
80 static inline instr_t *instr_ptr(compiler_ctx_t *ctx, unsigned off)
82 assert(off < ctx->code_off);
83 return ctx->code->instrs + off;
86 static HRESULT push_instr_int(compiler_ctx_t *ctx, jsop_t op, LONG arg)
90 instr = push_instr(ctx, op);
94 instr_ptr(ctx, instr)->arg1.lng = arg;
98 static HRESULT push_instr_str(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg)
103 str = compiler_alloc_string(ctx->code, arg);
105 return E_OUTOFMEMORY;
107 instr = push_instr(ctx, op);
109 return E_OUTOFMEMORY;
111 instr_ptr(ctx, instr)->arg1.str = str;
115 static HRESULT push_instr_double(compiler_ctx_t *ctx, jsop_t op, double arg)
120 dbl = compiler_alloc(ctx->code, sizeof(arg));
122 return E_OUTOFMEMORY;
125 instr = push_instr(ctx, op);
127 return E_OUTOFMEMORY;
129 instr_ptr(ctx, instr)->arg1.dbl = dbl;
133 static HRESULT compile_binary_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
137 hres = compile_expression(ctx, expr->expression1);
141 hres = compile_expression(ctx, expr->expression2);
145 return push_instr(ctx, op) == -1 ? E_OUTOFMEMORY : S_OK;
148 static HRESULT compile_unary_expression(compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op)
152 hres = compile_expression(ctx, expr->expression);
156 return push_instr(ctx, op) == -1 ? E_OUTOFMEMORY : S_OK;
159 /* ECMA-262 3rd Edition 11.14 */
160 static HRESULT compile_comma_expression(compiler_ctx_t *ctx, binary_expression_t *expr)
164 hres = compile_expression(ctx, expr->expression1);
168 if(push_instr(ctx, OP_pop) == -1)
169 return E_OUTOFMEMORY;
171 return compile_expression(ctx, expr->expression2);
174 /* ECMA-262 3rd Edition 11.11 */
175 static HRESULT compile_logical_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
180 hres = compile_expression(ctx, expr->expression1);
184 instr = push_instr(ctx, op);
186 return E_OUTOFMEMORY;
188 hres = compile_expression(ctx, expr->expression2);
192 instr_ptr(ctx, instr)->arg1.uint = ctx->code_off;
196 static HRESULT compile_interp_fallback(compiler_ctx_t *ctx, expression_t *expr)
200 instr = push_instr(ctx, OP_tree);
202 return E_OUTOFMEMORY;
204 instr_ptr(ctx, instr)->arg1.expr = expr;
208 static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal)
210 switch(literal->type) {
212 return push_instr_int(ctx, OP_bool, literal->u.bval);
214 return push_instr_double(ctx, OP_double, literal->u.dval);
216 return push_instr_int(ctx, OP_int, literal->u.lval);
218 return push_instr(ctx, OP_null);
220 return push_instr_str(ctx, OP_str, literal->u.wstr);
225 str = compiler_alloc(ctx->code, (literal->u.regexp.str_len+1)*sizeof(WCHAR));
227 return E_OUTOFMEMORY;
228 memcpy(str, literal->u.regexp.str, literal->u.regexp.str_len*sizeof(WCHAR));
229 str[literal->u.regexp.str_len] = 0;
231 instr = push_instr(ctx, OP_regexp);
233 return E_OUTOFMEMORY;
235 instr_ptr(ctx, instr)->arg1.str = str;
236 instr_ptr(ctx, instr)->arg2.lng = literal->u.regexp.flags;
244 static HRESULT compile_expression(compiler_ctx_t *ctx, expression_t *expr)
248 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_add);
250 return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_bneg);
252 return compile_comma_expression(ctx, (binary_expression_t*)expr);
254 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eq);
256 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eq2);
258 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_in);
260 return compile_literal(ctx, ((literal_expression_t*)expr)->literal);
262 return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_neg);
264 return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_minus);
266 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_neq);
268 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_neq2);
270 return compile_logical_expression(ctx, (binary_expression_t*)expr, OP_jmp_nz);
272 return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_tonum);
274 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub);
276 return push_instr(ctx, OP_this) == -1 ? E_OUTOFMEMORY : S_OK;
278 return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_void);
280 assert(expr->eval != compiled_expression_eval);
281 return compile_interp_fallback(ctx, expr);
287 void release_bytecode(bytecode_t *code)
289 jsheap_free(&code->heap);
290 heap_free(code->instrs);
294 void release_compiler(compiler_ctx_t *ctx)
299 HRESULT compile_subscript(parser_ctx_t *parser, expression_t *expr, unsigned *ret_off)
304 parser->code = heap_alloc_zero(sizeof(bytecode_t));
306 return E_OUTOFMEMORY;
307 jsheap_init(&parser->code->heap);
310 if(!parser->compiler) {
311 parser->compiler = heap_alloc_zero(sizeof(compiler_ctx_t));
312 if(!parser->compiler)
313 return E_OUTOFMEMORY;
315 parser->compiler->parser = parser;
316 parser->compiler->code = parser->code;
319 *ret_off = parser->compiler->code_off;
320 hres = compile_expression(parser->compiler, expr);
324 return push_instr(parser->compiler, OP_ret) == -1 ? E_OUTOFMEMORY : S_OK;