dwarf2out.c: Added explanation of abbreviations.
authorJeffrey Oldham <oldham@codesourcery.com>
Fri, 2 Feb 2001 06:11:26 +0000 (06:11 +0000)
committerJeffrey D. Oldham <oldham@gcc.gnu.org>
Fri, 2 Feb 2001 06:11:26 +0000 (06:11 +0000)
2001-02-01  Jeffrey Oldham  <oldham@codesourcery.com>

* dwarf2out.c: Added explanation of abbreviations.
(def_cfa_1): Added comments listing DWARF2 instructions.
(cfa_temp_reg): Removed in favor of cfa_temp.
(cfa_temp_value): Removed in favor of cfa_temp.
(cfa_temp): New global variable.
(dwarf2out_frame_debug_expr): Added extensive introductory
comments explaining the function's transformations.  Revised to
use cfa_temp.  Added some rtx checking.  Generalize IOR case.
(dwarf2out_frame_debug): Revised to use cfa_temp.
(output_aranges): Cast as "unsigned" to avoid warning.
* rtl.texi (RTX_FRAME_RELATED_P): Revise entry to emphasize better
explain which instructions must be marked.

From-SVN: r39405

gcc/ChangeLog
gcc/dwarf2out.c
gcc/rtl.texi

index 522c2c5ed8aa99cc1cfae3af126b1d9cd0a3df11..acf5120e56043acac80c55d325a9e751bd665f27 100644 (file)
@@ -1,3 +1,18 @@
+2001-02-01  Jeffrey Oldham  <oldham@codesourcery.com>
+
+       * dwarf2out.c: Added explanation of abbreviations.
+       (def_cfa_1): Added comments listing DWARF2 instructions.
+       (cfa_temp_reg): Removed in favor of cfa_temp.
+       (cfa_temp_value): Removed in favor of cfa_temp.
+       (cfa_temp): New global variable.
+       (dwarf2out_frame_debug_expr): Added extensive introductory
+       comments explaining the function's transformations.  Revised to
+       use cfa_temp.  Added some rtx checking.  Generalize IOR case.
+       (dwarf2out_frame_debug): Revised to use cfa_temp.
+       (output_aranges): Cast as "unsigned" to avoid warning.
+       * rtl.texi (RTX_FRAME_RELATED_P): Revise entry to emphasize better
+       explain which instructions must be marked.
+
 2001-02-01  Richard Henderson  <rth@redhat.com>
 
        * local-alloc.c (update_equiv_regs): Copy INSN_CODE to the
index 0bd968c80774bfb49befb01f888bd1f492b9b8be..04bfdbc8eab0791fa0b6aa8d7a59431a372cf552 100644 (file)
@@ -55,6 +55,24 @@ Boston, MA 02111-1307, USA.  */
 #include "md5.h"
 #include "tm_p.h"
 
+/* DWARF2 Abbreviation Glossary:
+   CFA = Canonical Frame Address
+          stack address identifying a stack call frame; its value is
+          the value of the stack pointer just before the call to the
+          current function
+   CFI = Canonical Frame Instruction
+           information describing entries in a stack call frame, e.g.,
+          CIE and FDE
+   CIE = Common Information Entry
+          information describing information common to one or more FDEs
+   DIE = Debugging Information Entry
+   FDE = Frame Description Entry
+          information describing the stack call frame, in particular,
+          how to restore registers
+
+   DW_CFA_... = DWARF2 CFA call frame instruction
+   DW_TAG_... = DWARF2 DIE tag */
+
 /* Decide whether we want to emit frame unwind information for the current
    translation unit.  */
 
@@ -855,7 +873,7 @@ dwarf2out_def_cfa (label, reg, offset)
   def_cfa_1 (label, &loc);
 }
 
-/* This routine does the actual work. The CFA is now calculated from
+/* This routine does the actual work.  The CFA is now calculated from
    the dw_cfa_location structure.  */
 static void
 def_cfa_1 (label, loc_p)
@@ -879,6 +897,8 @@ def_cfa_1 (label, loc_p)
     {
       if (loc.indirect == 0
          || loc.base_offset == old_cfa.base_offset)
+       /* Nothing changed so no need to issue any call frame
+           instructions.  */
        return;
     }
 
