OSDN Git Service

2002-04-02 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index 9b8e4a4..5a00bf4 100644 (file)
@@ -473,8 +473,18 @@ dwarf_cfi_name (cfi_opc)
       return "DW_CFA_def_cfa_register";
     case DW_CFA_def_cfa_offset:
       return "DW_CFA_def_cfa_offset";
+
+    /* DWARF 3 */
     case DW_CFA_def_cfa_expression:
       return "DW_CFA_def_cfa_expression";
+    case DW_CFA_expression:
+      return "DW_CFA_expression";
+    case DW_CFA_offset_extended_sf:
+      return "DW_CFA_offset_extended_sf";
+    case DW_CFA_def_cfa_sf:
+      return "DW_CFA_def_cfa_sf";
+    case DW_CFA_def_cfa_offset_sf:
+      return "DW_CFA_def_cfa_offset_sf";
 
     /* SGI/MIPS specific */
     case DW_CFA_MIPS_advance_loc8:
@@ -768,10 +778,7 @@ reg_save (label, reg, sreg, offset)
 #endif
       offset /= DWARF_CIE_DATA_ALIGNMENT;
       if (offset < 0)
-       {
-         cfi->dw_cfi_opc = DW_CFA_GNU_negative_offset_extended;
-         offset = -offset;
-       }
+       cfi->dw_cfi_opc = DW_CFA_offset_extended_sf;
 
       cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
     }
@@ -943,6 +950,8 @@ stack_adjust_offset (pattern)
        return 0;
 
       offset = INTVAL (XEXP (src, 1));
+      if (code == PLUS)
+       offset = -offset;
     }
   else if (GET_CODE (dest) == MEM)
     {
@@ -950,30 +959,47 @@ stack_adjust_offset (pattern)
       src = XEXP (dest, 0);
       code = GET_CODE (src);
 
-      if ((code != PRE_DEC && code != PRE_INC && code != PRE_MODIFY)
-         || XEXP (src, 0) != stack_pointer_rtx)
-       return 0;
+      switch (code) 
+        {
+       case PRE_MODIFY:
+       case POST_MODIFY:
+         if (XEXP (src, 0) == stack_pointer_rtx)
+           {
+             rtx val = XEXP (XEXP (src, 1), 1);
+             /* We handle only adjustments by constant amount.  */
+             if (GET_CODE (XEXP (src, 1)) != PLUS ||
+                 GET_CODE (val) != CONST_INT)
+               abort();
+             offset = -INTVAL (val);
+             break;
+           }
+         return 0;
 
-      if (code == PRE_MODIFY)
-       {
-         rtx val = XEXP (XEXP (src, 1), 1);
+       case PRE_DEC:
+       case POST_DEC:
+         if (XEXP (src, 0) == stack_pointer_rtx)
+           {
+             offset = GET_MODE_SIZE (GET_MODE (dest));
+             break;
+           }
+         return 0;
 
-         /* We handle only adjustments by constant amount.  */
-         if (GET_CODE (XEXP (src, 1)) != PLUS ||
-             GET_CODE (val) != CONST_INT)
-           abort ();
+       case PRE_INC:
+       case POST_INC:
+         if (XEXP (src, 0) == stack_pointer_rtx)
+           {
+             offset = -GET_MODE_SIZE (GET_MODE (dest));
+             break;
+           }
+         return 0;
 
-         offset = -INTVAL (val);
+       default:
+         return 0;
        }
-      else
-       offset = GET_MODE_SIZE (GET_MODE (dest));
     }
   else
     return 0;
 
-  if (code == PLUS || code == PRE_INC)
-    offset = -offset;
-
   return offset;
 }
 
@@ -1714,13 +1740,19 @@ output_cfi (cfi, fde, for_eh)
          break;
 
        case DW_CFA_offset_extended:
-       case DW_CFA_GNU_negative_offset_extended:
        case DW_CFA_def_cfa:
          dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num,
                                       NULL);
          dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL);
          break;
 
