xcoffout.c revision 259065
133965Sjdp/* Output xcoff-format symbol table information from GNU compiler.
233965Sjdp   Copyright (C) 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2002, 2003, 2004
333965Sjdp   Free Software Foundation, Inc.
433965Sjdp
533965SjdpThis file is part of GCC.
633965Sjdp
733965SjdpGCC is free software; you can redistribute it and/or modify it under
833965Sjdpthe terms of the GNU General Public License as published by the Free
933965SjdpSoftware Foundation; either version 2, or (at your option) any later
1033965Sjdpversion.
1133965Sjdp
1233965SjdpGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1333965SjdpWARRANTY; without even the implied warranty of MERCHANTABILITY or
1433965SjdpFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1533965Sjdpfor more details.
1633965Sjdp
1733965SjdpYou should have received a copy of the GNU General Public License
1833965Sjdpalong with GCC; see the file COPYING.  If not, write to the Free
1933965SjdpSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2033965Sjdp02110-1301, USA.  */
2133965Sjdp
2233965Sjdp/* Output xcoff-format symbol table data.  The main functionality is contained
2333965Sjdp   in dbxout.c.  This file implements the sdbout-like parts of the xcoff
2433965Sjdp   interface.  Many functions are very similar to their counterparts in
2533965Sjdp   sdbout.c.  */
2633965Sjdp
2733965Sjdp#include "config.h"
2833965Sjdp#include "system.h"
2933965Sjdp#include "coretypes.h"
3033965Sjdp#include "tm.h"
3133965Sjdp#include "tree.h"
3233965Sjdp#include "rtl.h"
3333965Sjdp#include "flags.h"
3433965Sjdp#include "toplev.h"
3533965Sjdp#include "output.h"
3633965Sjdp#include "ggc.h"
3733965Sjdp#include "target.h"
3833965Sjdp
3933965Sjdp#ifdef XCOFF_DEBUGGING_INFO
4033965Sjdp
4133965Sjdp/* This defines the C_* storage classes.  */
4233965Sjdp#include "xcoff.h"
4333965Sjdp#include "xcoffout.h"
4433965Sjdp#include "dbxout.h"
4533965Sjdp#include "gstab.h"
4633965Sjdp
4733965Sjdp/* Line number of beginning of current function, minus one.
4833965Sjdp   Negative means not in a function or not using xcoff.  */
4933965Sjdp
5033965Sjdpstatic int xcoff_begin_function_line = -1;
5133965Sjdpstatic int xcoff_inlining = 0;
5233965Sjdp
5333965Sjdp/* Name of the current include file.  */
5433965Sjdp
5533965Sjdpconst char *xcoff_current_include_file;
5633965Sjdp
5733965Sjdp/* Name of the current function file.  This is the file the `.bf' is
5833965Sjdp   emitted from.  In case a line is emitted from a different file,
5933965Sjdp   (by including that file of course), then the line number will be
6033965Sjdp   absolute.  */
6133965Sjdp
6233965Sjdpstatic const char *xcoff_current_function_file;
6333965Sjdp
6433965Sjdp/* Names of bss and data sections.  These should be unique names for each
6533965Sjdp   compilation unit.  */
6633965Sjdp
6733965Sjdpchar *xcoff_bss_section_name;
6833965Sjdpchar *xcoff_private_data_section_name;
6933965Sjdpchar *xcoff_read_only_section_name;
7033965Sjdp
7133965Sjdp/* Last source file name mentioned in a NOTE insn.  */
7233965Sjdp
7333965Sjdpconst char *xcoff_lastfile;
7433965Sjdp
7533965Sjdp/* Macro definitions used below.  */
7633965Sjdp
7733965Sjdp#define ABS_OR_RELATIVE_LINENO(LINENO)		\
7833965Sjdp((xcoff_inlining) ? (LINENO) : (LINENO) - xcoff_begin_function_line)
7933965Sjdp
8033965Sjdp/* Output source line numbers via ".line".  */
8133965Sjdp#define ASM_OUTPUT_LINE(FILE,LINENUM)					   \
8233965Sjdp  do									   \
8333965Sjdp    {									   \
8433965Sjdp      if (xcoff_begin_function_line >= 0)				   \
8533965Sjdp	fprintf (FILE, "\t.line\t%d\n", ABS_OR_RELATIVE_LINENO (LINENUM)); \
8633965Sjdp    }									   \
8733965Sjdp  while (0)
8833965Sjdp
8933965Sjdp#define ASM_OUTPUT_LFB(FILE,LINENUM) \
9033965Sjdp{						\
9133965Sjdp  if (xcoff_begin_function_line == -1)		\
9233965Sjdp    {						\
9333965Sjdp      xcoff_begin_function_line = (LINENUM) - 1;\
9433965Sjdp      fprintf (FILE, "\t.bf\t%d\n", (LINENUM));	\
9533965Sjdp    }						\
9633965Sjdp  xcoff_current_function_file			\
9733965Sjdp    = (xcoff_current_include_file		\
9833965Sjdp       ? xcoff_current_include_file : main_input_filename); \
9933965Sjdp}
10033965Sjdp
10133965Sjdp#define ASM_OUTPUT_LFE(FILE,LINENUM)		\
10233965Sjdp  do						\
10333965Sjdp    {						\
10433965Sjdp      fprintf (FILE, "\t.ef\t%d\n", (LINENUM));	\
10533965Sjdp      xcoff_begin_function_line = -1;		\
10633965Sjdp    }						\
10733965Sjdp  while (0)
10833965Sjdp
10933965Sjdp#define ASM_OUTPUT_LBB(FILE,LINENUM,BLOCKNUM) \
11033965Sjdp  fprintf (FILE, "\t.bb\t%d\n", ABS_OR_RELATIVE_LINENO (LINENUM))
11133965Sjdp
11233965Sjdp#define ASM_OUTPUT_LBE(FILE,LINENUM,BLOCKNUM) \
11333965Sjdp  fprintf (FILE, "\t.eb\t%d\n", ABS_OR_RELATIVE_LINENO (LINENUM))
11433965Sjdp
11533965Sjdpstatic void xcoffout_block (tree, int, tree);
11633965Sjdpstatic void xcoffout_source_file (FILE *, const char *, int);
11733965Sjdp
11833965Sjdp/* Support routines for XCOFF debugging info.  */
11933965Sjdp
12033965Sjdpstruct xcoff_type_number
12133965Sjdp{
12233965Sjdp  const char *name;
12333965Sjdp  int number;
12433965Sjdp};
12533965Sjdpstatic const struct xcoff_type_number xcoff_type_numbers[] = {
12633965Sjdp  { "int", -1 },
12733965Sjdp  { "char", -2 },
12833965Sjdp  { "short int", -3 },
12933965Sjdp  { "long int", -4 },  /* fiddled to -31 if 64 bits */
13033965Sjdp  { "unsigned char", -5 },
13133965Sjdp  { "signed char", -6 },
13233965Sjdp  { "short unsigned int", -7 },
13333965Sjdp  { "unsigned int", -8 },
13433965Sjdp  /* No such type "unsigned".  */
13533965Sjdp  { "long unsigned int", -10 }, /* fiddled to -32 if 64 bits */
13633965Sjdp  { "void", -11 },
13733965Sjdp  { "float", -12 },
13833965Sjdp  { "double", -13 },
13933965Sjdp  { "long double", -14 },
14033965Sjdp  /* Pascal and Fortran types run from -15 to -29.  */
14133965Sjdp  { "wchar", -30 },  /* XXX Should be "wchar_t" ? */
14233965Sjdp  { "long long int", -31 },
14333965Sjdp  { "long long unsigned int", -32 },
14433965Sjdp  /* Additional Fortran types run from -33 to -37.  */
14533965Sjdp
14633965Sjdp  /* ??? Should also handle built-in C++ and Obj-C types.  There perhaps
14733965Sjdp     aren't any that C doesn't already have.  */
14833965Sjdp};
14933965Sjdp
15033965Sjdp/* Returns an XCOFF fundamental type number for DECL (assumed to be a
15133965Sjdp   TYPE_DECL), or 0 if dbxout.c should assign a type number normally.  */
15233965Sjdpint
15333965Sjdpxcoff_assign_fundamental_type_number (tree decl)
15433965Sjdp{
15533965Sjdp  const char *name;
15633965Sjdp  size_t i;
15733965Sjdp
15833965Sjdp  /* Do not waste time searching the list for non-intrinsic types.  */
15933965Sjdp  if (DECL_NAME (decl) == 0 || ! DECL_IS_BUILTIN (decl))
16033965Sjdp    return 0;
16133965Sjdp
16233965Sjdp  name = IDENTIFIER_POINTER (DECL_NAME (decl));
16333965Sjdp
16433965Sjdp  /* Linear search, blech, but the list is too small to bother
16533965Sjdp     doing anything else.  */
16633965Sjdp  for (i = 0; i < ARRAY_SIZE (xcoff_type_numbers); i++)
16733965Sjdp    if (!strcmp (xcoff_type_numbers[i].name, name))
16833965Sjdp      goto found;
16933965Sjdp  return 0;
17033965Sjdp
17133965Sjdp found:
17233965Sjdp  /* -4 and -10 should be replaced with -31 and -32, respectively,
17333965Sjdp     when used for a 64-bit type.  */
17433965Sjdp  if (int_size_in_bytes (TREE_TYPE (decl)) == 8)
17533965Sjdp    {
17633965Sjdp      if (xcoff_type_numbers[i].number == -4)
17733965Sjdp	return -31;
17833965Sjdp      if (xcoff_type_numbers[i].number == -10)
17933965Sjdp	return -32;
18033965Sjdp    }
18133965Sjdp  return xcoff_type_numbers[i].number;
18233965Sjdp}
18333965Sjdp
18433965Sjdp/* Print an error message for unrecognized stab codes.  */
18533965Sjdp
18633965Sjdp#define UNKNOWN_STAB(STR)	\
18733965Sjdp  internal_error ("no sclass for %s stab (0x%x)", STR, stab)
18833965Sjdp
18933965Sjdp/* Conversion routine from BSD stabs to AIX storage classes.  */
19033965Sjdp
19133965Sjdpint
19233965Sjdpstab_to_sclass (int stab)
19333965Sjdp{
19433965Sjdp  switch (stab)
19533965Sjdp    {
19633965Sjdp    case N_GSYM:
19733965Sjdp      return C_GSYM;
19833965Sjdp
19933965Sjdp    case N_FNAME:
20033965Sjdp      UNKNOWN_STAB ("N_FNAME");
20133965Sjdp
20233965Sjdp    case N_FUN:
20333965Sjdp      return C_FUN;
20433965Sjdp
20533965Sjdp    case N_STSYM:
20633965Sjdp    case N_LCSYM:
20733965Sjdp      return C_STSYM;
20833965Sjdp
20933965Sjdp    case N_MAIN:
21033965Sjdp      UNKNOWN_STAB ("N_MAIN");
21133965Sjdp
21233965Sjdp    case N_RSYM:
21333965Sjdp      return C_RSYM;
21433965Sjdp
21533965Sjdp    case N_SSYM:
21633965Sjdp      UNKNOWN_STAB ("N_SSYM");
21733965Sjdp
21833965Sjdp    case N_RPSYM:
21933965Sjdp      return C_RPSYM;
22033965Sjdp
22133965Sjdp    case N_PSYM:
22233965Sjdp      return C_PSYM;
22333965Sjdp    case N_LSYM:
22433965Sjdp      return C_LSYM;
22533965Sjdp    case N_DECL:
22633965Sjdp      return C_DECL;
22733965Sjdp    case N_ENTRY:
22833965Sjdp      return C_ENTRY;
22933965Sjdp
23033965Sjdp    case N_SO:
23133965Sjdp      UNKNOWN_STAB ("N_SO");
23233965Sjdp
23333965Sjdp    case N_SOL:
23433965Sjdp      UNKNOWN_STAB ("N_SOL");
23533965Sjdp
23633965Sjdp    case N_SLINE:
23733965Sjdp      UNKNOWN_STAB ("N_SLINE");
23833965Sjdp
23933965Sjdp    case N_DSLINE:
24033965Sjdp      UNKNOWN_STAB ("N_DSLINE");
24133965Sjdp
24233965Sjdp    case N_BSLINE:
24333965Sjdp      UNKNOWN_STAB ("N_BSLINE");
24433965Sjdp
24533965Sjdp    case N_BINCL:
24633965Sjdp      UNKNOWN_STAB ("N_BINCL");
24733965Sjdp
24833965Sjdp    case N_EINCL:
24933965Sjdp      UNKNOWN_STAB ("N_EINCL");
25033965Sjdp
25133965Sjdp    case N_EXCL:
25233965Sjdp      UNKNOWN_STAB ("N_EXCL");
25333965Sjdp
25433965Sjdp    case N_LBRAC:
25533965Sjdp      UNKNOWN_STAB ("N_LBRAC");
25633965Sjdp
25733965Sjdp    case N_RBRAC:
25833965Sjdp      UNKNOWN_STAB ("N_RBRAC");
25933965Sjdp
26033965Sjdp    case N_BCOMM:
26133965Sjdp      return C_BCOMM;
26233965Sjdp    case N_ECOMM:
26333965Sjdp      return C_ECOMM;
26433965Sjdp    case N_ECOML:
26533965Sjdp      return C_ECOML;
26633965Sjdp
26733965Sjdp    case N_LENG:
26833965Sjdp      UNKNOWN_STAB ("N_LENG");
26933965Sjdp
27033965Sjdp    case N_PC:
27133965Sjdp      UNKNOWN_STAB ("N_PC");
27233965Sjdp
27333965Sjdp    case N_M2C:
27433965Sjdp      UNKNOWN_STAB ("N_M2C");
27533965Sjdp
27633965Sjdp    case N_SCOPE:
27733965Sjdp      UNKNOWN_STAB ("N_SCOPE");
27833965Sjdp
27933965Sjdp    case N_CATCH:
28033965Sjdp      UNKNOWN_STAB ("N_CATCH");
28133965Sjdp
28233965Sjdp    case N_OPT:
28333965Sjdp      UNKNOWN_STAB ("N_OPT");
28433965Sjdp
28533965Sjdp    default:
28633965Sjdp      UNKNOWN_STAB ("?");
28733965Sjdp    }
28833965Sjdp}
28933965Sjdp
29033965Sjdp/* Output debugging info to FILE to switch to sourcefile FILENAME.
29133965Sjdp   INLINE_P is true if this is from an inlined function.  */
29233965Sjdp
29333965Sjdpstatic void
29433965Sjdpxcoffout_source_file (FILE *file, const char *filename, int inline_p)
29533965Sjdp{
29633965Sjdp  if (filename
29733965Sjdp      && (xcoff_lastfile == 0 || strcmp (filename, xcoff_lastfile)
29833965Sjdp	  || (inline_p && ! xcoff_inlining)
29933965Sjdp	  || (! inline_p && xcoff_inlining)))
30033965Sjdp    {
30133965Sjdp      if (xcoff_current_include_file)
30233965Sjdp	{
30333965Sjdp	  fprintf (file, "\t.ei\t");
30433965Sjdp	  output_quoted_string (file, xcoff_current_include_file);
30533965Sjdp	  fprintf (file, "\n");
30633965Sjdp	  xcoff_current_include_file = NULL;
30733965Sjdp	}
30833965Sjdp      xcoff_inlining = inline_p;
30933965Sjdp      if (strcmp (main_input_filename, filename) || inline_p)
31033965Sjdp	{
31133965Sjdp	  fprintf (file, "\t.bi\t");
31233965Sjdp	  output_quoted_string (file, filename);
31333965Sjdp	  fprintf (file, "\n");
31433965Sjdp	  xcoff_current_include_file = filename;
31533965Sjdp	}
31633965Sjdp      xcoff_lastfile = filename;
31733965Sjdp    }
31833965Sjdp}
31933965Sjdp
32033965Sjdp/* Output a line number symbol entry for location (FILENAME, LINE).  */
32133965Sjdp
32233965Sjdpvoid
32333965Sjdpxcoffout_source_line (unsigned int line, const char *filename)
32433965Sjdp{
32533965Sjdp  bool inline_p = (strcmp (xcoff_current_function_file, filename) != 0
32633965Sjdp		   || (int) line < xcoff_begin_function_line);
32733965Sjdp
32833965Sjdp  xcoffout_source_file (asm_out_file, filename, inline_p);
32933965Sjdp
33033965Sjdp  ASM_OUTPUT_LINE (asm_out_file, line);
33133965Sjdp}
33233965Sjdp
33333965Sjdp/* Output the symbols defined in block number DO_BLOCK.
33433965Sjdp
33533965Sjdp   This function works by walking the tree structure of blocks,
33633965Sjdp   counting blocks until it finds the desired block.  */
33733965Sjdp
33833965Sjdpstatic int do_block = 0;
33933965Sjdp
34033965Sjdpstatic void
34133965Sjdpxcoffout_block (tree block, int depth, tree args)
34233965Sjdp{
34333965Sjdp  while (block)
34433965Sjdp    {
34533965Sjdp      /* Ignore blocks never expanded or otherwise marked as real.  */
34633965Sjdp      if (TREE_USED (block))
34733965Sjdp	{
34833965Sjdp	  /* When we reach the specified block, output its symbols.  */
34933965Sjdp	  if (BLOCK_NUMBER (block) == do_block)
35033965Sjdp	    {
35133965Sjdp	      /* Output the syms of the block.  */
35233965Sjdp	      if (debug_info_level != DINFO_LEVEL_TERSE || depth == 0)
35333965Sjdp		dbxout_syms (BLOCK_VARS (block));
35433965Sjdp	      if (args)
35533965Sjdp		dbxout_reg_parms (args);
35633965Sjdp
35733965Sjdp	      /* We are now done with the block.  Don't go to inner blocks.  */
35833965Sjdp	      return;
35933965Sjdp	    }
36033965Sjdp	  /* If we are past the specified block, stop the scan.  */
36133965Sjdp	  else if (BLOCK_NUMBER (block) >= do_block)
36233965Sjdp	    return;
36333965Sjdp
36433965Sjdp	  /* Output the subblocks.  */
36533965Sjdp	  xcoffout_block (BLOCK_SUBBLOCKS (block), depth + 1, NULL_TREE);
36633965Sjdp	}
36733965Sjdp      block = BLOCK_CHAIN (block);
36833965Sjdp    }
36933965Sjdp}
37033965Sjdp
37133965Sjdp/* Describe the beginning of an internal block within a function.
37233965Sjdp   Also output descriptions of variables defined in this block.
37333965Sjdp
37433965Sjdp   N is the number of the block, by order of beginning, counting from 1,
37533965Sjdp   and not counting the outermost (function top-level) block.
37633965Sjdp   The blocks match the BLOCKs in DECL_INITIAL (current_function_decl),
37733965Sjdp   if the count starts at 0 for the outermost one.  */
37833965Sjdp
37933965Sjdpvoid
38033965Sjdpxcoffout_begin_block (unsigned int line, unsigned int n)
38133965Sjdp{
38233965Sjdp  tree decl = current_function_decl;
38333965Sjdp
38433965Sjdp  /* The IBM AIX compiler does not emit a .bb for the function level scope,
38533965Sjdp     so we avoid it here also.  */
38633965Sjdp  if (n != 1)
38733965Sjdp    ASM_OUTPUT_LBB (asm_out_file, line, n);
38833965Sjdp
38933965Sjdp  do_block = n;
39033965Sjdp  xcoffout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl));
39133965Sjdp}
39233965Sjdp
39333965Sjdp/* Describe the end line-number of an internal block within a function.  */
39433965Sjdp
39533965Sjdpvoid
39633965Sjdpxcoffout_end_block (unsigned int line, unsigned int n)
39733965Sjdp{
39833965Sjdp  if (n != 1)
39933965Sjdp    ASM_OUTPUT_LBE (asm_out_file, line, n);
40033965Sjdp}
40133965Sjdp
40233965Sjdp/* Called at beginning of function (before prologue).
40333965Sjdp   Declare function as needed for debugging.  */
40433965Sjdp
40533965Sjdpvoid
40633965Sjdpxcoffout_declare_function (FILE *file, tree decl, const char *name)
40733965Sjdp{
40833965Sjdp  size_t len;
40933965Sjdp
41033965Sjdp  if (*name == '*')
41133965Sjdp    name++;
41233965Sjdp  len = strlen (name);
41333965Sjdp  if (name[len - 1] == ']')
41433965Sjdp    {
41533965Sjdp      char *n = alloca (len - 3);
41633965Sjdp      memcpy (n, name, len - 4);
41733965Sjdp      n[len - 4] = '\0';
41833965Sjdp      name = n;
41933965Sjdp    }
42033965Sjdp
42133965Sjdp  /* Any pending .bi or .ei must occur before the .function pseudo op.
42233965Sjdp     Otherwise debuggers will think that the function is in the previous
42333965Sjdp     file and/or at the wrong line number.  */
42433965Sjdp  xcoffout_source_file (file, DECL_SOURCE_FILE (decl), 0);
42533965Sjdp  dbxout_symbol (decl, 0);
42633965Sjdp
42733965Sjdp  /* .function NAME, TOP, MAPPING, TYPE, SIZE
42833965Sjdp     16 and 044 are placeholders for backwards compatibility */
42933965Sjdp  fprintf (file, "\t.function .%s,.%s,16,044,FE..%s-.%s\n",
43033965Sjdp	   name, name, name, name);
43133965Sjdp}
43233965Sjdp
43333965Sjdp/* Called at beginning of function body (at start of prologue).
43433965Sjdp   Record the function's starting line number, so we can output
43533965Sjdp   relative line numbers for the other lines.
43633965Sjdp   Record the file name that this function is contained in.  */
43733965Sjdp
43833965Sjdpvoid
43933965Sjdpxcoffout_begin_prologue (unsigned int line,
44033965Sjdp			 const char *file ATTRIBUTE_UNUSED)
44133965Sjdp{
44233965Sjdp  ASM_OUTPUT_LFB (asm_out_file, line);
44333965Sjdp  dbxout_parms (DECL_ARGUMENTS (current_function_decl));
44433965Sjdp
44533965Sjdp  /* Emit the symbols for the outermost BLOCK's variables.  sdbout.c does this
44633965Sjdp     in sdbout_begin_block, but there is no guarantee that there will be any
44733965Sjdp     inner block 1, so we must do it here.  This gives a result similar to
44833965Sjdp     dbxout, so it does make some sense.  */
44933965Sjdp  do_block = BLOCK_NUMBER (DECL_INITIAL (current_function_decl));
45033965Sjdp  xcoffout_block (DECL_INITIAL (current_function_decl), 0,
45133965Sjdp		  DECL_ARGUMENTS (current_function_decl));
45233965Sjdp
45333965Sjdp  ASM_OUTPUT_LINE (asm_out_file, line);
45433965Sjdp}
45533965Sjdp
45633965Sjdp/* Called at end of function (before epilogue).
45733965Sjdp   Describe end of outermost block.  */
45833965Sjdp
45933965Sjdpvoid
46033965Sjdpxcoffout_end_function (unsigned int last_linenum)
46133965Sjdp{
46233965Sjdp  ASM_OUTPUT_LFE (asm_out_file, last_linenum);
46333965Sjdp}
46433965Sjdp
46533965Sjdp/* Output xcoff info for the absolute end of a function.
46633965Sjdp   Called after the epilogue is output.  */
46733965Sjdp
46833965Sjdpvoid
46933965Sjdpxcoffout_end_epilogue (unsigned int line ATTRIBUTE_UNUSED,
47033965Sjdp		       const char *file ATTRIBUTE_UNUSED)
47133965Sjdp{
47233965Sjdp  /* We need to pass the correct function size to .function, otherwise,
47333965Sjdp     the xas assembler can't figure out the correct size for the function
47433965Sjdp     aux entry.  So, we emit a label after the last instruction which can
47533965Sjdp     be used by the .function pseudo op to calculate the function size.  */
47633965Sjdp
47733965Sjdp  const char *fname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
47833965Sjdp  if (*fname == '*')
47933965Sjdp    ++fname;
48033965Sjdp  fprintf (asm_out_file, "FE..");
48133965Sjdp  ASM_OUTPUT_LABEL (asm_out_file, fname);
48233965Sjdp}
48333965Sjdp#endif /* XCOFF_DEBUGGING_INFO */
48433965Sjdp