1 /*
2  *  ECMAScript compiler.
3  */
4 
5 #if !defined(DUK_JS_COMPILER_H_INCLUDED)
6 #define DUK_JS_COMPILER_H_INCLUDED
7 
8 /* ECMAScript compiler limits */
9 #define DUK_COMPILER_TOKEN_LIMIT           100000000L  /* 1e8: protects against deeply nested inner functions */
10 
11 /* maximum loopcount for peephole optimization */
12 #define DUK_COMPILER_PEEPHOLE_MAXITER      3
13 
14 /* maximum bytecode length in instructions */
15 #define DUK_COMPILER_MAX_BYTECODE_LENGTH   (256L * 1024L * 1024L)  /* 1 GB */
16 
17 /*
18  *  Compiler intermediate values
19  *
20  *  Intermediate values describe either plain values (e.g. strings or
21  *  numbers) or binary operations which have not yet been coerced into
22  *  either a left-hand-side or right-hand-side role (e.g. object property).
23  */
24 
25 #define DUK_IVAL_NONE          0   /* no value */
26 #define DUK_IVAL_PLAIN         1   /* register, constant, or value */
27 #define DUK_IVAL_ARITH         2   /* binary arithmetic; DUK_OP_ADD, DUK_OP_EQ, other binary ops */
28 #define DUK_IVAL_PROP          3   /* property access */
29 #define DUK_IVAL_VAR           4   /* variable access */
30 
31 #define DUK_ISPEC_NONE         0   /* no value */
32 #define DUK_ISPEC_VALUE        1   /* value resides in 'valstack_idx' */
33 #define DUK_ISPEC_REGCONST     2   /* value resides in a register or constant */
34 
35 /* Bit mask which indicates that a regconst is a constant instead of a register.
36  * Chosen so that when a regconst is cast to duk_int32_t, all consts are
37  * negative values.
38  */
39 #define DUK_REGCONST_CONST_MARKER    DUK_INT32_MIN  /* = -0x80000000 */
40 
41 /* Type to represent a reg/const reference during compilation, with <0
42  * indicating a constant.  Some call sites also use -1 to indicate 'none'.
43  */
44 typedef duk_int32_t duk_regconst_t;
45 
46 typedef struct {
47 	duk_small_uint_t t;          /* DUK_ISPEC_XXX */
48 	duk_regconst_t regconst;
49 	duk_idx_t valstack_idx;      /* always set; points to a reserved valstack slot */
50 } duk_ispec;
51 
52 typedef struct {
53 	/*
54 	 *  PLAIN: x1
55 	 *  ARITH: x1 <op> x2
56 	 *  PROP: x1.x2
57 	 *  VAR: x1 (name)
58 	 */
59 
60 	/* XXX: can be optimized for smaller footprint esp. on 32-bit environments */
61 	duk_small_uint_t t;          /* DUK_IVAL_XXX */
62 	duk_small_uint_t op;         /* bytecode opcode for binary ops */
63 	duk_ispec x1;
64 	duk_ispec x2;
65 } duk_ivalue;
66 
67 /*
68  *  Bytecode instruction representation during compilation
69  *
70  *  Contains the actual instruction and (optionally) debug info.
71  */
72 
73 struct duk_compiler_instr {
74 	duk_instr_t ins;
75 #if defined(DUK_USE_PC2LINE)
76 	duk_uint32_t line;
77 #endif
78 };
79 
80 /*
81  *  Compiler state
82  */
83 
84 #define DUK_LABEL_FLAG_ALLOW_BREAK       (1U << 0)
85 #define DUK_LABEL_FLAG_ALLOW_CONTINUE    (1U << 1)
86 
87 #define DUK_DECL_TYPE_VAR                0
88 #define DUK_DECL_TYPE_FUNC               1
89 
90 /* XXX: optimize to 16 bytes */
91 typedef struct {
92 	duk_small_uint_t flags;
93 	duk_int_t label_id;          /* numeric label_id (-1 reserved as marker) */
94 	duk_hstring *h_label;        /* borrowed label name */
95 	duk_int_t catch_depth;       /* catch depth at point of definition */
96 	duk_int_t pc_label;          /* pc of label statement:
97 	                              * pc+1: break jump site
98 	                              * pc+2: continue jump site
99 	                              */
100 
101 	/* Fast jumps (which avoid longjmp) jump directly to the jump sites
102 	 * which are always known even while the iteration/switch statement
103 	 * is still being parsed.  A final peephole pass "straightens out"
104 	 * the jumps.
105 	 */
106 } duk_labelinfo;
107 
108 /* Compiling state of one function, eventually converted to duk_hcompfunc */
109 struct duk_compiler_func {
110 	/* These pointers are at the start of the struct so that they pack
111 	 * nicely.  Mixing pointers and integer values is bad on some
112 	 * platforms (e.g. if int is 32 bits and pointers are 64 bits).
113 	 */
114 
115 	duk_bufwriter_ctx bw_code;          /* bufwriter for code */
116 
117 	duk_hstring *h_name;                /* function name (borrowed reference), ends up in _name */
118 	/* h_code: held in bw_code */
119 	duk_hobject *h_consts;              /* array */
120 	duk_hobject *h_funcs;               /* array of function templates: [func1, offset1, line1, func2, offset2, line2]
121 	                                     * offset/line points to closing brace to allow skipping on pass 2
122 	                                     */
123 	duk_hobject *h_decls;               /* array of declarations: [ name1, val1, name2, val2, ... ]
124 	                                     * valN = (typeN) | (fnum << 8), where fnum is inner func number (0 for vars)
125 	                                     * record function and variable declarations in pass 1
126 	                                     */
127 	duk_hobject *h_labelnames;          /* array of active label names */
128 	duk_hbuffer_dynamic *h_labelinfos;  /* C array of duk_labelinfo */
129 	duk_hobject *h_argnames;            /* array of formal argument names (-> _Formals) */
130 	duk_hobject *h_varmap;              /* variable map for pass 2 (identifier -> register number or null (unmapped)) */
131 
132 	/* Value stack indices for tracking objects. */
133 	/* code_idx: not needed */
134 	duk_idx_t consts_idx;
135 	duk_idx_t funcs_idx;
136 	duk_idx_t decls_idx;
137 	duk_idx_t labelnames_idx;
138 	duk_idx_t labelinfos_idx;
139 	duk_idx_t argnames_idx;
140 	duk_idx_t varmap_idx;
141 
142 	/* Temp reg handling. */
143 	duk_regconst_t temp_first;           /* first register that is a temporary (below: variables) */
144 	duk_regconst_t temp_next;            /* next temporary register to allocate */
145 	duk_regconst_t temp_max;             /* highest value of temp_reg (temp_max - 1 is highest used reg) */
146 
147 	/* Shuffle registers if large number of regs/consts. */
148 	duk_regconst_t shuffle1;
149 	duk_regconst_t shuffle2;
150 	duk_regconst_t shuffle3;
151 
152 	/* Stats for current expression being parsed. */
153 	duk_int_t nud_count;
154 	duk_int_t led_count;
155 	duk_int_t paren_level;              /* parenthesis count, 0 = top level */
156 	duk_bool_t expr_lhs;                /* expression is left-hand-side compatible */
157 	duk_bool_t allow_in;                /* current paren level allows 'in' token */
158 
159 	/* Misc. */
160 	duk_int_t stmt_next;                /* statement id allocation (running counter) */
161 	duk_int_t label_next;               /* label id allocation (running counter) */
162 	duk_int_t catch_depth;              /* catch stack depth */
163 	duk_int_t with_depth;               /* with stack depth (affects identifier lookups) */
164 	duk_int_t fnum_next;                /* inner function numbering */
165 	duk_int_t num_formals;              /* number of formal arguments */
166 	duk_regconst_t reg_stmt_value;      /* register for writing value of 'non-empty' statements (global or eval code), -1 is marker */
167 #if defined(DUK_USE_DEBUGGER_SUPPORT)
168 	duk_int_t min_line;                 /* XXX: typing (duk_hcompfunc has duk_uint32_t) */
169 	duk_int_t max_line;
170 #endif
171 
172 	/* Status booleans. */
173 	duk_uint8_t is_function;             /* is an actual function (not global/eval code) */
174 	duk_uint8_t is_eval;                 /* is eval code */
175 	duk_uint8_t is_global;               /* is global code */
176 	duk_uint8_t is_namebinding;          /* needs a name binding */
177 	duk_uint8_t is_constructable;        /* result is constructable */
178 	duk_uint8_t is_setget;               /* is a setter/getter */
179 	duk_uint8_t is_strict;               /* function is strict */
180 	duk_uint8_t is_notail;               /* function must not be tail called */
181 	duk_uint8_t in_directive_prologue;   /* parsing in "directive prologue", recognize directives */
182 	duk_uint8_t in_scanning;             /* parsing in "scanning" phase (first pass) */
183 	duk_uint8_t may_direct_eval;         /* function may call direct eval */
184 	duk_uint8_t id_access_arguments;     /* function refers to 'arguments' identifier */
185 	duk_uint8_t id_access_slow;          /* function makes one or more slow path accesses that won't match own static variables */
186 	duk_uint8_t id_access_slow_own;      /* function makes one or more slow path accesses that may match own static variables */
187 	duk_uint8_t is_arguments_shadowed;   /* argument/function declaration shadows 'arguments' */
188 	duk_uint8_t needs_shuffle;           /* function needs shuffle registers */
189 	duk_uint8_t reject_regexp_in_adv;    /* reject RegExp literal on next advance() call; needed for handling IdentifierName productions */
190 	duk_uint8_t allow_regexp_in_adv;     /* allow RegExp literal on next advance() call */
191 };
192 
193 struct duk_compiler_ctx {
194 	duk_hthread *thr;
195 
196 	/* filename being compiled (ends up in functions' '_filename' property) */
197 	duk_hstring *h_filename;            /* borrowed reference */
198 
199 	/* lexing (tokenization) state (contains two valstack slot indices) */
200 	duk_lexer_ctx lex;
201 
202 	/* current and previous token for parsing */
203 	duk_token prev_token;
204 	duk_token curr_token;
205 	duk_idx_t tok11_idx;                /* curr_token slot1 (matches 'lex' slot1_idx) */
206 	duk_idx_t tok12_idx;                /* curr_token slot2 (matches 'lex' slot2_idx) */
207 	duk_idx_t tok21_idx;                /* prev_token slot1 */
208 	duk_idx_t tok22_idx;                /* prev_token slot2 */
209 
210 	/* recursion limit */
211 	duk_int_t recursion_depth;
212 	duk_int_t recursion_limit;
213 
214 	/* code emission temporary */
215 	duk_int_t emit_jumpslot_pc;
216 
217 	/* current function being compiled (embedded instead of pointer for more compact access) */
218 	duk_compiler_func curr_func;
219 };
220 
221 /*
222  *  Prototypes
223  */
224 
225 DUK_INTERNAL_DECL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t src_length, duk_small_uint_t flags);
226 
227 #endif  /* DUK_JS_COMPILER_H_INCLUDED */
228