diff mbox series

[committed] d: Split up d-frontend.cc into multiple parts.

Message ID 20200604162154.27929-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Split up d-frontend.cc into multiple parts. | expand

Commit Message

Iain Buclaw June 4, 2020, 4:21 p.m. UTC
In preparation for possibly switching the front-end implementation from
C++ to D, a lot of changes in the "glue" layer are just noise from lots
of small, but invasive API changes in the DMD front-end headers.

This will be the first of about a dozen or so.  This change splits up
the few implementations in d/d-frontend.cc into separated files.

Regression tested on x86_64-linux-gnu and committed to mainline.

Regards
Iain


gcc/d/ChangeLog:

	* Make-lang.in (D_OBJS): Add d-compiler.o, d-ctfloat.o, d-port.o.
	* d-frontend.cc (Port::memicmp): Move to d-port.cc.
	(Port::strupr): Likewise.
	(Port::isFloat32LiteralOutOfRange): Likewise.
	(Port::isFloat64LiteralOutOfRange): Likewise.
	(Port::readwordLE): Likewise.
	(Port::readwordBE): Likewise.
	(Port::readlongLE): Likewise.
	(Port::readlongBE): Likewise.
	(Port::valcpy): Likewise.
	(CTFloat::fabs): Move to d-ctfloat.cc.
	(CTFloat::ldexp): Likewise.
	(CTFloat::isIdentical): Likewise.
	(CTFloat::isNaN): Likewise.
	(CTFloat::isSNaN): Likewise.
	(CTFloat::isInfinity): Likewise.
	(CTFloat::parse): Likewise.
	(CTFloat::sprint): Likewise.
	(CTFloat::hash): Likewise.
	(Compiler::genCmain): Move to d-compiler.cc.
	(Compiler::paintAsType): Likewise.
	(Compiler::loadModule): Likewise.
	* d-compiler.cc: New file.
	* d-ctfloat.cc: New file.
	* d-port.cc: New file.
---
 gcc/d/Make-lang.in  |  26 ++-
 gcc/d/d-compiler.cc | 182 +++++++++++++++++++
 gcc/d/d-ctfloat.cc  | 143 +++++++++++++++
 gcc/d/d-frontend.cc | 416 --------------------------------------------
 gcc/d/d-port.cc     | 169 ++++++++++++++++++
 5 files changed, 516 insertions(+), 420 deletions(-)
 create mode 100644 gcc/d/d-compiler.cc
 create mode 100644 gcc/d/d-ctfloat.cc
 create mode 100644 gcc/d/d-port.cc
diff mbox series

Patch

diff --git a/gcc/d/Make-lang.in b/gcc/d/Make-lang.in
index ac04d074aa5..6c8c611a0f7 100644
--- a/gcc/d/Make-lang.in
+++ b/gcc/d/Make-lang.in
@@ -133,10 +133,28 @@  D_GENERATED_OBJS = d/id.o d/impcnvtab.o
 
 # Language-specific object files for D.
 D_OBJS = \
-	d/d-attribs.o d/d-builtins.o d/d-codegen.o d/d-convert.o \
-	d/d-diagnostic.o d/d-frontend.o d/d-incpath.o d/d-lang.o \
-	d/d-longdouble.o d/d-target.o d/decl.o d/expr.o d/imports.o \
-	d/intrinsics.o d/modules.o d/runtime.o d/toir.o d/typeinfo.o d/types.o
+	d/d-attribs.o \
+	d/d-builtins.o \
+	d/d-codegen.o \
+	d/d-compiler.o \
+	d/d-convert.o \
+	d/d-ctfloat.o \
+	d/d-diagnostic.o \
+	d/d-frontend.o \
+	d/d-incpath.o \
+	d/d-lang.o \
+	d/d-longdouble.o \
+	d/d-port.o \
+	d/d-target.o \
+	d/decl.o \
+	d/expr.o \
+	d/imports.o \
+	d/intrinsics.o \
+	d/modules.o \
+	d/runtime.o \
+	d/toir.o \
+	d/typeinfo.o \
+	d/types.o
 
 # All language-specific object files for D.
 D_ALL_OBJS = $(D_FRONTEND_OBJS) $(D_GENERATED_OBJS) $(D_OBJS) $(D_TARGET_OBJS)
