public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: David Malcolm <dmalcolm@redhat.com>
To: Iain Buclaw <ibuclaw@gdcproject.org>,
	gcc-patches <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH 02/14] Add D frontend (GDC) implementation.
Date: Mon, 15 Oct 2018 14:25:00 -0000	[thread overview]
Message-ID: <1539613141.14521.172.camel@redhat.com> (raw)
In-Reply-To: <CABOHX+c1-je7h4sABuyfYzEvnKj=Ev0ExEWYYm9WbbpjjoZY7Q@mail.gmail.com>

On Tue, 2018-09-18 at 02:33 +0200, Iain Buclaw wrote:
> This patch adds the D front-end implementation, the only part of the
> compiler that interacts with GCC directly, and being the parts that I
> maintain, is something that I can talk about more directly.
> 
> For the actual code generation pass, that converts the front-end AST
> to GCC trees, most parts use a separate Visitor interfaces to do a
> certain kind of lowering, for instance, types.cc builds *_TYPE trees
> from AST Type's.  The Visitor class is part of the DMD front-end, and
> is defined in dfrontend/visitor.h.
> 
> There are also a few interfaces which have their headers in the DMD
> frontend, but are implemented here because they do something that
> requires knowledge of the GCC backend (d-target.cc), does something
> that may not be portable, or differ between D compilers
> (d-frontend.cc) or are a thin wrapper around something that is
> managed
> by GCC (d-diagnostic.cc).
> 
> Many high level operations result in generation of calls to D runtime
> library functions (runtime.def), all with require some kind of
> runtime
> type information (typeinfo.cc).  The compiler also generates
> functions
> for registering/deregistering compiled modules with the D runtime
> library (modules.cc).
> 
> As well as the D language having it's own built-in functions
> (intrinsics.cc), we also expose GCC builtins to D code via a
> `gcc.builtins' module (d-builtins.cc), and give special treatment to
> a
> number of UDAs that could be applied to functions (d-attribs.cc).
> 
> 
> That is roughly the high level jist of how things are currently
> organized.
> 
> ftp://ftp.gdcproject.org/patches/v4/02-v4-d-frontend-gdc.patch

Hi Iain.  I took at look at this patch, focusing on the diagnostics
side of things.

These are more suggestions than hard review blockers.

diff --git a/gcc/d/d-attribs.c b/gcc/d/d-attribs.c
new file mode 100644
index 00000000000..6c65b8cad9e
--- /dev/null
+++ b/gcc/d/d-attribs.c

I believe all new C++ source files are meant to be .cc, rather than .c,
so this should be d-attribs.cc, rather that d-attribs.c.

[...snip...]

diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
new file mode 100644
index 00000000000..c698890ba07
--- /dev/null
+++ b/gcc/d/d-codegen.cc

[...snip...]

+/* Return the GCC location for the D frontend location LOC.   */
+
+location_t
+get_linemap (const Loc& loc)
+{

I don't like the name "get_linemap", as it suggests to me that it's
getting the "struct line_map *" for LOC, rather than a location_t.

How about "get_location_t" instead, or "make_location_t"?  The latter
feels more appropriate, as it's doing non-trivial work.

+  location_t gcc_location = input_location;
+
+  if (loc.filename)
+    {
+      linemap_add (line_table, LC_ENTER, 0, loc.filename, loc.linnum);
+      linemap_line_start (line_table, loc.linnum, 0);
+      gcc_location = linemap_position_for_column (line_table, loc.charnum);
+      linemap_add (line_table, LC_LEAVE, 0, NULL, 0);
+    }
+
+  return gcc_location;
+}

[...snip...]

diff --git a/gcc/d/d-diagnostic.cc b/gcc/d/d-diagnostic.cc
new file mode 100644
index 00000000000..8b8a21e31b6
--- /dev/null
+++ b/gcc/d/d-diagnostic.cc
@@ -0,0 +1,347 @@
+/* d-diagnostics.cc -- D frontend interface to gcc diagnostics.
+   Copyright (C) 2017-2018 Free Software Foundation, Inc.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+
+#include "dmd/globals.h"
+#include "dmd/errors.h"
+
+#include "tree.h"
+#include "options.h"
+#include "diagnostic.h"
+
+#include "d-tree.h"
+
+
+/* Rewrite the format string FORMAT to deal with any format extensions not
+   supported by pp_format().  The result should be freed by the caller.  */
+static char *
+expand_format (const char *format)

Am I right in thinking this is to handle FORMAT strings coming from the
upstream D frontend, and this has its own formatting conventions?
Please can the leading comment have example(s) of the format, and what
it becomes (e.g. the backticks thing).

Maybe adopt a naming convention in the file, to distinguish d format
strings from pp format strings?  Maybe "d_format" vs "gcc_format"
?(though given the verbatim vs !verbatim below, am not sure how
feasible that is).

Maybe rename this function to expand_d_format??

(Might be nice to add some unittesting of this function via "selftest",
but that's definitely not a requirement; it's awkward to add right now)

+{
+  OutBuffer buf;
+  bool inbacktick = false;
+
+  for (const char *p = format; *p; )
+    {
+      while (*p != '\0' && *p != '%' && *p != '`')
+	{
+	  buf.writeByte (*p);
+	  p++;
+	}
+
+      if (*p == '\0')
+	break;
+
+      if (*p == '`')
+	{
+	  /* Text enclosed by `...` are translated as a quoted string.  */
+	  if (inbacktick)
+	    {
+	      buf.writestring ("%>");
+	      inbacktick = false;
+	    }
+	  else
+	    {
+	      buf.writestring ("%<");
+	      inbacktick = true;
+	    }
+	  p++;
+	  continue;
+	}
+
+      /* Check the conversion specification for unhandled flags.  */
+      buf.writeByte (*p);
+      p++;
+
+    Lagain:
+      switch (*p)
+	{
+	case '\0':
+	  /* Malformed format string.  */
+	  gcc_unreachable ();
+
+	case '-':
+	  /* Remove whitespace formatting. */
+	  p++;
+	  while (ISDIGIT (*p))
+	    p++;
+	  goto Lagain;
+
+	case '0':
+	  /* Remove zero padding from format string.  */
+	  while (ISDIGIT (*p))
+	    p++;
+	  goto Lagain;
+
+	case 'X':
+	  /* Hex format only supports lower-case.  */
+	  buf.writeByte ('x');
+	  p++;
+	  break;
+
+	default:
+	  break;
+	}
+    }
+
+  gcc_assert (!inbacktick);
+  return buf.extractString ();
+}
+
+/* Helper routine for all error routines.  Reports a diagnostic specified by
+   KIND at the explicit location LOC, where the message FORMAT has not yet
+   been translated by the gcc diagnostic routines.  */
+
+static void ATTRIBUTE_GCC_DIAG(3,0)
+d_diagnostic_report_diagnostic (const Loc& loc, int opt, const char *format,
+				va_list ap, diagnostic_t kind, bool verbatim)

