public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/iains/heads/d-for-darwin)] d: Implement __traits(getTargetInfo)
@ 2021-10-15 19:33 Iain D Sandoe
  0 siblings, 0 replies; 6+ messages in thread
From: Iain D Sandoe @ 2021-10-15 19:33 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:6c41c104ff8167cc28796f5b65c9d71c9a9693dc

commit 6c41c104ff8167cc28796f5b65c9d71c9a9693dc
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Fri Dec 4 23:04:21 2020 +0100

    d: Implement __traits(getTargetInfo)

Diff:
---
 gcc/config/arm/arm-d.c | 11 ++++-------
 gcc/d/dmd/traits.c     |  1 +
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/gcc/config/arm/arm-d.c b/gcc/config/arm/arm-d.c
index 5f43ef9b179..485b1b4d20a 100644
--- a/gcc/config/arm/arm-d.c
+++ b/gcc/config/arm/arm-d.c
@@ -38,15 +38,12 @@ arm_d_target_versions (void)
       d_add_builtin_version ("ARM_Thumb");
     }
 
-  if (TARGET_HARD_FLOAT_ABI)
+  if (arm_float_abi == ARM_FLOAT_ABI_HARD)
     d_add_builtin_version ("ARM_HardFloat");
-  else
-    {
-      if (TARGET_SOFT_FLOAT)
-	d_add_builtin_version ("ARM_SoftFloat");
-      else if (TARGET_HARD_FLOAT)
+  else if (arm_float_abi == ARM_FLOAT_ABI_SOFT)
+    d_add_builtin_version ("ARM_SoftFloat");
+  else if (arm_float_abi == ARM_FLOAT_ABI_SOFTFP)
 	d_add_builtin_version ("ARM_SoftFP");
-    }
 
   if (TARGET_SOFT_FLOAT)
     d_add_builtin_version ("D_SoftFloat");
diff --git a/gcc/d/dmd/traits.c b/gcc/d/dmd/traits.c
index 5a9f58b79f5..98cb6e4d48b 100644
--- a/gcc/d/dmd/traits.c
+++ b/gcc/d/dmd/traits.c
@@ -31,6 +31,7 @@
 #include "module.h"
 #include "attrib.h"
 #include "parse.h"
+#include "target.h"
 #include "root/speller.h"
 #include "target.h"


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [gcc(refs/users/iains/heads/d-for-darwin)] d: Implement __traits(getTargetInfo)
@ 2021-10-18 15:54 Iain D Sandoe
  0 siblings, 0 replies; 6+ messages in thread
From: Iain D Sandoe @ 2021-10-18 15:54 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:2bcaf641941a2df9a5571a3f39c568cca897b55d

commit 2bcaf641941a2df9a5571a3f39c568cca897b55d
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Fri Dec 4 23:04:21 2020 +0100

    d: Implement __traits(getTargetInfo)

Diff:
---
 gcc/config/arm/arm-d.c | 11 ++++-------
 gcc/d/dmd/traits.c     |  1 +
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/gcc/config/arm/arm-d.c b/gcc/config/arm/arm-d.c
index 5f43ef9b179..485b1b4d20a 100644
--- a/gcc/config/arm/arm-d.c
+++ b/gcc/config/arm/arm-d.c
@@ -38,15 +38,12 @@ arm_d_target_versions (void)
       d_add_builtin_version ("ARM_Thumb");
     }
 
-  if (TARGET_HARD_FLOAT_ABI)
+  if (arm_float_abi == ARM_FLOAT_ABI_HARD)
     d_add_builtin_version ("ARM_HardFloat");
-  else
-    {
-      if (TARGET_SOFT_FLOAT)
-	d_add_builtin_version ("ARM_SoftFloat");
-      else if (TARGET_HARD_FLOAT)
+  else if (arm_float_abi == ARM_FLOAT_ABI_SOFT)
+    d_add_builtin_version ("ARM_SoftFloat");
+  else if (arm_float_abi == ARM_FLOAT_ABI_SOFTFP)
 	d_add_builtin_version ("ARM_SoftFP");
-    }
 
   if (TARGET_SOFT_FLOAT)
     d_add_builtin_version ("D_SoftFloat");
diff --git a/gcc/d/dmd/traits.c b/gcc/d/dmd/traits.c
index 5a9f58b79f5..98cb6e4d48b 100644
--- a/gcc/d/dmd/traits.c
+++ b/gcc/d/dmd/traits.c
@@ -31,6 +31,7 @@
 #include "module.h"
 #include "attrib.h"
 #include "parse.h"
+#include "target.h"
 #include "root/speller.h"
 #include "target.h"


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [gcc(refs/users/iains/heads/d-for-darwin)] d: Implement __traits(getTargetInfo)
@ 2021-10-13  8:30 Iain D Sandoe
  0 siblings, 0 replies; 6+ messages in thread
From: Iain D Sandoe @ 2021-10-13  8:30 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:f5f7fae569bb5c4de1113b034ed947094cc049d4

commit f5f7fae569bb5c4de1113b034ed947094cc049d4
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Fri Dec 4 23:04:21 2020 +0100

    d: Implement __traits(getTargetInfo)

Diff:
---
 gcc/config/arm/arm-d.c | 11 ++++-------
 gcc/d/dmd/traits.c     |  1 +
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/gcc/config/arm/arm-d.c b/gcc/config/arm/arm-d.c
index 5f43ef9b179..485b1b4d20a 100644
--- a/gcc/config/arm/arm-d.c
+++ b/gcc/config/arm/arm-d.c
@@ -38,15 +38,12 @@ arm_d_target_versions (void)
       d_add_builtin_version ("ARM_Thumb");
     }
 
-  if (TARGET_HARD_FLOAT_ABI)
+  if (arm_float_abi == ARM_FLOAT_ABI_HARD)
     d_add_builtin_version ("ARM_HardFloat");
-  else
-    {
-      if (TARGET_SOFT_FLOAT)
-	d_add_builtin_version ("ARM_SoftFloat");
-      else if (TARGET_HARD_FLOAT)
+  else if (arm_float_abi == ARM_FLOAT_ABI_SOFT)
+    d_add_builtin_version ("ARM_SoftFloat");
+  else if (arm_float_abi == ARM_FLOAT_ABI_SOFTFP)
 	d_add_builtin_version ("ARM_SoftFP");
-    }
 
   if (TARGET_SOFT_FLOAT)
     d_add_builtin_version ("D_SoftFloat");
diff --git a/gcc/d/dmd/traits.c b/gcc/d/dmd/traits.c
index 5a9f58b79f5..98cb6e4d48b 100644
--- a/gcc/d/dmd/traits.c
+++ b/gcc/d/dmd/traits.c
@@ -31,6 +31,7 @@
 #include "module.h"
 #include "attrib.h"
 #include "parse.h"
+#include "target.h"
 #include "root/speller.h"
 #include "target.h"


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [gcc(refs/users/iains/heads/d-for-darwin)] d: Implement __traits(getTargetInfo)
@ 2021-10-11 20:34 Iain D Sandoe
  0 siblings, 0 replies; 6+ messages in thread
From: Iain D Sandoe @ 2021-10-11 20:34 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:2d2b98c454ffe8822aa2ef38f94df344e8ade030

commit 2d2b98c454ffe8822aa2ef38f94df344e8ade030
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Fri Dec 4 23:04:21 2020 +0100

    d: Implement __traits(getTargetInfo)

Diff:
---
 gcc/config/arm/arm-d.c | 11 ++++-------
 gcc/d/dmd/traits.c     |  1 +
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/gcc/config/arm/arm-d.c b/gcc/config/arm/arm-d.c
index 5f43ef9b179..485b1b4d20a 100644
--- a/gcc/config/arm/arm-d.c
+++ b/gcc/config/arm/arm-d.c
@@ -38,15 +38,12 @@ arm_d_target_versions (void)
       d_add_builtin_version ("ARM_Thumb");
     }
 
-  if (TARGET_HARD_FLOAT_ABI)
+  if (arm_float_abi == ARM_FLOAT_ABI_HARD)
     d_add_builtin_version ("ARM_HardFloat");
-  else
-    {
-      if (TARGET_SOFT_FLOAT)
-	d_add_builtin_version ("ARM_SoftFloat");
-      else if (TARGET_HARD_FLOAT)
+  else if (arm_float_abi == ARM_FLOAT_ABI_SOFT)
+    d_add_builtin_version ("ARM_SoftFloat");
+  else if (arm_float_abi == ARM_FLOAT_ABI_SOFTFP)
 	d_add_builtin_version ("ARM_SoftFP");
-    }
 
   if (TARGET_SOFT_FLOAT)
     d_add_builtin_version ("D_SoftFloat");
