{
/* The function uses this variable to issue error to user right away. */
int fp_traceable_p = 0;
- struct ginsn_dst *dst;
+ enum ginsn_type gtype;
struct ginsn_src *src1;
struct ginsn_src *src2;
+ struct ginsn_dst *dst;
+ unsigned int src1_reg;
+ unsigned int dst_reg;
+ enum ginsn_src_type src1_type;
+ enum ginsn_src_type src2_type;
+ enum ginsn_dst_type dst_type;
+
+ gtype = ginsn->type;
src1 = ginsn_get_src1 (ginsn);
src2 = ginsn_get_src2 (ginsn);
dst = ginsn_get_dst (ginsn);
+ src1_reg = ginsn_get_src_reg (src1);
+ dst_reg = ginsn_get_dst_reg (dst);
+
+ src1_type = ginsn_get_src_type (src1);
+ src2_type = ginsn_get_src_type (src2);
+ dst_type = ginsn_get_dst_type (dst);
+
/* Stack manipulation can be done in a variety of ways. A program may
allocate stack statically or may perform dynamic stack allocation in
the prologue.
/* Check all applicable instructions with dest REG_FP, when the CFA base
register is REG_FP. */
- if (state->regs[REG_CFA].base == REG_FP && ginsn_get_dst_reg (dst) == REG_FP)
+ if (state->regs[REG_CFA].base == REG_FP
+ && (dst_type == GINSN_DST_REG || dst_type == GINSN_DST_INDIRECT)
+ && dst_reg == REG_FP)
{
/* Excuse the add/sub with imm usage: They are OK. */
- if ((ginsn->type == GINSN_TYPE_ADD || ginsn->type == GINSN_TYPE_SUB)
- && ginsn_get_src_reg (src1) == REG_FP
- && ginsn_get_src_type (src2) == GINSN_SRC_IMM)
+ if ((gtype == GINSN_TYPE_ADD || gtype == GINSN_TYPE_SUB)
+ && src1_type == GINSN_SRC_REG && src1_reg == REG_FP
+ && src2_type == GINSN_SRC_IMM)
fp_traceable_p = 0;
/* REG_FP restore is OK too. */
else if (ginsn->type == GINSN_TYPE_LOAD)
fp_traceable_p = 0;
/* mov's to memory with REG_FP base do not make REG_FP untraceable. */
- else if (ginsn_get_dst_type (dst) == GINSN_DST_INDIRECT
- && (ginsn->type == GINSN_TYPE_MOV
- || ginsn->type == GINSN_TYPE_STORE))
+ else if (dst_type == GINSN_DST_INDIRECT
+ && (gtype == GINSN_TYPE_MOV || gtype == GINSN_TYPE_STORE))
fp_traceable_p = 0;
/* Manipulations of the values possibly on stack are OK too. */
- else if ((ginsn->type == GINSN_TYPE_ADD || ginsn->type == GINSN_TYPE_SUB
- || ginsn->type == GINSN_TYPE_AND)
- && ginsn_get_dst_type (dst) == GINSN_DST_INDIRECT)
+ else if ((gtype == GINSN_TYPE_ADD || gtype == GINSN_TYPE_SUB
+ || gtype == GINSN_TYPE_AND)
+ && dst_type == GINSN_DST_INDIRECT)
fp_traceable_p = 0;
/* All other ginsns with REG_FP as destination make REG_FP not
traceable. */
/* The function uses this variable to issue error to user right away. */
int sp_untraceable_p = 0;
bool possibly_untraceable = false;
+ enum ginsn_type gtype;
struct ginsn_dst *dst;
struct ginsn_src *src1;
struct ginsn_src *src2;
+ unsigned int src1_reg;
+ unsigned int dst_reg;
+ enum ginsn_src_type src1_type;
+ enum ginsn_src_type src2_type;
+ enum ginsn_dst_type dst_type;
+
+ gtype = ginsn->type;
src1 = ginsn_get_src1 (ginsn);
src2 = ginsn_get_src2 (ginsn);
dst = ginsn_get_dst (ginsn);
+ src1_reg = ginsn_get_src_reg (src1);
+ dst_reg = ginsn_get_dst_reg (dst);
+
+ src1_type = ginsn_get_src_type (src1);
+ src2_type = ginsn_get_src_type (src2);
+ dst_type = ginsn_get_dst_type (dst);
+
/* Stack manipulation can be done in a variety of ways. A program may
allocate stack statically in prologue or may need to do dynamic stack
allocation.
amount of stack usage (and hence, the value of rsp) must be known at
all times. */
- if (ginsn->type == GINSN_TYPE_MOV
- && ginsn_get_dst_type (dst) == GINSN_DST_REG
- && ginsn_get_dst_reg (dst) == REG_SP
- && ginsn_get_src_type (src1) == GINSN_SRC_REG
+ if (gtype == GINSN_TYPE_MOV
+ && dst_type == GINSN_DST_REG && dst_reg == REG_SP
/* Exclude mov %rbp, %rsp from this check. */
- && ginsn_get_src_reg (src1) != REG_FP)
+ && src1_type == GINSN_SRC_REG && src1_reg != REG_FP)
{
- /* mov %reg, %rsp. */
/* A previous mov %rsp, %reg must have been seen earlier for this to be
an OK for stack manipulation. */
- if (state->scratch[ginsn_get_src_reg (src1)].base != REG_CFA
- || state->scratch[ginsn_get_src_reg (src1)].state != CFI_IN_REG)
- {
- possibly_untraceable = true;
- }
+ if (state->scratch[src1_reg].base != REG_CFA
+ || state->scratch[src1_reg].state != CFI_IN_REG)
+ possibly_untraceable = true;
}
/* Check add/sub/and insn usage when CFA base register is REG_SP.
Any stack size manipulation, including stack realignment is not allowed
if CFA base register is REG_SP. */
- else if (ginsn_get_dst_type (dst) == GINSN_DST_REG
- && ginsn_get_dst_reg (dst) == REG_SP
- && (((ginsn->type == GINSN_TYPE_ADD || ginsn->type == GINSN_TYPE_SUB)
- && ginsn_get_src_type (src2) != GINSN_SRC_IMM)
- || ginsn->type == GINSN_TYPE_AND
- || ginsn->type == GINSN_TYPE_OTHER))
+ else if (dst_type == GINSN_DST_REG && dst_reg == REG_SP
+ && (((gtype == GINSN_TYPE_ADD || gtype == GINSN_TYPE_SUB)
+ && src2_type != GINSN_SRC_IMM)
+ || gtype == GINSN_TYPE_AND || gtype == GINSN_TYPE_OTHER))
possibly_untraceable = true;
/* If a register save operation is seen when REG_SP is untraceable,
CFI cannot be synthesized for register saves, hence bail out. */
/* If, however, the register save is an REG_FP-based, indirect mov
like: mov reg, disp(%rbp) and CFA base register is REG_BP,
untraceable REG_SP is not a problem. */
- if (ginsn->type == GINSN_TYPE_MOV
- && ginsn_get_dst_type (dst) == GINSN_DST_INDIRECT
- && (ginsn_get_dst_reg (dst) == REG_FP
- && state->regs[REG_CFA].base == REG_FP))
+ if (gtype == GINSN_TYPE_MOV && state->regs[REG_CFA].base == REG_FP
+ && dst_type == GINSN_DST_INDIRECT && dst_reg == REG_FP)
sp_untraceable_p = 0;
}
else if (ginsn_scfi_restore_reg_p (ginsn, state) && !state->traceable_p)
{
- if (ginsn->type == GINSN_TYPE_MOV
- && ginsn_get_dst_type (dst) == GINSN_DST_INDIRECT
- && (ginsn_get_src_reg (src1) == REG_SP
- || (ginsn_get_src_reg (src1) == REG_FP
- && state->regs[REG_CFA].base != REG_FP)))
+ if (gtype == GINSN_TYPE_MOV && dst_type == GINSN_DST_INDIRECT
+ && (src1_reg == REG_SP
+ || (src1_reg == REG_FP && state->regs[REG_CFA].base != REG_FP)))
sp_untraceable_p = 1;
}
struct ginsn_src *src1;
struct ginsn_src *src2;
struct ginsn_dst *dst;
+ unsigned int src1_reg;
+ unsigned int dst_reg;
+ enum ginsn_src_type src1_type;
+ enum ginsn_src_type src2_type;
+ enum ginsn_dst_type dst_type;
if (!ginsn || !state)
ret = 1;
src2 = ginsn_get_src2 (ginsn);
dst = ginsn_get_dst (ginsn);
+ src1_reg = ginsn_get_src_reg (src1);
+ dst_reg = ginsn_get_dst_reg (dst);
+
+ src1_type = ginsn_get_src_type (src1);
+ src2_type = ginsn_get_src_type (src2);
+ dst_type = ginsn_get_dst_type (dst);
+
ret = verify_heuristic_traceable_stack_manipulation (ginsn, state);
if (ret)
return ret;
if (ret)
return ret;
- switch (ginsn->dst.type)
+ switch (dst_type)
{
case GINSN_DST_REG:
switch (ginsn->type)
{
case GINSN_TYPE_MOV:
- if (ginsn_get_src_type (src1) == GINSN_SRC_REG
- && ginsn_get_src_reg (src1) == REG_SP
- && ginsn_get_dst_reg (dst) == REG_FP
+ if (src1_type == GINSN_SRC_REG && src1_reg == REG_SP
+ && dst_type == GINSN_DST_REG && dst_reg == REG_FP
&& state->regs[REG_CFA].base == REG_SP)
{
/* mov %rsp, %rbp. */
- scfi_op_add_def_cfa_reg (state, ginsn, ginsn_get_dst_reg (dst));
+ scfi_op_add_def_cfa_reg (state, ginsn, dst_reg);
}
- else if (ginsn_get_src_type (src1) == GINSN_SRC_REG
- && ginsn_get_src_reg (src1) == REG_FP
- && ginsn_get_dst_reg (dst) == REG_SP
+ else if (src1_type == GINSN_SRC_REG && src1_reg == REG_FP
+ && dst_type == GINSN_DST_REG && dst_reg == REG_SP
&& state->regs[REG_CFA].base == REG_FP)
{
/* mov %rbp, %rsp. */
state->stack_size = -state->regs[REG_FP].offset;
- scfi_op_add_def_cfa_reg (state, ginsn, ginsn_get_dst_reg (dst));
+ scfi_op_add_def_cfa_reg (state, ginsn, dst_reg);
state->traceable_p = true;
}
- else if (ginsn_get_src_type (src1) == GINSN_SRC_INDIRECT
- && (ginsn_get_src_reg (src1) == REG_SP
- || ginsn_get_src_reg (src1) == REG_FP)
- && ginsn_track_reg_p (ginsn_get_dst_reg (dst), GINSN_GEN_SCFI))
+ else if (src1_type == GINSN_SRC_INDIRECT
+ && (src1_reg == REG_SP || src1_reg == REG_FP)
+ && ginsn_track_reg_p (dst_reg, GINSN_GEN_SCFI))
{
/* mov disp(%rsp), reg. */
/* mov disp(%rbp), reg. */
if (verify_heuristic_symmetrical_restore_reg (state, ginsn))
{
- scfi_state_restore_reg (state, ginsn_get_dst_reg (dst));
- scfi_op_add_cfa_restore (ginsn, ginsn_get_dst_reg (dst));
+ scfi_state_restore_reg (state, dst_reg);
+ scfi_op_add_cfa_restore (ginsn, dst_reg);
}
else
as_warn_where (ginsn->file, ginsn->line,
_("SCFI: asymetrical register restore"));
}
- else if (ginsn_get_src_type (src1) == GINSN_SRC_REG
- && ginsn_get_dst_type (dst) == GINSN_DST_REG
- && ginsn_get_src_reg (src1) == REG_SP)
+ else if (src1_type == GINSN_SRC_REG && src1_reg == REG_SP
+ && dst_type == GINSN_DST_REG)
{
/* mov %rsp, %reg. */
/* The value of rsp is taken directly from state->stack_size.
IMP: The workflow in gen_scfi_ops must keep it updated.
PS: Not taking the value from state->scratch[REG_SP] is
intentional. */
- state->scratch[ginsn_get_dst_reg (dst)].base = REG_CFA;
- state->scratch[ginsn_get_dst_reg (dst)].offset = -state->stack_size;
- state->scratch[ginsn_get_dst_reg (dst)].state = CFI_IN_REG;
+ state->scratch[dst_reg].base = REG_CFA;
+ state->scratch[dst_reg].offset = -state->stack_size;
+ state->scratch[dst_reg].state = CFI_IN_REG;
}
- else if (ginsn_get_src_type (src1) == GINSN_SRC_REG
- && ginsn_get_dst_type (dst) == GINSN_DST_REG
- && ginsn_get_dst_reg (dst) == REG_SP)
+ else if (src1_type == GINSN_SRC_REG
+ && dst_type == GINSN_DST_REG && dst_reg == REG_SP)
{
/* mov %reg, %rsp. */
/* Keep the value of REG_SP updated. */
- if (state->scratch[ginsn_get_src_reg (src1)].state == CFI_IN_REG)
+ if (state->scratch[src1_reg].state == CFI_IN_REG)
{
- state->stack_size = -state->scratch[ginsn_get_src_reg (src1)].offset;
+ state->stack_size = -state->scratch[src1_reg].offset;
state->traceable_p = true;
}
# if 0
}
break;
case GINSN_TYPE_SUB:
- if (ginsn_get_src_reg (src1) == REG_SP
- && ginsn_get_dst_reg (dst) == REG_SP)
+ if (src1_type == GINSN_SRC_REG && src1_reg == REG_SP
+ && dst_type == GINSN_DST_REG && dst_reg == REG_SP
+ && src2_type == GINSN_SRC_IMM)
{
/* Stack inc/dec offset, when generated due to stack push and pop is
target-specific. Use the value encoded in the ginsn. */
}
break;
case GINSN_TYPE_ADD:
- if (ginsn_get_src_reg (src1) == REG_SP
- && ginsn_get_dst_reg (dst) == REG_SP)
+ if (src1_type == GINSN_SRC_REG && src1_reg == REG_SP
+ && dst_type == GINSN_DST_REG && dst_reg == REG_SP
+ && src2_type == GINSN_SRC_IMM)
{
/* Stack inc/dec offset is target-specific. Use the value
encoded in the ginsn. */
scfi_op_add_cfa_offset_inc (state, ginsn, ginsn_get_src_imm (src2));
}
}
- else if (ginsn_get_src_reg (src1) == REG_FP
- && ginsn_get_dst_reg (dst) == REG_SP
+ else if (src1_type == GINSN_SRC_REG && src1_reg == REG_FP
+ && dst_type == GINSN_DST_REG && dst_reg == REG_SP
&& state->regs[REG_CFA].base == REG_FP)
{
/* FIXME - what is this for ? */
break;
case GINSN_TYPE_LOAD:
/* If this is a load from stack. */
- if (ginsn_get_src_type (src1) == GINSN_SRC_INDIRECT
- && (ginsn_get_src_reg (src1) == REG_SP
- || (ginsn_get_src_reg (src1) == REG_FP
- && state->regs[REG_CFA].base == REG_FP)))
+ if (src1_type == GINSN_SRC_INDIRECT
+ && ((src1_reg == REG_FP && state->regs[REG_CFA].base == REG_FP)
+ || src1_reg == REG_SP))
+
{
/* pop %rbp when CFA tracking is REG_FP based. */
- if (ginsn_get_dst_reg (dst) == REG_FP
- && state->regs[REG_CFA].base == REG_FP)
+ if (dst_reg == REG_FP && state->regs[REG_CFA].base == REG_FP)
{
scfi_op_add_def_cfa_reg (state, ginsn, REG_SP);
if (state->regs[REG_CFA].offset != state->stack_size)
scfi_op_add_cfa_offset_inc (state, ginsn,
(state->regs[REG_CFA].offset - state->stack_size));
}
- if (ginsn_track_reg_p (ginsn_get_dst_reg (dst), GINSN_GEN_SCFI))
+ if (ginsn_track_reg_p (dst_reg, GINSN_GEN_SCFI))
{
if (verify_heuristic_symmetrical_restore_reg (state, ginsn))
{
- scfi_state_restore_reg (state, ginsn_get_dst_reg (dst));
- scfi_op_add_cfa_restore (ginsn, ginsn_get_dst_reg (dst));
+ scfi_state_restore_reg (state, dst_reg);
+ scfi_op_add_cfa_restore (ginsn, dst_reg);
}
else
as_warn_where (ginsn->file, ginsn->line,
/* mov reg, disp(%rsp) */
if (ginsn_scfi_save_reg_p (ginsn, state))
{
- if (ginsn_get_dst_reg (dst) == REG_SP)
+ if (dst_reg == REG_SP)
{
/* mov reg, disp(%rsp) */
offset = 0 - state->stack_size + ginsn_get_dst_disp (dst);
- scfi_state_save_reg (state, ginsn_get_src_reg (src1), REG_CFA, offset);
- scfi_op_add_cfi_offset (state, ginsn, ginsn_get_src_reg (src1));
+ scfi_state_save_reg (state, src1_reg, REG_CFA, offset);
+ scfi_op_add_cfi_offset (state, ginsn, src1_reg);
}
- else if (ginsn_get_dst_reg (dst) == REG_FP)
+ else if (dst_reg == REG_FP)
{
gas_assert (state->regs[REG_CFA].base == REG_FP);
/* mov reg, disp(%rbp) */
offset = 0 - state->regs[REG_CFA].offset + ginsn_get_dst_disp (dst);
- scfi_state_save_reg (state, ginsn_get_src_reg (src1), REG_CFA, offset);
- scfi_op_add_cfi_offset (state, ginsn, ginsn_get_src_reg (src1));
+ scfi_state_save_reg (state, src1_reg, REG_CFA, offset);
+ scfi_op_add_cfi_offset (state, ginsn, src1_reg);
}
}
break;