Given the call to expand_format for the !verbatim case, it seems that
ATTRIBUTE_GCC_DIAG isn't necessarily quite right here, as FORMAT would
then be a D format string.  But it's probably close enough for now.

+{
+  va_list argp;
+  va_copy (argp, ap);
+
+  if (loc.filename || !verbatim)
+    {
+      rich_location rich_loc (line_table, get_linemap (loc));
+      diagnostic_info diagnostic;
+      char *xformat = expand_format (format);
+
+      diagnostic_set_info (&diagnostic, xformat, &argp, &rich_loc, kind);
+      if (opt != 0)
+	diagnostic.option_index = opt;
+
+      diagnostic_report_diagnostic (global_dc, &diagnostic);
+      free (xformat);
+    }
+  else
+    {
+      /* Write verbatim messages with no location direct to stream.  */
+      text_info text;
+      text.err_no = errno;
+      text.args_ptr = &argp;
+      text.format_spec = expand_format (format);
+      text.x_data = NULL;
+
+      pp_format_verbatim (global_dc->printer, &text);
+      pp_newline_and_flush (global_dc->printer);
+    }
+
+  va_end (argp);
+}
+
+/* Print a hard error message with explicit location LOC, increasing the
+   global or gagged error count.  */
+
+void ATTRIBUTE_GCC_DIAG(2,3)
+error (const Loc& loc, const char *format, ...)
+{
+  va_list ap;
+  va_start (ap, format);
+  verror (loc, format, ap);
+  va_end (ap);
+}
+
+void ATTRIBUTE_GCC_DIAG(2,0)
+verror (const Loc& loc, const char *format, va_list ap,
+	const char *p1, const char *p2, const char *)