@@ -886,6 +906,9 @@ def_cfa_1 (label, loc_p)
 
   if (loc.reg == old_cfa.reg && !loc.indirect)
     {
+      /* Construct a "DW_CFA_def_cfa_offset <offset>" instruction,
+        indicating the CFA register did not change but the offset
+        did.  */
       cfi->dw_cfi_opc = DW_CFA_def_cfa_offset;
       cfi->dw_cfi_oprnd1.dw_cfi_offset = loc.offset;
     }
@@ -894,6 +917,9 @@ def_cfa_1 (label, loc_p)
   else if (loc.offset == old_cfa.offset && old_cfa.reg != (unsigned long) -1
           && !loc.indirect)
     {
+      /* Construct a "DW_CFA_def_cfa_register <register>" instruction,
+        indicating the CFA register has changed to <register> but the
+        offset has not changed.  */
       cfi->dw_cfi_opc = DW_CFA_def_cfa_register;
       cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg;
     }
@@ -901,12 +927,18 @@ def_cfa_1 (label, loc_p)
 
   else if (loc.indirect == 0)
     {
+      /* Construct a "DW_CFA_def_cfa <register> <offset>" instruction,
+        indicating the CFA register has changed to <register> with
+        the specified offset.  */
       cfi->dw_cfi_opc = DW_CFA_def_cfa;
       cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg;
       cfi->dw_cfi_oprnd2.dw_cfi_offset = loc.offset;
     }
   else
     {
+      /* Construct a DW_CFA_def_cfa_expression instruction to
+        calculate the CFA using a full location expression since no
+        register-offset pair is available.  */
       struct dw_loc_descr_struct *loc_list;
       cfi->dw_cfi_opc = DW_CFA_def_cfa_expression;
       loc_list = build_cfa_loc (&loc);
@@ -1237,15 +1269,132 @@ dwarf2out_stack_adjust (insn)
   dwarf2out_args_size (label, args_size);
 }
 
