From 39ef29459c8f17471b769fb36adf413dd974447a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc=20Poulhi=C3=A8s?= <poulhies@adacore.com>
Date: Tue, 4 Jan 2022 14:56:27 +0000
Subject: [PATCH 16/18] Define GCC_DRIVER_HOST_INITIALIZATION for VxWorks
 targets

This change prepares the ground prior to the reintroduction of
shared libs support for VxWorks.

On this platform, the use of shared libraries involves unusual
steps compared to standard native systems and enforcing static
links by default improves user experience.

This change arranges for the driver to insert a '-static' option by
default for this purpose.

g++ makes choices depending on such options from its
lang_specific_driver, so our default needs to be conveyed before
that and specs aren't handled early enough.

We then proceed by defining a GCC_DRIVER_HOST_INITIALIZATION macro
for VxWorks, to insert a -static option in case the user hasn't provided
any explicit indication on the command line of the kind of link desired.

While a HOST macro doesn't seem appropriate to control a target OS
driven behavior, this matches other uses and won't conflict as VxWorks
is not supported on any of the other configurations using this macro,
and we expect at least warnings if a not a plain failure if a build
with conflicting definitions is attempted.

We have been using this in gcc-11 based production compilers for
a while. I have performed a couple of build+test cycles on gcc-12
for powerpc64-vxworks7r2 and powerpc-vxworks6.9, and did a sanity
checking build of all-gcc for arm-wrs-vxworks7r2.

2022-09-29  Marc Poulhies  <poulhies@adacore.com>
            Olivier Hainque  <hainque@adacore.com>

gcc/
	* config/vxwkorks/vxwkorks-driver.cc: New.
	* config.gcc (*vxwkorks*): Add vxworks-driver.o in extra_gcc_objs.
	* config/t-vxworks: Add vxworks-driver.o.
	* config/vxworks.h (GCC_DRIVER_HOST_INITIALIZATION): New.
---
 gcc/config.gcc               |  2 +
 gcc/config/t-vxworks         |  4 ++
 gcc/config/vxworks-driver.cc | 93 ++++++++++++++++++++++++++++++++++++
 gcc/config/vxworks.h         | 10 ++++
 4 files changed, 109 insertions(+)
 create mode 100644 gcc/config/vxworks-driver.cc

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 999969d06df..5984dbf6419 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -1021,6 +1021,8 @@ case ${target} in
   extra_headers="${extra_headers} ../vxworks/vxworks-predef.h"
   target_has_targetcm="yes"
 
+  extra_gcc_objs="vxworks-driver.o"
+
   # This private header exposes a consistent interface for checks on
   # the VxWorks version our runtime header files need to perform, based on
   # what the system headers adverstise:
diff --git a/gcc/config/t-vxworks b/gcc/config/t-vxworks
index 40c6cc4185b..dc97a4e0f30 100644
--- a/gcc/config/t-vxworks
+++ b/gcc/config/t-vxworks
@@ -16,6 +16,10 @@
 # along with GCC; see the file COPYING3.  If not see
 # <http://www.gnu.org/licenses/>.
 
+vxworks-driver.o: $(srcdir)/config/vxworks-driver.cc
+	$(COMPILE) $<
+	$(POSTCOMPILE)
+
 vxworks.o: $(srcdir)/config/vxworks.cc
 	$(COMPILE) $<
 	$(POSTCOMPILE)
diff --git a/gcc/config/vxworks-driver.cc b/gcc/config/vxworks-driver.cc
new file mode 100644
index 00000000000..da5f015f1de
--- /dev/null
+++ b/gcc/config/vxworks-driver.cc
@@ -0,0 +1,93 @@
+/* Copyright (C) 2022 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+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 "tm.h"
+#include "opts.h"
+
+/* Perform early driver flags initializations that can't be achieved
+   with specs.  In particular, we need to explicitly request a static
+   link for rtps by default before lang_specific_driver gets control.  */
+
+void vxworks_driver_init (unsigned int *in_decoded_options_count,
+			  struct cl_decoded_option **in_decoded_options)
+{
+  unsigned int i;
+  struct cl_decoded_option *decoded_options = *in_decoded_options;
+
+  /* Arrange to add -static if we are going to link a rtp and there is no
+     trace of any explicit request for a specific kind of link.  */
+  bool wont_link = false;
+  bool mrtp = false;
+  bool link_kind_indication = false;
+
+  /* The new argument list will be contained in this.  */
+  struct cl_decoded_option *new_decoded_options;
+  unsigned int num_options = *in_decoded_options_count;
+
+  for (i = 1; i < num_options; i++)
+    {
+      if (decoded_options[i].errors & CL_ERR_MISSING_ARG)
+	continue;
+
+      switch (decoded_options[i].opt_index)
+	{
+	case OPT_static:
+	case OPT_shared:
+	case OPT_Bdynamic:
+	case OPT_Bstatic:
+	case OPT_non_static:
+	  link_kind_indication = true;
+	  break;
+
+	case OPT_c:
+	case OPT_r:
+	case OPT_S:
+	case OPT_E:
+	case OPT_M:
+	case OPT_MM:
+	case OPT_fsyntax_only:
+	  wont_link = true;
+	  break;
+
+	case OPT_mrtp:
+	  mrtp = true;
+	  break;
+
+	default:
+	  break;
+      }
+    }
+
+  if (!wont_link && mrtp && !link_kind_indication)
+    {
+      num_options++;
+      new_decoded_options = XNEWVEC(struct cl_decoded_option, num_options);
+
+      for (i = 0; i < num_options - 1; i++)
+	new_decoded_options[i] = decoded_options[i];
+
+      generate_option(OPT_static, NULL, 1, CL_DRIVER,
+		      &new_decoded_options[num_options - 1]);
+
+      *in_decoded_options = new_decoded_options;
+      *in_decoded_options_count = num_options;
+    }
+}
diff --git a/gcc/config/vxworks.h b/gcc/config/vxworks.h
index 13c616829c4..e7e5ffe9999 100644
--- a/gcc/config/vxworks.h
+++ b/gcc/config/vxworks.h
@@ -28,6 +28,16 @@ along with GCC; see the file COPYING3.  If not see
 #undef TARGET_VXWORKS
 #define TARGET_VXWORKS 1
 
+/* ??? Even though assigned to a HOST driver hook, this function
+   operates for all vxworks targets regardless of the current host.
+   We will get warnings at build time if the macro happens to be
+   redefined one way or another for a host.  */
+struct cl_decoded_option;
+extern void vxworks_driver_init (unsigned int *, struct cl_decoded_option **);
+
+#define GCC_DRIVER_HOST_INITIALIZATION \
+        vxworks_driver_init (&decoded_options_count, &decoded_options)
+
 /* In kernel mode, VxWorks provides all the libraries itself, as well as
    the functionality of startup files, etc.  In RTP mode, it behaves more
    like a traditional Unix, with more external files.  Most of our specs
-- 
2.25.1