This one needs a leading comment: what's the deal with P1 and P2?

+{
+  if (!global.gag || global.params.showGaggedErrors)
+    {
+      char *xformat;
+
+      /* Build string and emit.  */
+      if (p2 != NULL)
+	xformat = xasprintf ("%s %s %s", p1, p2, format);
+      else if (p1 != NULL)
+	xformat = xasprintf ("%s %s", p1, format);
+      else
+	xformat = xasprintf ("%s", format);
+
+      d_diagnostic_report_diagnostic (loc, 0, xformat, ap,
+				      global.gag ? DK_ANACHRONISM : DK_ERROR,
+				      false);
+      free (xformat);
+    }
+
+  if (global.gag)
+    global.gaggedErrors++;
+
+  global.errors++;
+}
+
+/* Print supplementary message about the last error with explicit location LOC.
+   This doesn't increase the global error count.  */
+
+void ATTRIBUTE_GCC_DIAG(2,3)
+errorSupplemental (const Loc& loc, const char *format, ...)
+{
+  va_list ap;
+  va_start (ap, format);
+  verrorSupplemental (loc, format, ap);
+  va_end (ap);
+}
+
+void ATTRIBUTE_GCC_DIAG(2,0)
+verrorSupplemental (const Loc& loc, const char *format, va_list ap)
+{
+  if (global.gag && !global.params.showGaggedErrors)
+    return;
+
+  d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, false);
+}
+
+/* Print a warning message with explicit location LOC, increasing the
+   global warning count.  */
+
+void ATTRIBUTE_GCC_DIAG(2,3)
+warning (const Loc& loc, const char *format, ...)
+{
+  va_list ap;
+  va_start (ap, format);
+  vwarning (loc, format, ap);
+  va_end (ap);
+}
+
+void ATTRIBUTE_GCC_DIAG(2,0)
+vwarning (const Loc& loc, const char *format, va_list ap)
+{
+  if (global.params.warnings && !global.gag)
+    {
+      /* Warnings don't count if gagged.  */
+      if (global.params.warnings == 1)

What's the magic "1" value above?  Can it be an enum?  (or is this
something from the upstream parsing code?)

+	global.warnings++;
+
+      d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_WARNING, false);
+    }
+}
+
+/* Print supplementary message about the last warning with explicit location
+   LOC.  This doesn't increase the global warning count.  */
+
+void ATTRIBUTE_GCC_DIAG(2,3)
+warningSupplemental (const Loc& loc, const char *format, ...)
+{
+  va_list ap;
+  va_start (ap, format);
+  vwarningSupplemental (loc, format, ap);
+  va_end (ap);
+}
+
+void ATTRIBUTE_GCC_DIAG(2,0)
+vwarningSupplemental (const Loc& loc, const char *format, va_list ap)
+{
+  if (!global.params.warnings || global.gag)
+    return;
+
+  d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, false);
+}
+
+/* Print a deprecation message with explicit location LOC, increasing the
+   global warning or error count depending on how deprecations are treated.  */
+
+void ATTRIBUTE_GCC_DIAG(2,3)
+deprecation (const Loc& loc, const char *format, ...)
+{
+  va_list ap;
+  va_start (ap, format);
+  vdeprecation (loc, format, ap);
+  va_end (ap);
+}
+
+void ATTRIBUTE_GCC_DIAG(2,0)
+vdeprecation (const Loc& loc, const char *format, va_list ap,
+	      const char *p1, const char *p2)
+{

Again: please can this have a leading comment explaining P1 and P2.

+  if (global.params.useDeprecated == 0)
+    verror (loc, format, ap, p1, p2);
+  else if (global.params.useDeprecated == 2 && !global.gag)

Can these "0" and "2" values be enums?

+    {
+      char *xformat;
+
+      /* Build string and emit.  */
+      if (p2 != NULL)
+	xformat = xasprintf ("%s %s %s", p1, p2, format);
+      else if (p1 != NULL)
+	xformat = xasprintf ("%s %s", p1, format);
+      else
+	xformat = xasprintf ("%s", format);
+
+      d_diagnostic_report_diagnostic (loc, OPT_Wdeprecated, xformat, ap,
+				      DK_WARNING, false);
+      free (xformat);
+    }
+}
+
+/* Print supplementary message about the last deprecation with explicit
+   location LOC.  This does not increase the global error count.  */
+
+void ATTRIBUTE_GCC_DIAG(2,3)
+deprecationSupplemental (const Loc& loc, const char *format, ...)
+{
+  va_list ap;
+  va_start (ap, format);
+  vdeprecationSupplemental (loc, format, ap);
+  va_end (ap);
+}
+
+void ATTRIBUTE_GCC_DIAG(2,0)
+vdeprecationSupplemental (const Loc& loc, const char *format, va_list ap)
+{
+  if (global.params.useDeprecated == 0)
+    verrorSupplemental (loc, format, ap);
+  else if (global.params.useDeprecated == 2 && !global.gag)
+    d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, false);

