/home/travis/build/MoarVM/MoarVM/src/jit/graph.h
Line | Count | Source |
1 | | /* The MVMJitGraph is - for now - really a linked list of instructions. |
2 | | * It's likely I'll add complexity when it's needed */ |
3 | | struct MVMJitGraph { |
4 | | MVMSpeshGraph *sg; |
5 | | MVMJitNode *first_node; |
6 | | MVMJitNode *last_node; |
7 | | |
8 | | /* Number of instruction+bb+graph labels, but excluding the expression labels */ |
9 | | MVMint32 num_labels; |
10 | | /* Offset for instruction labels */ |
11 | | MVMint32 obj_label_ofs; |
12 | | |
13 | | /* Sequence number for expr trees */ |
14 | | MVMuint16 expr_seq_nr; |
15 | | |
16 | | /* resultant JIT code is supports 'invokish' etc? */ |
17 | | MVMuint8 no_trampoline; |
18 | | |
19 | | /* All labeled things */ |
20 | | MVM_VECTOR_DECL(void*, obj_labels); |
21 | | MVM_VECTOR_DECL(MVMJitDeopt, deopts); |
22 | | MVM_VECTOR_DECL(MVMJitHandler, handlers); |
23 | | MVM_VECTOR_DECL(MVMJitInline, inlines); |
24 | | MVM_VECTOR_DECL(MVMJitNode*, label_nodes); |
25 | | }; |
26 | | |
27 | | struct MVMJitDeopt { |
28 | | MVMint32 idx; |
29 | | MVMint32 label; |
30 | | }; |
31 | | |
32 | | struct MVMJitHandler { |
33 | | MVMint32 start_label; |
34 | | MVMint32 end_label; |
35 | | MVMint32 goto_label; |
36 | | }; |
37 | | |
38 | | struct MVMJitInline { |
39 | | MVMint32 start_label; |
40 | | MVMint32 end_label; |
41 | | }; |
42 | | |
43 | | /* A label (no more than a number) */ |
44 | | struct MVMJitLabel { |
45 | | MVMint32 name; |
46 | | }; |
47 | | |
48 | | struct MVMJitPrimitive { |
49 | | MVMSpeshIns * ins; |
50 | | }; |
51 | | |
52 | | struct MVMJitGuard { |
53 | | MVMSpeshIns * ins; |
54 | | MVMint32 deopt_target; |
55 | | MVMint32 deopt_offset; |
56 | | }; |
57 | | |
58 | | |
59 | 2.14M | #define MVM_JIT_INFO_INVOKISH 1 |
60 | 2.14M | #define MVM_JIT_INFO_THROWISH 2 |
61 | | |
62 | | typedef enum { |
63 | | MVM_JIT_CONTROL_BREAKPOINT, |
64 | | } MVMJitControlType; |
65 | | |
66 | | struct MVMJitControl { |
67 | | MVMSpeshIns *ins; |
68 | | MVMJitControlType type; |
69 | | }; |
70 | | |
71 | | /* Special branch target for the exit */ |
72 | 5.61k | #define MVM_JIT_BRANCH_EXIT -1 |
73 | | |
74 | | |
75 | | /* What does a branch need? a label to go to, an instruction to read */ |
76 | | struct MVMJitBranch { |
77 | | MVMint32 dest; |
78 | | MVMSpeshIns *ins; |
79 | | }; |
80 | | |
81 | | typedef enum { |
82 | | MVM_JIT_INTERP_TC, |
83 | | MVM_JIT_INTERP_CU, |
84 | | MVM_JIT_INTERP_FRAME, |
85 | | MVM_JIT_INTERP_PARAMS, |
86 | | MVM_JIT_INTERP_CALLER, |
87 | | } MVMJitInterpVar; |
88 | | |
89 | | typedef enum { |
90 | | MVM_JIT_INTERP_VAR, |
91 | | MVM_JIT_REG_VAL, |
92 | | MVM_JIT_REG_VAL_F, |
93 | | MVM_JIT_REG_ADDR, |
94 | | MVM_JIT_STR_IDX, |
95 | | MVM_JIT_LITERAL, |
96 | | MVM_JIT_LITERAL_F, |
97 | | MVM_JIT_LITERAL_64, |
98 | | MVM_JIT_LITERAL_PTR, |
99 | | MVM_JIT_REG_STABLE, |
100 | | MVM_JIT_REG_OBJBODY, |
101 | | /* Take from register relative to cur_op. Usually code is JIT compiled by |
102 | | spesh which already known the indexes of the registers an op uses. |
103 | | Compilation of native calls however happens ahead of time when the code |
104 | | that will call the ncinvoke op may not even exist yet. In that case |
105 | | we need to do the same as interp.c and address registers relative to |
106 | | cur_op. */ |
107 | | MVM_JIT_REG_DYNIDX, |
108 | | MVM_JIT_DATA_LABEL, |
109 | | /* The MVM_JIT_ARG_* types are used when the offset into the WORK array is |
110 | | not known yet, i.e. for ahead of time compiled native calls. */ |
111 | | MVM_JIT_ARG_I64, |
112 | | MVM_JIT_ARG_I64_RW, |
113 | | /* Pointers are passed as objects with CPointer representation, i.e. the |
114 | | actual pointer is part of the object's data. The MVM_JIT_ARG_PTR type |
115 | | unboxes the CPointer object and passes on the contained pointer */ |
116 | | MVM_JIT_ARG_PTR, |
117 | | MVM_JIT_ARG_VMARRAY, |
118 | | /* The MVM_JIT_PARAM_* types are usd when actual JIT compilation is |
119 | | happening as part of spesh, i.e. the offset of the args buffer in WORK |
120 | | is already known. */ |
121 | | MVM_JIT_PARAM_I64, |
122 | | MVM_JIT_PARAM_I64_RW, |
123 | | MVM_JIT_PARAM_PTR, |
124 | | MVM_JIT_PARAM_VMARRAY, |
125 | | /* spesh slot value */ |
126 | | MVM_JIT_SPESH_SLOT_VALUE, |
127 | | /* stack relative address */ |
128 | | MVM_JIT_STACK_VALUE, |
129 | | } MVMJitArgType; |
130 | | |
131 | | struct MVMJitCallArg { |
132 | | MVMJitArgType type; |
133 | | union { |
134 | | MVMint64 lit_i64; |
135 | | MVMnum64 lit_n64; |
136 | | MVMJitInterpVar ivar; |
137 | | MVMint16 reg; |
138 | | void *ptr; |
139 | | } v; |
140 | | }; |
141 | | |
142 | | |
143 | | typedef enum { |
144 | | MVM_JIT_RV_VOID, |
145 | | /* ptr and int are mostly the same, but they might not be on all |
146 | | platforms */ |
147 | | MVM_JIT_RV_INT, |
148 | | MVM_JIT_RV_PTR, |
149 | | /* floats aren't */ |
150 | | MVM_JIT_RV_NUM, |
151 | | /* dereference and store */ |
152 | | MVM_JIT_RV_DEREF, |
153 | | /* store local at address */ |
154 | | MVM_JIT_RV_ADDR, |
155 | | /* Store in register relative to cur_op. Usually code is JIT compiled by |
156 | | spesh which already known the indexes of the registers an op uses. |
157 | | Compilation of native calls however happens ahead of time when the code |
158 | | that will call the ncinvoke op may not even exist yet. In that case |
159 | | we need to do the same as interp.c and address registers relative to |
160 | | cur_op. */ |
161 | | MVM_JIT_RV_DYNIDX, |
162 | | /* store pointer or vmnull */ |
163 | | MVM_JIT_RV_DEREF_OR_VMNULL, |
164 | | /* store on stack with offset */ |
165 | | MVM_JIT_RV_TO_STACK, |
166 | | } MVMJitRVMode; |
167 | | |
168 | | |
169 | | struct MVMJitCallC { |
170 | | void *func_ptr; |
171 | | MVMJitCallArg *args; |
172 | | MVMuint16 num_args; |
173 | | MVMuint16 has_vargs; |
174 | | MVMJitRVMode rv_mode; |
175 | | MVMint16 rv_idx; |
176 | | }; |
177 | | |
178 | | struct MVMJitInvoke { |
179 | | MVMint16 callsite_idx; |
180 | | MVMint16 arg_count; |
181 | | MVMSpeshIns **arg_ins; |
182 | | MVMReturnType return_type; |
183 | | MVMint16 return_register; |
184 | | MVMuint32 code_register_or_name; |
185 | | MVMint16 spesh_cand_or_sf_slot; |
186 | | MVMint8 is_fast; |
187 | | MVMint8 is_resolve; |
188 | | MVMuint32 resolve_offset; /* Only for spesh resolve */ |
189 | | MVMint32 reentry_label; |
190 | | }; |
191 | | |
192 | | struct MVMJitJumpList { |
193 | | MVMint64 num_labels; |
194 | | MVMint16 reg; |
195 | | /* labels of the goto's / jump instructions themselves */ |
196 | | MVMint32 *in_labels; |
197 | | /* labels the goto's jump to */ |
198 | | MVMint32 *out_labels; |
199 | | }; |
200 | | |
201 | | struct MVMJitData { |
202 | | MVMint32 label; |
203 | | void *data; |
204 | | size_t size; |
205 | | }; |
206 | | |
207 | | struct MVMJitStackSlot { |
208 | | MVMint16 slot; |
209 | | }; |
210 | | |
211 | | /* Node types */ |
212 | | typedef enum { |
213 | | MVM_JIT_NODE_PRIMITIVE, |
214 | | MVM_JIT_NODE_CALL_C, |
215 | | MVM_JIT_NODE_BRANCH, |
216 | | MVM_JIT_NODE_LABEL, |
217 | | MVM_JIT_NODE_GUARD, |
218 | | MVM_JIT_NODE_INVOKE, |
219 | | MVM_JIT_NODE_JUMPLIST, |
220 | | MVM_JIT_NODE_CONTROL, |
221 | | MVM_JIT_NODE_DATA, |
222 | | MVM_JIT_NODE_EXPR_TREE, |
223 | | } MVMJitNodeType; |
224 | | |
225 | | struct MVMJitNode { |
226 | | MVMJitNode * next; /* linked list */ |
227 | | MVMJitNodeType type; /* tag */ |
228 | | union { |
229 | | MVMJitPrimitive prim; |
230 | | MVMJitCallC call; |
231 | | MVMJitBranch branch; |
232 | | MVMJitLabel label; |
233 | | MVMJitGuard guard; |
234 | | MVMJitInvoke invoke; |
235 | | MVMJitJumpList jumplist; |
236 | | MVMJitControl control; |
237 | | MVMJitData data; |
238 | | MVMJitExprTree *tree; |
239 | | MVMJitStackSlot stack; |
240 | | } u; |
241 | | }; |
242 | | |
243 | | MVMJitGraph* MVM_jit_try_make_graph(MVMThreadContext *tc, MVMSpeshGraph *sg); |
244 | | void MVM_jit_graph_destroy(MVMThreadContext *tc, MVMJitGraph *graph); |