/* Convert RTL to assembler code and output it, for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of GCC.
#include "timevar.h"
#include "cgraph.h"
#include "coverage.h"
+#include "vecprim.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h" /* Needed for external data
static int *insn_lengths;
-varray_type insn_addresses_;
+VEC(int,heap) *insn_addresses_;
/* Max uid for which the above arrays are valid. */
static int insn_lengths_max_uid;
if (GET_CODE (body) == ASM_INPUT)
template = XSTR (body, 0);
else
- template = decode_asm_operands (body, NULL, NULL, NULL, NULL);
+ template = decode_asm_operands (body, NULL, NULL, NULL, NULL, NULL);
for (; *template; template++)
if (IS_ASM_LOGICAL_LINE_SEPARATOR (*template) || *template == '\n')
last_ignored_compare = 0;
-#ifdef SDB_DEBUGGING_INFO
- /* When producing SDB debugging info, delete troublesome line number
- notes from inlined functions in other files as well as duplicate
- line number notes. */
- if (write_symbols == SDB_DEBUG)
- {
- rtx last = 0;
- for (insn = first; insn; insn = NEXT_INSN (insn))
- if (NOTE_P (insn) && NOTE_LINE_NUMBER (insn) > 0)
- {
- if (last != 0
-#ifdef USE_MAPPED_LOCATION
- && NOTE_SOURCE_LOCATION (insn) == NOTE_SOURCE_LOCATION (last)
-#else
- && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last)
- && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last)
-#endif
- )
- {
- delete_insn (insn); /* Use delete_note. */
- continue;
- }
- last = insn;
- }
- }
-#endif
-
for (insn = first; insn; insn = NEXT_INSN (insn))
{
if (INSN_UID (insn) > max_uid) /* Find largest UID. */
switch (GET_CODE (insn))
{
case NOTE:
- switch (NOTE_LINE_NUMBER (insn))
+ switch (NOTE_KIND (insn))
{
case NOTE_INSN_DELETED:
- case NOTE_INSN_FUNCTION_END:
break;
case NOTE_INSN_SWITCH_TEXT_SECTIONS:
(*debug_hooks->var_location) (insn);
break;
- case 0:
- break;
-
default:
- gcc_assert (NOTE_LINE_NUMBER (insn) > 0);
+ gcc_unreachable ();
break;
}
break;
if (string[0])
{
+ location_t loc;
+
if (! app_on)
{
fputs (ASM_APP_ON, file);
app_on = 1;
}
+#ifdef USE_MAPPED_LOCATION
+ loc = ASM_INPUT_SOURCE_LOCATION (body);
+#else
+ loc.file = ASM_INPUT_SOURCE_FILE (body);
+ loc.line = ASM_INPUT_SOURCE_LINE (body);
+#endif
+ if (*loc.file && loc.line)
+ fprintf (asm_out_file, "%s %i \"%s\" 1\n",
+ ASM_COMMENT_START, loc.line, loc.file);
fprintf (asm_out_file, "\t%s\n", string);
+#if HAVE_AS_LINE_ZERO
+ if (*loc.file && loc.line)
+ fprintf (asm_out_file, "%s 0 \"\" 2\n", ASM_COMMENT_START);
+#endif
}
break;
}
unsigned int noperands = asm_noperands (body);
rtx *ops = alloca (noperands * sizeof (rtx));
const char *string;
+ location_t loc;
/* There's no telling what that did to the condition codes. */
CC_STATUS_INIT;
/* Get out the operand values. */
- string = decode_asm_operands (body, ops, NULL, NULL, NULL);
+ string = decode_asm_operands (body, ops, NULL, NULL, NULL, &loc);
/* Inhibit dieing on what would otherwise be compiler bugs. */
insn_noperands = noperands;
this_is_asm_operands = insn;
fputs (ASM_APP_ON, file);
app_on = 1;
}
+ if (loc.file && loc.line)
+ fprintf (asm_out_file, "%s %i \"%s\" 1\n",
+ ASM_COMMENT_START, loc.line, loc.file);
output_asm_insn (string, ops);
+#if HAVE_AS_LINE_ZERO
+ if (loc.file && loc.line)
+ fprintf (asm_out_file, "%s 0 \"\" 2\n", ASM_COMMENT_START);
+#endif
}
this_is_asm_operands = 0;
INSN_CODE (insn) = -1;
}
+ /* If this is a conditional trap, maybe modify it if the cc's
+ are in a nonstandard state so that it accomplishes the same
+ thing that it would do straightforwardly if the cc's were
+ set up normally. */
+ if (cc_status.flags != 0
+ && NONJUMP_INSN_P (insn)
+ && GET_CODE (body) == TRAP_IF
+ && COMPARISON_P (TRAP_CONDITION (body))
+ && XEXP (TRAP_CONDITION (body), 0) == cc0_rtx)
+ {
+ /* This function may alter the contents of its argument
+ and clear some of the cc_status.flags bits.
+ It may also return 1 meaning condition now always true
+ or -1 meaning condition now always false
+ or 2 meaning condition nontrivial but altered. */
+ int result = alter_cond (TRAP_CONDITION (body));
+
+ /* If TRAP_CONDITION has become always false, delete the
+ instruction. */
+ if (result == -1)
+ {
+ delete_insn (insn);
+ break;
+ }
+
+ /* If TRAP_CONDITION has become always true, replace
+ TRAP_CONDITION with const_true_rtx. */
+ if (result == 1)
+ TRAP_CONDITION (body) = const_true_rtx;
+
+ /* Rerecognize the instruction if it has changed. */
+ if (result != 0)
+ INSN_CODE (insn) = -1;
+ }
+
+ /* If this is a conditional trap, maybe modify it if the cc's
+ are in a nonstandard state so that it accomplishes the same
+ thing that it would do straightforwardly if the cc's were
+ set up normally. */
+ if (cc_status.flags != 0
+ && NONJUMP_INSN_P (insn)
+ && GET_CODE (body) == TRAP_IF
+ && COMPARISON_P (TRAP_CONDITION (body))
+ && XEXP (TRAP_CONDITION (body), 0) == cc0_rtx)
+ {
+ /* This function may alter the contents of its argument
+ and clear some of the cc_status.flags bits.
+ It may also return 1 meaning condition now always true
+ or -1 meaning condition now always false
+ or 2 meaning condition nontrivial but altered. */
+ int result = alter_cond (TRAP_CONDITION (body));
+
+ /* If TRAP_CONDITION has become always false, delete the
+ instruction. */
+ if (result == -1)
+ {
+ delete_insn (insn);
+ break;
+ }
+
+ /* If TRAP_CONDITION has become always true, replace
+ TRAP_CONDITION with const_true_rtx. */
+ if (result == 1)
+ TRAP_CONDITION (body) = const_true_rtx;
+
+ /* Rerecognize the instruction if it has changed. */
+ if (result != 0)
+ INSN_CODE (insn) = -1;
+ }
+
/* Make same adjustments to instructions that examine the
condition codes without jumping and instructions that
handle conditional moves (if this machine has either one). */
x = XEXP (x, 0);
if (LABEL_P (x)
|| (NOTE_P (x)
- && NOTE_LINE_NUMBER (x) == NOTE_INSN_DELETED_LABEL))
+ && NOTE_KIND (x) == NOTE_INSN_DELETED_LABEL))
ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
else
output_operand_lossage ("'%%l' operand isn't a label");
timevar_push (TV_SYMOUT);
(*debug_hooks->function_decl) (current_function_decl);
timevar_pop (TV_SYMOUT);
+ if (DECL_STATIC_CONSTRUCTOR (current_function_decl)
+ && targetm.have_ctors_dtors)
+ targetm.asm_out.constructor (XEXP (DECL_RTL (current_function_decl), 0),
+ decl_init_priority_lookup
+ (current_function_decl));
+ if (DECL_STATIC_DESTRUCTOR (current_function_decl)
+ && targetm.have_ctors_dtors)
+ targetm.asm_out.destructor (XEXP (DECL_RTL (current_function_decl), 0),
+ decl_fini_priority_lookup
+ (current_function_decl));
return 0;
}