+       case DW_CFA_offset_extended_sf:
+       case DW_CFA_def_cfa_sf:
+         dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num,
+                                      NULL);
+         dw2_asm_output_data_sleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL);
+         break;
+
        case DW_CFA_restore_extended:
        case DW_CFA_undefined:
        case DW_CFA_same_value:
@@ -1741,13 +1773,22 @@ output_cfi (cfi, fde, for_eh)
          dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL);
          break;
 
+       case DW_CFA_def_cfa_offset_sf:
+         dw2_asm_output_data_sleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL);
+         break;
+
        case DW_CFA_GNU_window_save:
          break;
 
        case DW_CFA_def_cfa_expression:
+       case DW_CFA_expression:
          output_cfa_loc (cfi);
          break;
 
+       case DW_CFA_GNU_negative_offset_extended:
+         /* Obsoleted by DW_CFA_offset_extended_sf.  */
+         abort ();
+
        default:
          break;
        }
@@ -2106,7 +2147,7 @@ dwarf2out_end_epilogue ()
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
   /* Output a label to mark the endpoint of the code generated for this
-     function.        */
+     function.  */
   ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL, current_funcdef_number);
   ASM_OUTPUT_LABEL (asm_out_file, label);
   fde = &fde_table[fde_table_in_use - 1];
@@ -3061,7 +3102,7 @@ static void dwarf2out_abstract_function PARAMS ((tree));
 
 /* The debug hooks structure.  */
 
