summaryrefslogtreecommitdiffstats
path: root/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_frontend.h
blob: 7aa460fd9b35142adf4a51e8bb7f41fdce1763be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
/*
 * Copyright (C) 2021 Intel Corporation.  All rights reserved.
 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 */

#ifndef _JIT_FRONTEND_H_
#define _JIT_FRONTEND_H_

#include "jit_utils.h"
#include "jit_ir.h"
#include "../interpreter/wasm_interp.h"
#if WASM_ENABLE_AOT != 0
#include "../aot/aot_runtime.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif

#if WASM_ENABLE_AOT == 0
typedef enum IntCond {
    INT_EQZ = 0,
    INT_EQ,
    INT_NE,
    INT_LT_S,
    INT_LT_U,
    INT_GT_S,
    INT_GT_U,
    INT_LE_S,
    INT_LE_U,
    INT_GE_S,
    INT_GE_U
} IntCond;

typedef enum FloatCond {
    FLOAT_EQ = 0,
    FLOAT_NE,
    FLOAT_LT,
    FLOAT_GT,
    FLOAT_LE,
    FLOAT_GE,
    FLOAT_UNO
} FloatCond;
#else
#define IntCond AOTIntCond
#define FloatCond AOTFloatCond
#endif

typedef enum IntArithmetic {
    INT_ADD = 0,
    INT_SUB,
    INT_MUL,
    INT_DIV_S,
    INT_DIV_U,
    INT_REM_S,
    INT_REM_U
} IntArithmetic;

typedef enum V128Arithmetic {
    V128_ADD = 0,
    V128_SUB,
    V128_MUL,
    V128_DIV,
    V128_NEG,
    V128_MIN,
    V128_MAX,
} V128Arithmetic;

typedef enum IntBitwise {
    INT_AND = 0,
    INT_OR,
    INT_XOR,
} IntBitwise;

typedef enum V128Bitwise {
    V128_NOT,
    V128_AND,
    V128_ANDNOT,
    V128_OR,
    V128_XOR,
    V128_BITSELECT,
} V128Bitwise;

typedef enum IntShift {
    INT_SHL = 0,
    INT_SHR_S,
    INT_SHR_U,
    INT_ROTL,
    INT_ROTR
} IntShift;

typedef enum FloatMath {
    FLOAT_ABS = 0,
    FLOAT_NEG,
    FLOAT_CEIL,
    FLOAT_FLOOR,
    FLOAT_TRUNC,
    FLOAT_NEAREST,
    FLOAT_SQRT
} FloatMath;

typedef enum FloatArithmetic {
    FLOAT_ADD = 0,
    FLOAT_SUB,
    FLOAT_MUL,
    FLOAT_DIV,
    FLOAT_MIN,
    FLOAT_MAX,
} FloatArithmetic;

#if WASM_ENABLE_SHARED_MEMORY != 0
typedef enum AtomicRMWBinOp {
    AtomicRMWBinOpAdd,
    AtomicRMWBinOpSub,
    AtomicRMWBinOpAnd,
    AtomicRMWBinOpOr,
    AtomicRMWBinOpXor,
    AtomicRMWBinOpXchg
} AtomicRMWBinOp;
#endif

/**
 * Translate instructions in a function. The translated block must
 * end with a branch instruction whose targets are offsets relating to
 * the end bcip of the translated block, which are integral constants.
 * If a target of a branch is really a constant value (which should be
 * rare), put it into a register and then jump to the register instead
 * of using the constant value directly in the target. In the
 * translation process, don't create any new labels. The code bcip of
 * the begin and end of the translated block is stored in the
 * jit_annl_begin_bcip and jit_annl_end_bcip annotations of the label
 * of the block, which must be the same as the bcips used in
 * profiling.
 *
 * NOTE: the function must explicitly set SP to correct value when the
 * entry's bcip is the function's entry address.
 *
 * @param cc containing compilation context of generated IR
 * @param entry entry of the basic block to be translated. If its
 * value is NULL, the function will clean up any pass local data that
 * might be created previously.
 * @param is_reached a bitmap recording which bytecode has been
 * reached as a block entry
 *
 * @return IR block containing translated instructions if succeeds,
 * NULL otherwise
 */
JitBasicBlock *
jit_frontend_translate_func(JitCompContext *cc);

/**
 * Lower the IR of the given compilation context.
 *
 * @param cc the compilation context
 *
 * @return true if succeeds, false otherwise
 */
bool
jit_frontend_lower(JitCompContext *cc);

uint32
jit_frontend_get_jitted_return_addr_offset();

