From: Jeffrey Oldham Date: Fri, 2 Feb 2001 06:11:26 +0000 (+0000) Subject: dwarf2out.c: Added explanation of abbreviations. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=770ca8c6b7e11533426b7a3d89f43f85c7930be2;p=gcc.git dwarf2out.c: Added explanation of abbreviations. 2001-02-01 Jeffrey Oldham * 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 522c2c5ed8a..acf5120e560 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2001-02-01 Jeffrey Oldham + + * 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 * local-alloc.c (update_equiv_regs): Copy INSN_CODE to the diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 0bd968c8077..04bfdbc8eab 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -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 " 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 " instruction, + indicating the CFA register has changed to 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 " instruction, + indicating the CFA register has changed to 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. + ":cfa.reg" indicates that must equal cfa.reg. + + Rule 1: + (set :cfa.reg) + effects: cfa.reg = + cfa.offset unchanged + + Rule 2: + (set sp ({minus,plus} {sp,fp}:cfa.reg {,:cfa_temp.reg})) + effects: cfa.reg = sp if fp used + cfa.offset += {+/- , cfa_temp.offset} if cfa.reg==sp + cfa_store.offset += {+/- , cfa_temp.offset} + if cfa_store.reg==sp + + Rule 3: + (set fp ({minus,plus} :cfa.reg )) + effects: cfa.reg = fp + cfa_offset += +/- + + Rule 4: + (set (plus :cfa.reg )) + constraints: != fp + != sp + effects: cfa.reg = + questions: Where is used? + Should cfa.offset be changed? + + Rule 5: + (set (plus :cfa_temp.reg sp:cfa.reg)) + constraints: != fp + != sp + effects: cfa_store.reg = + cfa_store.offset = cfa.offset - cfa_temp.offset + + Rule 6: + (set ) + effects: cfa_temp.reg = + cfa_temp.offset = + + Rule 7: + (set :cfa_temp.reg (ior :cfa_temp.reg )) + effects: cfa_temp.reg = + cfa_temp.offset |= + + Rule 8: + (set (high )) + effects: none + + Rule 9: + (set (lo_sum )) + effects: cfa_temp.reg = + cfa_temp.offset = + + Rule 10: + (set (mem (pre_modify sp:cfa_store (???? ))) ) + effects: cfa_store.offset -= + 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)) ) + 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} :cfa_store )) ) + effects: cfa_store.offset += -/+ + offset = -cfa_store.offset + cfa.reg = :cfa_store) ) + effects: offset = -cfa_store.offset + cfa.reg = + 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", diff --git a/gcc/rtl.texi b/gcc/rtl.texi index 6ed90f8fe77..f75ffcf1e72 100644 --- a/gcc/rtl.texi +++ b/gcc/rtl.texi @@ -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}