From d81bc495a426b0020e44a9764fd904462a39983b Mon Sep 17 00:00:00 2001
From: Iain Buclaw <ibuclaw@gdcproject.org>
Date: Mon, 12 Apr 2021 01:39:08 +0200
Subject: [PATCH] d: Implement __traits(getTargetInfo, "objectFormat")

Following on from adding TARGET_D_REGISTER_OS_TARGET_INFO, this adds the
required handlers to implement `__traits(getTargetInfo, "objectFormat")'
for all platforms that have D support files.

Some back-ends (i386, rs6000, and pa) have some awarenes of the what
object format they are compiling for, so new getTargetInfo handlers have
been have added both to those back-ends as well as platform-specific
target files to override the default in the D front-end.

gcc/ChangeLog:

	* config/darwin-d.c (darwin_d_handle_target_object_format): New
	function.
	(darwin_d_register_target_info): New function.
	(TARGET_D_REGISTER_OS_TARGET_INFO): Define.
	* config/dragonfly-d.c (dragonfly_d_handle_target_object_format): New
	function.
	(dragonfly_d_register_target_info): New function.
	(TARGET_D_REGISTER_OS_TARGET_INFO): Define.
	* config/freebsd-d.c (freebsd_d_handle_target_object_format): New
	function.
	(freebsd_d_register_target_info): New function.
	(TARGET_D_REGISTER_OS_TARGET_INFO): Define.
	* config/glibc-d.c (glibc_d_handle_target_object_format): New
	function.
	(glibc_d_register_target_info): New function.
	(TARGET_D_REGISTER_OS_TARGET_INFO): Define.
	* config/i386/i386-d.c (ix86_d_handle_target_object_format): New
	function.
	(ix86_d_register_target_info): Add ix86_d_handle_target_object_format
	as handler for objectFormat key.
	* config/i386/winnt-d.c (winnt_d_handle_target_object_format): New
	function.
	(winnt_d_register_target_info): New function.
	(TARGET_D_REGISTER_OS_TARGET_INFO): Define.
	* config/netbsd-d.c (netbsd_d_handle_target_object_format): New
	function.
	(netbsd_d_register_target_info): New function.
	(TARGET_D_REGISTER_OS_TARGET_INFO): Define.
	* config/openbsd-d.c (openbsd_d_handle_target_object_format): New
	function.
	(openbsd_d_register_target_info): New function.
	(TARGET_D_REGISTER_OS_TARGET_INFO): Define.
	* config/pa/pa-d.c (pa_d_handle_target_object_format): New function.
	(pa_d_register_target_info): Add pa_d_handle_target_object_format as
	handler for objectFormat key.
	* config/rs6000/rs6000-d.c (rs6000_d_handle_target_object_format): New
	function.
	(rs6000_d_register_target_info): Add
	rs6000_d_handle_target_object_format as handler for objectFormat key.
	* config/sol2-d.c (solaris_d_handle_target_object_format): New
	function.
	(solaris_d_register_target_info): New function.
	(TARGET_D_REGISTER_OS_TARGET_INFO): Define.

gcc/d/ChangeLog:

	* d-target.cc (d_handle_target_object_format): New function.
	(d_language_target_info): Add d_handle_target_object_format as handler
	for objectFormat key.
	(Target::getTargetInfo): Continue if handler returned NULL_TREE.
---
 gcc/config/darwin-d.c        | 26 ++++++++++++++++++++++++++
 gcc/config/dragonfly-d.c     | 26 ++++++++++++++++++++++++++
 gcc/config/freebsd-d.c       | 26 ++++++++++++++++++++++++++
 gcc/config/glibc-d.c         | 26 ++++++++++++++++++++++++++
 gcc/config/i386/i386-d.c     | 19 +++++++++++++++++++
 gcc/config/i386/winnt-d.c    | 25 +++++++++++++++++++++++++
 gcc/config/netbsd-d.c        | 28 ++++++++++++++++++++++++++++
 gcc/config/openbsd-d.c       | 28 ++++++++++++++++++++++++++++
 gcc/config/pa/pa-d.c         | 17 +++++++++++++++++
 gcc/config/rs6000/rs6000-d.c | 21 +++++++++++++++++++++
 gcc/config/sol2-d.c          | 26 ++++++++++++++++++++++++++
 gcc/d/d-target.cc            | 35 +++++++++++++++++++++++++++++++----
 12 files changed, 299 insertions(+), 4 deletions(-)

diff --git a/gcc/config/darwin-d.c b/gcc/config/darwin-d.c
index afc32da4ad85..67d69b721b56 100644
--- a/gcc/config/darwin-d.c
+++ b/gcc/config/darwin-d.c
@@ -32,9 +32,35 @@ darwin_d_os_builtins (void)
   d_add_builtin_version ("darwin");
 }
 
+/* Handle a call to `__traits(getTargetInfo, "objectFormat")'.  */
+
+static tree
+darwin_d_handle_target_object_format (void)
+{
+  const char *objfmt = "macho";
+
+  return build_string_literal (strlen (objfmt) + 1, objfmt);
+}
+
+/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for Darwin targets.  */
+
+static void
+darwin_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "objectFormat", darwin_d_handle_target_object_format },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
+
 #undef TARGET_D_OS_VERSIONS
 #define TARGET_D_OS_VERSIONS darwin_d_os_builtins
 