uint32
jit_frontend_get_global_data_offset(const WASMModule *module,
                                    uint32 global_idx);

uint32
jit_frontend_get_table_inst_offset(const WASMModule *module, uint32 tbl_idx);

uint32
jit_frontend_get_module_inst_extra_offset(const WASMModule *module);

JitReg
get_module_inst_reg(JitFrame *frame);

JitReg
get_module_reg(JitFrame *frame);

JitReg
get_import_func_ptrs_reg(JitFrame *frame);

JitReg
get_fast_jit_func_ptrs_reg(JitFrame *frame);

JitReg
get_func_type_indexes_reg(JitFrame *frame);

JitReg
get_aux_stack_bound_reg(JitFrame *frame);

JitReg
get_aux_stack_bottom_reg(JitFrame *frame);

JitReg
get_memory_data_reg(JitFrame *frame, uint32 mem_idx);

JitReg
get_memory_data_end_reg(JitFrame *frame, uint32 mem_idx);

JitReg
get_mem_bound_check_1byte_reg(JitFrame *frame, uint32 mem_idx);

JitReg
get_mem_bound_check_2bytes_reg(JitFrame *frame, uint32 mem_idx);

JitReg
get_mem_bound_check_4bytes_reg(JitFrame *frame, uint32 mem_idx);

JitReg
get_mem_bound_check_8bytes_reg(JitFrame *frame, uint32 mem_idx);

JitReg
get_mem_bound_check_16bytes_reg(JitFrame *frame, uint32 mem_idx);

JitReg
get_table_elems_reg(JitFrame *frame, uint32 table_idx);

JitReg
get_table_cur_size_reg(JitFrame *frame, uint32 table_idx);

void
clear_fixed_virtual_regs(JitFrame *frame);

void
clear_memory_regs(JitFrame *frame);

void
clear_table_regs(JitFrame *frame);

/**
 * Get the offset from frame pointer to the n-th local variable slot.
 *
 * @param n the index to the local variable array
 *
 * @return the offset from frame pointer to the local variable slot
 */
static inline unsigned
offset_of_local(unsigned n)
{
    return offsetof(WASMInterpFrame, lp) + n * 4;
}

/**
 * Generate instruction to load an integer from the frame.
 *
 * This and the below gen_load_X functions generate instructions to
 * load values from the frame into registers if the values have not
 * been loaded yet.
 *
 * @param frame the frame information
 * @param n slot index to the local variable array
 *
 * @return register holding the loaded value
 */
JitReg
gen_load_i32(JitFrame *frame, unsigned n);

/**
 * Generate instruction to load a i64 integer from the frame.
 *
 * @param frame the frame information
 * @param n slot index to the local variable array
 *
 * @return register holding the loaded value
 */
JitReg
gen_load_i64(JitFrame *frame, unsigned n);

/**
 * Generate instruction to load a floating point value from the frame.
 *
 * @param frame the frame information
 * @param n slot index to the local variable array
 *
 * @return register holding the loaded value
 */
JitReg
gen_load_f32(JitFrame *frame, unsigned n);

/**
 * Generate instruction to load a double value from the frame.
 *
 * @param frame the frame information
 * @param n slot index to the local variable array
 *
 * @return register holding the loaded value
 */
JitReg
gen_load_f64(JitFrame *frame, unsigned n);

/**
 * Generate instructions to commit computation result to the frame.
 * The general principle is to only commit values that will be used
 * through the frame.
 *
 * @param frame the frame information
 * @param begin the begin value slot to commit
 * @param end the end value slot to commit
 */
void
gen_commit_values(JitFrame *frame, JitValueSlot *begin, JitValueSlot *end);

/**
 * Generate instructions to commit SP and IP pointers to the frame.
 *
 * @param frame the frame information
 */
void
gen_commit_sp_ip(JitFrame *frame);

/**
 * Generate commit instructions for the block end.
 *
 * @param frame the frame information
 */
static inline void
gen_commit_for_branch(JitFrame *frame)
{
    gen_commit_values(frame, frame->lp, frame->sp);
}

/**
 * Generate commit instructions for exception checks.
 *
 * @param frame the frame information
 */
static inline void
gen_commit_for_exception(JitFrame *frame)
{
    gen_commit_values(frame, frame->lp, frame->lp + frame->max_locals);
    gen_commit_sp_ip(frame);
}

/**
 * Generate commit instructions to commit all status.
 *
 * @param frame the frame information
 */