diff --git a/gcc/d/d-compiler.cc b/gcc/d/d-compiler.cc
new file mode 100644
index 00000000000..a27261fb94e
--- /dev/null
+++ b/gcc/d/d-compiler.cc
@@ -0,0 +1,182 @@ 
+/* d-compiler.cc -- D frontend interface to the gcc back-end.
+   Copyright (C) 2020 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/compiler.h"
+#include "dmd/scope.h"
+#include "dmd/expression.h"
+#include "dmd/identifier.h"
+#include "dmd/module.h"
+#include "dmd/mtype.h"
+
+#include "tree.h"
+#include "fold-const.h"
+
+#include "d-tree.h"
+
+
+/* Implements the Compiler interface used by the frontend.  */
+
+/* Generate C main() in response to seeing D main().  This used to be in
+   libdruntime, but contained a reference to _Dmain which didn't work when
+   druntime was made into a shared library and was linked to a program, such
+   as a C++ program, that didn't have a _Dmain.  */
+
+void
+Compiler::genCmain (Scope *sc)
+{
+  static bool initialized = false;
+
+  if (initialized)
+    return;
+
+  /* The D code to be generated is provided by __entrypoint.di, try to load it,
+     but don't fail if unfound.  */
+  unsigned errors = global.startGagging ();
+  Module *m = Module::load (Loc (), NULL, Identifier::idPool ("__entrypoint"));
+
+  if (global.endGagging (errors))
+    m = NULL;
+
+  if (m != NULL)
+    {
+      m->importedFrom = m;
+      m->importAll (NULL);
+      m->semantic (NULL);
+      m->semantic2 (NULL);
+      m->semantic3 (NULL);
+      d_add_entrypoint_module (m, sc->_module);
+    }
+
+  initialized = true;
+}
+
+/* Perform a reinterpret cast of EXPR to type TYPE for use in CTFE.
+   The front end should have already ensured that EXPR is a constant,
+   so we just lower the value to GCC and return the converted CST.  */
+
+Expression *
+Compiler::paintAsType (UnionExp *, Expression *expr, Type *type)
+{
+  /* We support up to 512-bit values.  */
+  unsigned char buffer[64];
+  tree cst;
+
+  Type *tb = type->toBasetype ();
+
+  if (expr->type->isintegral ())
+    cst = build_integer_cst (expr->toInteger (), build_ctype (expr->type));
+  else if (expr->type->isfloating ())
+    cst = build_float_cst (expr->toReal (), expr->type);
+  else if (expr->op == TOKarrayliteral)
+    {
+      /* Build array as VECTOR_CST, assumes EXPR is constant.  */
+      Expressions *elements = ((ArrayLiteralExp *) expr)->elements;
+      vec<constructor_elt, va_gc> *elms = NULL;
+
+      vec_safe_reserve (elms, elements->dim);
+      for (size_t i = 0; i < elements->dim; i++)
+	{
+	  Expression *e = (*elements)[i];
+	  if (e->type->isintegral ())
+	    {
+	      tree value = build_integer_cst (e->toInteger (),
+					      build_ctype (e->type));
+	      CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value);
+	    }
+	  else if (e->type->isfloating ())
+	    {
+	      tree value = build_float_cst (e->toReal (), e->type);
+	      CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value);
+	    }
+	  else
+	    gcc_unreachable ();
+	}
+
+      /* Build vector type.  */
+      int nunits = ((TypeSArray *) expr->type)->dim->toUInteger ();
+      Type *telem = expr->type->nextOf ();
+      tree vectype = build_vector_type (build_ctype (telem), nunits);
+
+      cst = build_vector_from_ctor (vectype, elms);
+    }
+  else
+    gcc_unreachable ();
+
+  /* Encode CST to buffer.  */
+  int len = native_encode_expr (cst, buffer, sizeof (buffer));
+
+  if (tb->ty == Tsarray)
+    {
+      /* Interpret value as a vector of the same size,
+	 then return the array literal.  */
+      int nunits = ((TypeSArray *) type)->dim->toUInteger ();
+      Type *elem = type->nextOf ();
+      tree vectype = build_vector_type (build_ctype (elem), nunits);
+
+      cst = native_interpret_expr (vectype, buffer, len);
+
+      Expression *e = d_eval_constant_expression (cst);
+      gcc_assert (e != NULL && e->op == TOKvector);
+
+      return ((VectorExp *) e)->e1;
+    }
+  else
+    {
+      /* Normal interpret cast.  */
+      cst = native_interpret_expr (build_ctype (type), buffer, len);
+
+      Expression *e = d_eval_constant_expression (cst);
+      gcc_assert (e != NULL);
+
+      return e;
+    }
+}
+
+/* Check imported module M for any special processing.
+   Modules we look out for are:
+    - object: For D runtime type information.
+    - gcc.builtins: For all gcc builtins.
+    - core.stdc.*: For all gcc library builtins.  */
+
+void
+Compiler::loadModule (Module *m)
+{
+  ModuleDeclaration *md = m->md;
+
+  if (!md || !md->id || !md->packages)
+    {
+      Identifier *id = (md && md->id) ? md->id : m->ident;
+      if (!strcmp (id->toChars (), "object"))
+	create_tinfo_types (m);
+    }
+  else if (md->packages->dim == 1)
+    {
+      if (!strcmp ((*md->packages)[0]->toChars (), "gcc")
+	  && !strcmp (md->id->toChars (), "builtins"))
+	d_build_builtins_module (m);
+    }
+  else if (md->packages->dim == 2)
+    {
+      if (!strcmp ((*md->packages)[0]->toChars (), "core")
+	  && !strcmp ((*md->packages)[1]->toChars (), "stdc"))
+	d_add_builtin_module (m);
+    }
+}
diff --git a/gcc/d/d-ctfloat.cc b/gcc/d/d-ctfloat.cc
new file mode 100644
index 00000000000..f2243d4a45e
--- /dev/null
+++ b/gcc/d/d-ctfloat.cc
@@ -0,0 +1,143 @@ 
+/* d-ctfloat.cc -- D frontend interface to the gcc back-end.
+   Copyright (C) 2020 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/root/ctfloat.h"
+#include "dmd/target.h"
+
+#include "tree.h"
+
+
+/* Implements the CTFloat interface defined by the frontend.
+   Compile-time floating-pointer helper functions.  */
+
+/* Return the absolute value of R.  */
+
+real_t
+CTFloat::fabs (real_t r)
+{
+  real_t x;
+  real_arithmetic (&x.rv (), ABS_EXPR, &r.rv (), NULL);
+  return x.normalize ();
+}
+
+/* Return the value of R * 2 ^^ EXP.  */
+
+real_t
+CTFloat::ldexp (real_t r, int exp)
+{
+  real_t x;
+  real_ldexp (&x.rv (), &r.rv (), exp);
+  return x.normalize ();
+}
+
+/* Return true if longdouble value X is identical to Y.  */
+
+bool
+CTFloat::isIdentical (real_t x, real_t y)
+{
+  real_value rx = x.rv ();
+  real_value ry = y.rv ();
+  return (REAL_VALUE_ISNAN (rx) && REAL_VALUE_ISNAN (ry))
+    || real_identical (&rx, &ry);
+}
+
+/* Return true if real_t value R is NaN.  */
+
+bool
+CTFloat::isNaN (real_t r)
+{
+  return REAL_VALUE_ISNAN (r.rv ());
+}
+
+/* Same as isNaN, but also check if is signalling.  */
+
+bool
+CTFloat::isSNaN (real_t r)
+{
+  return REAL_VALUE_ISSIGNALING_NAN (r.rv ());
+}
+
+/* Return true if real_t value is +Inf.  */
+
+bool
+CTFloat::isInfinity (real_t r)
+{
+  return REAL_VALUE_ISINF (r.rv ());
+}
+
+/* Return a real_t value from string BUFFER rounded to long double mode.  */
+
+real_t
+CTFloat::parse (const char *buffer, bool *overflow)
+{
+  real_t r;
+  real_from_string3 (&r.rv (), buffer, TYPE_MODE (long_double_type_node));
+
+  /* Front-end checks overflow to see if the value is representable.  */
+  if (overflow && r == Target::RealProperties::infinity)
+    *overflow = true;
+
+  return r;
+}
+
+/* Format the real_t value R to string BUFFER as a decimal or hexadecimal,
+   converting the result to uppercase if FMT requests it.  */
+
+int
+CTFloat::sprint (char *buffer, char fmt, real_t r)
+{
+  if (fmt == 'a' || fmt == 'A')
+    {
+      /* Converting to a hexadecimal string.  */
+      real_to_hexadecimal (buffer, &r.rv (), 32, 0, 1);
+      int buflen;
+
+      switch (fmt)
+	{
+	case 'A':
+	  buflen = strlen (buffer);
+	  for (int i = 0; i < buflen; i++)
+	    buffer[i] = TOUPPER (buffer[i]);
+
+	  return buflen;
+
+	case 'a':
+	  return strlen (buffer);
+
+	default:
+	  gcc_unreachable ();
+	}
+    }
+  else
+    {
+      /* Note: restricting the precision of significant digits to 18.  */
+      real_to_decimal (buffer, &r.rv (), 32, 18, 1);
+      return strlen (buffer);
+    }
+}
+
+/* Return a hash value for real_t value R.  */
+
+size_t
+CTFloat::hash (real_t r)
+{
+  return real_hash (&r.rv ());
+}
diff --git a/gcc/d/d-frontend.cc b/gcc/d/d-frontend.cc
index ec08d62f53e..28756161b93 100644
--- a/gcc/d/d-frontend.cc
+++ b/gcc/d/d-frontend.cc
@@ -20,22 +20,16 @@  along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 
 #include "dmd/aggregate.h"
