mirror of
https://github.com/danog/ir.git
synced 2024-11-30 04:39:43 +01:00
Implement IJMP instruction (indirect jump or computed goto)
This commit is contained in:
parent
bae7df6a5f
commit
911219493d
1
TODO
1
TODO
@ -2,7 +2,6 @@
|
||||
- va_arg nodes
|
||||
- BSTART, BEND nodes (to free data allocated by ALLOCA)
|
||||
- ENTRY node for multy-entry units
|
||||
- IJMP
|
||||
- guards
|
||||
- variable name binding
|
||||
|
||||
|
5
ir.h
5
ir.h
@ -272,7 +272,7 @@ int ir_mem_flush(void *ptr, size_t size);
|
||||
_(LOOP_BEGIN, c2, src, src, ___) /* loop start */ \
|
||||
_(LOOP_END, c1X1, src, beg, ___) /* loop end */ \
|
||||
_(LOOP_EXIT, c1X1, src, beg, ___) /* loop exit */ \
|
||||
/* (IJMP) */ \
|
||||
_(IJMP, c2X1, src, def, ret) /* computed goto */ \
|
||||
\
|
||||
/* guards (floating or not) ??? */ \
|
||||
_(GUARD_TRUE, c2, src, def, ___) /* IF without second successor */ \
|
||||
@ -436,7 +436,8 @@ typedef struct _ir_strtab {
|
||||
((op) == IR_MERGE || (op) == IR_LOOP_BEGIN)
|
||||
|
||||
#define IR_IS_BB_END(op) \
|
||||
((op) == IR_RETURN || (op) == IR_END || (op) == IR_LOOP_END || (op) == IR_IF || (op) == IR_SWITCH)
|
||||
((op) == IR_RETURN || (op) == IR_END || (op) == IR_LOOP_END || (op) == IR_IF || \
|
||||
(op) == IR_SWITCH || (op) == IR_IJMP || (op) == IR_UNREACHABLE)
|
||||
|
||||
#define IR_BB_UNREACHABLE (1<<0)
|
||||
#define IR_BB_LOOP_HEADER (1<<1)
|
||||
|
@ -68,7 +68,7 @@ void ir_dump_dot(ir_ctx *ctx, FILE *f)
|
||||
if (flags & IR_OP_FLAG_CONTROL) {
|
||||
if (insn->op == IR_START) {
|
||||
fprintf(f, "\t{rank=min; n%d [label=\"%d: %s\",shape=box,style=\"rounded,filled\",fillcolor=red,rank=min];}\n", i, i, ir_op_name[insn->op]);
|
||||
} else if (insn->op == IR_RETURN || insn->op == IR_UNREACHABLE) {
|
||||
} else if (insn->op == IR_RETURN || insn->op == IR_UNREACHABLE || IR_IJMP) {
|
||||
fprintf(f, "\t{rank=max; n%d [label=\"%d: %s\",shape=box,style=\"rounded,filled\",fillcolor=red,rank=max];}\n", i, i, ir_op_name[insn->op]);
|
||||
} else if (flags & IR_OP_FLAG_MEM) {
|
||||
fprintf(f, "\tn%d [label=\"%d: %s\",shape=box,style=filled,fillcolor=pink];\n", i, i, ir_op_name[insn->op]);
|
||||
|
10
ir_emit_c.c
10
ir_emit_c.c
@ -424,6 +424,13 @@ static void ir_emit_tailcall(ir_ctx *ctx, FILE *f, ir_insn *insn)
|
||||
}
|
||||
}
|
||||
|
||||
static void ir_emit_ijmp(ir_ctx *ctx, FILE *f, ir_insn *insn)
|
||||
{
|
||||
fprintf(f, "\tgoto *(void**)(");
|
||||
ir_emit_ref(ctx, f, insn->op2);
|
||||
fprintf(f, ");\n");
|
||||
}
|
||||
|
||||
static void ir_emit_alloca(ir_ctx *ctx, FILE *f, ir_ref def, ir_insn *insn)
|
||||
{
|
||||
ir_emit_def_ref(ctx, f, def);
|
||||
@ -767,6 +774,9 @@ static int ir_emit_func(ir_ctx *ctx, FILE *f)
|
||||
case IR_TAILCALL:
|
||||
ir_emit_tailcall(ctx, f, insn);
|
||||
break;
|
||||
case IR_IJMP:
|
||||
ir_emit_ijmp(ctx, f, insn);
|
||||
break;
|
||||
case IR_ALLOCA:
|
||||
ir_emit_alloca(ctx, f, i, insn);
|
||||
break;
|
||||
|
@ -628,7 +628,7 @@ int ir_sccp(ir_ctx *ctx)
|
||||
ir_sccp_replace_insn(ctx, _values, i, IR_UNUSED);
|
||||
}
|
||||
} else {
|
||||
if (insn->op == IR_RETURN || insn->op == IR_UNREACHABLE) {
|
||||
if (insn->op == IR_RETURN || insn->op == IR_UNREACHABLE || insn->op == IR_IJMP) {
|
||||
ir_ref ref = ctx->ir_base[1].op1;
|
||||
if (ref == i) {
|
||||
ctx->ir_base[1].op1 = insn->op3;
|
||||
|
22
ir_x86.dasc
22
ir_x86.dasc
@ -4506,6 +4506,25 @@ static void ir_emit_tailcall(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
}
|
||||
}
|
||||
|
||||
static void ir_emit_ijmp(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
{
|
||||
ir_backend_data *data = ctx->data;
|
||||
dasm_State **Dst = &data->dasm_state;
|
||||
ir_reg op2_reg = ctx->regs[def][2];
|
||||
|
||||
if (op2_reg != IR_REG_NONE) {
|
||||
if (op2_reg & IR_REG_SPILL_LOAD) {
|
||||
op2_reg &= ~IR_REG_SPILL_LOAD;
|
||||
ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2);
|
||||
}
|
||||
| jmp Ra(op2_reg)
|
||||
} else {
|
||||
int32_t offset = ir_ref_spill_slot(ctx, insn->op2);
|
||||
ir_reg fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_RBP : IR_REG_RSP;
|
||||
| jmp aword [Ra(fp)+offset]
|
||||
}
|
||||
}
|
||||
|
||||
static int ir_emit_dessa_move(ir_ctx *ctx, uint8_t type, ir_ref from, ir_ref to)
|
||||
{
|
||||
ir_backend_data *data = ctx->data;
|
||||
@ -5796,6 +5815,9 @@ void *ir_emit(ir_ctx *ctx, size_t *size)
|
||||
case IR_TAILCALL:
|
||||
ir_emit_tailcall(ctx, i, insn);
|
||||
break;
|
||||
case IR_IJMP:
|
||||
ir_emit_ijmp(ctx, i, insn);
|
||||
break;
|
||||
case IR_MEM_OP_INT:
|
||||
case IR_MEM_INC:
|
||||
case IR_MEM_DEC:
|
||||
|
16
tests/c/ijmp_001.irt
Normal file
16
tests/c/ijmp_001.irt
Normal file
@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
001: IJMP - computed goto
|
||||
--ARGS--
|
||||
--emit-c
|
||||
--CODE--
|
||||
{
|
||||
l_1 = START(l_2);
|
||||
uintptr_t p = PARAM(l_1, "p", 1);
|
||||
l_2 = IJMP(l_1, p);
|
||||
}
|
||||
--EXPECT--
|
||||
void test(uintptr_t p)
|
||||
{
|
||||
uintptr_t d_1 = p;
|
||||
goto *(void**)(d_1);
|
||||
}
|
13
tests/debug/ijmp_001.irt
Normal file
13
tests/debug/ijmp_001.irt
Normal file
@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
001: IJMP - computed goto
|
||||
--ARGS--
|
||||
-S
|
||||
--CODE--
|
||||
{
|
||||
l_1 = START(l_2);
|
||||
uintptr_t p = PARAM(l_1, "p", 1);
|
||||
l_2 = IJMP(l_1, p);
|
||||
}
|
||||
--EXPECT--
|
||||
test:
|
||||
jmpq *%rdi
|
Loading…
Reference in New Issue
Block a user