-/* A temporary register used in adjusting SP or setting up the store_reg.  */
-static unsigned cfa_temp_reg;
-
-/* A temporary value used in adjusting SP or setting up the store_reg.  */
-static long cfa_temp_value;
-
-/* Record call frame debugging information for an expression, which either
-   sets SP or FP (adjusting how we calculate the frame address) or saves a
-   register to the stack.  */
+/* A temporary register holding an integral value used in adjusting SP
+   or setting up the store_reg.  The "offset" field holds the integer
+   value, not an offset.  */
+dw_cfa_location cfa_temp;
+
+/* Record call frame debugging information for an expression EXPR,
+   which either sets SP or FP (adjusting how we calculate the frame
+   address) or saves a register to the stack.  LABEL indicates the
+   address of EXPR.
+
+   This function encodes a state machine mapping rtxes to actions on
+   cfa, cfa_store, and cfa_temp.reg.  We describe these rules so
+   users need not read the source code.
+
+  Invariants / Summaries of Rules
+
+  cfa         current register used to calculate the DWARF2 canonical
+              frame address register and offset
+  cfa_store    register used by prologue code to save things to the stack
+              cfa_store.offset is the offset from the value of
+              cfa_store.reg to the actual CFA
+  cfa_temp     register holding an integral value.  cfa_temp.offset
+              stores the value, which will be used to adjust the
+              stack pointer.
+  Rules  1- 4: Setting a register's value to cfa.reg or an expression
+              with cfa.reg as the first operand changes the cfa.reg and its
+              cfa.offset.
+              (For an unknown reason, Rule 4 does not fully obey the
+              invariant.)
+
+  Rules  6- 9: Set a non-cfa.reg register value to a constant or an
+              expression yielding a constant.  This sets cfa_temp.reg
+              and cfa_temp.offset.
+
+  Rule 5:      Create a new register cfa_store used to save items to the
+              stack.
+
+  Rules 10-13: Save a register to the stack.  Record the location in
+              cfa_store.offset.  Define offset as the difference of
+              the original location and cfa_store's location.
+
+  The Rules
+
+  "{a,b}" indicates a choice of a xor b.
+  "<reg>:cfa.reg" indicates that <reg> must equal cfa.reg.
+
+  Rule 1:
+  (set <reg1> <reg2>:cfa.reg)
+  effects: cfa.reg = <REG1>
+           cfa.offset unchanged
+
+  Rule 2:
+  (set sp ({minus,plus} {sp,fp}:cfa.reg {<const_int>,<reg>:cfa_temp.reg}))
+  effects: cfa.reg = sp if fp used
+          cfa.offset += {+/- <const_int>, cfa_temp.offset} if cfa.reg==sp
+          cfa_store.offset += {+/- <const_int>, cfa_temp.offset}
+            if cfa_store.reg==sp
+
+  Rule 3:
+  (set fp ({minus,plus} <reg>:cfa.reg <const_int>))
+  effects: cfa.reg = fp
+          cfa_offset += +/- <const_int>
+
+  Rule 4:
+  (set <reg1> (plus <reg2>:cfa.reg <const_int>))
+  constraints: <reg1> != fp
+              <reg1> != sp
+  effects: cfa.reg = <reg1>
+  questions: Where is <const_int> used?
+            Should cfa.offset be changed?
+
+  Rule 5:
+  (set <reg1> (plus <reg2>:cfa_temp.reg sp:cfa.reg))
+  constraints: <reg1> != fp
+              <reg1> != sp
+  effects: cfa_store.reg = <reg1>
+          cfa_store.offset = cfa.offset - cfa_temp.offset
+
+  Rule 6:
+  (set <reg> <const_int>)
+  effects: cfa_temp.reg = <reg>
+          cfa_temp.offset = <const_int>
+
+  Rule 7:
+  (set <reg1>:cfa_temp.reg (ior <reg2>:cfa_temp.reg <const_int>))
+  effects: cfa_temp.reg = <reg1>
+          cfa_temp.offset |= <const_int>
+
+  Rule 8:
+  (set <reg> (high <exp>))
+  effects: none
+
+  Rule 9:
+  (set <reg> (lo_sum <exp> <const_int>))
+  effects: cfa_temp.reg = <reg>
+          cfa_temp.offset = <const_int>
+
+  Rule 10:
+  (set (mem (pre_modify sp:cfa_store (???? <reg1> <const_int>))) <reg2>)
+  effects: cfa_store.offset -= <const_int>
+          cfa.offset = cfa_store.offset if cfa.reg == sp
+          offset = -cfa_store.offset
+          cfa.reg = sp
+          cfa.base_offset = offset
+
+  Rule 11:
+  (set (mem ({pre_inc,pre_dec} sp:cfa_store.reg)) <reg>)
+  effects: cfa_store.offset += -/+ mode_size(mem)
+          cfa.offset = cfa_store.offset if cfa.reg == sp
+          offset = -cfa_store.offset
+          cfa.reg = sp
+          cfa.base_offset = offset
+
+  Rule 12:
+  (set (mem ({minus,plus} <reg1>:cfa_store <const_int>)) <reg2>)
+  effects: cfa_store.offset += -/+ <const_int>
+          offset = -cfa_store.offset
+          cfa.reg = <reg1
+          cfa.base_offset = offset
+
+  Rule 13:
+  (set (mem <reg1>:cfa_store) <reg2>)
+  effects: offset = -cfa_store.offset
+          cfa.reg = <reg1>
+          cfa.base_offset = offset */
 
 static void
 dwarf2out_frame_debug_expr (expr, label)
@@ -1257,7 +1406,7 @@ dwarf2out_frame_debug_expr (expr, label)
 
   /* If RTX_FRAME_RELATED_P is set on a PARALLEL, process each member of
      the PARALLEL independently. The first element is always processed if
-     it is a SET. This is for backward compatability.   Other elements
+     it is a SET. This is for backward compatibility.   Other elements
      are processed only if they are SETs and the RTX_FRAME_RELATED_P
      flag is set in them.  */
 
