1132718Skan/* RTL specific diagnostic subroutines for GCC
2169689Skan   Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
390075Sobrien   Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
490075Sobrien
590075SobrienThis file is part of GCC.
690075Sobrien
790075SobrienGCC is free software; you can redistribute it and/or modify
890075Sobrienit under the terms of the GNU General Public License as published by
990075Sobrienthe Free Software Foundation; either version 2, or (at your option)
1090075Sobrienany later version.
1190075Sobrien
1290075SobrienGCC is distributed in the hope that it will be useful,
1390075Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of
1490075SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1590075SobrienGNU General Public License for more details.
1690075Sobrien
1790075SobrienYou should have received a copy of the GNU General Public License
1890075Sobrienalong with GCC; see the file COPYING.  If not, write to
19169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor,
20169689SkanBoston, MA 02110-1301, USA.  */
2190075Sobrien
2290075Sobrien#include "config.h"
2390075Sobrien#undef FLOAT /* This is for hpux. They should change hpux.  */
2490075Sobrien#undef FFS  /* Some systems define this in param.h.  */
2590075Sobrien#include "system.h"
26132718Skan#include "coretypes.h"
27132718Skan#include "tm.h"
2890075Sobrien#include "rtl.h"
2990075Sobrien#include "insn-attr.h"
3090075Sobrien#include "insn-config.h"
3190075Sobrien#include "input.h"
3290075Sobrien#include "toplev.h"
3390075Sobrien#include "intl.h"
3490075Sobrien#include "diagnostic.h"
3590075Sobrien
36132718Skanstatic location_t location_for_asm (rtx);
37169689Skanstatic void diagnostic_for_asm (rtx, const char *, va_list *, diagnostic_t) ATTRIBUTE_GCC_DIAG(2,0);
3890075Sobrien
39132718Skan/* Figure the location of the given INSN.  */
40132718Skanstatic location_t
41132718Skanlocation_for_asm (rtx insn)
4290075Sobrien{
4390075Sobrien  rtx body = PATTERN (insn);
4490075Sobrien  rtx asmop;
45132718Skan  location_t loc;
4690075Sobrien
4790075Sobrien  /* Find the (or one of the) ASM_OPERANDS in the insn.  */
4890075Sobrien  if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) == ASM_OPERANDS)
4990075Sobrien    asmop = SET_SRC (body);
5090075Sobrien  else if (GET_CODE (body) == ASM_OPERANDS)
5190075Sobrien    asmop = body;
5290075Sobrien  else if (GET_CODE (body) == PARALLEL
5390075Sobrien	   && GET_CODE (XVECEXP (body, 0, 0)) == SET)
5490075Sobrien    asmop = SET_SRC (XVECEXP (body, 0, 0));
5590075Sobrien  else if (GET_CODE (body) == PARALLEL
5690075Sobrien	   && GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS)
5790075Sobrien    asmop = XVECEXP (body, 0, 0);
5890075Sobrien  else
5990075Sobrien    asmop = NULL;
6090075Sobrien
6190075Sobrien  if (asmop)
62169689Skan#ifdef USE_MAPPED_LOCATION
63169689Skan    loc = ASM_OPERANDS_SOURCE_LOCATION (asmop);
64169689Skan#else
6590075Sobrien    {
66132718Skan      loc.file = ASM_OPERANDS_SOURCE_FILE (asmop);
67132718Skan      loc.line = ASM_OPERANDS_SOURCE_LINE (asmop);
6890075Sobrien    }
69169689Skan#endif
7090075Sobrien  else
71132718Skan    loc = input_location;
72132718Skan  return loc;
7390075Sobrien}
7490075Sobrien
7590075Sobrien/* Report a diagnostic MESSAGE (an errror or a WARNING) at the line number
7690075Sobrien   of the insn INSN.  This is used only when INSN is an `asm' with operands,
7790075Sobrien   and each ASM_OPERANDS records its own source file and line.  */
7890075Sobrienstatic void
79132718Skandiagnostic_for_asm (rtx insn, const char *msg, va_list *args_ptr,
80132718Skan		    diagnostic_t kind)
8190075Sobrien{
82117395Skan  diagnostic_info diagnostic;
8390075Sobrien
84132718Skan  diagnostic_set_info (&diagnostic, msg, args_ptr,
85132718Skan		       location_for_asm (insn), kind);
86117395Skan  report_diagnostic (&diagnostic);
8790075Sobrien}
8890075Sobrien
8990075Sobrienvoid
90169689Skanerror_for_asm (rtx insn, const char *gmsgid, ...)
9190075Sobrien{
92132718Skan  va_list ap;
9390075Sobrien
94169689Skan  va_start (ap, gmsgid);
95169689Skan  diagnostic_for_asm (insn, gmsgid, &ap, DK_ERROR);
96132718Skan  va_end (ap);
9790075Sobrien}
9890075Sobrien
9990075Sobrienvoid
100169689Skanwarning_for_asm (rtx insn, const char *gmsgid, ...)
10190075Sobrien{
102132718Skan  va_list ap;
10390075Sobrien
104169689Skan  va_start (ap, gmsgid);
105169689Skan  diagnostic_for_asm (insn, gmsgid, &ap, DK_WARNING);
106132718Skan  va_end (ap);
10790075Sobrien}
10890075Sobrien
10990075Sobrienvoid
110132718Skan_fatal_insn (const char *msgid, rtx insn, const char *file, int line,
111132718Skan	     const char *function)
11290075Sobrien{
11390075Sobrien  error ("%s", _(msgid));
11490075Sobrien
11590075Sobrien  /* The above incremented error_count, but isn't an error that we want to
11690075Sobrien     count, so reset it here.  */
11790075Sobrien  errorcount--;
11890075Sobrien
11990075Sobrien  debug_rtx (insn);
12090075Sobrien  fancy_abort (file, line, function);
12190075Sobrien}
12290075Sobrien
12390075Sobrienvoid
124132718Skan_fatal_insn_not_found (rtx insn, const char *file, int line,
125132718Skan		       const char *function)
12690075Sobrien{
12790075Sobrien  if (INSN_CODE (insn) < 0)
12890075Sobrien    _fatal_insn ("unrecognizable insn:", insn, file, line, function);
12990075Sobrien  else
13090075Sobrien    _fatal_insn ("insn does not satisfy its constraints:",
13190075Sobrien		insn, file, line, function);
13290075Sobrien}
133