diff --git a/gcc/d/dmd/traits.c b/gcc/d/dmd/traits.c
index 5a9f58b79f5..98cb6e4d48b 100644
--- a/gcc/d/dmd/traits.c
+++ b/gcc/d/dmd/traits.c
@@ -31,6 +31,7 @@
 #include "module.h"
 #include "attrib.h"
 #include "parse.h"
+#include "target.h"
 #include "root/speller.h"
 #include "target.h"


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [gcc(refs/users/iains/heads/d-for-darwin)] d: Implement __traits(getTargetInfo)
@ 2020-12-21 20:36 Iain D Sandoe
  0 siblings, 0 replies; 6+ messages in thread
From: Iain D Sandoe @ 2020-12-21 20:36 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:738af1c3ff9f5146846865b28983d11ea9a009ac

commit 738af1c3ff9f5146846865b28983d11ea9a009ac
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Fri Dec 4 23:04:21 2020 +0100

    d: Implement __traits(getTargetInfo)

Diff:
---
 gcc/config/aarch64/aarch64-d.c                | 23 +++++++
 gcc/config/arm/arm-d.c                        | 53 +++++++++++++---
 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                      | 28 +++++++++
 gcc/config/i386/i386-protos.h                 |  1 +
 gcc/config/i386/i386.h                        |  3 +-
 gcc/config/mips/mips-d.c                      | 30 +++++++++
 gcc/config/netbsd-d.c                         | 26 ++++++++
 gcc/config/pa/pa-d.c                          | 28 +++++++++
 gcc/config/riscv/riscv-d.c                    | 46 ++++++++++++++
 gcc/config/rs6000/rs6000-d.c                  | 30 +++++++++
 gcc/config/s390/s390-d.c                      | 30 +++++++++
 gcc/config/sol2-d.c                           | 26 ++++++++
 gcc/config/sparc/sparc-d.c                    | 28 +++++++++
 gcc/d/d-builtins.cc                           | 31 ++++++---
 gcc/d/d-compiler.cc                           |  4 +-
 gcc/d/d-frontend.cc                           |  2 +-
 gcc/d/d-target.cc                             | 90 +++++++++++++++++++++++++++
 gcc/d/d-target.def                            | 20 ++++++
 gcc/d/d-target.h                              | 15 +++++
 gcc/d/d-tree.h                                |  2 +-
 gcc/d/dmd/idgen.c                             |  1 +
 gcc/d/dmd/target.h                            |  1 +
 gcc/d/dmd/traits.c                            | 24 +++++++
 gcc/doc/tm.texi                               | 14 +++++
 gcc/doc/tm.texi.in                            |  4 ++
 libphobos/libdruntime/core/sys/posix/setjmp.d |  3 +-
 30 files changed, 646 insertions(+), 21 deletions(-)

diff --git a/gcc/config/aarch64/aarch64-d.c b/gcc/config/aarch64/aarch64-d.c
index 69efd8df3d2..b01367a33ec 100644
--- a/gcc/config/aarch64/aarch64-d.c
+++ b/gcc/config/aarch64/aarch64-d.c
@@ -29,3 +29,26 @@ aarch64_d_target_versions (void)
   d_add_builtin_version ("AArch64");
   d_add_builtin_version ("D_HardFloat");
 }
+
+/* Handle a call to `__traits(getTargetInfo, "floatAbi")'.  */
+
+static tree
+aarch64_d_handle_target_float_abi (void)
+{
+  const char *abi = "hard";
+
+  return build_string_literal (strlen (abi) + 1, abi);
+}
+
+/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
+
+void
+aarch64_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "floatAbi", aarch64_d_handle_target_float_abi },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
diff --git a/gcc/config/arm/arm-d.c b/gcc/config/arm/arm-d.c
index e6c751c1e6c..138463e561b 100644
--- a/gcc/config/arm/arm-d.c
+++ b/gcc/config/arm/arm-d.c
@@ -36,18 +36,57 @@ arm_d_target_versions (void)
       d_add_builtin_version ("ARM_Thumb");
     }
 
-  if (TARGET_HARD_FLOAT_ABI)
+  if (arm_float_abi == ARM_FLOAT_ABI_HARD)
     d_add_builtin_version ("ARM_HardFloat");
-  else
-    {
-      if (TARGET_SOFT_FLOAT)
-	d_add_builtin_version ("ARM_SoftFloat");
-      else if (TARGET_HARD_FLOAT)
+  else if (arm_float_abi == ARM_FLOAT_ABI_SOFT)
+    d_add_builtin_version ("ARM_SoftFloat");
+  else if (arm_float_abi == ARM_FLOAT_ABI_SOFTFP)
 	d_add_builtin_version ("ARM_SoftFP");
-    }
 
   if (TARGET_SOFT_FLOAT)
     d_add_builtin_version ("D_SoftFloat");
   else if (TARGET_HARD_FLOAT)
     d_add_builtin_version ("D_HardFloat");
 }
+
+/* Handle a call to `__traits(getTargetInfo, "floatAbi")'.  */
+
+static tree
+arm_d_handle_target_float_abi (void)
+{
+  const char *abi;
+
+  switch (arm_float_abi)
+    {
+    case ARM_FLOAT_ABI_HARD:
+      abi = "hard";
+      break;
+
+    case ARM_FLOAT_ABI_SOFT:
+      abi = "soft";
+      break;
+
+    case ARM_FLOAT_ABI_SOFTFP:
+      abi = "softfp";
+      break;
+
+    default:
+      abi = "";
+      break;
+    }
+
+  return build_string_literal (strlen (abi) + 1, abi);
+}
+
+/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
+
+void
+arm_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "floatAbi", arm_d_handle_target_float_abi },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
diff --git a/gcc/config/darwin-d.c b/gcc/config/darwin-d.c
index ced07ce006a..7b8c72efe27 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 70ec820b75d..dac561e21d7 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 d79d82b5aa4..d8cf0dbab83 100644
--- a/gcc/config/freebsd-d.c
+++ b/gcc/config/freebsd-d.c
@@ -36,7 +36,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 7eb9e315f00..ca5bcc52dac 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 56fec11846e..9e40c2c2c66 100644
--- a/gcc/config/i386/i386-d.c
+++ b/gcc/config/i386/i386-d.c
@@ -42,3 +42,31 @@ ix86_d_target_versions (void)
   else
     d_add_builtin_version ("D_SoftFloat");
 }
+
+/* Handle a call to `__traits(getTargetInfo, "floatAbi")'.  */
+
+static tree
+ix86_d_handle_target_float_abi (void)
+{
+  const char *abi;
+
+  if (! (TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387))
+    abi = "soft";
+  else
+    abi = "hard";
+
+  return build_string_literal (strlen (abi) + 1, abi);
+}
+
+/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
+
+void
+ix86_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "floatAbi", ix86_d_handle_target_float_abi },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 65347a59b79..91bb77c6a4c 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -264,6 +264,7 @@ extern void ix86_register_pragmas (void);
 
 /* In i386-d.c  */
 extern void ix86_d_target_versions (void);
+extern void ix86_d_register_target_info (void);
 
 /* In winnt.c  */
 extern void i386_pe_unique_section (tree, int);
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index e88738ca873..3965ba861b3 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -799,8 +799,9 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
 /* Target Pragmas.  */
 #define REGISTER_TARGET_PRAGMAS() ix86_register_pragmas ()
 
-/* Target CPU versions for D.  */
+/* Target hooks for D language.  */
 #define TARGET_D_CPU_VERSIONS ix86_d_target_versions
+#define TARGET_D_REGISTER_CPU_TARGET_INFO ix86_d_register_target_info
 
 #ifndef CC1_SPEC
 #define CC1_SPEC "%(cc1_cpu) "
diff --git a/gcc/config/mips/mips-d.c b/gcc/config/mips/mips-d.c
index a9d4ba1f0b3..cd4f97a81d3 100644
--- a/gcc/config/mips/mips-d.c
+++ b/gcc/config/mips/mips-d.c
@@ -54,3 +54,33 @@ mips_d_target_versions (void)
       d_add_builtin_version ("D_SoftFloat");
     }
 }
+
+/* Handle a call to `__traits(getTargetInfo, "floatAbi")'.  */
+
+static tree
+mips_d_handle_target_float_abi (void)
+{
+  const char *abi;
+
+  if (TARGET_HARD_FLOAT_ABI)
+    abi = "hard";
+  else if (TARGET_SOFT_FLOAT_ABI)
+    abi = "soft";
+  else
+    abi = "";
+
+  return build_string_literal (strlen (abi) + 1, abi);
+}
+
+/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
+
+void
+mips_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "floatAbi", mips_d_handle_target_float_abi },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
diff --git a/gcc/config/netbsd-d.c b/gcc/config/netbsd-d.c
index 7c30d02b556..c7708edebff 100644
--- a/gcc/config/netbsd-d.c
+++ b/gcc/config/netbsd-d.c
@@ -33,7 +33,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/pa/pa-d.c b/gcc/config/pa/pa-d.c
index dda555858e3..b792985a623 100644
--- a/gcc/config/pa/pa-d.c
+++ b/gcc/config/pa/pa-d.c
@@ -37,3 +37,31 @@ pa_d_target_versions (void)
   else
     d_add_builtin_version ("D_HardFloat");
 }