static inline void
gen_commit_for_all(JitFrame *frame)
{
    gen_commit_values(frame, frame->lp, frame->sp);
    gen_commit_sp_ip(frame);
}

static inline void
clear_values(JitFrame *frame)
{
    size_t total_size =
        sizeof(JitValueSlot) * (frame->max_locals + frame->max_stacks);
    memset(frame->lp, 0, total_size);
    frame->committed_sp = NULL;
    frame->committed_ip = NULL;
    clear_fixed_virtual_regs(frame);
}

static inline void
push_i32(JitFrame *frame, JitReg value)
{
    frame->sp->reg = value;
    frame->sp->dirty = 1;
    frame->sp++;
}

static inline void
push_i64(JitFrame *frame, JitReg value)
{
    frame->sp->reg = value;
    frame->sp->dirty = 1;
    frame->sp++;
    frame->sp->reg = value;
    frame->sp->dirty = 1;
    frame->sp++;
}

static inline void
push_f32(JitFrame *frame, JitReg value)
{
    push_i32(frame, value);
}

static inline void
push_f64(JitFrame *frame, JitReg value)
{
    push_i64(frame, value);
}

static inline JitReg
pop_i32(JitFrame *frame)
{
    frame->sp--;
    return gen_load_i32(frame, frame->sp - frame->lp);
}

static inline JitReg
pop_i64(JitFrame *frame)
{
    frame->sp -= 2;
    return gen_load_i64(frame, frame->sp - frame->lp);
}

static inline JitReg
pop_f32(JitFrame *frame)
{
    frame->sp--;
    return gen_load_f32(frame, frame->sp - frame->lp);
}

static inline JitReg
pop_f64(JitFrame *frame)
{
    frame->sp -= 2;
    return gen_load_f64(frame, frame->sp - frame->lp);
}

static inline void
pop(JitFrame *frame, int n)
{
    frame->sp -= n;
    memset(frame->sp, 0, n * sizeof(*frame->sp));
}

static inline JitReg
local_i32(JitFrame *frame, int n)
{
    return gen_load_i32(frame, n);
}

static inline JitReg
local_i64(JitFrame *frame, int n)
{
    return gen_load_i64(frame, n);
}

static inline JitReg
local_f32(JitFrame *frame, int n)
{
    return gen_load_f32(frame, n);
}

static inline JitReg
local_f64(JitFrame *frame, int n)
{
    return gen_load_f64(frame, n);
}

static void
set_local_i32(JitFrame *frame, int n, JitReg val)
{
    frame->lp[n].reg = val;
    frame->lp[n].dirty = 1;
}

static void
set_local_i64(JitFrame *frame, int n, JitReg val)
{
    frame->lp[n].reg = val;
    frame->lp[n].dirty = 1;
    frame->lp[n + 1].reg = val;
    frame->lp[n + 1].dirty = 1;
}

static inline void
set_local_f32(JitFrame *frame, int n, JitReg val)
{
    set_local_i32(frame, n, val);
}

static inline void
set_local_f64(JitFrame *frame, int n, JitReg val)
{
    set_local_i64(frame, n, val);
}

#define POP(jit_value, value_type)                         \
    do {                                                   \
        if (!jit_cc_pop_value(cc, value_type, &jit_value)) \
            goto fail;                                     \
    } while (0)

#define POP_I32(v) POP(v, VALUE_TYPE_I32)
#define POP_I64(v) POP(v, VALUE_TYPE_I64)
#define POP_F32(v) POP(v, VALUE_TYPE_F32)
#define POP_F64(v) POP(v, VALUE_TYPE_F64)
#define POP_FUNCREF(v) POP(v, VALUE_TYPE_FUNCREF)
#define POP_EXTERNREF(v) POP(v, VALUE_TYPE_EXTERNREF)

#define PUSH(jit_value, value_type)                        \
    do {                                                   \
        if (!jit_value)                                    \
            goto fail;                                     \
        if (!jit_cc_push_value(cc, value_type, jit_value)) \
            goto fail;                                     \
    } while (0)

#define PUSH_I32(v) PUSH(v, VALUE_TYPE_I32)
#define PUSH_I64(v) PUSH(v, VALUE_TYPE_I64)
#define PUSH_F32(v) PUSH(v, VALUE_TYPE_F32)
#define PUSH_F64(v) PUSH(v, VALUE_TYPE_F64)
#define PUSH_FUNCREF(v) PUSH(v, VALUE_TYPE_FUNCREF)
#define PUSH_EXTERNREF(v) PUSH(v, VALUE_TYPE_EXTERNREF)

#ifdef __cplusplus
}
#endif

#endif