I don't know if there are any CFI experts out there but I am working on
dynamic stack alignment for MIPS. I think I have it working in the 'normal'
case but when I try to do stack unwinding through a routine with an aligned
stack, then I have problems. I was wondering if someone can help me understand
what CFI directives to generate to allow stack unwinding. Using
gcc.dg/cleanup-8.c as an example (because it fails with my stack alignment
code), if I generate code with no dynamic stack alignment (but forcing the
use of the frame pointer), the routine fn2 looks like this on MIPS:
fn2:
.frame $fp,32,$31 # vars= 0, regs= 2/0, args= 16, gp= 8
.mask 0xc000,-4
.fmask 0x,0
.setnoreorder
.setnomacro
lui $2,%hi(null)
addiu $sp,$sp,-32
.cfi_def_cfa_offset 32
lw $2,%lo(null)($2)
sw $fp,24($sp)
.cfi_offset 30, -8
move$fp,$sp
.cfi_def_cfa_register 30
sw $31,28($sp)
.cfi_offset 31, -4
jal abort
sb $0,0($2)
There are .cfi directives when incrementing the stack pointer, saving the
frame pointer, and copying the stack pointer to the frame pointer.
When I generate code to dynamically align the stack my code looks like
this:
fn2:
.frame $fp,32,$31 # vars= 0, regs= 2/0, args= 16, gp= 8
.mask 0xc000,-4
.fmask 0x,0
.setnoreorder
.setnomacro
lui $2,%hi(null)
li $3,-16 # 0xfff0
lw $2,%lo(null)($2)
and $sp,$sp,$3
addiu $sp,$sp,-32
.cfi_def_cfa_offset 32
sw $fp,24($sp)
.cfi_offset 30, -8
move$fp,$sp
.cfi_def_cfa_register 30
sw $31,28($sp)
.cfi_offset 31, -4
jal abort
sb $0,0($2)
The 'and' instruction is where the stack gets aligned and if I remove that
one instruction, everything works. I think I need to put out some new CFI
psuedo-ops to handle this but I am not sure what they should be. I am just
not very familiar with the CFI directives.
I looked at ix86_emit_save_reg_using_mov where there is some special
code for handling the drap register and for saving registers on a
realigned stack but I don't really understand what they are trying
to do.
Any help?
Steve Ellcey
sell...@imgtec.com
P.S. For completeness sake I have attached my current dynamic
alignment changes in case anyone wants to see them.
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 4f9a31d..386c2ce 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -5737,6 +5737,29 @@ expand_stack_alignment (void)
gcc_assert (targetm.calls.get_drap_rtx != NULL);
drap_rtx = targetm.calls.get_drap_rtx ();
+ /* I am not doing this in get_drap_rtx because we are also calling
+ that from expand_function_end in order to get/set the drap_reg
+ and vdrap_reg variables and doing these instructions at that
+ point is not working. */
+
+ if (drap_rtx != NULL_RTX)
+{
+ rtx_insn *insn, *seq;
+
+ start_sequence ();
+ emit_move_insn (crtl->vdrap_reg, crtl->drap_reg);
+ seq = get_insns ();
+ insn = get_last_insn ();
+ end_sequence ();
+ emit_insn_at_entry (seq);
+ if (!optimize)
+{
+ add_reg_note (insn, REG_CFA_SET_VDRAP, crtl->vdrap_reg);
+ RTX_FRAME_RELATED_P (insn) = 1;
+}
+}
+
+
/* stack_realign_drap and drap_rtx must match. */
gcc_assert ((stack_realign_drap != 0) == (drap_rtx != NULL));
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index ce21a0f..b6ab30a 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -746,6 +746,8 @@ static const struct attribute_spec mips_attribute_table[] = {
{ "use_shadow_register_set", 0, 0, false, true, true, NULL, false },
{ "keep_interrupts_masked", 0, 0, false, true, true, NULL, false },
{ "use_debug_exception_return", 0, 0, false, true, true, NULL, false },
+ { "align_stack", 0, 0, true, false, false, NULL, false },
+ { "no_align_stack", 0, 0, true, false, false, NULL, false },
{ NULL, 0, 0, false, false, false, NULL, false }
};
@@ -1528,6 +1530,61 @@ mips_merge_decl_attributes (tree olddecl, tree newdecl)
DECL_ATTRIBUTES (newdecl));
}
+static bool
+mips_cfun_has_msa_p (void)
+{
+ /* For now, for testing, assume all functions use MSA
+ (and thus need alignment). */
+#if 0
+ if (!cfun || !TARGET_MSA)
+return FALSE;
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+{
+ if (MSA_SUPPORTED_MODE_P (GET_MODE (insn)))
+ return TRUE;
+}
+
+ return FALSE;
+#else
+ return TRUE;
+#endif
+}
+
+bool
+mips_align_stack_p (void)
+{
+ bool want_alignment = TARGET_ALIGN_STACK && mips_cfun_has_msa_p ();
+
+ if (current_function_decl)
+{
+ tree attr = DECL_ATTRIBUTES (cu