From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Andreas Kling <awesomekling@gmail.com>
Date: Fri, 5 Apr 2019 03:02:52 +0200
Subject: [PATCH] Add a gcc driver for Minerva

This patch adds support for the `*-*-minerva` target to gcc.

It specifies which flags need to be passed to the linker, defines the
__minerva__ macro, sets the correct underlying type of `size_t` and
`ptrdiff_t`, and enables IFUNCs.

Co-Authored-By: Gunnar Beutner <gbeutner@serenityos.org>
Co-Authored-By: Itamar <itamar8910@gmail.com>
Co-Authored-By: Daniel Bertalan <dani@danielbertalan.dev>
Co-Authored-By: Nico Weber <thakis@chromium.org>
Co-Authored-By: Tim Schumacher <timschumi@gmx.de>
Co-Authored-By: Andrew Kaster <andrewdkaster@gmail.com>
Co-Authored-By: Brian Gianforcaro <bgianf@serenityos.org>
Co-Authored-By: Philip Herron <herron.philip@googlemail.com>
Co-Authored-By: Shannon Booth <shannon@serenityos.org>
---
 gcc/config.gcc               | 23 +++++++++++++++++
 gcc/config.host              |  2 +-
 gcc/config/i386/minerva.h   |  7 +++++
 gcc/config/minerva.h        | 50 ++++++++++++++++++++++++++++++++++++
 gcc/config/minerva.opt      | 35 +++++++++++++++++++++++++
 gcc/config/minerva.opt.urls |  1 +
 6 files changed, 117 insertions(+), 1 deletion(-)
 create mode 100644 gcc/config/i386/minerva.h
 create mode 100644 gcc/config/minerva.h
 create mode 100644 gcc/config/minerva.opt
 create mode 100644 gcc/config/minerva.opt.urls

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 40b50dc969ede4418b305ca01869ec157e054283..550573f66da4982f21334a16157220c6b3bca81f 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -723,6 +723,18 @@ x86_cpus="generic intel"
 
 # Common parts for widely ported systems.
 case ${target} in
+*-*-minerva*)
+  gas=yes
+  gnu_ld=yes
+  default_use_cxa_atexit=yes
+  extra_options="${extra_options} minerva.opt"
+  tmake_file="t-slibgcc"
+  case ${target} in
+    aarch64*-* | riscv64-* | x86_64-*)
+      default_gnu_indirect_function=yes
+      ;;
+  esac
+  ;;
 *-*-darwin*)
   tmake_file="t-darwin "
   tm_file="${tm_file} darwin.h"
@@ -1186,6 +1198,17 @@ case ${target} in
 esac
 
 case ${target} in
+x86_64-*-minerva*)
+	tm_file="${tm_file} i386/unix.h i386/att.h elfos.h glibc-stdint.h i386/i386elf.h i386/x86-64.h minerva.h i386/minerva.h"
+	;;
+aarch64*-*-minerva*)
+	tm_file="${tm_file} elfos.h glibc-stdint.h aarch64/aarch64-elf.h minerva.h"
+	tmake_file="${tmake_file} aarch64/t-aarch64"
+	;;
+riscv64-*-minerva*)
+	tm_file="${tm_file} elfos.h glibc-stdint.h riscv/elf.h minerva.h"
+	tmake_file="${tmake_file} riscv/t-riscv"
+	;;
 aarch64*-*-elf | aarch64*-*-fuchsia* | aarch64*-*-rtems*)
 	tm_file="${tm_file} elfos.h newlib-stdint.h"
 	tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-errata.h aarch64/aarch64-elf-raw.h"
diff --git a/gcc/config.host b/gcc/config.host
index 4c1a5e9910c8181a7dce9159da43139ec9accc8a..49128b1e2e791bdb810c74e9f6f5fd082f82e997 100644
--- a/gcc/config.host
+++ b/gcc/config.host
@@ -100,7 +100,7 @@ esac
 
 case ${host} in
   aarch64*-*-freebsd* | aarch64*-*-linux* | aarch64*-*-fuchsia* |\
-  aarch64*-*-darwin*)
+  aarch64*-*-darwin* | aarch64-*-minerva*)
     case ${target} in
       aarch64*-*-*)
 	host_extra_gcc_objs="driver-aarch64.o"
