php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
ir.h
Go to the documentation of this file.
1/*
2 * IR - Lightweight JIT Compilation Framework
3 * (Public API)
4 * Copyright (C) 2022 Zend by Perforce.
5 * Authors: Dmitry Stogov <dmitry@php.net>
6 */
7
8#ifndef IR_H
9#define IR_H
10
11#ifdef __cplusplus
12extern "C" {
13#endif
14
15#include <inttypes.h>
16#include <stdint.h>
17#include <stdbool.h>
18#include <stdio.h>
19#include <stdlib.h>
20
21#define IR_VERSION "0.0.1"
22
23#ifdef _WIN32
24/* TODO Handle ARM, too. */
25# if defined(_M_X64) || defined(_M_ARM64)
26# define __SIZEOF_SIZE_T__ 8
27# elif defined(_M_IX86)
28# define __SIZEOF_SIZE_T__ 4
29# endif
30/* Only supported is little endian for any arch on Windows,
31 so just fake the same for all. */
32# ifndef __ORDER_LITTLE_ENDIAN__
33# define __ORDER_LITTLE_ENDIAN__ 1
34# endif
35# define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
36# ifndef __has_builtin
37# define __has_builtin(arg) (0)
38# endif
39#endif
40
41/* target auto detection */
42#if !defined(IR_TARGET_X86) && !defined(IR_TARGET_X64) && !defined(IR_TARGET_AARCH64)
43# if defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
44# define IR_TARGET_X64
45# elif defined(i386) || defined(__i386) || defined(__i386__) || defined(_M_IX86)
46# define IR_TARGET_X86
47# elif defined(__aarch64__) || defined(_M_ARM64)
48# define IR_TARGET_AARCH64
49# elif defined (_WIN64)
50# define IR_TARGET_X64
51# elif defined (_WIN32)
52# define IR_TARGET_X86
53# endif
54#endif
55
56#if defined(IR_TARGET_X86)
57# define IR_TARGET "x86"
58#elif defined(IR_TARGET_X64)
59# ifdef _WIN64
60# define IR_TARGET "Windows-x86_64" /* 64-bit Windows use different ABI and calling convention */
61# else
62# define IR_TARGET "x86_64"
63# endif
64#elif defined(IR_TARGET_AARCH64)
65# define IR_TARGET "aarch64"
66#else
67# error "Unknown IR target"
68#endif
69
70#if defined(__SIZEOF_SIZE_T__)
71# if __SIZEOF_SIZE_T__ == 8
72# define IR_64 1
73# elif __SIZEOF_SIZE_T__ != 4
74# error "Unknown addr size"
75# endif
76#else
77# error "Unknown addr size"
78#endif
79
80#if defined(__BYTE_ORDER__)
81# if defined(__ORDER_LITTLE_ENDIAN__)
82# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
83# define IR_STRUCT_LOHI(lo, hi) struct {lo; hi;}
84# endif
85# endif
86# if defined(__ORDER_BIG_ENDIAN__)
87# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
88# define IR_STRUCT_LOHI(lo, hi) struct {hi; lo;}
89# endif
90# endif
91#endif
92#ifndef IR_STRUCT_LOHI
93# error "Unknown byte order"
94#endif
95
96#ifdef __has_attribute
97# if __has_attribute(always_inline)
98# define IR_ALWAYS_INLINE static inline __attribute__((always_inline))
99# endif
100# if __has_attribute(noinline)
101# define IR_NEVER_INLINE __attribute__((noinline))
102# endif
103#else
104# define __has_attribute(x) 0
105#endif
106
107#ifndef IR_ALWAYS_INLINE
108# define IR_ALWAYS_INLINE static inline
109#endif
110#ifndef IR_NEVER_INLINE
111# define IR_NEVER_INLINE
112#endif
113
114#ifdef IR_PHP
115# include "ir_php.h"
116#endif
117
118/* IR Type flags (low 4 bits are used for type size) */
119#define IR_TYPE_SIGNED (1<<4)
120#define IR_TYPE_UNSIGNED (1<<5)
121#define IR_TYPE_FP (1<<6)
122#define IR_TYPE_SPECIAL (1<<7)
123#define IR_TYPE_BOOL (IR_TYPE_SPECIAL|IR_TYPE_UNSIGNED)
124#define IR_TYPE_ADDR (IR_TYPE_SPECIAL|IR_TYPE_UNSIGNED)
125#define IR_TYPE_CHAR (IR_TYPE_SPECIAL|IR_TYPE_SIGNED)
126
127/* List of IR types */
128#define IR_TYPES(_) \
129 _(BOOL, bool, b, IR_TYPE_BOOL) \
130 _(U8, uint8_t, u8, IR_TYPE_UNSIGNED) \
131 _(U16, uint16_t, u16, IR_TYPE_UNSIGNED) \
132 _(U32, uint32_t, u32, IR_TYPE_UNSIGNED) \
133 _(U64, uint64_t, u64, IR_TYPE_UNSIGNED) \
134 _(ADDR, uintptr_t, addr, IR_TYPE_ADDR) \
135 _(CHAR, char, c, IR_TYPE_CHAR) \
136 _(I8, int8_t, i8, IR_TYPE_SIGNED) \
137 _(I16, int16_t, i16, IR_TYPE_SIGNED) \
138 _(I32, int32_t, i32, IR_TYPE_SIGNED) \
139 _(I64, int64_t, i64, IR_TYPE_SIGNED) \
140 _(DOUBLE, double, d, IR_TYPE_FP) \
141 _(FLOAT, float, f, IR_TYPE_FP) \
142
143#define IR_IS_TYPE_UNSIGNED(t) ((t) < IR_CHAR)
144#define IR_IS_TYPE_SIGNED(t) ((t) >= IR_CHAR && (t) < IR_DOUBLE)
145#define IR_IS_TYPE_INT(t) ((t) < IR_DOUBLE)
146#define IR_IS_TYPE_FP(t) ((t) >= IR_DOUBLE)
147
148#define IR_TYPE_ENUM(name, type, field, flags) IR_ ## name,
149
155
156#ifdef IR_64
157# define IR_SIZE_T IR_U64
158# define IR_SSIZE_T IR_I64
159# define IR_UINTPTR_T IR_U64
160# define IR_INTPTR_T IR_I64
161# define IR_C_UINTPTR IR_U64
162# define IR_C_INTPTR IR_I64
163#else
164# define IR_SIZE_T IR_U32
165# define IR_SSIZE_T IR_I32
166# define IR_UINTPTR_T IR_U32
167# define IR_INTPTR_T IR_I32
168# define IR_C_UINTPTR IR_U32
169# define IR_C_INTPTR IR_I32
170#endif
171
172/* List of IR opcodes
173 * ==================
174 *
175 * Each instruction is described by a type (opcode, flags, op1_type, op2_type, op3_type)
176 *
177 * flags
178 * -----
179 * v - void
180 * d - data IR_OP_FLAG_DATA
181 * r - ref IR_OP_FLAG_DATA alias
182 * p - pinned IR_OP_FLAG_DATA + IR_OP_FLAG_PINNED
183 * c - control IR_OP_FLAG_CONTROL
184 * S - control IR_OP_FLAG_CONTROL + IR_OP_FLAG_BB_START
185 * E - control IR_OP_FLAG_CONTROL + IR_OP_FLAG_BB_END
186 * T - control IR_OP_FLAG_CONTROL + IR_OP_FLAG_BB_END + IR_OP_FLAG_TERMINATOR
187 * l - load IR_OP_FLAG_MEM + IR_OP_FLAG_MEM_LOAD
188 * s - store IR_OP_FLAG_MEM + IR_OP_FLAG_STORE
189 * x - call IR_OP_FLAG_MEM + IR_OP_FLAG_CALL
190 * a - alloc IR_OP_FLAG_MEM + IR_OP_FLAG_ALLOC
191 * 0-3 - number of input edges
192 * N - number of arguments is defined in the insn->inputs_count (MERGE, PHI, CALL)
193 * X1-X3 - number of extra data ops
194 * C - commutative operation ("d2C" => IR_OP_FLAG_DATA + IR_OP_FLAG_COMMUTATIVE)
195 *
196 * operand types
197 * -------------
198 * ___ - unused
199 * def - reference to a definition op (data-flow use-def dependency edge)
200 * ref - memory reference (data-flow use-def dependency edge)
201 * var - variable reference (data-flow use-def dependency edge)
202 * arg - argument reference CALL/TAILCALL/CARG->CARG
203 * src - reference to a previous control region (IF, IF_TRUE, IF_FALSE, MERGE, LOOP_BEGIN, LOOP_END, RETURN)
204 * reg - data-control dependency on region (PHI, VAR, PARAM)
205 * ret - reference to a previous RETURN instruction (RETURN)
206 * str - string: variable/argument name (VAR, PARAM, CALL, TAILCALL)
207 * num - number: argument number (PARAM)
208 * prb - branch probability 1-99 (0 - unspecified): (IF_TRUE, IF_FALSE, CASE_VAL, CASE_DEFAULT)
209 * opt - optional number
210 * pro - function prototype
211 *
212 * The order of IR opcodes is carefully selected for efficient folding.
213 * - foldable instruction go first
214 * - NOP is never used (code 0 is used as ANY pattern)
215 * - CONST is the most often used instruction (encode with 1 bit)
216 * - equality inversion: EQ <-> NE => op =^ 1
217 * - comparison inversion: [U]LT <-> [U]GT, [U]LE <-> [U]GE => op =^ 3
218 */
219
220#define IR_OPS(_) \
221 /* special op (must be the first !!!) */ \
222 _(NOP, v, ___, ___, ___) /* empty instruction */ \
223 \
224 /* constants reference */ \
225 _(C_BOOL, r0, ___, ___, ___) /* constant */ \
226 _(C_U8, r0, ___, ___, ___) /* constant */ \
227 _(C_U16, r0, ___, ___, ___) /* constant */ \
228 _(C_U32, r0, ___, ___, ___) /* constant */ \
229 _(C_U64, r0, ___, ___, ___) /* constant */ \
230 _(C_ADDR, r0, ___, ___, ___) /* constant */ \
231 _(C_CHAR, r0, ___, ___, ___) /* constant */ \
232 _(C_I8, r0, ___, ___, ___) /* constant */ \
233 _(C_I16, r0, ___, ___, ___) /* constant */ \
234 _(C_I32, r0, ___, ___, ___) /* constant */ \
235 _(C_I64, r0, ___, ___, ___) /* constant */ \
236 _(C_DOUBLE, r0, ___, ___, ___) /* constant */ \
237 _(C_FLOAT, r0, ___, ___, ___) /* constant */ \
238 \
239 /* equality ops */ \
240 _(EQ, d2C, def, def, ___) /* equal */ \
241 _(NE, d2C, def, def, ___) /* not equal */ \
242 \
243 /* comparison ops (order matters, LT must be a modulo of 4 !!!) */ \
244 _(LT, d2, def, def, ___) /* less */ \
245 _(GE, d2, def, def, ___) /* greater or equal */ \
246 _(LE, d2, def, def, ___) /* less or equal */ \
247 _(GT, d2, def, def, ___) /* greater */ \
248 _(ULT, d2, def, def, ___) /* unsigned less */ \
249 _(UGE, d2, def, def, ___) /* unsigned greater or equal */ \
250 _(ULE, d2, def, def, ___) /* unsigned less or equal */ \
251 _(UGT, d2, def, def, ___) /* unsigned greater */ \
252 \
253 /* arithmetic ops */ \
254 _(ADD, d2C, def, def, ___) /* addition */ \
255 _(SUB, d2, def, def, ___) /* subtraction (must be ADD+1) */ \
256 _(MUL, d2C, def, def, ___) /* multiplication */ \
257 _(DIV, d2, def, def, ___) /* division */ \
258 _(MOD, d2, def, def, ___) /* modulo */ \
259 _(NEG, d1, def, ___, ___) /* change sign */ \
260 _(ABS, d1, def, ___, ___) /* absolute value */ \
261 /* (LDEXP, MIN, MAX, FPMATH) */ \
262 \
263 /* type conversion ops */ \
264 _(SEXT, d1, def, ___, ___) /* sign extension */ \
265 _(ZEXT, d1, def, ___, ___) /* zero extension */ \
266 _(TRUNC, d1, def, ___, ___) /* truncates to int type */ \
267 _(BITCAST, d1, def, ___, ___) /* binary representation */ \
268 _(INT2FP, d1, def, ___, ___) /* int to float conversion */ \
269 _(FP2INT, d1, def, ___, ___) /* float to int conversion */ \
270 _(FP2FP, d1, def, ___, ___) /* float to float conversion */ \
271 _(PROTO, d1X1, def, pro, ___) /* apply function prototype */ \
272 \
273 /* overflow-check */ \
274 _(ADD_OV, d2C, def, def, ___) /* addition */ \
275 _(SUB_OV, d2, def, def, ___) /* subtraction */ \
276 _(MUL_OV, d2C, def, def, ___) /* multiplication */ \
277 _(OVERFLOW, d1, def, ___, ___) /* overflow check add/sub/mul */ \
278 \
279 /* bitwise and shift ops */ \
280 _(NOT, d1, def, ___, ___) /* bitwise NOT */ \
281 _(OR, d2C, def, def, ___) /* bitwise OR */ \
282 _(AND, d2C, def, def, ___) /* bitwise AND */ \
283 _(XOR, d2C, def, def, ___) /* bitwise XOR */ \
284 _(SHL, d2, def, def, ___) /* logic shift left */ \
285 _(SHR, d2, def, def, ___) /* logic shift right */ \
286 _(SAR, d2, def, def, ___) /* arithmetic shift right */ \
287 _(ROL, d2, def, def, ___) /* rotate left */ \
288 _(ROR, d2, def, def, ___) /* rotate right */ \
289 _(BSWAP, d1, def, ___, ___) /* byte swap */ \
290 _(CTPOP, d1, def, ___, ___) /* count population */ \
291 _(CTLZ, d1, def, ___, ___) /* count leading zeros */ \
292 _(CTTZ, d1, def, ___, ___) /* count trailing zeros */ \
293 \
294 /* branch-less conditional ops */ \
295 _(MIN, d2C, def, def, ___) /* min(op1, op2) */ \
296 _(MAX, d2C, def, def, ___) /* max(op1, op2) */ \
297 _(COND, d3, def, def, def) /* op1 ? op2 : op3 */ \
298 \
299 /* data-flow and miscellaneous ops */ \
300 _(VADDR, d1, var, ___, ___) /* load address of local var */ \
301 _(FRAME_ADDR, d0, ___, ___, ___) /* function frame address */ \
302 _(PHI, pN, reg, def, def) /* SSA Phi function */ \
303 _(COPY, d1X1, def, opt, ___) /* COPY (last foldable op) */ \
304 _(PI, p2, reg, def, ___) /* e-SSA Pi constraint ??? */ \
305 /* (USE, RENAME) */ \
306 \
307 /* data ops */ \
308 _(PARAM, p1X2, reg, str, num) /* incoming parameter proj. */ \
309 _(VAR, p1X1, reg, str, ___) /* local variable */ \
310 _(FUNC_ADDR, r0, ___, ___, ___) /* constant func ref */ \
311 _(FUNC, r0, ___, ___, ___) /* constant func ref */ \
312 _(SYM, r0, ___, ___, ___) /* constant symbol ref */ \
313 _(STR, r0, ___, ___, ___) /* constant str ref */ \
314 \
315 /* call ops */ \
316 _(CALL, xN, src, def, def) /* CALL(src, func, args...) */ \
317 _(TAILCALL, xN, src, def, def) /* CALL+RETURN */ \
318 \
319 /* memory reference and load/store ops */ \
320 _(ALLOCA, a2, src, def, ___) /* alloca(def) */ \
321 _(AFREE, a2, src, def, ___) /* revert alloca(def) */ \
322 _(BLOCK_BEGIN, a1, src, ___, ___) /* stacksave */ \
323 _(BLOCK_END, a2, src, def, ___) /* stackrestore */ \
324 _(VLOAD, l2, src, var, ___) /* load value of local var */ \
325 _(VSTORE, s3, src, var, def) /* store value to local var */ \
326 _(RLOAD, l1X2, src, num, opt) /* load value from register */ \
327 _(RSTORE, s2X1, src, def, num) /* store value into register */ \
328 _(LOAD, l2, src, ref, ___) /* load from memory */ \
329 _(STORE, s3, src, ref, def) /* store to memory */ \
330 _(TLS, l1X2, src, num, num) /* thread local variable */ \
331 _(TRAP, x1, src, ___, ___) /* DebugBreak */ \
332 /* memory reference ops (A, H, U, S, TMP, STR, NEW, X, V) ??? */ \
333 \
334 /* va_args */ \
335 _(VA_START, x2, src, def, ___) /* va_start(va_list) */ \
336 _(VA_END, x2, src, def, ___) /* va_end(va_list) */ \
337 _(VA_COPY, x3, src, def, def) /* va_copy(dst, stc) */ \
338 _(VA_ARG, x2, src, def, ___) /* va_arg(va_list) */ \
339 \
340 /* guards */ \
341 _(GUARD, c3, src, def, def) /* IF without second successor */ \
342 _(GUARD_NOT , c3, src, def, def) /* IF without second successor */ \
343 \
344 /* deoptimization */ \
345 _(SNAPSHOT, xN, src, def, def) /* SNAPSHOT(src, args...) */ \
346 \
347 /* control-flow nodes */ \
348 _(START, S0X1, ret, ___, ___) /* function start */ \
349 _(ENTRY, S1X1, src, num, ___) /* entry with a fake src edge */ \
350 _(BEGIN, S1, src, ___, ___) /* block start */ \
351 _(IF_TRUE, S1X1, src, prb, ___) /* IF TRUE proj. */ \
352 _(IF_FALSE, S1X1, src, prb, ___) /* IF FALSE proj. */ \
353 _(CASE_VAL, S2X1, src, def, prb) /* switch proj. */ \
354 _(CASE_DEFAULT, S1X1, src, prb, ___) /* switch proj. */ \
355 _(MERGE, SN, src, src, src) /* control merge */ \
356 _(LOOP_BEGIN, SN, src, src, src) /* loop start */ \
357 _(END, E1, src, ___, ___) /* block end */ \
358 _(LOOP_END, E1, src, ___, ___) /* loop end */ \
359 _(IF, E2, src, def, ___) /* conditional control split */ \
360 _(SWITCH, E2, src, def, ___) /* multi-way control split */ \
361 _(RETURN, T2X1, src, def, ret) /* function return */ \
362 _(IJMP, T2X1, src, def, ret) /* computed goto */ \
363 _(UNREACHABLE, T1X2, src, ___, ret) /* unreachable (tailcall, etc) */ \
364 \
365 /* deoptimization helper */ \
366 _(EXITCALL, x2, src, def, ___) /* save CPU regs and call op2 */ \
367
368
369#define IR_OP_ENUM(name, flags, op1, op2, op3) IR_ ## name,
370
371typedef enum _ir_op {
373#ifdef IR_PHP
375#endif
378
379/* IR Opcode and Type Union */
380#define IR_OPT_OP_MASK 0x00ff
381#define IR_OPT_TYPE_MASK 0xff00
382#define IR_OPT_TYPE_SHIFT 8
383#define IR_OPT_INPUTS_SHIFT 16
384
385#define IR_OPT(op, type) ((uint16_t)(op) | ((uint16_t)(type) << IR_OPT_TYPE_SHIFT))
386#define IR_OPTX(op, type, n) ((uint32_t)(op) | ((uint32_t)(type) << IR_OPT_TYPE_SHIFT) | ((uint32_t)(n) << IR_OPT_INPUTS_SHIFT))
387#define IR_OPT_TYPE(opt) (((opt) & IR_OPT_TYPE_MASK) >> IR_OPT_TYPE_SHIFT)
388
389/* IR References */
390typedef int32_t ir_ref;
391
392#define IR_IS_CONST_REF(ref) ((ref) < 0)
393
394/* IR Constant Value */
395#define IR_UNUSED 0
396#define IR_NULL (-1)
397#define IR_FALSE (-2)
398#define IR_TRUE (-3)
399#define IR_LAST_FOLDABLE_OP IR_COPY
400
401#define IR_CONSTS_LIMIT_MIN (-(IR_TRUE - 1))
402#define IR_INSNS_LIMIT_MIN (IR_UNUSED + 1)
403
404#ifndef IR_64
405# define ADDR_MEMBER uintptr_t addr;
406#else
407# define ADDR_MEMBER
408#endif
409typedef union _ir_val {
410 double d;
411 uint64_t u64;
412 int64_t i64;
413#ifdef IR_64
414 uintptr_t addr;
415#endif
417 union {
418 uint32_t u32;
419 int32_t i32;
420 float f;
422 ir_ref name;
423 ir_ref str;
425 union {
426 uint16_t u16;
427 int16_t i16;
429 union {
430 uint8_t u8;
431 int8_t i8;
432 bool b;
433 char c;
434 },
435 uint8_t u8_hi
436 );
437 },
438 uint16_t u16_hi
439 );
440 },
441 uint32_t u32_hi
442 );
444#undef ADDR_MEMBER
445
446/* IR Instruction */
447typedef struct _ir_insn {
449 union {
451 union {
453 uint8_t op,
454 uint8_t type
455 );
456 uint16_t opt;
457 },
458 union {
459 uint16_t inputs_count; /* number of input control edges for MERGE, PHI, CALL, TAILCALL */
460 uint16_t prev_insn_offset; /* 16-bit backward offset from current instruction for CSE */
461 uint16_t proto;
462 }
463 );
464 uint32_t optx;
465 ir_ref ops[1];
466 },
467 union {
468 ir_ref op1;
469 ir_ref prev_const;
470 }
471 );
472 union {
474 ir_ref op2,
475 ir_ref op3
476 );
478 };
480
481/* IR Hash Tables API (private) */
482typedef struct _ir_hashtab ir_hashtab;
483
484/* IR String Tables API (implementation in ir_strtab.c) */
485typedef struct _ir_strtab {
486 void *data;
487 uint32_t mask;
488 uint32_t size;
489 uint32_t count;
490 uint32_t pos;
491 char *buf;
492 uint32_t buf_size;
493 uint32_t buf_top;
495
496#define ir_strtab_count(strtab) (strtab)->count
497
498typedef void (*ir_strtab_apply_t)(const char *str, uint32_t len, ir_ref val);
499
500void ir_strtab_init(ir_strtab *strtab, uint32_t count, uint32_t buf_size);
501ir_ref ir_strtab_lookup(ir_strtab *strtab, const char *str, uint32_t len, ir_ref val);
502ir_ref ir_strtab_find(const ir_strtab *strtab, const char *str, uint32_t len);
503ir_ref ir_strtab_update(ir_strtab *strtab, const char *str, uint32_t len, ir_ref val);
504const char *ir_strtab_str(const ir_strtab *strtab, ir_ref idx);
505const char *ir_strtab_strl(const ir_strtab *strtab, ir_ref idx, size_t *len);
507void ir_strtab_free(ir_strtab *strtab);
508
509/* IR Context Flags */
510#define IR_FUNCTION (1<<0) /* Generate a function. */
511#define IR_FASTCALL_FUNC (1<<1) /* Generate a function with fastcall calling convention, x86 32-bit only. */
512#define IR_VARARG_FUNC (1<<2)
513#define IR_BUILTIN_FUNC (1<<3)
514#define IR_STATIC (1<<4)
515#define IR_EXTERN (1<<5)
516#define IR_CONST (1<<6)
517
518#define IR_INITIALIZED (1<<7) /* sym data flag: constant or an initialized variable */
519#define IR_CONST_STRING (1<<8) /* sym data flag: constant string */
520
521#define IR_SKIP_PROLOGUE (1<<8) /* Don't generate function prologue. */
522#define IR_USE_FRAME_POINTER (1<<9)
523#define IR_PREALLOCATED_STACK (1<<10)
524#define IR_NO_STACK_COMBINE (1<<11)
525#define IR_START_BR_TARGET (1<<12)
526#define IR_ENTRY_BR_TARGET (1<<13)
527#define IR_GEN_ENDBR (1<<14)
528#define IR_MERGE_EMPTY_ENTRIES (1<<15)
529
530#define IR_OPT_INLINE (1<<16)
531#define IR_OPT_FOLDING (1<<17)
532#define IR_OPT_CFG (1<<18) /* merge BBs, by remove END->BEGIN nodes during CFG construction */
533#define IR_OPT_MEM2SSA (1<<19)
534#define IR_OPT_CODEGEN (1<<20)
535#define IR_GEN_NATIVE (1<<21)
536#define IR_GEN_CODE (1<<22) /* C or LLVM */
537
538#define IR_GEN_CACHE_DEMOTE (1<<23) /* Demote the generated code from closest CPU caches */
539
540/* debug related */
541#ifdef IR_DEBUG
542# define IR_DEBUG_SCCP (1<<26)
543# define IR_DEBUG_GCM (1<<27)
544# define IR_DEBUG_GCM_SPLIT (1<<28)
545# define IR_DEBUG_SCHEDULE (1<<29)
546# define IR_DEBUG_RA (1<<30)
547# define IR_DEBUG_BB_SCHEDULE (1U<<31)
548#endif
549
550typedef struct _ir_ctx ir_ctx;
552typedef struct _ir_block ir_block;
553typedef struct _ir_arena ir_arena;
556typedef struct _ir_loader ir_loader;
557typedef int8_t ir_regs[4];
558
560
561#if defined(IR_TARGET_AARCH64)
562typedef const void *(*ir_get_exit_addr_t)(uint32_t exit_num);
563typedef const void *(*ir_get_veneer_t)(ir_ctx *ctx, const void *addr);
564typedef bool (*ir_set_veneer_t)(ir_ctx *ctx, const void *addr, const void *veneer);
565#endif
566
567typedef struct _ir_code_buffer {
568 void *start;
569 void *end;
570 void *pos;
572
573struct _ir_ctx {
574 ir_insn *ir_base; /* two directional array - instructions grow down, constants grow up */
575 ir_ref insns_count; /* number of instructions stored in instructions buffer */
576 ir_ref insns_limit; /* size of allocated instructions buffer (it's extended when overflow) */
577 ir_ref consts_count; /* number of constants stored in constants buffer */
578 ir_ref consts_limit; /* size of allocated constants buffer (it's extended when overflow) */
579 uint32_t flags; /* IR context flags (see IR_* defines above) */
580 uint32_t flags2; /* IR context private flags (see IR_* defines in ir_private.h) */
581 ir_type ret_type; /* Function return type */
582 uint32_t mflags; /* CPU specific flags (see IR_X86_... macros below) */
583 int32_t status; /* non-zero error code (see IR_ERROR_... macros), app may use negative codes */
584 ir_ref fold_cse_limit; /* CSE finds identical insns backward from "insn_count" to "fold_cse_limit" */
585 ir_insn fold_insn; /* temporary storage for folding engine */
587 ir_use_list *use_lists; /* def->use lists for each instruction */
588 ir_ref *use_edges; /* the actual uses: use = ctx->use_edges[ctx->use_lists[def].refs + n] */
589 ir_ref use_edges_count; /* number of elements in use_edges[] array */
590 uint32_t cfg_blocks_count; /* number of elements in cfg_blocks[] array */
591 uint32_t cfg_edges_count; /* number of elements in cfg_edges[] array */
592 ir_block *cfg_blocks; /* list of basic blocks (starts from 1) */
593 uint32_t *cfg_edges; /* the actual basic blocks predecessors and successors edges */
594 uint32_t *cfg_map; /* map of instructions to basic block number */
595 uint32_t *cfg_schedule; /* BB order for code generation */
596 uint32_t *rules; /* array of target specific code-generation rules (for each instruction) */
597 uint32_t *vregs;
599 int32_t spill_base; /* base register for special spill area (e.g. PHP VM frame pointer) */
600 uint64_t fixed_regset; /* fixed registers, excluded for regular register allocation */
601 int32_t fixed_stack_red_zone; /* reusable stack allocated by caller (default 0) */
602 int32_t fixed_stack_frame_size; /* fixed stack allocated by generated code for spills and registers save/restore */
603 int32_t fixed_call_stack_size; /* fixed preallocated stack for parameter passing (default 0) */
604 uint64_t fixed_save_regset; /* registers that always saved/restored in prologue/epilogue */
615 union {
616 void *data;
617 ir_ref control; /* used by IR construction API (see ir_builder.h) */
618 ir_ref bb_start; /* used by target CPU instruction matcher */
619 ir_ref vars; /* list of VARs (used by register allocator) */
620 };
623 int32_t stack_frame_size; /* spill stack frame size (used by register allocator and code generator) */
624 int32_t call_stack_size; /* stack for parameter passing (used by register allocator and code generator) */
626#ifdef IR_TARGET_X86
627 int32_t ret_slot;
628#endif
632 uint32_t *entries; /* array of ENTRY blocks */
635#if defined(IR_TARGET_AARCH64)
636 int32_t deoptimization_exits;
637 const void *deoptimization_exits_base;
638 ir_get_exit_addr_t get_exit_addr;
639 ir_get_veneer_t get_veneer;
640 ir_set_veneer_t set_veneer;
641#endif
646};
647
648/* Basic IR Construction API (implementation in ir.c) */
649void ir_init(ir_ctx *ctx, uint32_t flags, ir_ref consts_limit, ir_ref insns_limit);
650void ir_free(ir_ctx *ctx);
651void ir_truncate(ir_ctx *ctx);
652
653ir_ref ir_const(ir_ctx *ctx, ir_val val, uint8_t type);
654ir_ref ir_const_i8(ir_ctx *ctx, int8_t c);
655ir_ref ir_const_i16(ir_ctx *ctx, int16_t c);
656ir_ref ir_const_i32(ir_ctx *ctx, int32_t c);
657ir_ref ir_const_i64(ir_ctx *ctx, int64_t c);
658ir_ref ir_const_u8(ir_ctx *ctx, uint8_t c);
659ir_ref ir_const_u16(ir_ctx *ctx, uint16_t c);
660ir_ref ir_const_u32(ir_ctx *ctx, uint32_t c);
661ir_ref ir_const_u64(ir_ctx *ctx, uint64_t c);
662ir_ref ir_const_bool(ir_ctx *ctx, bool c);
663ir_ref ir_const_char(ir_ctx *ctx, char c);
664ir_ref ir_const_float(ir_ctx *ctx, float c);
665ir_ref ir_const_double(ir_ctx *ctx, double c);
666ir_ref ir_const_addr(ir_ctx *ctx, uintptr_t c);
667
668ir_ref ir_const_func_addr(ir_ctx *ctx, uintptr_t c, ir_ref proto);
669ir_ref ir_const_func(ir_ctx *ctx, ir_ref str, ir_ref proto);
672
673ir_ref ir_unique_const_addr(ir_ctx *ctx, uintptr_t c);
674
675void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f, bool quoted);
676
677ir_ref ir_str(ir_ctx *ctx, const char *s);
678ir_ref ir_strl(ir_ctx *ctx, const char *s, size_t len);
679const char *ir_get_str(const ir_ctx *ctx, ir_ref idx);
680const char *ir_get_strl(const ir_ctx *ctx, ir_ref idx, size_t *len);
681
682#define IR_MAX_PROTO_PARAMS 255
683
684typedef struct _ir_proto_t {
685 uint8_t flags;
686 uint8_t ret_type;
688 uint8_t param_types[5];
690
691ir_ref ir_proto_0(ir_ctx *ctx, uint8_t flags, ir_type ret_type);
692ir_ref ir_proto_1(ir_ctx *ctx, uint8_t flags, ir_type ret_type, ir_type t1);
693ir_ref ir_proto_2(ir_ctx *ctx, uint8_t flags, ir_type ret_type, ir_type t1, ir_type t2);
694ir_ref ir_proto_3(ir_ctx *ctx, uint8_t flags, ir_type ret_type, ir_type t1, ir_type t2, ir_type t3);
695ir_ref ir_proto_4(ir_ctx *ctx, uint8_t flags, ir_type ret_type, ir_type t1, ir_type t2, ir_type t3,
696 ir_type t4);
697ir_ref ir_proto_5(ir_ctx *ctx, uint8_t flags, ir_type ret_type, ir_type t1, ir_type t2, ir_type t3,
698 ir_type t4, ir_type t5);
699ir_ref ir_proto(ir_ctx *ctx, uint8_t flags, ir_type ret_type, uint32_t params_counts, uint8_t *param_types);
700
701ir_ref ir_emit(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir_ref op3);
702
703ir_ref ir_emit0(ir_ctx *ctx, uint32_t opt);
704ir_ref ir_emit1(ir_ctx *ctx, uint32_t opt, ir_ref op1);
705ir_ref ir_emit2(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2);
706ir_ref ir_emit3(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir_ref op3);
707
708ir_ref ir_emit_N(ir_ctx *ctx, uint32_t opt, int32_t count);
709void ir_set_op(ir_ctx *ctx, ir_ref ref, int32_t n, ir_ref val);
710ir_ref ir_get_op(ir_ctx *ctx, ir_ref ref, int32_t n);
711
713{
714 ctx->ir_base[ref].op1 = val;
715}
716
718{
719 ctx->ir_base[ref].op2 = val;
720}
721
723{
724 ctx->ir_base[ref].op3 = val;
725}
726
728{
729 const ir_ref *p = insn->ops + n;
730 return *p;
731}
732
734{
735 ir_ref *p = insn->ops + n;
736 *p = val;
737}
738
740{
741 int i, n = insn->inputs_count;
742
743 for (i = 1; i <= n; i++) {
744 if (ir_insn_op(insn, i) == val) {
745 return i;
746 }
747 }
748 return 0;
749}
750
751ir_ref ir_fold(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir_ref op3);
752
753ir_ref ir_fold0(ir_ctx *ctx, uint32_t opt);
754ir_ref ir_fold1(ir_ctx *ctx, uint32_t opt, ir_ref op1);
755ir_ref ir_fold2(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2);
756ir_ref ir_fold3(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir_ref op3);
757
758ir_ref ir_param(ir_ctx *ctx, ir_type type, ir_ref region, const char *name, int pos);
759ir_ref ir_var(ir_ctx *ctx, ir_type type, ir_ref region, const char *name);
760
761/* IR Binding */
762ir_ref ir_bind(ir_ctx *ctx, ir_ref var, ir_ref def);
763ir_ref ir_binding_find(const ir_ctx *ctx, ir_ref ref);
764
765/* Def -> Use lists */
767
768/* SSA Construction */
770
771/* CFG - Control Flow Graph (implementation in ir_cfg.c) */
772int ir_build_cfg(ir_ctx *ctx);
774int ir_find_loops(ir_ctx *ctx);
775int ir_schedule_blocks(ir_ctx *ctx);
776void ir_reset_cfg(ir_ctx *ctx);
777
778/* SCCP - Sparse Conditional Constant Propagation (implementation in ir_sccp.c) */
779int ir_sccp(ir_ctx *ctx);
780
781/* GCM - Global Code Motion and scheduling (implementation in ir_gcm.c) */
782int ir_gcm(ir_ctx *ctx);
783int ir_schedule(ir_ctx *ctx);
784
785/* Liveness & Register Allocation (implementation in ir_ra.c) */
786#define IR_REG_NONE -1
787#define IR_REG_SPILL_LOAD (1<<6)
788#define IR_REG_SPILL_STORE (1<<6)
789#define IR_REG_SPILL_SPECIAL (1<<7)
790#define IR_REG_SPILLED(r) \
791 ((r) & (IR_REG_SPILL_LOAD|IR_REG_SPILL_STORE|IR_REG_SPILL_SPECIAL))
792#define IR_REG_NUM(r) \
793 ((int8_t)((r) == IR_REG_NONE ? IR_REG_NONE : ((r) & ~(IR_REG_SPILL_LOAD|IR_REG_SPILL_STORE|IR_REG_SPILL_SPECIAL))))
794
797int ir_coalesce(ir_ctx *ctx);
799int ir_reg_alloc(ir_ctx *ctx);
800
801int ir_regs_number(void);
802bool ir_reg_is_int(int32_t reg);
803const char *ir_reg_name(int8_t reg, ir_type type);
804int32_t ir_get_spill_slot_offset(ir_ctx *ctx, ir_ref ref);
805
806/* Target CPU instruction selection and code generation (see ir_x86.c) */
807int ir_match(ir_ctx *ctx);
808void *ir_emit_code(ir_ctx *ctx, size_t *size);
809
810bool ir_needs_thunk(ir_code_buffer *code_buffer, void *addr);
811void *ir_emit_thunk(ir_code_buffer *code_buffer, void *addr, size_t *size_ptr);
812void ir_fix_thunk(void *thunk_entry, void *addr);
813
814/* Target address resolution (implementation in ir_emit.c) */
815void *ir_resolve_sym_name(const char *name);
816
817/* Target CPU disassembler (implementation in ir_disasm.c) */
818int ir_disasm_init(void);
819void ir_disasm_free(void);
820void ir_disasm_add_symbol(const char *name, uint64_t addr, uint64_t size);
821const char* ir_disasm_find_symbol(uint64_t addr, int64_t *offset);
822int ir_disasm(const char *name,
823 const void *start,
824 size_t size,
825 bool asm_addr,
826 ir_ctx *ctx,
827 FILE *f);
828
829/* Linux perf interface (implementation in ir_perf.c) */
830int ir_perf_jitdump_open(void);
831int ir_perf_jitdump_close(void);
832int ir_perf_jitdump_register(const char *name, const void *start, size_t size);
833void ir_perf_map_register(const char *name, const void *start, size_t size);
834
835/* GDB JIT interface (implementation in ir_gdb.c) */
836int ir_gdb_register(const char *name,
837 const void *start,
838 size_t size,
839 uint32_t sp_offset,
840 uint32_t sp_adjustment);
841void ir_gdb_unregister_all(void);
842bool ir_gdb_present(void);
843
844/* IR load API (implementation in ir_load.c) */
847 bool (*init_module) (ir_loader *loader, const char *name, const char *filename, const char *target);
848 bool (*external_sym_dcl) (ir_loader *loader, const char *name, uint32_t flags);
849 bool (*external_func_dcl) (ir_loader *loader, const char *name,
850 uint32_t flags, ir_type ret_type, uint32_t params_count, const uint8_t *param_types);
851 bool (*forward_func_dcl) (ir_loader *loader, const char *name,
852 uint32_t flags, ir_type ret_type, uint32_t params_count, const uint8_t *param_types);
853 bool (*sym_dcl) (ir_loader *loader, const char *name, uint32_t flags, size_t size);
854 bool (*sym_data) (ir_loader *loader, ir_type type, uint32_t count, const void *data);
855 bool (*sym_data_str) (ir_loader *loader, const char *str, size_t len);
856 bool (*sym_data_pad) (ir_loader *loader, size_t offset);
857 bool (*sym_data_ref) (ir_loader *loader, ir_op op, const char *ref, uintptr_t offset);
858 bool (*sym_data_end) (ir_loader *loader, uint32_t flags);
859 bool (*func_init) (ir_loader *loader, ir_ctx *ctx, const char *name);
860 bool (*func_process) (ir_loader *loader, ir_ctx *ctx, const char *name);
861 void*(*resolve_sym_name) (ir_loader *loader, const char *name, bool add_thunk);
862 bool (*has_sym) (ir_loader *loader, const char *name);
863 bool (*add_sym) (ir_loader *loader, const char *name, void *addr);
864};
865
866void ir_loader_init(void);
867void ir_loader_free(void);
868int ir_load(ir_loader *loader, FILE *f);
869
870/* IR LLVM load API (implementation in ir_load_llvm.c) */
871int ir_load_llvm_bitcode(ir_loader *loader, const char *filename);
872int ir_load_llvm_asm(ir_loader *loader, const char *filename);
873
874/* IR save API (implementation in ir_save.c) */
875#define IR_SAVE_CFG (1<<0) /* add info about CFG */
876#define IR_SAVE_CFG_MAP (1<<1) /* add info about CFG block assignment */
877#define IR_SAVE_USE_LISTS (1<<2) /* add info about def->use lists */
878#define IR_SAVE_RULES (1<<3) /* add info about selected code-generation rules */
879#define IR_SAVE_REGS (1<<4) /* add info about selected registers */
880
881void ir_print_proto(const ir_ctx *ctx, ir_ref proto, FILE *f);
882void ir_save(const ir_ctx *ctx, uint32_t save_flags, FILE *f);
883
884/* IR debug dump API (implementation in ir_dump.c) */
885void ir_dump(const ir_ctx *ctx, FILE *f);
886void ir_dump_dot(const ir_ctx *ctx, const char *name, FILE *f);
887void ir_dump_use_lists(const ir_ctx *ctx, FILE *f);
888void ir_dump_cfg(ir_ctx *ctx, FILE *f);
889void ir_dump_cfg_map(const ir_ctx *ctx, FILE *f);
890void ir_dump_live_ranges(const ir_ctx *ctx, FILE *f);
891void ir_dump_codegen(const ir_ctx *ctx, FILE *f);
892
893/* IR to C conversion (implementation in ir_emit_c.c) */
894int ir_emit_c(ir_ctx *ctx, const char *name, FILE *f);
895void ir_emit_c_func_decl(const char *name, uint32_t flags, ir_type ret_type, uint32_t params_count, const uint8_t *param_types, FILE *f);
896void ir_emit_c_sym_decl(const char *name, uint32_t flags, FILE *f);
897
898/* IR to LLVM conversion (implementation in ir_emit_llvm.c) */
899int ir_emit_llvm(ir_ctx *ctx, const char *name, FILE *f);
900void ir_emit_llvm_func_decl(const char *name, uint32_t flags, ir_type ret_type, uint32_t params_count, const uint8_t *param_types, FILE *f);
901void ir_emit_llvm_sym_decl(const char *name, uint32_t flags, FILE *f);
902
903/* IR verification API (implementation in ir_check.c) */
904bool ir_check(const ir_ctx *ctx);
905void ir_consistency_check(void);
906
907/* Code patching (implementation in ir_patch.c) */
908int ir_patch(const void *code, size_t size, uint32_t jmp_table_size, const void *from_addr, const void *to_addr);
909
910/* CPU information (implementation in ir_cpuinfo.c) */
911#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
912# define IR_X86_SSE2 (1<<0)
913# define IR_X86_SSE3 (1<<1)
914# define IR_X86_SSSE3 (1<<2)
915# define IR_X86_SSE41 (1<<3)
916# define IR_X86_SSE42 (1<<4)
917# define IR_X86_AVX (1<<5)
918# define IR_X86_AVX2 (1<<6)
919# define IR_X86_BMI1 (1<<7)
920# define IR_X86_CLDEMOTE (1<<8)
921#endif
922
923uint32_t ir_cpuinfo(void);
924
925/* Deoptimization helpers */
926const void *ir_emit_exitgroup(uint32_t first_exit_point, uint32_t exit_points_per_group, const void *exit_addr, ir_code_buffer *code_buffer, size_t *size_ptr);
927
928/* A reference IR JIT compiler */
929IR_ALWAYS_INLINE void *ir_jit_compile(ir_ctx *ctx, int opt_level, size_t *size)
930{
931 if (opt_level == 0) {
932 if (ctx->flags & IR_OPT_FOLDING) {
933 // IR_ASSERT(0 && "IR_OPT_FOLDING is incompatible with -O0");
934 return NULL;
935 }
936 ctx->flags &= ~(IR_OPT_CFG | IR_OPT_CODEGEN);
937
939
940 if (!ir_build_cfg(ctx)
941 || !ir_match(ctx)
943 || !ir_compute_dessa_moves(ctx)) {
944 return NULL;
945 }
946
947 return ir_emit_code(ctx, size);
948 } else if (opt_level > 0) {
949 if (!(ctx->flags & IR_OPT_FOLDING)) {
950 // IR_ASSERT(0 && "IR_OPT_FOLDING must be set in ir_init() for -O1 and -O2");
951 return NULL;
952 }
954
956
957 if (ctx->flags & IR_OPT_MEM2SSA) {
958 if (!ir_build_cfg(ctx)
960 || !ir_mem2ssa(ctx)) {
961 return NULL;
962 }
963 ir_reset_cfg(ctx);
964 }
965
966 if (opt_level > 1) {
967 if (!ir_sccp(ctx)) {
968 return NULL;
969 }
970 }
971
972 if (!ctx->cfg_blocks) {
973 if (!ir_build_cfg(ctx)
974 || !ir_build_dominators_tree(ctx)) {
975 return NULL;
976 }
977 }
978
979 if (!ir_find_loops(ctx)
980 || !ir_gcm(ctx)
981 || !ir_schedule(ctx)
982 || !ir_match(ctx)
985 || !ir_coalesce(ctx)
986 || !ir_reg_alloc(ctx)
987 || !ir_schedule_blocks(ctx)) {
988 return NULL;
989 }
990
991 return ir_emit_code(ctx, size);
992 } else {
993 // IR_ASSERT(0 && "wrong optimization level");
994 return NULL;
995 }
996}
997
998#define IR_ERROR_CODE_MEM_OVERFLOW 1
999#define IR_ERROR_FIXED_STACK_FRAME_OVERFLOW 2
1000#define IR_ERROR_UNSUPPORTED_CODE_RULE 3
1001#define IR_ERROR_LINK 4
1002#define IR_ERROR_ENCODE 5
1003
1004/* IR Memmory Allocation */
1005#ifndef ir_mem_malloc
1006# define ir_mem_malloc malloc
1007#endif
1008#ifndef ir_mem_calloc
1009# define ir_mem_calloc calloc
1010#endif
1011#ifndef ir_mem_realloc
1012# define ir_mem_realloc realloc
1013#endif
1014#ifndef ir_mem_free
1015# define ir_mem_free free
1016#endif
1017
1018#ifndef ir_mem_pmalloc
1019# define ir_mem_pmalloc malloc
1020#endif
1021#ifndef ir_mem_pcalloc
1022# define ir_mem_pcalloc calloc
1023#endif
1024#ifndef ir_mem_prealloc
1025# define ir_mem_prealloc realloc
1026#endif
1027#ifndef ir_mem_pfree
1028# define ir_mem_pfree free
1029#endif
1030
1031void *ir_mem_mmap(size_t size);
1032int ir_mem_unmap(void *ptr, size_t size);
1033int ir_mem_protect(void *ptr, size_t size);
1034int ir_mem_unprotect(void *ptr, size_t size);
1035int ir_mem_flush(void *ptr, size_t size);
1036
1037#ifdef __cplusplus
1038} /* extern "C" */
1039#endif
1040
1041#endif /* IR_H */
size_t len
Definition apprentice.c:174
count(Countable|array $value, int $mode=COUNT_NORMAL)
char s[4]
Definition cdf.c:77
uint16_t u16
Definition endianness.h:3
uint8_t u8[2]
Definition endianness.h:2
zend_ffi_type * type
Definition ffi.c:3812
zend_long n
Definition ffi.c:4979
new_type size
Definition ffi.c:4365
void * ptr
Definition ffi.c:3814
zval * val
Definition ffi.c:4262
buf start
Definition ffi.c:4687
const php_stream_filter_ops * ops
Definition filters.c:1899
zend_long offset
#define NULL
Definition gdcache.h:45
int ir_disasm_init(void)
Definition ir_disasm.c:850
const char * ir_get_strl(const ir_ctx *ctx, ir_ref idx, size_t *len)
Definition ir.c:715
IR_ALWAYS_INLINE void * ir_jit_compile(ir_ctx *ctx, int opt_level, size_t *size)
Definition ir.h:929
ir_ref ir_strtab_find(const ir_strtab *strtab, const char *str, uint32_t len)
Definition ir_strtab.c:115
void ir_loader_free(void)
struct _ir_live_range ir_live_range
Definition ir.h:555
ir_ref ir_binding_find(const ir_ctx *ctx, ir_ref ref)
Definition ir.c:1161
ir_ref ir_fold2(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2)
Definition ir.c:1067
#define IR_OPT_CODEGEN
Definition ir.h:534
void ir_free(ir_ctx *ctx)
Definition ir.c:412
#define IR_OPT_CFG
Definition ir.h:532
int ir_load(ir_loader *loader, FILE *f)
ir_ref ir_str(ir_ctx *ctx, const char *s)
Definition ir.c:688
int ir_load_llvm_bitcode(ir_loader *loader, const char *filename)
const char * ir_strtab_strl(const ir_strtab *strtab, ir_ref idx, size_t *len)
Definition ir_strtab.c:208
ir_ref ir_emit3(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir_ref op3)
Definition ir.c:839
#define IR_TYPES(_)
Definition ir.h:128
ir_ref ir_const_func(ir_ctx *ctx, ir_ref str, ir_ref proto)
Definition ir.c:666
ir_ref ir_bind(ir_ctx *ctx, ir_ref var, ir_ref def)
Definition ir.c:1142
ir_ref ir_const_i64(ir_ctx *ctx, int64_t c)
Definition ir.c:583
ir_ref ir_get_op(ir_ctx *ctx, ir_ref ref, int32_t n)
Definition ir.c:1114
enum _ir_type ir_type
ir_ref ir_fold3(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir_ref op3)
Definition ir.c:1072
void ir_truncate(ir_ctx *ctx)
Definition ir.c:370
int ir_match(ir_ctx *ctx)
Definition ir_emit.c:964
uint32_t ir_cpuinfo(void)
IR_ALWAYS_INLINE uint32_t ir_insn_find_op(const ir_insn *insn, ir_ref val)
Definition ir.h:739
#define ADDR_MEMBER
Definition ir.h:405
union _ir_val ir_val
ir_ref ir_const_i32(ir_ctx *ctx, int32_t c)
Definition ir.c:576
ir_ref ir_emit2(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2)
Definition ir.c:834
bool ir_reg_is_int(int32_t reg)
Definition ir_ra.c:35
int ir_coalesce(ir_ctx *ctx)
Definition ir_ra.c:1856
struct _ir_live_interval ir_live_interval
Definition ir.h:554
ir_ref ir_const_addr(ir_ctx *ctx, uintptr_t c)
Definition ir.c:645
int ir_assign_virtual_registers(ir_ctx *ctx)
Definition ir_ra.c:82
void ir_strtab_apply(const ir_strtab *strtab, ir_strtab_apply_t func)
Definition ir_strtab.c:228
ir_ref ir_const_double(ir_ctx *ctx, double c)
Definition ir.c:638
#define IR_OPT_FOLDING
Definition ir.h:531
ir_ref ir_strtab_update(ir_strtab *strtab, const char *str, uint32_t len, ir_ref val)
Definition ir_strtab.c:183
ir_ref ir_const_bool(ir_ctx *ctx, bool c)
Definition ir.c:618
void ir_build_def_use_lists(ir_ctx *ctx)
Definition ir.c:1224
bool ir_needs_thunk(ir_code_buffer *code_buffer, void *addr)
struct _ir_hashtab ir_hashtab
Definition ir.h:482
int ir_mem_unprotect(void *ptr, size_t size)
Definition ir.c:1851
int ir_mem_unmap(void *ptr, size_t size)
Definition ir.c:1834
int ir_schedule_blocks(ir_ctx *ctx)
Definition ir_cfg.c:1833
void ir_emit_c_sym_decl(const char *name, uint32_t flags, FILE *f)
int ir_mem_flush(void *ptr, size_t size)
Definition ir.c:1862
#define IR_OPS(_)
Definition ir.h:220
void ir_dump_dot(const ir_ctx *ctx, const char *name, FILE *f)
Definition ir_dump.c:55
void ir_disasm_free(void)
Definition ir_disasm.c:858
ir_ref ir_const_i8(ir_ctx *ctx, int8_t c)
Definition ir.c:562
int32_t ir_get_spill_slot_offset(ir_ctx *ctx, ir_ref ref)
Definition ir_emit.c:1040
int ir_compute_dessa_moves(ir_ctx *ctx)
Definition ir_ra.c:2061
ir_ref ir_emit1(ir_ctx *ctx, uint32_t opt, ir_ref op1)
Definition ir.c:829
void ir_consistency_check(void)
Definition ir_check.c:11
int ir_find_loops(ir_ctx *ctx)
Definition ir_cfg.c:911
ir_ref ir_fold(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir_ref op3)
Definition ir.c:1046
int ir_disasm(const char *name, const void *start, size_t size, bool asm_addr, ir_ctx *ctx, FILE *f)
Definition ir_disasm.c:326
ir_ref ir_const_func_addr(ir_ctx *ctx, uintptr_t c, ir_ref proto)
Definition ir.c:655
const void * ir_emit_exitgroup(uint32_t first_exit_point, uint32_t exit_points_per_group, const void *exit_addr, ir_code_buffer *code_buffer, size_t *size_ptr)
int ir_gdb_register(const char *name, const void *start, size_t size, uint32_t sp_offset, uint32_t sp_adjustment)
Definition ir_gdb.c:631
IR_ALWAYS_INLINE void ir_set_op1(ir_ctx *ctx, ir_ref ref, ir_ref val)
Definition ir.h:712
ir_ref ir_emit_N(ir_ctx *ctx, uint32_t opt, int32_t count)
Definition ir.c:1077
_ir_type
Definition ir.h:150
@ IR_VOID
Definition ir.h:151
@ IR_LAST_TYPE
Definition ir.h:153
void ir_print_proto(const ir_ctx *ctx, ir_ref proto, FILE *f)
Definition ir_save.c:11
ir_ref ir_const_u64(ir_ctx *ctx, uint64_t c)
Definition ir.c:611
#define IR_OPT_MEM2SSA
Definition ir.h:533
#define IR_OP_ENUM(name, flags, op1, op2, op3)
Definition ir.h:369
void ir_dump_live_ranges(const ir_ctx *ctx, FILE *f)
Definition ir_dump.c:337
void ir_dump_cfg(ir_ctx *ctx, FILE *f)
Definition ir_dump.c:301
int ir_build_dominators_tree(ir_ctx *ctx)
Definition ir_cfg.c:672
ir_ref ir_const_i16(ir_ctx *ctx, int16_t c)
Definition ir.c:569
ir_ref ir_const(ir_ctx *ctx, ir_val val, uint8_t type)
Definition ir.c:557
int ir_mem2ssa(ir_ctx *ctx)
int32_t ir_ref
Definition ir.h:390
ir_ref ir_proto_5(ir_ctx *ctx, uint8_t flags, ir_type ret_type, ir_type t1, ir_type t2, ir_type t3, ir_type t4, ir_type t5)
Definition ir.c:782
void ir_fix_thunk(void *thunk_entry, void *addr)
int ir_build_cfg(ir_ctx *ctx)
Definition ir_cfg.c:80
IR_ALWAYS_INLINE ir_ref ir_insn_op(const ir_insn *insn, int32_t n)
Definition ir.h:727
struct _ir_proto_t ir_proto_t
void ir_disasm_add_symbol(const char *name, uint64_t addr, uint64_t size)
Definition ir_disasm.c:85
const char * ir_get_str(const ir_ctx *ctx, ir_ref idx)
Definition ir.c:709
void ir_dump_use_lists(const ir_ctx *ctx, FILE *f)
Definition ir_dump.c:142
void * ir_emit_code(ir_ctx *ctx, size_t *size)
int ir_perf_jitdump_register(const char *name, const void *start, size_t size)
Definition ir_perf.c:205
ir_ref ir_var(ir_ctx *ctx, ir_type type, ir_ref region, const char *name)
Definition ir.c:1136
ir_ref ir_emit(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir_ref op3)
Definition ir.c:811
const char * ir_disasm_find_symbol(uint64_t addr, int64_t *offset)
Definition ir_disasm.c:189
IR_ALWAYS_INLINE void ir_insn_set_op(ir_insn *insn, int32_t n, ir_ref val)
Definition ir.h:733
int8_t ir_regs[4]
Definition ir.h:557
ir_ref ir_fold1(ir_ctx *ctx, uint32_t opt, ir_ref op1)
Definition ir.c:1062
int ir_compute_live_ranges(ir_ctx *ctx)
Definition ir_ra.c:1239
const char * ir_strtab_str(const ir_strtab *strtab, ir_ref idx)
Definition ir_strtab.c:202
int ir_gcm(ir_ctx *ctx)
Definition ir_gcm.c:564
ir_ref ir_const_sym(ir_ctx *ctx, ir_ref str)
Definition ir.c:674
struct _ir_arena ir_arena
Definition ir.h:553
bool ir_check(const ir_ctx *ctx)
Definition ir_check.c:89
void ir_emit_llvm_func_decl(const char *name, uint32_t flags, ir_type ret_type, uint32_t params_count, const uint8_t *param_types, FILE *f)
int ir_patch(const void *code, size_t size, uint32_t jmp_table_size, const void *from_addr, const void *to_addr)
Definition ir_patch.c:251
void(* ir_snapshot_create_t)(ir_ctx *ctx, ir_ref addr)
Definition ir.h:559
IR_ALWAYS_INLINE void ir_set_op3(ir_ctx *ctx, ir_ref ref, ir_ref val)
Definition ir.h:722
ir_ref ir_strtab_lookup(ir_strtab *strtab, const char *str, uint32_t len, ir_ref val)
Definition ir_strtab.c:134
int ir_regs_number(void)
Definition ir_ra.c:30
ir_ref ir_strl(ir_ctx *ctx, const char *s, size_t len)
Definition ir.c:700
#define IR_LAST_FOLDABLE_OP
Definition ir.h:399
void ir_set_op(ir_ctx *ctx, ir_ref ref, int32_t n, ir_ref val)
Definition ir.c:1098
void * ir_resolve_sym_name(const char *name)
Definition ir_emit.c:273
struct _ir_code_buffer ir_code_buffer
void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f, bool quoted)
Definition ir.c:117
void ir_reset_cfg(ir_ctx *ctx)
Definition ir_cfg.c:62
int ir_emit_llvm(ir_ctx *ctx, const char *name, FILE *f)
struct _ir_loader ir_loader
Definition ir.h:556
void ir_dump(const ir_ctx *ctx, FILE *f)
Definition ir_dump.c:11
int ir_perf_jitdump_open(void)
Definition ir_perf.c:101
_ir_op
Definition ir.h:371
@ IR_LAST_OP
Definition ir.h:376
const char * ir_reg_name(int8_t reg, ir_type type)
struct _ir_strtab ir_strtab
void ir_init(ir_ctx *ctx, uint32_t flags, ir_ref consts_limit, ir_ref insns_limit)
Definition ir.c:381
void ir_gdb_unregister_all(void)
Definition ir_gdb.c:547
#define IR_TYPE_ENUM(name, type, field, flags)
Definition ir.h:148
int ir_load_llvm_asm(ir_loader *loader, const char *filename)
void * ir_emit_thunk(ir_code_buffer *code_buffer, void *addr, size_t *size_ptr)
int ir_sccp(ir_ctx *ctx)
Definition ir_sccp.c:3638
ir_ref ir_proto_2(ir_ctx *ctx, uint8_t flags, ir_type ret_type, ir_type t1, ir_type t2)
Definition ir.c:742
ir_ref ir_const_u8(ir_ctx *ctx, uint8_t c)
Definition ir.c:590
ir_ref ir_const_u32(ir_ctx *ctx, uint32_t c)
Definition ir.c:604
int ir_mem_protect(void *ptr, size_t size)
Definition ir.c:1840
ir_ref ir_unique_const_addr(ir_ctx *ctx, uintptr_t c)
Definition ir.c:472
ir_ref ir_const_float(ir_ctx *ctx, float c)
Definition ir.c:630
void ir_strtab_free(ir_strtab *strtab)
Definition ir_strtab.c:216
int ir_perf_jitdump_close(void)
Definition ir_perf.c:183
void ir_emit_c_func_decl(const char *name, uint32_t flags, ir_type ret_type, uint32_t params_count, const uint8_t *param_types, FILE *f)
int ir_reg_alloc(ir_ctx *ctx)
Definition ir_ra.c:4111
ir_ref ir_proto_0(ir_ctx *ctx, uint8_t flags, ir_type ret_type)
Definition ir.c:721
ir_ref ir_param(ir_ctx *ctx, ir_type type, ir_ref region, const char *name, int pos)
Definition ir.c:1130
struct _ir_ctx ir_ctx
Definition ir.h:550
void ir_emit_llvm_sym_decl(const char *name, uint32_t flags, FILE *f)
void ir_save(const ir_ctx *ctx, uint32_t save_flags, FILE *f)
Definition ir_save.c:89
ir_ref ir_proto_1(ir_ctx *ctx, uint8_t flags, ir_type ret_type, ir_type t1)
Definition ir.c:731
ir_ref ir_const_str(ir_ctx *ctx, ir_ref str)
Definition ir.c:681
ir_ref ir_const_char(ir_ctx *ctx, char c)
Definition ir.c:623
enum _ir_op ir_op
int ir_schedule(ir_ctx *ctx)
Definition ir_gcm.c:788
void ir_dump_codegen(const ir_ctx *ctx, FILE *f)
Definition ir_dump.c:478
IR_ALWAYS_INLINE void ir_set_op2(ir_ctx *ctx, ir_ref ref, ir_ref val)
Definition ir.h:717
void ir_loader_init(void)
ir_ref ir_proto_4(ir_ctx *ctx, uint8_t flags, ir_type ret_type, ir_type t1, ir_type t2, ir_type t3, ir_type t4)
Definition ir.c:767
ir_ref ir_const_u16(ir_ctx *ctx, uint16_t c)
Definition ir.c:597
void ir_perf_map_register(const char *name, const void *start, size_t size)
Definition ir_perf.c:252
int ir_emit_c(ir_ctx *ctx, const char *name, FILE *f)
void * ir_mem_mmap(size_t size)
Definition ir.c:1821
ir_ref ir_fold0(ir_ctx *ctx, uint32_t opt)
Definition ir.c:1057
#define IR_ALWAYS_INLINE
Definition ir.h:108
void ir_dump_cfg_map(const ir_ctx *ctx, FILE *f)
Definition ir_dump.c:323
void ir_strtab_init(ir_strtab *strtab, uint32_t count, uint32_t buf_size)
Definition ir_strtab.c:93
void(* ir_strtab_apply_t)(const char *str, uint32_t len, ir_ref val)
Definition ir.h:498
bool ir_gdb_present(void)
Definition ir_gdb.c:581
struct _ir_use_list ir_use_list
Definition ir.h:551
struct _ir_insn ir_insn
ir_ref ir_proto(ir_ctx *ctx, uint8_t flags, ir_type ret_type, uint32_t params_counts, uint8_t *param_types)
Definition ir.c:798
ir_ref ir_proto_3(ir_ctx *ctx, uint8_t flags, ir_type ret_type, ir_type t1, ir_type t2, ir_type t3)
Definition ir.c:754
ir_ref ir_emit0(ir_ctx *ctx, uint32_t opt)
Definition ir.c:824
struct _ir_block ir_block
Definition ir.h:552
#define IR_PHP_OPS(_)
Definition ir_php.h:11
unsigned const char * pos
Definition php_ffi.h:52
#define t4
#define t1
#define t3
#define t2
zend_constant * data
p
Definition session.c:1105
void * end
Definition ir.h:569
void * pos
Definition ir.h:570
void * start
Definition ir.h:568
Definition ir.h:573
uint32_t * cfg_edges
Definition ir.h:593
uint32_t cfg_edges_count
Definition ir.h:591
ir_live_interval ** live_intervals
Definition ir.h:609
uint32_t mflags
Definition ir.h:582
int32_t fixed_stack_red_zone
Definition ir.h:601
ir_live_range * unused_ranges
Definition ir.h:611
ir_hashtab * binding
Definition ir.h:586
ir_ref control
Definition ir.h:617
ir_insn fold_insn
Definition ir.h:585
uint32_t gp_reg_params
Definition ir.h:606
ir_ref prev_const_chain[IR_LAST_TYPE]
Definition ir.h:645
ir_ref consts_count
Definition ir.h:577
uint32_t * entries
Definition ir.h:632
uint32_t entries_count
Definition ir.h:631
int32_t fixed_stack_frame_size
Definition ir.h:602
ir_ref bb_start
Definition ir.h:618
ir_ref fold_cse_limit
Definition ir.h:584
ir_ref * prev_ref
Definition ir.h:614
ir_ref vars
Definition ir.h:619
ir_strtab * fused_regs
Definition ir.h:613
ir_arena * arena
Definition ir.h:610
uint32_t * cfg_schedule
Definition ir.h:595
void * data
Definition ir.h:616
ir_snapshot_create_t snapshot_create
Definition ir.h:621
uint32_t rodata_offset
Definition ir.h:629
ir_ref vregs_count
Definition ir.h:598
ir_code_buffer * code_buffer
Definition ir.h:634
ir_block * cfg_blocks
Definition ir.h:592
int32_t param_stack_size
Definition ir.h:608
int32_t status
Definition ir.h:583
ir_ref use_edges_count
Definition ir.h:589
ir_type ret_type
Definition ir.h:581
uint32_t * vregs
Definition ir.h:597
ir_strtab strtab
Definition ir.h:643
ir_loader * loader
Definition ir.h:642
void * osr_entry_loads
Definition ir.h:633
int32_t stack_frame_alignment
Definition ir.h:622
ir_use_list * use_lists
Definition ir.h:587
ir_ref consts_limit
Definition ir.h:578
ir_regs * regs
Definition ir.h:612
uint32_t jmp_table_offset
Definition ir.h:630
uint64_t fixed_regset
Definition ir.h:600
ir_insn * ir_base
Definition ir.h:574
uint32_t flags
Definition ir.h:579
uint32_t fp_reg_params
Definition ir.h:607
uint32_t cfg_blocks_count
Definition ir.h:590
int32_t stack_frame_size
Definition ir.h:623
ir_ref insns_count
Definition ir.h:575
int32_t call_stack_size
Definition ir.h:624
uint32_t flags2
Definition ir.h:580
uint32_t * rules
Definition ir.h:596
ir_ref * use_edges
Definition ir.h:588
uint64_t fixed_save_regset
Definition ir.h:604
uint32_t * cfg_map
Definition ir.h:594
ir_ref prev_insn_chain[IR_LAST_FOLDABLE_OP+1]
Definition ir.h:644
ir_ref insns_limit
Definition ir.h:576
int32_t fixed_call_stack_size
Definition ir.h:603
uint64_t used_preserved_regs
Definition ir.h:625
int32_t spill_base
Definition ir.h:599
uint32_t locals_area_size
Definition ir.h:605
Definition ir.h:447
IR_STRUCT_LOHI(union { IR_STRUCT_LOHI(union { IR_STRUCT_LOHI(uint8_t op, uint8_t type);uint16_t opt;}, union { uint16_t inputs_count;uint16_t prev_insn_offset;uint16_t proto;});uint32_t optx;ir_ref ops[1];}, union { ir_ref op1;ir_ref prev_const;})
ir_val val
Definition ir.h:477
bool(* func_process)(ir_loader *loader, ir_ctx *ctx, const char *name)
Definition ir.h:860
bool(* sym_data_str)(ir_loader *loader, const char *str, size_t len)
Definition ir.h:855
bool(* sym_data_pad)(ir_loader *loader, size_t offset)
Definition ir.h:856
bool(* external_sym_dcl)(ir_loader *loader, const char *name, uint32_t flags)
Definition ir.h:848
bool(* sym_data)(ir_loader *loader, ir_type type, uint32_t count, const void *data)
Definition ir.h:854
bool(* sym_data_end)(ir_loader *loader, uint32_t flags)
Definition ir.h:858
uint32_t default_func_flags
Definition ir.h:846
bool(* sym_dcl)(ir_loader *loader, const char *name, uint32_t flags, size_t size)
Definition ir.h:853
bool(* sym_data_ref)(ir_loader *loader, ir_op op, const char *ref, uintptr_t offset)
Definition ir.h:857
bool(* has_sym)(ir_loader *loader, const char *name)
Definition ir.h:862
bool(* forward_func_dcl)(ir_loader *loader, const char *name, uint32_t flags, ir_type ret_type, uint32_t params_count, const uint8_t *param_types)
Definition ir.h:851
bool(* external_func_dcl)(ir_loader *loader, const char *name, uint32_t flags, ir_type ret_type, uint32_t params_count, const uint8_t *param_types)
Definition ir.h:849
bool(* init_module)(ir_loader *loader, const char *name, const char *filename, const char *target)
Definition ir.h:847
bool(* add_sym)(ir_loader *loader, const char *name, void *addr)
Definition ir.h:863
bool(* func_init)(ir_loader *loader, ir_ctx *ctx, const char *name)
Definition ir.h:859
uint8_t param_types[5]
Definition ir.h:688
uint8_t ret_type
Definition ir.h:686
uint8_t flags
Definition ir.h:685
uint8_t params_count
Definition ir.h:687
uint32_t buf_top
Definition ir.h:493
uint32_t pos
Definition ir.h:490
uint32_t mask
Definition ir.h:487
uint32_t size
Definition ir.h:488
char * buf
Definition ir.h:491
void * data
Definition ir.h:486
uint32_t count
Definition ir.h:489
uint32_t buf_size
Definition ir.h:492
Definition ir.h:409
IR_STRUCT_LOHI(union { uint32_t u32;int32_t i32;float f;ADDR_MEMBER ir_ref name;ir_ref str;IR_STRUCT_LOHI(union { uint16_t u16;int16_t i16;IR_STRUCT_LOHI(union { uint8_t u8;int8_t i8;bool b;char c;}, uint8_t u8_hi);}, uint16_t u16_hi);}, uint32_t u32_hi)
uint64_t u64
Definition ir.h:411
int64_t i64
Definition ir.h:412
double d
Definition ir.h:410
execute_data func
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
zend_string * name
op2
op1