From patchwork Wed Jul 27 13:40:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Li, Pan2 via Gcc-patches" X-Patchwork-Id: 56371 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 4D5E1385C302 for ; Wed, 27 Jul 2022 13:42:37 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4D5E1385C302 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1658929357; bh=2D/Hay8pJOcpDxfGYzdeghmiAQ6f0nQ2+qYlFcn7yvY=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=w73Kroh0diuiWGUE2nH7oeS333zl63ml4e3zIrnkfpL1Kwp8vGP8KOw0f3G/FGzue 4BiVqfM+DAIaW8m4vCXtYo/XUSR/3r4vhsD+NbPjykjR1ean/CXgxYsPElfxrcAqVU mwxvk7Un6wBu7hhCsHhUtBBndNXkndMJY+iMgQZk= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) by sourceware.org (Postfix) with ESMTPS id A43CA385AC2F for ; Wed, 27 Jul 2022 13:40:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org A43CA385AC2F Received: by mail-wr1-x42b.google.com with SMTP id d8so24154946wrp.6 for ; Wed, 27 Jul 2022 06:40:59 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:reply-to:mime-version:content-transfer-encoding; bh=2D/Hay8pJOcpDxfGYzdeghmiAQ6f0nQ2+qYlFcn7yvY=; b=rFHeIy+xfzLVfNN1lYHL+SpgwxfPTTeoivWZWLeFK4fM8hS4uT2s52rBKeqt6oT9kK Anb4lOru1VmzG3m7G4VT5elkYKWseIOG87yNWoZAtsjqbPU0z84yqG2QMv7XorMYFG60 meyk4kl0e18K7u8X0fPWZ/hznB2XuJLGdryqlqxQ1yQFjVqxMq6dRCuICHiOIytRMY6+ La0yNR9Wg+DsmV2TSJC0ka+MPirCpSFClz07F2hY84cHr57m8u6QnV0OEQprXzXh68hY TrJnkdnJvxN30Ig56bHcXiTzg/1gX79If/f6CyPA5NscNEdxGqZ03xx8d+ZxHO3n2QMj hooQ== X-Gm-Message-State: AJIora8BSefaGLSFWvWsv7zeeb+euaRYbR7r/TpR2GlCGoOKPOMWFOuS EZp60CuBeQbO2yBl9hdLIWUVxBWolcsKzA== X-Google-Smtp-Source: AGRyM1tEfJ1BYyEtHNPtFACIlIaTN7KktfFMUHUDplw6BFfQV4TrjkrTGSEuH56v0+A0XvsXYPo5Vg== X-Received: by 2002:adf:fb0e:0:b0:21a:34a2:5ca9 with SMTP id c14-20020adffb0e000000b0021a34a25ca9mr14531755wrr.472.1658929257036; Wed, 27 Jul 2022 06:40:57 -0700 (PDT) Received: from localhost.localdomain ([86.14.124.218]) by smtp.gmail.com with ESMTPSA id u18-20020a5d4352000000b0021e297d6850sm16846195wrr.110.2022.07.27.06.40.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 27 Jul 2022 06:40:55 -0700 (PDT) X-Google-Original-From: philip.herron@embecosm.com To: gcc-patches@gcc.gnu.org Subject: [PATCH Rust front-end v1 2/4] Add Rust lang TargetHooks for i386 and x86_64 Date: Wed, 27 Jul 2022 14:40:38 +0100 Message-Id: <20220727134040.843750-3-philip.herron@embecosm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220727134040.843750-1-philip.herron@embecosm.com> References: <20220727134040.843750-1-philip.herron@embecosm.com> MIME-Version: 1.0 X-Spam-Status: No, score=-11.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_NUMSUBJECT, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: "herron.philip--- via Gcc-patches" From: "Li, Pan2 via Gcc-patches" Reply-To: philip.herron@embecosm.com Cc: herron.philip@googlemail.com, SimplyTheOther , Philip Herron Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" From: Philip Herron This patch introduces a new set of interfaces to define the target info as expected by the rust front-end. It takes advantage of the information within gcc/config/target directories which gets called by the front-end to populate rust front-end datastructures by calling into: builtin_rust_info. This patch has been isolated to find if we are approaching this in an idiomatic way and is compilable without the rust-front-end code. We have received many patches here which gives us the target hook info for most platforms but getting the normal x86 done correctly will define if the other patches are done correctly. gcc/doc/ChangeLog: * tm.texi.in: specifiy hooks for rust target info * tm.texi: commit the generated documentation gcc/ChangeLog: * Makefile.in: add target to generate rust hooks * config.gcc: add rust target interface to be compiled for i386 * genhooks.cc: generate rust target hooks * configure: autoconf update * configure.ac: add tm_rust_file_list and tm_rust_include_list gcc/config/ChangeLog: * default-rust.cc: new target hooks initializer for rust * gnu.h: add new macro GNU_USER_TARGET_RUST_OS_INFO * dragonfly.h: define TARGET_RUST_OS_INFO * freebsd-spec.h: define FBSD_TARGET_RUST_OS_INFO * freebsd.h: define guard for TARGET_RUST_OS_INFO * fuchsia.h: define TARGET_RUST_OS_INFO * kfreebsd-gnu.h: define GNU_USER_TARGET_RUST_OS_INFO * kopensolaris-gnu.h: define GNU_USER_TARGET_RUST_OS_INFO * linux-android.h: define ANDROID_TARGET_RUST_OS_INFO * linux.h: define GNU_USER_TARGET_RUST_OS_INFO * netbsd.h: define NETBSD_TARGET_RUST_OS_INFO * openbsd.h: define OPENBSD_TARGET_RUST_OS_INFO * phoenix.h: define TARGET_RUST_OS_INFO * sol2.h: define TARGET_RUST_OS_INFO * vxworks.h: define VXWORKS_TARGET_RUST_OS_INFO * vxworksae.h: define VXWORKS_TARGET_RUST_OS_INFO gcc/config/i386/ChangeLog: * crtdll.h: define EXTRA_TARGET_RUST_OS_INFO * cygming.h: define TARGET_RUST_OS_INFO * cygwin.h: define EXTRA_TARGET_RUST_OS_INFO * darwin.h: define TARGET_RUST_OS_INFO * djgpp.h: likewise * gnu-user-common.h: define TARGET_RUST_OS_INFO * i386-protos.h: prototype for ix86_rust_target_cpu_info * i386-rust.cc: new file to generate the rust target host info * i386.h: define TARGET_RUST_CPU_INFO hook * linux-common.h: define hooks for target info * lynx.h: likewise * mingw32.h: likewise * netbsd-elf.h: likewise * netbsd64.h: likewise * nto.h: likewise * openbsdelf.h: likewise * rdos.h: likewise * rtemself.h: likewise * t-i386: add makefilke rule for i386-rust.cc * vxworks.h: define TARGET_RUST_OS_INFO gcc/rust/ChangeLog: * rust-target-def.h: define the headers to access the hooks * rust-target.def: define the hooks nessecary based on C90 * rust-target.h: define extern gcc_targetrustm Co-authored-by: SimplyTheOther --- gcc/Makefile.in | 35 ++- gcc/config.gcc | 17 + gcc/config/default-rust.cc | 26 ++ gcc/config/dragonfly.h | 12 + gcc/config/freebsd-spec.h | 9 + gcc/config/freebsd.h | 5 + gcc/config/fuchsia.h | 16 + gcc/config/gnu.h | 12 + gcc/config/i386/crtdll.h | 12 + gcc/config/i386/cygming.h | 5 + gcc/config/i386/cygwin.h | 10 + gcc/config/i386/darwin.h | 10 + gcc/config/i386/djgpp.h | 9 + gcc/config/i386/gnu-user-common.h | 5 + gcc/config/i386/i386-protos.h | 3 + gcc/config/i386/i386-rust.cc | 501 ++++++++++++++++++++++++++++++ gcc/config/i386/i386.h | 3 + gcc/config/i386/linux-common.h | 17 + gcc/config/i386/lynx.h | 9 + gcc/config/i386/mingw32.h | 8 + gcc/config/i386/netbsd-elf.h | 5 + gcc/config/i386/netbsd64.h | 5 + gcc/config/i386/nto.h | 12 + gcc/config/i386/openbsdelf.h | 5 + gcc/config/i386/rdos.h | 11 + gcc/config/i386/rtemself.h | 10 + gcc/config/i386/t-i386 | 4 + gcc/config/i386/vxworks.h | 5 + gcc/config/kfreebsd-gnu.h | 8 + gcc/config/kopensolaris-gnu.h | 12 + gcc/config/linux-android.h | 12 + gcc/config/linux.h | 14 + gcc/config/netbsd.h | 9 + gcc/config/openbsd.h | 8 + gcc/config/phoenix.h | 12 + gcc/config/sol2.h | 10 + gcc/config/vxworks.h | 8 + gcc/config/vxworksae.h | 9 + gcc/configure | 19 ++ gcc/configure.ac | 19 ++ gcc/doc/tm.texi | 17 + gcc/doc/tm.texi.in | 9 + gcc/genhooks.cc | 1 + gcc/rust/rust-target-def.h | 20 ++ gcc/rust/rust-target.def | 89 ++++++ gcc/rust/rust-target.h | 47 +++ 46 files changed, 1101 insertions(+), 3 deletions(-) create mode 100644 gcc/config/default-rust.cc create mode 100644 gcc/config/i386/i386-rust.cc create mode 100644 gcc/rust/rust-target-def.h create mode 100644 gcc/rust/rust-target.def create mode 100644 gcc/rust/rust-target.h diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 001506f8abf..e5a15b8b667 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -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 # diff --git a/gcc/config.gcc b/gcc/config.gcc index 4e3b15bb5e9..cdd4fb4392a 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -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 diff --git a/gcc/config/default-rust.cc b/gcc/config/default-rust.cc new file mode 100644 index 00000000000..a2754396e8c --- /dev/null +++ b/gcc/config/default-rust.cc @@ -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 +. */ + +#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; diff --git a/gcc/config/dragonfly.h b/gcc/config/dragonfly.h index 0235e62681d..15209f987ab 100644 --- a/gcc/config/dragonfly.h +++ b/gcc/config/dragonfly.h @@ -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}" diff --git a/gcc/config/freebsd-spec.h b/gcc/config/freebsd-spec.h index 594487829b5..d0c6ece315f 100644 --- a/gcc/config/freebsd-spec.h +++ b/gcc/config/freebsd-spec.h @@ -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. */ diff --git a/gcc/config/freebsd.h b/gcc/config/freebsd.h index d89ee7dfc97..5748645673c 100644 --- a/gcc/config/freebsd.h +++ b/gcc/config/freebsd.h @@ -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 diff --git a/gcc/config/fuchsia.h b/gcc/config/fuchsia.h index 0baf6f1f385..98dee35d823 100644 --- a/gcc/config/fuchsia.h +++ b/gcc/config/fuchsia.h @@ -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) diff --git a/gcc/config/gnu.h b/gcc/config/gnu.h index de2ead82be9..b0707148dd1 100644 --- a/gcc/config/gnu.h +++ b/gcc/config/gnu.h @@ -37,3 +37,15 @@ along with GCC. If not, see . 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) + diff --git a/gcc/config/i386/crtdll.h b/gcc/config/i386/crtdll.h index 75fede50fa0..5112e35389a 100644 --- a/gcc/config/i386/crtdll.h +++ b/gcc/config/i386/crtdll.h @@ -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" diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h index 45150458cc5..097592a4617 100644 --- a/gcc/config/i386/cygming.h +++ b/gcc/config/i386/cygming.h @@ -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 diff --git a/gcc/config/i386/cygwin.h b/gcc/config/i386/cygwin.h index d06eda369cf..7657c2b3649 100644 --- a/gcc/config/i386/cygwin.h +++ b/gcc/config/i386/cygwin.h @@ -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} \ diff --git a/gcc/config/i386/darwin.h b/gcc/config/i386/darwin.h index a55f6b2b874..3654a50d158 100644 --- a/gcc/config/i386/darwin.h +++ b/gcc/config/i386/darwin.h @@ -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") diff --git a/gcc/config/i386/djgpp.h b/gcc/config/i386/djgpp.h index 909821e953b..bc65b77470e 100644 --- a/gcc/config/i386/djgpp.h +++ b/gcc/config/i386/djgpp.h @@ -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}" diff --git a/gcc/config/i386/gnu-user-common.h b/gcc/config/i386/gnu-user-common.h index cab9be2bfb7..f95f8c047d6 100644 --- a/gcc/config/i386/gnu-user-common.h +++ b/gcc/config/i386/gnu-user-common.h @@ -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}" diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index cf847751ac5..da360591e8f 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -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); diff --git a/gcc/config/i386/i386-rust.cc b/gcc/config/i386/i386-rust.cc new file mode 100644 index 00000000000..1441a63f32c --- /dev/null +++ b/gcc/config/i386/i386-rust.cc @@ -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 +. */ + +#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");*/ +} diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index f16df633e84..93d5de5cd61 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -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 diff --git a/gcc/config/i386/linux-common.h b/gcc/config/i386/linux-common.h index efa7fb2072c..25aa5f368f2 100644 --- a/gcc/config/i386/linux-common.h +++ b/gcc/config/i386/linux-common.h @@ -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, \ diff --git a/gcc/config/i386/lynx.h b/gcc/config/i386/lynx.h index baa62c14986..ecc10264dde 100644 --- a/gcc/config/i386/lynx.h +++ b/gcc/config/i386/lynx.h @@ -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. */ diff --git a/gcc/config/i386/mingw32.h b/gcc/config/i386/mingw32.h index d3ca0cd0279..e5381de9f90 100644 --- a/gcc/config/i386/mingw32.h +++ b/gcc/config/i386/mingw32.h @@ -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" diff --git a/gcc/config/i386/netbsd-elf.h b/gcc/config/i386/netbsd-elf.h index b1d7d484ce7..aa60438ea77 100644 --- a/gcc/config/i386/netbsd-elf.h +++ b/gcc/config/i386/netbsd-elf.h @@ -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. */ diff --git a/gcc/config/i386/netbsd64.h b/gcc/config/i386/netbsd64.h index 656fd45af6f..7eba96b9ec0 100644 --- a/gcc/config/i386/netbsd64.h +++ b/gcc/config/i386/netbsd64.h @@ -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. */ diff --git a/gcc/config/i386/nto.h b/gcc/config/i386/nto.h index 5df300918d9..6b92d5924be 100644 --- a/gcc/config/i386/nto.h +++ b/gcc/config/i386/nto.h @@ -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" diff --git a/gcc/config/i386/openbsdelf.h b/gcc/config/i386/openbsdelf.h index 2176e79495c..060ae0f6afa 100644 --- a/gcc/config/i386/openbsdelf.h +++ b/gcc/config/i386/openbsdelf.h @@ -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]) diff --git a/gcc/config/i386/rdos.h b/gcc/config/i386/rdos.h index 9549977cbf8..c185d0efc2f 100644 --- a/gcc/config/i386/rdos.h +++ b/gcc/config/i386/rdos.h @@ -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) diff --git a/gcc/config/i386/rtemself.h b/gcc/config/i386/rtemself.h index a6035ffdad1..2f1cbdaf23f 100644 --- a/gcc/config/i386/rtemself.h +++ b/gcc/config/i386/rtemself.h @@ -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) diff --git a/gcc/config/i386/t-i386 b/gcc/config/i386/t-i386 index 4e2a0efc615..61ddfcab6ba 100644 --- a/gcc/config/i386/t-i386 +++ b/gcc/config/i386/t-i386 @@ -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) diff --git a/gcc/config/i386/vxworks.h b/gcc/config/i386/vxworks.h index 3b8eb6f3a59..af1f42abcb3 100644 --- a/gcc/config/i386/vxworks.h +++ b/gcc/config/i386/vxworks.h @@ -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 diff --git a/gcc/config/kfreebsd-gnu.h b/gcc/config/kfreebsd-gnu.h index f74a627bc43..d8892bf4bc5 100644 --- a/gcc/config/kfreebsd-gnu.h +++ b/gcc/config/kfreebsd-gnu.h @@ -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 diff --git a/gcc/config/kopensolaris-gnu.h b/gcc/config/kopensolaris-gnu.h index 8379f960b8b..bdeb29a635d 100644 --- a/gcc/config/kopensolaris-gnu.h +++ b/gcc/config/kopensolaris-gnu.h @@ -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" diff --git a/gcc/config/linux-android.h b/gcc/config/linux-android.h index cf340660adb..3d5548e3eb3 100644 --- a/gcc/config/linux-android.h +++ b/gcc/config/linux-android.h @@ -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 diff --git a/gcc/config/linux.h b/gcc/config/linux.h index 74f70793d90..13a714b9e81 100644 --- a/gcc/config/linux.h +++ b/gcc/config/linux.h @@ -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 diff --git a/gcc/config/netbsd.h b/gcc/config/netbsd.h index 9e46a0fff02..8e6bd0a2675 100644 --- a/gcc/config/netbsd.h +++ b/gcc/config/netbsd.h @@ -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} \ diff --git a/gcc/config/openbsd.h b/gcc/config/openbsd.h index 54be2225492..d91e1e9d8d7 100644 --- a/gcc/config/openbsd.h +++ b/gcc/config/openbsd.h @@ -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. diff --git a/gcc/config/phoenix.h b/gcc/config/phoenix.h index d9eef357370..e9dbbd0b2ae 100644 --- a/gcc/config/phoenix.h +++ b/gcc/config/phoenix.h @@ -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. */ diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h index e22c70c45ae..8cf2164c284 100644 --- a/gcc/config/sol2.h +++ b/gcc/config/sol2.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 diff --git a/gcc/config/vxworks.h b/gcc/config/vxworks.h index 6a5f2f8f2ec..4811b428455 100644 --- a/gcc/config/vxworks.h +++ b/gcc/config/vxworks.h @@ -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=..." diff --git a/gcc/config/vxworksae.h b/gcc/config/vxworksae.h index 0cc45467ab8..dc1dbe15ff1 100644 --- a/gcc/config/vxworksae.h +++ b/gcc/config/vxworksae.h @@ -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. */ diff --git a/gcc/configure b/gcc/configure index 62872d132ea..44cab9654d9 100755 --- a/gcc/configure +++ b/gcc/configure @@ -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 diff --git a/gcc/configure.ac b/gcc/configure.ac index 446747311a6..c54e9f40796 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -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) diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index b0ea39884aa..2ccda74c979 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -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 diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index f869ddd5e5b..c90c90f97a4 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -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 diff --git a/gcc/genhooks.cc b/gcc/genhooks.cc index 6bae85d7b8d..4e1338d21b7 100644 --- a/gcc/genhooks.cc +++ b/gcc/genhooks.cc @@ -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 }; diff --git a/gcc/rust/rust-target-def.h b/gcc/rust/rust-target-def.h new file mode 100644 index 00000000000..94c3f9f9a23 --- /dev/null +++ b/gcc/rust/rust-target-def.h @@ -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 + . */ + +#include "rust/rust-target-hooks-def.h" +#include "tree.h" +#include "hooks.h" diff --git a/gcc/rust/rust-target.def b/gcc/rust/rust-target.def new file mode 100644 index 00000000000..6d1ccaf8ad1 --- /dev/null +++ b/gcc/rust/rust-target.def @@ -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 + . */ + +/* 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) diff --git a/gcc/rust/rust-target.h b/gcc/rust/rust-target.h new file mode 100644 index 00000000000..743ac518ebb --- /dev/null +++ b/gcc/rust/rust-target.h @@ -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 + . */ + +#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