As before for the "0" and "2".

+}
+
+/* Print a verbose message with explicit location LOC.  */
+
+void ATTRIBUTE_GCC_DIAG(2, 3)
+message (const Loc& loc, const char *format, ...)
+{
+  va_list ap;
+  va_start (ap, format);
+  vmessage (loc, format, ap);
+  va_end (ap);
+}
+
+void ATTRIBUTE_GCC_DIAG(2,0)
+vmessage(const Loc& loc, const char *format, va_list ap)
+{
+  d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, true);
+}
+
+/* Same as above, but doesn't take a location argument.  */
+
+void ATTRIBUTE_GCC_DIAG(1, 2)
+message (const char *format, ...)
+{
+  va_list ap;
+  va_start (ap, format);
+  vmessage (Loc (), format, ap);
+  va_end (ap);
+}
+
+/* Call this after printing out fatal error messages to clean up and
+   exit the compiler.  */
+
+void
+fatal (void)
+{
+  exit (FATAL_EXIT_CODE);
+}
[...snip...]

diff --git a/gcc/d/d-spec.c b/gcc/d/d-spec.c
new file mode 100644
index 00000000000..6a68ebbcf24
--- /dev/null
+++ b/gcc/d/d-spec.c

As above, this new C++ file should be .cc, rather than .c.

[...snip...]

Hope this is constructive
Dave

  parent reply	other threads:[~2018-10-15 14:19 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-18  0:34 Iain Buclaw
2018-09-19 20:06 ` Iain Buclaw
2018-10-14 19:28   ` Richard Sandiford
2018-10-15  7:36     ` Iain Buclaw
2018-10-20 10:51       ` Richard Sandiford
2018-10-20 15:53         ` Iain Buclaw
2018-10-20 22:57         ` Iain Buclaw
2018-10-22  1:13         ` Iain Buclaw
2018-10-23 14:47           ` Richard Sandiford
2018-10-23 19:49             ` Iain Buclaw
2018-10-25 14:12               ` Is the D frontend good to go? (was Re: [PATCH 02/14] Add D frontend (GDC) implementation.) David Malcolm
2018-10-25 15:01                 ` Iain Buclaw
2018-10-26 10:07                   ` Richard Biener
2018-10-28 23:55                     ` Iain Buclaw
2018-10-16 11:14   ` [PATCH 02/14] Add D frontend (GDC) implementation Richard Sandiford
2018-10-16 11:39     ` Richard Sandiford
2018-10-21  0:02     ` Iain Buclaw
2018-10-15 14:25 ` David Malcolm [this message]
2018-10-15 16:46   ` Iain Buclaw

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1539613141.14521.172.camel@redhat.com \
    --to=dmalcolm@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=ibuclaw@gdcproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).