+
+/* Handle a call to `__traits(getTargetInfo, "floatAbi")'.  */
+
+static tree
+pa_d_handle_target_float_abi (void)
+{
+  const char *abi;
+
+  if (TARGET_DISABLE_FPREGS || TARGET_SOFT_FLOAT)
+    abi = "soft";
+  else
+    abi = "hard";
+
+  return build_string_literal (strlen (abi) + 1, abi);
+}
+
+/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
+
+void
+pa_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "floatAbi", pa_d_handle_target_float_abi },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
diff --git a/gcc/config/riscv/riscv-d.c b/gcc/config/riscv/riscv-d.c
index 0fb08b49a30..34e7bc590a8 100644
--- a/gcc/config/riscv/riscv-d.c
+++ b/gcc/config/riscv/riscv-d.c
@@ -37,3 +37,49 @@ riscv_d_target_versions (void)
   else
     d_add_builtin_version ("D_SoftFloat");
 }
+
+/* Handle a call to `__traits(getTargetInfo, "floatAbi")'.  */
+
+static tree
+riscv_d_handle_target_float_abi (void)
+{
+  const char *abi;
+
+  switch (riscv_abi)
+    {
+    case ABI_ILP32E:
+    case ABI_ILP32:
+    case ABI_LP64:
+      abi = "soft";
+      break;
+
+    case ABI_ILP32F:
+    case ABI_LP64F:
+      abi = "single";
+      break;
+
+    case ABI_ILP32D:
+    case ABI_LP64D:
+      abi = "double";
+      break;
+
+    default:
+      abi = "";
+      break;
+    }
+
+  return build_string_literal (strlen (abi) + 1, abi);
+}
+
+/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
+
+void
+riscv_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "floatAbi", riscv_d_handle_target_float_abi },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
diff --git a/gcc/config/rs6000/rs6000-d.c b/gcc/config/rs6000/rs6000-d.c
index fd16e80aafd..d503a838c21 100644
--- a/gcc/config/rs6000/rs6000-d.c
+++ b/gcc/config/rs6000/rs6000-d.c
@@ -43,3 +43,33 @@ rs6000_d_target_versions (void)
       d_add_builtin_version ("D_SoftFloat");
     }
 }
+
+/* Handle a call to `__traits(getTargetInfo, "floatAbi")'.  */
+
+static tree
+rs6000_d_handle_target_float_abi (void)
+{
+  const char *abi;
+
+  if (TARGET_HARD_FLOAT)
+    abi = "hard";
+  else if (TARGET_SOFT_FLOAT)
+    abi = "soft";
+  else
+    abi = "";
+
+  return build_string_literal (strlen (abi) + 1, abi);
+}
+
+/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
+
+void
+rs6000_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "floatAbi", rs6000_d_handle_target_float_abi },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
diff --git a/gcc/config/s390/s390-d.c b/gcc/config/s390/s390-d.c
index 5a70e066e00..375c06a632a 100644
--- a/gcc/config/s390/s390-d.c
+++ b/gcc/config/s390/s390-d.c
@@ -39,3 +39,33 @@ s390_d_target_versions (void)
   else if (TARGET_HARD_FLOAT)
     d_add_builtin_version ("D_HardFloat");
 }
+
+/* Handle a call to `__traits(getTargetInfo, "floatAbi")'.  */
+
+static tree
+s390_d_handle_target_float_abi (void)
+{
+  const char *abi;
+
+  if (TARGET_HARD_FLOAT)
+    abi = "hard";
+  else if (TARGET_SOFT_FLOAT)
+    abi = "soft";
+  else
+    abi = "";
+
+  return build_string_literal (strlen (abi) + 1, abi);
+}
+
+/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
+
+void
+s390_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "floatAbi", s390_d_handle_target_float_abi },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
diff --git a/gcc/config/sol2-d.c b/gcc/config/sol2-d.c
index 27068f83082..dc542b4d5ee 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/config/sparc/sparc-d.c b/gcc/config/sparc/sparc-d.c
index 53163c6f32e..f28693ff652 100644
--- a/gcc/config/sparc/sparc-d.c
+++ b/gcc/config/sparc/sparc-d.c
@@ -46,3 +46,31 @@ sparc_d_target_versions (void)
       d_add_builtin_version ("SPARC_SoftFloat");
     }
 }
+
+/* Handle a call to `__traits(getTargetInfo, "floatAbi")'.  */
+
+static tree
+sparc_d_handle_target_float_abi (void)
+{
+  const char *abi;
+
+  if (TARGET_FPU)
+    abi = "hard";
+  else
+    abi = "soft";
+
+  return build_string_literal (strlen (abi) + 1, abi);
+}
+
+/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
+
+void
+sparc_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "floatAbi", sparc_d_handle_target_float_abi },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc
index 72e2d3a7168..b599931ae52 100644
--- a/gcc/d/d-builtins.cc
+++ b/gcc/d/d-builtins.cc
@@ -332,11 +332,12 @@ build_frontend_type (tree type)
 }
 
 /* Attempt to convert GCC evaluated CST to a D Frontend Expression.
+   LOC is the location in the source file where this CST is being evaluated.
    This is used for getting the CTFE value out of a const-folded builtin,
    returns NULL if it cannot convert CST.  */
 
 Expression *
-d_eval_constant_expression (tree cst)
+d_eval_constant_expression (const Loc &loc, tree cst)
 {
   STRIP_TYPE_NOPS (cst);
   Type *type = build_frontend_type (TREE_TYPE (cst));
@@ -353,23 +354,23 @@ d_eval_constant_expression (tree cst)
 	  real_value re = TREE_REAL_CST (TREE_REALPART (cst));
 	  real_value im = TREE_REAL_CST (TREE_IMAGPART (cst));
 	  complex_t value = complex_t (ldouble (re), ldouble (im));
-	  return ComplexExp::create (Loc (), value, type);
+	  return ComplexExp::create (loc, value, type);
 	}
       else if (code == INTEGER_CST)
 	{
 	  dinteger_t value = TREE_INT_CST_LOW (cst);
-	  return IntegerExp::create (Loc (), value, type);
+	  return IntegerExp::create (loc, value, type);
 	}
       else if (code == REAL_CST)
 	{
 	  real_value value = TREE_REAL_CST (cst);
-	  return RealExp::create (Loc (), ldouble (value), type);
+	  return RealExp::create (loc, ldouble (value), type);
 	}
       else if (code == STRING_CST)
 	{
 	  const void *string = TREE_STRING_POINTER (cst);
 	  size_t len = TREE_STRING_LENGTH (cst);
-	  return StringExp::create (Loc (), CONST_CAST (void *, string), len);
+	  return StringExp::create (loc, CONST_CAST (void *, string), len);
 	}
       else if (code == VECTOR_CST)
 	{
@@ -380,17 +381,31 @@ d_eval_constant_expression (tree cst)
 	  for (size_t i = 0; i < nunits; i++)
 	    {
 	      Expression *elem
-		= d_eval_constant_expression (VECTOR_CST_ELT (cst, i));
+		= d_eval_constant_expression (loc, VECTOR_CST_ELT (cst, i));
 	      if (elem == NULL)
 		return NULL;
 
 	      (*elements)[i] = elem;
 	    }
 
-	  Expression *e = ArrayLiteralExp::create (Loc (), elements);
+	  Expression *e = ArrayLiteralExp::create (loc, elements);
 	  e->type = type->isTypeVector ()->basetype;
 
-	  return VectorExp::create (Loc (), e, type);
+	  return VectorExp::create (loc, e, type);
+	}
+      else if (code == ADDR_EXPR)
+	{
+	  /* Special handling for trees constructed by build_string_literal.
+	     What we receive is an `&"string"[0]' expression, strip off the
+	     outer ADDR_EXPR and ARRAY_REF to get to the underlying CST.  */
+	  tree pointee = TREE_OPERAND (cst, 0);
+
+	  if (TREE_CODE (pointee) != ARRAY_REF
+	      || TREE_OPERAND (pointee, 1) != integer_zero_node
+	      || TREE_CODE (TREE_OPERAND (pointee, 0)) != STRING_CST)
+	    return NULL;
+
+	  return d_eval_constant_expression (loc, TREE_OPERAND (pointee, 0));
 	}
     }
 
diff --git a/gcc/d/d-compiler.cc b/gcc/d/d-compiler.cc
index ffa7f78c82e..f737d8d9686 100644
--- a/gcc/d/d-compiler.cc
+++ b/gcc/d/d-compiler.cc
@@ -133,7 +133,7 @@ Compiler::paintAsType (UnionExp *, Expression *expr, Type *type)
 
       cst = native_interpret_expr (vectype, buffer, len);
 