@@ -1287,6 +1436,7 @@ dwarf2out_frame_debug_expr (expr, label)
   switch (GET_CODE (dest))
     {
     case REG:
+      /* Rule 1 */
       /* Update the CFA rule wrt SP or FP.  Make sure src is
          relative to the current CFA register.  */
       switch (GET_CODE (src))
@@ -1310,6 +1460,7 @@ dwarf2out_frame_debug_expr (expr, label)
        case MINUS:
          if (dest == stack_pointer_rtx)
            {
+             /* Rule 2 */
              /* Adjusting SP.  */
              switch (GET_CODE (XEXP (src, 1)))
                {
@@ -1317,9 +1468,9 @@ dwarf2out_frame_debug_expr (expr, label)
                  offset = INTVAL (XEXP (src, 1));
                  break;
                case REG:
-                 if ((unsigned) REGNO (XEXP (src, 1)) != cfa_temp_reg)
+                 if ((unsigned) REGNO (XEXP (src, 1)) != cfa_temp.reg)
                    abort ();
-                 offset = cfa_temp_value;
+                 offset = cfa_temp.offset;
                  break;
                default:
                  abort ();
@@ -1344,6 +1495,7 @@ dwarf2out_frame_debug_expr (expr, label)
            }
          else if (dest == hard_frame_pointer_rtx)
            {
+             /* Rule 3 */
              /* Either setting the FP from an offset of the SP,
                 or adjusting the FP */
              if (! frame_pointer_needed)
@@ -1367,39 +1519,44 @@ dwarf2out_frame_debug_expr (expr, label)
              if (GET_CODE (src) != PLUS)
                abort ();
 
+             /* Rule 4 */
              if (GET_CODE (XEXP (src, 0)) == REG
                  && REGNO (XEXP (src, 0)) == cfa.reg
                  && GET_CODE (XEXP (src, 1)) == CONST_INT)
                /* Setting the FP (or a scratch that will be copied into the FP
                   later on) from SP + const.  */
                cfa.reg = REGNO (dest);
+             /* Rule 5 */
              else
                {
                  if (XEXP (src, 1) != stack_pointer_rtx)
                    abort ();
                  if (GET_CODE (XEXP (src, 0)) != REG
-                     || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp_reg)
+                     || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp.reg)
                    abort ();
                  if (cfa.reg != STACK_POINTER_REGNUM)
                    abort ();
                  cfa_store.reg = REGNO (dest);
-                 cfa_store.offset = cfa.offset - cfa_temp_value;
+                 cfa_store.offset = cfa.offset - cfa_temp.offset;
                }
            }
          break;
 
+         /* Rule 6 */
        case CONST_INT:
-         cfa_temp_reg = REGNO (dest);
-         cfa_temp_value = INTVAL (src);
+         cfa_temp.reg = REGNO (dest);
+         cfa_temp.offset = INTVAL (src);
          break;
 
+         /* Rule 7 */
        case IOR:
          if (GET_CODE (XEXP (src, 0)) != REG
-             || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp_reg
-             || (unsigned) REGNO (dest) != cfa_temp_reg
+             || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp.reg
              || GET_CODE (XEXP (src, 1)) != CONST_INT)
            abort ();
-         cfa_temp_value |= INTVAL (XEXP (src, 1));
+         if ((unsigned) REGNO (dest) != cfa_temp.reg)
+           cfa_temp.reg = REGNO (dest);
+         cfa_temp.offset |= INTVAL (XEXP (src, 1));
          break;
 
        default:
@@ -1410,12 +1567,16 @@ dwarf2out_frame_debug_expr (expr, label)
 
       /* Skip over HIGH, assuming it will be followed by a LO_SUM, which
         will fill in all of the bits.  */
+      /* Rule 8 */
     case HIGH:
       break;
 
+      /* Rule 9 */
     case LO_SUM:
-      cfa_temp_reg = REGNO (dest);
-      cfa_temp_value = INTVAL (XEXP (src, 1));
+      if (GET_CODE (XEXP (src, 1)) != CONST_INT)
+       abort ();
+      cfa_temp.reg = REGNO (dest);
+      cfa_temp.offset = INTVAL (XEXP (src, 1));
       break;
 
     case MEM:
@@ -1426,6 +1587,7 @@ dwarf2out_frame_debug_expr (expr, label)
         CFA register.  */
       switch (GET_CODE (XEXP (dest, 0)))
        {
+         /* Rule 10 */
          /* With a push.  */
        case PRE_MODIFY:
          /* We can't handle variable size modifications.  */
@@ -1442,6 +1604,7 @@ dwarf2out_frame_debug_expr (expr, label)
 
          offset = -cfa_store.offset;
          break;
+         /* Rule 11 */
        case PRE_INC:
        case PRE_DEC:
          offset = GET_MODE_SIZE (GET_MODE (dest));
@@ -1458,9 +1621,12 @@ dwarf2out_frame_debug_expr (expr, label)
          offset = -cfa_store.offset;
          break;
 
+         /* Rule 12 */
          /* With an offset.  */
        case PLUS:
        case MINUS:
+         if (GET_CODE (XEXP (XEXP (dest, 0), 1)) != CONST_INT)
+           abort ();
          offset = INTVAL (XEXP (XEXP (dest, 0), 1));
          if (GET_CODE (XEXP (dest, 0)) == MINUS)
            offset = -offset;
@@ -1470,6 +1636,7 @@ dwarf2out_frame_debug_expr (expr, label)
          offset -= cfa_store.offset;
          break;
 
+         /* Rule 13 */
          /* Without an offset.  */
        case REG:
          if (cfa_store.reg != (unsigned) REGNO (XEXP (dest, 0)))
@@ -1543,8 +1710,8 @@ dwarf2out_frame_debug (insn)
        abort ();
       cfa.reg = STACK_POINTER_REGNUM;
       cfa_store = cfa;
-      cfa_temp_reg = -1;
-      cfa_temp_value = 0;
+      cfa_temp.reg = -1;
+      cfa_temp.offset = 0;
       return;
     }
 
@@ -6356,7 +6523,7 @@ output_aranges ()
       /* Pad using a 2 bytes word so that padding is correct
          for any pointer size.  */
       ASM_OUTPUT_DWARF_DATA2 (asm_out_file, 0);
-      for (i = 2; i < DWARF_ARANGES_PAD_SIZE; i += 2)
+      for (i = 2; i < (unsigned) DWARF_ARANGES_PAD_SIZE; i += 2)
        fprintf (asm_out_file, ",0");
       if (flag_debug_asm)
        fprintf (asm_out_file, "\t%s Pad to %d byte boundary",
index 6ed90f8fe77394ba7842e9d4f86180219eb40c73..f75ffcf1e72bcafc508700cbe9b6aee08fd4736e 100644 (file)
@@ -458,10 +458,29 @@ Stored in the @code{integrated} field and printed as @samp{/i}.
 
 @findex RTX_FRAME_RELATED_P
 @item RTX_FRAME_RELATED_P (@var{x})
-Nonzero in an insn or expression which is part of a function
-prologue and sets the stack pointer, sets the frame pointer, or saves a 
-register. This flag is required for exception handling support
-on targets with RTL prologues.
+Nonzero in an insn or expression which is part of a function prologue
+and sets the stack pointer, sets the frame pointer, or saves a register.
+This flag should also be set on an instruction that sets up a temporary
+register to use in place of the frame pointer.
+
+In particular, on RISC targets where there are limits on the sizes of
+immediate constants, it is sometimes impossible to reach the register
+save area directly from the stack pointer.  In that case, a temporary
+register is used that is near enough to the register save area, and the
+Canonical Frame Address, i.e., DWARF2's logical frame pointer, register
+must (temporarily) be changed to be this temporary register.  So, the
+instruction that sets this temporary register must be marked as
+@code{RTX_FRAME_RELATED_P}.
+
+If the marked instruction is overly complex (defined in terms of what
+@code{dwarf2out_frame_debug_expr} can handle), you will also have to
+create a @code{REG_FRAME_RELATED_EXPR} note and attach it to the
+instruction.  This note should contain a simple expression of the
+computation performed by this instruction, i.e., one that
+@code{dwarf2out_frame_debug_expr} can handle.
+
+This flag is required for exception handling support on targets with RTL
+prologues.
 
 @findex SYMBOL_REF_USED
 @cindex @code{used}, in @code{symbol_ref}