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 static HRESULT
compile_interp_fallback(compiler_ctx_t
*ctx
, expression_t
*expr
)
163 instr
= push_instr(ctx
, OP_tree
);
165 return E_OUTOFMEMORY
;
167 instr_ptr(ctx
, instr
)->arg1
.expr
= expr
;
171 static HRESULT
compile_literal(compiler_ctx_t
*ctx
, literal_expression_t
*expr
)
173 literal_t
*literal
= expr
->literal
;
175 switch(literal
->type
) {
177 return push_instr_int(ctx
, OP_bool
, literal
->u
.bval
);
179 return push_instr_double(ctx
, OP_double
, literal
->u
.dval
);
181 return push_instr_int(ctx
, OP_int
, literal
->u
.lval
);
183 return push_instr_str(ctx
, OP_str
, literal
->u
.wstr
);
185 return compile_interp_fallback(ctx
, &expr
->expr
);
189 static HRESULT
compile_expression(compiler_ctx_t
*ctx
, expression_t
*expr
)
193 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
195 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_bneg
);
197 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq2
);
199 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_in
);
201 return compile_literal(ctx
, (literal_expression_t
*)expr
);
203 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_neg
);
205 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq2
);
207 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_tonum
);
209 assert(expr
->eval
!= compiled_expression_eval
);
210 return compile_interp_fallback(ctx
, expr
);
216 void release_bytecode(bytecode_t
*code
)
218 jsheap_free(&code
->heap
);
219 heap_free(code
->instrs
);
223 void release_compiler(compiler_ctx_t
*ctx
)
228 HRESULT
compile_subscript(parser_ctx_t
*parser
, expression_t
*expr
, unsigned *ret_off
)
233 parser
->code
= heap_alloc_zero(sizeof(bytecode_t
));
235 return E_OUTOFMEMORY
;
236 jsheap_init(&parser
->code
->heap
);
239 if(!parser
->compiler
) {
240 parser
->compiler
= heap_alloc_zero(sizeof(compiler_ctx_t
));
241 if(!parser
->compiler
)
242 return E_OUTOFMEMORY
;
244 parser
->compiler
->parser
= parser
;
245 parser
->compiler
->code
= parser
->code
;
248 *ret_off
= parser
->compiler
->code_off
;
249 hres
= compile_expression(parser
->compiler
, expr
);
253 return push_instr(parser
->compiler
, OP_ret
) == -1 ? E_OUTOFMEMORY
: S_OK
;