-      Expression *e = d_eval_constant_expression (cst);
+      Expression *e = d_eval_constant_expression (expr->loc, cst);
       gcc_assert (e != NULL && e->op == TOKvector);
 
       return e->isVectorExp ()->e1;
@@ -143,7 +143,7 @@ Compiler::paintAsType (UnionExp *, Expression *expr, Type *type)
       /* Normal interpret cast.  */
       cst = native_interpret_expr (build_ctype (type), buffer, len);
 
-      Expression *e = d_eval_constant_expression (cst);
+      Expression *e = d_eval_constant_expression (expr->loc, cst);
       gcc_assert (e != NULL);
 
       return e;
diff --git a/gcc/d/d-frontend.cc b/gcc/d/d-frontend.cc
index da34e902275..91335307150 100644
--- a/gcc/d/d-frontend.cc
+++ b/gcc/d/d-frontend.cc
@@ -195,7 +195,7 @@ eval_builtin (Loc loc, FuncDeclaration *fd, Expressions *arguments)
   /* Builtin should be successfully evaluated.
      Will only return NULL if we can't convert it.  */
   if (TREE_CONSTANT (result) && TREE_CODE (result) != CALL_EXPR)
-    e = d_eval_constant_expression (result);
+    e = d_eval_constant_expression (loc, result);
 
   return e;
 }
diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index cd136524eb9..5424ad0ae28 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -44,6 +44,25 @@ along with GCC; see the file COPYING3.  If not see
 
 Target target;
 
+/* Table `__traits(getTargetInfo)' keys.  */
+static vec<d_target_info_spec> target_info_table;
+
+/* Internal key handlers for `__traits(getTargetInfo)'.  */
+static tree d_handle_target_cpp_std (void);
+static tree d_handle_target_cpp_runtime_library (void);
+
+/* In [traits/getTargetInfo], a reliable subset of getTargetInfo keys exists
+   which are always available.  */
+static const struct d_target_info_spec d_language_target_info[] =
+{
+  /* { name, handler } */
+    { "cppStd", d_handle_target_cpp_std },
+    { "cppRuntimeLibrary", d_handle_target_cpp_runtime_library },
+    { "floatAbi", NULL },
+    { "objectFormat", NULL },
+    { NULL, NULL },
+};
+
 
 /* Initialize the floating-point constants for TYPE.  */
 
@@ -167,6 +186,12 @@ Target::_init (const Param &)
   real_convert (&CTFloat::one.rv (), mode, &dconst1);
   real_convert (&CTFloat::minusone.rv (), mode, &dconstm1);
   real_convert (&CTFloat::half.rv (), mode, &dconsthalf);
+
+  /* Initialize target info tables, the keys required by the language are added
+     last, so that the OS and CPU handlers can override.  */
+  targetdm.d_register_cpu_target_info ();
+  targetdm.d_register_os_target_info ();
+  d_add_target_info_handlers (d_language_target_info);
 }
 
 /* Return GCC memory alignment size for type TYPE.  */
@@ -413,3 +438,68 @@ Target::toArgTypes (Type *)
   /* Not implemented, however this is not currently used anywhere.  */
   return NULL;
 }
+
+
+/* Add all target info in HANDLERS to TARGET_INFO_TABLE for use by
+   Target::getTargetInfo().  */
+
+void
+d_add_target_info_handlers (const d_target_info_spec *handlers)
+{
+  gcc_assert (handlers != NULL);
+
+  if (target_info_table.is_empty ())
+    target_info_table.create (8);
+
+  for (size_t i = 0; handlers[i].name != NULL; i++)
+    target_info_table.safe_push (handlers[i]);
+}
+
+/* Handle a call to `__traits(getTargetInfo, "cppStd")'.  */
+
+tree
+d_handle_target_cpp_std (void)
+{
+  return build_integer_cst (global.params.cplusplus);
+}
+
+/* Handle a call to `__traits(getTargetInfo, "cppRuntimeLibrary")'.  */
+
+tree
+d_handle_target_cpp_runtime_library (void)
+{
+  /* The driver only ever optionally links to libstdc++.  */
+  const char *libstdcxx = "libstdc++";
+  return build_string_literal (strlen (libstdcxx) + 1, libstdcxx);
+}
+
+/* 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.
+   LOC is the location to use for the returned expression.  */
+
+Expression *
+Target::getTargetInfo (const char *key, const Loc &loc)
+{
+  unsigned ix;
+  d_target_info_spec *spec;
+
+  FOR_EACH_VEC_ELT (target_info_table, ix, spec)
+    {
+      tree result;
+
+      if (strcmp (key, spec->name) != 0)
+	continue;
+
+      /* Get the requested information, or empty string if unhandled.  */
+      if (spec->handler)
+	result = (spec->handler) ();
+      else
+	result = build_string_literal (1, "");
+
+      gcc_assert (result);
+      return d_eval_constant_expression (loc, result);
+    }
+
+  return NULL;
+}
diff --git a/gcc/d/d-target.def b/gcc/d/d-target.def
index 728cba70335..4471d5155cc 100644
--- a/gcc/d/d-target.def
+++ b/gcc/d/d-target.def
@@ -46,6 +46,26 @@ relating to the target operating system.",
  void, (void),
  hook_void_void)
 
+/* getTargetInfo keys relating to the target CPU.  */
+DEFHOOK
+(d_register_cpu_target_info,
+ "Register all target information keys relating to the target CPU using the\n\
+function @code{d_add_target_info_handlers}, which takes a\n\
+@samp{struct d_target_info_spec} (defined in @file{d/d-target.h}).  The keys\n\
+added by this hook are made available at compile time by the\n\
+@code{__traits(getTargetInfo)} extension, the result is an expression\n\
+describing the requested target information.",
+ void, (void),
+ hook_void_void)
+
+/* getTargetInfo keys relating to the target OS.  */
+DEFHOOK
+(d_register_os_target_info,
+ "Same as @code{TARGET_D_CPU_TARGET_INFO}, but is used for keys relating to\n\
+the target operating system.",
+ void, (void),
+ hook_void_void)
+
 /* ModuleInfo section name and brackets.  */
 DEFHOOKPOD
 (d_minfo_section,
diff --git a/gcc/d/d-target.h b/gcc/d/d-target.h
index d4413e47c61..8d3d6545a1c 100644
--- a/gcc/d/d-target.h
+++ b/gcc/d/d-target.h
@@ -31,4 +31,19 @@ extern struct gcc_targetdm targetdm;
 /* Used by target to add predefined version idenditiers.  */
 extern void d_add_builtin_version (const char *);
 
+/* Structure describing a supported key for `__traits(getTargetInfo)' and a
+   function to handle it.  */
+struct d_target_info_spec
+{
+  /* The name of the key or NULL to mark the end of a table of keys.  */
+  const char *name;
+  /* Function to handle this key, the return value of the handler must be a CST.
+     This pointer may be NULL if no special handling is required, for instance,
+     the key must always be available according to the D language spec.  */
+  tree (*handler) ();
+};
+
+/* Used by target to add getTargetInfo handlers.  */
+extern void d_add_target_info_handlers (const d_target_info_spec *);
+
 #endif /* GCC_D_TARGET_H  */
diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h
index 31fe5181912..f5cf9d3f214 100644
--- a/gcc/d/d-tree.h
+++ b/gcc/d/d-tree.h
@@ -496,7 +496,7 @@ extern void d_init_builtins (void);
 extern void d_register_builtin_type (tree, const char *);
 extern void d_build_builtins_module (Module *);
 extern void d_maybe_set_builtin (Module *);
-extern Expression *d_eval_constant_expression (tree);
+extern Expression *d_eval_constant_expression (const Loc &, tree);
 extern void d_init_versions (void);
 
 /* In d-codegen.cc.  */
diff --git a/gcc/d/dmd/idgen.c b/gcc/d/dmd/idgen.c
index 16f3b5f29ec..316c5e3b0dd 100644
--- a/gcc/d/dmd/idgen.c
+++ b/gcc/d/dmd/idgen.c
@@ -360,6 +360,7 @@ Msgtable msgtable[] =
     { "getUnitTests", NULL },
     { "getVirtualIndex", NULL },
     { "getPointerBitmap", NULL },
+    { "getTargetInfo", NULL },
 
     // For C++ mangling
     { "allocator", NULL },
diff --git a/gcc/d/dmd/target.h b/gcc/d/dmd/target.h
index f2a55d6a134..20b505220e7 100644
--- a/gcc/d/dmd/target.h
+++ b/gcc/d/dmd/target.h
@@ -105,6 +105,7 @@ public:
     // ABI and backend.
     LINK systemLinkage();
     TypeTuple *toArgTypes(Type *t);
+    Expression *getTargetInfo(const char* name, const Loc& loc);
 };
 
 extern Target target;