-struct gcc_debug_hooks dwarf2_debug_hooks =
+const struct gcc_debug_hooks dwarf2_debug_hooks =
 {
   dwarf2out_init,
   dwarf2out_finish,
@@ -3212,8 +3253,6 @@ limbo_die_node;
 /* Information concerning the compilation unit's programming
    language, and compiler version.  */
 
-extern int flag_traditional;
-
 /* Fixed size portion of the DWARF compilation unit header.  */
 #define DWARF_COMPILE_UNIT_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 3)
 
@@ -3243,16 +3282,6 @@ extern int flag_traditional;
 #endif
 #endif
 
-/* Define the architecture-dependent minimum instruction length (in bytes).
-   In this implementation of DWARF, this field is used for information
-   purposes only.  Since GCC generates assembly language, we have
-   no a priori knowledge of how many instruction bytes are generated
-   for each source line, and therefore can use only the  DW_LNE_set_address
-   and DW_LNS_fixed_advance_pc line information commands.  */
-#ifndef DWARF_LINE_MIN_INSTR_LENGTH
-#define DWARF_LINE_MIN_INSTR_LENGTH 4
-#endif
-
 /* Minimum line offset in a special line info. opcode.
    This value was chosen to give a reasonable range of values.  */
 #define DWARF_LINE_BASE  -10
@@ -5116,8 +5145,8 @@ equate_decl_number_to_die (decl, decl_die)
      tree decl;
      dw_die_ref decl_die;
 {
-  unsigned decl_id = DECL_UID (decl);
-  unsigned num_allocated;
+  unsigned int decl_id = DECL_UID (decl);
+  unsigned int num_allocated;
 
   if (decl_id >= decl_die_table_allocated)
     {
@@ -6464,16 +6493,16 @@ output_comp_unit (die)
     unmark_dies (die);
 }
 
-/* The DWARF2 pubname for a nested thingy looks like "A::f".  The output
-   of decl_printable_name for C++ looks like "A::f(int)".  Let's drop the
-   argument list, and maybe the scope.  */
+/* The DWARF2 pubname for a nested thingy looks like "A::f".  The
+   output of lang_hooks.decl_printable_name for C++ looks like
+   "A::f(int)".  Let's drop the argument list, and maybe the scope.  */
 
 static const char *
 dwarf2_name (decl, scope)
      tree decl;
      int scope;
 {
-  return (*decl_printable_name) (decl, scope ? 1 : 0);
+  return (*lang_hooks.decl_printable_name) (decl, scope ? 1 : 0);
 }
 
 /* Add a new entry to .debug_pubnames if appropriate.  */
@@ -7009,8 +7038,17 @@ output_line_info ()
   dw2_asm_output_delta (DWARF_OFFSET_SIZE, p2, p1, "Prolog Length");
   ASM_OUTPUT_LABEL (asm_out_file, p1);
 
-  dw2_asm_output_data (1, DWARF_LINE_MIN_INSTR_LENGTH,
+  /* Define the architecture-dependent minimum instruction length (in
+   bytes).  In this implementation of DWARF, this field is used for
+   information purposes only.  Since GCC generates assembly language,
+   we have no a priori knowledge of how many instruction bytes are
+   generated for each source line, and therefore can use only the
+   DW_LNE_set_address and DW_LNS_fixed_advance_pc line information
+   commands.  Accordingly, we fix this as `1', which is "correct
+   enough" for all architectures, and don't let the target override.  */
+  dw2_asm_output_data (1, 1,
                       "Minimum Instruction Length");
+
   dw2_asm_output_data (1, DWARF_LINE_DEFAULT_IS_STMT_START,
                       "Default is_stmt_start flag");
   dw2_asm_output_data (1, DWARF_LINE_BASE,
@@ -7544,7 +7582,12 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
             copy was created to help us keep track of typedef names) and
             that copy might have a different TYPE_UID from the original
             ..._TYPE node.  */
-         mod_type_die = lookup_type_die (type_main_variant (type));
+         if (TREE_CODE (type) != VECTOR_TYPE)
+           mod_type_die = lookup_type_die (type_main_variant (type));
+         else
+           /* Vectors have the debugging information in the type,
+              not the main variant.  */
+           mod_type_die = lookup_type_die (type);
          if (mod_type_die == NULL)
            abort ();
        }
@@ -7779,10 +7822,24 @@ mem_loc_descriptor (rtl, mode)
         by a different symbol.  */
       if (GET_CODE (rtl) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (rtl))
        {
-         rtx tmp = get_pool_constant (rtl);
+         bool marked;
+         rtx tmp = get_pool_constant_mark (rtl, &marked);
 
          if (GET_CODE (tmp) == SYMBOL_REF)
-           rtl = tmp;
+           {
+             rtl = tmp;
+             if (CONSTANT_POOL_ADDRESS_P (tmp))
+               get_pool_constant_mark (tmp, &marked);
+             else
+               marked = true;
+           }
+
+         /* If all references to this pool constant were optimized away,
+            it was not output and thus we can't represent it.
+            FIXME: might try to use DW_OP_const_value here, though
+            DW_OP_piece complicates it.  */
+         if (!marked)
+           return 0;
        }
 
       mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0);
@@ -7973,6 +8030,24 @@ loc_descriptor_from_tree (loc, addressp)
         the names of types.  */
       return 0;
 
+    case CALL_EXPR:
+      return 0;
+
+    case ADDR_EXPR:
+      /* We can support this only if we can look through conversions and
+        find an INDIRECT_EXPR.  */
+      for (loc = TREE_OPERAND (loc, 0);
+          TREE_CODE (loc) == CONVERT_EXPR || TREE_CODE (loc) == NOP_EXPR
+          || TREE_CODE (loc) == NON_LVALUE_EXPR
+          || TREE_CODE (loc) == VIEW_CONVERT_EXPR
+          || TREE_CODE (loc) == SAVE_EXPR;
+          loc = TREE_OPERAND (loc, 0))
+       ;
+
+       return (TREE_CODE (loc) == INDIRECT_REF
+              ? loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp)
+              : 0);
+
     case VAR_DECL:
     case PARM_DECL:
       {
@@ -8066,14 +8141,19 @@ loc_descriptor_from_tree (loc, addressp)
        return 0;
       break;
 
+    case TRUTH_AND_EXPR: 
+    case TRUTH_ANDIF_EXPR:
     case BIT_AND_EXPR:
       op = DW_OP_and;
       goto do_binop;
 
+    case TRUTH_XOR_EXPR:
     case BIT_XOR_EXPR:
       op = DW_OP_xor;
       goto do_binop;
 
+    case TRUTH_OR_EXPR:
+    case TRUTH_ORIF_EXPR:
     case BIT_IOR_EXPR:
       op = DW_OP_or;
       goto do_binop;
@@ -8167,6 +8247,7 @@ loc_descriptor_from_tree (loc, addressp)
       add_loc_descr (&ret, new_loc_descr (op, 0, 0));
       break;
 
+    case TRUTH_NOT_EXPR:
     case BIT_NOT_EXPR:
       op = DW_OP_not;
       goto do_unop;
@@ -8193,7 +8274,7 @@ loc_descriptor_from_tree (loc, addressp)
                          TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)),
                   TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
 