-#include "dmd/compiler.h"
 #include "dmd/declaration.h"
-#include "dmd/errors.h"
 #include "dmd/expression.h"
-#include "dmd/identifier.h"
 #include "dmd/module.h"
 #include "dmd/mtype.h"
 #include "dmd/scope.h"
-#include "dmd/statement.h"
-#include "dmd/target.h"
 
 #include "tree.h"
 #include "options.h"
 #include "fold-const.h"
 #include "diagnostic.h"
-#include "stor-layout.h"
 
 #include "d-tree.h"
 
@@ -144,416 +138,6 @@  Loc::equals (const Loc& loc)
 }
 
 
-/* Implements the Port interface defined by the frontend.
-   A mini library for doing compiler/system specific things.  */
-
-/* Compare the first N bytes of S1 and S2 without regard to the case.  */
-
-int
-Port::memicmp (const char *s1, const char *s2, size_t n)
-{
-  int result = 0;
-
-  for (size_t i = 0; i < n; i++)
-    {
-      char c1 = s1[i];
-      char c2 = s2[i];
-
-      result = c1 - c2;
-      if (result)
-	{
-	  result = TOUPPER (c1) - TOUPPER (c2);
-	  if (result)
-	    break;
-	}
-    }
-
-  return result;
-}
-
-/* Convert all characters in S to uppercase.  */
-
-char *
-Port::strupr (char *s)
-{
-  char *t = s;
-
-  while (*s)
-    {
-      *s = TOUPPER (*s);
-      s++;
-    }
-
-  return t;
-}
-
-/* Return true if the real_t value from string BUFFER overflows
-   as a result of rounding down to float mode.  */
-
-bool
-Port::isFloat32LiteralOutOfRange (const char *buffer)
-{
-  real_t r;
-
-  real_from_string3 (&r.rv (), buffer, TYPE_MODE (float_type_node));
-
-  return r == Target::RealProperties::infinity;
-}
-
-/* Return true if the real_t value from string BUFFER overflows
-   as a result of rounding down to double mode.  */
-
-bool
-Port::isFloat64LiteralOutOfRange (const char *buffer)
-{
-  real_t r;
-
-  real_from_string3 (&r.rv (), buffer, TYPE_MODE (double_type_node));
-
-  return r == Target::RealProperties::infinity;
-}
-
-/* Fetch a little-endian 16-bit value from BUFFER.  */
-
-unsigned
-Port::readwordLE (void *buffer)
-{
-  unsigned char *p = (unsigned char*) buffer;
-
-  return ((unsigned) p[1] << 8) | (unsigned) p[0];
-}
-
-/* Fetch a big-endian 16-bit value from BUFFER.  */
-
-unsigned
-Port::readwordBE (void *buffer)
-{
-  unsigned char *p = (unsigned char*) buffer;
-
-  return ((unsigned) p[0] << 8) | (unsigned) p[1];
-}
-
-/* Fetch a little-endian 32-bit value from BUFFER.  */
-
-unsigned
-Port::readlongLE (void *buffer)
-{
-  unsigned char *p = (unsigned char*) buffer;
-
-  return (((unsigned) p[3] << 24)
-	  | ((unsigned) p[2] << 16)
-	  | ((unsigned) p[1] << 8)
-	  | (unsigned) p[0]);
-}
-
-/* Fetch a big-endian 32-bit value from BUFFER.  */
-
-unsigned
-Port::readlongBE (void *buffer)
-{
-  unsigned char *p = (unsigned char*) buffer;
-
-  return (((unsigned) p[0] << 24)
-	  | ((unsigned) p[1] << 16)
-	  | ((unsigned) p[2] << 8)
-	  | (unsigned) p[3]);
-}
-
-/* Write an SZ-byte sized VALUE to BUFFER, ignoring endian-ness.  */
-
-void
-Port::valcpy (void *buffer, uint64_t value, size_t sz)
-{
-  switch (sz)
-    {
-    case 1:
-      *(uint8_t *) buffer = (uint8_t) value;
-      break;
-
-    case 2:
-      *(uint16_t *) buffer = (uint16_t) value;
-      break;
-
-    case 4:
-      *(uint32_t *) buffer = (uint32_t) value;
-      break;
-
-    case 8:
-      *(uint64_t *) buffer = (uint64_t) value;
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-}
-
-
-/* Implements the CTFloat interface defined by the frontend.
-   Compile-time floating-pointer helper functions.  */
-
-/* Return the absolute value of R.  */
-
-real_t
-CTFloat::fabs (real_t r)
-{
-  real_t x;
-  real_arithmetic (&x.rv (), ABS_EXPR, &r.rv (), NULL);
-  return x.normalize ();
-}
-
-/* Return the value of R * 2 ^^ EXP.  */
-
-real_t
-CTFloat::ldexp (real_t r, int exp)
-{
-  real_t x;
-  real_ldexp (&x.rv (), &r.rv (), exp);
-  return x.normalize ();
-}
-
-/* Return true if longdouble value X is identical to Y.  */
-
-bool
-CTFloat::isIdentical (real_t x, real_t y)
-{
-  real_value rx = x.rv ();
-  real_value ry = y.rv ();
-  return (REAL_VALUE_ISNAN (rx) && REAL_VALUE_ISNAN (ry))
-    || real_identical (&rx, &ry);
-}
-
-/* Return true if real_t value R is NaN.  */
-
-bool
-CTFloat::isNaN (real_t r)
-{
-  return REAL_VALUE_ISNAN (r.rv ());
-}
-
-/* Same as isNaN, but also check if is signalling.  */
-
-bool
-CTFloat::isSNaN (real_t r)
-{
-  return REAL_VALUE_ISSIGNALING_NAN (r.rv ());
-}
-
-/* Return true if real_t value is +Inf.  */
-
-bool
-CTFloat::isInfinity (real_t r)
-{
-  return REAL_VALUE_ISINF (r.rv ());
-}
-
-/* Return a real_t value from string BUFFER rounded to long double mode.  */
-
-real_t
-CTFloat::parse (const char *buffer, bool *overflow)
-{
-  real_t r;
-  real_from_string3 (&r.rv (), buffer, TYPE_MODE (long_double_type_node));
-
-  /* Front-end checks overflow to see if the value is representable.  */
-  if (overflow && r == Target::RealProperties::infinity)
-    *overflow = true;
-
-  return r;
-}
-
-/* Format the real_t value R to string BUFFER as a decimal or hexadecimal,
-   converting the result to uppercase if FMT requests it.  */
-
-int
-CTFloat::sprint (char *buffer, char fmt, real_t r)
-{
-  if (fmt == 'a' || fmt == 'A')
-    {
-      /* Converting to a hexadecimal string.  */
-      real_to_hexadecimal (buffer, &r.rv (), 32, 0, 1);
-      int buflen;
-
-      switch (fmt)
-	{
-	case 'A':
-	  buflen = strlen (buffer);
-	  for (int i = 0; i < buflen; i++)
-	    buffer[i] = TOUPPER (buffer[i]);
-
-	  return buflen;
-
-	case 'a':
-	  return strlen (buffer);
-
-	default:
-	  gcc_unreachable ();
-	}
-    }
-  else
-    {
-      /* Note: restricting the precision of significant digits to 18.  */
-      real_to_decimal (buffer, &r.rv (), 32, 18, 1);
-      return strlen (buffer);
-    }
-}
-
-/* Return a hash value for real_t value R.  */
-
-size_t
-CTFloat::hash (real_t r)
-{
-  return real_hash (&r.rv ());
-}
-
-/* Implements the Compiler interface used by the frontend.  */
-
-/* Generate C main() in response to seeing D main().  This used to be in
-   libdruntime, but contained a reference to _Dmain which didn't work when
-   druntime was made into a shared library and was linked to a program, such
-   as a C++ program, that didn't have a _Dmain.  */
-
-void
-Compiler::genCmain (Scope *sc)
-{
-  static bool initialized = false;
-
-  if (initialized)
-    return;
-
-  /* The D code to be generated is provided by __entrypoint.di, try to load it,
-     but don't fail if unfound.  */
-  unsigned errors = global.startGagging ();
-  Module *m = Module::load (Loc (), NULL, Identifier::idPool ("__entrypoint"));
-
-  if (global.endGagging (errors))
-    m = NULL;
-
-  if (m != NULL)
-    {
-      m->importedFrom = m;
-      m->importAll (NULL);
-      m->semantic (NULL);
-      m->semantic2 (NULL);
-      m->semantic3 (NULL);
-      d_add_entrypoint_module (m, sc->_module);
-    }
-
-  initialized = true;
-}
-
-/* Perform a reinterpret cast of EXPR to type TYPE for use in CTFE.
-   The front end should have already ensured that EXPR is a constant,
-   so we just lower the value to GCC and return the converted CST.  */
-
-Expression *
-Compiler::paintAsType (UnionExp *, Expression *expr, Type *type)
-{
-  /* We support up to 512-bit values.  */
-  unsigned char buffer[64];
-  tree cst;
-
-  Type *tb = type->toBasetype ();
-
-  if (expr->type->isintegral ())
-    cst = build_integer_cst (expr->toInteger (), build_ctype (expr->type));
-  else if (expr->type->isfloating ())
-    cst = build_float_cst (expr->toReal (), expr->type);
-  else if (expr->op == TOKarrayliteral)
-    {
-      /* Build array as VECTOR_CST, assumes EXPR is constant.  */
-      Expressions *elements = ((ArrayLiteralExp *) expr)->elements;
-      vec<constructor_elt, va_gc> *elms = NULL;
-
-      vec_safe_reserve (elms, elements->dim);
-      for (size_t i = 0; i < elements->dim; i++)
-	{
-	  Expression *e = (*elements)[i];
-	  if (e->type->isintegral ())
-	    {
-	      tree value = build_integer_cst (e->toInteger (),
-					      build_ctype (e->type));
-	      CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value);
-	    }
-	  else if (e->type->isfloating ())
-	    {
-	      tree value = build_float_cst (e->toReal (), e->type);
-	      CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value);
-	    }
-	  else
-	    gcc_unreachable ();
-	}
-
-      /* Build vector type.  */
-      int nunits = ((TypeSArray *) expr->type)->dim->toUInteger ();
-      Type *telem = expr->type->nextOf ();
-      tree vectype = build_vector_type (build_ctype (telem), nunits);
-
-      cst = build_vector_from_ctor (vectype, elms);
-    }
-  else
-    gcc_unreachable ();
-
-  /* Encode CST to buffer.  */
-  int len = native_encode_expr (cst, buffer, sizeof (buffer));
-
-  if (tb->ty == Tsarray)
-    {
-      /* Interpret value as a vector of the same size,
-	 then return the array literal.  */
-      int nunits = ((TypeSArray *) type)->dim->toUInteger ();
-      Type *elem = type->nextOf ();
-      tree vectype = build_vector_type (build_ctype (elem), nunits);
-
-      cst = native_interpret_expr (vectype, buffer, len);
-
-      Expression *e = d_eval_constant_expression (cst);
-      gcc_assert (e != NULL && e->op == TOKvector);
-
-      return ((VectorExp *) e)->e1;
-    }
-  else
-    {
-      /* Normal interpret cast.  */
-      cst = native_interpret_expr (build_ctype (type), buffer, len);
-
-      Expression *e = d_eval_constant_expression (cst);
-      gcc_assert (e != NULL);
-
-      return e;
-    }
-}
-
-/* Check imported module M for any special processing.
-   Modules we look out for are:
-    - object: For D runtime type information.
-    - gcc.builtins: For all gcc builtins.
-    - core.stdc.*: For all gcc library builtins.  */
-
-void
-Compiler::loadModule (Module *m)
-{
-  ModuleDeclaration *md = m->md;
-
-  if (!md || !md->id || !md->packages)
-    {
-      Identifier *id = (md && md->id) ? md->id : m->ident;
-      if (!strcmp (id->toChars (), "object"))
-	create_tinfo_types (m);
-    }
-  else if (md->packages->dim == 1)
-    {
-      if (!strcmp ((*md->packages)[0]->toChars (), "gcc")
-	  && !strcmp (md->id->toChars (), "builtins"))
-	d_build_builtins_module (m);
-    }
-  else if (md->packages->dim == 2)
-    {
-      if (!strcmp ((*md->packages)[0]->toChars (), "core")
-	  && !strcmp ((*md->packages)[1]->toChars (), "stdc"))
-	d_add_builtin_module (m);
-    }
-}
-
 /* Implements back-end specific interfaces used by the frontend.  */
 
 /* Determine return style of function - whether in registers or through a
diff --git a/gcc/d/d-port.cc b/gcc/d/d-port.cc
new file mode 100644
index 00000000000..12208a9039f
--- /dev/null
+++ b/gcc/d/d-port.cc
@@ -0,0 +1,169 @@ 
+/* d-port.cc -- D frontend interface to the gcc back-end.
+   Copyright (C) 2013-2020 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/root/port.h"
+#include "dmd/target.h"
+
+#include "tree.h"
+
+
+/* Implements the Port interface defined by the frontend.
+   A mini library for doing compiler/system specific things.  */
+
+/* Compare the first N bytes of S1 and S2 without regard to the case.  */
+
+int
+Port::memicmp (const char *s1, const char *s2, size_t n)
+{
+  int result = 0;
+
+  for (size_t i = 0; i < n; i++)
+    {
+      char c1 = s1[i];
+      char c2 = s2[i];
+
+      result = c1 - c2;
+      if (result)
+	{
+	  result = TOUPPER (c1) - TOUPPER (c2);
+	  if (result)
+	    break;
+	}
+    }
+
+  return result;
+}
+
+/* Convert all characters in S to uppercase.  */
+
+char *
+Port::strupr (char *s)
+{
+  char *t = s;
+
+  while (*s)
+    {
+      *s = TOUPPER (*s);
+      s++;
+    }
+
+  return t;
+}
+
+/* Return true if the real_t value from string BUFFER overflows
+   as a result of rounding down to float mode.  */
+
+bool
+Port::isFloat32LiteralOutOfRange (const char *buffer)
+{
+  real_t r;
+
+  real_from_string3 (&r.rv (), buffer, TYPE_MODE (float_type_node));
+
+  return r == Target::RealProperties::infinity;
+}
+
+/* Return true if the real_t value from string BUFFER overflows
+   as a result of rounding down to double mode.  */
+
+bool
+Port::isFloat64LiteralOutOfRange (const char *buffer)
+{
+  real_t r;
+
+  real_from_string3 (&r.rv (), buffer, TYPE_MODE (double_type_node));
+
+  return r == Target::RealProperties::infinity;
+}
+
+/* Fetch a little-endian 16-bit value from BUFFER.  */
+
+unsigned
+Port::readwordLE (void *buffer)
+{
+  unsigned char *p = (unsigned char*) buffer;
+
+  return ((unsigned) p[1] << 8) | (unsigned) p[0];
+}
+
+/* Fetch a big-endian 16-bit value from BUFFER.  */
+
+unsigned
+Port::readwordBE (void *buffer)
+{
+  unsigned char *p = (unsigned char*) buffer;
+
+  return ((unsigned) p[0] << 8) | (unsigned) p[1];
+}
+
+/* Fetch a little-endian 32-bit value from BUFFER.  */
+
+unsigned
+Port::readlongLE (void *buffer)
+{
+  unsigned char *p = (unsigned char*) buffer;
+
+  return (((unsigned) p[3] << 24)
+	  | ((unsigned) p[2] << 16)
+	  | ((unsigned) p[1] << 8)
+	  | (unsigned) p[0]);
+}
+
+/* Fetch a big-endian 32-bit value from BUFFER.  */
+
+unsigned
+Port::readlongBE (void *buffer)
+{
+  unsigned char *p = (unsigned char*) buffer;
+
+  return (((unsigned) p[0] << 24)
+	  | ((unsigned) p[1] << 16)
+	  | ((unsigned) p[2] << 8)
+	  | (unsigned) p[3]);
+}
+
+/* Write an SZ-byte sized VALUE to BUFFER, ignoring endian-ness.  */
+
+void
+Port::valcpy (void *buffer, uint64_t value, size_t sz)
+{
+  switch (sz)
+    {
+    case 1:
+      *(uint8_t *) buffer = (uint8_t) value;
+      break;
+
+    case 2:
+      *(uint16_t *) buffer = (uint16_t) value;
+      break;
+
+    case 4:
+      *(uint32_t *) buffer = (uint32_t) value;
+      break;
+
+    case 8:
+      *(uint64_t *) buffer = (uint64_t) value;
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+}