diff --git a/gcc/d/dmd/traits.c b/gcc/d/dmd/traits.c
index bc1e2c3c234..f859749be14 100644
--- a/gcc/d/dmd/traits.c
+++ b/gcc/d/dmd/traits.c
@@ -31,6 +31,7 @@
 #include "module.h"
 #include "attrib.h"
 #include "parse.h"
+#include "target.h"
 #include "root/speller.h"
 
 typedef int (*ForeachDg)(void *ctx, size_t idx, Dsymbol *s);
@@ -265,6 +266,7 @@ TraitsInitializer::TraitsInitializer()
         "getUnitTests",
         "getVirtualIndex",
         "getPointerBitmap",
+        "getTargetInfo",
         NULL
     };
 
@@ -1471,6 +1473,28 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
     {
         return pointerBitmap(e);
     }
+    else if (e->ident == Id::getTargetInfo)
+    {
+        if (dim != 1)
+            return dimError(e, 1, dim);
+
+        Expression *ex = isExpression((*e->args)[0]);
+        StringExp *se = ex ? ex->ctfeInterpret()->toStringExp() : NULL;
+        if (!ex || !se || se->len == 0)
+        {
+            e->error("string expected as argument of __traits `%s` instead of `%s`", e->ident->toChars(), ex->toChars());
+            return new ErrorExp();
+        }
+        se = se->toUTF8(sc);
+
+        Expression *r = target.getTargetInfo(se->toPtr(), e->loc);
+        if (!r)
+        {
+            e->error("`getTargetInfo` key `\"%s\"` not supported by this implementation", se->toPtr());
+            return new ErrorExp();
+        }
+        return semantic(r, sc);
+    }
 
     if (const char *sub = (const char *)speller(e->ident->toChars(), &trait_search_fp, NULL, idchars))
         e->error("unrecognized trait '%s', did you mean '%s'?", e->ident->toChars(), sub);
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 900d584d178..6874fafa48b 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -10804,6 +10804,20 @@ Similarly to @code{TARGET_D_CPU_VERSIONS}, but is used for versions
 relating to the target operating system.
 @end deftypefn
 
+@deftypefn {D Target Hook} void TARGET_D_REGISTER_CPU_TARGET_INFO (void)
+Register all target information keys relating to the target CPU using the
+function @code{d_add_target_info_handlers}, which takes a
+@samp{struct d_target_info_spec} (defined in @file{d/d-target.h}).  The keys
+added by this hook are made available at compile time by the
+@code{__traits(getTargetInfo)} extension, the result is an expression
+describing the requested target information.
+@end deftypefn
+
+@deftypefn {D Target Hook} void TARGET_D_REGISTER_OS_TARGET_INFO (void)
+Same as @code{TARGET_D_CPU_TARGET_INFO}, but is used for keys relating to
+the target operating system.
+@end deftypefn
+
 @deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_SECTION
 Contains the name of the section in which module info references should be
 placed.  This section is expected to be bracketed by two symbols to indicate
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index ad568581fd4..a14ae7780a5 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -7355,6 +7355,10 @@ floating-point support; they are not included in this mechanism.
 
 @hook TARGET_D_OS_VERSIONS
 
+@hook TARGET_D_REGISTER_CPU_TARGET_INFO
+
+@hook TARGET_D_REGISTER_OS_TARGET_INFO
+
 @hook TARGET_D_MINFO_SECTION
 
 @hook TARGET_D_MINFO_START_NAME
diff --git a/libphobos/libdruntime/core/sys/posix/setjmp.d b/libphobos/libdruntime/core/sys/posix/setjmp.d
index 38d4f7086f2..3f5cb2a8241 100644
--- a/libphobos/libdruntime/core/sys/posix/setjmp.d
+++ b/libphobos/libdruntime/core/sys/posix/setjmp.d
@@ -151,7 +151,8 @@ version (CRuntime_Glibc)
             c_long __pc;
             c_long[12] __regs;
             c_long __sp;
-            double[12] __fpregs;
+            static if (__traits(getTargetInfo, "floatAbi") == "double")
+                double[12] __fpregs;
         }
         alias __jmp_buf = __riscv_jmp_buf[1];
     }


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [gcc(refs/users/iains/heads/d-for-darwin)] d: Implement __traits(getTargetInfo)
@ 2020-12-13 17:43 Iain D Sandoe
  0 siblings, 0 replies; 6+ messages in thread
From: Iain D Sandoe @ 2020-12-13 17:43 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:4d952061d58d4cc69f1383b5c6159f07325893c8

commit 4d952061d58d4cc69f1383b5c6159f07325893c8
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Fri Dec 4 23:04:21 2020 +0100

    d: Implement __traits(getTargetInfo)

Diff:
---
 gcc/config/aarch64/aarch64-d.c                | 23 +++++++
 gcc/config/arm/arm-d.c                        | 53 +++++++++++++---
 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                      | 28 +++++++++
 gcc/config/i386/i386-protos.h                 |  1 +
 gcc/config/i386/i386.h                        |  3 +-
 gcc/config/mips/mips-d.c                      | 30 +++++++++
 gcc/config/netbsd-d.c                         | 26 ++++++++
 gcc/config/pa/pa-d.c                          | 28 +++++++++
 gcc/config/riscv/riscv-d.c                    | 46 ++++++++++++++
 gcc/config/rs6000/rs6000-d.c                  | 30 +++++++++
 gcc/config/s390/s390-d.c                      | 30 +++++++++
 gcc/config/sol2-d.c                           | 26 ++++++++
 gcc/config/sparc/sparc-d.c                    | 28 +++++++++
 gcc/d/d-builtins.cc                           | 31 ++++++---
 gcc/d/d-compiler.cc                           |  4 +-
 gcc/d/d-frontend.cc                           |  2 +-
 gcc/d/d-target.cc                             | 90 +++++++++++++++++++++++++++
 gcc/d/d-target.def                            | 20 ++++++
 gcc/d/d-target.h                              | 15 +++++
 gcc/d/d-tree.h                                |  2 +-
 gcc/d/dmd/idgen.c                             |  1 +
 gcc/d/dmd/target.h                            |  1 +
 gcc/d/dmd/traits.c                            | 24 +++++++
 gcc/doc/tm.texi                               | 14 +++++
 gcc/doc/tm.texi.in                            |  4 ++
 libphobos/libdruntime/core/sys/posix/setjmp.d |  3 +-
 30 files changed, 646 insertions(+), 21 deletions(-)

diff --git a/gcc/config/aarch64/aarch64-d.c b/gcc/config/aarch64/aarch64-d.c
index 69efd8df3d2..b01367a33ec 100644
--- a/gcc/config/aarch64/aarch64-d.c
+++ b/gcc/config/aarch64/aarch64-d.c
@@ -29,3 +29,26 @@ aarch64_d_target_versions (void)
   d_add_builtin_version ("AArch64");
   d_add_builtin_version ("D_HardFloat");
 }
+
+/* Handle a call to `__traits(getTargetInfo, "floatAbi")'.  */
+
+static tree
+aarch64_d_handle_target_float_abi (void)
+{
+  const char *abi = "hard";
+
+  return build_string_literal (strlen (abi) + 1, abi);
+}
+
+/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
+
+void
+aarch64_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "floatAbi", aarch64_d_handle_target_float_abi },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
diff --git a/gcc/config/arm/arm-d.c b/gcc/config/arm/arm-d.c
index e6c751c1e6c..138463e561b 100644
--- a/gcc/config/arm/arm-d.c
+++ b/gcc/config/arm/arm-d.c
@@ -36,18 +36,57 @@ arm_d_target_versions (void)
       d_add_builtin_version ("ARM_Thumb");
     }
 
-  if (TARGET_HARD_FLOAT_ABI)
+  if (arm_float_abi == ARM_FLOAT_ABI_HARD)
     d_add_builtin_version ("ARM_HardFloat");
-  else
-    {
-      if (TARGET_SOFT_FLOAT)
-	d_add_builtin_version ("ARM_SoftFloat");
-      else if (TARGET_HARD_FLOAT)
+  else if (arm_float_abi == ARM_FLOAT_ABI_SOFT)
+    d_add_builtin_version ("ARM_SoftFloat");
+  else if (arm_float_abi == ARM_FLOAT_ABI_SOFTFP)
 	d_add_builtin_version ("ARM_SoftFP");
-    }
 
   if (TARGET_SOFT_FLOAT)
     d_add_builtin_version ("D_SoftFloat");
   else if (TARGET_HARD_FLOAT)
     d_add_builtin_version ("D_HardFloat");
 }