+#undef TARGET_D_REGISTER_OS_TARGET_INFO
+#define TARGET_D_REGISTER_OS_TARGET_INFO darwin_d_register_target_info
+
 /* Define TARGET_D_MINFO_SECTION for Darwin targets.  */
 
 #undef TARGET_D_MINFO_SECTION
diff --git a/gcc/config/dragonfly-d.c b/gcc/config/dragonfly-d.c
index 76f4cc02ff73..dc301b54e8f4 100644
--- a/gcc/config/dragonfly-d.c
+++ b/gcc/config/dragonfly-d.c
@@ -31,7 +31,33 @@ dragonfly_d_os_builtins (void)
   d_add_builtin_version ("Posix");
 }
 
+/* Handle a call to `__traits(getTargetInfo, "objectFormat")'.  */
+
+static tree
+dragonfly_d_handle_target_object_format (void)
+{
+  const char *objfmt = "elf";
+
+  return build_string_literal (strlen (objfmt) + 1, objfmt);
+}
+
+/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for DragonFly targets.  */
+
+static void
+dragonfly_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "objectFormat", dragonfly_d_handle_target_object_format },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
+
 #undef TARGET_D_OS_VERSIONS
 #define TARGET_D_OS_VERSIONS dragonfly_d_os_builtins
 
+#undef TARGET_D_REGISTER_OS_TARGET_INFO
+#define TARGET_D_REGISTER_OS_TARGET_INFO dragonfly_d_register_target_info
+
 struct gcc_targetdm targetdm = TARGETDM_INITIALIZER;
diff --git a/gcc/config/freebsd-d.c b/gcc/config/freebsd-d.c
index 8a8ddd92884c..8bebe79c895f 100644
--- a/gcc/config/freebsd-d.c
+++ b/gcc/config/freebsd-d.c
@@ -37,7 +37,33 @@ freebsd_d_os_builtins (void)
   d_add_builtin_version ("Posix");
 }
 
+/* Handle a call to `__traits(getTargetInfo, "objectFormat")'.  */
+
+static tree
+freebsd_d_handle_target_object_format (void)
+{
+  const char *objfmt = "elf";
+
+  return build_string_literal (strlen (objfmt) + 1, objfmt);
+}
+
+/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for FreeBSD targets.  */
+
+static void
+freebsd_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "objectFormat", freebsd_d_handle_target_object_format },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
+
 #undef TARGET_D_OS_VERSIONS
 #define TARGET_D_OS_VERSIONS freebsd_d_os_builtins
 
+#undef TARGET_D_REGISTER_OS_TARGET_INFO
+#define TARGET_D_REGISTER_OS_TARGET_INFO freebsd_d_register_target_info
+
 struct gcc_targetdm targetdm = TARGETDM_INITIALIZER;
diff --git a/gcc/config/glibc-d.c b/gcc/config/glibc-d.c
index 092c5d805a60..c98d494cd771 100644
--- a/gcc/config/glibc-d.c
+++ b/gcc/config/glibc-d.c
@@ -42,7 +42,33 @@ glibc_d_os_builtins (void)
 #endif
 }
 