diff --git a/gcc/config/i386/minerva.h b/gcc/config/i386/minerva.h
new file mode 100644
index 0000000000000000000000000000000000000000..53a4b8e93b74b4808a4bfed91c4d5558217c584a
--- /dev/null
+++ b/gcc/config/i386/minerva.h
@@ -0,0 +1,7 @@
+/* Ensure that we are using the SIZE_TYPE indicated by SysV */
+#undef SIZE_TYPE
+#define SIZE_TYPE    (TARGET_64BIT ? "long unsigned int" : "unsigned int")
+
+/* Ensure that ptrdiff_t matches the actual pointer size */
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE    (TARGET_64BIT ? "long int" : "int")
diff --git a/gcc/config/minerva.h b/gcc/config/minerva.h
new file mode 100644
index 0000000000000000000000000000000000000000..7ee040c395e7bd404aa1f2b112e9248c556fca2a
--- /dev/null
+++ b/gcc/config/minerva.h
@@ -0,0 +1,50 @@
+/* Useful if you wish to make target-specific GCC changes. */
+#undef TARGET_MINERVA
+#define TARGET_MINERVA 1
+
+#if defined(HAVE_LD_EH_FRAME_HDR)
+#define LINK_EH_SPEC "%{!static|static-pie:--eh-frame-hdr} "
+#endif
+
+/* Default arguments you want when running your
+   x86_64-minerva-gcc toolchain */
+#undef LIB_SPEC
+#define LIB_SPEC "-lc" /* link against C standard library */
+
+/* Files that are linked before user code.
+   The %s tells GCC to look for these files in the library directory. */
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "%{!shared:crt0.o%s} crti.o%s %{shared: %{!fbuilding-libgcc:crt0_shared.o%s}} %{shared|static-pie|!no-pie:crtbeginS.o%s; :crtbegin.o%s}"
+
+/* Files that are linked after user code. */
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "%{shared|static-pie|!no-pie:crtendS.o%s; :crtend.o%s} crtn.o%s"
+
+#define TARGET_LIBC_PROVIDES_SSP
+
+#undef LINK_SPEC
+#define LINK_SPEC "%{shared:-shared} %{static:-static} %{!static: %{rdynamic:-export-dynamic} -dynamic-linker /usr/lib/Loader.so}"
+
+#undef CC1_SPEC
+#define CC1_SPEC "-fno-semantic-interposition"
+
+#undef CPP_SPEC
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
+
+/* Use --as-needed -lgcc_s for eh support. */
+#define USE_LD_AS_NEEDED 1
+
+/* We don't have a separate math library, it's included within libc. While we do have compatibility
+   linker scripts in place, just don't add it to the linker invocation to begin with. */
+#define MATH_LIBRARY ""
+
+/* Additional predefined macros. */
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS()      \
+  do {                                \
+    builtin_define ("__minerva__");      \
+    builtin_define ("__unix__");      \
+    builtin_assert ("system=minerva");   \
+    builtin_assert ("system=unix");   \
+    builtin_assert ("system=posix");   \
+  } while(0);
diff --git a/gcc/config/minerva.opt b/gcc/config/minerva.opt
new file mode 100644
index 0000000000000000000000000000000000000000..2756a5575480449a2c46b9fdfde541ba2787a263
--- /dev/null
+++ b/gcc/config/minerva.opt
@@ -0,0 +1,35 @@
+; Minerva options.
+
+; Copyright (C) 2021 Gunnar Beutner <gunnar@beutner.name>
+;
+; 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/>.
+
+; See the GCC internals manual (options.texi) for a description of
+; this file's format.
+
+; Please try to keep this file in ASCII collating order.
+
+posix
+Driver
+
+pthread
+Driver
+
+rdynamic
+Driver
+
+; This comment is to ensure we retain the blank line above.
diff --git a/gcc/config/minerva.opt.urls b/gcc/config/minerva.opt.urls
new file mode 100644
index 0000000000000000000000000000000000000000..3166f813b1464cfe71aeaa035ae1e3834f54df75
--- /dev/null
+++ b/gcc/config/minerva.opt.urls
@@ -0,0 +1 @@
+; Not sure what to put here but this works