+
+/* Handle a call to `__traits(getTargetInfo, "floatAbi")'.  */
+
+static tree
+arm_d_handle_target_float_abi (void)
+{
+  const char *abi;
+
+  switch (arm_float_abi)
+    {
+    case ARM_FLOAT_ABI_HARD:
+      abi = "hard";
+      break;
+
+    case ARM_FLOAT_ABI_SOFT:
+      abi = "soft";
+      break;
+
+    case ARM_FLOAT_ABI_SOFTFP:
+      abi = "softfp";
+      break;
+
+    default:
+      abi = "";
+      break;
+    }
+
+  return build_string_literal (strlen (abi) + 1, abi);
+}
+
+/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
+
+void
+arm_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "floatAbi", arm_d_handle_target_float_abi },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
diff --git a/gcc/config/darwin-d.c b/gcc/config/darwin-d.c
index ced07ce006a..7b8c72efe27 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 70ec820b75d..dac561e21d7 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 d79d82b5aa4..d8cf0dbab83 100644
--- a/gcc/config/freebsd-d.c
+++ b/gcc/config/freebsd-d.c
@@ -36,7 +36,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 7eb9e315f00..ca5bcc52dac 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 56fec11846e..9e40c2c2c66 100644
--- a/gcc/config/i386/i386-d.c
+++ b/gcc/config/i386/i386-d.c
@@ -42,3 +42,31 @@ ix86_d_target_versions (void)
   else
     d_add_builtin_version ("D_SoftFloat");
 }
+
+/* Handle a call to `__traits(getTargetInfo, "floatAbi")'.  */
+
+static tree
+ix86_d_handle_target_float_abi (void)
+{
+  const char *abi;
+
+  if (! (TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387))
+    abi = "soft";
+  else
+    abi = "hard";
+
+  return build_string_literal (strlen (abi) + 1, abi);
+}
+
+/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
+
+void
+ix86_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "floatAbi", ix86_d_handle_target_float_abi },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 65347a59b79..91bb77c6a4c 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -264,6 +264,7 @@ extern void ix86_register_pragmas (void);
 
 /* In i386-d.c  */
 extern void ix86_d_target_versions (void);
+extern void ix86_d_register_target_info (void);
 
 /* In winnt.c  */
 extern void i386_pe_unique_section (tree, int);
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index e88738ca873..3965ba861b3 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -799,8 +799,9 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
 /* Target Pragmas.  */
 #define REGISTER_TARGET_PRAGMAS() ix86_register_pragmas ()
 
-/* Target CPU versions for D.  */
+/* Target hooks for D language.  */
 #define TARGET_D_CPU_VERSIONS ix86_d_target_versions
+#define TARGET_D_REGISTER_CPU_TARGET_INFO ix86_d_register_target_info
 
 #ifndef CC1_SPEC
 #define CC1_SPEC "%(cc1_cpu) "
diff --git a/gcc/config/mips/mips-d.c b/gcc/config/mips/mips-d.c
index a9d4ba1f0b3..cd4f97a81d3 100644
--- a/gcc/config/mips/mips-d.c
+++ b/gcc/config/mips/mips-d.c
@@ -54,3 +54,33 @@ mips_d_target_versions (void)
       d_add_builtin_version ("D_SoftFloat");
     }
 }
+
+/* Handle a call to `__traits(getTargetInfo, "floatAbi")'.  */
+
+static tree
+mips_d_handle_target_float_abi (void)
+{
+  const char *abi;
+
+  if (TARGET_HARD_FLOAT_ABI)
+    abi = "hard";
+  else if (TARGET_SOFT_FLOAT_ABI)
+    abi = "soft";
+  else
+    abi = "";
+
+  return build_string_literal (strlen (abi) + 1, abi);
+}
+
+/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
+
+void
+mips_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "floatAbi", mips_d_handle_target_float_abi },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
diff --git a/gcc/config/netbsd-d.c b/gcc/config/netbsd-d.c
index 7c30d02b556..c7708edebff 100644
--- a/gcc/config/netbsd-d.c
+++ b/gcc/config/netbsd-d.c
@@ -33,7 +33,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/pa/pa-d.c b/gcc/config/pa/pa-d.c
index dda555858e3..b792985a623 100644
--- a/gcc/config/pa/pa-d.c
+++ b/gcc/config/pa/pa-d.c
@@ -37,3 +37,31 @@ pa_d_target_versions (void)
   else
     d_add_builtin_version ("D_HardFloat");
 }
+
+/* Handle a call to `__traits(getTargetInfo, "floatAbi")'.  */
+
+static tree
+pa_d_handle_target_float_abi (void)
+{
+  const char *abi;
+
+  if (TARGET_DISABLE_FPREGS || TARGET_SOFT_FLOAT)
+    abi = "soft";
+  else
+    abi = "hard";
+
+  return build_string_literal (strlen (abi) + 1, abi);
+}
+
+/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
+
+void
+pa_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "floatAbi", pa_d_handle_target_float_abi },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
diff --git a/gcc/config/riscv/riscv-d.c b/gcc/config/riscv/riscv-d.c
index 0fb08b49a30..34e7bc590a8 100644
--- a/gcc/config/riscv/riscv-d.c
+++ b/gcc/config/riscv/riscv-d.c
@@ -37,3 +37,49 @@ riscv_d_target_versions (void)
   else
     d_add_builtin_version ("D_SoftFloat");
 }
+
+/* Handle a call to `__traits(getTargetInfo, "floatAbi")'.  */
+
+static tree
+riscv_d_handle_target_float_abi (void)
+{
+  const char *abi;
+
+  switch (riscv_abi)
+    {
+    case ABI_ILP32E:
+    case ABI_ILP32:
+    case ABI_LP64:
+      abi = "soft";
+      break;
+
+    case ABI_ILP32F:
+    case ABI_LP64F:
+      abi = "single";
+      break;
+
+    case ABI_ILP32D:
+    case ABI_LP64D:
+      abi = "double";
+      break;
+
+    default:
+      abi = "";
+      break;
+    }
+
+  return build_string_literal (strlen (abi) + 1, abi);
+}
+
+/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
+
+void
+riscv_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "floatAbi", riscv_d_handle_target_float_abi },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
diff --git a/gcc/config/rs6000/rs6000-d.c b/gcc/config/rs6000/rs6000-d.c
index fd16e80aafd..d503a838c21 100644
--- a/gcc/config/rs6000/rs6000-d.c
+++ b/gcc/config/rs6000/rs6000-d.c
@@ -43,3 +43,33 @@ rs6000_d_target_versions (void)
       d_add_builtin_version ("D_SoftFloat");
     }
 }
+
+/* Handle a call to `__traits(getTargetInfo, "floatAbi")'.  */
+
+static tree
+rs6000_d_handle_target_float_abi (void)
+{
+  const char *abi;
+
+  if (TARGET_HARD_FLOAT)
+    abi = "hard";
+  else if (TARGET_SOFT_FLOAT)
+    abi = "soft";
+  else
+    abi = "";
+
+  return build_string_literal (strlen (abi) + 1, abi);
+}
+
+/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
+
+void
+rs6000_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "floatAbi", rs6000_d_handle_target_float_abi },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
diff --git a/gcc/config/s390/s390-d.c b/gcc/config/s390/s390-d.c
index 5a70e066e00..375c06a632a 100644
--- a/gcc/config/s390/s390-d.c
+++ b/gcc/config/s390/s390-d.c
@@ -39,3 +39,33 @@ s390_d_target_versions (void)
   else if (TARGET_HARD_FLOAT)
     d_add_builtin_version ("D_HardFloat");
 }
+
+/* Handle a call to `__traits(getTargetInfo, "floatAbi")'.  */
+
+static tree
+s390_d_handle_target_float_abi (void)
+{
+  const char *abi;
+
+  if (TARGET_HARD_FLOAT)
+    abi = "hard";
+  else if (TARGET_SOFT_FLOAT)
+    abi = "soft";
+  else
+    abi = "";
+
+  return build_string_literal (strlen (abi) + 1, abi);
+}
+
+/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
+
+void
+s390_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "floatAbi", s390_d_handle_target_float_abi },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
diff --git a/gcc/config/sol2-d.c b/gcc/config/sol2-d.c
index 27068f83082..dc542b4d5ee 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/config/sparc/sparc-d.c b/gcc/config/sparc/sparc-d.c
index 53163c6f32e..f28693ff652 100644
--- a/gcc/config/sparc/sparc-d.c
+++ b/gcc/config/sparc/sparc-d.c
@@ -46,3 +46,31 @@ sparc_d_target_versions (void)
       d_add_builtin_version ("SPARC_SoftFloat");
     }
 }