+/* Handle a call to `__traits(getTargetInfo, "objectFormat")'.  */
+
+static tree
+glibc_d_handle_target_object_format (void)
+{
+  const char *objfmt = "elf";
+
+  return build_string_literal (strlen (objfmt) + 1, objfmt);
+}
+
+/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for Glibc targets.  */
+
+static void
+glibc_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "objectFormat", glibc_d_handle_target_object_format },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
+
 #undef TARGET_D_OS_VERSIONS
 #define TARGET_D_OS_VERSIONS glibc_d_os_builtins
 
+#undef TARGET_D_REGISTER_OS_TARGET_INFO
+#define TARGET_D_REGISTER_OS_TARGET_INFO glibc_d_register_target_info
+
 struct gcc_targetdm targetdm = TARGETDM_INITIALIZER;
diff --git a/gcc/config/i386/i386-d.c b/gcc/config/i386/i386-d.c
index da5958c3e7d0..cb99376cd78d 100644
--- a/gcc/config/i386/i386-d.c
+++ b/gcc/config/i386/i386-d.c
@@ -60,6 +60,24 @@ ix86_d_handle_target_float_abi (void)
   return build_string_literal (strlen (abi) + 1, abi);
 }
 
+/* Handle a call to `__traits(getTargetInfo, "objectFormat")'.  */
+
+static tree
+ix86_d_handle_target_object_format (void)
+{
+  const char *objfmt = NULL;
+
+  if (TARGET_MACHO)
+    objfmt = "macho";
+  else if (TARGET_COFF || TARGET_PECOFF)
+    objfmt = "coff";
+
+  if (objfmt == NULL)
+    return NULL_TREE;
+
+  return build_string_literal (strlen (objfmt) + 1, objfmt);
+}
+
 /* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
 
 void
@@ -67,6 +85,7 @@ ix86_d_register_target_info (void)
 {
   const struct d_target_info_spec handlers[] = {
     { "floatAbi", ix86_d_handle_target_float_abi },
+    { "objectFormat", ix86_d_handle_target_object_format },
     { NULL, NULL },
   };
 
diff --git a/gcc/config/i386/winnt-d.c b/gcc/config/i386/winnt-d.c
index 8a6b9c57d8df..b97802585490 100644
--- a/gcc/config/i386/winnt-d.c
+++ b/gcc/config/i386/winnt-d.c
@@ -39,9 +39,34 @@ winnt_d_os_builtins (void)
 #endif
 }
 
+/* Handle a call to `__traits(getTargetInfo, "objectFormat")'.  */
+
+static tree
+winnt_d_handle_target_object_format (void)
+{
+  const char *objfmt = "coff";
+
+  return build_string_literal (strlen (objfmt) + 1, objfmt);
+}
+
+/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for Windows targets.  */
+
+static void
+winnt_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "objectFormat", winnt_d_handle_target_object_format },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
 #undef TARGET_D_OS_VERSIONS
 #define TARGET_D_OS_VERSIONS winnt_d_os_builtins
 
+#undef TARGET_D_REGISTER_OS_TARGET_INFO
+#define TARGET_D_REGISTER_OS_TARGET_INFO winnt_d_register_target_info
+
 /* Define TARGET_D_MINFO_SECTION for Windows targets.  */
 
 #undef TARGET_D_MINFO_SECTION
diff --git a/gcc/config/netbsd-d.c b/gcc/config/netbsd-d.c
index c3ac01067feb..842644f82a39 100644
--- a/gcc/config/netbsd-d.c
+++ b/gcc/config/netbsd-d.c
@@ -26,6 +26,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "d/d-target.h"
 #include "d/d-target-def.h"
 
+/* Define TARGET_D_OS_VERSIONS for NetBSD targets.  */
+
 static void
 netbsd_d_os_builtins (void)
 {
@@ -33,7 +35,33 @@ netbsd_d_os_builtins (void)
   d_add_builtin_version ("NetBSD");
 }
 
