mirror of
https://github.com/danog/ir.git
synced 2024-11-30 04:39:43 +01:00
Move some common code into ir_emit.c
This commit is contained in:
parent
1b84570aa3
commit
3af9e1a062
115
ir_aarch64.dasc
115
ir_aarch64.dasc
@ -243,14 +243,7 @@ enum _ir_rule {
|
||||
IR_RETURN_FP,
|
||||
};
|
||||
|
||||
/* instruction selection */
|
||||
|
||||
IR_ALWAYS_INLINE uint32_t ir_rule(ir_ctx *ctx, ir_ref ref)
|
||||
{
|
||||
IR_ASSERT(!IR_IS_CONST_REF(ref));
|
||||
return ctx->rules[ref];
|
||||
}
|
||||
|
||||
/* register allocation */
|
||||
bool ir_needs_vreg(ir_ctx *ctx, ir_ref ref)
|
||||
{
|
||||
uint32_t rule;
|
||||
@ -730,6 +723,7 @@ cmp_fp:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* instruction selection */
|
||||
static void ir_match_fuse_addr(ir_ctx *ctx, ir_ref addr_ref, ir_type type)
|
||||
{
|
||||
if (!IR_IS_CONST_REF(addr_ref)) {
|
||||
@ -1097,48 +1091,8 @@ binop_fp:
|
||||
return insn->op;
|
||||
}
|
||||
|
||||
int ir_match(ir_ctx *ctx)
|
||||
{
|
||||
int b, n;
|
||||
ir_ref i;
|
||||
ir_block *bb;
|
||||
ir_insn *insn;
|
||||
|
||||
if (!ctx->prev_insn_len) {
|
||||
ctx->prev_insn_len = ir_mem_malloc(ctx->insns_count * sizeof(uint32_t));
|
||||
n = 1;
|
||||
for (b = 1, bb = ctx->cfg_blocks + b; b <= ctx->cfg_blocks_count; b++, bb++) {
|
||||
if (bb->flags & IR_BB_UNREACHABLE) {
|
||||
continue;
|
||||
}
|
||||
for (i = bb->start, insn = ctx->ir_base + i; i <= bb->end;) {
|
||||
ctx->prev_insn_len[i] = n;
|
||||
n = ir_operands_count(ctx, insn);
|
||||
n = 1 + (n >> 2); // support for multi-word instructions like MERGE and PHI
|
||||
i += n;
|
||||
insn += n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->rules = ir_mem_calloc(ctx->insns_count, sizeof(uint32_t));
|
||||
for (b = ctx->cfg_blocks_count, bb = ctx->cfg_blocks + b; b > 0; b--, bb--) {
|
||||
if (bb->flags & IR_BB_UNREACHABLE) {
|
||||
continue;
|
||||
}
|
||||
for (i = bb->end; i >= bb->start; i -= ctx->prev_insn_len[i]) {
|
||||
insn = &ctx->ir_base[i];
|
||||
if (!ctx->rules[i]) {
|
||||
ctx->rules[i] = ir_match_insn(ctx, i, bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* code genertion */
|
||||
IR_ALWAYS_INLINE int32_t ir_ref_spill_slot(ir_ctx *ctx, ir_ref ref, ir_reg *reg)
|
||||
static int32_t ir_ref_spill_slot(ir_ctx *ctx, ir_ref ref, ir_reg *reg)
|
||||
{
|
||||
ir_backend_data *data = ctx->data;
|
||||
int32_t offset;
|
||||
@ -1434,25 +1388,6 @@ static void ir_emit_store(ir_ctx *ctx, ir_type type, ir_ref dst, ir_reg reg)
|
||||
}
|
||||
}
|
||||
|
||||
static bool ir_is_same_mem(ir_ctx *ctx, ir_ref r1, ir_ref r2)
|
||||
{
|
||||
ir_live_interval *ival1, *ival2;
|
||||
int32_t o1, o2;
|
||||
|
||||
if (IR_IS_CONST_REF(r1) || IR_IS_CONST_REF(r2)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
IR_ASSERT(ctx->vregs[r1] && ctx->vregs[r2]);
|
||||
ival1 = ctx->live_intervals[ctx->vregs[r1]];
|
||||
ival2 = ctx->live_intervals[ctx->vregs[r2]];
|
||||
IR_ASSERT(ival1 && ival2);
|
||||
o1 = ival1->stack_spill_pos;
|
||||
o2 = ival2->stack_spill_pos;
|
||||
IR_ASSERT(o1 != -1 && o2 != -1);
|
||||
return o1 == o2;
|
||||
}
|
||||
|
||||
static void ir_emit_mov(ir_ctx *ctx, ir_type type, ir_reg dst, ir_reg src)
|
||||
{
|
||||
ir_backend_data *data = ctx->data;
|
||||
@ -3571,27 +3506,6 @@ static void ir_emit_switch(ir_ctx *ctx, int b, ir_ref def, ir_insn *insn)
|
||||
}
|
||||
}
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
static void *ir_resolve_sym_name(const char *name)
|
||||
{
|
||||
void *handle = NULL;
|
||||
void *addr;
|
||||
|
||||
#ifdef RTLD_DEFAULT
|
||||
handle = RTLD_DEFAULT;
|
||||
#endif
|
||||
addr = dlsym(handle, name);
|
||||
IR_ASSERT(addr != NULL);
|
||||
return addr;
|
||||
}
|
||||
|
||||
typedef struct _ir_copy {
|
||||
ir_type type;
|
||||
ir_reg from;
|
||||
ir_reg to;
|
||||
} ir_copy;
|
||||
|
||||
static int ir_parallel_copy(ir_ctx *ctx, ir_copy *copies, int count, ir_reg tmp_reg, ir_reg tmp_fp_reg)
|
||||
{
|
||||
int i;
|
||||
@ -4002,29 +3916,6 @@ static void ir_emit_tailcall(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IR_SNAPSHOT_HANDLER_DCL
|
||||
IR_SNAPSHOT_HANDLER_DCL();
|
||||
#endif
|
||||
|
||||
static void *ir_jmp_addr(ir_ctx *ctx, ir_insn *insn, ir_insn *addr_insn)
|
||||
{
|
||||
void *addr;
|
||||
|
||||
IR_ASSERT(addr_insn->type == IR_ADDR);
|
||||
if (addr_insn->op == IR_FUNC) {
|
||||
addr = ir_resolve_sym_name(ir_get_str(ctx, addr_insn->val.addr));
|
||||
} else {
|
||||
IR_ASSERT(addr_insn->op == IR_ADDR || addr_insn->op == IR_FUNC_ADDR);
|
||||
addr = (void*)addr_insn->val.addr;
|
||||
}
|
||||
#ifdef IR_SNAPSHOT_HANDLER
|
||||
if (ctx->ir_base[insn->op1].op == IR_SNAPSHOT) {
|
||||
addr = IR_SNAPSHOT_HANDLER(ctx, insn->op1, &ctx->ir_base[insn->op1], addr);
|
||||
}
|
||||
#endif
|
||||
return addr;
|
||||
}
|
||||
|
||||
static void ir_emit_ijmp(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
{
|
||||
ir_backend_data *data = ctx->data;
|
||||
|
122
ir_emit.c
122
ir_emit.c
@ -1,5 +1,16 @@
|
||||
#include "ir.h"
|
||||
|
||||
#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
|
||||
# include "ir_x86.h"
|
||||
#elif defined(IR_TARGET_AARCH64)
|
||||
# include "ir_aarch64.h"
|
||||
#else
|
||||
# error "Unknown IR target"
|
||||
#endif
|
||||
|
||||
#include "ir_private.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define DASM_M_GROW(ctx, t, p, sz, need) \
|
||||
do { \
|
||||
size_t _sz = (sz), _need = (need); \
|
||||
@ -21,18 +32,121 @@
|
||||
# pragma GCC diagnostic ignored "-Warray-bounds"
|
||||
#endif
|
||||
|
||||
typedef struct _ir_copy {
|
||||
ir_type type;
|
||||
ir_reg from;
|
||||
ir_reg to;
|
||||
} ir_copy;
|
||||
|
||||
IR_ALWAYS_INLINE uint32_t ir_rule(ir_ctx *ctx, ir_ref ref)
|
||||
{
|
||||
IR_ASSERT(!IR_IS_CONST_REF(ref));
|
||||
return ctx->rules[ref];
|
||||
}
|
||||
|
||||
static bool ir_is_same_mem(ir_ctx *ctx, ir_ref r1, ir_ref r2)
|
||||
{
|
||||
ir_live_interval *ival1, *ival2;
|
||||
int32_t o1, o2;
|
||||
|
||||
if (IR_IS_CONST_REF(r1) || IR_IS_CONST_REF(r2)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
IR_ASSERT(ctx->vregs[r1] && ctx->vregs[r2]);
|
||||
ival1 = ctx->live_intervals[ctx->vregs[r1]];
|
||||
ival2 = ctx->live_intervals[ctx->vregs[r2]];
|
||||
IR_ASSERT(ival1 && ival2);
|
||||
o1 = ival1->stack_spill_pos;
|
||||
o2 = ival2->stack_spill_pos;
|
||||
IR_ASSERT(o1 != -1 && o2 != -1);
|
||||
return o1 == o2;
|
||||
}
|
||||
|
||||
static void *ir_resolve_sym_name(const char *name)
|
||||
{
|
||||
void *handle = NULL;
|
||||
void *addr;
|
||||
|
||||
#ifdef RTLD_DEFAULT
|
||||
handle = RTLD_DEFAULT;
|
||||
#endif
|
||||
addr = dlsym(handle, name);
|
||||
IR_ASSERT(addr != NULL);
|
||||
return addr;
|
||||
}
|
||||
|
||||
#ifdef IR_SNAPSHOT_HANDLER_DCL
|
||||
IR_SNAPSHOT_HANDLER_DCL();
|
||||
#endif
|
||||
|
||||
static void *ir_jmp_addr(ir_ctx *ctx, ir_insn *insn, ir_insn *addr_insn)
|
||||
{
|
||||
void *addr;
|
||||
|
||||
IR_ASSERT(addr_insn->type == IR_ADDR);
|
||||
if (addr_insn->op == IR_FUNC) {
|
||||
addr = ir_resolve_sym_name(ir_get_str(ctx, addr_insn->val.addr));
|
||||
} else {
|
||||
IR_ASSERT(addr_insn->op == IR_ADDR || addr_insn->op == IR_FUNC_ADDR);
|
||||
addr = (void*)addr_insn->val.addr;
|
||||
}
|
||||
#ifdef IR_SNAPSHOT_HANDLER
|
||||
if (ctx->ir_base[insn->op1].op == IR_SNAPSHOT) {
|
||||
addr = IR_SNAPSHOT_HANDLER(ctx, insn->op1, &ctx->ir_base[insn->op1], addr);
|
||||
}
|
||||
#endif
|
||||
return addr;
|
||||
}
|
||||
|
||||
#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
|
||||
# include "ir_x86.h"
|
||||
# include "ir_private.h"
|
||||
# include "dynasm/dasm_proto.h"
|
||||
# include "dynasm/dasm_x86.h"
|
||||
# include "ir_emit_x86.h"
|
||||
#elif defined(IR_TARGET_AARCH64)
|
||||
# include "ir_aarch64.h"
|
||||
# include "ir_private.h"
|
||||
# include "dynasm/dasm_proto.h"
|
||||
# include "dynasm/dasm_arm64.h"
|
||||
# include "ir_emit_aarch64.h"
|
||||
#else
|
||||
# error "Unknown IR target"
|
||||
#endif
|
||||
|
||||
int ir_match(ir_ctx *ctx)
|
||||
{
|
||||
int b, n;
|
||||
ir_ref i;
|
||||
ir_block *bb;
|
||||
ir_insn *insn;
|
||||
|
||||
if (!ctx->prev_insn_len) {
|
||||
ctx->prev_insn_len = ir_mem_malloc(ctx->insns_count * sizeof(uint32_t));
|
||||
n = 1;
|
||||
for (b = 1, bb = ctx->cfg_blocks + b; b <= ctx->cfg_blocks_count; b++, bb++) {
|
||||
if (bb->flags & IR_BB_UNREACHABLE) {
|
||||
continue;
|
||||
}
|
||||
for (i = bb->start, insn = ctx->ir_base + i; i <= bb->end;) {
|
||||
ctx->prev_insn_len[i] = n;
|
||||
n = ir_operands_count(ctx, insn);
|
||||
n = 1 + (n >> 2); // support for multi-word instructions like MERGE and PHI
|
||||
i += n;
|
||||
insn += n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->rules = ir_mem_calloc(ctx->insns_count, sizeof(uint32_t));
|
||||
for (b = ctx->cfg_blocks_count, bb = ctx->cfg_blocks + b; b > 0; b--, bb--) {
|
||||
if (bb->flags & IR_BB_UNREACHABLE) {
|
||||
continue;
|
||||
}
|
||||
for (i = bb->end; i >= bb->start; i -= ctx->prev_insn_len[i]) {
|
||||
insn = &ctx->ir_base[i];
|
||||
if (!ctx->rules[i]) {
|
||||
ctx->rules[i] = ir_match_insn(ctx, i, bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
2
ir_ra.c
2
ir_ra.c
@ -9,6 +9,8 @@
|
||||
# include "ir_x86.h"
|
||||
#elif defined(IR_TARGET_AARCH64)
|
||||
# include "ir_aarch64.h"
|
||||
#else
|
||||
# error "Unknown IR target"
|
||||
#endif
|
||||
|
||||
#include "ir_private.h"
|
||||
|
113
ir_x86.dasc
113
ir_x86.dasc
@ -523,14 +523,7 @@ enum _ir_rule {
|
||||
IR_RETURN_FP,
|
||||
};
|
||||
|
||||
/* instruction selection */
|
||||
|
||||
IR_ALWAYS_INLINE uint32_t ir_rule(ir_ctx *ctx, ir_ref ref)
|
||||
{
|
||||
IR_ASSERT(!IR_IS_CONST_REF(ref));
|
||||
return ctx->rules[ref];
|
||||
}
|
||||
|
||||
/* register allocation */
|
||||
bool ir_needs_vreg(ir_ctx *ctx, ir_ref ref)
|
||||
{
|
||||
uint32_t rule;
|
||||
@ -1138,6 +1131,7 @@ cmp_fp:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* instruction selection */
|
||||
static uint32_t ir_match_insn(ir_ctx *ctx, ir_ref ref, ir_block *bb);
|
||||
|
||||
static void ir_match_fuse_addr(ir_ctx *ctx, ir_ref addr_ref, ir_block *bb)
|
||||
@ -2022,46 +2016,6 @@ store_int:
|
||||
return insn->op;
|
||||
}
|
||||
|
||||
int ir_match(ir_ctx *ctx)
|
||||
{
|
||||
int b, n;
|
||||
ir_ref i;
|
||||
ir_block *bb;
|
||||
ir_insn *insn;
|
||||
|
||||
if (!ctx->prev_insn_len) {
|
||||
ctx->prev_insn_len = ir_mem_malloc(ctx->insns_count * sizeof(uint32_t));
|
||||
n = 1;
|
||||
for (b = 1, bb = ctx->cfg_blocks + b; b <= ctx->cfg_blocks_count; b++, bb++) {
|
||||
if (bb->flags & IR_BB_UNREACHABLE) {
|
||||
continue;
|
||||
}
|
||||
for (i = bb->start, insn = ctx->ir_base + i; i <= bb->end;) {
|
||||
ctx->prev_insn_len[i] = n;
|
||||
n = ir_operands_count(ctx, insn);
|
||||
n = 1 + (n >> 2); // support for multi-word instructions like MERGE and PHI
|
||||
i += n;
|
||||
insn += n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->rules = ir_mem_calloc(ctx->insns_count, sizeof(uint32_t));
|
||||
for (b = ctx->cfg_blocks_count, bb = ctx->cfg_blocks + b; b > 0; b--, bb--) {
|
||||
if (bb->flags & IR_BB_UNREACHABLE) {
|
||||
continue;
|
||||
}
|
||||
for (i = bb->end; i >= bb->start; i -= ctx->prev_insn_len[i]) {
|
||||
insn = &ctx->ir_base[i];
|
||||
if (!ctx->rules[i]) {
|
||||
ctx->rules[i] = ir_match_insn(ctx, i, bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* code genertion */
|
||||
static int32_t ir_ref_spill_slot(ir_ctx *ctx, ir_ref ref, ir_reg *reg)
|
||||
{
|
||||
@ -2206,25 +2160,6 @@ static void ir_emit_store(ir_ctx *ctx, ir_type type, ir_ref dst, ir_reg reg)
|
||||
}
|
||||
}
|
||||
|
||||
static bool ir_is_same_mem(ir_ctx *ctx, ir_ref r1, ir_ref r2)
|
||||
{
|
||||
ir_live_interval *ival1, *ival2;
|
||||
int32_t o1, o2;
|
||||
|
||||
if (IR_IS_CONST_REF(r1) || IR_IS_CONST_REF(r2)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
IR_ASSERT(ctx->vregs[r1] && ctx->vregs[r2]);
|
||||
ival1 = ctx->live_intervals[ctx->vregs[r1]];
|
||||
ival2 = ctx->live_intervals[ctx->vregs[r2]];
|
||||
IR_ASSERT(ival1 && ival2);
|
||||
o1 = ival1->stack_spill_pos;
|
||||
o2 = ival2->stack_spill_pos;
|
||||
IR_ASSERT(o1 != -1 && o2 != -1);
|
||||
return o1 == o2;
|
||||
}
|
||||
|
||||
static void ir_emit_mov(ir_ctx *ctx, ir_type type, ir_reg dst, ir_reg src)
|
||||
{
|
||||
ir_backend_data *data = ctx->data;
|
||||
@ -5731,27 +5666,6 @@ static void ir_emit_switch(ir_ctx *ctx, int b, ir_ref def, ir_insn *insn)
|
||||
}
|
||||
}
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
static void *ir_resolve_sym_name(const char *name)
|
||||
{
|
||||
void *handle = NULL;
|
||||
void *addr;
|
||||
|
||||
#ifdef RTLD_DEFAULT
|
||||
handle = RTLD_DEFAULT;
|
||||
#endif
|
||||
addr = dlsym(handle, name);
|
||||
IR_ASSERT(addr != NULL);
|
||||
return addr;
|
||||
}
|
||||
|
||||
typedef struct _ir_copy {
|
||||
ir_type type;
|
||||
ir_reg from;
|
||||
ir_reg to;
|
||||
} ir_copy;
|
||||
|
||||
static int ir_parallel_copy(ir_ctx *ctx, ir_copy *copies, int count, ir_reg tmp_reg, ir_reg tmp_fp_reg)
|
||||
{
|
||||
int i;
|
||||
@ -6260,29 +6174,6 @@ static void ir_emit_tailcall(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IR_SNAPSHOT_HANDLER_DCL
|
||||
IR_SNAPSHOT_HANDLER_DCL();
|
||||
#endif
|
||||
|
||||
static void *ir_jmp_addr(ir_ctx *ctx, ir_insn *insn, ir_insn *addr_insn)
|
||||
{
|
||||
void *addr;
|
||||
|
||||
IR_ASSERT(addr_insn->type == IR_ADDR);
|
||||
if (addr_insn->op == IR_FUNC) {
|
||||
addr = ir_resolve_sym_name(ir_get_str(ctx, addr_insn->val.addr));
|
||||
} else {
|
||||
IR_ASSERT(addr_insn->op == IR_ADDR || addr_insn->op == IR_FUNC_ADDR);
|
||||
addr = (void*)addr_insn->val.addr;
|
||||
}
|
||||
#ifdef IR_SNAPSHOT_HANDLER
|
||||
if (ctx->ir_base[insn->op1].op == IR_SNAPSHOT) {
|
||||
addr = IR_SNAPSHOT_HANDLER(ctx, insn->op1, &ctx->ir_base[insn->op1], addr);
|
||||
}
|
||||
#endif
|
||||
return addr;
|
||||
}
|
||||
|
||||
static void ir_emit_ijmp(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
{
|
||||
ir_backend_data *data = ctx->data;
|
||||
|
Loading…
Reference in New Issue
Block a user