+
+/* Handle a call to `__traits(getTargetInfo, "floatAbi")'.  */
+
+static tree
+sparc_d_handle_target_float_abi (void)
+{
+  const char *abi;
+
+  if (TARGET_FPU)
+    abi = "hard";
+  else
+    abi = "soft";
+
+  return build_string_literal (strlen (abi) + 1, abi);
+}
+
+/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO.  */
+
+void
+sparc_d_register_target_info (void)
+{
+  const struct d_target_info_spec handlers[] = {
+    { "floatAbi", sparc_d_handle_target_float_abi },
+    { NULL, NULL },
+  };
+
+  d_add_target_info_handlers (handlers);
+}
diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc
index 72e2d3a7168..b599931ae52 100644
--- a/gcc/d/d-builtins.cc
+++ b/gcc/d/d-builtins.cc
@@ -332,11 +332,12 @@ build_frontend_type (tree type)
 }
 
 /* Attempt to convert GCC evaluated CST to a D Frontend Expression.
+   LOC is the location in the source file where this CST is being evaluated.
    This is used for getting the CTFE value out of a const-folded builtin,
    returns NULL if it cannot convert CST.  */
 
 Expression *
-d_eval_constant_expression (tree cst)
+d_eval_constant_expression (const Loc &loc, tree cst)
 {
   STRIP_TYPE_NOPS (cst);
   Type *type = build_frontend_type (TREE_TYPE (cst));
@@ -353,23 +354,23 @@ d_eval_constant_expression (tree cst)
 	  real_value re = TREE_REAL_CST (TREE_REALPART (cst));
 	  real_value im = TREE_REAL_CST (TREE_IMAGPART (cst));
 	  complex_t value = complex_t (ldouble (re), ldouble (im));
-	  return ComplexExp::create (Loc (), value, type);
+	  return ComplexExp::create (loc, value, type);
 	}
       else if (code == INTEGER_CST)
 	{
 	  dinteger_t value = TREE_INT_CST_LOW (cst);
-	  return IntegerExp::create (Loc (), value, type);
+	  return IntegerExp::create (loc, value, type);
 	}
       else if (code == REAL_CST)
 	{
 	  real_value value = TREE_REAL_CST (cst);
-	  return RealExp::create (Loc (), ldouble (value), type);
+	  return RealExp::create (loc, ldouble (value), type);
 	}
       else if (code == STRING_CST)
 	{
 	  const void *string = TREE_STRING_POINTER (cst);
 	  size_t len = TREE_STRING_LENGTH (cst);
-	  return StringExp::create (Loc (), CONST_CAST (void *, string), len);
+	  return StringExp::create (loc, CONST_CAST (void *, string), len);
 	}
       else if (code == VECTOR_CST)
 	{
@@ -380,17 +381,31 @@ d_eval_constant_expression (tree cst)
 	  for (size_t i = 0; i < nunits; i++)
 	    {
 	      Expression *elem
-		= d_eval_constant_expression (VECTOR_CST_ELT (cst, i));
+		= d_eval_constant_expression (loc, VECTOR_CST_ELT (cst, i));
 	      if (elem == NULL)
 		return NULL;
 
 	      (*elements)[i] = elem;
 	    }
 
-	  Expression *e = ArrayLiteralExp::create (Loc (), elements);
+	  Expression *e = ArrayLiteralExp::create (loc, elements);
 	  e->type = type->isTypeVector ()->basetype;
 
-	  return VectorExp::create (Loc (), e, type);
+	  return VectorExp::create (loc, e, type);
+	}
+      else if (code == ADDR_EXPR)
+	{
+	  /* Special handling for trees constructed by build_string_literal.
+	     What we receive is an `&"string"[0]' expression, strip off the
+	     outer ADDR_EXPR and ARRAY_REF to get to the underlying CST.  */
+	  tree pointee = TREE_OPERAND (cst, 0);
+
+	  if (TREE_CODE (pointee) != ARRAY_REF
+	      || TREE_OPERAND (pointee, 1) != integer_zero_node
+	      || TREE_CODE (TREE_OPERAND (pointee, 0)) != STRING_CST)
+	    return NULL;
+
+	  return d_eval_constant_expression (loc, TREE_OPERAND (pointee, 0));
 	}
     }
 
diff --git a/gcc/d/d-compiler.cc b/gcc/d/d-compiler.cc
index ffa7f78c82e..f737d8d9686 100644
--- a/gcc/d/d-compiler.cc
+++ b/gcc/d/d-compiler.cc
@@ -133,7 +133,7 @@ Compiler::paintAsType (UnionExp *, Expression *expr, Type *type)
 
       cst = native_interpret_expr (vectype, buffer, len);
 
-      Expression *e = d_eval_constant_expression (cst);
+      Expression *e = d_eval_constant_expression (expr->loc, cst);
       gcc_assert (e != NULL && e->op == TOKvector);
 
       return e->isVectorExp ()->e1;
@@ -143,7 +143,7 @@ Compiler::paintAsType (UnionExp *, Expression *expr, Type *type)
       /* Normal interpret cast.  */
       cst = native_interpret_expr (build_ctype (type), buffer, len);
 
-      Expression *e = d_eval_constant_expression (cst);
+      Expression *e = d_eval_constant_expression (expr->loc, cst);
       gcc_assert (e != NULL);
 
       return e;
diff --git a/gcc/d/d-frontend.cc b/gcc/d/d-frontend.cc
index da34e902275..91335307150 100644
--- a/gcc/d/d-frontend.cc
+++ b/gcc/d/d-frontend.cc
@@ -195,7 +195,7 @@ eval_builtin (Loc loc, FuncDeclaration *fd, Expressions *arguments)
   /* Builtin should be successfully evaluated.
      Will only return NULL if we can't convert it.  */
   if (TREE_CONSTANT (result) && TREE_CODE (result) != CALL_EXPR)
-    e = d_eval_constant_expression (result);
+    e = d_eval_constant_expression (loc, result);
 
   return e;
 }
diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index cd136524eb9..5424ad0ae28 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -44,6 +44,25 @@ along with GCC; see the file COPYING3.  If not see
 
 Target target;
 
+/* Table `__traits(getTargetInfo)' keys.  */
+static vec<d_target_info_spec> target_info_table;
+
+/* Internal key handlers for `__traits(getTargetInfo)'.  */
+static tree d_handle_target_cpp_std (void);
+static tree d_handle_target_cpp_runtime_library (void);
+
+/* In [traits/getTargetInfo], a reliable subset of getTargetInfo keys exists
+   which are always available.  */
+static const struct d_target_info_spec d_language_target_info[] =
+{
+  /* { name, handler } */
+    { "cppStd", d_handle_target_cpp_std },
+    { "cppRuntimeLibrary", d_handle_target_cpp_runtime_library },
+    { "floatAbi", NULL },
+    { "objectFormat", NULL },
+    { NULL, NULL },
+};
+
 
 /* Initialize the floating-point constants for TYPE.  */
 
@@ -167,6 +186,12 @@ Target::_init (const Param &)
   real_convert (&CTFloat::one.rv (), mode, &dconst1);
   real_convert (&CTFloat::minusone.rv (), mode, &dconstm1);
   real_convert (&CTFloat::half.rv (), mode, &dconsthalf);
+
+  /* Initialize target info tables, the keys required by the language are added
+     last, so that the OS and CPU handlers can override.  */
+  targetdm.d_register_cpu_target_info ();
+  targetdm.d_register_os_target_info ();
+  d_add_target_info_handlers (d_language_target_info);
 }
 
 /* Return GCC memory alignment size for type TYPE.  */
@@ -413,3 +438,68 @@ Target::toArgTypes (Type *)
   /* Not implemented, however this is not currently used anywhere.  */
   return NULL;
 }
+
+
+/* Add all target info in HANDLERS to TARGET_INFO_TABLE for use by
+   Target::getTargetInfo().  */
+
+void
+d_add_target_info_handlers (const d_target_info_spec *handlers)
+{
+  gcc_assert (handlers != NULL);
+
+  if (target_info_table.is_empty ())
+    target_info_table.create (8);
+
+  for (size_t i = 0; handlers[i].name != NULL; i++)
+    target_info_table.safe_push (handlers[i]);
+}
+
+/* Handle a call to `__traits(getTargetInfo, "cppStd")'.  */
+
+tree
+d_handle_target_cpp_std (void)
+{
+  return build_integer_cst (global.params.cplusplus);
+}
+
+/* Handle a call to `__traits(getTargetInfo, "cppRuntimeLibrary")'.  */
+
+tree
+d_handle_target_cpp_runtime_library (void)
+{
+  /* The driver only ever optionally links to libstdc++.  */
+  const char *libstdcxx = "libstdc++";
+  return build_string_literal (strlen (libstdcxx) + 1, libstdcxx);
+}
+
+/* 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.
+   LOC is the location to use for the returned expression.  */
+
+Expression *
+Target::getTargetInfo (const char *key, const Loc &loc)
+{
+  unsigned ix;
+  d_target_info_spec *spec;
+
+  FOR_EACH_VEC_ELT (target_info_table, ix, spec)
+    {
+      tree result;
+
+      if (strcmp (key, spec->name) != 0)
+	continue;
+
+      /* Get the requested information, or empty string if unhandled.  */
+      if (spec->handler)
+	result = (spec->handler) ();
+      else
+	result = build_string_literal (1, "");
+
+      gcc_assert (result);
+      return d_eval_constant_expression (loc, result);
+    }
+
+  return NULL;
+}
diff --git a/gcc/d/d-target.def b/gcc/d/d-target.def
index 728cba70335..4471d5155cc 100644
--- a/gcc/d/d-target.def
+++ b/gcc/d/d-target.def
@@ -46,6 +46,26 @@ relating to the target operating system.",
  void, (void),
  hook_void_void)
 
