Coverage Report

Created: 2018-07-03 15:31

/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);