@@ -573,6 +573,8 @@ tm_p_file_list=@tm_p_file_list@
tm_p_include_list=@tm_p_include_list@
tm_d_file_list=@tm_d_file_list@
tm_d_include_list=@tm_d_include_list@
+tm_rust_file_list=@tm_rust_file_list@
+tm_rust_include_list=@tm_rust_include_list@
build_xm_file_list=@build_xm_file_list@
build_xm_include_list=@build_xm_include_list@
build_xm_defines=@build_xm_defines@
@@ -866,6 +868,7 @@ CONFIG_H = config.h $(host_xm_file_list)
TCONFIG_H = tconfig.h $(xm_file_list)
TM_P_H = tm_p.h $(tm_p_file_list)
TM_D_H = tm_d.h $(tm_d_file_list)
+TM_RUST_H = tm_rust.h $(tm_rust_file_list)
GTM_H = tm.h $(tm_file_list) insn-constants.h
TM_H = $(GTM_H) insn-flags.h $(OPTIONS_H)
@@ -928,6 +931,7 @@ TARGET_H = $(TM_H) target.h $(TARGET_DEF) insn-modes.h insn-codes.h
C_TARGET_H = c-family/c-target.h $(C_TARGET_DEF)
COMMON_TARGET_H = common/common-target.h $(INPUT_H) $(COMMON_TARGET_DEF)
D_TARGET_H = d/d-target.h $(D_TARGET_DEF)
+RUST_TARGET_H = rust/rust-target.h $(RUST_TARGET_DEF)
MACHMODE_H = machmode.h mode-classes.def
HOOKS_H = hooks.h
HOSTHOOKS_DEF_H = hosthooks-def.h $(HOOKS_H)
@@ -1228,6 +1232,9 @@ CXX_TARGET_OBJS=@cxx_target_objs@
# Target specific, D specific object file
D_TARGET_OBJS=@d_target_objs@
+# Target specific, Rust specific object file
+RUST_TARGET_OBJS=@rust_target_objs@
+
# Target specific, Fortran specific object file
FORTRAN_TARGET_OBJS=@fortran_target_objs@
@@ -1937,6 +1944,7 @@ tconfig.h: cs-tconfig.h ; @true
tm.h: cs-tm.h ; @true
tm_p.h: cs-tm_p.h ; @true
tm_d.h: cs-tm_d.h ; @true
+tm_rust.h: cs-tm_rust.h ; @true
cs-config.h: Makefile
TARGET_CPU_DEFAULT="" \
@@ -1968,6 +1976,11 @@ cs-tm_d.h: Makefile
HEADERS="$(tm_d_include_list)" DEFINES="" \
$(SHELL) $(srcdir)/mkconfig.sh tm_d.h
+cs-tm_rust.h: Makefile
+ TARGET_CPU_DEFAULT="" \
+ HEADERS="$(tm_rust_include_list)" DEFINES="" \
+ $(SHELL) $(srcdir)/mkconfig.sh tm_rust.h
+
# Don't automatically run autoconf, since configure.ac might be accidentally
# newer than configure. Also, this writes into the source directory which
# might be on a read-only file system. If configured for maintainer mode
@@ -2304,6 +2317,12 @@ default-d.o: config/default-d.cc
$(COMPILE) $<
$(POSTCOMPILE)
+# Files used by the Rust language front end.
+
+default-rust.o: config/default-rust.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
# Language-independent files.
DRIVER_DEFINES = \
@@ -2609,6 +2628,15 @@ s-d-target-hooks-def-h: build/genhooks$(build_exeext)
d/d-target-hooks-def.h
$(STAMP) s-d-target-hooks-def-h
+rust/rust-target-hooks-def.h: s-rust-target-hooks-def-h; @true
+
+s-rust-target-hooks-def-h: build/genhooks$(build_exeext)
+ $(RUN_GEN) build/genhooks$(build_exeext) "Rust Target Hook" \
+ > tmp-rust-target-hooks-def.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-rust-target-hooks-def.h \
+ rust/rust-target-hooks-def.h
+ $(STAMP) s-rust-target-hooks-def-h
+
# check if someone mistakenly only changed tm.texi.
# We use a different pathname here to avoid a circular dependency.
s-tm-texi: $(srcdir)/doc/../doc/tm.texi
@@ -2633,6 +2661,7 @@ s-tm-texi: build/genhooks$(build_exeext) $(srcdir)/doc/tm.texi.in
|| test $(srcdir)/doc/tm.texi -nt $(srcdir)/c-family/c-target.def \
|| test $(srcdir)/doc/tm.texi -nt $(srcdir)/common/common-target.def \
|| test $(srcdir)/doc/tm.texi -nt $(srcdir)/d/d-target.def \
+ || test $(srcdir)/doc/tm.texi -nt $(srcdir)/rust/rust-target.def \
); then \
echo >&2 ; \
echo You should edit $(srcdir)/doc/tm.texi.in rather than $(srcdir)/doc/tm.texi . >&2 ; \
@@ -2782,8 +2811,8 @@ s-gtype: $(EXTRA_GTYPE_DEPS) build/gengtype$(build_exeext) \
-r gtype.state
$(STAMP) s-gtype
-generated_files = config.h tm.h $(TM_P_H) $(TM_D_H) $(TM_H) multilib.h \
- $(simple_generated_h) specs.h \
+generated_files = config.h tm.h $(TM_P_H) $(TM_D_H) $(TM_RUST_H) $(TM_H) multilib.h \
+ $(simple_generated_h) specs.h \
tree-check.h genrtl.h insn-modes.h insn-modes-inline.h \
tm-preds.h tm-constrs.h \
$(ALL_GTFILES_H) gtype-desc.cc gtype-desc.h version.h \
@@ -2791,7 +2820,7 @@ generated_files = config.h tm.h $(TM_P_H) $(TM_D_H) $(TM_H) multilib.h \
common/common-target-hooks-def.h pass-instances.def \
gimple-match.cc generic-match.cc \
c-family/c-target-hooks-def.h d/d-target-hooks-def.h \
- case-cfn-macros.h \
+ rust/rust-target-hooks-def.h case-cfn-macros.h \
cfn-operators.pd omp-device-properties.h
#
@@ -90,6 +90,9 @@
# tm_d_file A list of headers with definitions of target hook
# macros for the D compiler.
#
+# tm_rust_file A list of headers with definitions of target hook
+# macros for the Rust compiler.
+#
# out_file The name of the machine description C support
# file, if different from "$cpu_type/$cpu_type.c".
#
@@ -146,6 +149,9 @@
# d_target_objs List of extra target-dependent objects that be
# linked into the D compiler only.
#
+# rust_target_objs List of extra target-dependent objects that be
+# linked into the Rust compiler only.
+#
# fortran_target_objs List of extra target-dependent objects that be
# linked into the fortran compiler only.
#
@@ -201,6 +207,9 @@
#
# target_has_targetdm Set to yes or no depending on whether the target
# has its own definition of targetdm.
+#
+# target_has_targetrustm Set to yes or no depending on whether the target
+# has its own definition of targetrustm.
out_file=
common_out_file=
@@ -217,6 +226,7 @@ extra_options=
c_target_objs=
cxx_target_objs=
d_target_objs=
+rust_target_objs=
fortran_target_objs=
target_has_targetcm=no
target_has_targetm_common=yes
@@ -391,6 +401,7 @@ i[34567]86-*-* | x86_64-*-*)
c_target_objs="i386-c.o"
cxx_target_objs="i386-c.o"
d_target_objs="i386-d.o"
+ rust_target_objs="i386-rust.o"
extra_objs="x86-tune-sched.o x86-tune-sched-bd.o x86-tune-sched-atom.o x86-tune-sched-core.o i386-options.o i386-builtins.o i386-expand.o i386-features.o"
target_gtfiles="\$(srcdir)/config/i386/i386-builtins.cc \$(srcdir)/config/i386/i386-expand.cc \$(srcdir)/config/i386/i386-options.cc"
extra_options="${extra_options} fused-madd.opt"
@@ -560,10 +571,12 @@ esac
tm_file=${cpu_type}/${cpu_type}.h
tm_d_file=${cpu_type}/${cpu_type}.h
+tm_rust_file=${cpu_type}/${cpu_type}.h
if test -f ${srcdir}/config/${cpu_type}/${cpu_type}-protos.h
then
tm_p_file=${cpu_type}/${cpu_type}-protos.h
tm_d_file="${tm_d_file} ${cpu_type}/${cpu_type}-protos.h"
+ tm_rust_file="${tm_rust_file} ${cpu_type}/${cpu_type}-protos.h"
fi
extra_modes=
@@ -3626,6 +3639,10 @@ if [ "$target_has_targetdm" = "no" ]; then
d_target_objs="$d_target_objs default-d.o"
fi
+if [ "$target_has_targetrustm" = "no" ]; then
+ rust_target_objs="$rust_target_objs default-rust.o"
+fi
+
# Support for --with-cpu and related options (and a few unrelated options,
# too).
case ${with_cpu} in
new file mode 100644
@@ -0,0 +1,26 @@
+/* Default Rust language target hooks initializer.
+ Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "memmodel.h"
+#include "tm_rust.h"
+#include "rust/rust-target.h"
+#include "rust/rust-target-def.h"
+
+struct gcc_targetrustm targetrustm = TARGETRUSTM_INITIALIZER;
@@ -35,6 +35,18 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
} \
while (0)
+#ifdef TARGET_RUST_OS_INFO
+# error "TARGET_RUST_OS_INFO already defined in dragonflybsd.h - c++ undefines it and redefines it."
+/* TODO: ensure that this works correctly and the undef and redef reason is known */
+#endif
+#define TARGET_RUST_OS_INFO() \
+ do { \
+ builtin_rust_info ("target_family", "unix"); \
+ builtin_rust_info ("target_os", "dragonfly"); \
+ builtin_rust_info ("target_vendor", "unknown"); \
+ builtin_rust_info ("target_env", ""); \
+ } while (0)
+
#undef CPP_SPEC
#define CPP_SPEC \
"%(cpp_cpu) %(cpp_arch) %{posix:-D_POSIX_SOURCE}"
@@ -49,6 +49,15 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* Define the default FreeBSD-specific per-CPU hook code. */
#define FBSD_TARGET_CPU_CPP_BUILTINS() do {} while (0)
+#define FBSD_TARGET_RUST_OS_INFO() \
+ do { \
+ builtin_rust_info ("target_family", "unix"); \
+ builtin_rust_info ("target_os", "freebsd"); \
+ builtin_rust_info ("target_vendor", "unknown"); \
+ builtin_rust_info ("target_env", ""); \
+ /*TODO: is default per-CPU hook code required here?*/ \
+ } while (0)
+
/* Provide a CPP_SPEC appropriate for FreeBSD. We just deal with the GCC
option `-posix', and PIC issues. */
@@ -32,6 +32,11 @@ along with GCC; see the file COPYING3. If not see
#undef TARGET_OS_CPP_BUILTINS
#define TARGET_OS_CPP_BUILTINS() FBSD_TARGET_OS_CPP_BUILTINS()
+#ifdef TARGET_RUST_OS_INFO
+# error "TARGET_RUST_OS_INFO already defined in freebsd.h - c++ undefines it and redefines it."
+#endif
+#define TARGET_RUST_OS_INFO() FBSD_TARGET_RUST_OS_INFO()
+
#undef CPP_SPEC
#define CPP_SPEC FBSD_CPP_SPEC
@@ -68,3 +68,19 @@ along with GCC; see the file COPYING3. If not see
} \
while (false)
+#ifndef EXTRA_TARGET_RUST_OS_INFO
+#define EXTRA_TARGET_RUST_OS_INFO()
+#endif
+
+#ifdef TARGET_RUST_OS_INFO
+# error "TARGET_RUST_OS_INFO already defined in fuchsia.h - c++ undefines it and redefines it."
+#endif
+#define TARGET_RUST_OS_INFO() \
+ do { \
+ builtin_rust_info ("target_family", "unix"); \
+ /*NOTE: target_family is subject to change if rustc decides to change it to non-unix*/ \
+ builtin_rust_info ("target_os", "fuchsia"); \
+ builtin_rust_info ("target_vendor", ""); \
+ builtin_rust_info ("target_env", ""); \
+ EXTRA_TARGET_RUST_OS_INFO(); \
+ } while (0)
@@ -37,3 +37,15 @@ along with GCC. If not, see <http://www.gnu.org/licenses/>.
builtin_version ("Hurd"); \
builtin_version ("CRuntime_Glibc"); \
} while (0)
+
+#define GNU_USER_TARGET_RUST_OS_INFO() \
+ do \
+ { /*is this correct? or should os be "hurd"?*/ \
+ builtin_rust_info ("target_family", "unix"); \
+ builtin_rust_info ("target_os", "gnu"); \
+ builtin_rust_info ("target_vendor", "unknown"); \
+ builtin_rust_info ("target_env", ""); \
+ /* TODO: is target_env required?*/ \
+ } \
+ while (0)
+
@@ -31,6 +31,18 @@ along with GCC; see the file COPYING3. If not see
} \
while (0)
+#ifdef EXTRA_TARGET_RUST_OS_INFO
+# error "EXTRA_TARGET_RUST_OS_INFO already defined in crtdll.h (i386) - c++ undefines it and redefines it."
+#endif
+#define EXTRA_TARGET_RUST_OS_INFO() \
+ do { \
+ builtin_rust_info ("target_family", "windows"); \
+ builtin_rust_info ("target_os", "windows"); \
+ builtin_rust_info ("target_vendor", "pc"); \
+ /*TODO: is this the right target_env? it says gnu tools up there, but env may change.*/ \
+ builtin_rust_info ("target_env", "gnu"); \
+ } while (0)
+
#undef LIBGCC_SPEC
#define LIBGCC_SPEC \
"%{mthreads:-lmingwthrd} -lmingw32 -lgcc -lcoldname -libmingwex -lcrtdll"
@@ -151,6 +151,11 @@ along with GCC; see the file COPYING3. If not see
} \
while (0)
+#define TARGET_RUST_OS_INFO() \
+ do { \
+ EXTRA_TARGET_RUST_OS_INFO (); \
+ } while (0)
+
/* Get tree.cc to declare a target-specific specialization of
merge_decl_attributes. */
#define TARGET_DLLIMPORT_DECL_ATTRIBUTES 1
@@ -38,6 +38,16 @@ along with GCC; see the file COPYING3. If not see
} \
while (0)
+#define EXTRA_TARGET_RUST_OS_INFO() \
+ do { \
+ /*TODO: derived from llvm triple - rustc has no support for cygwin, but follows llvm triple*/ \
+ /*target_family is defined as unix due to posix-compliance, but this is subject to change*/ \
+ builtin_rust_info ("target_family", "unix"); \
+ builtin_rust_info ("target_os", "windows"); \
+ builtin_rust_info ("target_vendor", "unknown"); \
+ builtin_rust_info ("target_env", "cygnus"); \
+ } while (0)
+
#undef CPP_SPEC
#define CPP_SPEC "%(cpp_cpu) %{posix:-D_POSIX_SOURCE} \
%{!ansi:-Dunix} \
@@ -40,6 +40,16 @@ along with GCC; see the file COPYING3. If not see
darwin_cpp_builtins (pfile); \
} while (0)
+#define TARGET_RUST_OS_INFO() \
+ do { \
+ builtin_rust_info ("target_family", "unix"); \
+ /*TODO: rust actually has "macos", "ios", and "tvos" for darwin targets, but gcc seems to have no*/ \
+ /*current support for them, so assuming that target_os is always macos for now*/ \
+ builtin_rust_info ("target_os", "macos"); \
+ builtin_rust_info ("target_vendor", "apple"); \
+ builtin_rust_info ("target_env", ""); \
+ } while (0)
+
#undef PTRDIFF_TYPE
#define PTRDIFF_TYPE (TARGET_64BIT ? "long int" : "int")
@@ -57,6 +57,15 @@ along with GCC; see the file COPYING3. If not see
} \
while (0)
+#define TARGET_RUST_OS_INFO() \
+ do { \
+ /*rustc has no support for this, so values are taken from rusty-dos' djgpp github issue guesses*/ \
+ builtin_rust_info ("target_family", "windows"); \
+ builtin_rust_info ("target_os", "msdos"); \
+ builtin_rust_info ("target_vendor", "pc"); \
+ builtin_rust_info ("target_env", "djgpp"); \
+ } while (0)
+
#undef CPP_SPEC
#define CPP_SPEC "-remap %{posix:-D_POSIX_SOURCE}"
@@ -36,6 +36,11 @@ along with GCC; see the file COPYING3. If not see
} \
while (0)
+#define TARGET_RUST_OS_INFO() \
+ do { \
+ GNU_USER_TARGET_RUST_OS_INFO(); \
+ } while (0)
+
#undef CPP_SPEC
#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
@@ -281,6 +281,9 @@ extern void ix86_d_target_versions (void);
extern void ix86_d_register_target_info (void);
extern bool ix86_d_has_stdcall_convention (unsigned int *, unsigned int *);
+/* In i386-rust.cc */
+extern void ix86_rust_target_cpu_info (void);
+
/* In winnt.cc */
extern void i386_pe_unique_section (tree, int);
extern void i386_pe_declare_function_type (FILE *, const char *, int);
new file mode 100644
@@ -0,0 +1,501 @@
+/* Subroutines for the Rust front end on the x86 architecture.
+ Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tm_p.h"
+#include "rust/rust-target.h"
+#include "rust/rust-target-def.h"
+
+/* Implement TARGET_RUST_CPU_INFO for x86 targets. */
+
+void
+ix86_rust_target_cpu_info (void)
+{
+ if (TARGET_64BIT) {
+ rust_add_target_info("target_arch", "x86_64");
+
+ if (TARGET_X32) {
+ // this means it uses 32-bit pointers with 64-bit, basically (ILP32)
+ //rust_add_target_info("target_pointer_width", "32");
+ // TODO: may also change x86_64-...-linux-gnu to x86_64-...-linux-gnux32
+
+ // is this better than just putting in pointer width outside of if statement?
+
+ /* TODO: compared to base linux, may also need to change max_atomic_width to 64, add "-mx32"
+ * to pre-link args, make stack_probes true, make has_elf_tls false, make needs_plt true.
+ * Also, still target_endian is "little", target_c_int_width is "32", maybe steal data layout
+ * later from rustc spec, target_os is "linux", target_env is "gnu", target_vendor is "unknown"
+ * There is no rustc support for non-gnu/linux targets with ILP32. */
+ }
+ } else {
+ rust_add_target_info("target_arch", "x86");
+ }
+
+ // features officially "stabilised" in rustc
+ if (TARGET_MMX)
+ rust_add_target_info("target_feature", "mmx");
+ if (TARGET_SSE)
+ rust_add_target_info("target_feature", "sse");
+ if (TARGET_SSE2)
+ rust_add_target_info("target_feature", "sse2");
+ if (TARGET_SSE3)
+ rust_add_target_info("target_feature", "sse3");
+ if (TARGET_SSSE3)
+ rust_add_target_info("target_feature", "ssse3");
+ if (TARGET_SSE4_1)
+ rust_add_target_info("target_feature", "sse4.1");
+ if (TARGET_SSE4_2)
+ rust_add_target_info("target_feature", "sse4.2");
+ if (TARGET_AES)
+ rust_add_target_info("target_feature", "aes");
+ if (TARGET_SHA)
+ rust_add_target_info("target_feature", "sha");
+ if (TARGET_AVX)
+ rust_add_target_info("target_feature", "avx");
+ if (TARGET_AVX2)
+ rust_add_target_info("target_feature", "avx2");
+ if (TARGET_AVX512F)
+ rust_add_target_info("target_feature", "avx512f");
+ if (TARGET_AVX512ER)
+ rust_add_target_info("target_feature", "avx512er");
+ if (TARGET_AVX512CD)
+ rust_add_target_info("target_feature", "avx512cd");
+ if (TARGET_AVX512PF)
+ rust_add_target_info("target_feature", "avx512pf");
+ if (TARGET_AVX512DQ)
+ rust_add_target_info("target_feature", "avx512dq");
+ if (TARGET_AVX512BW)
+ rust_add_target_info("target_feature", "avx512bw");
+ if (TARGET_AVX512VL)
+ rust_add_target_info("target_feature", "avx512vl");
+ if (TARGET_AVX512VBMI)
+ rust_add_target_info("target_feature", "avx512vbmi");
+ if (TARGET_AVX512IFMA)
+ rust_add_target_info("target_feature", "avx512ifma");
+ if (TARGET_AVX512VPOPCNTDQ)
+ rust_add_target_info("target_feature", "avx512vpopcntdq");
+ if (TARGET_FMA)
+ rust_add_target_info("target_feature", "fma");
+ if (TARGET_RTM)
+ rust_add_target_info("target_feature", "rtm");
+ if (TARGET_SSE4A)
+ rust_add_target_info("target_feature", "sse4a");
+ if (TARGET_BMI) {
+ rust_add_target_info("target_feature", "bmi1");
+ rust_add_target_info("target_feature", "bmi");
+ }
+ if (TARGET_BMI2)
+ rust_add_target_info("target_feature", "bmi2");
+ if (TARGET_LZCNT)
+ rust_add_target_info("target_feature", "lzcnt");
+ if (TARGET_TBM)
+ rust_add_target_info("target_feature", "tbm");
+ if (TARGET_POPCNT)
+ rust_add_target_info("target_feature", "popcnt");
+ if (TARGET_RDRND) {
+ rust_add_target_info("target_feature", "rdrand");
+ rust_add_target_info("target_feature", "rdrnd");
+ }
+ if (TARGET_F16C)
+ rust_add_target_info("target_feature", "f16c");
+ if (TARGET_RDSEED)
+ rust_add_target_info("target_feature", "rdseed");
+ if (TARGET_ADX)
+ rust_add_target_info("target_feature", "adx");
+ if (TARGET_FXSR)
+ rust_add_target_info("target_feature", "fxsr");
+ if (TARGET_XSAVE)
+ rust_add_target_info("target_feature", "xsave");
+ if (TARGET_XSAVEOPT)
+ rust_add_target_info("target_feature", "xsaveopt");
+ if (TARGET_XSAVEC)
+ rust_add_target_info("target_feature", "xsavec");
+ if (TARGET_XSAVES)
+ rust_add_target_info("target_feature", "xsaves");
+ if (TARGET_VPCLMULQDQ) {
+ rust_add_target_info("target_feature", "pclmulqdq");
+ rust_add_target_info("target_feature", "vpclmulqdq");
+ }
+ if (TARGET_CMPXCHG16B)
+ rust_add_target_info("target_feature", "cmpxchg16b");
+ if (TARGET_MOVBE)
+ rust_add_target_info("target_feature", "movbe");
+
+ // features derived from llvm not yet in rustc:
+ if (TARGET_64BIT)
+ rust_add_target_info("target_feature", "64bit-mode");
+ else if (TARGET_CODE16)
+ rust_add_target_info("target_feature", "16bit-mode");
+ else
+ rust_add_target_info("target_feature", "32bit-mode");
+
+ // TODO: assuming that the TARGET_80387 (which seems to mean "hard float") is also required for x87
+ if (TARGET_80387 && (ix86_fpmath & FPMATH_387) != 0)
+ rust_add_target_info("target_feature", "x87");
+
+ // nopl: hard-coded (as gcc doesn't technically have feature) to return true for cpu arches with it
+ // maybe refactor into switch if multiple options
+ bool hasNOPL = ix86_arch == PROCESSOR_PENTIUMPRO || ix86_arch == PROCESSOR_PENTIUM4
+ || ix86_arch == PROCESSOR_NOCONA || ix86_arch == PROCESSOR_CORE2 || ix86_arch == PROCESSOR_NEHALEM
+ || ix86_arch == PROCESSOR_BONNELL || ix86_arch == PROCESSOR_SILVERMONT
+ || ix86_arch == PROCESSOR_GOLDMONT || ix86_arch == PROCESSOR_GOLDMONT_PLUS
+ || ix86_arch == PROCESSOR_TREMONT || ix86_arch == PROCESSOR_SANDYBRIDGE
+ || ix86_arch == PROCESSOR_HASWELL || ix86_arch == PROCESSOR_SKYLAKE
+ || ix86_arch == PROCESSOR_SKYLAKE_AVX512 || ix86_arch == PROCESSOR_CANNONLAKE
+ || ix86_arch == PROCESSOR_CASCADELAKE || ix86_arch == PROCESSOR_COOPERLAKE
+ || ix86_arch == PROCESSOR_ICELAKE_CLIENT || ix86_arch == PROCESSOR_ICELAKE_SERVER
+ || ix86_arch == PROCESSOR_TIGERLAKE || ix86_arch == PROCESSOR_KNL || ix86_arch == PROCESSOR_KNM
+ || ix86_arch == PROCESSOR_AMDFAM10 || ix86_arch == PROCESSOR_BTVER1 || ix86_arch == PROCESSOR_BTVER2
+ || ix86_arch == PROCESSOR_BDVER1 || ix86_arch == PROCESSOR_BDVER2 || ix86_arch == PROCESSOR_BDVER3
+ || ix86_arch == PROCESSOR_BDVER4 || ix86_arch == PROCESSOR_ZNVER1 || ix86_arch == PROCESSOR_ZNVER2
+ || ix86_arch == PROCESSOR_ATHLON || ix86_arch == PROCESSOR_K8;
+ // this list should be exhaustive
+ if (hasNOPL)
+ rust_add_target_info("target_feature", "nopl");
+ if (TARGET_CMOVE)
+ rust_add_target_info("target_feature", "cmov");
+ if (TARGET_CMPXCHG8B)
+ rust_add_target_info("target_feature", "cx8");
+ if (TARGET_3DNOW)
+ rust_add_target_info("target_feature", "3dnow");
+ if (TARGET_3DNOW_A)
+ rust_add_target_info("target_feature", "3dnowa");
+ if (TARGET_64BIT)
+ rust_add_target_info("target_feature", "64bit");
+ if (TARGET_CMPXCHG16B)
+ rust_add_target_info("target_feature", "cx16");
+
+ bool hasSlowSHLD = ix86_arch == PROCESSOR_AMDFAM10 || ix86_arch == PROCESSOR_BTVER1
+ || ix86_arch == PROCESSOR_BTVER2 || ix86_arch == PROCESSOR_BDVER1 || ix86_arch == PROCESSOR_BDVER2
+ || ix86_arch == PROCESSOR_BDVER3 || ix86_arch == PROCESSOR_BDVER4 || ix86_arch == PROCESSOR_ZNVER1
+ || ix86_arch == PROCESSOR_ZNVER2 || ix86_arch == PROCESSOR_ATHLON || ix86_arch == PROCESSOR_K8;
+ // TODO: this is not ideal as it marks the baseline x86-64 CPU as having it - only AMD ones do
+ if (hasSlowSHLD)
+ rust_add_target_info("target_feature", "slow-shld");
+ if (ix86_arch == PROCESSOR_SILVERMONT)
+ rust_add_target_info("target_feature", "slow-pmulld");
+ if (ix86_arch == PROCESSOR_KNL || ix86_arch == PROCESSOR_KNM)
+ rust_add_target_info("target_feature", "slow-pmaddwd");
+
+ bool hasSlowUnaligned16 = ix86_arch == PROCESSOR_BONNELL || ix86_arch == PROCESSOR_GENERIC
+ || ix86_arch == PROCESSOR_I386 || ix86_arch == PROCESSOR_I486 || ix86_arch == PROCESSOR_PENTIUM
+ || ix86_arch == PROCESSOR_PENTIUMPRO || ix86_arch == PROCESSOR_PENTIUM4
+ || ix86_arch == PROCESSOR_NOCONA || ix86_arch == PROCESSOR_CORE2 || ix86_arch == PROCESSOR_K6
+ || ix86_arch == PROCESSOR_ATHLON || ix86_arch == PROCESSOR_K8 || ix86_arch == PROCESSOR_GEODE;
+ if (hasSlowUnaligned16)
+ rust_add_target_info("target_feature", "slow-unaligned-mem-16");
+ if (ix86_arch == PROCESSOR_SANDYBRIDGE)
+ rust_add_target_info("target_feature", "slow-unaligned-mem-32");
+ if (TARGET_PREFETCHWT1)
+ rust_add_target_info("target_feature", "prefetchwt1");
+ if (TARGET_AVX512VBMI2)
+ rust_add_target_info("target_feature", "avx512vbmi2");
+ if (TARGET_PKU)
+ rust_add_target_info("target_feature", "pku");
+ if (TARGET_AVX512VNNI)
+ rust_add_target_info("target_feature", "avx512vnni");
+ if (TARGET_AVX512BF16)
+ rust_add_target_info("target_feature", "avx512bf16");
+ if (TARGET_AVX512BITALG)
+ rust_add_target_info("target_feature", "avx512bitalg");
+ if (TARGET_AVX512VP2INTERSECT)
+ rust_add_target_info("target_feature", "avx512vp2intersect");
+ if (TARGET_PCLMUL)
+ rust_add_target_info("target_feature", "pclmul");
+ if (TARGET_GFNI)
+ rust_add_target_info("target_feature", "gfni");
+ if (TARGET_FMA4)
+ rust_add_target_info("target_feature", "fma4");
+ if (TARGET_XOP)
+ rust_add_target_info("target_feature", "xop");
+
+ // this is only enabled by choice in llvm, never by default - TODO determine if gcc enables it
+ // rust_add_target_info("target_feature", "sse-unaligned-mem");
+
+ if (TARGET_VAES)
+ rust_add_target_info("target_feature", "vaes");
+ if (TARGET_LWP)
+ rust_add_target_info("target_feature", "lwp");
+ if (TARGET_FSGSBASE)
+ rust_add_target_info("target_feature", "fsgsbase");
+ if (TARGET_SHSTK)
+ rust_add_target_info("target_feature", "shstk");
+ if (TARGET_PRFCHW)
+ rust_add_target_info("target_feature", "prfchw");
+ if (TARGET_SAHF) // would this be better as TARGET_USE_SAHF?
+ rust_add_target_info("target_feature", "sahf");
+ if (TARGET_MWAITX)
+ rust_add_target_info("target_feature", "mwaitx");
+ if (TARGET_CLZERO)
+ rust_add_target_info("target_feature", "clzero");
+ if (TARGET_CLDEMOTE)
+ rust_add_target_info("target_feature", "cldemote");
+ if (TARGET_PTWRITE)
+ rust_add_target_info("target_feature", "ptwrite");
+ // TODO: add amx-tile, amx-int8, amx-bf16 features when gcc supports them
+
+ // TODO: can't find any gcc option relating to using LEA for adjusting stack pointer, so hardcoding
+ if (ix86_arch == PROCESSOR_BONNELL)
+ rust_add_target_info("target_feature", "lea-sp");
+
+ // TODO: confirm that this is what it actually refers to
+ if (TARGET_USE_8BIT_IDIV)
+ rust_add_target_info("target_feature", "idivl-to-divb");
+
+ /* TODO: can't find any gcc option corresponding to idivq-to-divl - does gcc perform this optimisation?
+ * if so, add that feature (use 32-bit divide for positive values less than 2^32) */
+ /* bool llvmHasSlowDivide64 = ix86_arch == PROCESSOR_SANDYBRIDGE || ix86_arch == PROCESSOR_HASWELL
+ || ix86_arch == PROCESSOR_SKYLAKE || ix86_arch == PROCESSOR_SKYLAKE_AVX512
+ || ix86_arch == PROCESSOR_CANNONLAKE || ix86_arch == PROCESSOR_ICELAKE_CLIENT
+ || ix86_arch == PROCESSOR_ICELAKE_SERVER || ix86_arch == PROCESSOR_CASCADELAKE
+ || ix86_arch == PROCESSOR_TIGERLAKE || ix86_arch == PROCESSOR_COOPERLAKE
+ || ix86_arch == PROCESSOR_BONNELL || ix86_arch == PROCESSOR_SILVERMONT || ix86_arch == PROCESSOR_KNL
+ || ix86_arch == PROCESSOR_KNM || ix86_arch == PROCESSOR_K8;*/
+
+ if (TARGET_PAD_SHORT_FUNCTION)
+ rust_add_target_info("target_feature", "pad-short-functions");
+
+ // TODO: gcc seems to not record whether INVPCID exists, so basing it on llvm
+ bool hasINVPCID = ix86_arch == PROCESSOR_HASWELL || ix86_arch == PROCESSOR_SKYLAKE
+ || ix86_arch == PROCESSOR_SKYLAKE_AVX512 || ix86_arch == PROCESSOR_CANNONLAKE
+ || ix86_arch == PROCESSOR_ICELAKE_CLIENT || ix86_arch == PROCESSOR_ICELAKE_SERVER
+ || ix86_arch == PROCESSOR_CASCADELAKE || ix86_arch == PROCESSOR_TIGERLAKE
+ || ix86_arch == PROCESSOR_COOPERLAKE;
+ if (hasINVPCID)
+ rust_add_target_info("target_feature", "invpcid");
+ if (TARGET_SGX)
+ rust_add_target_info("target_feature", "sgx");
+ if (TARGET_CLFLUSHOPT)
+ rust_add_target_info("target_feature", "clflushopt");
+ if (TARGET_CLWB)
+ rust_add_target_info("target_feature", "clwb");
+ if (TARGET_WBNOINVD)
+ rust_add_target_info("target_feature", "wbnoinvd");
+ if (TARGET_RDPID)
+ rust_add_target_info("target_feature", "rdpid");
+ if (TARGET_WAITPKG)
+ rust_add_target_info("target_feature", "waitpkg");
+ if (TARGET_ENQCMD)
+ rust_add_target_info("target_feature", "enqcmd");
+
+ // these are only enabled by choice in llvm, never by default - TODO determine if gcc supports them
+ // rust_add_target_info("target_feature", "serialize");
+ // rust_add_target_info("target_feature", "tsxldtrk");
+
+ // TODO: gcc seems to not record whether to avoid memory operanded instructions, so basing it on llvm
+ bool hasSlowTwoMemOps = ix86_arch == PROCESSOR_BONNELL || ix86_arch == PROCESSOR_SILVERMONT
+ || ix86_arch == PROCESSOR_GOLDMONT || ix86_arch == PROCESSOR_GOLDMONT_PLUS
+ || ix86_arch == PROCESSOR_TREMONT || ix86_arch == PROCESSOR_KNL || ix86_arch == PROCESSOR_KNM;
+ if (hasSlowTwoMemOps)
+ rust_add_target_info("target_feature", "slow-two-mem-ops");
+
+ // TODO: gcc seems to not record whether LEA needs input at AG stage, so basing it on llvm
+ // TODO: maybe something to do with X86_TUNE_OPT_AGU?
+ if (ix86_arch == PROCESSOR_BONNELL)
+ rust_add_target_info("target_feature", "lea-uses-ag");
+
+ // TODO: gcc seems to not record whether LEA with certain arguments is slow, so basing it on llvm
+ // TODO: maybe TARGET_AVOID_LEA_FOR_ADDR has something to do with it?
+ bool hasSlowLEA = ix86_arch == PROCESSOR_SILVERMONT || ix86_arch == PROCESSOR_GOLDMONT
+ || ix86_arch == PROCESSOR_GOLDMONT_PLUS || ix86_arch == PROCESSOR_TREMONT;
+ if (hasSlowLEA)
+ rust_add_target_info("target_feature", "slow-lea");
+
+ // TODO: gcc seems to not record whether LEA with 3 ops or certain regs is slow, so basing it on llvm
+ // TODO: maybe TARGET_AVOID_LEA_FOR_ADDR has something to do with it?
+ bool hasSlow3OpsLEA = ix86_arch == PROCESSOR_SANDYBRIDGE || ix86_arch == PROCESSOR_HASWELL
+ || ix86_arch == PROCESSOR_SKYLAKE || ix86_arch == PROCESSOR_SKYLAKE_AVX512
+ || ix86_arch == PROCESSOR_CANNONLAKE || ix86_arch == PROCESSOR_ICELAKE_CLIENT
+ || ix86_arch == PROCESSOR_ICELAKE_SERVER || ix86_arch == PROCESSOR_CASCADELAKE
+ || ix86_arch == PROCESSOR_TIGERLAKE || ix86_arch == PROCESSOR_COOPERLAKE
+ || ix86_arch == PROCESSOR_KNL || ix86_arch == PROCESSOR_KNM || ix86_arch == PROCESSOR_K8;
+ if (hasSlow3OpsLEA)
+ rust_add_target_info("target_feature", "slow-3ops-lea");
+
+ // TODO: assuming that this is equivalent option - it strictly doesn't cover same cpus
+ if (!TARGET_USE_INCDEC)
+ rust_add_target_info("target_feature", "slow-incdec");
+ // TODO: assuming that this mask actually refers to "hard float" and not x87 specifically
+ if (!TARGET_80387)
+ rust_add_target_info("target_feature", "soft-float");
+
+ // TODO: gcc seems to not record if LZCNT/TZCNT has false deps on dest register, so basing it on llvm
+ if (ix86_arch == PROCESSOR_HASWELL)
+ rust_add_target_info("target_feature", "false-deps-lzcnt-tzcnt");
+
+ if (TARGET_PCONFIG)
+ rust_add_target_info("target_feature", "pconfig");
+
+ // TODO: gcc seems to not record if variable-mask shuffles are fast, so basing it on llvm
+ bool hasFastVariableShuffle = ix86_arch == PROCESSOR_HASWELL || ix86_arch == PROCESSOR_SKYLAKE
+ || ix86_arch == PROCESSOR_SKYLAKE_AVX512 || ix86_arch == PROCESSOR_CANNONLAKE
+ || ix86_arch == PROCESSOR_ICELAKE_CLIENT || ix86_arch == PROCESSOR_ICELAKE_SERVER
+ || ix86_arch == PROCESSOR_CASCADELAKE || ix86_arch == PROCESSOR_TIGERLAKE
+ || ix86_arch == PROCESSOR_COOPERLAKE;
+ if (hasFastVariableShuffle)
+ rust_add_target_info("target_feature", "fast-variable-shuffle");
+
+ // TODO: ensure that this actually refers to the right thing - difference in gcc and llvm description
+ if (TARGET_VZEROUPPER)
+ rust_add_target_info("target_feature", "vzeroupper");
+
+ // option based on llvm arch analysis as gcc tuning costs seem to indicate a different result
+ bool hasFastScalarFSQRT = ix86_arch == PROCESSOR_SANDYBRIDGE || ix86_arch == PROCESSOR_HASWELL
+ || ix86_arch == PROCESSOR_SKYLAKE || ix86_arch == PROCESSOR_SKYLAKE_AVX512
+ || ix86_arch == PROCESSOR_CANNONLAKE || ix86_arch == PROCESSOR_ICELAKE_CLIENT
+ || ix86_arch == PROCESSOR_ICELAKE_SERVER || ix86_arch == PROCESSOR_CASCADELAKE
+ || ix86_arch == PROCESSOR_TIGERLAKE || ix86_arch == PROCESSOR_COOPERLAKE;
+ if (hasFastScalarFSQRT)
+ rust_add_target_info("target_feature", "fast-scalar-fsqrt");
+
+ // option also based on llvm arch analysis
+ bool hasFastVectorFSQRT = ix86_arch == PROCESSOR_SKYLAKE || ix86_arch == PROCESSOR_SKYLAKE_AVX512
+ || ix86_arch == PROCESSOR_CANNONLAKE || ix86_arch == PROCESSOR_ICELAKE_CLIENT
+ || ix86_arch == PROCESSOR_ICELAKE_SERVER || ix86_arch == PROCESSOR_CASCADELAKE
+ || ix86_arch == PROCESSOR_TIGERLAKE || ix86_arch == PROCESSOR_COOPERLAKE;
+ if (hasFastVectorFSQRT)
+ rust_add_target_info("target_feature", "fast-vector-fsqrt");
+
+ bool hasFastLZCNT = ix86_arch == PROCESSOR_BTVER2 || ix86_arch == PROCESSOR_ZNVER1
+ || ix86_arch == PROCESSOR_ZNVER2;
+ if (hasFastLZCNT)
+ rust_add_target_info("target_feature", "fast-lzcnt");
+
+ if (ix86_arch == PROCESSOR_SILVERMONT)
+ rust_add_target_info("target_feature", "fast-7bytenop");
+
+ bool hasFast11ByteNOP = ix86_arch == PROCESSOR_BDVER1 || ix86_arch == PROCESSOR_BDVER2
+ || ix86_arch == PROCESSOR_BDVER3 || ix86_arch == PROCESSOR_BDVER4;
+ if (hasFast11ByteNOP)
+ rust_add_target_info("target_feature", "fast-11bytenop");
+
+ bool hasFast15ByteNOP = ix86_arch == PROCESSOR_SANDYBRIDGE || ix86_arch == PROCESSOR_HASWELL
+ || ix86_arch == PROCESSOR_SKYLAKE || ix86_arch == PROCESSOR_SKYLAKE_AVX512
+ || ix86_arch == PROCESSOR_CANNONLAKE || ix86_arch == PROCESSOR_ICELAKE_CLIENT
+ || ix86_arch == PROCESSOR_ICELAKE_SERVER || ix86_arch == PROCESSOR_CASCADELAKE
+ || ix86_arch == PROCESSOR_TIGERLAKE || ix86_arch == PROCESSOR_COOPERLAKE
+ || ix86_arch == PROCESSOR_BTVER1 || ix86_arch == PROCESSOR_BTVER2
+ || ix86_arch == PROCESSOR_ZNVER1 || ix86_arch == PROCESSOR_ZNVER2;
+ if (hasFast15ByteNOP)
+ rust_add_target_info("target_feature", "fast-15bytenop");
+
+ bool hasFastSHLDRotate = ix86_arch == PROCESSOR_SANDYBRIDGE || ix86_arch == PROCESSOR_HASWELL
+ || ix86_arch == PROCESSOR_SKYLAKE || ix86_arch == PROCESSOR_SKYLAKE_AVX512
+ || ix86_arch == PROCESSOR_CANNONLAKE || ix86_arch == PROCESSOR_ICELAKE_CLIENT
+ || ix86_arch == PROCESSOR_ICELAKE_SERVER || ix86_arch == PROCESSOR_CASCADELAKE
+ || ix86_arch == PROCESSOR_TIGERLAKE || ix86_arch == PROCESSOR_COOPERLAKE;
+ if (hasFastSHLDRotate)
+ rust_add_target_info("target_feature", "fast-shld-rotate");
+
+ bool hasERMSB = ix86_arch == PROCESSOR_HASWELL || ix86_arch == PROCESSOR_SKYLAKE
+ || ix86_arch == PROCESSOR_SKYLAKE_AVX512 || ix86_arch == PROCESSOR_CANNONLAKE
+ || ix86_arch == PROCESSOR_ICELAKE_CLIENT || ix86_arch == PROCESSOR_ICELAKE_SERVER
+ || ix86_arch == PROCESSOR_CASCADELAKE || ix86_arch == PROCESSOR_TIGERLAKE
+ || ix86_arch == PROCESSOR_COOPERLAKE;
+ if (hasERMSB)
+ rust_add_target_info("target_feature", "ermsbd");
+
+ // TODO: may exist in gcc as tune macros, but not sure, so based on llvm arches
+ bool hasBranchFusion = ix86_arch == PROCESSOR_BDVER1 || ix86_arch == PROCESSOR_BDVER2
+ || ix86_arch == PROCESSOR_BDVER3 || ix86_arch == PROCESSOR_BDVER4 || ix86_arch == PROCESSOR_ZNVER1
+ || ix86_arch == PROCESSOR_ZNVER2;
+ if (hasBranchFusion)
+ rust_add_target_info("target_feature", "branchfusion");
+
+ // TODO: again, may exist as tune macros, but again based on llvm arches
+ bool hasMacroFusion = ix86_arch == PROCESSOR_CORE2 || ix86_arch == PROCESSOR_NEHALEM
+ || ix86_arch == PROCESSOR_SANDYBRIDGE || ix86_arch == PROCESSOR_HASWELL
+ || ix86_arch == PROCESSOR_SKYLAKE || ix86_arch == PROCESSOR_SKYLAKE_AVX512
+ || ix86_arch == PROCESSOR_CANNONLAKE || ix86_arch == PROCESSOR_ICELAKE_CLIENT
+ || ix86_arch == PROCESSOR_ICELAKE_SERVER || ix86_arch == PROCESSOR_CASCADELAKE
+ || ix86_arch == PROCESSOR_TIGERLAKE || ix86_arch == PROCESSOR_COOPERLAKE || ix86_arch == PROCESSOR_K8;
+ if (hasMacroFusion)
+ rust_add_target_info("target_feature", "macrofusion");
+
+ // TODO: is this equivalent to TARGET_USE_GATHER?
+ bool hasFastGather = ix86_arch == PROCESSOR_SKYLAKE || ix86_arch == PROCESSOR_SKYLAKE_AVX512
+ || ix86_arch == PROCESSOR_CASCADELAKE || ix86_arch == PROCESSOR_COOPERLAKE
+ || ix86_arch == PROCESSOR_CANNONLAKE || ix86_arch == PROCESSOR_ICELAKE_CLIENT
+ || ix86_arch == PROCESSOR_ICELAKE_SERVER || ix86_arch == PROCESSOR_TIGERLAKE
+ || ix86_arch == PROCESSOR_KNL || ix86_arch == PROCESSOR_KNM;
+ if (hasFastGather)
+ rust_add_target_info("target_feature", "fast-gather");
+
+ if (TARGET_PREFER_AVX128)
+ rust_add_target_info("target_feature", "prefer-128-bit");
+ if (TARGET_PREFER_AVX256)
+ rust_add_target_info("target_feature", "prefer-256-bit");
+
+ bool preferMaskRegisters = ix86_arch == PROCESSOR_KNL || ix86_arch == PROCESSOR_KNM;
+ if (preferMaskRegisters)
+ rust_add_target_info("target_feature", "prefer-mask-registers");
+
+ /* TODO: add retpoline-indirect-calls, retpoline-indirect-branches, retpoline, retpoline-external-thunk,
+ * lvi-cfi (LVI control flow integrity), seses (speculative execution side-effect suppression)
+ * lvi-load-hardening if gcc gets support */
+
+ if (TARGET_MOVDIRI)
+ rust_add_target_info("target_feature", "movdiri");
+ if (TARGET_MOVDIR64B)
+ rust_add_target_info("target_feature", "movdir64b");
+
+ bool hasFastBEXTR = ix86_arch == PROCESSOR_BTVER2 || ix86_arch == PROCESSOR_BDVER2
+ || ix86_arch == PROCESSOR_BDVER3 || ix86_arch == PROCESSOR_BDVER4 || ix86_arch == PROCESSOR_ZNVER1
+ || ix86_arch == PROCESSOR_ZNVER2;
+ if (hasFastBEXTR)
+ rust_add_target_info("target_feature", "fast-bextr");
+
+ if (ix86_arch == PROCESSOR_BTVER2)
+ rust_add_target_info("target_feature", "fast-hops");
+
+ bool hasFastScalarShiftMasks = ix86_arch == PROCESSOR_AMDFAM10 || ix86_arch == PROCESSOR_BTVER1
+ || ix86_arch == PROCESSOR_BTVER2 || ix86_arch == PROCESSOR_BDVER1 || ix86_arch == PROCESSOR_BDVER2
+ || ix86_arch == PROCESSOR_BDVER3 || ix86_arch == PROCESSOR_BDVER4 || ix86_arch == PROCESSOR_ZNVER1
+ || ix86_arch == PROCESSOR_ZNVER2 || ix86_arch == PROCESSOR_K8;
+ if (hasFastScalarShiftMasks)
+ rust_add_target_info("target_feature", "fast-scalar-shift-masks");
+
+ bool hasFastVectorShiftMasks = ix86_arch == PROCESSOR_BTVER1 || ix86_arch == PROCESSOR_BTVER2;
+ if (hasFastVectorShiftMasks)
+ rust_add_target_info("target_feature", "fast-vector-shift-masks");
+
+ bool useGoldmontDivSqrtCosts = ix86_arch == PROCESSOR_GOLDMONT || ix86_arch == PROCESSOR_GOLDMONT_PLUS
+ || ix86_arch == PROCESSOR_TREMONT;
+ if (useGoldmontDivSqrtCosts)
+ rust_add_target_info("target_feature", "use-glm-div-sqrt-costs");
+
+ // TODO: determine if gcc supports alias analysis (in which case "use-aa" is defined)
+
+ // features not supported by llvm but important enough for c frontend to define macros for
+ /*if (TARGET_AVX5124VNNIW)
+ rust_add_target_info("target_feature", "avx5124vnniw");
+ if (TARGET_AVX5124FMAPS)
+ rust_add_target_info("target_feature", "avx5124fmaps");
+ if (TARGET_ABM)
+ rust_add_target_info("target_feature", "abm");
+ if ((ix86_fpmath & FPMATH_SSE) && TARGET_SSE)
+ ; //def_or_undef (parse_in, "__SSE_MATH__");
+ if ((ix86_fpmath & FPMATH_SSE) && TARGET_SSE2)
+ ; //def_or_undef (parse_in, "__SSE2_MATH__");
+ if (TARGET_MMX_WITH_SSE)
+ ; //def_or_undef (parse_in, "__MMX_WITH_SSE__");
+ if (TARGET_IAMCU)
+ rust_add_target_info("target_feature", "iamcu");*/
+}
@@ -613,6 +613,9 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
#define TARGET_D_REGISTER_CPU_TARGET_INFO ix86_d_register_target_info
#define TARGET_D_HAS_STDCALL_CONVENTION ix86_d_has_stdcall_convention
+/* Target CPU info for Rust. */
+#define TARGET_RUST_CPU_INFO ix86_rust_target_cpu_info
+
#ifndef CC1_SPEC
#define CC1_SPEC "%(cc1_cpu) "
#endif
@@ -30,6 +30,23 @@ along with GCC; see the file COPYING3. If not see
#define EXTRA_TARGET_D_OS_VERSIONS() \
ANDROID_TARGET_D_OS_VERSIONS();
+#define EXTRA_TARGET_RUST_OS_INFO() \
+ ANDROID_TARGET_RUST_OS_INFO();
+// TODO: decide on whether following c frontend style or d one - leaning towards c
+
+
+/*#ifdef TARGET_RUST_OS_INFO
+# error "TARGET_RUST_OS_INFO already defined in linux-common.h (i386) - c++ undefines it and redefines it."
+# error "note that this above error (linux-common-i386) is expected due to already defining EXTRA_TARGET stuff"
+#endif*/
+/* This is previously defined in gnu-user-common.h, but has no linux-specific info. */
+#undef TARGET_RUST_OS_INFO
+#define TARGET_RUST_OS_INFO() \
+ do { \
+ GNU_USER_TARGET_RUST_OS_INFO(); \
+ ANDROID_TARGET_RUST_OS_INFO(); \
+ } while (0)
+
#undef CC1_SPEC
#define CC1_SPEC \
LINUX_OR_ANDROID_CC (GNU_USER_TARGET_CC1_SPEC, \
@@ -25,6 +25,15 @@ along with GCC; see the file COPYING3. If not see
} \
while (0)
+#define TARGET_RUST_OS_INFO() \
+ do { \
+ /*TODO: not supported by rustc and so subject to change - based on llvm triple*/ \
+ builtin_rust_info ("target_family", "unix"); \
+ builtin_rust_info ("target_os", "lynxos"); \
+ builtin_rust_info ("target_vendor", "unknown"); \
+ builtin_rust_info ("target_env", ""); \
+ } while (0)
+
/* The svr4 ABI for the i386 says that records and unions are returned
in memory. */
@@ -65,6 +65,14 @@ along with GCC; see the file COPYING3. If not see
} \
while (0)
+#define EXTRA_TARGET_RUST_OS_INFO() \
+ do { \
+ builtin_rust_info ("target_family", "windows"); \
+ builtin_rust_info ("target_os", "windows"); \
+ builtin_rust_info ("target_vendor", "pc"); \
+ builtin_rust_info ("target_env", "gnu"); \
+ } while (0)
+
#ifndef TARGET_USE_PTHREAD_BY_DEFAULT
#define SPEC_PTHREAD1 "pthread"
#define SPEC_PTHREAD2 "!no-pthread"
@@ -26,6 +26,11 @@ along with GCC; see the file COPYING3. If not see
} \
while (0)
+#define TARGET_RUST_OS_INFO() \
+ do { \
+ NETBSD_TARGET_RUST_OS_INFO(); \
+ } while (0)
+
/* Extra specs needed for NetBSD/i386 ELF. */
@@ -26,6 +26,11 @@ along with GCC; see the file COPYING3. If not see
} \
while (0)
+#define TARGET_RUST_OS_INFO() \
+ do { \
+ NETBSD_TARGET_RUST_OS_INFO(); \
+ } while (0)
+
/* Extra specs needed for NetBSD/x86-64 ELF. */
@@ -36,6 +36,18 @@ along with GCC; see the file COPYING3. If not see
} \
while (0)
+#ifdef TARGET_RUST_OS_INFO
+# error "TARGET_RUST_OS_INFO already defined in nto.h (i386) - c++ undefines it and redefines it."
+#endif
+#define TARGET_RUST_OS_INFO() \
+ do { \
+ /*TODO: not supported by rustc and so subject to change - based on triple found online*/ \
+ builtin_rust_info ("target_family", "unix"); \
+ builtin_rust_info ("target_os", "nto"); \
+ builtin_rust_info ("target_vendor", "pc"); \
+ builtin_rust_info ("target_env", "qnx"); \
+ } while (0)
+
#undef THREAD_MODEL_SPEC
#define THREAD_MODEL_SPEC "posix"
@@ -25,6 +25,11 @@ along with GCC; see the file COPYING3. If not see
} \
while (0)
+#define TARGET_RUST_OS_INFO() \
+ do { \
+ OPENBSD_TARGET_RUST_OS_INFO(); \
+ } while (0)
+
#undef DBX_REGISTER_NUMBER
#define DBX_REGISTER_NUMBER(n) \
(TARGET_64BIT ? dbx64_register_map[n] : svr4_dbx_register_map[n])
@@ -37,3 +37,14 @@ along with GCC; see the file COPYING3. If not see
builtin_assert ("system=rdos"); \
} \
while (0)
+
+#define TARGET_RUST_OS_INFO() \
+ do { \
+ /*TODO: not supported by rustc and so subject to change - based on triple found online*/ \
+ /*this seems to not refer to the 70s Data General RDOS, but one partly compatible with win32*/ \
+ /*as such, target_family could be windows*/ \
+ builtin_rust_info ("target_family", ""); \
+ builtin_rust_info ("target_os", "rdos"); \
+ builtin_rust_info ("target_vendor", "pc"); \
+ builtin_rust_info ("target_env", ""); \
+ } while (0)
@@ -33,3 +33,13 @@
builtin_assert ("system=rtems"); \
} \
while (0)
+
+#define TARGET_RUST_OS_INFO() \
+ do { \
+ /*note: as far as I know, rustc has no supported for rtems, so this is just guessed*/ \
+ /*everything is subject to change, especially target_env and target_family*/ \
+ builtin_rust_info ("target_family", "unix"); \
+ builtin_rust_info ("target_os", "rtems"); \
+ builtin_rust_info ("target_vendor", "unknown"); \
+ builtin_rust_info ("target_env", ""); \
+ } while (0)
@@ -46,6 +46,10 @@ i386-d.o: $(srcdir)/config/i386/i386-d.cc
$(COMPILE) $<
$(POSTCOMPILE)
+i386-rust.o: $(srcdir)/config/i386/i386-rust.cc
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
i386-options.o: $(srcdir)/config/i386/i386-options.cc
$(COMPILE) $<
$(POSTCOMPILE)
@@ -113,6 +113,11 @@ along with GCC; see the file COPYING3. If not see
} \
while (0)
+#define TARGET_RUST_OS_INFO() \
+ do { \
+ VXWORKS_TARGET_RUST_OS_INFO(); \
+ } while (0)
+
#undef CPP_SPEC
#define CPP_SPEC VXWORKS_ADDITIONAL_CPP_SPEC
#undef CC1_SPEC
@@ -35,6 +35,14 @@ along with GCC; see the file COPYING3. If not see
builtin_version ("CRuntime_Glibc"); \
} while (0)
+#define GNU_USER_TARGET_RUST_OS_INFO() \
+ do { \
+ builtin_rust_info ("target_family", "unix"); \
+ builtin_rust_info ("target_os", "kfreebsd"); \
+ builtin_rust_info ("target_vendor", "unknown"); \
+ builtin_rust_info ("target_env", "gnu"); \
+ } while (0)
+
#define GNU_USER_DYNAMIC_LINKER GLIBC_DYNAMIC_LINKER
#define GNU_USER_DYNAMIC_LINKER32 GLIBC_DYNAMIC_LINKER32
#define GNU_USER_DYNAMIC_LINKER64 GLIBC_DYNAMIC_LINKER64
@@ -36,5 +36,17 @@ along with GCC; see the file COPYING3. If not see
builtin_version ("CRuntime_Glibc"); \
} while (0)
+#ifdef GNU_USER_TARGET_RUST_OS_INFO
+# error # error "TARGET_RUST_OS_INFO already defined in kopensolaris-gnu.h - c++ undefines it and redefines it."
+#endif
+#define GNU_USER_TARGET_RUST_OS_INFO() \
+ do { \
+ builtin_rust_info ("target_family", "unix"); \
+ builtin_rust_info ("target_os", "kopensolaris"); \
+ /*the target_os is maybe not right but i can't find any better atm*/ \
+ builtin_rust_info ("target_vendor", "unknown"); \
+ builtin_rust_info ("target_env", "gnu"); \
+ } while (0)
+
#undef GNU_USER_DYNAMIC_LINKER
#define GNU_USER_DYNAMIC_LINKER "/lib/ld.so.1"
@@ -31,6 +31,18 @@
builtin_version ("Android"); \
} while (0)
+#define ANDROID_TARGET_RUST_OS_INFO() \
+ do { \
+ if (TARGET_ANDROID) { \
+ builtin_rust_info ("target_family", "unix"); \
+ builtin_rust_info ("target_os", "android"); \
+ builtin_rust_info ("target_vendor", "unknown"); \
+ builtin_rust_info ("target_env", ""); \
+ } else { \
+ builtin_rust_info ("target_os", "linux"); \
+ } /*this else is required if I'm intepreting structure of defines correctly*/ \
+ } while (0)
+
#if ANDROID_DEFAULT
# define NOANDROID "mno-android"
#else
@@ -71,6 +71,20 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
builtin_version ("CRuntime_Musl"); \
} while (0)
+#define GNU_USER_TARGET_RUST_OS_INFO() \
+ do { \
+ builtin_rust_info ("target_family", "unix"); \
+ builtin_rust_info ("target_vendor", "unknown"); \
+ /*is there way of determining target_os and target_env here since could also be android?*/ \
+ /*target_vendor may not be "unknown" - FIXME ensure it is*/ \
+ if (OPTION_GLIBC) \
+ builtin_rust_info ("target_env", "gnu"); \
+ else if (OPTION_MUSL) \
+ builtin_rust_info ("target_env", "musl"); \
+ else /*TODO: determine if bionic and uclibc are considered to be different envs in rustc*/ \
+ builtin_rust_info ("target_env", ""); \
+ } while (0)
+
/* Determine which dynamic linker to use depending on whether GLIBC or
uClibc or Bionic or musl is the default C library and whether
-muclibc or -mglibc or -mbionic or -mmusl has been passed to change
@@ -29,6 +29,15 @@ along with GCC; see the file COPYING3. If not see
} \
while (0)
+/* TARGET_RUST_OS_INFO() common to all NetBSD targets. */
+#define NETBSD_TARGET_RUST_OS_INFO() \
+ do { \
+ builtin_rust_info ("target_family", "unix"); \
+ builtin_rust_info ("target_os", "netbsd"); \
+ builtin_rust_info ("target_vendor", "unknown"); \
+ builtin_rust_info ("target_env", ""); \
+ } while (0)
+
/* CPP_SPEC parts common to all NetBSD targets. */
#define NETBSD_CPP_SPEC \
"%{posix:-D_POSIX_SOURCE} \
@@ -102,6 +102,14 @@ while (0)
} \
while (0)
+#define OPENBSD_TARGET_RUST_OS_INFO() \
+ do { \
+ builtin_rust_info ("target_family", "unix"); \
+ builtin_rust_info ("target_os", "openbsd"); \
+ builtin_rust_info ("target_vendor", "unknown"); \
+ builtin_rust_info ("target_env", ""); \
+ } while(0)
+
/* CPP_SPEC appropriate for OpenBSD. We deal with -posix and -pthread.
XXX the way threads are handled currently is not very satisfying,
since all code must be compiled with -pthread to work.
@@ -26,6 +26,18 @@ along with GCC; see the file COPYING3. If not see
builtin_assert ("system=unix"); \
} while (0)
+#ifdef TARGET_RUST_OS_INFO
+# error "TARGET_RUST_OS_INFO already defined in phoenix.h - c++ undefines it and redefines it."
+#endif
+#define TARGET_RUST_OS_INFO() \
+ do { \
+ builtin_rust_info ("target_family", "unix"); \
+ builtin_rust_info ("target_os", "phoenix"); \
+ builtin_rust_info ("target_vendor", "unknown"); \
+ builtin_rust_info ("target_env", ""); \
+ /*TODO: ensure these values are correct*/ \
+ } while(0)
+
#define STD_LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
/* This will prevent selecting 'unsigned long int' instead of 'unsigned int' as 'uint32_t' in stdint-newlib.h. */
@@ -124,6 +124,16 @@ along with GCC; see the file COPYING3. If not see
solaris_override_options (); \
} while (0)
+#define EXTRA_TARGET_RUST_OS_INFO()
+#define TARGET_RUST_OS_INFO() \
+ do { \
+ builtin_rust_info ("target_family", "unix"); \
+ builtin_rust_info ("target_os", "solaris"); \
+ builtin_rust_info ("target_vendor", "sun"); \
+ builtin_rust_info ("target_env", ""); \
+ EXTRA_TARGET_RUST_OS_INFO(); \
+ } while (0)
+
#if DEFAULT_ARCH32_P
#define MULTILIB_DEFAULTS { "m32" }
#else
@@ -337,6 +337,14 @@ extern void vxworks_asm_out_destructor (rtx symbol, int priority);
} \
while (0)
+#define VXWORKS_TARGET_RUST_OS_INFO() \
+ do { \
+ builtin_rust_info ("target_family", "unix"); \
+ builtin_rust_info ("target_os", "vxworks"); \
+ builtin_rust_info ("target_vendor", "wrs"); \
+ builtin_rust_info ("target_env", "gnu"); \
+ } while (0)
+
/* For specific CPU macro definitions expected by the system headers,
different versions of VxWorks expect different forms of macros,
such as "_VX_CPU=..." on Vx7 and some variants of Vx6, or "CPU=..."
@@ -77,6 +77,15 @@ along with GCC; see the file COPYING3. If not see
} \
while (0)
+#define VXWORKS_TARGET_RUST_OS_INFO() \
+ do { \
+ builtin_rust_info ("target_family", "unix"); \
+ builtin_rust_info ("target_os", "vxworks"); \
+ builtin_rust_info ("target_vendor", "wrs"); \
+ builtin_rust_info ("target_env", "gnu"); \
+ /*is env correct? vxworks.h implies that this might not come with a gnu toolchain*/ \
+ } while (0)
+
/* Do VxWorks-specific parts of TARGET_OPTION_OVERRIDE. */
/* None of the VxWorks AE/653/MILS ports to date has native TLS support. */
@@ -644,6 +644,7 @@ ISLLIBS
GMPINC
GMPLIBS
target_cpu_default
+rust_target_objs
d_target_objs
fortran_target_objs
cxx_target_objs
@@ -652,6 +653,8 @@ use_gcc_stdint
xm_defines
xm_include_list
xm_file_list
+tm_rust_include_list
+tm_rust_file_list
tm_d_include_list
tm_d_file_list
tm_p_include_list
@@ -13010,6 +13013,7 @@ fi
tm_file="${tm_file} defaults.h"
tm_p_file="${tm_p_file} tm-preds.h"
tm_d_file="${tm_d_file} defaults.h"
+tm_rust_file="${tm_rust_file} defaults.h"
host_xm_file="auto-host.h ansidecl.h ${host_xm_file}"
build_xm_file="${build_auto} ansidecl.h ${build_xm_file}"
# We don't want ansidecl.h in target files, write code there in ISO/GNU C.
@@ -13418,6 +13422,21 @@ for f in $tm_d_file; do
esac
done
+tm_rust_file_list=
+tm_rust_include_list="options.h insn-constants.h"
+for f in $tm_rust_file; do
+ case $f in
+ defaults.h )
+ tm_rust_file_list="${tm_rust_file_list} \$(srcdir)/$f"
+ tm_rust_include_list="${tm_rust_include_list} $f"
+ ;;
+ * )
+ tm_rust_file_list="${tm_rust_file_list} \$(srcdir)/config/$f"
+ tm_rust_include_list="${tm_rust_include_list} config/$f"
+ ;;
+ esac
+done
+
xm_file_list=
xm_include_list=
for f in $xm_file; do
@@ -2114,6 +2114,7 @@ AC_SUBST(HAVE_AUTO_BUILD)
tm_file="${tm_file} defaults.h"
tm_p_file="${tm_p_file} tm-preds.h"
tm_d_file="${tm_d_file} defaults.h"
+tm_rust_file="${tm_rust_file} defaults.h"
host_xm_file="auto-host.h ansidecl.h ${host_xm_file}"
build_xm_file="${build_auto} ansidecl.h ${build_xm_file}"
# We don't want ansidecl.h in target files, write code there in ISO/GNU C.
@@ -2371,6 +2372,21 @@ for f in $tm_d_file; do
esac
done
+tm_rust_file_list=
+tm_rust_include_list="options.h insn-constants.h"
+for f in $tm_rust_file; do
+ case $f in
+ defaults.h )
+ tm_rust_file_list="${tm_rust_file_list} \$(srcdir)/$f"
+ tm_rust_include_list="${tm_rust_include_list} $f"
+ ;;
+ * )
+ tm_rust_file_list="${tm_rust_file_list} \$(srcdir)/config/$f"
+ tm_rust_include_list="${tm_rust_include_list} config/$f"
+ ;;
+ esac
+done
+
xm_file_list=
xm_include_list=
for f in $xm_file; do
@@ -7350,6 +7366,8 @@ AC_SUBST(tm_p_file_list)
AC_SUBST(tm_p_include_list)
AC_SUBST(tm_d_file_list)
AC_SUBST(tm_d_include_list)
+AC_SUBST(tm_rust_file_list)
+AC_SUBST(tm_rust_include_list)
AC_SUBST(xm_file_list)
AC_SUBST(xm_include_list)
AC_SUBST(xm_defines)
@@ -7358,6 +7376,7 @@ AC_SUBST(c_target_objs)
AC_SUBST(cxx_target_objs)
AC_SUBST(fortran_target_objs)
AC_SUBST(d_target_objs)
+AC_SUBST(rust_target_objs)
AC_SUBST(target_cpu_default)
AC_SUBST_FILE(language_hooks)
@@ -53,6 +53,7 @@ through the macros defined in the @file{.h} file.
* PCH Target:: Validity checking for precompiled headers.
* C++ ABI:: Controlling C++ ABI changes.
* D Language and ABI:: Controlling D ABI changes.
+* Rust Language and ABI:: Controlling Rust ABI changes.
* Named Address Spaces:: Adding support for named address spaces
* Misc:: Everything else.
@end menu
@@ -11065,6 +11066,22 @@ if they have external linkage. If this flag is false, then instantiated
decls will be emitted as weak symbols. The default is @code{false}.
@end deftypevr
+@node Rust Language and ABI
+@section Rust ABI parameters
+@cindex parameters, rust abi
+
+@deftypefn {Rust Target Hook} void TARGET_RUST_CPU_INFO (void)
+Declare all environmental CPU info and features relating to the target CPU
+using the function @code{rust_add_target_info}, which takes a string representing
+the feature key and a string representing the feature value. Configuration pairs
+predefined by this hook apply to all files that are being compiled.
+@end deftypefn
+
+@deftypefn {Rust Target Hook} void TARGET_RUST_OS_INFO (void)
+Similar to @code{TARGET_RUST_CPU_INFO}, but is used for configuration info
+relating to the target operating system.
+@end deftypefn
+
@node Named Address Spaces
@section Adding support for named address spaces
@cindex named address spaces
@@ -53,6 +53,7 @@ through the macros defined in the @file{.h} file.
* PCH Target:: Validity checking for precompiled headers.
* C++ ABI:: Controlling C++ ABI changes.
* D Language and ABI:: Controlling D ABI changes.
+* Rust Language and ABI:: Controlling Rust ABI changes.
* Named Address Spaces:: Adding support for named address spaces
* Misc:: Everything else.
@end menu
@@ -7327,6 +7328,14 @@ floating-point support; they are not included in this mechanism.
@hook TARGET_D_TEMPLATES_ALWAYS_COMDAT
+@node Rust Language and ABI
+@section Rust ABI parameters
+@cindex parameters, rust abi
+
+@hook TARGET_RUST_CPU_INFO
+
+@hook TARGET_RUST_OS_INFO
+
@node Named Address Spaces
@section Adding support for named address spaces
@cindex named address spaces
@@ -35,6 +35,7 @@ static struct hook_desc hook_array[] = {
#include "c-family/c-target.def"
#include "common/common-target.def"
#include "d/d-target.def"
+#include "rust/rust-target.def"
#undef DEFHOOK
};
new file mode 100644
@@ -0,0 +1,20 @@
+/* rust-target-def.h -- Default initializers for Rust target hooks.
+ Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+ This program 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.
+
+ This program 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 this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#include "rust/rust-target-hooks-def.h"
+#include "tree.h"
+#include "hooks.h"
new file mode 100644
@@ -0,0 +1,89 @@
+/* rust-target.def -- Target hook definitions for the Rust front end.
+ Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+ This program 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.
+
+ This program 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 this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+/* See target-hooks-macros.h for details of macros that should be
+ provided by the including file, and how to use them here. */
+
+#include "target-hooks-macros.h"
+
+#undef HOOK_TYPE
+#define HOOK_TYPE "Rust Target Hook"
+
+HOOK_VECTOR (TARGETRUSTM_INITIALIZER, gcc_targetrustm)
+
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_"
+
+/* Environmental CPU info and features (e.g. endianness, pointer size) relating to the target CPU. */
+DEFHOOK
+(rust_cpu_info,
+ "Declare all environmental CPU info and features relating to the target CPU\n\
+using the function @code{rust_add_target_info}, which takes a string representing\n\
+the feature key and a string representing the feature value. Configuration pairs\n\
+predefined by this hook apply to all files that are being compiled.",
+ void, (void),
+ hook_void_void)
+
+// TODO: remove: format of DEFHOOK is return type, (param types), default value for function that it translates to
+
+/* Environmental OS info relating to the target OS. */
+DEFHOOK
+(/*d_os_versions*/rust_os_info,
+ "Similar to @code{TARGET_RUST_CPU_INFO}, but is used for configuration info\n\
+relating to the target operating system.",
+ void, (void),
+ hook_void_void)
+
+/* The sizeof CRITICAL_SECTION or pthread_mutex_t. */
+/*DEFHOOK
+(d_critsec_size,
+ "Returns the size of the data structure used by the target operating system\n\
+for critical sections and monitors. For example, on Microsoft Windows this\n\
+would return the @code{sizeof(CRITICAL_SECTION)}, while other platforms that\n\
+implement pthreads would return @code{sizeof(pthread_mutex_t)}.",
+ unsigned, (void),
+ hook_uint_void_0)*/
+
+ /* TODO: add more if required. Possible ones include static C runtime, target_env
+ * or vendor (if not covered by OS), and flags from the driver that may or may not
+ * require a target hook (might instead require a different type of hook) like
+ * test, debug_assertions, and proc_macro. */
+
+ /* TODO: rustc target support by tier:
+ * Tier 1 (definitely work):
+ * - i686-pc-windows-gnu
+ * - i686-pc-windows-msvc
+ * - i686-unknown-linux-gnu
+ * - x86_64-apple-darwin
+ * - x86_64-pc-windows-gnu
+ * - x86_64-pc-windows-msvc
+ * - x86_64-unknown-linux-gnu
+ * - Basically, 32-bit and 64-bit x86 for windows (MinGW and MSVC), gnu/linux, and osx
+ * Other tiers have too much crap, but basic breakdown is:
+ * Tier 2:
+ * - archs: ARM64 (aarch64), ARMv7, ARMv6, asm.js, i586 (32-bit x86 without SSE), mips,
+ * mips64, powerpc, powerpc64, risc-v, s390x, sparc, webasm, netbsd, redox (does gcc have support?),
+ * cloudabi (never head of it; i imagine no gcc support)
+ * - oses: ios, fuchsia, android, windows (msvc and mingw), gnu/linux, freebsd, netbsd
+ * Tier 2.5:
+ * - powerpc SPE linux, various cloudabi stuff, sparc
+ * Tier 3:
+ * - more obscure stuff like UWP support, vxworks, openbsd, dragonflybsd, haiku, bitrig, windows xp,
+ * cuda, hexagon, and combinations of them and earlier stuff */
+
+/* Close the 'struct gcc_targetrustm' definition. */
+HOOK_VECTOR_END (C90_EMPTY_HACK)
new file mode 100644
@@ -0,0 +1,47 @@
+/* rust-target.h -- Data structure definitions for target-specific Rust
+ behavior. Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+ This program 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.
+
+ This program 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 this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_RUST_TARGET_H
+#define GCC_RUST_TARGET_H
+
+#include "target.h"
+#include "tm.h"
+#include "memmodel.h"
+#include "tm_p.h"
+
+// TODO: find out what this stuff actually does
+#define DEFHOOKPOD(NAME, DOC, TYPE, INIT) TYPE NAME;
+// #define DEFHOOK(NAME, DOC, TYPE, PARAMS, INIT) TYPE (*NAME) PARAMS;
+#define DEFHOOK_UNDOC DEFHOOK
+#define HOOKSTRUCT(FRAGMENT) FRAGMENT
+
+#include "rust-target.def"
+
+/* Each target can provide their own. */
+extern struct gcc_targetrustm targetrustm;
+/* Some kind of structure to store all rust hook macros (like the
+ * TARGET_RUST_CPU_INFO). This is required to store the function pointers for
+ * the target hooks so that the frontend can call them
+ * and it calls the correct target-specific function. */
+
+/* Used by target to add predefined version idenditiers. */
+// extern void d_add_builtin_version (const char *);
+/* Used by target to add target-related info. */
+extern void
+rust_add_target_info (const char *key, const char *value);
+
+#endif