issue #169 update MIR code from upstream

lua54-randomgen
Dibyendu Majumdar 4 years ago
parent 4d6f9dd9f2
commit bf5aa3e3f6

@ -12308,17 +12308,7 @@ static void compile_finish (MIR_context_t ctx) {
if (init_object_path != NULL) VARR_DESTROY (init_object_t, init_object_path);
}
#include <sys/time.h>
#if defined(__unix__) || defined(__APPLE__)
#include <sys/stat.h>
#endif
static double real_usec_time (void) {
struct timeval tv;
gettimeofday (&tv, NULL);
return tv.tv_usec + tv.tv_sec * 1000000.0;
}
#include "real-time.h"
static const char *get_module_name (MIR_context_t ctx) {
c2m_ctx_t c2m_ctx = *c2m_ctx_loc (ctx);

@ -146,8 +146,8 @@ static MIR_reg_t get_arg_reg (MIR_type_t arg_type, size_t *int_arg_num, size_t *
return arg_reg;
}
static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void machinize_call (gen_ctx_t gen_ctx, MIR_insn_t call_insn) {
MIR_context_t ctx = gen_ctx->ctx;
MIR_func_t func = curr_func_item->u.func;
MIR_proto_t proto = call_insn->ops[0].u.ref->u.proto;
size_t nargs, nops = MIR_insn_nops (ctx, call_insn), start = proto->nres + 2;
@ -173,10 +173,10 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
}
if (call_insn->ops[1].mode != MIR_OP_REG && call_insn->ops[1].mode != MIR_OP_HARD_REG) {
// ??? to optimize (can be immediate operand for func call)
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
new_insn = MIR_new_insn (ctx, MIR_MOV, temp_op, call_insn->ops[1]);
call_insn->ops[1] = temp_op;
gen_add_insn_before (ctx, call_insn, new_insn);
gen_add_insn_before (gen_ctx, call_insn, new_insn);
}
for (size_t i = start; i < nops; i++) {
arg_op = call_insn->ops[i];
@ -194,17 +194,17 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
}
ext_insn = NULL;
if ((ext_code = get_ext_code (type)) != MIR_INVALID_INSN) { /* extend arg if necessary */
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
ext_insn = MIR_new_insn (ctx, ext_code, temp_op, arg_op);
call_insn->ops[i] = arg_op = temp_op;
}
if ((arg_reg = get_arg_reg (type, &int_arg_num, &fp_arg_num, &new_insn_code))
!= MIR_NON_HARD_REG) {
/* put arguments to argument hard regs */
if (ext_insn != NULL) gen_add_insn_before (ctx, call_insn, ext_insn);
if (ext_insn != NULL) gen_add_insn_before (gen_ctx, call_insn, ext_insn);
arg_reg_op = _MIR_new_hard_reg_op (ctx, arg_reg);
new_insn = MIR_new_insn (ctx, new_insn_code, arg_reg_op, arg_op);
gen_add_insn_before (ctx, call_insn, new_insn);
gen_add_insn_before (gen_ctx, call_insn, new_insn);
call_insn->ops[i] = arg_reg_op;
} else { /* put arguments on the stack */
if (type == MIR_T_LD && mem_size % 16 != 0) mem_size = (mem_size + 15) / 16 * 16;
@ -218,10 +218,10 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
MIR_insert_insn_after (ctx, curr_func_item, prev_call_insn, new_insn);
prev_insn = DLIST_PREV (MIR_insn_t, new_insn);
next_insn = DLIST_NEXT (MIR_insn_t, new_insn);
create_new_bb_insns (ctx, prev_insn, next_insn, call_insn);
create_new_bb_insns (gen_ctx, prev_insn, next_insn, call_insn);
call_insn->ops[i] = mem_op;
mem_size += type == MIR_T_LD ? 16 : 8;
if (ext_insn != NULL) gen_add_insn_after (ctx, prev_call_insn, ext_insn);
if (ext_insn != NULL) gen_add_insn_after (gen_ctx, prev_call_insn, ext_insn);
}
}
n_iregs = n_vregs = 0;
@ -252,7 +252,7 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
MIR_new_insn (ctx, ext_code, ret_reg_op, ret_reg_op));
new_insn = DLIST_NEXT (MIR_insn_t, new_insn);
}
create_new_bb_insns (ctx, call_insn, DLIST_NEXT (MIR_insn_t, new_insn), call_insn);
create_new_bb_insns (gen_ctx, call_insn, DLIST_NEXT (MIR_insn_t, new_insn), call_insn);
}
if (mem_size != 0) { /* allocate/deallocate stack for args passed on stack */
mem_size = (mem_size + 15) / 16 * 16; /* make it of several 16 bytes */
@ -261,13 +261,13 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
_MIR_new_hard_reg_op (ctx, SP_HARD_REG), MIR_new_int_op (ctx, mem_size));
MIR_insert_insn_after (ctx, curr_func_item, prev_call_insn, new_insn);
next_insn = DLIST_NEXT (MIR_insn_t, new_insn);
create_new_bb_insns (ctx, prev_call_insn, next_insn, call_insn);
create_new_bb_insns (gen_ctx, prev_call_insn, next_insn, call_insn);
new_insn
= MIR_new_insn (ctx, MIR_ADD, _MIR_new_hard_reg_op (ctx, SP_HARD_REG),
_MIR_new_hard_reg_op (ctx, SP_HARD_REG), MIR_new_int_op (ctx, mem_size));
MIR_insert_insn_after (ctx, curr_func_item, call_insn, new_insn);
next_insn = DLIST_NEXT (MIR_insn_t, new_insn);
create_new_bb_insns (ctx, call_insn, next_insn, call_insn);
create_new_bb_insns (gen_ctx, call_insn, next_insn, call_insn);
}
}
@ -346,9 +346,9 @@ static int64_t mir_ldle (long double d1, long double d2) { return d1 <= d2; }
static const char *LDLE = "mir.ldle";
static const char *LDLE_P = "mir.ldle.p";
static int get_builtin (MIR_context_t ctx, MIR_insn_code_t code, MIR_item_t *proto_item,
static int get_builtin (gen_ctx_t gen_ctx, MIR_insn_code_t code, MIR_item_t *proto_item,
MIR_item_t *func_import_item) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
MIR_context_t ctx = gen_ctx->ctx;
MIR_type_t res_type;
*func_import_item = *proto_item = NULL; /* to remove uninitialized warning */
@ -471,9 +471,9 @@ static int get_builtin (MIR_context_t ctx, MIR_insn_code_t code, MIR_item_t *pro
}
}
static void gen_mov (MIR_context_t ctx, MIR_insn_t anchor, MIR_insn_code_t code, MIR_op_t dst_op,
static void gen_mov (gen_ctx_t gen_ctx, MIR_insn_t anchor, MIR_insn_code_t code, MIR_op_t dst_op,
MIR_op_t src_op) {
gen_add_insn_before (ctx, anchor, MIR_new_insn (ctx, code, dst_op, src_op));
gen_add_insn_before (gen_ctx, anchor, MIR_new_insn (gen_ctx->ctx, code, dst_op, src_op));
}
DEF_VARR (int);
@ -518,17 +518,16 @@ struct target_ctx {
#define abs_address_locs gen_ctx->target_ctx->abs_address_locs
#define relocs gen_ctx->target_ctx->relocs
static MIR_disp_t target_get_stack_slot_offset (MIR_context_t ctx, MIR_type_t type,
static MIR_disp_t target_get_stack_slot_offset (gen_ctx_t gen_ctx, MIR_type_t type,
MIR_reg_t slot) {
/* slot is 0, 1, ... */
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
size_t offset = curr_func_item->u.func->vararg_p || stack_arg_func_p ? 32 : 16;
return ((MIR_disp_t) slot * 8 + offset);
}
static void target_machinize (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void target_machinize (gen_ctx_t gen_ctx) {
MIR_context_t ctx = gen_ctx->ctx;
MIR_func_t func;
MIR_type_t type, mem_type, res_type;
MIR_insn_code_t code, new_insn_code;
@ -548,13 +547,13 @@ static void target_machinize (MIR_context_t ctx) {
arg_reg = get_arg_reg (type, &int_arg_num, &fp_arg_num, &new_insn_code);
if (arg_reg != MIR_NON_HARD_REG) {
arg_reg_op = _MIR_new_hard_reg_op (ctx, arg_reg);
gen_mov (ctx, anchor, new_insn_code, MIR_new_reg_op (ctx, i + 1), arg_reg_op);
gen_mov (gen_ctx, anchor, new_insn_code, MIR_new_reg_op (ctx, i + 1), arg_reg_op);
} else {
/* arg is on the stack */
if (!stack_arg_func_p) {
stack_arg_func_p = TRUE;
prev_sp_op = _MIR_new_hard_reg_op (ctx, R8_HARD_REG);
gen_mov (ctx, anchor, MIR_MOV, prev_sp_op,
gen_mov (gen_ctx, anchor, MIR_MOV, prev_sp_op,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, 16, FP_HARD_REG, MIR_NON_HARD_REG, 1));
}
mem_type = type == MIR_T_F || type == MIR_T_D || type == MIR_T_LD ? type : MIR_T_I64;
@ -563,7 +562,7 @@ static void target_machinize (MIR_context_t ctx) {
= (type == MIR_T_F ? MIR_FMOV
: type == MIR_T_D ? MIR_DMOV : type == MIR_T_LD ? MIR_LDMOV : MIR_MOV);
mem_op = _MIR_new_hard_reg_mem_op (ctx, mem_type, mem_size, R8_HARD_REG, MIR_NON_HARD_REG, 1);
gen_mov (ctx, anchor, new_insn_code, MIR_new_reg_op (ctx, i + 1), mem_op);
gen_mov (gen_ctx, anchor, new_insn_code, MIR_new_reg_op (ctx, i + 1), mem_op);
mem_size += type == MIR_T_LD ? 16 : 8;
}
}
@ -577,7 +576,7 @@ static void target_machinize (MIR_context_t ctx) {
code = insn->code;
if (code == MIR_LDBEQ || code == MIR_LDBNE || code == MIR_LDBLT || code == MIR_LDBGE
|| code == MIR_LDBGT || code == MIR_LDBLE) {
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
code = (code == MIR_LDBEQ
? MIR_LDEQ
: code == MIR_LDBNE
@ -586,13 +585,13 @@ static void target_machinize (MIR_context_t ctx) {
? MIR_LDLT
: code == MIR_LDBGE ? MIR_LDGE : code == MIR_LDBGT ? MIR_LDGT : MIR_LDLE);
new_insn = MIR_new_insn (ctx, code, temp_op, insn->ops[1], insn->ops[2]);
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
next_insn = MIR_new_insn (ctx, MIR_BT, insn->ops[0], temp_op);
gen_add_insn_after (ctx, new_insn, next_insn);
gen_delete_insn (ctx, insn);
gen_add_insn_after (gen_ctx, new_insn, next_insn);
gen_delete_insn (gen_ctx, insn);
insn = new_insn;
}
if ((nargs = get_builtin (ctx, code, &proto_item, &func_import_item)) > 0) {
if ((nargs = get_builtin (gen_ctx, code, &proto_item, &func_import_item)) > 0) {
if (code == MIR_VA_ARG) { /* do nothing */
/* Use a builtin func call:
mov func_reg, func ref; mov flag_reg, <type>; call proto, func_reg, res_reg, va_reg,
@ -602,46 +601,45 @@ static void target_machinize (MIR_context_t ctx) {
assert (res_reg_op.mode == MIR_OP_REG && va_reg_op.mode == MIR_OP_REG
&& mem_op.mode == MIR_OP_MEM);
func_reg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
flag_reg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
func_reg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
flag_reg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
next_insn = new_insn
= MIR_new_insn (ctx, MIR_MOV, func_reg_op, MIR_new_ref_op (ctx, func_import_item));
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
new_insn = MIR_new_insn (ctx, MIR_MOV, flag_reg_op,
MIR_new_int_op (ctx, (int64_t) mem_op.u.mem.type));
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
ops[0] = MIR_new_ref_op (ctx, proto_item);
ops[1] = func_reg_op;
ops[2] = res_reg_op;
ops[3] = va_reg_op;
ops[4] = flag_reg_op;
new_insn = MIR_new_insn_arr (ctx, MIR_CALL, 5, ops);
gen_add_insn_before (ctx, insn, new_insn);
gen_delete_insn (ctx, insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
gen_delete_insn (gen_ctx, insn);
} else { /* Use builtin: mov freg, func ref; call proto, freg, res_reg, op_reg[, op_reg2] */
MIR_op_t freg_op, res_reg_op = insn->ops[0], op_reg_op = insn->ops[1], ops[5];
assert (res_reg_op.mode == MIR_OP_REG && op_reg_op.mode == MIR_OP_REG);
freg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
freg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
next_insn = new_insn
= MIR_new_insn (ctx, MIR_MOV, freg_op, MIR_new_ref_op (ctx, func_import_item));
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
ops[0] = MIR_new_ref_op (ctx, proto_item);
ops[1] = freg_op;
ops[2] = res_reg_op;
ops[3] = op_reg_op;
if (nargs == 2) ops[4] = insn->ops[2];
new_insn = MIR_new_insn_arr (ctx, MIR_CALL, nargs + 3, ops);
gen_add_insn_before (ctx, insn, new_insn);
gen_delete_insn (ctx, insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
gen_delete_insn (gen_ctx, insn);
}
} else if (code == MIR_VA_START) {
MIR_op_t treg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
MIR_op_t prev_sp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
MIR_op_t treg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
MIR_op_t prev_sp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
MIR_op_t va_op = insn->ops[0];
MIR_reg_t va_reg;
int gp_offset, fp_offset;
MIR_var_t var;
assert (func->vararg_p && va_op.mode == MIR_OP_REG);
gp_offset = (int_arg_num >= 8 ? 0 : 8 * int_arg_num - 64);
@ -649,28 +647,29 @@ static void target_machinize (MIR_context_t ctx) {
va_reg = va_op.u.reg;
/* Insns can be not simplified as soon as they match a machine insn. */
/* mem32[va_reg].__gr_offset = gp_offset; mem32[va_reg].__vr_offset = fp_offset */
gen_mov (ctx, insn, MIR_MOV, treg_op, MIR_new_int_op (ctx, gp_offset));
gen_mov (ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_U32, 24, va_reg, 0, 1), treg_op);
gen_mov (ctx, insn, MIR_MOV, treg_op, MIR_new_int_op (ctx, fp_offset));
gen_mov (ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_U32, 28, va_reg, 0, 1), treg_op);
gen_mov (gen_ctx, insn, MIR_MOV, treg_op, MIR_new_int_op (ctx, gp_offset));
gen_mov (gen_ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_U32, 24, va_reg, 0, 1), treg_op);
gen_mov (gen_ctx, insn, MIR_MOV, treg_op, MIR_new_int_op (ctx, fp_offset));
gen_mov (gen_ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_U32, 28, va_reg, 0, 1), treg_op);
/* __stack: prev_sp = mem64[fp + 16]; mem64[va_reg].__stack = prev_sp + mem_size */
gen_mov (ctx, insn, MIR_MOV, prev_sp_op,
gen_mov (gen_ctx, insn, MIR_MOV, prev_sp_op,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, 16, FP_HARD_REG, MIR_NON_HARD_REG, 1));
new_insn = MIR_new_insn (ctx, MIR_ADD, treg_op, prev_sp_op, MIR_new_int_op (ctx, mem_size));
gen_add_insn_before (ctx, insn, new_insn);
gen_mov (ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 0, va_reg, 0, 1), treg_op);
gen_add_insn_before (gen_ctx, insn, new_insn);
gen_mov (gen_ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 0, va_reg, 0, 1), treg_op);
/* __gr_top: mem64[va_reg].__gr_top = prev_sp */
gen_mov (ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 8, va_reg, 0, 1), prev_sp_op);
gen_mov (gen_ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 8, va_reg, 0, 1),
prev_sp_op);
/* __vr_top: treg = prev_sp - int_reg_save_area; mem64[va_reg].__vr_top = treg */
new_insn = MIR_new_insn (ctx, MIR_SUB, treg_op, prev_sp_op,
MIR_new_int_op (ctx, int_reg_save_area_size));
gen_add_insn_before (ctx, insn, new_insn);
gen_mov (ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 16, va_reg, 0, 1), treg_op);
gen_delete_insn (ctx, insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
gen_mov (gen_ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 16, va_reg, 0, 1), treg_op);
gen_delete_insn (gen_ctx, insn);
} else if (code == MIR_VA_END) { /* do nothing */
gen_delete_insn (ctx, insn);
gen_delete_insn (gen_ctx, insn);
} else if (MIR_call_code_p (code)) {
machinize_call (ctx, insn);
machinize_call (gen_ctx, insn);
leaf_p = FALSE;
} else if (code == MIR_ALLOCA) {
alloca_p = TRUE;
@ -695,28 +694,30 @@ static void target_machinize (MIR_context_t ctx) {
"aarch64 can not handle this combination of return values");
}
ret_reg_op = _MIR_new_hard_reg_op (ctx, ret_reg);
gen_mov (ctx, insn, new_insn_code, ret_reg_op, insn->ops[i]);
gen_mov (gen_ctx, insn, new_insn_code, ret_reg_op, insn->ops[i]);
insn->ops[i] = ret_reg_op;
}
}
}
}
static void isave (MIR_context_t ctx, MIR_insn_t anchor, int disp, MIR_reg_t base, MIR_reg_t hard_reg) {
gen_mov (ctx, anchor, MIR_MOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, disp, base, MIR_NON_HARD_REG, 1),
_MIR_new_hard_reg_op (ctx, hard_reg));
static void isave (gen_ctx_t gen_ctx, MIR_insn_t anchor, int disp, MIR_reg_t base,
MIR_reg_t hard_reg) {
gen_mov (gen_ctx, anchor, MIR_MOV,
_MIR_new_hard_reg_mem_op (gen_ctx->ctx, MIR_T_I64, disp, base, MIR_NON_HARD_REG, 1),
_MIR_new_hard_reg_op (gen_ctx->ctx, hard_reg));
}
static void fsave (MIR_context_t ctx, MIR_insn_t anchor, int disp, MIR_reg_t base, MIR_reg_t hard_reg) {
gen_mov (ctx, anchor, MIR_LDMOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_LD, disp, base, MIR_NON_HARD_REG, 1),
_MIR_new_hard_reg_op (ctx, hard_reg));
static void fsave (gen_ctx_t gen_ctx, MIR_insn_t anchor, int disp, MIR_reg_t base,
MIR_reg_t hard_reg) {
gen_mov (gen_ctx, anchor, MIR_LDMOV,
_MIR_new_hard_reg_mem_op (gen_ctx->ctx, MIR_T_LD, disp, base, MIR_NON_HARD_REG, 1),
_MIR_new_hard_reg_op (gen_ctx->ctx, hard_reg));
}
static void target_make_prolog_epilog (MIR_context_t ctx, bitmap_t used_hard_regs,
static void target_make_prolog_epilog (gen_ctx_t gen_ctx, bitmap_t used_hard_regs,
size_t stack_slots_num) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
MIR_context_t ctx = gen_ctx->ctx;
MIR_func_t func;
MIR_insn_t anchor, new_insn;
MIR_op_t sp_reg_op, fp_reg_op, treg_op, treg_op2;
@ -757,7 +758,7 @@ static void target_make_prolog_epilog (MIR_context_t ctx, bitmap_t used_hard_reg
save_prev_stack_p = func->vararg_p || stack_arg_func_p;
treg_op = _MIR_new_hard_reg_op (ctx, R9_HARD_REG);
if (save_prev_stack_p) { /* prev stack pointer */
gen_mov (ctx, anchor, MIR_MOV, treg_op, sp_reg_op);
gen_mov (gen_ctx, anchor, MIR_MOV, treg_op, sp_reg_op);
frame_size += 16;
}
frame_size += 16; /* lr/fp */
@ -766,61 +767,61 @@ static void target_make_prolog_epilog (MIR_context_t ctx, bitmap_t used_hard_reg
} else {
treg_op2 = _MIR_new_hard_reg_op (ctx, R10_HARD_REG);
new_insn = MIR_new_insn (ctx, MIR_MOV, treg_op2, MIR_new_int_op (ctx, frame_size));
gen_add_insn_before (ctx, anchor, new_insn); /* t = frame_size */
gen_add_insn_before (gen_ctx, anchor, new_insn); /* t = frame_size */
new_insn = MIR_new_insn (ctx, MIR_SUB, sp_reg_op, sp_reg_op, treg_op2);
}
gen_add_insn_before (ctx, anchor, new_insn); /* sp = sp - (frame_size|t) */
gen_add_insn_before (gen_ctx, anchor, new_insn); /* sp = sp - (frame_size|t) */
if (save_prev_stack_p)
gen_mov (ctx, anchor, MIR_MOV,
gen_mov (gen_ctx, anchor, MIR_MOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, 16, SP_HARD_REG, MIR_NON_HARD_REG, 1),
treg_op); /* mem[sp + 16] = treg */
gen_mov (ctx, anchor, MIR_MOV,
gen_mov (gen_ctx, anchor, MIR_MOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, 8, SP_HARD_REG, MIR_NON_HARD_REG, 1),
_MIR_new_hard_reg_op (ctx, LINK_HARD_REG)); /* mem[sp + 8] = lr */
gen_mov (ctx, anchor, MIR_MOV,
gen_mov (gen_ctx, anchor, MIR_MOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, 0, SP_HARD_REG, MIR_NON_HARD_REG, 1),
_MIR_new_hard_reg_op (ctx, FP_HARD_REG)); /* mem[sp] = fp */
gen_mov (ctx, anchor, MIR_MOV, fp_reg_op, sp_reg_op); /* fp = sp */
_MIR_new_hard_reg_op (ctx, FP_HARD_REG)); /* mem[sp] = fp */
gen_mov (gen_ctx, anchor, MIR_MOV, fp_reg_op, sp_reg_op); /* fp = sp */
if (func->vararg_p) {
MIR_reg_t base = SP_HARD_REG;
start = (int64_t) frame_size - reg_save_area_size;
if ((start + 184) >= (1 << 12)) {
new_insn = MIR_new_insn (ctx, MIR_MOV, treg_op, MIR_new_int_op (ctx, start));
gen_add_insn_before (ctx, anchor, new_insn); /* t = frame_size - reg_save_area_size */
gen_add_insn_before (gen_ctx, anchor, new_insn); /* t = frame_size - reg_save_area_size */
start = 0;
base = R9_HARD_REG;
}
fsave (ctx, anchor, start, base, V0_HARD_REG);
fsave (ctx, anchor, start + 16, base, V1_HARD_REG);
fsave (ctx, anchor, start + 32, base, V2_HARD_REG);
fsave (ctx, anchor, start + 48, base, V3_HARD_REG);
fsave (ctx, anchor, start + 64, base, V4_HARD_REG);
fsave (ctx, anchor, start + 80, base, V5_HARD_REG);
fsave (ctx, anchor, start + 96, base, V6_HARD_REG);
fsave (ctx, anchor, start + 112, base, V7_HARD_REG);
isave (ctx, anchor, start + 128, base, R0_HARD_REG);
isave (ctx, anchor, start + 136, base, R1_HARD_REG);
isave (ctx, anchor, start + 144, base, R2_HARD_REG);
isave (ctx, anchor, start + 152, base, R3_HARD_REG);
isave (ctx, anchor, start + 160, base, R4_HARD_REG);
isave (ctx, anchor, start + 168, base, R5_HARD_REG);
isave (ctx, anchor, start + 176, base, R6_HARD_REG);
isave (ctx, anchor, start + 184, base, R7_HARD_REG);
fsave (gen_ctx, anchor, start, base, V0_HARD_REG);
fsave (gen_ctx, anchor, start + 16, base, V1_HARD_REG);
fsave (gen_ctx, anchor, start + 32, base, V2_HARD_REG);
fsave (gen_ctx, anchor, start + 48, base, V3_HARD_REG);
fsave (gen_ctx, anchor, start + 64, base, V4_HARD_REG);
fsave (gen_ctx, anchor, start + 80, base, V5_HARD_REG);
fsave (gen_ctx, anchor, start + 96, base, V6_HARD_REG);
fsave (gen_ctx, anchor, start + 112, base, V7_HARD_REG);
isave (gen_ctx, anchor, start + 128, base, R0_HARD_REG);
isave (gen_ctx, anchor, start + 136, base, R1_HARD_REG);
isave (gen_ctx, anchor, start + 144, base, R2_HARD_REG);
isave (gen_ctx, anchor, start + 152, base, R3_HARD_REG);
isave (gen_ctx, anchor, start + 160, base, R4_HARD_REG);
isave (gen_ctx, anchor, start + 168, base, R5_HARD_REG);
isave (gen_ctx, anchor, start + 176, base, R6_HARD_REG);
isave (gen_ctx, anchor, start + 184, base, R7_HARD_REG);
}
/* Saving callee saved hard registers: */
offset = frame_size - frame_size_after_saved_regs;
for (i = 0; i <= MAX_HARD_REG; i++)
if (!target_call_used_hard_reg_p (i) && bitmap_bit_p (used_hard_regs, i)) {
if (i < V0_HARD_REG) {
gen_mov (ctx, anchor, MIR_MOV,
gen_mov (gen_ctx, anchor, MIR_MOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, offset, FP_HARD_REG, MIR_NON_HARD_REG,
1),
_MIR_new_hard_reg_op (ctx, i));
offset += 8;
} else {
if (offset % 16 != 0) offset = (offset + 15) / 16 * 16;
gen_mov (ctx, anchor, MIR_LDMOV,
gen_mov (gen_ctx, anchor, MIR_LDMOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_LD, offset, FP_HARD_REG, MIR_NON_HARD_REG, 1),
_MIR_new_hard_reg_op (ctx, i));
offset += 16;
@ -834,30 +835,30 @@ static void target_make_prolog_epilog (MIR_context_t ctx, bitmap_t used_hard_reg
for (i = 0; i <= MAX_HARD_REG; i++)
if (!target_call_used_hard_reg_p (i) && bitmap_bit_p (used_hard_regs, i)) {
if (i < V0_HARD_REG) {
gen_mov (ctx, anchor, MIR_MOV, _MIR_new_hard_reg_op (ctx, i),
gen_mov (gen_ctx, anchor, MIR_MOV, _MIR_new_hard_reg_op (ctx, i),
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, offset, FP_HARD_REG, MIR_NON_HARD_REG,
1));
offset += 8;
} else {
if (offset % 16 != 0) offset = (offset + 15) / 16 * 16;
gen_mov (ctx, anchor, MIR_LDMOV, _MIR_new_hard_reg_op (ctx, i),
gen_mov (gen_ctx, anchor, MIR_LDMOV, _MIR_new_hard_reg_op (ctx, i),
_MIR_new_hard_reg_mem_op (ctx, MIR_T_LD, offset, FP_HARD_REG, MIR_NON_HARD_REG,
1));
offset += 16;
}
}
/* Restore lr, sp, fp */
gen_mov (ctx, anchor, MIR_MOV, _MIR_new_hard_reg_op (ctx, LINK_HARD_REG),
gen_mov (gen_ctx, anchor, MIR_MOV, _MIR_new_hard_reg_op (ctx, LINK_HARD_REG),
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, 8, FP_HARD_REG, MIR_NON_HARD_REG, 1));
if (frame_size < (1 << 12)) {
new_insn = MIR_new_insn (ctx, MIR_ADD, sp_reg_op, fp_reg_op, MIR_new_int_op (ctx, frame_size));
} else {
} else {
new_insn = MIR_new_insn (ctx, MIR_MOV, treg_op, MIR_new_int_op (ctx, frame_size));
gen_add_insn_before (ctx, anchor, new_insn); /* t = frame_size */
gen_add_insn_before (gen_ctx, anchor, new_insn); /* t = frame_size */
new_insn = MIR_new_insn (ctx, MIR_ADD, sp_reg_op, fp_reg_op, treg_op);
}
gen_add_insn_before (ctx, anchor, new_insn); /* sp = fp + (frame_size|t) */
gen_mov (ctx, anchor, MIR_MOV, fp_reg_op,
gen_add_insn_before (gen_ctx, anchor, new_insn); /* sp = fp + (frame_size|t) */
gen_mov (gen_ctx, anchor, MIR_MOV, fp_reg_op,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, 0, FP_HARD_REG, MIR_NON_HARD_REG, 1));
}
@ -1454,8 +1455,7 @@ static int pattern_index_cmp (const void *a1, const void *a2) {
return c1 != c2 ? c1 - c2 : (long) i1 - (long) i2;
}
static void patterns_init (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void patterns_init (gen_ctx_t gen_ctx) {
int i, ind, n = sizeof (patterns) / sizeof (struct pattern);
MIR_insn_code_t prev_code, code;
insn_pattern_info_t *info_addr;
@ -1544,13 +1544,13 @@ static int lshift_const_p (int64_t v, int short_p, int *immr, int *imms) {
return TRUE;
}
static int pattern_match_p (MIR_context_t ctx, const struct pattern *pat, MIR_insn_t insn) {
int nop, n;
static int pattern_match_p (gen_ctx_t gen_ctx, const struct pattern *pat, MIR_insn_t insn) {
MIR_context_t ctx = gen_ctx->ctx;
int nop;
size_t nops = MIR_insn_nops (ctx, insn);
const char *p;
char ch, start_ch;
MIR_op_mode_t mode;
MIR_op_t op, original;
MIR_op_t op;
MIR_reg_t hr;
for (nop = 0, p = pat->pattern; *p != 0; p++, nop++) {
@ -1660,7 +1660,7 @@ static int pattern_match_p (MIR_context_t ctx, const struct pattern *pat, MIR_in
if (op.u.d != 0.0) return FALSE;
} else {
if (op.mode != MIR_OP_INT && op.mode != MIR_OP_UINT && op.mode != MIR_OP_REF) return FALSE;
gen_assert ('0' <= ch && ch <= '2' || start_ch == 'Z' && ch == '3');
gen_assert (('0' <= ch && ch <= '2') || (start_ch == 'Z' && ch == '3'));
n = ch - '0';
if (op.mode != MIR_OP_REF) {
v = op.u.u;
@ -1718,22 +1718,19 @@ static int pattern_match_p (MIR_context_t ctx, const struct pattern *pat, MIR_in
return TRUE;
}
static const char *find_insn_pattern_replacement (MIR_context_t ctx, MIR_insn_t insn) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static const char *find_insn_pattern_replacement (gen_ctx_t gen_ctx, MIR_insn_t insn) {
int i;
const struct pattern *pat;
insn_pattern_info_t info = VARR_GET (insn_pattern_info_t, insn_pattern_info, insn->code);
for (i = 0; i < info.num; i++) {
pat = &patterns[VARR_GET (int, pattern_indexes, info.start + i)];
if (pattern_match_p (ctx, pat, insn)) return pat->replacement;
if (pattern_match_p (gen_ctx, pat, insn)) return pat->replacement;
}
return NULL;
}
static void patterns_finish (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void patterns_finish (gen_ctx_t gen_ctx) {
VARR_DESTROY (int, pattern_indexes);
VARR_DESTROY (insn_pattern_info_t, insn_pattern_info);
}
@ -1788,8 +1785,8 @@ static uint32_t check_and_set_mask (uint32_t opcode_mask, uint32_t mask) {
return opcode_mask | mask;
}
static void out_insn (MIR_context_t ctx, MIR_insn_t insn, const char *replacement) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void out_insn (gen_ctx_t gen_ctx, MIR_insn_t insn, const char *replacement) {
MIR_context_t ctx = gen_ctx->ctx;
size_t offset;
const char *p, *insn_str;
label_ref_t lr;
@ -1870,7 +1867,7 @@ static void out_insn (MIR_context_t ctx, MIR_insn_t insn, const char *replacemen
scale = op.u.hard_reg_mem.scale;
break;
case 'M': {
int scale;
int scale = 1;
op = insn->ops[0].mode == MIR_OP_HARD_REG_MEM ? insn->ops[0] : insn->ops[1];
switch (op.u.hard_reg_mem.type) {
@ -1900,7 +1897,7 @@ static void out_insn (MIR_context_t ctx, MIR_insn_t insn, const char *replacemen
break;
}
case 'S': { /* S, SL, Sl */
int flag, r, s;
int flag;
op = insn->ops[2];
gen_assert (op.mode == MIR_OP_INT || op.mode == MIR_OP_UINT);
@ -2060,12 +2057,12 @@ static void out_insn (MIR_context_t ctx, MIR_insn_t insn, const char *replacemen
}
}
static int target_insn_ok_p (MIR_context_t ctx, MIR_insn_t insn) {
return find_insn_pattern_replacement (ctx, insn) != NULL;
static int target_insn_ok_p (gen_ctx_t gen_ctx, MIR_insn_t insn) {
return find_insn_pattern_replacement (gen_ctx, insn) != NULL;
}
static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static uint8_t *target_translate (gen_ctx_t gen_ctx, size_t *len) {
MIR_context_t ctx = gen_ctx->ctx;
size_t i;
MIR_insn_t insn;
const char *replacement;
@ -2077,16 +2074,16 @@ static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
for (insn = DLIST_HEAD (MIR_insn_t, curr_func_item->u.func->insns); insn != NULL;
insn = DLIST_NEXT (MIR_insn_t, insn)) {
if (insn->code == MIR_LABEL) {
set_label_disp (ctx, insn, VARR_LENGTH (uint8_t, result_code));
set_label_disp (gen_ctx, insn, VARR_LENGTH (uint8_t, result_code));
} else {
replacement = find_insn_pattern_replacement (ctx, insn);
replacement = find_insn_pattern_replacement (gen_ctx, insn);
if (replacement == NULL) {
fprintf (stderr, "fatal failure in matching insn:");
MIR_output_insn (ctx, stderr, insn, curr_func_item->u.func, TRUE);
exit (1);
} else {
gen_assert (replacement != NULL);
out_insn (ctx, insn, replacement);
out_insn (gen_ctx, insn, replacement);
}
}
}
@ -2095,8 +2092,8 @@ static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
label_ref_t lr = VARR_GET (label_ref_t, label_refs, i);
if (!lr.abs_addr_p) {
int64_t offset
= (int64_t) get_label_disp (ctx, lr.label) - (int64_t) lr.label_val_disp; /* pc offset */
int64_t offset = (int64_t) get_label_disp (gen_ctx, lr.label)
- (int64_t) lr.label_val_disp; /* pc offset */
gen_assert ((offset & 0x3) == 0);
if (lr.short_p)
*(uint32_t *) (VARR_ADDR (uint8_t, result_code) + lr.label_val_disp)
@ -2106,7 +2103,7 @@ static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
|= (offset / 4) & 0x3ffffff; /* 26-bit */
} else {
set_int64 (&VARR_ADDR (uint8_t, result_code)[lr.label_val_disp],
(int64_t) get_label_disp (ctx, lr.label), 8);
(int64_t) get_label_disp (gen_ctx, lr.label), 8);
VARR_PUSH (uint64_t, abs_address_locs, lr.label_val_disp);
}
}
@ -2116,8 +2113,7 @@ static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
return VARR_ADDR (uint8_t, result_code);
}
static void target_rebase (MIR_context_t ctx, uint8_t *base) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void target_rebase (gen_ctx_t gen_ctx, uint8_t *base) {
MIR_code_reloc_t reloc;
VARR_TRUNC (MIR_code_reloc_t, relocs, 0);
@ -2126,25 +2122,21 @@ static void target_rebase (MIR_context_t ctx, uint8_t *base) {
reloc.value = base + get_int64 (base + reloc.offset, 8);
VARR_PUSH (MIR_code_reloc_t, relocs, reloc);
}
_MIR_update_code_arr (ctx, base, VARR_LENGTH (MIR_code_reloc_t, relocs),
_MIR_update_code_arr (gen_ctx->ctx, base, VARR_LENGTH (MIR_code_reloc_t, relocs),
VARR_ADDR (MIR_code_reloc_t, relocs));
}
static void target_init (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
gen_ctx->target_ctx = gen_malloc (ctx, sizeof (struct target_ctx));
static void target_init (gen_ctx_t gen_ctx) {
gen_ctx->target_ctx = gen_malloc (gen_ctx, sizeof (struct target_ctx));
VARR_CREATE (uint8_t, result_code, 0);
VARR_CREATE (label_ref_t, label_refs, 0);
VARR_CREATE (uint64_t, abs_address_locs, 0);
VARR_CREATE (MIR_code_reloc_t, relocs, 0);
patterns_init (ctx);
patterns_init (gen_ctx);
}
static void target_finish (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
patterns_finish (ctx);
static void target_finish (gen_ctx_t gen_ctx) {
patterns_finish (gen_ctx);
VARR_DESTROY (uint8_t, result_code);
VARR_DESTROY (label_ref_t, label_refs);
VARR_DESTROY (uint64_t, abs_address_locs);

@ -160,13 +160,13 @@ struct target_ctx {
#define abs_address_locs gen_ctx->target_ctx->abs_address_locs
#define relocs gen_ctx->target_ctx->relocs
static void gen_mov (MIR_context_t ctx, MIR_insn_t anchor, MIR_insn_code_t code, MIR_op_t dst_op,
static void gen_mov (gen_ctx_t gen_ctx, MIR_insn_t anchor, MIR_insn_code_t code, MIR_op_t dst_op,
MIR_op_t src_op) {
gen_add_insn_before (ctx, anchor, MIR_new_insn (ctx, code, dst_op, src_op));
gen_add_insn_before (gen_ctx, anchor, MIR_new_insn (gen_ctx->ctx, code, dst_op, src_op));
}
static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void machinize_call (gen_ctx_t gen_ctx, MIR_insn_t call_insn) {
MIR_context_t ctx = gen_ctx->ctx;
MIR_func_t func = curr_func_item->u.func;
MIR_proto_t proto = call_insn->ops[0].u.ref->u.proto;
int vararg_p = proto->vararg_p;
@ -175,11 +175,10 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
MIR_type_t type, mem_type;
MIR_op_mode_t mode;
MIR_var_t *arg_vars = NULL;
MIR_reg_t arg_reg, ret_reg;
MIR_reg_t ret_reg;
MIR_op_t arg_op, temp_op, arg_reg_op, ret_reg_op, mem_op;
MIR_insn_code_t new_insn_code, ext_code;
MIR_insn_t new_insn, prev_insn, next_insn, ext_insn;
MIR_insn_t prev_call_insn = DLIST_PREV (MIR_insn_t, call_insn);
MIR_insn_t new_insn, ext_insn;
if (call_insn->code == MIR_INLINE) call_insn->code = MIR_CALL;
if (proto->args == NULL) {
@ -192,10 +191,10 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
}
if (call_insn->ops[1].mode != MIR_OP_REG && call_insn->ops[1].mode != MIR_OP_HARD_REG) {
// ??? to optimize (can be immediate operand for func call)
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
new_insn = MIR_new_insn (ctx, MIR_MOV, temp_op, call_insn->ops[1]);
call_insn->ops[1] = temp_op;
gen_add_insn_before (ctx, call_insn, new_insn);
gen_add_insn_before (gen_ctx, call_insn, new_insn);
}
for (size_t i = start; i < nops; i++) {
arg_op = call_insn->ops[i];
@ -213,55 +212,55 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
}
ext_insn = NULL;
if ((ext_code = get_ext_code (type)) != MIR_INVALID_INSN) { /* extend arg if necessary */
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
ext_insn = MIR_new_insn (ctx, ext_code, temp_op, arg_op);
call_insn->ops[i] = arg_op = temp_op;
}
mem_type = type == MIR_T_F || type == MIR_T_D || type == MIR_T_LD ? type : MIR_T_I64; // ???
if ((type == MIR_T_F || type == MIR_T_D || type == MIR_T_LD) && n_fregs < 13) {
/* put arguments to argument hard regs */
if (ext_insn != NULL) gen_add_insn_before (ctx, call_insn, ext_insn);
if (ext_insn != NULL) gen_add_insn_before (gen_ctx, call_insn, ext_insn);
arg_reg_op = _MIR_new_hard_reg_op (ctx, F1_HARD_REG + n_fregs);
gen_mov (ctx, call_insn,
gen_mov (gen_ctx, call_insn,
type == MIR_T_F ? MIR_FMOV : type == MIR_T_D ? MIR_DMOV : MIR_LDMOV, // ???
arg_reg_op, arg_op);
call_insn->ops[i] = arg_reg_op;
if (vararg_p) { // ??? dead insns
if (n_iregs >= 8 || type == MIR_T_LD && n_iregs == 7) { /* store in memory too */
if (vararg_p) { // ??? dead insns
if (n_iregs >= 8 || (type == MIR_T_LD && n_iregs == 7)) { /* store in memory too */
mem_op = _MIR_new_hard_reg_mem_op (ctx, mem_type, mem_size + PPC64_STACK_HEADER_SIZE,
SP_HARD_REG, MIR_NON_HARD_REG, 1);
gen_assert (n_fregs < 12);
gen_mov (ctx, call_insn, type == MIR_T_LD ? MIR_LDMOV : MIR_DMOV, mem_op, arg_reg_op);
gen_mov (gen_ctx, call_insn, type == MIR_T_LD ? MIR_LDMOV : MIR_DMOV, mem_op, arg_reg_op);
}
if (n_iregs < 8) { /* load into gp reg too */
mem_op = _MIR_new_hard_reg_mem_op (ctx, mem_type, -16, SP_HARD_REG, MIR_NON_HARD_REG, 1);
gen_mov (ctx, call_insn, type == MIR_T_LD ? MIR_LDMOV : MIR_DMOV, mem_op, arg_reg_op);
gen_mov (gen_ctx, call_insn, type == MIR_T_LD ? MIR_LDMOV : MIR_DMOV, mem_op, arg_reg_op);
mem_type = mem_type == MIR_T_F ? MIR_T_I32 : MIR_T_I64; // ???
mem_op = _MIR_new_hard_reg_mem_op (ctx, mem_type, -16, SP_HARD_REG, MIR_NON_HARD_REG, 1);
arg_reg_op = _MIR_new_hard_reg_op (ctx, R3_HARD_REG + n_iregs);
gen_mov (ctx, call_insn, MIR_MOV, arg_reg_op, mem_op);
gen_mov (gen_ctx, call_insn, MIR_MOV, arg_reg_op, mem_op);
call_insn->ops[i] = arg_reg_op; /* keep it alive */
if (type == MIR_T_LD && n_iregs + 1 < 8) {
mem_op = _MIR_new_hard_reg_mem_op (ctx, mem_type, -8, SP_HARD_REG, MIR_NON_HARD_REG, 1);
gen_mov (ctx, call_insn, MIR_MOV, _MIR_new_hard_reg_op (ctx, R3_HARD_REG + n_iregs + 1),
mem_op);
gen_mov (gen_ctx, call_insn, MIR_MOV,
_MIR_new_hard_reg_op (ctx, R3_HARD_REG + n_iregs + 1), mem_op);
}
}
}
n_fregs += type == MIR_T_LD ? 2 : 1;
} else if (type != MIR_T_F && type != MIR_T_D && type != MIR_T_LD && n_iregs < 8) {
if (ext_insn != NULL) gen_add_insn_before (ctx, call_insn, ext_insn);
if (ext_insn != NULL) gen_add_insn_before (gen_ctx, call_insn, ext_insn);
arg_reg_op = _MIR_new_hard_reg_op (ctx, R3_HARD_REG + n_iregs);
gen_mov (ctx, call_insn, MIR_MOV, arg_reg_op, arg_op);
gen_mov (gen_ctx, call_insn, MIR_MOV, arg_reg_op, arg_op);
call_insn->ops[i] = arg_reg_op;
} else { /* put arguments on the stack */
if (ext_insn != NULL) gen_add_insn_before (ctx, call_insn, ext_insn);
if (ext_insn != NULL) gen_add_insn_before (gen_ctx, call_insn, ext_insn);
new_insn_code
= (type == MIR_T_F ? MIR_FMOV
: type == MIR_T_D ? MIR_DMOV : type == MIR_T_LD ? MIR_LDMOV : MIR_MOV);
mem_op = _MIR_new_hard_reg_mem_op (ctx, mem_type, mem_size + PPC64_STACK_HEADER_SIZE,
SP_HARD_REG, MIR_NON_HARD_REG, 1);
gen_mov (ctx, call_insn, new_insn_code, mem_op, arg_op);
gen_mov (gen_ctx, call_insn, new_insn_code, mem_op, arg_op);
call_insn->ops[i] = mem_op;
}
mem_size += type == MIR_T_LD ? 16 : 8;
@ -297,7 +296,7 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
MIR_new_insn (ctx, ext_code, ret_reg_op, ret_reg_op));
new_insn = DLIST_NEXT (MIR_insn_t, new_insn);
}
create_new_bb_insns (ctx, call_insn, DLIST_NEXT (MIR_insn_t, new_insn), call_insn);
create_new_bb_insns (gen_ctx, call_insn, DLIST_NEXT (MIR_insn_t, new_insn), call_insn);
}
}
@ -376,9 +375,9 @@ static int64_t mir_ldle (long double d1, long double d2) { return d1 <= d2; }
static const char *LDLE = "mir.ldle";
static const char *LDLE_P = "mir.ldle.p";
static int get_builtin (MIR_context_t ctx, MIR_insn_code_t code, MIR_item_t *proto_item,
static int get_builtin (gen_ctx_t gen_ctx, MIR_insn_code_t code, MIR_item_t *proto_item,
MIR_item_t *func_import_item) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
MIR_context_t ctx = gen_ctx->ctx;
MIR_type_t res_type;
*func_import_item = *proto_item = NULL; /* to remove uninitialized warning */
@ -501,33 +500,30 @@ static int get_builtin (MIR_context_t ctx, MIR_insn_code_t code, MIR_item_t *pro
}
}
static MIR_disp_t target_get_stack_slot_offset (MIR_context_t ctx, MIR_type_t type,
static MIR_disp_t target_get_stack_slot_offset (gen_ctx_t gen_ctx, MIR_type_t type,
MIR_reg_t slot) {
/* slot is 0, 1, ... */
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
return ((MIR_disp_t) slot * 8 + PPC64_STACK_HEADER_SIZE + param_save_area_size);
}
static void set_prev_sp_op (MIR_context_t ctx, MIR_insn_t anchor, MIR_op_t *prev_sp_op) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void set_prev_sp_op (gen_ctx_t gen_ctx, MIR_insn_t anchor, MIR_op_t *prev_sp_op) {
if (!stack_arg_func_p) {
stack_arg_func_p = TRUE;
*prev_sp_op = _MIR_new_hard_reg_op (ctx, R11_HARD_REG);
gen_mov (ctx, anchor, MIR_MOV, *prev_sp_op,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, 0, SP_HARD_REG, MIR_NON_HARD_REG, 1));
*prev_sp_op = _MIR_new_hard_reg_op (gen_ctx->ctx, R11_HARD_REG);
gen_mov (gen_ctx, anchor, MIR_MOV, *prev_sp_op,
_MIR_new_hard_reg_mem_op (gen_ctx->ctx, MIR_T_I64, 0, SP_HARD_REG, MIR_NON_HARD_REG,
1));
}
}
static void target_machinize (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void target_machinize (gen_ctx_t gen_ctx) {
MIR_context_t ctx = gen_ctx->ctx;
MIR_func_t func;
MIR_type_t type, mem_type, res_type;
MIR_type_t type, res_type;
MIR_insn_code_t code, new_insn_code;
MIR_insn_t insn, next_insn, new_insn, anchor;
MIR_reg_t ret_reg, arg_reg;
MIR_op_t ret_reg_op, arg_reg_op, mem_op, prev_sp_op, temp_op, arg_var_op;
MIR_reg_t ret_reg;
MIR_op_t ret_reg_op, arg_reg_op, prev_sp_op, temp_op, arg_var_op;
size_t i, int_arg_num, fp_arg_num, disp, var_args_start;
assert (curr_func_item->item_type == MIR_func_item);
@ -535,8 +531,9 @@ static void target_machinize (MIR_context_t ctx) {
stack_arg_func_p = FALSE;
param_save_area_size = 0;
anchor = DLIST_HEAD (MIR_insn_t, func->insns);
if (func->vararg_p) set_prev_sp_op (ctx, anchor, &prev_sp_op); /* arg can be taken from memory */
disp = PPC64_STACK_HEADER_SIZE; /* param area start in the caller frame */
if (func->vararg_p)
set_prev_sp_op (gen_ctx, anchor, &prev_sp_op); /* arg can be taken from memory */
disp = PPC64_STACK_HEADER_SIZE; /* param area start in the caller frame */
for (i = int_arg_num = fp_arg_num = 0; i < func->nargs; i++) {
/* Argument extensions is already done in simplify */
/* Prologue: generate arg_var = hard_reg|stack mem ... */
@ -544,28 +541,28 @@ static void target_machinize (MIR_context_t ctx) {
arg_var_op = MIR_new_reg_op (ctx, i + 1);
if ((type == MIR_T_F || type == MIR_T_D || type == MIR_T_LD) && fp_arg_num < 13) {
if (type == MIR_T_LD && fp_arg_num == 12) { /* dmov f14,disp(r1) -> lfd f14,disp(r1): */
set_prev_sp_op (ctx, anchor, &prev_sp_op);
set_prev_sp_op (gen_ctx, anchor, &prev_sp_op);
arg_reg_op = _MIR_new_hard_reg_op (ctx, F14_HARD_REG);
gen_mov (ctx, anchor, MIR_DMOV, arg_reg_op,
gen_mov (gen_ctx, anchor, MIR_DMOV, arg_reg_op,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_D, disp + 8, R11_HARD_REG, MIR_NON_HARD_REG,
1));
}
arg_reg_op = _MIR_new_hard_reg_op (ctx, F1_HARD_REG + fp_arg_num);
gen_mov (ctx, anchor, type == MIR_T_F ? MIR_FMOV : type == MIR_T_D ? MIR_DMOV : MIR_LDMOV,
gen_mov (gen_ctx, anchor, type == MIR_T_F ? MIR_FMOV : type == MIR_T_D ? MIR_DMOV : MIR_LDMOV,
arg_var_op, arg_reg_op); /* (f|d|ld|)mov arg, arg_hard_reg */
fp_arg_num += type == MIR_T_LD ? 2 : 1;
} else if (type == MIR_T_F || type == MIR_T_D
|| type == MIR_T_LD) { /* (f|d|ld|)mov arg, arg_memory */
set_prev_sp_op (ctx, anchor, &prev_sp_op);
gen_mov (ctx, anchor, type == MIR_T_F ? MIR_FMOV : type == MIR_T_D ? MIR_DMOV : MIR_LDMOV,
set_prev_sp_op (gen_ctx, anchor, &prev_sp_op);
gen_mov (gen_ctx, anchor, type == MIR_T_F ? MIR_FMOV : type == MIR_T_D ? MIR_DMOV : MIR_LDMOV,
arg_var_op,
_MIR_new_hard_reg_mem_op (ctx, type, disp, R11_HARD_REG, MIR_NON_HARD_REG, 1));
} else if (int_arg_num < 8) { /* mov arg, arg_hard_reg */
arg_reg_op = _MIR_new_hard_reg_op (ctx, R3_HARD_REG + int_arg_num);
gen_mov (ctx, anchor, MIR_MOV, arg_var_op, arg_reg_op);
gen_mov (gen_ctx, anchor, MIR_MOV, arg_var_op, arg_reg_op);
} else { /* mov arg, arg_memory */
set_prev_sp_op (ctx, anchor, &prev_sp_op);
gen_mov (ctx, anchor, MIR_MOV, arg_var_op,
set_prev_sp_op (gen_ctx, anchor, &prev_sp_op);
gen_mov (gen_ctx, anchor, MIR_MOV, arg_var_op,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, disp, R11_HARD_REG, MIR_NON_HARD_REG, 1));
}
disp += type == MIR_T_LD ? 16 : 8;
@ -582,7 +579,7 @@ static void target_machinize (MIR_context_t ctx) {
code = insn->code;
if (code == MIR_LDBEQ || code == MIR_LDBNE || code == MIR_LDBLT || code == MIR_LDBGE
|| code == MIR_LDBGT || code == MIR_LDBLE) { /* split to cmp and branch */
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
code = (code == MIR_LDBEQ
? MIR_LDEQ
: code == MIR_LDBNE
@ -591,13 +588,13 @@ static void target_machinize (MIR_context_t ctx) {
? MIR_LDLT
: code == MIR_LDBGE ? MIR_LDGE : code == MIR_LDBGT ? MIR_LDGT : MIR_LDLE);
new_insn = MIR_new_insn (ctx, code, temp_op, insn->ops[1], insn->ops[2]);
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
next_insn = MIR_new_insn (ctx, MIR_BT, insn->ops[0], temp_op);
gen_add_insn_after (ctx, new_insn, next_insn);
gen_delete_insn (ctx, insn);
gen_add_insn_after (gen_ctx, new_insn, next_insn);
gen_delete_insn (gen_ctx, insn);
insn = new_insn;
}
if ((nargs = get_builtin (ctx, code, &proto_item, &func_import_item)) > 0) {
if ((nargs = get_builtin (gen_ctx, code, &proto_item, &func_import_item)) > 0) {
if (code == MIR_VA_ARG) {
/* Use a builtin func call:
mov func_reg, func ref; mov flag_reg, <type>; call proto, func_reg, res_reg, va_reg,
@ -607,42 +604,42 @@ static void target_machinize (MIR_context_t ctx) {
assert (res_reg_op.mode == MIR_OP_REG && va_reg_op.mode == MIR_OP_REG
&& mem_op.mode == MIR_OP_MEM);
func_reg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
flag_reg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
func_reg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
flag_reg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
next_insn = new_insn
= MIR_new_insn (ctx, MIR_MOV, func_reg_op, MIR_new_ref_op (ctx, func_import_item));
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
new_insn = MIR_new_insn (ctx, MIR_MOV, flag_reg_op,
MIR_new_int_op (ctx, (int64_t) mem_op.u.mem.type));
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
ops[0] = MIR_new_ref_op (ctx, proto_item);
ops[1] = func_reg_op;
ops[2] = res_reg_op;
ops[3] = va_reg_op;
ops[4] = flag_reg_op;
new_insn = MIR_new_insn_arr (ctx, MIR_CALL, 5, ops);
gen_add_insn_before (ctx, insn, new_insn);
gen_delete_insn (ctx, insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
gen_delete_insn (gen_ctx, insn);
} else { /* Use builtin: mov freg, func ref; call proto, freg, res_reg, op_reg[, op_reg2] */
MIR_op_t freg_op, res_reg_op = insn->ops[0], op_reg_op = insn->ops[1], ops[5];
assert (res_reg_op.mode == MIR_OP_REG && op_reg_op.mode == MIR_OP_REG);
freg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
freg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
next_insn = new_insn
= MIR_new_insn (ctx, MIR_MOV, freg_op, MIR_new_ref_op (ctx, func_import_item));
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
ops[0] = MIR_new_ref_op (ctx, proto_item);
ops[1] = freg_op;
ops[2] = res_reg_op;
ops[3] = op_reg_op;
if (nargs == 2) ops[4] = insn->ops[2];
new_insn = MIR_new_insn_arr (ctx, MIR_CALL, nargs + 3, ops);
gen_add_insn_before (ctx, insn, new_insn);
gen_delete_insn (ctx, insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
gen_delete_insn (gen_ctx, insn);
}
} else if (code == MIR_VA_START) {
MIR_op_t treg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
MIR_op_t treg_op2 = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
MIR_op_t treg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
MIR_op_t treg_op2 = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
MIR_op_t va_op = insn->ops[0];
MIR_reg_t va_reg;
@ -650,18 +647,18 @@ static void target_machinize (MIR_context_t ctx) {
va_reg = va_op.u.reg;
/* Insns can be non-simplified as soon as they match a machine insn. */
/* treg = mem64[r1]; treg = treg + var_args_start; mem64[va_reg] = treg */
gen_mov (ctx, insn, MIR_MOV, treg_op,
gen_mov (gen_ctx, insn, MIR_MOV, treg_op,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, 0, R1_HARD_REG, MIR_NON_HARD_REG, 1));
gen_mov (ctx, insn, MIR_MOV, treg_op2, MIR_new_int_op (ctx, var_args_start));
gen_mov (gen_ctx, insn, MIR_MOV, treg_op2, MIR_new_int_op (ctx, var_args_start));
/* don't use immediate in ADD as treg_op can become r0: */
new_insn = MIR_new_insn (ctx, MIR_ADD, treg_op, treg_op, treg_op2);
gen_add_insn_before (ctx, insn, new_insn);
gen_mov (ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 0, va_reg, 0, 1), treg_op);
gen_delete_insn (ctx, insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
gen_mov (gen_ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 0, va_reg, 0, 1), treg_op);
gen_delete_insn (gen_ctx, insn);
} else if (code == MIR_VA_END) { /* do nothing */
gen_delete_insn (ctx, insn);
gen_delete_insn (gen_ctx, insn);
} else if (MIR_call_code_p (code)) {
machinize_call (ctx, insn);
machinize_call (gen_ctx, insn);
leaf_p = FALSE;
} else if (code == MIR_ALLOCA) {
alloca_p = TRUE;
@ -689,39 +686,41 @@ static void target_machinize (MIR_context_t ctx) {
"ppc64 can not handle this combination of return values");
}
ret_reg_op = _MIR_new_hard_reg_op (ctx, ret_reg);
gen_mov (ctx, insn, new_insn_code, ret_reg_op, insn->ops[i]);
gen_mov (gen_ctx, insn, new_insn_code, ret_reg_op, insn->ops[i]);
insn->ops[i] = ret_reg_op;
}
}
}
}
static void isave (MIR_context_t ctx, MIR_insn_t anchor, int disp, MIR_reg_t hard_reg) {
gen_mov (ctx, anchor, MIR_MOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, disp, R1_HARD_REG, MIR_NON_HARD_REG, 1),
_MIR_new_hard_reg_op (ctx, hard_reg));
static void isave (gen_ctx_t gen_ctx, MIR_insn_t anchor, int disp, MIR_reg_t hard_reg) {
gen_mov (gen_ctx, anchor, MIR_MOV,
_MIR_new_hard_reg_mem_op (gen_ctx->ctx, MIR_T_I64, disp, R1_HARD_REG, MIR_NON_HARD_REG,
1),
_MIR_new_hard_reg_op (gen_ctx->ctx, hard_reg));
}
static void fsave (MIR_context_t ctx, MIR_insn_t anchor, int disp, MIR_reg_t hard_reg) {
gen_mov (ctx, anchor, MIR_DMOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_D, disp, R1_HARD_REG, MIR_NON_HARD_REG, 1),
_MIR_new_hard_reg_op (ctx, hard_reg));
static void fsave (gen_ctx_t gen_ctx, MIR_insn_t anchor, int disp, MIR_reg_t hard_reg) {
gen_mov (gen_ctx, anchor, MIR_DMOV,
_MIR_new_hard_reg_mem_op (gen_ctx->ctx, MIR_T_D, disp, R1_HARD_REG, MIR_NON_HARD_REG, 1),
_MIR_new_hard_reg_op (gen_ctx->ctx, hard_reg));
}
static void target_make_prolog_epilog (MIR_context_t ctx, bitmap_t used_hard_regs,
static void target_make_prolog_epilog (gen_ctx_t gen_ctx, bitmap_t used_hard_regs,
size_t stack_slots_num) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
MIR_context_t ctx = gen_ctx->ctx;
MIR_func_t func;
MIR_insn_t anchor, new_insn;
MIR_op_t sp_reg_op, fp_reg_op, treg_op, r0_reg_op, lr_reg_op;
MIR_op_t sp_reg_op, fp_reg_op, r0_reg_op, lr_reg_op;
int64_t start_save_regs_offset;
size_t i, n, offset, frame_size, frame_size_after_saved_regs, saved_iregs_num, saved_fregs_num;
size_t i, n, frame_size, saved_iregs_num, saved_fregs_num;
assert (curr_func_item->item_type == MIR_func_item);
func = curr_func_item->u.func;
anchor = DLIST_HEAD (MIR_insn_t, func->insns);
if (func->vararg_p) {
for (i = 0; i < 8; i++) isave (ctx, anchor, PPC64_STACK_HEADER_SIZE + i * 8, i + R3_HARD_REG);
for (i = 0; i < 8; i++)
isave (gen_ctx, anchor, PPC64_STACK_HEADER_SIZE + i * 8, i + R3_HARD_REG);
}
for (i = saved_iregs_num = saved_fregs_num = 0; i <= MAX_HARD_REG; i++)
if (!target_call_used_hard_reg_p (i) && bitmap_bit_p (used_hard_regs, i)) {
@ -743,29 +742,29 @@ static void target_make_prolog_epilog (MIR_context_t ctx, bitmap_t used_hard_reg
start_save_regs_offset = frame_size;
frame_size += (saved_iregs_num + saved_fregs_num) * 8;
if (frame_size % 16 != 0) frame_size = (frame_size + 15) / 16 * 16;
gen_mov (ctx, anchor, MIR_MOV, r0_reg_op, lr_reg_op); /* r0 = lr */
gen_mov (ctx, anchor, MIR_MOV,
gen_mov (gen_ctx, anchor, MIR_MOV, r0_reg_op, lr_reg_op); /* r0 = lr */
gen_mov (gen_ctx, anchor, MIR_MOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, 16, R1_HARD_REG, MIR_NON_HARD_REG, 1),
r0_reg_op); /* mem[r1] = r0 */
gen_mov (ctx, anchor, MIR_MOV, r0_reg_op, sp_reg_op);
gen_mov (gen_ctx, anchor, MIR_MOV, r0_reg_op, sp_reg_op);
new_insn = MIR_new_insn (ctx, MIR_ADD, sp_reg_op, sp_reg_op, MIR_new_int_op (ctx, -frame_size));
gen_add_insn_before (ctx, anchor, new_insn); /* r1 -= frame_size */
gen_mov (ctx, anchor, MIR_MOV,
gen_add_insn_before (gen_ctx, anchor, new_insn); /* r1 -= frame_size */
gen_mov (gen_ctx, anchor, MIR_MOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, 0, R1_HARD_REG, MIR_NON_HARD_REG, 1),
r0_reg_op); /* mem[r1] = r0 */
gen_mov (ctx, anchor, MIR_MOV,
gen_mov (gen_ctx, anchor, MIR_MOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, PPC64_TOC_OFFSET, R1_HARD_REG,
MIR_NON_HARD_REG, 1),
_MIR_new_hard_reg_op (ctx, R2_HARD_REG)); /* mem[r1+toc_off] = r2 */
for (n = i = 0; i <= MAX_HARD_REG; i++)
if (!target_call_used_hard_reg_p (i) && bitmap_bit_p (used_hard_regs, i)) {
if (i < F0_HARD_REG)
isave (ctx, anchor, start_save_regs_offset + (n++) * 8, i);
isave (gen_ctx, anchor, start_save_regs_offset + (n++) * 8, i);
else
fsave (ctx, anchor, start_save_regs_offset + (n++) * 8, i);
fsave (gen_ctx, anchor, start_save_regs_offset + (n++) * 8, i);
}
isave (ctx, anchor, start_save_regs_offset + n * 8, R31_HARD_REG); /* save R31 */
gen_mov (ctx, anchor, MIR_MOV, fp_reg_op, sp_reg_op); /* r31 = r1 */
isave (gen_ctx, anchor, start_save_regs_offset + n * 8, R31_HARD_REG); /* save R31 */
gen_mov (gen_ctx, anchor, MIR_MOV, fp_reg_op, sp_reg_op); /* r31 = r1 */
/* Epilogue: */
anchor = DLIST_TAIL (MIR_insn_t, func->insns);
assert (anchor->code == MIR_RET);
@ -773,25 +772,25 @@ static void target_make_prolog_epilog (MIR_context_t ctx, bitmap_t used_hard_reg
for (i = n = 0; i <= MAX_HARD_REG; i++)
if (!target_call_used_hard_reg_p (i) && bitmap_bit_p (used_hard_regs, i)) {
if (i < F0_HARD_REG) {
gen_mov (ctx, anchor, MIR_MOV, _MIR_new_hard_reg_op (ctx, i),
gen_mov (gen_ctx, anchor, MIR_MOV, _MIR_new_hard_reg_op (ctx, i),
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, start_save_regs_offset + (n++) * 8,
FP_HARD_REG, MIR_NON_HARD_REG, 1));
} else {
gen_mov (ctx, anchor, MIR_DMOV, _MIR_new_hard_reg_op (ctx, i),
gen_mov (gen_ctx, anchor, MIR_DMOV, _MIR_new_hard_reg_op (ctx, i),
_MIR_new_hard_reg_mem_op (ctx, MIR_T_D, start_save_regs_offset + (n++) * 8,
FP_HARD_REG, MIR_NON_HARD_REG, 1));
}
}
/* Restore sp, fp, lr */
new_insn = MIR_new_insn (ctx, MIR_ADD, sp_reg_op, fp_reg_op, MIR_new_int_op (ctx, frame_size));
gen_add_insn_before (ctx, anchor, new_insn); /* sp = fp + frame_size */
gen_mov (ctx, anchor, MIR_MOV, fp_reg_op,
gen_add_insn_before (gen_ctx, anchor, new_insn); /* sp = fp + frame_size */
gen_mov (gen_ctx, anchor, MIR_MOV, fp_reg_op,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, start_save_regs_offset + n * 8, FP_HARD_REG,
MIR_NON_HARD_REG, 1)); /* restore fp */
gen_mov (ctx, anchor, MIR_MOV, r0_reg_op,
gen_mov (gen_ctx, anchor, MIR_MOV, r0_reg_op,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, 16, R1_HARD_REG, MIR_NON_HARD_REG,
1)); /* r0 = 16(sp) */
gen_mov (ctx, anchor, MIR_MOV, lr_reg_op, r0_reg_op); /* lr = r0 */
1)); /* r0 = 16(sp) */
gen_mov (gen_ctx, anchor, MIR_MOV, lr_reg_op, r0_reg_op); /* lr = r0 */
}
struct pattern {
@ -1360,8 +1359,7 @@ static int pattern_index_cmp (const void *a1, const void *a2) {
return c1 != c2 ? c1 - c2 : (long) i1 - (long) i2;
}
static void patterns_init (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void patterns_init (gen_ctx_t gen_ctx) {
int i, ind, n = sizeof (patterns) / sizeof (struct pattern);
MIR_insn_code_t prev_code, code;
insn_pattern_info_t *info_addr;
@ -1402,14 +1400,14 @@ static int negative32_p (uint64_t u, uint64_t *n) {
return u == 0;
}
static int pattern_match_p (MIR_context_t ctx, const struct pattern *pat, MIR_insn_t insn,
static int pattern_match_p (gen_ctx_t gen_ctx, const struct pattern *pat, MIR_insn_t insn,
int use_short_label_p) {
int nop, n;
MIR_context_t ctx = gen_ctx->ctx;
int nop;
size_t nops = MIR_insn_nops (ctx, insn);
const char *p;
char ch, start_ch;
MIR_op_mode_t mode;
MIR_op_t op, original;
MIR_op_t op;
MIR_reg_t hr;
for (nop = 0, p = pat->pattern; *p != 0; p++, nop++) {
@ -1444,8 +1442,7 @@ static int pattern_match_p (MIR_context_t ctx, const struct pattern *pat, MIR_in
case 'm':
case 'M': {
MIR_type_t type, type2, type3 = MIR_T_BOUND;
int ds_p = FALSE, l_p = FALSE, br0_p = FALSE, u_p = TRUE, s_p = TRUE,
index_p = start_ch == 'M';
int ds_p = FALSE, l_p = FALSE, br0_p = FALSE, u_p = TRUE, s_p = TRUE;
if (op.mode != MIR_OP_HARD_REG_MEM) return FALSE;
ch = *++p;
@ -1465,7 +1462,6 @@ static int pattern_match_p (MIR_context_t ctx, const struct pattern *pat, MIR_in
#else
if (start_ch == 'M') type3 = MIR_T_P;
#endif
index_p = FALSE;
} else {
p--;
type = MIR_T_D;
@ -1523,7 +1519,8 @@ static int pattern_match_p (MIR_context_t ctx, const struct pattern *pat, MIR_in
&& (op.u.hard_reg_mem.index != MIR_NON_HARD_REG
|| (!br0_p && op.u.hard_reg_mem.base == R0_HARD_REG)
|| (br0_p && op.u.hard_reg_mem.base != R0_HARD_REG)
|| !int16_p (op.u.hard_reg_mem.disp) || l_p && !int16_p (op.u.hard_reg_mem.disp + 8)))
|| !int16_p (op.u.hard_reg_mem.disp)
|| (l_p && !int16_p (op.u.hard_reg_mem.disp + 8))))
return FALSE;
if (!ds_p && start_ch == 'M'
&& (op.u.hard_reg_mem.disp != 0
@ -1602,23 +1599,20 @@ static int pattern_match_p (MIR_context_t ctx, const struct pattern *pat, MIR_in
return TRUE;
}
static const char *find_insn_pattern_replacement (MIR_context_t ctx, MIR_insn_t insn,
static const char *find_insn_pattern_replacement (gen_ctx_t gen_ctx, MIR_insn_t insn,
int use_short_label_p) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
int i;
const struct pattern *pat;
insn_pattern_info_t info = VARR_GET (insn_pattern_info_t, insn_pattern_info, insn->code);
for (i = 0; i < info.num; i++) {
pat = &patterns[VARR_GET (int, pattern_indexes, info.start + i)];
if (pattern_match_p (ctx, pat, insn, use_short_label_p)) return pat->replacement;
if (pattern_match_p (gen_ctx, pat, insn, use_short_label_p)) return pat->replacement;
}
return NULL;
}
static void patterns_finish (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void patterns_finish (gen_ctx_t gen_ctx) {
VARR_DESTROY (int, pattern_indexes);
VARR_DESTROY (insn_pattern_info_t, insn_pattern_info);
}
@ -1659,8 +1653,8 @@ static void set_int64 (uint8_t *addr, int64_t v) { *(int64_t *) addr = v; }
static int64_t get_int64 (uint8_t *addr) { return *(int64_t *) addr; }
static void out_insn (MIR_context_t ctx, MIR_insn_t insn, const char *replacement) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void out_insn (gen_ctx_t gen_ctx, MIR_insn_t insn, const char *replacement) {
MIR_context_t ctx = gen_ctx->ctx;
size_t nops = MIR_insn_nops (ctx, insn);
size_t offset;
const char *p, *insn_str;
@ -1801,10 +1795,10 @@ static void out_insn (MIR_context_t ctx, MIR_insn_t insn, const char *replacemen
gen_assert (dec_value (ch2) >= 0 && Mb < 0 && Me < 0);
if (b_p) {
Mb = read_dec (&p);
Mb = ((Mb & 0x1f) << 1) | (Mb >> 5) & 1;
Mb = ((Mb & 0x1f) << 1) | ((Mb >> 5) & 1);
} else {
Me = read_dec (&p);
Me = ((Me & 0x1f) << 1) | (Me >> 5) & 1;
Me = ((Me & 0x1f) << 1) | ((Me >> 5) & 1);
}
} else {
op = insn->ops[0].mode == MIR_OP_HARD_REG_MEM ? insn->ops[0] : insn->ops[1];
@ -1863,10 +1857,10 @@ static void out_insn (MIR_context_t ctx, MIR_insn_t insn, const char *replacemen
gen_assert (Mb < 0 && Me < 0);
if (b_p) {
Mb = op.u.i;
Mb = ((Mb & 0x1f) << 1) | (Mb >> 5) & 1;
Mb = ((Mb & 0x1f) << 1) | ((Mb >> 5) & 1);
} else {
Me = 63 - op.u.i;
Me = ((Me & 0x1f) << 1) | (Me >> 5) & 1;
Me = ((Me & 0x1f) << 1) | ((Me >> 5) & 1);
}
} else if (b_p) {
gen_assert (mb < 0);
@ -1947,7 +1941,7 @@ static void out_insn (MIR_context_t ctx, MIR_insn_t insn, const char *replacemen
ok_p = negative32_p (v, &n);
n = 32 - n;
gen_assert (Mb < 0 && ok_p);
Mb = ((n & 0x1f) << 1) | (n >> 5) & 1;
Mb = ((n & 0x1f) << 1) | ((n >> 5) & 1);
} else {
gen_assert (imm < 0);
n = dec_value (*++p);
@ -2197,12 +2191,12 @@ static void out_insn (MIR_context_t ctx, MIR_insn_t insn, const char *replacemen
}
}
static int target_insn_ok_p (MIR_context_t ctx, MIR_insn_t insn) {
return find_insn_pattern_replacement (ctx, insn, TRUE) != NULL;
static int target_insn_ok_p (gen_ctx_t gen_ctx, MIR_insn_t insn) {
return find_insn_pattern_replacement (gen_ctx, insn, TRUE) != NULL;
}
static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static uint8_t *target_translate (gen_ctx_t gen_ctx, size_t *len) {
MIR_context_t ctx = gen_ctx->ctx;
size_t i;
int short_label_disp_fail_p, n_iter = 0;
MIR_insn_t insn, old_insn;
@ -2222,10 +2216,10 @@ static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
|| code == MIR_LSHS || code == MIR_URSHS)
&& (insn->ops[2].mode == MIR_OP_INT || insn->ops[2].mode == MIR_OP_UINT)) {
if (insn->ops[2].u.i == 0) {
gen_mov (ctx, insn, MIR_MOV, insn->ops[0], insn->ops[1]);
gen_mov (gen_ctx, insn, MIR_MOV, insn->ops[0], insn->ops[1]);
old_insn = insn;
insn = DLIST_NEXT (MIR_insn_t, insn);
gen_delete_insn (ctx, old_insn);
gen_delete_insn (gen_ctx, old_insn);
} else {
if (insn->ops[2].mode == MIR_OP_INT && insn->ops[2].u.i < 0) {
switch (code) {
@ -2235,6 +2229,7 @@ static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
case MIR_RSHS: insn->code = MIR_LSHS; break;
case MIR_URSHS: insn->code = MIR_LSHS; break;
case MIR_LSHS: insn->code = MIR_RSHS; break;
default: gen_assert (FALSE); break;
}
insn->ops[2].u.i = -insn->ops[2].u.i;
}
@ -2246,25 +2241,25 @@ static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
}
}
if (insn->code == MIR_LABEL) {
set_label_disp (ctx, insn, VARR_LENGTH (uint8_t, result_code));
set_label_disp (gen_ctx, insn, VARR_LENGTH (uint8_t, result_code));
} else {
int use_short_label_p = TRUE;
if (n_iter > 0 && MIR_branch_code_p (code)) {
MIR_label_t label = insn->ops[0].u.label;
int64_t offset
= (int64_t) get_label_disp (ctx, label) - (int64_t) VARR_LENGTH (uint8_t, result_code);
int64_t offset = (int64_t) get_label_disp (gen_ctx, label)
- (int64_t) VARR_LENGTH (uint8_t, result_code);
use_short_label_p = ((offset < 0 ? -offset : offset) & ~(int64_t) 0x7fff) == 0;
}
replacement = find_insn_pattern_replacement (ctx, insn, use_short_label_p);
replacement = find_insn_pattern_replacement (gen_ctx, insn, use_short_label_p);
if (replacement == NULL) {
fprintf (stderr, "fatal failure in matching insn:");
MIR_output_insn (ctx, stderr, insn, curr_func_item->u.func, TRUE);
exit (1);
} else {
gen_assert (replacement != NULL);
out_insn (ctx, insn, replacement);
out_insn (gen_ctx, insn, replacement);
}
}
}
@ -2274,10 +2269,10 @@ static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
if (lr.abs_addr_p) {
set_int64 (&VARR_ADDR (uint8_t, result_code)[lr.label_val_disp],
(int64_t) get_label_disp (ctx, lr.label));
(int64_t) get_label_disp (gen_ctx, lr.label));
VARR_PUSH (uint64_t, abs_address_locs, lr.label_val_disp);
} else if (lr.short_addr_p) { /* 14-bit relative addressing */
int64_t offset = (int64_t) get_label_disp (ctx, lr.label) - (int64_t) lr.label_val_disp;
int64_t offset = (int64_t) get_label_disp (gen_ctx, lr.label) - (int64_t) lr.label_val_disp;
gen_assert ((offset & 0x3) == 0);
if (((offset < 0 ? -offset : offset) & ~(int64_t) 0x7fff) != 0) {
@ -2287,7 +2282,7 @@ static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
|= ((offset / 4) & 0x3fff) << 2;
}
} else { /* 24-bit relative address */
int64_t offset = (int64_t) get_label_disp (ctx, lr.label) - (int64_t) lr.label_val_disp;
int64_t offset = (int64_t) get_label_disp (gen_ctx, lr.label) - (int64_t) lr.label_val_disp;
gen_assert ((offset & 0x3) == 0
&& ((offset < 0 ? -offset : offset) & ~(int64_t) 0x1ffffff) == 0);
*(uint32_t *) (VARR_ADDR (uint8_t, result_code) + lr.label_val_disp)
@ -2302,8 +2297,7 @@ static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
return VARR_ADDR (uint8_t, result_code);
}
static void target_rebase (MIR_context_t ctx, uint8_t *base) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void target_rebase (gen_ctx_t gen_ctx, uint8_t *base) {
MIR_code_reloc_t reloc;
VARR_TRUNC (MIR_code_reloc_t, relocs, 0);
@ -2312,25 +2306,21 @@ static void target_rebase (MIR_context_t ctx, uint8_t *base) {
reloc.value = base + get_int64 (base + reloc.offset);
VARR_PUSH (MIR_code_reloc_t, relocs, reloc);
}
_MIR_update_code_arr (ctx, base, VARR_LENGTH (MIR_code_reloc_t, relocs),
_MIR_update_code_arr (gen_ctx->ctx, base, VARR_LENGTH (MIR_code_reloc_t, relocs),
VARR_ADDR (MIR_code_reloc_t, relocs));
}
static void target_init (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
gen_ctx->target_ctx = gen_malloc (ctx, sizeof (struct target_ctx));
static void target_init (gen_ctx_t gen_ctx) {
gen_ctx->target_ctx = gen_malloc (gen_ctx, sizeof (struct target_ctx));
VARR_CREATE (uint8_t, result_code, 0);
VARR_CREATE (label_ref_t, label_refs, 0);
VARR_CREATE (uint64_t, abs_address_locs, 0);
VARR_CREATE (MIR_code_reloc_t, relocs, 0);
patterns_init (ctx);
patterns_init (gen_ctx);
}
static void target_finish (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
patterns_finish (ctx);
static void target_finish (gen_ctx_t gen_ctx) {
patterns_finish (gen_ctx);
VARR_DESTROY (uint8_t, result_code);
VARR_DESTROY (label_ref_t, label_refs);
VARR_DESTROY (uint64_t, abs_address_locs);

@ -171,13 +171,13 @@ struct target_ctx {
#define relocs gen_ctx->target_ctx->relocs
#define ld_addr_regs gen_ctx->target_ctx->ld_addr_regs
static void gen_mov (MIR_context_t ctx, MIR_insn_t anchor, MIR_insn_code_t code, MIR_op_t dst_op,
static void gen_mov (gen_ctx_t gen_ctx, MIR_insn_t anchor, MIR_insn_code_t code, MIR_op_t dst_op,
MIR_op_t src_op) {
gen_add_insn_before (ctx, anchor, MIR_new_insn (ctx, code, dst_op, src_op));
gen_add_insn_before (gen_ctx, anchor, MIR_new_insn (gen_ctx->ctx, code, dst_op, src_op));
}
static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void machinize_call (gen_ctx_t gen_ctx, MIR_insn_t call_insn) {
MIR_context_t ctx = gen_ctx->ctx;
MIR_func_t func = curr_func_item->u.func;
MIR_proto_t proto = call_insn->ops[0].u.ref->u.proto;
int vararg_p = proto->vararg_p;
@ -186,11 +186,9 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
MIR_type_t type, mem_type;
MIR_op_mode_t mode;
MIR_var_t *arg_vars = NULL;
MIR_reg_t arg_reg;
MIR_op_t arg_op, temp_op, arg_reg_op, ret_op, mem_op, ret_val_op, call_res_op;
MIR_insn_code_t new_insn_code, ext_code;
MIR_insn_t new_insn, prev_insn, next_insn, ext_insn;
MIR_insn_t prev_call_insn = DLIST_PREV (MIR_insn_t, call_insn);
MIR_insn_t new_insn, ext_insn;
if (call_insn->code == MIR_INLINE) call_insn->code = MIR_CALL;
if (proto->args == NULL) {
@ -203,10 +201,10 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
}
if (call_insn->ops[1].mode != MIR_OP_REG && call_insn->ops[1].mode != MIR_OP_HARD_REG) {
// ??? to optimize (can be immediate operand for func call)
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
new_insn = MIR_new_insn (ctx, MIR_MOV, temp_op, call_insn->ops[1]);
call_insn->ops[1] = temp_op;
gen_add_insn_before (ctx, call_insn, new_insn);
gen_add_insn_before (gen_ctx, call_insn, new_insn);
}
n_iregs = n_fregs = param_mem_size = call_ld_value_area_size = 0;
for (size_t i = 2; i < nops; i++) {
@ -256,7 +254,7 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
if (type != MIR_T_LD && i < start) continue;
ext_insn = NULL;
if ((ext_code = get_ext_code (type)) != MIR_INVALID_INSN) { /* extend arg if necessary */
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
ext_insn = MIR_new_insn (ctx, ext_code, temp_op, arg_op);
call_insn->ops[i] = arg_op = temp_op;
}
@ -264,34 +262,34 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
if (i >= start) { /* put arg value in saved ld value area: */
mem_op = _MIR_new_hard_reg_mem_op (ctx, MIR_T_LD, ld_value_disp + S390X_STACK_HEADER_SIZE,
FP_HARD_REG, MIR_NON_HARD_REG, 1);
gen_mov (ctx, call_insn, MIR_LDMOV, mem_op, arg_op);
gen_mov (gen_ctx, call_insn, MIR_LDMOV, mem_op, arg_op);
}
arg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
arg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
new_insn = MIR_new_insn (ctx, MIR_ADD, arg_op, _MIR_new_hard_reg_op (ctx, FP_HARD_REG),
MIR_new_int_op (ctx, S390X_STACK_HEADER_SIZE + ld_value_disp));
gen_add_insn_before (ctx, call_insn, new_insn);
gen_add_insn_before (gen_ctx, call_insn, new_insn);
ld_value_disp += 16;
}
mem_type = type == MIR_T_F || type == MIR_T_D ? type : MIR_T_I64;
if ((type == MIR_T_F || type == MIR_T_D) && n_fregs < 4) {
/* put arguments to argument hard regs: */
if (ext_insn != NULL) gen_add_insn_before (ctx, call_insn, ext_insn);
if (ext_insn != NULL) gen_add_insn_before (gen_ctx, call_insn, ext_insn);
arg_reg_op = _MIR_new_hard_reg_op (ctx, F0_HARD_REG + n_fregs * 2);
gen_mov (ctx, call_insn, type == MIR_T_F ? MIR_FMOV : MIR_DMOV, arg_reg_op, arg_op);
gen_mov (gen_ctx, call_insn, type == MIR_T_F ? MIR_FMOV : MIR_DMOV, arg_reg_op, arg_op);
call_insn->ops[i] = arg_reg_op;
n_fregs++;
} else if (type != MIR_T_F && type != MIR_T_D && n_iregs < 5) {
if (ext_insn != NULL) gen_add_insn_before (ctx, call_insn, ext_insn);
if (ext_insn != NULL) gen_add_insn_before (gen_ctx, call_insn, ext_insn);
arg_reg_op = _MIR_new_hard_reg_op (ctx, R2_HARD_REG + n_iregs);
gen_mov (ctx, call_insn, MIR_MOV, arg_reg_op, arg_op);
gen_mov (gen_ctx, call_insn, MIR_MOV, arg_reg_op, arg_op);
if (i >= start) call_insn->ops[i] = arg_reg_op; /* don't change LD return yet */
n_iregs++;
} else { /* put arguments on the stack: */
if (ext_insn != NULL) gen_add_insn_before (ctx, call_insn, ext_insn);
if (ext_insn != NULL) gen_add_insn_before (gen_ctx, call_insn, ext_insn);
new_insn_code = (type == MIR_T_F ? MIR_FMOV : type == MIR_T_D ? MIR_DMOV : MIR_MOV);
mem_op = _MIR_new_hard_reg_mem_op (ctx, mem_type, param_mem_size + S390X_STACK_HEADER_SIZE,
SP_HARD_REG, MIR_NON_HARD_REG, 1);
gen_mov (ctx, call_insn, new_insn_code, mem_op, arg_op);
gen_mov (gen_ctx, call_insn, new_insn_code, mem_op, arg_op);
if (i >= start) call_insn->ops[i] = mem_op;
param_mem_size += 8;
}
@ -333,7 +331,7 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
MIR_new_insn (ctx, ext_code, ret_op, ret_op));
new_insn = DLIST_NEXT (MIR_insn_t, new_insn);
}
create_new_bb_insns (ctx, call_insn, DLIST_NEXT (MIR_insn_t, new_insn), call_insn);
create_new_bb_insns (gen_ctx, call_insn, DLIST_NEXT (MIR_insn_t, new_insn), call_insn);
}
}
@ -413,9 +411,9 @@ static int64_t mir_ldle (long double d1, long double d2) { return d1 <= d2; }
static const char *LDLE = "mir.ldle";
static const char *LDLE_P = "mir.ldle.p";
static int get_builtin (MIR_context_t ctx, MIR_insn_code_t code, MIR_item_t *proto_item,
static int get_builtin (gen_ctx_t gen_ctx, MIR_insn_code_t code, MIR_item_t *proto_item,
MIR_item_t *func_import_item) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
MIR_context_t ctx = gen_ctx->ctx;
MIR_type_t res_type;
*func_import_item = *proto_item = NULL; /* to remove uninitialized warning */
@ -538,38 +536,36 @@ static int get_builtin (MIR_context_t ctx, MIR_insn_code_t code, MIR_item_t *pro
}
}
static MIR_disp_t target_get_stack_slot_offset (MIR_context_t ctx, MIR_type_t type,
static MIR_disp_t target_get_stack_slot_offset (gen_ctx_t gen_ctx, MIR_type_t type,
MIR_reg_t slot) {
/* slot is 0, 1, ... */
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
return ((MIR_disp_t) slot * 8 + S390X_STACK_HEADER_SIZE + param_save_area_size
+ ld_value_save_area_size);
}
static void set_prev_sp_reg (MIR_context_t ctx, MIR_insn_t anchor, int *prev_sp_set_p,
static void set_prev_sp_reg (gen_ctx_t gen_ctx, MIR_insn_t anchor, int *prev_sp_set_p,
MIR_reg_t *prev_sp_reg) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
MIR_context_t ctx = gen_ctx->ctx;
MIR_func_t func = curr_func_item->u.func;
if (!*prev_sp_set_p) {
*prev_sp_set_p = TRUE;
*prev_sp_reg = gen_new_temp_reg (ctx, MIR_T_I64, func);
gen_mov (ctx, anchor, MIR_MOV, MIR_new_reg_op (ctx, *prev_sp_reg),
*prev_sp_reg = gen_new_temp_reg (gen_ctx, MIR_T_I64, func);
gen_mov (gen_ctx, anchor, MIR_MOV, MIR_new_reg_op (ctx, *prev_sp_reg),
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, 0, SP_HARD_REG, MIR_NON_HARD_REG, 1));
}
}
static void target_machinize (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void target_machinize (gen_ctx_t gen_ctx) {
MIR_context_t ctx = gen_ctx->ctx;
MIR_func_t func;
MIR_type_t type, mem_type, res_type;
MIR_type_t type, res_type;
MIR_insn_code_t code, new_insn_code;
MIR_insn_t insn, next_insn, new_insn, anchor;
MIR_reg_t ret_reg, arg_reg, ld_addr_reg, prev_sp_reg;
MIR_op_t ret_reg_op, arg_reg_op, mem_op, temp_op, arg_var_op;
MIR_reg_t ret_reg, ld_addr_reg, prev_sp_reg;
MIR_op_t ret_reg_op, arg_reg_op, temp_op, arg_var_op;
int prev_sp_set_p = FALSE;
size_t i, int_arg_num = 0, fp_arg_num = 0, disp, var_args_start;
size_t i, int_arg_num = 0, fp_arg_num = 0, disp;
gen_assert (curr_func_item->item_type == MIR_func_item);
func = curr_func_item->u.func;
@ -578,15 +574,15 @@ static void target_machinize (MIR_context_t ctx) {
VARR_TRUNC (uint64_t, ld_addr_regs, 0);
for (i = 0; i < func->nres; i++) { /* reserve regs/space for LD result addresses */
if (func->res_types[i] != MIR_T_LD) continue;
ld_addr_reg = gen_new_temp_reg (ctx, MIR_T_I64, func);
ld_addr_reg = gen_new_temp_reg (gen_ctx, MIR_T_I64, func);
VARR_PUSH (uint64_t, ld_addr_regs, ld_addr_reg);
if (int_arg_num < 5) {
gen_mov (ctx, anchor, MIR_MOV, MIR_new_reg_op (ctx, ld_addr_reg),
gen_mov (gen_ctx, anchor, MIR_MOV, MIR_new_reg_op (ctx, ld_addr_reg),
_MIR_new_hard_reg_op (ctx, R2_HARD_REG + int_arg_num));
int_arg_num++;
} else {
set_prev_sp_reg (ctx, anchor, &prev_sp_set_p, &prev_sp_reg);
gen_mov (ctx, anchor, MIR_MOV, MIR_new_reg_op (ctx, ld_addr_reg),
set_prev_sp_reg (gen_ctx, anchor, &prev_sp_set_p, &prev_sp_reg);
gen_mov (gen_ctx, anchor, MIR_MOV, MIR_new_reg_op (ctx, ld_addr_reg),
MIR_new_mem_op (ctx, MIR_T_I64, disp, prev_sp_reg, 0, 1));
disp += 8;
}
@ -598,31 +594,31 @@ static void target_machinize (MIR_context_t ctx) {
if ((type == MIR_T_F || type == MIR_T_D) && fp_arg_num < 4) {
arg_reg_op = _MIR_new_hard_reg_op (ctx, F0_HARD_REG + fp_arg_num * 2);
/* (f|d)mov arg, arg_hard_reg: */
gen_mov (ctx, anchor, type == MIR_T_F ? MIR_FMOV : MIR_DMOV, arg_var_op, arg_reg_op);
gen_mov (gen_ctx, anchor, type == MIR_T_F ? MIR_FMOV : MIR_DMOV, arg_var_op, arg_reg_op);
fp_arg_num++;
} else if (type == MIR_T_F || type == MIR_T_D) { /* (f|d)mov arg, arg_memory */
set_prev_sp_reg (ctx, anchor, &prev_sp_set_p, &prev_sp_reg);
gen_mov (ctx, anchor, type == MIR_T_F ? MIR_FMOV : MIR_DMOV, arg_var_op,
set_prev_sp_reg (gen_ctx, anchor, &prev_sp_set_p, &prev_sp_reg);
gen_mov (gen_ctx, anchor, type == MIR_T_F ? MIR_FMOV : MIR_DMOV, arg_var_op,
MIR_new_mem_op (ctx, type, disp + (type == MIR_T_F ? 4 : 0), prev_sp_reg, 0, 1));
disp += 8;
} else if (int_arg_num < 5) { /* (ld)mov arg, arg_hard_reg */
if (type != MIR_T_LD)
gen_mov (ctx, anchor, MIR_MOV, arg_var_op,
gen_mov (gen_ctx, anchor, MIR_MOV, arg_var_op,
_MIR_new_hard_reg_op (ctx, R2_HARD_REG + int_arg_num));
else
gen_mov (ctx, anchor, MIR_LDMOV, arg_var_op,
gen_mov (gen_ctx, anchor, MIR_LDMOV, arg_var_op,
_MIR_new_hard_reg_mem_op (ctx, type, 0, R2_HARD_REG + int_arg_num,
MIR_NON_HARD_REG, 1));
int_arg_num++;
} else { /* (ld)mov arg, arg_memory */
set_prev_sp_reg (ctx, anchor, &prev_sp_set_p, &prev_sp_reg);
set_prev_sp_reg (gen_ctx, anchor, &prev_sp_set_p, &prev_sp_reg);
if (type != MIR_T_LD) {
gen_mov (ctx, anchor, MIR_MOV, arg_var_op,
gen_mov (gen_ctx, anchor, MIR_MOV, arg_var_op,
MIR_new_mem_op (ctx, MIR_T_I64, disp, prev_sp_reg, 0, 1));
} else {
gen_mov (ctx, anchor, MIR_MOV, _MIR_new_hard_reg_op (ctx, R1_HARD_REG),
gen_mov (gen_ctx, anchor, MIR_MOV, _MIR_new_hard_reg_op (ctx, R1_HARD_REG),
MIR_new_mem_op (ctx, MIR_T_I64, disp, prev_sp_reg, 0, 1));
gen_mov (ctx, anchor, MIR_MOV, arg_var_op,
gen_mov (gen_ctx, anchor, MIR_MOV, arg_var_op,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_LD, 0, R1_HARD_REG, MIR_NON_HARD_REG, 1));
}
disp += 8;
@ -640,7 +636,7 @@ static void target_machinize (MIR_context_t ctx) {
code = insn->code;
if (code == MIR_LDBEQ || code == MIR_LDBNE || code == MIR_LDBLT || code == MIR_LDBGE
|| code == MIR_LDBGT || code == MIR_LDBLE) { /* split to cmp and branch */
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
code = (code == MIR_LDBEQ
? MIR_LDEQ
: code == MIR_LDBNE
@ -649,13 +645,13 @@ static void target_machinize (MIR_context_t ctx) {
? MIR_LDLT
: code == MIR_LDBGE ? MIR_LDGE : code == MIR_LDBGT ? MIR_LDGT : MIR_LDLE);
new_insn = MIR_new_insn (ctx, code, temp_op, insn->ops[1], insn->ops[2]);
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
next_insn = MIR_new_insn (ctx, MIR_BT, insn->ops[0], temp_op);
gen_add_insn_after (ctx, new_insn, next_insn);
gen_delete_insn (ctx, insn);
gen_add_insn_after (gen_ctx, new_insn, next_insn);
gen_delete_insn (gen_ctx, insn);
insn = new_insn;
}
if ((nargs = get_builtin (ctx, code, &proto_item, &func_import_item)) > 0) {
if ((nargs = get_builtin (gen_ctx, code, &proto_item, &func_import_item)) > 0) {
if (code == MIR_VA_ARG) {
/* Use a builtin func call:
mov func_reg, func ref; mov flag_reg, <type>; call proto, func_reg, res_reg, va_reg,
@ -665,42 +661,42 @@ static void target_machinize (MIR_context_t ctx) {
gen_assert (res_reg_op.mode == MIR_OP_REG && va_reg_op.mode == MIR_OP_REG
&& mem_op.mode == MIR_OP_MEM);
func_reg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
flag_reg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
func_reg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
flag_reg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
next_insn = new_insn
= MIR_new_insn (ctx, MIR_MOV, func_reg_op, MIR_new_ref_op (ctx, func_import_item));
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
new_insn = MIR_new_insn (ctx, MIR_MOV, flag_reg_op,
MIR_new_int_op (ctx, (int64_t) mem_op.u.mem.type));
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
ops[0] = MIR_new_ref_op (ctx, proto_item);
ops[1] = func_reg_op;
ops[2] = res_reg_op;
ops[3] = va_reg_op;
ops[4] = flag_reg_op;
new_insn = MIR_new_insn_arr (ctx, MIR_CALL, 5, ops);
gen_add_insn_before (ctx, insn, new_insn);
gen_delete_insn (ctx, insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
gen_delete_insn (gen_ctx, insn);
} else { /* Use builtin: mov freg, func ref; call proto, freg, res_reg, op_reg[, op_reg2] */
MIR_op_t freg_op, res_reg_op = insn->ops[0], op_reg_op = insn->ops[1], ops[5];
gen_assert (res_reg_op.mode == MIR_OP_REG && op_reg_op.mode == MIR_OP_REG);
freg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
freg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
next_insn = new_insn
= MIR_new_insn (ctx, MIR_MOV, freg_op, MIR_new_ref_op (ctx, func_import_item));
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
ops[0] = MIR_new_ref_op (ctx, proto_item);
ops[1] = freg_op;
ops[2] = res_reg_op;
ops[3] = op_reg_op;
if (nargs == 2) ops[4] = insn->ops[2];
new_insn = MIR_new_insn_arr (ctx, MIR_CALL, nargs + 3, ops);
gen_add_insn_before (ctx, insn, new_insn);
gen_delete_insn (ctx, insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
gen_delete_insn (gen_ctx, insn);
}
} else if (code == MIR_VA_START) {
MIR_op_t treg_op
= MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, curr_func_item->u.func));
= MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, curr_func_item->u.func));
MIR_op_t va_op = insn->ops[0];
MIR_reg_t va_reg;
int gpr_val = 0, fpr_val = 0;
@ -726,26 +722,26 @@ static void target_machinize (MIR_context_t ctx) {
va_reg = va_op.mode == MIR_OP_REG ? va_op.u.reg : va_op.u.hard_reg;
/* Insns can be not simplified as soon as they match a machine insn. */
/* mem64[va_reg] = gpr_val; mem64[va_reg + 8] = fpr_val */
gen_mov (ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 0, va_reg, 0, 1),
gen_mov (gen_ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 0, va_reg, 0, 1),
MIR_new_int_op (ctx, gpr_val));
next_insn = DLIST_PREV (MIR_insn_t, insn);
gen_mov (ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 8, va_reg, 0, 1),
gen_mov (gen_ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 8, va_reg, 0, 1),
MIR_new_int_op (ctx, fpr_val));
/* reg_save_area: treg = mem64[sp]; mem64[va_reg+24] = treg: */
gen_mov (ctx, insn, MIR_MOV, treg_op,
gen_mov (gen_ctx, insn, MIR_MOV, treg_op,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, 0, SP_HARD_REG, MIR_NON_HARD_REG, 1));
gen_mov (ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 24, va_reg, 0, 1), treg_op);
gen_mov (gen_ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 24, va_reg, 0, 1), treg_op);
/* overflow_arg_area_reg: treg = treg_op+S390X_STACK_HEADER_SIZE + disp;
mem64[va_reg+16] = treg: */
new_insn = MIR_new_insn (ctx, MIR_ADD, treg_op, treg_op,
MIR_new_int_op (ctx, S390X_STACK_HEADER_SIZE + disp));
gen_add_insn_before (ctx, insn, new_insn);
gen_mov (ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 16, va_reg, 0, 1), treg_op);
gen_delete_insn (ctx, insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
gen_mov (gen_ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 16, va_reg, 0, 1), treg_op);
gen_delete_insn (gen_ctx, insn);
} else if (code == MIR_VA_END) { /* do nothing */
gen_delete_insn (ctx, insn);
gen_delete_insn (gen_ctx, insn);
} else if (MIR_call_code_p (code)) {
machinize_call (ctx, insn);
machinize_call (gen_ctx, insn);
leaf_p = FALSE;
} else if (code == MIR_ALLOCA) {
alloca_p = TRUE;
@ -753,7 +749,7 @@ static void target_machinize (MIR_context_t ctx) {
switch_p = TRUE;
} else if (code == MIR_RET) {
/* In simplify we already transformed code for one return insn and added extension insns. */
uint32_t n_gpregs = 0, n_fregs = 0, n_addr_res = 0, ld_addr_n = 0;
uint32_t n_gpregs = 0, n_fregs = 0, ld_addr_n = 0;
gen_assert (func->nres == MIR_insn_nops (ctx, insn));
for (size_t i = 0; i < func->nres; i++) {
@ -761,9 +757,9 @@ static void target_machinize (MIR_context_t ctx) {
res_type = func->res_types[i];
if (res_type == MIR_T_LD) { /* ldmov f1,0(addr_reg);std f1,0(r2);std f3,8(r2): */
ld_addr_reg = VARR_GET (uint64_t, ld_addr_regs, ld_addr_n);
gen_mov (ctx, insn, MIR_LDMOV, _MIR_new_hard_reg_op (ctx, F1_HARD_REG), insn->ops[i]);
gen_mov (gen_ctx, insn, MIR_LDMOV, _MIR_new_hard_reg_op (ctx, F1_HARD_REG), insn->ops[i]);
insn->ops[i] = MIR_new_mem_op (ctx, MIR_T_LD, 0, ld_addr_reg, 0, 1);
gen_mov (ctx, insn, MIR_LDMOV, insn->ops[i], _MIR_new_hard_reg_op (ctx, F1_HARD_REG));
gen_mov (gen_ctx, insn, MIR_LDMOV, insn->ops[i], _MIR_new_hard_reg_op (ctx, F1_HARD_REG));
ld_addr_n++;
continue;
}
@ -779,31 +775,32 @@ static void target_machinize (MIR_context_t ctx) {
"s390x can not handle this combination of return values");
}
ret_reg_op = _MIR_new_hard_reg_op (ctx, ret_reg);
gen_mov (ctx, insn, new_insn_code, ret_reg_op, insn->ops[i]);
gen_mov (gen_ctx, insn, new_insn_code, ret_reg_op, insn->ops[i]);
insn->ops[i] = ret_reg_op;
}
}
}
}
static void isave (MIR_context_t ctx, MIR_insn_t anchor, int disp, MIR_reg_t hard_reg) {
gen_mov (ctx, anchor, MIR_MOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, disp, SP_HARD_REG, MIR_NON_HARD_REG, 1),
_MIR_new_hard_reg_op (ctx, hard_reg));
static void isave (gen_ctx_t gen_ctx, MIR_insn_t anchor, int disp, MIR_reg_t hard_reg) {
gen_mov (gen_ctx, anchor, MIR_MOV,
_MIR_new_hard_reg_mem_op (gen_ctx->ctx, MIR_T_I64, disp, SP_HARD_REG, MIR_NON_HARD_REG,
1),
_MIR_new_hard_reg_op (gen_ctx->ctx, hard_reg));
}
static void fsave (MIR_context_t ctx, MIR_insn_t anchor, int disp, MIR_reg_t hard_reg) {
gen_mov (ctx, anchor, MIR_DMOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_D, disp, SP_HARD_REG, MIR_NON_HARD_REG, 1),
_MIR_new_hard_reg_op (ctx, hard_reg));
static void fsave (gen_ctx_t gen_ctx, MIR_insn_t anchor, int disp, MIR_reg_t hard_reg) {
gen_mov (gen_ctx, anchor, MIR_DMOV,
_MIR_new_hard_reg_mem_op (gen_ctx->ctx, MIR_T_D, disp, SP_HARD_REG, MIR_NON_HARD_REG, 1),
_MIR_new_hard_reg_op (gen_ctx->ctx, hard_reg));
}
static void target_make_prolog_epilog (MIR_context_t ctx, bitmap_t used_hard_regs,
static void target_make_prolog_epilog (gen_ctx_t gen_ctx, bitmap_t used_hard_regs,
size_t stack_slots_num) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
MIR_context_t ctx = gen_ctx->ctx;
MIR_func_t func;
MIR_insn_t anchor, new_insn;
MIR_op_t r15_reg_op, r14_reg_op, r11_reg_op, treg_op, r0_reg_op, lr_reg_op;
MIR_op_t r15_reg_op, r14_reg_op, r11_reg_op, r0_reg_op;
int saved_regs_p = FALSE;
int64_t start_saved_fregs_offset;
size_t i, n, frame_size, saved_fregs_num;
@ -813,9 +810,9 @@ static void target_make_prolog_epilog (MIR_context_t ctx, bitmap_t used_hard_reg
anchor = DLIST_HEAD (MIR_insn_t, func->insns);
if (func->vararg_p) { /* save r2-r6,f0,f2,f4,f6: */
for (i = 0; i < 5; i++)
isave (ctx, anchor, S390X_GP_REG_RSAVE_AREA_START + i * 8, i + R2_HARD_REG);
isave (gen_ctx, anchor, S390X_GP_REG_RSAVE_AREA_START + i * 8, i + R2_HARD_REG);
for (i = 0; i < 4; i++)
fsave (ctx, anchor, S390X_FP_REG_ARG_SAVE_AREA_START + i * 8, i * 2 + F0_HARD_REG);
fsave (gen_ctx, anchor, S390X_FP_REG_ARG_SAVE_AREA_START + i * 8, i * 2 + F0_HARD_REG);
}
for (i = saved_fregs_num = 0; i <= MAX_HARD_REG; i++)
if (!target_call_used_hard_reg_p (i) && bitmap_bit_p (used_hard_regs, i)) {
@ -833,50 +830,50 @@ static void target_make_prolog_epilog (MIR_context_t ctx, bitmap_t used_hard_reg
start_saved_fregs_offset = frame_size;
frame_size += saved_fregs_num * 8;
gen_assert (frame_size % 8 == 0);
gen_mov (ctx, anchor, MIR_MOV,
gen_mov (gen_ctx, anchor, MIR_MOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, S390X_GP_REG_RSAVE_AREA_START + (14 - 2) * 8,
R15_HARD_REG, MIR_NON_HARD_REG, 1),
r14_reg_op); /* mem[r15+112] = r14 */
gen_mov (ctx, anchor, MIR_MOV,
gen_mov (gen_ctx, anchor, MIR_MOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, S390X_GP_REG_RSAVE_AREA_START + (11 - 2) * 8,
R15_HARD_REG, MIR_NON_HARD_REG, 1),
r11_reg_op); /* mem[r15+76] = r11 */
for (i = R2_HARD_REG; i < R15_HARD_REG; i++) /* exclude r15 */
if (!target_call_used_hard_reg_p (i) && bitmap_bit_p (used_hard_regs, i)
&& (i != 6 || !func->vararg_p))
isave (ctx, anchor, S390X_GP_REG_RSAVE_AREA_START + (i - R2_HARD_REG) * 8, i);
gen_mov (ctx, anchor, MIR_MOV, r0_reg_op, r15_reg_op); /* r0 = r15 */
isave (gen_ctx, anchor, S390X_GP_REG_RSAVE_AREA_START + (i - R2_HARD_REG) * 8, i);
gen_mov (gen_ctx, anchor, MIR_MOV, r0_reg_op, r15_reg_op); /* r0 = r15 */
new_insn = MIR_new_insn (ctx, MIR_ADD, r15_reg_op, r15_reg_op, MIR_new_int_op (ctx, -frame_size));
gen_add_insn_before (ctx, anchor, new_insn); /* r15 -= frame_size */
gen_mov (ctx, anchor, MIR_MOV,
gen_add_insn_before (gen_ctx, anchor, new_insn); /* r15 -= frame_size */
gen_mov (gen_ctx, anchor, MIR_MOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, 0, R15_HARD_REG, MIR_NON_HARD_REG, 1),
r0_reg_op); /* mem[r15] = r0 */
for (n = 0, i = F0_HARD_REG; i <= MAX_HARD_REG; i++)
if (!target_call_used_hard_reg_p (i) && bitmap_bit_p (used_hard_regs, i))
fsave (ctx, anchor, start_saved_fregs_offset + (n++) * 8, i);
gen_mov (ctx, anchor, MIR_MOV, r11_reg_op, r15_reg_op); /* r11 = r15 */
fsave (gen_ctx, anchor, start_saved_fregs_offset + (n++) * 8, i);
gen_mov (gen_ctx, anchor, MIR_MOV, r11_reg_op, r15_reg_op); /* r11 = r15 */
/* Epilogue: */
anchor = DLIST_TAIL (MIR_insn_t, func->insns);
gen_assert (anchor->code == MIR_RET || anchor->code == MIR_JMP);
/* Restoring fp hard registers: */
for (n = 0, i = F0_HARD_REG; i <= MAX_HARD_REG; i++)
if (!target_call_used_hard_reg_p (i) && bitmap_bit_p (used_hard_regs, i))
gen_mov (ctx, anchor, MIR_DMOV, _MIR_new_hard_reg_op (ctx, i),
gen_mov (gen_ctx, anchor, MIR_DMOV, _MIR_new_hard_reg_op (ctx, i),
_MIR_new_hard_reg_mem_op (ctx, MIR_T_D, start_saved_fregs_offset + (n++) * 8,
R11_HARD_REG, MIR_NON_HARD_REG, 1));
new_insn = MIR_new_insn (ctx, MIR_ADD, r15_reg_op, r11_reg_op, MIR_new_int_op (ctx, frame_size));
gen_add_insn_before (ctx, anchor, new_insn); /* r15 = r11 + frame_size */
gen_add_insn_before (gen_ctx, anchor, new_insn); /* r15 = r11 + frame_size */
/* Restore saved gp regs (including r11 and excluding r15) and r14 */
for (i = R2_HARD_REG; i < R15_HARD_REG; i++)
if (!target_call_used_hard_reg_p (i) && bitmap_bit_p (used_hard_regs, i))
gen_mov (ctx, anchor, MIR_MOV, _MIR_new_hard_reg_op (ctx, i),
gen_mov (gen_ctx, anchor, MIR_MOV, _MIR_new_hard_reg_op (ctx, i),
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64,
S390X_GP_REG_RSAVE_AREA_START + (i - R2_HARD_REG) * 8,
SP_HARD_REG, MIR_NON_HARD_REG, 1));
gen_mov (ctx, anchor, MIR_MOV, r11_reg_op,
gen_mov (gen_ctx, anchor, MIR_MOV, r11_reg_op,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, S390X_GP_REG_RSAVE_AREA_START + (11 - 2) * 8,
R15_HARD_REG, MIR_NON_HARD_REG, 1)); /* restore r11 */
gen_mov (ctx, anchor, MIR_MOV, r14_reg_op,
gen_mov (gen_ctx, anchor, MIR_MOV, r14_reg_op,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, S390X_GP_REG_RSAVE_AREA_START + (14 - 2) * 8,
R15_HARD_REG, MIR_NON_HARD_REG, 1)); /* restore r14 */
}
@ -1354,8 +1351,7 @@ static int pattern_index_cmp (const void *a1, const void *a2) {
return c1 != c2 ? c1 - c2 : (long) i1 - (long) i2;
}
static void patterns_init (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void patterns_init (gen_ctx_t gen_ctx) {
int i, ind, n = sizeof (patterns) / sizeof (struct pattern);
MIR_insn_code_t prev_code, code;
insn_pattern_info_t *info_addr;
@ -1385,7 +1381,8 @@ static int int16_p (int64_t i) { return -(1 << 15) <= i && i < (1 << 15); }
static int uint16_p (uint64_t u) { return !(u >> 16); }
static int nth_uint16_p (uint64_t u, int n) { return !(u & ~(((uint64_t) 0xffff) << n * 16)); }
static int pattern_match_p (MIR_context_t ctx, const struct pattern *pat, MIR_insn_t insn) {
static int pattern_match_p (gen_ctx_t gen_ctx, const struct pattern *pat, MIR_insn_t insn) {
MIR_context_t ctx = gen_ctx->ctx;
int nop, n;
size_t nops = MIR_insn_nops (ctx, insn);
const char *p;
@ -1568,22 +1565,19 @@ static int pattern_match_p (MIR_context_t ctx, const struct pattern *pat, MIR_in
return TRUE;
}
static const char *find_insn_pattern_replacement (MIR_context_t ctx, MIR_insn_t insn) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static const char *find_insn_pattern_replacement (gen_ctx_t gen_ctx, MIR_insn_t insn) {
int i;
const struct pattern *pat;
insn_pattern_info_t info = VARR_GET (insn_pattern_info_t, insn_pattern_info, insn->code);
for (i = 0; i < info.num; i++) {
pat = &patterns[VARR_GET (int, pattern_indexes, info.start + i)];
if (pattern_match_p (ctx, pat, insn)) return pat->replacement;
if (pattern_match_p (gen_ctx, pat, insn)) return pat->replacement;
}
return NULL;
}
static void patterns_finish (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void patterns_finish (gen_ctx_t gen_ctx) {
VARR_DESTROY (int, pattern_indexes);
VARR_DESTROY (insn_pattern_info_t, insn_pattern_info);
}
@ -1656,24 +1650,25 @@ static int setup_imm_addr (struct gen_ctx *gen_ctx, uint64_t v) {
return VARR_LENGTH (const_ref_t, const_refs) - 1;
}
static uint64_t get_op_imm (MIR_context_t ctx, MIR_op_t op) {
static uint64_t get_op_imm (gen_ctx_t gen_ctx, MIR_op_t op) {
if (op.mode == MIR_OP_INT || op.mode == MIR_OP_UINT) return op.u.u;
gen_assert (op.mode == MIR_OP_REF);
if (op.u.ref->item_type == MIR_data_item && op.u.ref->u.data->name != NULL
&& _MIR_reserved_ref_name_p (ctx, op.u.ref->u.data->name))
&& _MIR_reserved_ref_name_p (gen_ctx->ctx, op.u.ref->u.data->name))
return (uint64_t) op.u.ref->u.data->u.els;
return (uint64_t) op.u.ref->addr;
}
static uint64_t get_imm (MIR_context_t ctx, MIR_insn_t insn) {
static uint64_t get_imm (gen_ctx_t gen_ctx, MIR_insn_t insn) {
MIR_op_t *ops = insn->ops;
if (insn->nops >= 2
&& (ops[1].mode == MIR_OP_INT || ops[1].mode == MIR_OP_UINT || ops[1].mode == MIR_OP_REF))
return get_op_imm (ctx, ops[1]);
return get_op_imm (gen_ctx, ops[1]);
if (insn->nops >= 3
&& (ops[2].mode == MIR_OP_INT || ops[2].mode == MIR_OP_UINT || ops[2].mode == MIR_OP_REF))
return get_op_imm (ctx, ops[2]);
return get_op_imm (gen_ctx, ops[2]);
gen_assert (FALSE);
return 0;
}
static uint64_t place_field (uint64_t v, int start_bit, int len) {
@ -1690,8 +1685,8 @@ static void check_and_set_mask (uint64_t *binsn_mask, uint64_t mask, int start_b
*binsn_mask |= place_field (mask, start_bit, len);
}
static void out_insn (MIR_context_t ctx, MIR_insn_t insn, const char *replacement) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void out_insn (gen_ctx_t gen_ctx, MIR_insn_t insn, const char *replacement) {
MIR_context_t ctx = gen_ctx->ctx;
size_t nops = MIR_insn_nops (ctx, insn);
size_t offset;
const char *p, *insn_str;
@ -1710,7 +1705,7 @@ static void out_insn (MIR_context_t ctx, MIR_insn_t insn, const char *replacemen
int opcode1 = -1, opcode2 = -1, opcode11 = -1, opcode12 = -1, mask = -1, MASK = -1;
int r1 = -1, r2 = -1, R1 = -1, R2 = -1, rs = -1, rx = -1;
int imm = -1, IMM = -1, d = -1, dh = -1, label_off = -1, const_ref_num = -1, label_ref_num = -1;
int n, len, v, reg;
int n, len = 0, v, reg;
int switch_table_addr_p = FALSE;
for (p = insn_str; (ch = *p) != '\0' && ch != ';'; p++) {
@ -1822,10 +1817,10 @@ static void out_insn (MIR_context_t ctx, MIR_insn_t insn, const char *replacemen
} else if (ch2 == 'd' || ch2 == 'D') { /* displacement from immediate */
gen_assert (d < 0 && dh < 0);
if (ch2 != 'd' || (d = read_dec (&p)) < 0) {
u = get_imm (ctx, insn);
u = get_imm (gen_ctx, insn);
d = u & 0xfff;
dh = ((int64_t) u >> 12) & 0xff;
if (dh == 0) dh < 0;
if (dh == 0) dh = -1;
}
} else {
if (ch2 != 'n') p--;
@ -1857,13 +1852,13 @@ static void out_insn (MIR_context_t ctx, MIR_insn_t insn, const char *replacemen
gen_assert (imm < 0);
if ((imm = read_dec (&p)) >= 0) {
} else {
u = get_imm (ctx, insn);
u = get_imm (gen_ctx, insn);
imm = u & 0xffff;
}
break;
case 'u':
gen_assert (imm < 0);
u = get_imm (ctx, insn);
u = get_imm (gen_ctx, insn);
ch2 = *++p;
if (ch2 == 'a') {
imm = (u + 7) / 8 * 8;
@ -1874,7 +1869,7 @@ static void out_insn (MIR_context_t ctx, MIR_insn_t insn, const char *replacemen
break;
case 'j':
gen_assert (IMM < 0);
u = get_imm (ctx, insn);
u = get_imm (gen_ctx, insn);
IMM = u & 0xffff;
break;
case 'I': {
@ -1883,7 +1878,7 @@ static void out_insn (MIR_context_t ctx, MIR_insn_t insn, const char *replacemen
ch2 = *++p;
gen_assert (ch2 == 'a');
gen_assert (const_ref_num < 0);
imm = get_imm (ctx, insn);
imm = get_imm (gen_ctx, insn);
const_ref_num = setup_imm_addr (gen_ctx, imm);
break;
}
@ -1895,7 +1890,7 @@ static void out_insn (MIR_context_t ctx, MIR_insn_t insn, const char *replacemen
d = u & 0xfff;
dh = ((int64_t) u >> 12) & 0xff;
gen_assert (ch2 == 'D' || dh == 0);
if (dh == 0) dh < 0;
if (dh == 0) dh = -1;
break;
case 'l':
label_off = read_dec (&p);
@ -2048,12 +2043,12 @@ static void out_insn (MIR_context_t ctx, MIR_insn_t insn, const char *replacemen
}
}
static int target_insn_ok_p (MIR_context_t ctx, MIR_insn_t insn) {
return find_insn_pattern_replacement (ctx, insn) != NULL;
static int target_insn_ok_p (gen_ctx_t gen_ctx, MIR_insn_t insn) {
return find_insn_pattern_replacement (gen_ctx, insn) != NULL;
}
static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static uint8_t *target_translate (gen_ctx_t gen_ctx, size_t *len) {
MIR_context_t ctx = gen_ctx->ctx;
size_t i;
uint64_t zero64 = 0;
MIR_insn_t insn, old_insn;
@ -2073,10 +2068,10 @@ static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
|| code == MIR_LSHS || code == MIR_URSHS)
&& (insn->ops[2].mode == MIR_OP_INT || insn->ops[2].mode == MIR_OP_UINT)) {
if (insn->ops[2].u.i == 0) {
gen_mov (ctx, insn, MIR_MOV, insn->ops[0], insn->ops[1]);
gen_mov (gen_ctx, insn, MIR_MOV, insn->ops[0], insn->ops[1]);
old_insn = insn;
insn = DLIST_NEXT (MIR_insn_t, insn);
gen_delete_insn (ctx, old_insn);
gen_delete_insn (gen_ctx, old_insn);
} else {
if (insn->ops[2].mode == MIR_OP_INT && insn->ops[2].u.i < 0) {
switch (code) {
@ -2086,6 +2081,7 @@ static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
case MIR_RSHS: insn->code = MIR_LSHS; break;
case MIR_URSHS: insn->code = MIR_LSHS; break;
case MIR_LSHS: insn->code = MIR_RSHS; break;
default: gen_assert (FALSE); break;
}
insn->ops[2].u.i = -insn->ops[2].u.i;
}
@ -2097,16 +2093,16 @@ static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
}
}
if (insn->code == MIR_LABEL) {
set_label_disp (ctx, insn, VARR_LENGTH (uint8_t, result_code));
set_label_disp (gen_ctx, insn, VARR_LENGTH (uint8_t, result_code));
} else {
replacement = find_insn_pattern_replacement (ctx, insn);
replacement = find_insn_pattern_replacement (gen_ctx, insn);
if (replacement == NULL) {
fprintf (stderr, "fatal failure in matching insn:");
MIR_output_insn (ctx, stderr, insn, curr_func_item->u.func, TRUE);
exit (1);
} else {
gen_assert (replacement != NULL);
out_insn (ctx, insn, replacement);
out_insn (gen_ctx, insn, replacement);
}
}
}
@ -2116,10 +2112,10 @@ static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
if (lr.abs_addr_p) {
set_int64 (&VARR_ADDR (uint8_t, result_code)[lr.label_val_disp],
(int64_t) get_label_disp (ctx, lr.label));
(int64_t) get_label_disp (gen_ctx, lr.label));
VARR_PUSH (uint64_t, abs_address_locs, lr.label_val_disp);
} else { /* 32-bit relative address */
int64_t offset = (int64_t) get_label_disp (ctx, lr.label) - (int64_t) lr.label_val_disp;
int64_t offset = (int64_t) get_label_disp (gen_ctx, lr.label) - (int64_t) lr.label_val_disp;
gen_assert (offset % 2 == 0);
offset /= 2;
gen_assert (((offset < 0 ? -offset : offset) & ~(int64_t) 0x7fffffff) == 0);
@ -2144,8 +2140,7 @@ static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
return VARR_ADDR (uint8_t, result_code);
}
static void target_rebase (MIR_context_t ctx, uint8_t *base) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void target_rebase (gen_ctx_t gen_ctx, uint8_t *base) {
MIR_code_reloc_t reloc;
VARR_TRUNC (MIR_code_reloc_t, relocs, 0);
@ -2154,14 +2149,12 @@ static void target_rebase (MIR_context_t ctx, uint8_t *base) {
reloc.value = base + get_int64 (base + reloc.offset);
VARR_PUSH (MIR_code_reloc_t, relocs, reloc);
}
_MIR_update_code_arr (ctx, base, VARR_LENGTH (MIR_code_reloc_t, relocs),
_MIR_update_code_arr (gen_ctx->ctx, base, VARR_LENGTH (MIR_code_reloc_t, relocs),
VARR_ADDR (MIR_code_reloc_t, relocs));
}
static void target_init (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
gen_ctx->target_ctx = gen_malloc (ctx, sizeof (struct target_ctx));
static void target_init (gen_ctx_t gen_ctx) {
gen_ctx->target_ctx = gen_malloc (gen_ctx, sizeof (struct target_ctx));
VARR_CREATE (uint8_t, result_code, 0);
VARR_CREATE (uint64_t, const_pool, 0);
VARR_CREATE (const_ref_t, const_refs, 0);
@ -2169,13 +2162,11 @@ static void target_init (MIR_context_t ctx) {
VARR_CREATE (uint64_t, abs_address_locs, 0);
VARR_CREATE (MIR_code_reloc_t, relocs, 0);
VARR_CREATE (uint64_t, ld_addr_regs, 0);
patterns_init (ctx);
patterns_init (gen_ctx);
}
static void target_finish (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
patterns_finish (ctx);
static void target_finish (gen_ctx_t gen_ctx) {
patterns_finish (gen_ctx);
VARR_DESTROY (uint8_t, result_code);
VARR_DESTROY (uint64_t, const_pool);
VARR_DESTROY (const_ref_t, const_refs);

@ -101,11 +101,9 @@ static const int reg_save_area_size = 0;
static const int spill_space_size = 32;
#endif
static MIR_disp_t target_get_stack_slot_offset (MIR_context_t ctx, MIR_type_t type,
static MIR_disp_t target_get_stack_slot_offset (gen_ctx_t gen_ctx, MIR_type_t type,
MIR_reg_t slot) {
/* slot is 0, 1, ... */
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
return -((MIR_disp_t) (slot + (type == MIR_T_LD ? 2 : 1)) * 8
+ (curr_func_item->u.func->vararg_p ? reg_save_area_size : 0));
}
@ -195,8 +193,8 @@ static MIR_reg_t get_arg_reg (MIR_type_t arg_type, size_t *int_arg_num, size_t *
return arg_reg;
}
static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void machinize_call (gen_ctx_t gen_ctx, MIR_insn_t call_insn) {
MIR_context_t ctx = gen_ctx->ctx;
MIR_func_t func = curr_func_item->u.func;
MIR_proto_t proto = call_insn->ops[0].u.ref->u.proto;
size_t nargs, nops = MIR_insn_nops (ctx, call_insn), start = proto->nres + 2;
@ -221,10 +219,10 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
arg_vars = VARR_ADDR (MIR_var_t, proto->args);
}
if (call_insn->ops[1].mode != MIR_OP_REG && call_insn->ops[1].mode != MIR_OP_HARD_REG) {
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
new_insn = MIR_new_insn (ctx, MIR_MOV, temp_op, call_insn->ops[1]);
call_insn->ops[1] = temp_op;
gen_add_insn_before (ctx, call_insn, new_insn);
gen_add_insn_before (gen_ctx, call_insn, new_insn);
}
for (size_t i = start; i < nops; i++) {
arg_op = call_insn->ops[i];
@ -243,17 +241,17 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
if (xmm_args < 8 && (type == MIR_T_F || type == MIR_T_D)) xmm_args++;
ext_insn = NULL;
if ((ext_code = get_ext_code (type)) != MIR_INVALID_INSN) { /* extend arg if necessary */
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, func));
temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func));
ext_insn = MIR_new_insn (ctx, ext_code, temp_op, arg_op);
call_insn->ops[i] = arg_op = temp_op;
}
if ((arg_reg = get_arg_reg (type, &int_arg_num, &fp_arg_num, &new_insn_code))
!= MIR_NON_HARD_REG) {
/* put arguments to argument hard regs */
if (ext_insn != NULL) gen_add_insn_before (ctx, call_insn, ext_insn);
if (ext_insn != NULL) gen_add_insn_before (gen_ctx, call_insn, ext_insn);
arg_reg_op = _MIR_new_hard_reg_op (ctx, arg_reg);
new_insn = MIR_new_insn (ctx, new_insn_code, arg_reg_op, arg_op);
gen_add_insn_before (ctx, call_insn, new_insn);
gen_add_insn_before (gen_ctx, call_insn, new_insn);
call_insn->ops[i] = arg_reg_op;
#ifdef _WIN64
/* copy fp reg varargs into corresponding int regs */
@ -264,10 +262,10 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
/* mir does not support moving fp to int regs directly, spill and load them instead */
mem_op = _MIR_new_hard_reg_mem_op (ctx, MIR_T_D, 8, SP_HARD_REG, MIR_NON_HARD_REG, 1);
new_insn = MIR_new_insn (ctx, MIR_DMOV, mem_op, arg_op);
gen_add_insn_before (ctx, call_insn, new_insn);
gen_add_insn_before (gen_ctx, call_insn, new_insn);
mem_op = _MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, 8, SP_HARD_REG, MIR_NON_HARD_REG, 1);
new_insn = MIR_new_insn (ctx, MIR_MOV, _MIR_new_hard_reg_op (ctx, arg_reg), mem_op);
gen_add_insn_before (ctx, call_insn, new_insn);
gen_add_insn_before (gen_ctx, call_insn, new_insn);
}
#endif
} else { /* put arguments on the stack */
@ -281,18 +279,18 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
MIR_insert_insn_after (ctx, curr_func_item, prev_call_insn, new_insn);
prev_insn = DLIST_PREV (MIR_insn_t, new_insn);
next_insn = DLIST_NEXT (MIR_insn_t, new_insn);
create_new_bb_insns (ctx, prev_insn, next_insn, call_insn);
create_new_bb_insns (gen_ctx, prev_insn, next_insn, call_insn);
call_insn->ops[i] = mem_op;
mem_size += type == MIR_T_LD ? 16 : 8;
if (ext_insn != NULL) gen_add_insn_after (ctx, prev_call_insn, ext_insn);
if (ext_insn != NULL) gen_add_insn_after (gen_ctx, prev_call_insn, ext_insn);
}
}
#ifndef _WIN64
if (proto->vararg_p) {
setup_call_hard_reg_args (ctx, call_insn, AX_HARD_REG);
setup_call_hard_reg_args (gen_ctx, call_insn, AX_HARD_REG);
new_insn = MIR_new_insn (ctx, MIR_MOV, _MIR_new_hard_reg_op (ctx, AX_HARD_REG),
MIR_new_int_op (ctx, xmm_args));
gen_add_insn_before (ctx, call_insn, new_insn);
gen_add_insn_before (gen_ctx, call_insn, new_insn);
}
#else
if (proto->nres > 1)
@ -334,7 +332,7 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
MIR_new_insn (ctx, ext_code, ret_reg_op, ret_reg_op));
new_insn = DLIST_NEXT (MIR_insn_t, new_insn);
}
create_new_bb_insns (ctx, call_insn, DLIST_NEXT (MIR_insn_t, new_insn), call_insn);
create_new_bb_insns (gen_ctx, call_insn, DLIST_NEXT (MIR_insn_t, new_insn), call_insn);
}
if (mem_size != 0) { /* allocate/deallocate stack for args passed on stack */
mem_size = (mem_size + 15) / 16 * 16; /* make it of several 16 bytes */
@ -343,13 +341,13 @@ static void machinize_call (MIR_context_t ctx, MIR_insn_t call_insn) {
_MIR_new_hard_reg_op (ctx, SP_HARD_REG), MIR_new_int_op (ctx, mem_size));
MIR_insert_insn_after (ctx, curr_func_item, prev_call_insn, new_insn);
next_insn = DLIST_NEXT (MIR_insn_t, new_insn);
create_new_bb_insns (ctx, prev_call_insn, next_insn, call_insn);
create_new_bb_insns (gen_ctx, prev_call_insn, next_insn, call_insn);
new_insn
= MIR_new_insn (ctx, MIR_ADD, _MIR_new_hard_reg_op (ctx, SP_HARD_REG),
_MIR_new_hard_reg_op (ctx, SP_HARD_REG), MIR_new_int_op (ctx, mem_size));
MIR_insert_insn_after (ctx, curr_func_item, call_insn, new_insn);
next_insn = DLIST_NEXT (MIR_insn_t, new_insn);
create_new_bb_insns (ctx, call_insn, next_insn, call_insn);
create_new_bb_insns (gen_ctx, call_insn, next_insn, call_insn);
}
}
@ -369,9 +367,9 @@ static const char *LD2I_P = "mir.ld2i.p";
static const char *VA_ARG_P = "mir.va_arg.p";
static const char *VA_ARG = "mir.va_arg";
static void get_builtin (MIR_context_t ctx, MIR_insn_code_t code, MIR_item_t *proto_item,
static void get_builtin (gen_ctx_t gen_ctx, MIR_insn_code_t code, MIR_item_t *proto_item,
MIR_item_t *func_import_item) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
MIR_context_t ctx = gen_ctx->ctx;
MIR_type_t res_type;
*func_import_item = *proto_item = NULL; /* to remove uninitialized warning */
@ -410,9 +408,9 @@ static void get_builtin (MIR_context_t ctx, MIR_insn_code_t code, MIR_item_t *pr
}
}
static void gen_mov (MIR_context_t ctx, MIR_insn_t anchor, MIR_insn_code_t code, MIR_op_t dst_op,
static void gen_mov (gen_ctx_t gen_ctx, MIR_insn_t anchor, MIR_insn_code_t code, MIR_op_t dst_op,
MIR_op_t src_op) {
gen_add_insn_before (ctx, anchor, MIR_new_insn (ctx, code, dst_op, src_op));
gen_add_insn_before (gen_ctx, anchor, MIR_new_insn (gen_ctx->ctx, code, dst_op, src_op));
}
DEF_VARR (int);
@ -473,8 +471,8 @@ struct target_ctx {
#define abs_address_locs gen_ctx->target_ctx->abs_address_locs
#define relocs gen_ctx->target_ctx->relocs
static void target_machinize (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void target_machinize (gen_ctx_t gen_ctx) {
MIR_context_t ctx = gen_ctx->ctx;
MIR_func_t func;
MIR_type_t type, mem_type, res_type;
MIR_insn_code_t code, new_insn_code;
@ -496,7 +494,7 @@ static void target_machinize (MIR_context_t ctx) {
arg_reg_op = _MIR_new_hard_reg_op (ctx, arg_reg);
new_insn = MIR_new_insn (ctx, new_insn_code, MIR_new_reg_op (ctx, i + 1), arg_reg_op);
MIR_prepend_insn (ctx, curr_func_item, new_insn);
create_new_bb_insns (ctx, NULL, DLIST_NEXT (MIR_insn_t, new_insn), NULL);
create_new_bb_insns (gen_ctx, NULL, DLIST_NEXT (MIR_insn_t, new_insn), NULL);
} else {
/* arg is on the stack */
stack_arg_func_p = TRUE;
@ -511,7 +509,7 @@ static void target_machinize (MIR_context_t ctx) {
new_insn = MIR_new_insn (ctx, new_insn_code, MIR_new_reg_op (ctx, i + 1), mem_op);
MIR_prepend_insn (ctx, curr_func_item, new_insn);
next_insn = DLIST_NEXT (MIR_insn_t, new_insn);
create_new_bb_insns (ctx, NULL, next_insn, NULL);
create_new_bb_insns (gen_ctx, NULL, next_insn, NULL);
mem_size += type == MIR_T_LD ? 16 : 8;
}
}
@ -525,22 +523,22 @@ static void target_machinize (MIR_context_t ctx) {
MIR_item_t proto_item, func_import_item;
MIR_op_t freg_op, res_reg_op = insn->ops[0], op_reg_op = insn->ops[1], ops[4];
get_builtin (ctx, code, &proto_item, &func_import_item);
get_builtin (gen_ctx, code, &proto_item, &func_import_item);
assert (res_reg_op.mode == MIR_OP_REG && op_reg_op.mode == MIR_OP_REG);
freg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, curr_func_item->u.func));
freg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, curr_func_item->u.func));
next_insn = new_insn
= MIR_new_insn (ctx, MIR_MOV, freg_op, MIR_new_ref_op (ctx, func_import_item));
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
ops[0] = MIR_new_ref_op (ctx, proto_item);
ops[1] = freg_op;
ops[2] = res_reg_op;
ops[3] = op_reg_op;
new_insn = MIR_new_insn_arr (ctx, MIR_CALL, 4, ops);
gen_add_insn_before (ctx, insn, new_insn);
gen_delete_insn (ctx, insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
gen_delete_insn (gen_ctx, insn);
} else if (code == MIR_VA_START) {
MIR_op_t treg_op
= MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, curr_func_item->u.func));
= MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, curr_func_item->u.func));
MIR_op_t va_op = insn->ops[0];
MIR_reg_t va_reg;
#ifndef _WIN64
@ -558,21 +556,21 @@ static void target_machinize (MIR_context_t ctx) {
va_reg = va_op.mode == MIR_OP_REG ? va_op.u.reg : va_op.u.hard_reg;
/* Insns can be not simplified as soon as they match a machine insn. */
/* mem32[va_reg] = gp_offset; mem32[va_reg] = fp_offset */
gen_mov (ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_U32, 0, va_reg, 0, 1),
gen_mov (gen_ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_U32, 0, va_reg, 0, 1),
MIR_new_int_op (ctx, gp_offset));
next_insn = DLIST_PREV (MIR_insn_t, insn);
gen_mov (ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_U32, 4, va_reg, 0, 1),
gen_mov (gen_ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_U32, 4, va_reg, 0, 1),
MIR_new_int_op (ctx, fp_offset));
/* overflow_arg_area_reg: treg = start sp + 8; mem64[va_reg + 8] = treg */
new_insn = MIR_new_insn (ctx, MIR_ADD, treg_op, _MIR_new_hard_reg_op (ctx, FP_HARD_REG),
MIR_new_int_op (ctx, 8 /*ret*/ + start_sp_from_bp_offset));
gen_add_insn_before (ctx, insn, new_insn);
gen_mov (ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 8, va_reg, 0, 1), treg_op);
gen_add_insn_before (gen_ctx, insn, new_insn);
gen_mov (gen_ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 8, va_reg, 0, 1), treg_op);
/* reg_save_area: treg = start sp - reg_save_area_size; mem64[va_reg + 16] = treg */
new_insn = MIR_new_insn (ctx, MIR_ADD, treg_op, _MIR_new_hard_reg_op (ctx, FP_HARD_REG),
MIR_new_int_op (ctx, -reg_save_area_size));
gen_add_insn_before (ctx, insn, new_insn);
gen_mov (ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 16, va_reg, 0, 1), treg_op);
gen_add_insn_before (gen_ctx, insn, new_insn);
gen_mov (gen_ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 16, va_reg, 0, 1), treg_op);
#else
stack_arg_func_p = TRUE;
/* spill reg args */
@ -582,20 +580,20 @@ static void target_machinize (MIR_context_t ctx) {
mem_op
= _MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, mem_size, FP_HARD_REG, MIR_NON_HARD_REG, 1);
new_insn = MIR_new_insn (ctx, MIR_MOV, mem_op, _MIR_new_hard_reg_op (ctx, arg_reg));
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
mem_size += 8;
}
/* init va_list */
mem_size = 8 /*ret*/ + start_sp_from_bp_offset + func->nargs * 8;
new_insn = MIR_new_insn (ctx, MIR_ADD, treg_op, _MIR_new_hard_reg_op (ctx, FP_HARD_REG),
MIR_new_int_op (ctx, mem_size));
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
va_reg = va_op.mode == MIR_OP_REG ? va_op.u.reg : va_op.u.hard_reg;
gen_mov (ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 0, va_reg, 0, 1), treg_op);
gen_mov (gen_ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 0, va_reg, 0, 1), treg_op);
#endif
gen_delete_insn (ctx, insn);
gen_delete_insn (gen_ctx, insn);
} else if (code == MIR_VA_END) { /* do nothing */
gen_delete_insn (ctx, insn);
gen_delete_insn (gen_ctx, insn);
} else if (code == MIR_VA_ARG) { /* do nothing */
#ifndef _WIN64
/* Use a builtin func call:
@ -605,42 +603,44 @@ static void target_machinize (MIR_context_t ctx) {
MIR_op_t ops[5], func_reg_op, flag_reg_op;
MIR_op_t res_reg_op = insn->ops[0], va_reg_op = insn->ops[1], mem_op = insn->ops[2];
get_builtin (ctx, code, &proto_item, &func_import_item);
get_builtin (gen_ctx, code, &proto_item, &func_import_item);
assert (res_reg_op.mode == MIR_OP_REG && va_reg_op.mode == MIR_OP_REG
&& mem_op.mode == MIR_OP_MEM);
func_reg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, curr_func_item->u.func));
flag_reg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, curr_func_item->u.func));
func_reg_op
= MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, curr_func_item->u.func));
flag_reg_op
= MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, curr_func_item->u.func));
next_insn = new_insn
= MIR_new_insn (ctx, MIR_MOV, func_reg_op, MIR_new_ref_op (ctx, func_import_item));
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
new_insn = MIR_new_insn (ctx, MIR_MOV, flag_reg_op,
MIR_new_int_op (ctx, (int64_t) mem_op.u.mem.type));
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
ops[0] = MIR_new_ref_op (ctx, proto_item);
ops[1] = func_reg_op;
ops[2] = res_reg_op;
ops[3] = va_reg_op;
ops[4] = flag_reg_op;
new_insn = MIR_new_insn_arr (ctx, MIR_CALL, 5, ops);
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
#else
MIR_op_t res_reg_op = insn->ops[0], va_reg_op = insn->ops[1], mem_op = insn->ops[2], treg_op;
assert (res_reg_op.mode == MIR_OP_REG && va_reg_op.mode == MIR_OP_REG
&& mem_op.mode == MIR_OP_MEM);
/* load and increment va pointer */
treg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (ctx, MIR_T_I64, curr_func_item->u.func));
gen_mov (ctx, insn, MIR_MOV, treg_op,
treg_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, curr_func_item->u.func));
gen_mov (gen_ctx, insn, MIR_MOV, treg_op,
MIR_new_mem_op (ctx, MIR_T_I64, 0, va_reg_op.u.reg, 0, 1));
new_insn = MIR_new_insn (ctx, MIR_MOV, res_reg_op, treg_op);
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
new_insn = MIR_new_insn (ctx, MIR_ADD, treg_op, treg_op, MIR_new_int_op (ctx, 8));
gen_add_insn_before (ctx, insn, new_insn);
gen_mov (ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 0, va_reg_op.u.reg, 0, 1),
gen_add_insn_before (gen_ctx, insn, new_insn);
gen_mov (gen_ctx, insn, MIR_MOV, MIR_new_mem_op (ctx, MIR_T_I64, 0, va_reg_op.u.reg, 0, 1),
treg_op);
#endif
gen_delete_insn (ctx, insn);
gen_delete_insn (gen_ctx, insn);
} else if (MIR_call_code_p (code)) {
machinize_call (ctx, insn);
machinize_call (gen_ctx, insn);
leaf_p = FALSE;
} else if (code == MIR_ALLOCA) {
alloca_p = TRUE;
@ -674,7 +674,7 @@ static void target_machinize (MIR_context_t ctx) {
}
ret_reg_op = _MIR_new_hard_reg_op (ctx, ret_reg);
new_insn = MIR_new_insn (ctx, new_insn_code, ret_reg_op, insn->ops[i]);
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
insn->ops[i] = ret_reg_op;
}
} else if (code == MIR_LSH || code == MIR_RSH || code == MIR_URSH || code == MIR_LSHS
@ -683,16 +683,16 @@ static void target_machinize (MIR_context_t ctx) {
MIR_op_t creg_op = _MIR_new_hard_reg_op (ctx, CX_HARD_REG);
new_insn = MIR_new_insn (ctx, MIR_MOV, creg_op, insn->ops[2]);
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
insn->ops[2] = creg_op;
} else if (code == MIR_DIV || code == MIR_UDIV || code == MIR_DIVS || code == MIR_UDIVS) {
/* Divide uses ax/dx as operands: */
MIR_op_t areg_op = _MIR_new_hard_reg_op (ctx, AX_HARD_REG);
new_insn = MIR_new_insn (ctx, MIR_MOV, areg_op, insn->ops[1]);
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
new_insn = MIR_new_insn (ctx, MIR_MOV, insn->ops[0], areg_op);
gen_add_insn_after (ctx, insn, new_insn);
gen_add_insn_after (gen_ctx, insn, new_insn);
insn->ops[0] = insn->ops[1] = areg_op;
} else if (code == MIR_MOD || code == MIR_UMOD || code == MIR_MODS || code == MIR_UMODS) {
/* Divide uses ax/dx as operands: */
@ -700,10 +700,10 @@ static void target_machinize (MIR_context_t ctx) {
MIR_op_t dreg_op = _MIR_new_hard_reg_op (ctx, DX_HARD_REG);
new_insn = MIR_new_insn (ctx, MIR_MOV, areg_op, insn->ops[1]);
gen_add_insn_before (ctx, insn, new_insn);
gen_add_insn_before (gen_ctx, insn, new_insn);
insn->ops[1] = areg_op;
new_insn = MIR_new_insn (ctx, MIR_MOV, insn->ops[0], dreg_op);
gen_add_insn_after (ctx, insn, new_insn);
gen_add_insn_after (gen_ctx, insn, new_insn);
insn->ops[0] = dreg_op;
} else if (code == MIR_EQ || code == MIR_NE || code == MIR_LT || code == MIR_ULT
|| code == MIR_LE || code == MIR_ULE || code == MIR_GT || code == MIR_UGT
@ -717,27 +717,31 @@ static void target_machinize (MIR_context_t ctx) {
MIR_op_t areg_op = _MIR_new_hard_reg_op (ctx, AX_HARD_REG);
new_insn = MIR_new_insn (ctx, MIR_MOV, insn->ops[0], areg_op);
gen_add_insn_after (ctx, insn, new_insn);
gen_add_insn_after (gen_ctx, insn, new_insn);
insn->ops[0] = areg_op;
}
}
}
static void isave (MIR_context_t ctx, MIR_insn_t anchor, int disp, MIR_reg_t hard_reg) {
gen_mov (ctx, anchor, MIR_MOV,
static void isave (gen_ctx_t gen_ctx, MIR_insn_t anchor, int disp, MIR_reg_t hard_reg) {
MIR_context_t ctx = gen_ctx->ctx;
gen_mov (gen_ctx, anchor, MIR_MOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, disp, SP_HARD_REG, MIR_NON_HARD_REG, 1),
_MIR_new_hard_reg_op (ctx, hard_reg));
}
static void dsave (MIR_context_t ctx, MIR_insn_t anchor, int disp, MIR_reg_t hard_reg) {
gen_mov (ctx, anchor, MIR_DMOV,
static void dsave (gen_ctx_t gen_ctx, MIR_insn_t anchor, int disp, MIR_reg_t hard_reg) {
MIR_context_t ctx = gen_ctx->ctx;
gen_mov (gen_ctx, anchor, MIR_DMOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_D, disp, SP_HARD_REG, MIR_NON_HARD_REG, 1),
_MIR_new_hard_reg_op (ctx, hard_reg));
}
static void target_make_prolog_epilog (MIR_context_t ctx, bitmap_t used_hard_regs,
static void target_make_prolog_epilog (gen_ctx_t gen_ctx, bitmap_t used_hard_regs,
size_t stack_slots_num) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
MIR_context_t ctx = gen_ctx->ctx;
MIR_func_t func;
MIR_insn_t anchor, new_insn;
MIR_op_t sp_reg_op, fp_reg_op;
@ -760,65 +764,82 @@ static void target_make_prolog_epilog (MIR_context_t ctx, bitmap_t used_hard_reg
= MIR_new_insn (ctx, MIR_MOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, -8, SP_HARD_REG, MIR_NON_HARD_REG, 1),
fp_reg_op);
gen_add_insn_before (ctx, anchor, new_insn); /* -8(sp) = bp */
gen_add_insn_before (gen_ctx, anchor, new_insn); /* -8(sp) = bp */
/* Use add for matching LEA: */
new_insn = MIR_new_insn (ctx, MIR_ADD, fp_reg_op, sp_reg_op, MIR_new_int_op (ctx, -8));
gen_add_insn_before (ctx, anchor, new_insn); /* bp = sp - 8 */
gen_add_insn_before (gen_ctx, anchor, new_insn); /* bp = sp - 8 */
service_area_size = func->vararg_p ? reg_save_area_size + 8 : 8;
stack_slots_size = stack_slots_num * 8;
/* stack slots, and saved regs as multiple of 16 bytes: */
block_size = (stack_slots_size + 8 * saved_hard_regs_num + 15) / 16 * 16;
new_insn = MIR_new_insn (ctx, MIR_SUB, sp_reg_op, sp_reg_op,
MIR_new_int_op (ctx, block_size + service_area_size));
gen_add_insn_before (ctx, anchor, new_insn); /* sp -= block size + service_area_size */
gen_add_insn_before (gen_ctx, anchor, new_insn); /* sp -= block size + service_area_size */
if (func->vararg_p) {
#ifndef _WIN64
start = block_size;
isave (ctx, anchor, start, DI_HARD_REG);
isave (ctx, anchor, start + 8, SI_HARD_REG);
isave (ctx, anchor, start + 16, DX_HARD_REG);
isave (ctx, anchor, start + 24, CX_HARD_REG);
isave (ctx, anchor, start + 32, R8_HARD_REG);
isave (ctx, anchor, start + 40, R9_HARD_REG);
dsave (ctx, anchor, start + 48, XMM0_HARD_REG);
dsave (ctx, anchor, start + 64, XMM1_HARD_REG);
dsave (ctx, anchor, start + 80, XMM2_HARD_REG);
dsave (ctx, anchor, start + 96, XMM3_HARD_REG);
dsave (ctx, anchor, start + 112, XMM4_HARD_REG);
dsave (ctx, anchor, start + 128, XMM5_HARD_REG);
dsave (ctx, anchor, start + 144, XMM6_HARD_REG);
dsave (ctx, anchor, start + 160, XMM7_HARD_REG);
isave (gen_ctx, anchor, start, DI_HARD_REG);
isave (gen_ctx, anchor, start + 8, SI_HARD_REG);
isave (gen_ctx, anchor, start + 16, DX_HARD_REG);
isave (gen_ctx, anchor, start + 24, CX_HARD_REG);
isave (gen_ctx, anchor, start + 32, R8_HARD_REG);
isave (gen_ctx, anchor, start + 40, R9_HARD_REG);
dsave (gen_ctx, anchor, start + 48, XMM0_HARD_REG);
dsave (gen_ctx, anchor, start + 64, XMM1_HARD_REG);
dsave (gen_ctx, anchor, start + 80, XMM2_HARD_REG);
dsave (gen_ctx, anchor, start + 96, XMM3_HARD_REG);
dsave (gen_ctx, anchor, start + 112, XMM4_HARD_REG);
dsave (gen_ctx, anchor, start + 128, XMM5_HARD_REG);
dsave (gen_ctx, anchor, start + 144, XMM6_HARD_REG);
dsave (gen_ctx, anchor, start + 160, XMM7_HARD_REG);
#endif
}
bp_saved_reg_offset = block_size + (func->vararg_p ? reg_save_area_size : 0);
/* Saving callee saved hard registers: */
for (i = n = 0; i <= MAX_HARD_REG; i++)
if (!target_call_used_hard_reg_p (i) && bitmap_bit_p (used_hard_regs, i)) {
MIR_insn_code_t code = MIR_MOV;
MIR_type_t type = MIR_T_I64;
#ifdef _WIN64
if (i > R15_HARD_REG) {
code = MIR_DMOV;
type = MIR_T_D;
}
#else
assert (i <= R15_HARD_REG); /* xmm regs are always callee-clobbered */
new_insn = MIR_new_insn (ctx, MIR_MOV,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64,
#endif
new_insn = MIR_new_insn (ctx, code,
_MIR_new_hard_reg_mem_op (ctx, type,
(int64_t) (n++ * 8) - bp_saved_reg_offset,
FP_HARD_REG, MIR_NON_HARD_REG, 1),
_MIR_new_hard_reg_op (ctx, i));
gen_add_insn_before (ctx, anchor, new_insn); /* disp(sp) = saved hard reg */
gen_add_insn_before (gen_ctx, anchor, new_insn); /* disp(sp) = saved hard reg */
}
/* Epilogue: */
anchor = DLIST_TAIL (MIR_insn_t, func->insns);
/* Restoring hard registers: */
for (i = n = 0; i <= MAX_HARD_REG; i++)
if (!target_call_used_hard_reg_p (i) && bitmap_bit_p (used_hard_regs, i)) {
new_insn = MIR_new_insn (ctx, MIR_MOV, _MIR_new_hard_reg_op (ctx, i),
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64,
MIR_insn_code_t code = MIR_MOV;
MIR_type_t type = MIR_T_I64;
#ifdef _WIN64
if (i > R15_HARD_REG) {
code = MIR_DMOV;
type = MIR_T_D;
}
#endif
new_insn = MIR_new_insn (ctx, code, _MIR_new_hard_reg_op (ctx, i),
_MIR_new_hard_reg_mem_op (ctx, type,
(int64_t) (n++ * 8) - bp_saved_reg_offset,
FP_HARD_REG, MIR_NON_HARD_REG, 1));
gen_add_insn_before (ctx, anchor, new_insn); /* hard reg = disp(sp) */
gen_add_insn_before (gen_ctx, anchor, new_insn); /* hard reg = disp(sp) */
}
new_insn = MIR_new_insn (ctx, MIR_ADD, sp_reg_op, fp_reg_op, MIR_new_int_op (ctx, 8));
gen_add_insn_before (ctx, anchor, new_insn); /* sp = bp + 8 */
gen_add_insn_before (gen_ctx, anchor, new_insn); /* sp = bp + 8 */
new_insn = MIR_new_insn (ctx, MIR_MOV, fp_reg_op,
_MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, -8, SP_HARD_REG,
MIR_NON_HARD_REG, 1));
gen_add_insn_before (ctx, anchor, new_insn); /* bp = -8(sp) */
gen_add_insn_before (gen_ctx, anchor, new_insn); /* bp = -8(sp) */
}
struct pattern {
@ -1225,8 +1246,7 @@ static int pattern_index_cmp (const void *a1, const void *a2) {
return c1 != c2 ? c1 - c2 : (long) i1 - (long) i2;
}
static void patterns_init (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void patterns_init (gen_ctx_t gen_ctx) {
int i, ind, n = sizeof (patterns) / sizeof (struct pattern);
MIR_insn_code_t prev_code, code;
insn_pattern_info_t *info_addr;
@ -1250,7 +1270,8 @@ static void patterns_init (MIR_context_t ctx) {
info_addr[prev_code].num = n - info_addr[prev_code].start;
}
static int pattern_match_p (MIR_context_t ctx, const struct pattern *pat, MIR_insn_t insn) {
static int pattern_match_p (gen_ctx_t gen_ctx, const struct pattern *pat, MIR_insn_t insn) {
MIR_context_t ctx = gen_ctx->ctx;
int nop, n;
size_t nops = MIR_insn_nops (ctx, insn);
const char *p;
@ -1409,22 +1430,19 @@ static int pattern_match_p (MIR_context_t ctx, const struct pattern *pat, MIR_in
return TRUE;
}
static const char *find_insn_pattern_replacement (MIR_context_t ctx, MIR_insn_t insn) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static const char *find_insn_pattern_replacement (gen_ctx_t gen_ctx, MIR_insn_t insn) {
int i;
const struct pattern *pat;
insn_pattern_info_t info = VARR_GET (insn_pattern_info_t, insn_pattern_info, insn->code);
for (i = 0; i < info.num; i++) {
pat = &patterns[VARR_GET (int, pattern_indexes, info.start + i)];
if (pattern_match_p (ctx, pat, insn)) return pat->replacement;
if (pattern_match_p (gen_ctx, pat, insn)) return pat->replacement;
}
return NULL;
}
static void patterns_finish (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void patterns_finish (gen_ctx_t gen_ctx) {
VARR_DESTROY (int, pattern_indexes);
VARR_DESTROY (insn_pattern_info_t, insn_pattern_info);
}
@ -1590,8 +1608,8 @@ static int setup_imm_addr (struct gen_ctx *gen_ctx, uint64_t v, int *mod, int *r
return VARR_LENGTH (const_ref_t, const_refs) - 1;
}
static void out_insn (MIR_context_t ctx, MIR_insn_t insn, const char *replacement) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void out_insn (gen_ctx_t gen_ctx, MIR_insn_t insn, const char *replacement) {
MIR_context_t ctx = gen_ctx->ctx;
const char *p, *insn_str;
label_ref_t lr;
int switch_table_addr_start = -1;
@ -1906,12 +1924,12 @@ static uint8_t MIR_UNUSED get_short_jump_opcode (uint8_t *long_jump_opcode) {
return long_jump_opcode[1] - 0x10;
}
static int target_insn_ok_p (MIR_context_t ctx, MIR_insn_t insn) {
return find_insn_pattern_replacement (ctx, insn) != NULL;
static int target_insn_ok_p (gen_ctx_t gen_ctx, MIR_insn_t insn) {
return find_insn_pattern_replacement (gen_ctx, insn) != NULL;
}
static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static uint8_t *target_translate (gen_ctx_t gen_ctx, size_t *len) {
MIR_context_t ctx = gen_ctx->ctx;
size_t i;
MIR_insn_t insn;
const char *replacement;
@ -1925,16 +1943,16 @@ static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
for (insn = DLIST_HEAD (MIR_insn_t, curr_func_item->u.func->insns); insn != NULL;
insn = DLIST_NEXT (MIR_insn_t, insn)) {
if (insn->code == MIR_LABEL) {
set_label_disp (ctx, insn, VARR_LENGTH (uint8_t, result_code));
set_label_disp (gen_ctx, insn, VARR_LENGTH (uint8_t, result_code));
} else {
replacement = find_insn_pattern_replacement (ctx, insn);
replacement = find_insn_pattern_replacement (gen_ctx, insn);
if (replacement == NULL) {
fprintf (stderr, "fatal failure in matching insn:");
MIR_output_insn (ctx, stderr, insn, curr_func_item->u.func, TRUE);
exit (1);
} else {
gen_assert (replacement != NULL);
out_insn (ctx, insn, replacement);
out_insn (gen_ctx, insn, replacement);
}
}
}
@ -1944,10 +1962,10 @@ static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
if (!lr.abs_addr_p) {
set_int64 (&VARR_ADDR (uint8_t, result_code)[lr.label_val_disp],
(int64_t) get_label_disp (ctx, lr.label) - (int64_t) lr.next_insn_disp, 4);
(int64_t) get_label_disp (gen_ctx, lr.label) - (int64_t) lr.next_insn_disp, 4);
} else {
set_int64 (&VARR_ADDR (uint8_t, result_code)[lr.label_val_disp],
(int64_t) get_label_disp (ctx, lr.label), 8);
(int64_t) get_label_disp (gen_ctx, lr.label), 8);
VARR_PUSH (uint64_t, abs_address_locs, lr.label_val_disp);
}
}
@ -1965,8 +1983,7 @@ static uint8_t *target_translate (MIR_context_t ctx, size_t *len) {
return VARR_ADDR (uint8_t, result_code);
}
static void target_rebase (MIR_context_t ctx, uint8_t *base) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
static void target_rebase (gen_ctx_t gen_ctx, uint8_t *base) {
MIR_code_reloc_t reloc;
VARR_TRUNC (MIR_code_reloc_t, relocs, 0);
@ -1975,27 +1992,23 @@ static void target_rebase (MIR_context_t ctx, uint8_t *base) {
reloc.value = base + get_int64 (base + reloc.offset, 8);
VARR_PUSH (MIR_code_reloc_t, relocs, reloc);
}
_MIR_update_code_arr (ctx, base, VARR_LENGTH (MIR_code_reloc_t, relocs),
_MIR_update_code_arr (gen_ctx->ctx, base, VARR_LENGTH (MIR_code_reloc_t, relocs),
VARR_ADDR (MIR_code_reloc_t, relocs));
}
static void target_init (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
gen_ctx->target_ctx = gen_malloc (ctx, sizeof (struct target_ctx));
static void target_init (gen_ctx_t gen_ctx) {
gen_ctx->target_ctx = gen_malloc (gen_ctx, sizeof (struct target_ctx));
VARR_CREATE (uint8_t, result_code, 0);
VARR_CREATE (uint64_t, const_pool, 0);
VARR_CREATE (const_ref_t, const_refs, 0);
VARR_CREATE (label_ref_t, label_refs, 0);
VARR_CREATE (uint64_t, abs_address_locs, 0);
VARR_CREATE (MIR_code_reloc_t, relocs, 0);
patterns_init (ctx);
patterns_init (gen_ctx);
}
static void target_finish (MIR_context_t ctx) {
struct gen_ctx *gen_ctx = *gen_ctx_loc (ctx);
patterns_finish (ctx);
static void target_finish (gen_ctx_t gen_ctx) {
patterns_finish (gen_ctx);
VARR_DESTROY (uint8_t, result_code);
VARR_DESTROY (uint64_t, const_pool);
VARR_DESTROY (const_ref_t, const_refs);

File diff suppressed because it is too large Load Diff

@ -518,23 +518,18 @@ static void push_data (MIR_context_t ctx, uint8_t *els, size_t size) {
const char *MIR_item_name (MIR_context_t ctx, MIR_item_t item) {
mir_assert (item != NULL);
return (item->item_type == MIR_func_item
? item->u.func->name
: item->item_type == MIR_proto_item
? item->u.proto->name
: item->item_type == MIR_import_item
? item->u.import_id
: item->item_type == MIR_export_item
? item->u.export_id
: item->item_type == MIR_forward_item
? item->u.forward_id
: item->item_type == MIR_bss_item
? item->u.bss->name
: item->item_type == MIR_data_item
? item->u.data->name
: item->item_type == MIR_ref_data_item
? item->u.ref_data->name
: item->u.expr_data->name);
switch (item->item_type) {
case MIR_func_item: return item->u.func->name;
case MIR_proto_item: return item->u.proto->name;
case MIR_import_item: return item->u.import_id;
case MIR_export_item: return item->u.export_id;
case MIR_forward_item: return item->u.forward_id;
case MIR_bss_item: return item->u.bss->name;
case MIR_data_item: return item->u.data->name;
case MIR_ref_data_item: return item->u.ref_data->name;
case MIR_expr_data_item: return item->u.expr_data->name;
default: mir_assert (FALSE);
}
}
#if !MIR_NO_IO
@ -3262,9 +3257,46 @@ MIR_item_t _MIR_builtin_func (MIR_context_t ctx, MIR_module_t module, const char
/* New Page */
#ifndef _WIN32
#include <sys/mman.h>
#include <unistd.h>
#define PROT_WRITE_EXEC (PROT_WRITE | PROT_EXEC)
#define PROT_READ_EXEC (PROT_READ | PROT_EXEC)
#define mem_protect mprotect
#define mem_unmap munmap
static void *mem_map (size_t len) {
return mmap (NULL, len, PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
}
static size_t mem_page_size () { return sysconf (_SC_PAGE_SIZE); }
#else
#include <memoryapi.h>
#include <sysinfoapi.h>
#define PROT_WRITE_EXEC PAGE_EXECUTE_READWRITE
#define PROT_READ_EXEC PAGE_EXECUTE_READ
#define MAP_FAILED NULL
static int mem_protect (void *addr, size_t len, int prot) {
DWORD old_prot = 0;
return VirtualProtect (addr, len, prot, &old_prot) ? 0 : -1;
}
static int mem_unmap (void *addr, size_t len) {
return VirtualFree (addr, len, MEM_RELEASE) ? 0 : -1;
}
static void *mem_map (size_t len) { return VirtualAlloc (NULL, len, MEM_COMMIT, PAGE_EXECUTE); }
static size_t mem_page_size () {
SYSTEM_INFO sysInfo;
GetSystemInfo (&sysInfo);
return sysInfo.dwPageSize;
}
#endif
struct code_holder {
uint8_t *start, *free, *bound;
};
@ -3296,7 +3328,7 @@ static code_holder_t *get_last_code_holder (MIR_context_t ctx, size_t size) {
}
npages = (size + page_size) / page_size;
len = page_size * npages;
mem = (uint8_t *) mmap (NULL, len, PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
mem = (uint8_t *) mem_map (len);
if (mem == MAP_FAILED) return NULL;
ch.start = mem;
ch.free = mem;
@ -3320,9 +3352,9 @@ static uint8_t *add_code (MIR_context_t ctx, code_holder_t *ch_ptr, const uint8_
ch_ptr->free += code_len;
mir_assert (ch_ptr->free <= ch_ptr->bound);
mprotect (ch_ptr->start, ch_ptr->bound - ch_ptr->start, PROT_WRITE | PROT_EXEC);
mem_protect (ch_ptr->start, ch_ptr->bound - ch_ptr->start, PROT_WRITE_EXEC);
memcpy (mem, code, code_len);
mprotect (ch_ptr->start, ch_ptr->bound - ch_ptr->start, PROT_READ | PROT_EXEC);
mem_protect (ch_ptr->start, ch_ptr->bound - ch_ptr->start, PROT_READ_EXEC);
_MIR_flush_code_cache (mem, ch_ptr->free);
return mem;
}
@ -3354,9 +3386,9 @@ void _MIR_change_code (MIR_context_t ctx, uint8_t *addr, const uint8_t *code, si
start = (size_t) addr / page_size * page_size;
len = (size_t) addr + code_len - start;
mprotect ((uint8_t *) start, len, PROT_WRITE | PROT_EXEC);
mem_protect ((uint8_t *) start, len, PROT_WRITE_EXEC);
memcpy (addr, code, code_len);
mprotect ((uint8_t *) start, len, PROT_READ | PROT_EXEC);
mem_protect ((uint8_t *) start, len, PROT_READ_EXEC);
_MIR_flush_code_cache (addr, addr + code_len);
}
@ -3369,9 +3401,9 @@ void _MIR_update_code_arr (MIR_context_t ctx, uint8_t *base, size_t nloc,
if (max_offset < relocs[i].offset) max_offset = relocs[i].offset;
start = (size_t) base / page_size * page_size;
len = (size_t) base + max_offset + sizeof (void *) - start;
mprotect ((uint8_t *) start, len, PROT_WRITE | PROT_EXEC);
mem_protect ((uint8_t *) start, len, PROT_WRITE_EXEC);
for (i = 0; i < nloc; i++) memcpy (base + relocs[i].offset, &relocs[i].value, sizeof (void *));
mprotect ((uint8_t *) start, len, PROT_READ | PROT_EXEC);
mem_protect ((uint8_t *) start, len, PROT_READ_EXEC);
_MIR_flush_code_cache (base, base + max_offset + sizeof (void *));
}
@ -3389,14 +3421,14 @@ void _MIR_update_code (MIR_context_t ctx, uint8_t *base, size_t nloc, ...) {
va_end (args);
start = (size_t) base / page_size * page_size;
len = (size_t) base + max_offset + sizeof (void *) - start;
mprotect ((uint8_t *) start, len, PROT_WRITE | PROT_EXEC);
mem_protect ((uint8_t *) start, len, PROT_WRITE_EXEC);
va_start (args, nloc);
for (size_t i = 0; i < nloc; i++) {
offset = va_arg (args, size_t);
value = va_arg (args, void *);
memcpy (base + offset, &value, sizeof (void *));
}
mprotect ((uint8_t *) start, len, PROT_READ | PROT_EXEC);
mem_protect ((uint8_t *) start, len, PROT_READ_EXEC);
_MIR_flush_code_cache (base, base + max_offset + sizeof (void *));
va_end (args);
}
@ -3404,7 +3436,7 @@ void _MIR_update_code (MIR_context_t ctx, uint8_t *base, size_t nloc, ...) {
static void code_init (MIR_context_t ctx) {
if ((ctx->machine_code_ctx = malloc (sizeof (struct machine_code_ctx))) == NULL)
(*error_func) (MIR_alloc_error, "Not enough memory for ctx");
page_size = sysconf (_SC_PAGE_SIZE);
page_size = mem_page_size ();
VARR_CREATE (code_holder_t, code_holders, 128);
VARR_CREATE (uint8_t, machine_insns, 1024);
}
@ -3412,7 +3444,7 @@ static void code_init (MIR_context_t ctx) {
static void code_finish (MIR_context_t ctx) {
while (VARR_LENGTH (code_holder_t, code_holders) != 0) {
code_holder_t ch = VARR_POP (code_holder_t, code_holders);
munmap (ch.start, ch.bound - ch.start);
mem_unmap (ch.start, ch.bound - ch.start);
}
VARR_DESTROY (code_holder_t, code_holders);
VARR_DESTROY (uint8_t, machine_insns);
@ -4661,6 +4693,7 @@ DEF_HTAB (label_desc_t);
struct scan_ctx {
jmp_buf error_jmp_buf;
VARR (char) * error_msg_buf;
size_t curr_lno;
HTAB (insn_name_t) * insn_name_tab;
const char *input_string;
@ -4670,6 +4703,7 @@ struct scan_ctx {
};
#define error_jmp_buf ctx->scan_ctx->error_jmp_buf
#define error_msg_buf ctx->scan_ctx->error_msg_buf
#define curr_lno ctx->scan_ctx->curr_lno
#define insn_name_tab ctx->scan_ctx->insn_name_tab
#define input_string ctx->scan_ctx->input_string
@ -4677,16 +4711,19 @@ struct scan_ctx {
#define label_names ctx->scan_ctx->label_names
#define label_desc_tab ctx->scan_ctx->label_desc_tab
static void MIR_NO_RETURN MIR_UNUSED process_error (MIR_context_t ctx,
enum MIR_error_type error_type,
const char *format, ...) {
#define MAX_MESSAGE_LEN 300
char message[MAX_MESSAGE_LEN];
static void scan_error (MIR_context_t ctx, const char *format, ...) {
char message[150];
size_t len;
va_list va;
va_start (va, format);
vsnprintf (message, MAX_MESSAGE_LEN, format, va);
(*error_func) (error_type, "ln %lu: %s", (unsigned long) curr_lno, message);
if (VARR_LENGTH (char, error_msg_buf) != 0) VARR_POP (char, error_msg_buf); /* remove last '\0' */
sprintf (message, "ln %lu: ", (unsigned long) curr_lno);
VARR_PUSH_ARR (char, error_msg_buf, message, strlen (message));
len = vsnprintf (message, sizeof (message), format, va);
VARR_PUSH_ARR (char, error_msg_buf, message, len);
VARR_PUSH_ARR (char, error_msg_buf, "\n", 2); /* add '\n' and '\0' */
va_end (va);
longjmp (error_jmp_buf, TRUE);
}
@ -4784,8 +4821,7 @@ static void scan_string (MIR_context_t ctx, token_t *t, int c, int get_char (MIR
for (;;) {
if ((c = get_char (ctx)) == EOF || c == '\n') {
VARR_PUSH (char, temp_string, '\0');
process_error (ctx, MIR_syntax_error, "unfinished string \"%s",
VARR_ADDR (char, temp_string));
scan_error (ctx, "unfinished string \"%s", VARR_ADDR (char, temp_string));
}
if (c == '"') break;
if (c == '\\') {
@ -4829,8 +4865,7 @@ static void scan_string (MIR_context_t ctx, token_t *t, int c, int get_char (MIR
c = get_char (ctx);
if (!isxdigit (c)) {
VARR_PUSH (char, temp_string, '\0');
process_error (ctx, MIR_syntax_error, "wrong hexadecimal escape in %s",
VARR_ADDR (char, temp_string));
scan_error (ctx, "wrong hexadecimal escape in %s", VARR_ADDR (char, temp_string));
}
c = '0' <= c && c <= '9' ? c - '0' : 'a' <= c && c <= 'f' ? c - 'a' + 10 : c - 'A' + 10;
ch_code = (ch_code << 4) | c;
@ -4905,8 +4940,7 @@ static void scan_token (MIR_context_t ctx, token_t *token, int (*get_char) (MIR_
if (ch == '+' || ch == '-') {
next_ch = get_char (ctx);
if (!isdigit (next_ch))
process_error (ctx, MIR_syntax_error, "no number after a sign %c", ch);
if (!isdigit (next_ch)) scan_error (ctx, "no number after a sign %c", ch);
unget_char (ctx, next_ch);
}
scan_number (ctx, ch, get_char, unget_char, &base, &float_p, &double_p, &ldouble_p);
@ -4932,7 +4966,7 @@ static void scan_token (MIR_context_t ctx, token_t *token, int (*get_char) (MIR_
return;
} else {
VARR_PUSH (char, temp_string, '\0');
process_error (ctx, MIR_syntax_error, "wrong char after %s", VARR_ADDR (char, temp_string));
scan_error (ctx, "wrong char after %s", VARR_ADDR (char, temp_string));
}
}
}
@ -4959,22 +4993,6 @@ static MIR_label_t create_label_desc (MIR_context_t ctx, const char *name) {
return label;
}
MIR_type_t MIR_str2type (MIR_context_t ctx, const char *type_name) {
if (strcmp (type_name, "i64") == 0) return MIR_T_I64;
if (strcmp (type_name, "u64") == 0) return MIR_T_U64;
if (strcmp (type_name, "f") == 0) return MIR_T_F;
if (strcmp (type_name, "d") == 0) return MIR_T_D;
if (strcmp (type_name, "ld") == 0) return MIR_T_LD;
if (strcmp (type_name, "p") == 0) return MIR_T_P;
if (strcmp (type_name, "i32") == 0) return MIR_T_I32;
if (strcmp (type_name, "u32") == 0) return MIR_T_U32;
if (strcmp (type_name, "i16") == 0) return MIR_T_I16;
if (strcmp (type_name, "u16") == 0) return MIR_T_U16;
if (strcmp (type_name, "i8") == 0) return MIR_T_I8;
if (strcmp (type_name, "u8") == 0) return MIR_T_U8;
return MIR_T_BOUND;
}
static int func_reg_p (MIR_context_t ctx, MIR_func_t func, const char *name) {
size_t rdn, tab_rdn;
reg_desc_t rd;
@ -5002,16 +5020,30 @@ static void read_func_proto (MIR_context_t ctx, size_t nops, MIR_op_t *ops) {
}
VARR_TRUNC (MIR_var_t, temp_vars, 0);
for (; i < nops; i++) {
if (ops[i].mode != MIR_OP_MEM)
process_error (ctx, MIR_syntax_error, "wrong prototype/func arg");
if (ops[i].mode != MIR_OP_MEM) scan_error (ctx, "wrong prototype/func arg");
var.type = ops[i].u.mem.type;
var.name = (const char *) ops[i].u.mem.disp;
if (var.name == NULL)
process_error (ctx, MIR_syntax_error, "all func/prototype args should have type:name form");
if (var.name == NULL) scan_error (ctx, "all func/prototype args should have type:name form");
VARR_PUSH (MIR_var_t, temp_vars, var);
}
}
static MIR_type_t str2type (const char *type_name) {
if (strcmp (type_name, "i64") == 0) return MIR_T_I64;
if (strcmp (type_name, "u64") == 0) return MIR_T_U64;
if (strcmp (type_name, "f") == 0) return MIR_T_F;
if (strcmp (type_name, "d") == 0) return MIR_T_D;
if (strcmp (type_name, "ld") == 0) return MIR_T_LD;
if (strcmp (type_name, "p") == 0) return MIR_T_P;
if (strcmp (type_name, "i32") == 0) return MIR_T_I32;
if (strcmp (type_name, "u32") == 0) return MIR_T_U32;
if (strcmp (type_name, "i16") == 0) return MIR_T_I16;
if (strcmp (type_name, "u16") == 0) return MIR_T_U16;
if (strcmp (type_name, "i8") == 0) return MIR_T_I8;
if (strcmp (type_name, "u8") == 0) return MIR_T_U8;
return MIR_T_BOUND;
}
/* Syntax:
program: { insn / sep }
sep : ';' | NL
@ -5044,6 +5076,7 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) {
int bss_p, ref_p, expr_p, string_p, local_p, push_op_p, read_p, disp_p;
insn_name_t in, el;
VARR_TRUNC (char, error_msg_buf, 0);
curr_lno = 1;
input_string = str;
input_string_char_num = 0;
@ -5059,8 +5092,7 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) {
while (t.code == TC_NL) scan_token (ctx, &t, get_string_char, unget_string_char);
if (t.code == TC_EOFILE) break;
for (;;) { /* label_names */
if (t.code != TC_NAME)
process_error (ctx, MIR_syntax_error, "insn should start with label or insn name");
if (t.code != TC_NAME) scan_error (ctx, "insn should start with label or insn name");
name = t.u.name;
scan_token (ctx, &t, get_string_char, unget_string_char);
if (t.code != TC_COL) break;
@ -5074,63 +5106,63 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) {
if (strcmp (name, "module") == 0) {
module_p = TRUE;
if (VARR_LENGTH (label_name_t, label_names) != 1)
process_error (ctx, MIR_syntax_error, "only one label should be used for module");
scan_error (ctx, "only one label should be used for module");
} else if (strcmp (name, "endmodule") == 0) {
end_module_p = TRUE;
if (VARR_LENGTH (label_name_t, label_names) != 0)
process_error (ctx, MIR_syntax_error, "endmodule should have no labels");
scan_error (ctx, "endmodule should have no labels");
} else if (strcmp (name, "proto") == 0) {
proto_p = TRUE;
if (VARR_LENGTH (label_name_t, label_names) != 1)
process_error (ctx, MIR_syntax_error, "only one label should be used for proto");
scan_error (ctx, "only one label should be used for proto");
} else if (strcmp (name, "func") == 0) {
func_p = TRUE;
if (VARR_LENGTH (label_name_t, label_names) != 1)
process_error (ctx, MIR_syntax_error, "only one label should be used for func");
scan_error (ctx, "only one label should be used for func");
} else if (strcmp (name, "endfunc") == 0) {
end_func_p = TRUE;
if (VARR_LENGTH (label_name_t, label_names) != 0)
process_error (ctx, MIR_syntax_error, "endfunc should have no labels");
scan_error (ctx, "endfunc should have no labels");
} else if (strcmp (name, "export") == 0) {
export_p = TRUE;
if (VARR_LENGTH (label_name_t, label_names) != 0)
process_error (ctx, MIR_syntax_error, "export should have no labels");
scan_error (ctx, "export should have no labels");
} else if (strcmp (name, "import") == 0) {
import_p = TRUE;
if (VARR_LENGTH (label_name_t, label_names) != 0)
process_error (ctx, MIR_syntax_error, "import should have no labels");
scan_error (ctx, "import should have no labels");
} else if (strcmp (name, "forward") == 0) {
forward_p = TRUE;
if (VARR_LENGTH (label_name_t, label_names) != 0)
process_error (ctx, MIR_syntax_error, "forward should have no labels");
scan_error (ctx, "forward should have no labels");
} else if (strcmp (name, "bss") == 0) {
bss_p = TRUE;
if (VARR_LENGTH (label_name_t, label_names) > 1)
process_error (ctx, MIR_syntax_error, "at most one label should be used for bss");
scan_error (ctx, "at most one label should be used for bss");
} else if (strcmp (name, "ref") == 0) {
ref_p = TRUE;
if (VARR_LENGTH (label_name_t, label_names) > 1)
process_error (ctx, MIR_syntax_error, "at most one label should be used for ref");
scan_error (ctx, "at most one label should be used for ref");
} else if (strcmp (name, "expr") == 0) {
expr_p = TRUE;
if (VARR_LENGTH (label_name_t, label_names) > 1)
process_error (ctx, MIR_syntax_error, "at most one label should be used for expr");
scan_error (ctx, "at most one label should be used for expr");
} else if (strcmp (name, "string") == 0) {
string_p = TRUE;
if (VARR_LENGTH (label_name_t, label_names) > 1)
process_error (ctx, MIR_syntax_error, "at most one label should be used for string");
scan_error (ctx, "at most one label should be used for string");
} else if (strcmp (name, "local") == 0) {
local_p = TRUE;
if (func == NULL) process_error (ctx, MIR_syntax_error, "local outside func");
if (func == NULL) scan_error (ctx, "local outside func");
if (VARR_LENGTH (label_name_t, label_names) != 0)
process_error (ctx, MIR_syntax_error, "local should have no labels");
} else if ((data_type = MIR_str2type (ctx, name)) != MIR_T_BOUND) {
scan_error (ctx, "local should have no labels");
} else if ((data_type = str2type (name)) != MIR_T_BOUND) {
if (VARR_LENGTH (label_name_t, label_names) > 1)
process_error (ctx, MIR_syntax_error, "at most one label should be used for data");
scan_error (ctx, "at most one label should be used for data");
} else {
in.name = name;
if (!HTAB_DO (insn_name_t, insn_name_tab, in, HTAB_FIND, el))
process_error (ctx, MIR_syntax_error, "Unknown insn %s", name);
scan_error (ctx, "Unknown insn %s", name);
insn_code = el.code;
for (n = 0; n < VARR_LENGTH (label_name_t, label_names); n++) {
label = create_label_desc (ctx, VARR_GET (label_name_t, label_names, n));
@ -5176,23 +5208,22 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) {
} else if ((item = find_item (ctx, name, module)) != NULL) {
op = MIR_new_ref_op (ctx, item);
} else {
process_error (ctx, MIR_syntax_error, "undeclared name %s", name);
scan_error (ctx, "undeclared name %s", name);
}
break;
}
/* Memory, type only, arg, or var */
type = MIR_str2type (ctx, name);
type = str2type (name);
if (type == MIR_T_BOUND)
process_error (ctx, MIR_syntax_error, "Unknown type %s", name);
scan_error (ctx, "Unknown type %s", name);
else if (local_p && type != MIR_T_I64 && type != MIR_T_F && type != MIR_T_D
&& type != MIR_T_LD)
process_error (ctx, MIR_syntax_error, "wrong type %s for local var", name);
scan_error (ctx, "wrong type %s for local var", name);
op = MIR_new_mem_op (ctx, type, 0, 0, 0, 1);
if (proto_p || func_p || local_p) {
if (t.code == TC_COL) {
scan_token (ctx, &t, get_string_char, unget_string_char);
if (t.code != TC_NAME)
process_error (ctx, MIR_syntax_error, func_p ? "wrong arg" : "wrong local var");
if (t.code != TC_NAME) scan_error (ctx, func_p ? "wrong arg" : "wrong local var");
op.u.mem.disp = (MIR_disp_t) t.u.name;
scan_token (ctx, &t, get_string_char, unget_string_char);
}
@ -5216,20 +5247,20 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) {
}
if (t.code == TC_COMMA) {
scan_token (ctx, &t, get_string_char, unget_string_char);
if (t.code != TC_NAME) process_error (ctx, MIR_syntax_error, "wrong index");
if (t.code != TC_NAME) scan_error (ctx, "wrong index");
op.u.mem.index = MIR_reg (ctx, t.u.name, func->u.func);
scan_token (ctx, &t, get_string_char, unget_string_char);
if (t.code == TC_COMMA) {
scan_token (ctx, &t, get_string_char, unget_string_char);
if (t.code != TC_INT) process_error (ctx, MIR_syntax_error, "wrong scale");
if (t.code != TC_INT) scan_error (ctx, "wrong scale");
op.u.mem.scale = t.u.i;
scan_token (ctx, &t, get_string_char, unget_string_char);
}
}
if (t.code != TC_RIGHT_PAR) process_error (ctx, MIR_syntax_error, "wrong memory op");
if (t.code != TC_RIGHT_PAR) scan_error (ctx, "wrong memory op");
scan_token (ctx, &t, get_string_char, unget_string_char);
} else if (!disp_p)
process_error (ctx, MIR_syntax_error, "wrong memory");
scan_error (ctx, "wrong memory");
}
break;
}
@ -5262,61 +5293,59 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) {
scan_token (ctx, &t, get_string_char, unget_string_char);
}
if (t.code != TC_NL && t.code != TC_EOFILE && t.code != TC_SEMICOL)
process_error (ctx, MIR_syntax_error, "wrong insn end");
scan_error (ctx, "wrong insn end");
if (module_p) {
if (module != NULL) process_error (ctx, MIR_syntax_error, "nested module");
if (module != NULL) scan_error (ctx, "nested module");
if (VARR_LENGTH (MIR_op_t, temp_insn_ops) != 0)
process_error (ctx, MIR_syntax_error, "module should have no params");
scan_error (ctx, "module should have no params");
module = MIR_new_module (ctx, VARR_GET (label_name_t, label_names, 0));
} else if (end_module_p) {
if (module == NULL) process_error (ctx, MIR_syntax_error, "standalone endmodule");
if (module == NULL) scan_error (ctx, "standalone endmodule");
if (VARR_LENGTH (MIR_op_t, temp_insn_ops) != 0)
process_error (ctx, MIR_syntax_error, "endmodule should have no params");
scan_error (ctx, "endmodule should have no params");
MIR_finish_module (ctx);
module = NULL;
} else if (bss_p) {
if (VARR_LENGTH (MIR_op_t, temp_insn_ops) != 1)
process_error (ctx, MIR_syntax_error, "bss should have one operand");
scan_error (ctx, "bss should have one operand");
op_addr = VARR_ADDR (MIR_op_t, temp_insn_ops);
if (op_addr[0].mode != MIR_OP_INT || op_addr[0].u.i < 0)
process_error (ctx, MIR_syntax_error, "wrong bss operand type or value");
scan_error (ctx, "wrong bss operand type or value");
name
= (VARR_LENGTH (label_name_t, label_names) == 0 ? NULL
: VARR_GET (label_name_t, label_names, 0));
MIR_new_bss (ctx, name, op_addr[0].u.i);
} else if (ref_p) {
if (VARR_LENGTH (MIR_op_t, temp_insn_ops) != 2)
process_error (ctx, MIR_syntax_error, "ref should have two operands");
scan_error (ctx, "ref should have two operands");
op_addr = VARR_ADDR (MIR_op_t, temp_insn_ops);
if (op_addr[0].mode != MIR_OP_REF) process_error (ctx, MIR_syntax_error, "wrong ref operand");
if (op_addr[1].mode != MIR_OP_INT)
process_error (ctx, MIR_syntax_error, "wrong ref disp operand");
if (op_addr[0].mode != MIR_OP_REF) scan_error (ctx, "wrong ref operand");
if (op_addr[1].mode != MIR_OP_INT) scan_error (ctx, "wrong ref disp operand");
name
= (VARR_LENGTH (label_name_t, label_names) == 0 ? NULL
: VARR_GET (label_name_t, label_names, 0));
MIR_new_ref_data (ctx, name, op_addr[0].u.ref, op_addr[1].u.i);
} else if (expr_p) {
if (VARR_LENGTH (MIR_op_t, temp_insn_ops) != 1)
process_error (ctx, MIR_syntax_error, "expr should have one operand");
scan_error (ctx, "expr should have one operand");
op_addr = VARR_ADDR (MIR_op_t, temp_insn_ops);
if (op_addr[0].mode != MIR_OP_REF || op_addr[0].u.ref->item_type != MIR_func_item)
process_error (ctx, MIR_syntax_error, "wrong expr operand");
scan_error (ctx, "wrong expr operand");
name
= (VARR_LENGTH (label_name_t, label_names) == 0 ? NULL
: VARR_GET (label_name_t, label_names, 0));
MIR_new_expr_data (ctx, name, op_addr[0].u.ref);
} else if (string_p) {
if (VARR_LENGTH (MIR_op_t, temp_insn_ops) != 1)
process_error (ctx, MIR_syntax_error, "string should have one operand");
scan_error (ctx, "string should have one operand");
op_addr = VARR_ADDR (MIR_op_t, temp_insn_ops);
if (op_addr[0].mode != MIR_OP_STR)
process_error (ctx, MIR_syntax_error, "wrong string data operand type");
if (op_addr[0].mode != MIR_OP_STR) scan_error (ctx, "wrong string data operand type");
name
= (VARR_LENGTH (label_name_t, label_names) == 0 ? NULL
: VARR_GET (label_name_t, label_names, 0));
MIR_new_string_data (ctx, name, op_addr[0].u.str);
} else if (proto_p) {
if (module == NULL) process_error (ctx, MIR_syntax_error, "prototype outside module");
if (module == NULL) scan_error (ctx, "prototype outside module");
read_func_proto (ctx, VARR_LENGTH (MIR_op_t, temp_insn_ops),
VARR_ADDR (MIR_op_t, temp_insn_ops));
if (dots_p)
@ -5330,8 +5359,8 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) {
VARR_LENGTH (MIR_type_t, temp_types), VARR_ADDR (MIR_type_t, temp_types),
VARR_LENGTH (MIR_var_t, temp_vars), VARR_ADDR (MIR_var_t, temp_vars));
} else if (func_p) {
if (module == NULL) process_error (ctx, MIR_syntax_error, "func outside module");
if (func != NULL) process_error (ctx, MIR_syntax_error, "nested func");
if (module == NULL) scan_error (ctx, "func outside module");
if (func != NULL) scan_error (ctx, "nested func");
read_func_proto (ctx, VARR_LENGTH (MIR_op_t, temp_insn_ops),
VARR_ADDR (MIR_op_t, temp_insn_ops));
if (dots_p)
@ -5348,9 +5377,9 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) {
VARR_LENGTH (MIR_var_t, temp_vars), VARR_ADDR (MIR_var_t, temp_vars));
HTAB_CLEAR (label_desc_t, label_desc_tab);
} else if (end_func_p) {
if (func == NULL) process_error (ctx, MIR_syntax_error, "standalone endfunc");
if (func == NULL) scan_error (ctx, "standalone endfunc");
if (VARR_LENGTH (MIR_op_t, temp_insn_ops) != 0)
process_error (ctx, MIR_syntax_error, "endfunc should have no params");
scan_error (ctx, "endfunc should have no params");
func = NULL;
MIR_finish_func (ctx);
} else if (export_p || import_p || forward_p) { /* we already created items, now do nothing: */
@ -5360,7 +5389,7 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) {
n = VARR_LENGTH (MIR_op_t, temp_insn_ops);
for (i = 0; i < n; i++) {
if (op_addr[i].mode != MIR_OP_MEM || (const char *) op_addr[i].u.mem.disp == NULL)
process_error (ctx, MIR_syntax_error, "wrong local var");
scan_error (ctx, "wrong local var");
MIR_new_func_reg (ctx, func->u.func, op_addr[i].u.mem.type,
(const char *) op_addr[i].u.mem.disp);
}
@ -5381,7 +5410,7 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) {
VARR_TRUNC (uint8_t, temp_data, 0);
for (i = 0; i < n; i++) {
if (op_addr[i].mode != type2mode (data_type))
process_error (ctx, MIR_syntax_error, "data operand is not of data type");
scan_error (ctx, "data operand is not of data type");
switch (data_type) {
case MIR_T_I8:
v.i8 = op_addr[i].u.i;
@ -5421,7 +5450,7 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) {
push_data (ctx, (uint8_t *) &op_addr[i].u.ld, sizeof (long double));
break;
/* ptr ??? */
default: process_error (ctx, MIR_syntax_error, "wrong data clause");
default: scan_error (ctx, "wrong data clause");
}
}
name
@ -5436,8 +5465,10 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) {
if (func != NULL) MIR_append_insn (ctx, func, insn);
}
}
if (func != NULL) process_error (ctx, MIR_syntax_error, "absent endfunc");
if (module != NULL) process_error (ctx, MIR_syntax_error, "absent endmodule");
if (func != NULL) scan_error (ctx, "absent endfunc");
if (module != NULL) scan_error (ctx, "absent endmodule");
if (VARR_LENGTH (char, error_msg_buf) != 0)
(*error_func) (MIR_syntax_error, VARR_ADDR (char, error_msg_buf));
}
static void scan_init (MIR_context_t ctx) {
@ -5446,6 +5477,7 @@ static void scan_init (MIR_context_t ctx) {
if ((ctx->scan_ctx = malloc (sizeof (struct scan_ctx))) == NULL)
(*error_func) (MIR_alloc_error, "Not enough memory for ctx");
VARR_CREATE (char, error_msg_buf, 0);
VARR_CREATE (label_name_t, label_names, 0);
HTAB_CREATE (label_desc_t, label_desc_tab, 100, label_hash, label_eq, NULL);
HTAB_CREATE (insn_name_t, insn_name_tab, MIR_INSN_BOUND, insn_name_hash, insn_name_eq, NULL);
@ -5457,6 +5489,7 @@ static void scan_init (MIR_context_t ctx) {
}
static void scan_finish (MIR_context_t ctx) {
VARR_DESTROY (char, error_msg_buf);
VARR_DESTROY (label_name_t, label_names);
HTAB_DESTROY (label_desc_t, label_desc_tab);
HTAB_DESTROY (insn_name_t, insn_name_tab);

@ -0,0 +1,40 @@
/* This file is a part of MIR project.
Copyright (C) 2018-2020 Vladimir Makarov <vmakarov.gcc@gmail.com> and logzero <core13@gmx.net>
*/
#ifndef _WIN32
#include <sys/time.h>
static double __attribute__ ((unused)) real_sec_time (void) {
struct timeval tv;
gettimeofday (&tv, NULL);
return tv.tv_usec / 1000000.0 + tv.tv_sec;
}
static double __attribute__ ((unused)) real_usec_time (void) {
struct timeval tv;
gettimeofday (&tv, NULL);
return tv.tv_usec + tv.tv_sec * 1000000.0;
}
#else
#include <profileapi.h>
// does not return actual time, use as a stopwatch only
static double real_sec_time (void) {
LARGE_INTEGER freq, count;
if (QueryPerformanceFrequency (&freq) && QueryPerformanceCounter (&count))
return (double) count.QuadPart / (double) freq.QuadPart;
return 0.0;
}
static double real_usec_time (void) {
LARGE_INTEGER freq, count;
if (QueryPerformanceFrequency (&freq) && QueryPerformanceCounter (&count))
return (double) count.QuadPart / ((double) freq.QuadPart * 1.0E-6);
return 0.0;
}
#endif
Loading…
Cancel
Save