-      /* ... fall through ... */
+      /* ... fall through ...  */
 
     case COND_EXPR:
       {
@@ -8838,8 +8919,38 @@ rtl_for_decl_location (decl)
      and will have been substituted directly into all expressions that use it.
      C does not have such a concept, but C++ and other languages do.  */
   else if (TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl))
-    rtl = expand_expr (DECL_INITIAL (decl), NULL_RTX, VOIDmode,
-                      EXPAND_INITIALIZER);
+    {
+      /* If a variable is initialized with a string constant without embedded
+        zeros, build CONST_STRING.  */
+      if (TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
+         && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+       {
+         tree arrtype = TREE_TYPE (decl);
+         tree enttype = TREE_TYPE (arrtype);
+         tree domain = TYPE_DOMAIN (arrtype);
+         tree init = DECL_INITIAL (decl);
+         enum machine_mode mode = TYPE_MODE (enttype);
+
+         if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE_SIZE (mode) == 1
+             && domain
+             && integer_zerop (TYPE_MIN_VALUE (domain))
+             && compare_tree_int (TYPE_MAX_VALUE (domain),
+                                  TREE_STRING_LENGTH (init) - 1) == 0
+             && ((size_t) TREE_STRING_LENGTH (init)
+                 == strlen (TREE_STRING_POINTER (init)) + 1))
+           rtl = gen_rtx_CONST_STRING (VOIDmode, TREE_STRING_POINTER (init));
+       }
+
+      if (rtl == NULL)
+       {
+         rtl = expand_expr (DECL_INITIAL (decl), NULL_RTX, VOIDmode,
+                            EXPAND_INITIALIZER);
+         /* If expand_expr returned a MEM, we cannot use it, since
+            it won't be output, leading to unresolved symbol.  */
+         if (rtl && GET_CODE (rtl) == MEM)
+           rtl = NULL;
+       }
+    }
 
   return rtl;
 }
@@ -8971,7 +9082,7 @@ add_bound_info (subrange_die, bound_attr, bound)
     case ERROR_MARK:
       return;
 
-    /* All fixed-bounds are represented by INTEGER_CST nodes.        */
+    /* All fixed-bounds are represented by INTEGER_CST nodes.  */
     case INTEGER_CST:
       if (! host_integerp (bound, 0)
          || (bound_attr == DW_AT_lower_bound
@@ -9071,6 +9182,15 @@ add_bound_info (subrange_die, bound_attr, bound)
        else
          ctx = lookup_decl_die (current_function_decl);
 
+       /* If we weren't able to find a context, it's most likely the case
+          that we are processing the return type of the function.  So
+          make a SAVE_EXPR to point to it and have the limbo DIE code
+          find the proper die.  The save_expr function doesn't always
+          make a SAVE_EXPR, so do it ourselves.  */
+       if (ctx == 0)
+         bound = build (SAVE_EXPR, TREE_TYPE (bound), bound,
+                        current_function_decl, NULL_TREE);
+
        decl_die = new_die (DW_TAG_variable, ctx, bound);
        add_AT_flag (decl_die, DW_AT_artificial, 1);
        add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
@@ -10506,6 +10626,20 @@ gen_inlined_subroutine_die (stmt, context_die, depth)
       decls_for_scope (stmt, subr_die, depth);
       current_function_has_inlines = 1;
     }
+  else
+    /* We may get here if we're the outer block of function A that was
+       inlined into function B that was inlined into function C.  When
+       generating debugging info for C, dwarf2out_abstract_function(B)
+       would mark all inlined blocks as abstract, including this one.
+       So, we wouldn't (and shouldn't) expect labels to be generated
+       for this one.  Instead, just emit debugging info for
+       declarations within the block.  This is particularly important
+       in the case of initializers of arguments passed from B to us:
+       if they're statement expressions containing declarations, we
+       wouldn't generate dies for their abstract variables, and then,
+       when generating dies for the real variables, we'd die (pun
+       intended :-)  */
+    gen_lexical_block_die (stmt, context_die, depth);
 }
 
 /* Generate a DIE for a field in a record, or structure.  */