+/* Handle a call to `__traits(getTargetInfo, "objectFormat")'.  */
+
+static tree
+netbsd_d_handle_target_object_format (void)
+{
+  const char *objfmt = "elf";
+
+  return build_string_literal (strlen (objfmt) + 1, objfmt);
+}
+
+/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for NetBSD targets.  */
+
+static void
+netbsd_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "objectFormat", netbsd_d_handle_target_object_format },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
+
 #undef TARGET_D_OS_VERSIONS
 #define TARGET_D_OS_VERSIONS netbsd_d_os_builtins
 
+#undef TARGET_D_REGISTER_OS_TARGET_INFO
+#define TARGET_D_REGISTER_OS_TARGET_INFO netbsd_d_register_target_info
+
 struct gcc_targetdm targetdm = TARGETDM_INITIALIZER;
diff --git a/gcc/config/openbsd-d.c b/gcc/config/openbsd-d.c
index b42727e1d5ac..31f8eb496fc9 100644
--- a/gcc/config/openbsd-d.c
+++ b/gcc/config/openbsd-d.c
@@ -26,6 +26,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "d/d-target.h"
 #include "d/d-target-def.h"
 
+/* Define TARGET_D_OS_VERSIONS for OpenBSD targets.  */
+
 static void
 openbsd_d_os_builtins (void)
 {
@@ -33,7 +35,33 @@ openbsd_d_os_builtins (void)
   d_add_builtin_version ("OpenBSD");
 }
 
+/* Handle a call to `__traits(getTargetInfo, "objectFormat")'.  */
+
+static tree
+openbsd_d_handle_target_object_format (void)
+{
+  const char *objfmt = "elf";
+
+  return build_string_literal (strlen (objfmt) + 1, objfmt);
+}
+
+/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for OpenBSD targets.  */
+
+static void
+openbsd_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "objectFormat", openbsd_d_handle_target_object_format },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
+
 #undef TARGET_D_OS_VERSIONS
 #define TARGET_D_OS_VERSIONS openbsd_d_os_builtins
 
+#undef TARGET_D_REGISTER_OS_TARGET_INFO
+#define TARGET_D_REGISTER_OS_TARGET_INFO openbsd_d_register_target_info
+
 struct gcc_targetdm targetdm = TARGETDM_INITIALIZER;
diff --git a/gcc/config/pa/pa-d.c b/gcc/config/pa/pa-d.c
index 41b2f1848e77..6802738e85bb 100644
--- a/gcc/config/pa/pa-d.c
+++ b/gcc/config/pa/pa-d.c
@@ -55,6 +55,22 @@ pa_d_handle_target_float_abi (void)
   return build_string_literal (strlen (abi) + 1, abi);
 }
 
+/* Handle a call to `__traits(getTargetInfo, "objectFormat")'.  */
+
+static tree
+pa_d_handle_target_object_format (void)
+{
+  const char *objfmt = NULL;
+
+  if (TARGET_SOM)
+    objfmt = "som";
+
+  if (objfmt == NULL)
+    return NULL_TREE;
+
+  return build_string_literal (strlen (objfmt) + 1, objfmt);
+}
+
 /* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
 
 void
@@ -62,6 +78,7 @@ pa_d_register_target_info (void)
 {
   const struct d_target_info_spec handlers[] = {
     { "floatAbi", pa_d_handle_target_float_abi },
+    { "objectFormat", pa_d_handle_target_object_format },
     { NULL, NULL },
   };
 
diff --git a/gcc/config/rs6000/rs6000-d.c b/gcc/config/rs6000/rs6000-d.c
index 755de42733bf..6f1f55b01b85 100644
--- a/gcc/config/rs6000/rs6000-d.c
+++ b/gcc/config/rs6000/rs6000-d.c
@@ -63,6 +63,26 @@ rs6000_d_handle_target_float_abi (void)
   return build_string_literal (strlen (abi) + 1, abi);
 }
 
+/* Handle a call to `__traits(getTargetInfo, "objectFormat")'.  */
+
+static tree
+rs6000_d_handle_target_object_format (void)
+{
+  const char *objfmt = NULL;
+
+  if (TARGET_ELF)
+    objfmt = "elf";
+  else if (TARGET_MACHO)
+    objfmt = "macho";
+  else if (TARGET_XCOFF)
+    objfmt = "coff";
+
+  if (objfmt == NULL)
+    return NULL_TREE;
+
+  return build_string_literal (strlen (objfmt) + 1, objfmt);
+}
+
 /* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
 
 void
@@ -70,6 +90,7 @@ rs6000_d_register_target_info (void)
 {
   const struct d_target_info_spec handlers[] = {
     { "floatAbi", rs6000_d_handle_target_float_abi },
+    { "objectFormat", rs6000_d_handle_target_object_format },
     { NULL, NULL },
   };
 
diff --git a/gcc/config/sol2-d.c b/gcc/config/sol2-d.c
index 529d365296ce..650cb3719278 100644
--- a/gcc/config/sol2-d.c
+++ b/gcc/config/sol2-d.c
@@ -33,7 +33,33 @@ solaris_d_os_builtins (void)
   d_add_builtin_version ("Solaris");			\
 }
 
+/* Handle a call to `__traits(getTargetInfo, "objectFormat")'.  */
+
+static tree
+solaris_d_handle_target_object_format (void)
+{
+  const char *objfmt = "elf";
+
+  return build_string_literal (strlen (objfmt) + 1, objfmt);
+}
+
+/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for Solaris targets.  */
+
+static void
+solaris_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "objectFormat", solaris_d_handle_target_object_format },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
+
 #undef TARGET_D_OS_VERSIONS
 #define TARGET_D_OS_VERSIONS solaris_d_os_builtins
 
