Skip to content

Commit c0f6719

Browse files
committed
Update IR
IR commit: d0686408e20cd8c8640e37ed52ab81403a2383cb
1 parent e14dad7 commit c0f6719

File tree

10 files changed

+427
-87
lines changed

10 files changed

+427
-87
lines changed

ext/opcache/jit/ir/ir.c

Lines changed: 39 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ const char *ir_op_name[IR_LAST_OP] = {
6969

7070
void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f, bool quoted)
7171
{
72-
if (insn->op == IR_FUNC) {
72+
if (insn->op == IR_FUNC || insn->op == IR_SYM) {
7373
fprintf(f, "%s", ir_get_str(ctx, insn->val.i32));
7474
return;
7575
} else if (insn->op == IR_STR) {
@@ -462,7 +462,7 @@ ir_ref ir_unique_const_addr(ir_ctx *ctx, uintptr_t addr)
462462
return ref;
463463
}
464464

465-
IR_NEVER_INLINE ir_ref ir_const(ir_ctx *ctx, ir_val val, uint8_t type)
465+
static IR_NEVER_INLINE ir_ref ir_const_ex(ir_ctx *ctx, ir_val val, uint8_t type, uint32_t optx)
466466
{
467467
ir_insn *insn, *prev_insn;
468468
ir_ref ref, prev;
@@ -477,7 +477,7 @@ IR_NEVER_INLINE ir_ref ir_const(ir_ctx *ctx, ir_val val, uint8_t type)
477477
while (ref) {
478478
insn = &ctx->ir_base[ref];
479479
if (UNEXPECTED(insn->val.u64 >= val.u64)) {
480-
if (insn->val.u64 == val.u64) {
480+
if (insn->val.u64 == val.u64 && insn->optx == optx) {
481481
return ref;
482482
} else {
483483
break;
@@ -499,12 +499,17 @@ IR_NEVER_INLINE ir_ref ir_const(ir_ctx *ctx, ir_val val, uint8_t type)
499499
insn = &ctx->ir_base[ref];
500500
insn->prev_const = prev;
501501

502-
insn->optx = IR_OPT(type, type);
502+
insn->optx = optx;
503503
insn->val.u64 = val.u64;
504504

505505
return ref;
506506
}
507507

508+
ir_ref ir_const(ir_ctx *ctx, ir_val val, uint8_t type)
509+
{
510+
return ir_const_ex(ctx, val, type, IR_OPT(type, type));
511+
}
512+
508513
ir_ref ir_const_i8(ir_ctx *ctx, int8_t c)
509514
{
510515
ir_val val;
@@ -600,47 +605,33 @@ ir_ref ir_const_addr(ir_ctx *ctx, uintptr_t c)
600605

601606
ir_ref ir_const_func_addr(ir_ctx *ctx, uintptr_t c, uint16_t flags)
602607
{
603-
ir_ref top = -ctx->consts_count;
604-
ir_ref ref;
605-
ir_insn *insn;
606-
607608
if (c == 0) {
608609
return IR_NULL;
609610
}
610611
ir_val val;
611612
val.u64 = c;
612-
ref = ir_const(ctx, val, IR_ADDR);
613-
if (ref == top) {
614-
insn = &ctx->ir_base[ref];
615-
insn->optx = IR_OPT(IR_FUNC_ADDR, IR_ADDR);
616-
insn->const_flags = flags;
617-
} else {
618-
IR_ASSERT(ctx->ir_base[ref].opt == IR_OPT(IR_FUNC_ADDR, IR_ADDR) && ctx->ir_base[ref].const_flags == flags);
619-
}
620-
return ref;
613+
return ir_const_ex(ctx, val, IR_ADDR, IR_OPTX(IR_FUNC_ADDR, IR_ADDR, flags));
621614
}
622615

623616
ir_ref ir_const_func(ir_ctx *ctx, ir_ref str, uint16_t flags)
624617
{
625-
ir_ref ref = ir_next_const(ctx);
626-
ir_insn *insn = &ctx->ir_base[ref];
627-
628-
insn->optx = IR_OPT(IR_FUNC, IR_ADDR);
629-
insn->const_flags = flags;
630-
insn->val.addr = str;
618+
ir_val val;
619+
val.addr = str;
620+
return ir_const_ex(ctx, val, IR_ADDR, IR_OPTX(IR_FUNC, IR_ADDR, flags));
621+
}
631622

632-
return ref;
623+
ir_ref ir_const_sym(ir_ctx *ctx, ir_ref str)
624+
{
625+
ir_val val;
626+
val.addr = str;
627+
return ir_const_ex(ctx, val, IR_ADDR, IR_OPTX(IR_SYM, IR_ADDR, 0));
633628
}
634629

635630
ir_ref ir_const_str(ir_ctx *ctx, ir_ref str)
636631
{
637-
ir_ref ref = ir_next_const(ctx);
638-
ir_insn *insn = &ctx->ir_base[ref];
639-
640-
insn->optx = IR_OPT(IR_STR, IR_ADDR);
641-
insn->val.addr = str;
642-
643-
return ref;
632+
ir_val val;
633+
val.addr = str;
634+
return ir_const_ex(ctx, val, IR_ADDR, IR_OPTX(IR_STR, IR_ADDR, 0));
644635
}
645636

646637
ir_ref ir_str(ir_ctx *ctx, const char *s)
@@ -1997,26 +1988,26 @@ void _ir_UNREACHABLE(ir_ctx *ctx)
19971988
ctx->control = IR_UNUSED;
19981989
}
19991990

2000-
void _ir_TAILCALL(ir_ctx *ctx, ir_ref func)
1991+
void _ir_TAILCALL(ir_ctx *ctx, ir_type type, ir_ref func)
20011992
{
20021993
IR_ASSERT(ctx->control);
2003-
ctx->control = ir_emit2(ctx, IR_OPTX(IR_TAILCALL, IR_VOID, 2), ctx->control, func);
1994+
ctx->control = ir_emit2(ctx, IR_OPTX(IR_TAILCALL, type, 2), ctx->control, func);
20041995
_ir_UNREACHABLE(ctx);
20051996
}
20061997

2007-
void _ir_TAILCALL_1(ir_ctx *ctx, ir_ref func, ir_ref arg1)
1998+
void _ir_TAILCALL_1(ir_ctx *ctx, ir_type type, ir_ref func, ir_ref arg1)
20081999
{
20092000
IR_ASSERT(ctx->control);
2010-
ctx->control = ir_emit3(ctx, IR_OPTX(IR_TAILCALL, IR_VOID, 3), ctx->control, func, arg1);
2001+
ctx->control = ir_emit3(ctx, IR_OPTX(IR_TAILCALL, type, 3), ctx->control, func, arg1);
20112002
_ir_UNREACHABLE(ctx);
20122003
}
20132004

2014-
void _ir_TAILCALL_2(ir_ctx *ctx, ir_ref func, ir_ref arg1, ir_ref arg2)
2005+
void _ir_TAILCALL_2(ir_ctx *ctx, ir_type type, ir_ref func, ir_ref arg1, ir_ref arg2)
20152006
{
20162007
ir_ref call;
20172008

20182009
IR_ASSERT(ctx->control);
2019-
call = ir_emit_N(ctx, IR_TAILCALL, 4);
2010+
call = ir_emit_N(ctx, IR_OPT(IR_TAILCALL, type), 4);
20202011
ir_set_op(ctx, call, 1, ctx->control);
20212012
ir_set_op(ctx, call, 2, func);
20222013
ir_set_op(ctx, call, 3, arg1);
@@ -2025,12 +2016,12 @@ void _ir_TAILCALL_2(ir_ctx *ctx, ir_ref func, ir_ref arg1, ir_ref arg2)
20252016
_ir_UNREACHABLE(ctx);
20262017
}
20272018

2028-
void _ir_TAILCALL_3(ir_ctx *ctx, ir_ref func, ir_ref arg1, ir_ref arg2, ir_ref arg3)
2019+
void _ir_TAILCALL_3(ir_ctx *ctx, ir_type type, ir_ref func, ir_ref arg1, ir_ref arg2, ir_ref arg3)
20292020
{
20302021
ir_ref call;
20312022

20322023
IR_ASSERT(ctx->control);
2033-
call = ir_emit_N(ctx, IR_TAILCALL, 5);
2024+
call = ir_emit_N(ctx, IR_OPT(IR_TAILCALL, type), 5);
20342025
ir_set_op(ctx, call, 1, ctx->control);
20352026
ir_set_op(ctx, call, 2, func);
20362027
ir_set_op(ctx, call, 3, arg1);
@@ -2040,12 +2031,12 @@ void _ir_TAILCALL_3(ir_ctx *ctx, ir_ref func, ir_ref arg1, ir_ref arg2, ir_ref a
20402031
_ir_UNREACHABLE(ctx);
20412032
}
20422033

2043-
void _ir_TAILCALL_4(ir_ctx *ctx, ir_ref func, ir_ref arg1, ir_ref arg2, ir_ref arg3, ir_ref arg4)
2034+
void _ir_TAILCALL_4(ir_ctx *ctx, ir_type type, ir_ref func, ir_ref arg1, ir_ref arg2, ir_ref arg3, ir_ref arg4)
20442035
{
20452036
ir_ref call;
20462037

20472038
IR_ASSERT(ctx->control);
2048-
call = ir_emit_N(ctx, IR_TAILCALL, 6);
2039+
call = ir_emit_N(ctx, IR_OPT(IR_TAILCALL, type), 6);
20492040
ir_set_op(ctx, call, 1, ctx->control);
20502041
ir_set_op(ctx, call, 2, func);
20512042
ir_set_op(ctx, call, 3, arg1);
@@ -2056,12 +2047,12 @@ void _ir_TAILCALL_4(ir_ctx *ctx, ir_ref func, ir_ref arg1, ir_ref arg2, ir_ref a
20562047
_ir_UNREACHABLE(ctx);
20572048
}
20582049

2059-
void _ir_TAILCALL_5(ir_ctx *ctx, ir_ref func, ir_ref arg1, ir_ref arg2, ir_ref arg3, ir_ref arg4, ir_ref arg5)
2050+
void _ir_TAILCALL_5(ir_ctx *ctx, ir_type type, ir_ref func, ir_ref arg1, ir_ref arg2, ir_ref arg3, ir_ref arg4, ir_ref arg5)
20602051
{
20612052
ir_ref call;
20622053

20632054
IR_ASSERT(ctx->control);
2064-
call = ir_emit_N(ctx, IR_TAILCALL, 7);
2055+
call = ir_emit_N(ctx, IR_OPT(IR_TAILCALL, type), 7);
20652056
ir_set_op(ctx, call, 1, ctx->control);
20662057
ir_set_op(ctx, call, 2, func);
20672058
ir_set_op(ctx, call, 3, arg1);
@@ -2073,13 +2064,13 @@ void _ir_TAILCALL_5(ir_ctx *ctx, ir_ref func, ir_ref arg1, ir_ref arg2, ir_ref a
20732064
_ir_UNREACHABLE(ctx);
20742065
}
20752066

2076-
void _ir_TAILCALL_N(ir_ctx *ctx, ir_ref func, uint32_t count, ir_ref *args)
2067+
void _ir_TAILCALL_N(ir_ctx *ctx, ir_type type, ir_ref func, uint32_t count, ir_ref *args)
20772068
{
20782069
ir_ref call;
20792070
uint32_t i;
20802071

20812072
IR_ASSERT(ctx->control);
2082-
call = ir_emit_N(ctx, IR_TAILCALL, count + 2);
2073+
call = ir_emit_N(ctx, IR_OPT(IR_TAILCALL, type), count + 2);
20832074
ir_set_op(ctx, call, 1, ctx->control);
20842075
ir_set_op(ctx, call, 2, func);
20852076
for (i = 0; i < count; i++) {
@@ -2375,7 +2366,9 @@ ir_type ir_get_return_type(ir_ctx *ctx)
23752366
insn = &ctx->ir_base[insn->op1];
23762367
if (insn->op == IR_TAILCALL) {
23772368
type = insn->type;
2378-
goto check_type;
2369+
if (type != IR_VOID) {
2370+
goto check_type;
2371+
}
23792372
}
23802373
}
23812374
ref = ctx->ir_base[ref].op3;

ext/opcache/jit/ir/ir.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ typedef enum _ir_type {
269269
_(VAR, p1X1, reg, str, ___) /* local variable */ \
270270
_(FUNC_ADDR, r0, ___, ___, ___) /* constant func ref */ \
271271
_(FUNC, r0, ___, ___, ___) /* constant func ref */ \
272+
_(SYM, r0, ___, ___, ___) /* constant symbol ref */ \
272273
_(STR, r0, ___, ___, ___) /* constant str ref */ \
273274
\
274275
/* call ops */ \
@@ -614,6 +615,7 @@ ir_ref ir_const_addr(ir_ctx *ctx, uintptr_t c);
614615
ir_ref ir_const_func_addr(ir_ctx *ctx, uintptr_t c, uint16_t flags);
615616

616617
ir_ref ir_const_func(ir_ctx *ctx, ir_ref str, uint16_t flags);
618+
ir_ref ir_const_sym(ir_ctx *ctx, ir_ref str);
617619
ir_ref ir_const_str(ir_ctx *ctx, ir_ref str);
618620

619621
ir_ref ir_unique_const_addr(ir_ctx *ctx, uintptr_t c);
@@ -746,13 +748,27 @@ void ir_gdb_unregister_all(void);
746748
bool ir_gdb_present(void);
747749

748750
/* IR load API (implementation in ir_load.c) */
751+
752+
typedef struct _ir_loader ir_loader;
753+
754+
struct _ir_loader {
755+
uint32_t default_func_flags;
756+
bool (*init_module) (ir_loader *loader, const char *name, const char *filename, const char *target);
757+
bool (*external_sym_dcl) (ir_loader *loader, const char *name, bool is_const);
758+
bool (*sym_dcl) (ir_loader *loader, const char *name, bool is_const, bool is_static, size_t size, const void *data);
759+
bool (*external_func_dcl) (ir_loader *loader, const char *name);
760+
bool (*forward_func_dcl) (ir_loader *loader, const char *name, bool is_static);
761+
bool (*init_func) (ir_loader *loader, ir_ctx *ctx, const char *name);
762+
bool (*process_func) (ir_loader *loader, ir_ctx *ctx, const char *name);
763+
};
764+
749765
void ir_loader_init(void);
750766
void ir_loader_free(void);
751767
int ir_load(ir_ctx *ctx, FILE *f);
752768

753769
/* IR LLVM load API (implementation in ir_load_llvm.c) */
754-
int ir_load_llvm_bitcode(const char *filename, uint32_t flags);
755-
int ir_load_llvm_asm(const char *filename, uint32_t flags);
770+
int ir_load_llvm_bitcode(ir_loader *loader, const char *filename);
771+
int ir_load_llvm_asm(ir_loader *loader, const char *filename);
756772

757773
/* IR save API (implementation in ir_save.c) */
758774
void ir_save(const ir_ctx *ctx, FILE *f);

ext/opcache/jit/ir/ir_aarch64.dasc

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,15 @@ static bool aarch64_may_encode_addr_offset(int64_t offset, uint32_t type_size)
137137
|| }
138138
|.endmacro
139139

140+
|.macro ASM_FP_REG_IMM_OP, op, type, reg, val
141+
|| if (type == IR_DOUBLE) {
142+
| op Rd(reg-IR_REG_FP_FIRST), #val
143+
|| } else {
144+
|| IR_ASSERT(type == IR_FLOAT);
145+
| op Rs(reg-IR_REG_FP_FIRST), #val
146+
|| }
147+
|.endmacro
148+
140149
|.macro ASM_FP_REG_REG_REG_OP, op, type, dst, src1, src2
141150
|| if (type == IR_DOUBLE) {
142151
| op Rd(dst-IR_REG_FP_FIRST), Rd(src1-IR_REG_FP_FIRST), Rd(src2-IR_REG_FP_FIRST)
@@ -2366,6 +2375,69 @@ static void ir_emit_if_int(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn)
23662375
ir_emit_jcc(ctx, IR_NE, b, def, insn, 1);
23672376
}
23682377

2378+
static void ir_emit_cond(ir_ctx *ctx, ir_ref def, ir_insn *insn)
2379+
{
2380+
ir_backend_data *data = ctx->data;
2381+
dasm_State **Dst = &data->dasm_state;
2382+
ir_type type = insn->type;
2383+
ir_ref op1 = insn->op1;
2384+
ir_ref op2 = insn->op2;
2385+
ir_ref op3 = insn->op3;
2386+
ir_type op1_type = ctx->ir_base[op1].type;
2387+
ir_reg def_reg = IR_REG_NUM(ctx->regs[def][0]);
2388+
ir_reg op1_reg = ctx->regs[def][1];
2389+
ir_reg op2_reg = ctx->regs[def][2];
2390+
ir_reg op3_reg = ctx->regs[def][3];
2391+
2392+
IR_ASSERT(def_reg != IR_REG_NONE);
2393+
2394+
if (IR_REG_SPILLED(op2_reg) || IR_IS_CONST_REF(op2)) {
2395+
op2_reg = IR_REG_NUM(op2_reg);
2396+
ir_emit_load(ctx, type, op2_reg, op2);
2397+
if (op1 == op2) {
2398+
op1_reg = op2_reg;
2399+
}
2400+
if (op3 == op2) {
2401+
op3_reg = op2_reg;
2402+
}
2403+
}
2404+
if (op3 != op2 && (IR_REG_SPILLED(op3_reg) || IR_IS_CONST_REF(op3))) {
2405+
op3_reg = IR_REG_NUM(op3_reg);
2406+
ir_emit_load(ctx, type, op3_reg, op3);
2407+
if (op1 == op2) {
2408+
op1_reg = op3_reg;
2409+
}
2410+
}
2411+
if (op1 != op2 && op1 != op3 && (IR_REG_SPILLED(op1_reg) || IR_IS_CONST_REF(op1))) {
2412+
op1_reg = IR_REG_NUM(op1_reg);
2413+
ir_emit_load(ctx, op1_type, op1_reg, op1);
2414+
}
2415+
2416+
if (IR_IS_TYPE_INT(op1_type)) {
2417+
| ASM_REG_IMM_OP cmp, op1_type, op1_reg, 0
2418+
} else{
2419+
| ASM_FP_REG_IMM_OP fcmp, op1_type, op1_reg, 0.0
2420+
}
2421+
2422+
if (IR_IS_TYPE_INT(type)) {
2423+
if (ir_type_size[type] == 8) {
2424+
| csel Rx(def_reg), Rx(op2_reg), Rx(op3_reg), eq
2425+
} else {
2426+
| csel Rw(def_reg), Rw(op2_reg), Rw(op3_reg), eq
2427+
}
2428+
} else{
2429+
if (type == IR_DOUBLE) {
2430+
| fcsel Rd(def_reg-IR_REG_FP_FIRST), Rd(op2_reg-IR_REG_FP_FIRST), Rd(op3_reg-IR_REG_FP_FIRST), eq
2431+
} else {
2432+
| fcsel Rs(def_reg-IR_REG_FP_FIRST), Rs(op2_reg-IR_REG_FP_FIRST), Rs(op3_reg-IR_REG_FP_FIRST), eq
2433+
}
2434+
}
2435+
2436+
if (IR_REG_SPILLED(ctx->regs[def][0])) {
2437+
ir_emit_store(ctx, type, def, def_reg);
2438+
}
2439+
}
2440+
23692441
static void ir_emit_return_void(ir_ctx *ctx)
23702442
{
23712443
ir_backend_data *data = ctx->data;
@@ -4952,6 +5024,9 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
49525024
case IR_IF_INT:
49535025
ir_emit_if_int(ctx, b, i, insn);
49545026
break;
5027+
case IR_COND:
5028+
ir_emit_cond(ctx, i, insn);
5029+
break;
49555030
case IR_SWITCH:
49565031
ir_emit_switch(ctx, b, i, insn);
49575032
break;

ext/opcache/jit/ir/ir_builder.h

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -480,13 +480,13 @@ extern "C" {
480480
#define ir_CALL_5(type, func, a1, a2, a3, a4, a5) _ir_CALL_5(_ir_CTX, type, func, a1, a2, a3, a4, a5)
481481
#define ir_CALL_N(type, func, count, args) _ir_CALL_N(_ir_CTX, type, func, count, args)
482482

483-
#define ir_TAILCALL(func) _ir_TAILCALL(_ir_CTX, func)
484-
#define ir_TAILCALL_1(func, a1) _ir_TAILCALL_1(_ir_CTX, func, a1)
485-
#define ir_TAILCALL_2(func, a1, a2) _ir_TAILCALL_2(_ir_CTX, func, a1, a2)
486-
#define ir_TAILCALL_3(func, a1, a2, a3) _ir_TAILCALL_3(_ir_CTX, func, a1, a2, a3)
487-
#define ir_TAILCALL_4(func, a1, a2, a3, a4) _ir_TAILCALL_4(_ir_CTX, func, a1, a2, a3, a4)
488-
#define ir_TAILCALL_5(func, a1, a2, a3, a4, a5) _ir_TAILCALL_5(_ir_CTX, func, a1, a2, a3, a4, a5)
489-
#define ir_TAILCALL_N(func, count, args) _ir_TAILCALL_N(_ir_CTX, func, count, args)
483+
#define ir_TAILCALL(type, func) _ir_TAILCALL(_ir_CTX, type, func)
484+
#define ir_TAILCALL_1(type, func, a1) _ir_TAILCALL_1(_ir_CTX, type, func, a1)
485+
#define ir_TAILCALL_2(type, func, a1, a2) _ir_TAILCALL_2(_ir_CTX, type, func, a1, a2)
486+
#define ir_TAILCALL_3(type, func, a1, a2, a3) _ir_TAILCALL_3(_ir_CTX, type, func, a1, a2, a3)
487+
#define ir_TAILCALL_4(type, func, a1, a2, a3, a4) _ir_TAILCALL_4(_ir_CTX, type, func, a1, a2, a3, a4)
488+
#define ir_TAILCALL_5(type, func, a1, a2, a3, a4, a5) _ir_TAILCALL_5(_ir_CTX, type, func, a1, a2, a3, a4, a5)
489+
#define ir_TAILCALL_N(type, func, count, args) _ir_TAILCALL_N(_ir_CTX, type, func, count, args)
490490

491491
#define ir_ALLOCA(_size) _ir_ALLOCA(_ir_CTX, (_size))
492492
#define ir_AFREE(_size) _ir_AFREE(_ir_CTX, (_size))
@@ -588,13 +588,13 @@ ir_ref _ir_CALL_3(ir_ctx *ctx, ir_type type, ir_ref func, ir_ref arg1, ir_ref ar
588588
ir_ref _ir_CALL_4(ir_ctx *ctx, ir_type type, ir_ref func, ir_ref arg1, ir_ref arg2, ir_ref arg3, ir_ref arg4);
589589
ir_ref _ir_CALL_5(ir_ctx *ctx, ir_type type, ir_ref func, ir_ref arg1, ir_ref arg2, ir_ref arg3, ir_ref arg4, ir_ref arg5);
590590
ir_ref _ir_CALL_N(ir_ctx *ctx, ir_type type, ir_ref func, uint32_t count, ir_ref *args);
591-
void _ir_TAILCALL(ir_ctx *ctx, ir_ref func);
592-
void _ir_TAILCALL_1(ir_ctx *ctx, ir_ref func, ir_ref arg1);
593-
void _ir_TAILCALL_2(ir_ctx *ctx, ir_ref func, ir_ref arg1, ir_ref arg2);
594-
void _ir_TAILCALL_3(ir_ctx *ctx, ir_ref func, ir_ref arg1, ir_ref arg2, ir_ref arg3);
595-
void _ir_TAILCALL_4(ir_ctx *ctx, ir_ref func, ir_ref arg1, ir_ref arg2, ir_ref arg3, ir_ref arg4);
596-
void _ir_TAILCALL_5(ir_ctx *ctx, ir_ref func, ir_ref arg1, ir_ref arg2, ir_ref arg3, ir_ref arg4, ir_ref arg5);
597-
ir_ref _ir_TAILCALL_N(ir_ctx *ctx, ir_ref func, uint32_t count, ir_ref *args);
591+
void _ir_TAILCALL(ir_ctx *ctx, ir_type type, ir_ref func);
592+
void _ir_TAILCALL_1(ir_ctx *ctx, ir_type type, ir_ref func, ir_ref arg1);
593+
void _ir_TAILCALL_2(ir_ctx *ctx, ir_type type, ir_ref func, ir_ref arg1, ir_ref arg2);
594+
void _ir_TAILCALL_3(ir_ctx *ctx, ir_type type, ir_ref func, ir_ref arg1, ir_ref arg2, ir_ref arg3);
595+
void _ir_TAILCALL_4(ir_ctx *ctx, ir_type type, ir_ref func, ir_ref arg1, ir_ref arg2, ir_ref arg3, ir_ref arg4);
596+
void _ir_TAILCALL_5(ir_ctx *ctx, ir_type type, ir_ref func, ir_ref arg1, ir_ref arg2, ir_ref arg3, ir_ref arg4, ir_ref arg5);
597+
ir_ref _ir_TAILCALL_N(ir_ctx *ctx, ir_type type, ir_ref func, uint32_t count, ir_ref *args);
598598
ir_ref _ir_ALLOCA(ir_ctx *ctx, ir_ref size);
599599
void _ir_AFREE(ir_ctx *ctx, ir_ref size);
600600
ir_ref _ir_VLOAD(ir_ctx *ctx, ir_type type, ir_ref var);

0 commit comments

Comments
 (0)