+/* getTargetInfo keys relating to the target CPU.  */
+DEFHOOK
+(d_register_cpu_target_info,
+ "Register all target information keys relating to the target CPU using the\n\
+function @code{d_add_target_info_handlers}, which takes a\n\
+@samp{struct d_target_info_spec} (defined in @file{d/d-target.h}).  The keys\n\
+added by this hook are made available at compile time by the\n\
+@code{__traits(getTargetInfo)} extension, the result is an expression\n\
+describing the requested target information.",
+ void, (void),
+ hook_void_void)
+
+/* getTargetInfo keys relating to the target OS.  */
+DEFHOOK
+(d_register_os_target_info,
+ "Same as @code{TARGET_D_CPU_TARGET_INFO}, but is used for keys relating to\n\
+the target operating system.",
+ void, (void),
+ hook_void_void)
+
 /* ModuleInfo section name and brackets.  */
 DEFHOOKPOD
 (d_minfo_section,
diff --git a/gcc/d/d-target.h b/gcc/d/d-target.h
index d4413e47c61..8d3d6545a1c 100644
--- a/gcc/d/d-target.h
+++ b/gcc/d/d-target.h
@@ -31,4 +31,19 @@ extern struct gcc_targetdm targetdm;
 /* Used by target to add predefined version idenditiers.  */
 extern void d_add_builtin_version (const char *);
 
+/* Structure describing a supported key for `__traits(getTargetInfo)' and a
+   function to handle it.  */
+struct d_target_info_spec
+{
+  /* The name of the key or NULL to mark the end of a table of keys.  */
+  const char *name;
+  /* Function to handle this key, the return value of the handler must be a CST.
+     This pointer may be NULL if no special handling is required, for instance,
+     the key must always be available according to the D language spec.  */
+  tree (*handler) ();
+};
+
+/* Used by target to add getTargetInfo handlers.  */
+extern void d_add_target_info_handlers (const d_target_info_spec *);
+
 #endif /* GCC_D_TARGET_H  */
diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h
index 31fe5181912..f5cf9d3f214 100644
--- a/gcc/d/d-tree.h
+++ b/gcc/d/d-tree.h
@@ -496,7 +496,7 @@ extern void d_init_builtins (void);
 extern void d_register_builtin_type (tree, const char *);
 extern void d_build_builtins_module (Module *);
 extern void d_maybe_set_builtin (Module *);
-extern Expression *d_eval_constant_expression (tree);
+extern Expression *d_eval_constant_expression (const Loc &, tree);
 extern void d_init_versions (void);
 
 /* In d-codegen.cc.  */
diff --git a/gcc/d/dmd/idgen.c b/gcc/d/dmd/idgen.c
index 16f3b5f29ec..316c5e3b0dd 100644
--- a/gcc/d/dmd/idgen.c
+++ b/gcc/d/dmd/idgen.c
@@ -360,6 +360,7 @@ Msgtable msgtable[] =
     { "getUnitTests", NULL },
     { "getVirtualIndex", NULL },
     { "getPointerBitmap", NULL },
+    { "getTargetInfo", NULL },
 
     // For C++ mangling
     { "allocator", NULL },
diff --git a/gcc/d/dmd/target.h b/gcc/d/dmd/target.h
index f2a55d6a134..20b505220e7 100644
--- a/gcc/d/dmd/target.h
+++ b/gcc/d/dmd/target.h
@@ -105,6 +105,7 @@ public:
     // ABI and backend.
     LINK systemLinkage();
     TypeTuple *toArgTypes(Type *t);
+    Expression *getTargetInfo(const char* name, const Loc& loc);
 };
 
 extern Target target;
diff --git a/gcc/d/dmd/traits.c b/gcc/d/dmd/traits.c
index bc1e2c3c234..f859749be14 100644
--- a/gcc/d/dmd/traits.c
+++ b/gcc/d/dmd/traits.c
@@ -31,6 +31,7 @@
 #include "module.h"
 #include "attrib.h"
 #include "parse.h"
+#include "target.h"
 #include "root/speller.h"
 
 typedef int (*ForeachDg)(void *ctx, size_t idx, Dsymbol *s);
@@ -265,6 +266,7 @@ TraitsInitializer::TraitsInitializer()
         "getUnitTests",
         "getVirtualIndex",
         "getPointerBitmap",
+        "getTargetInfo",
         NULL
     };
 
@@ -1471,6 +1473,28 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
     {
         return pointerBitmap(e);
     }
+    else if (e->ident == Id::getTargetInfo)
+    {
+        if (dim != 1)
+            return dimError(e, 1, dim);
+
+        Expression *ex = isExpression((*e->args)[0]);
+        StringExp *se = ex ? ex->ctfeInterpret()->toStringExp() : NULL;
+        if (!ex || !se || se->len == 0)
+        {
+            e->error("string expected as argument of __traits `%s` instead of `%s`", e->ident->toChars(), ex->toChars());
+            return new ErrorExp();
+        }
+        se = se->toUTF8(sc);
+
+        Expression *r = target.getTargetInfo(se->toPtr(), e->loc);
+        if (!r)
+        {
+            e->error("`getTargetInfo` key `\"%s\"` not supported by this implementation", se->toPtr());
+            return new ErrorExp();
+        }
+        return semantic(r, sc);
+    }
 
     if (const char *sub = (const char *)speller(e->ident->toChars(), &trait_search_fp, NULL, idchars))
         e->error("unrecognized trait '%s', did you mean '%s'?", e->ident->toChars(), sub);
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index d9b855c13ac..8e8475dfdd9 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -10801,6 +10801,20 @@ Similarly to @code{TARGET_D_CPU_VERSIONS}, but is used for versions
 relating to the target operating system.
 @end deftypefn
 
+@deftypefn {D Target Hook} void TARGET_D_REGISTER_CPU_TARGET_INFO (void)
+Register all target information keys relating to the target CPU using the
+function @code{d_add_target_info_handlers}, which takes a
+@samp{struct d_target_info_spec} (defined in @file{d/d-target.h}).  The keys
+added by this hook are made available at compile time by the
+@code{__traits(getTargetInfo)} extension, the result is an expression
+describing the requested target information.
+@end deftypefn
+
+@deftypefn {D Target Hook} void TARGET_D_REGISTER_OS_TARGET_INFO (void)
+Same as @code{TARGET_D_CPU_TARGET_INFO}, but is used for keys relating to
+the target operating system.
+@end deftypefn
+
 @deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_SECTION
 Contains the name of the section in which module info references should be
 placed.  This section is expected to be bracketed by two symbols to indicate
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index ad568581fd4..a14ae7780a5 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -7355,6 +7355,10 @@ floating-point support; they are not included in this mechanism.
 
 @hook TARGET_D_OS_VERSIONS
 
+@hook TARGET_D_REGISTER_CPU_TARGET_INFO
+
+@hook TARGET_D_REGISTER_OS_TARGET_INFO
+
 @hook TARGET_D_MINFO_SECTION
 
 @hook TARGET_D_MINFO_START_NAME
diff --git a/libphobos/libdruntime/core/sys/posix/setjmp.d b/libphobos/libdruntime/core/sys/posix/setjmp.d
index 38d4f7086f2..3f5cb2a8241 100644
--- a/libphobos/libdruntime/core/sys/posix/setjmp.d
+++ b/libphobos/libdruntime/core/sys/posix/setjmp.d
@@ -151,7 +151,8 @@ version (CRuntime_Glibc)
             c_long __pc;
             c_long[12] __regs;
             c_long __sp;
-            double[12] __fpregs;
+            static if (__traits(getTargetInfo, "floatAbi") == "double")
+                double[12] __fpregs;
         }
         alias __jmp_buf = __riscv_jmp_buf[1];
     }


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-10-18 15:54 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-15 19:33 [gcc(refs/users/iains/heads/d-for-darwin)] d: Implement __traits(getTargetInfo) Iain D Sandoe
  -- strict thread matches above, loose matches on Subject: below --
2021-10-18 15:54 Iain D Sandoe
2021-10-13  8:30 Iain D Sandoe
2021-10-11 20:34 Iain D Sandoe
2020-12-21 20:36 Iain D Sandoe
2020-12-13 17:43 Iain D Sandoe

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).