+#undef TARGET_D_REGISTER_OS_TARGET_INFO
+#define TARGET_D_REGISTER_OS_TARGET_INFO solaris_d_register_target_info
+
 struct gcc_targetdm targetdm = TARGETDM_INITIALIZER;
diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index be354d9f1f0b..1488bcebb2c6 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -47,6 +47,7 @@ Target target;
 /* Internal key handlers for `__traits(getTargetInfo)'.  */
 static tree d_handle_target_cpp_std (void);
 static tree d_handle_target_cpp_runtime_library (void);
+static tree d_handle_target_object_format (void);
 
 /* In [traits/getTargetInfo], a reliable subset of getTargetInfo keys exists
    which are always available.  */
@@ -56,7 +57,7 @@ static const struct d_target_info_spec d_language_target_info[] =
   { "cppStd", d_handle_target_cpp_std },
   { "cppRuntimeLibrary", d_handle_target_cpp_runtime_library },
   { "floatAbi", NULL },
-  { "objectFormat", NULL },
+  { "objectFormat", d_handle_target_object_format },
   { NULL, NULL },
 };
 
@@ -517,6 +518,25 @@ d_handle_target_cpp_runtime_library (void)
   return build_string_literal (strlen (libstdcxx) + 1, libstdcxx);
 }
 
+/* Handle a call to `__traits(getTargetInfo, "objectFormat")'.  */
+
+tree
+d_handle_target_object_format (void)
+{
+  const char *objfmt;
+
+#ifdef OBJECT_FORMAT_ELF
+  objfmt = "elf";
+#else
+  if (TARGET_COFF || TARGET_PECOFF)
+    objfmt = "coff";
+  else
+    objfmt = "";
+#endif
+
+  return build_string_literal (strlen (objfmt) + 1, objfmt);
+}
+
 /* Look up the target info KEY in the available getTargetInfo tables, and return
    the result as an Expression, or NULL if KEY is not found.  When the key must
    always exist, but is not supported, an empty string expression is returned.
@@ -533,13 +553,20 @@ Target::getTargetInfo (const char *key, const Loc &loc)
       tree result;
 
       if (strcmp (key, spec->name) != 0)
-       continue;
+	continue;
 
       /* Get the requested information, or empty string if unhandled.  */
       if (spec->handler)
-       result = (spec->handler) ();
+	{
+	  result = (spec->handler) ();
+	  /* Handler didn't return a result, meaning it really does not support
+	     the key in the current target configuration.  Check whether there
+	     are any other handlers which may recognize the key.  */
+	  if (result == NULL_TREE)
+	    continue;
+	}
       else
-       result = build_string_literal (1, "");
+	result = build_string_literal (1, "");
 
       gcc_assert (result);
       return d_eval_constant_expression (loc, result);
-- 
GitLab