@@ -10639,8 +10773,6 @@ gen_compile_unit_die (filename)
     language = DW_LANG_Pascal83;
   else if (strcmp (language_string, "GNU Java") == 0)
     language = DW_LANG_Java;
-  else if (flag_traditional)
-    language = DW_LANG_C;
   else
     language = DW_LANG_C89;
 
@@ -10829,7 +10961,8 @@ gen_struct_or_union_type_die (type, context_die)
       add_AT_flag (type_die, DW_AT_declaration, 1);
 
       /* We don't need to do this for function-local types.  */
-      if (! decl_function_context (TYPE_STUB_DECL (type)))
+      if (TYPE_STUB_DECL (type)
+         && ! decl_function_context (TYPE_STUB_DECL (type)))
        VARRAY_PUSH_TREE (incomplete_types, type);
     }
 }
@@ -10907,10 +11040,13 @@ gen_type_die (type, context_die)
   if (type == NULL_TREE || type == error_mark_node)
     return;
 
-  /* We are going to output a DIE to represent the unqualified version of
-     this type (i.e. without any const or volatile qualifiers) so get the
-     main variant (i.e. the unqualified version) of this type now.  */
-  type = type_main_variant (type);
+  /* We are going to output a DIE to represent the unqualified version
+     of this type (i.e. without any const or volatile qualifiers) so
+     get the main variant (i.e. the unqualified version) of this type
+     now.  (Vectors are special because the debugging info is in the
+     cloned type itself).  */
+  if (TREE_CODE (type) != VECTOR_TYPE)
+    type = type_main_variant (type);
 
   if (TREE_ASM_WRITTEN (type))
     return;
@@ -11811,13 +11947,6 @@ dwarf2out_define (lineno, buffer)
      unsigned lineno ATTRIBUTE_UNUSED;
      const char *buffer ATTRIBUTE_UNUSED;
 {
-  static int initialized = 0;
-  if (!initialized)
-    {
-      dwarf2out_start_source_file (0, primary_filename);
-      initialized = 1;
-    }
-
   if (debug_info_level >= DINFO_LEVEL_VERBOSE)
     {
       named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
@@ -12006,6 +12135,18 @@ dwarf2out_finish (input_filename)
            add_child_die (origin->die_parent, die);
          else if (die == comp_unit_die)
            ;
+         /* If this was an expression for a bound involved in a function
+            return type, it may be a SAVE_EXPR for which we weren't able
+            to find a DIE previously.  So try now.  */
+         else if (node->created_for
+                  && TREE_CODE (node->created_for) == SAVE_EXPR
+                  && 0 != (origin = (lookup_decl_die
+                                     (SAVE_EXPR_CONTEXT
+                                      (node->created_for)))))
+           add_child_die (origin, die);
+         else if (errorcount > 0 || sorrycount > 0)
+           /* It's OK to be confused by errors in the input.  */
+           add_child_die (comp_unit_die, die);
          else if (node->created_for
                   && ((DECL_P (node->created_for)
                        && (context = DECL_CONTEXT (node->created_for)))
@@ -12023,9 +12164,6 @@ dwarf2out_finish (input_filename)
                abort ();
              add_child_die (origin, die);
            }
-         else if (errorcount > 0 || sorrycount > 0)
-           /* It's OK to be confused by errors in the input.  */
-           add_child_die (comp_unit_die, die);
          else
            abort ();
        }