[Rust,front-end,v1,2/4] Add Rust lang TargetHooks for i386 and x86_64

Message ID 20220727134040.843750-3-philip.herron@embecosm.com
State New
Headers
Series [Rust,front-end,v1,1/4] Add skeleton Rust front-end folder |

Commit Message

Li, Pan2 via Gcc-patches July 27, 2022, 1:40 p.m. UTC
  From: Philip Herron <philip.herron@embecosm.com>

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 <simplytheother@gmail.com>
---
 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
  

Comments

Jakub Jelinek July 28, 2022, 9:57 a.m. UTC | #1
Note, the ChangeLog entry formatting is wrong and in various places
the code formatting as well.  In gcc/rust/ you can choose different
formatting if there are strong reasons for that, but at least it should be
consistent and ideally documented.

None of the gcc/doc, gcc/config, gcc/config/i386 directories have
ChangeLog files, so all this should go into gcc/ChangeLog
and filenames should be relative to the gcc/ directory, so
doc/tm.texi.in, config/default-rust.cc, config/i386/crtdll.h etc.

After : there should be a capital letter and the description what
changed should end with a dot.
Where possible, before : there should be space ( followed by what
has changed followed by ).
When some file is regenerated, just write Regenerated. or so.
When a new file is added, just write New. or New file.

On Wed, Jul 27, 2022 at 02:40:38PM +0100, herron.philip--- via Gcc-patches wrote:
> 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
> +/* 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");

The indentation should be just 2 columns rather than 4, and
{ doesn't go at the end of line.  Single statement if/else/etc.
bodies aren't wrapped with {}s.  There is space before (.
So
  if (TARGET_64BIT)
    {
      rust_add_target_info ("target_arch", "x86_64");
      ...
    }
  else
    rust_add_target_info ("target_arch", "x86");

> +  // 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 

Some lines are too long.

	Jakub
  
Thomas Schwinge July 28, 2022, 10:38 a.m. UTC | #2
Hi!

On 2022-07-27T14:40:38+0100, "herron.philip--- via Gcc-patches" <gcc-patches@gcc.gnu.org> wrote:
> 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.

I suppose the general approach may be fine, as is similarly implemented
by other languages' front ends in GCC.

> We have received many patches here which gives us the target hook info for
> most platforms

But this is all so much WIP and full of TODO notes, and has no test cases
at all!, that I still don't really see much value in keeping the current
implementations of 'TARGET_RUST_CPU_INFO', 'TARGET_RUST_OS_INFO', etc.
Applying "[HACK] Disable 'TARGET_RUST_CPU_INFO', 'TARGET_RUST_OS_INFO'"
that I've attached, we're not seeing any change in 'make check-rust'
results, for example.

In my opinion, the current implementation should be backed out from the
main development branch (would also reduce pain in merges from GCC
upstream, as mentioned before), and then be developed (quite possibly
based on the current implementation) individually for all GCC
configurations that we'd like to support (with 'sorry' otherwise), in a
coherent way, instead of trying to guess all possible target options as
done by the current implementation.  And, with all relevant test cases
getting added, of course.  That is, at this time, restrict outselves to
GCC configurations that we're actually supporting and testing.

Have we even figured out which of those target options are actually
mandated for a conforming Rust programming language implementation (that
is, users would potentially rely on these)?

As far as I can tell, 'rustc' defines target options here:
<https://github.com/rust-lang/rust/tree/master/compiler/rustc_target/src/spec>,
and you may use 'rustc --print=cfg' to dump for the current
configuration?

> but getting the normal x86 done correctly will define if
> the other patches are done correctly.

Yes -- but I'm not sure this is it really, in its current WIPy,
un-tested, un-verified form:

> gcc/config/ChangeLog:

>         * 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


Grüße
 Thomas


-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955
  
Philip Herron July 28, 2022, 10:51 a.m. UTC | #3
Hi Thomas,

I think you are right here. There are parts in
libstd/liballoc/libpanic which start to look for what CPU features are
available iirc. Maintaining our patches here has been becoming
difficult as of late, especially when it comes to libcore, which just
cares about target pointer width and endienness which is more
generally available as macros.

It seems more clear now that maybe for this v1 set of patches,
possibly this stuff doesn't really matter right now until we compile
libstd which seems like a much better approach in order to review the
front-end code. I think i will apply your patch and revert these
changes for now since we have the git history for them we can look at
this more closely when we need it.

Thanks

--Phil


On Thu, 28 Jul 2022 at 11:38, Thomas Schwinge <thomas@codesourcery.com> wrote:
>
> Hi!
>
> On 2022-07-27T14:40:38+0100, "herron.philip--- via Gcc-patches" <gcc-patches@gcc.gnu.org> wrote:
> > 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.
>
> I suppose the general approach may be fine, as is similarly implemented
> by other languages' front ends in GCC.
>
> > We have received many patches here which gives us the target hook info for
> > most platforms
>
> But this is all so much WIP and full of TODO notes, and has no test cases
> at all!, that I still don't really see much value in keeping the current
> implementations of 'TARGET_RUST_CPU_INFO', 'TARGET_RUST_OS_INFO', etc.
> Applying "[HACK] Disable 'TARGET_RUST_CPU_INFO', 'TARGET_RUST_OS_INFO'"
> that I've attached, we're not seeing any change in 'make check-rust'
> results, for example.
>
> In my opinion, the current implementation should be backed out from the
> main development branch (would also reduce pain in merges from GCC
> upstream, as mentioned before), and then be developed (quite possibly
> based on the current implementation) individually for all GCC
> configurations that we'd like to support (with 'sorry' otherwise), in a
> coherent way, instead of trying to guess all possible target options as
> done by the current implementation.  And, with all relevant test cases
> getting added, of course.  That is, at this time, restrict outselves to
> GCC configurations that we're actually supporting and testing.
>
> Have we even figured out which of those target options are actually
> mandated for a conforming Rust programming language implementation (that
> is, users would potentially rely on these)?
>
> As far as I can tell, 'rustc' defines target options here:
> <https://github.com/rust-lang/rust/tree/master/compiler/rustc_target/src/spec>,
> and you may use 'rustc --print=cfg' to dump for the current
> configuration?
>
> > but getting the normal x86 done correctly will define if
> > the other patches are done correctly.
>
> Yes -- but I'm not sure this is it really, in its current WIPy,
> un-tested, un-verified form:
>
> > gcc/config/ChangeLog:
>
> >         * 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
>
>
> Grüße
>  Thomas
>
>
> -----------------
> Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955
  
Thomas Schwinge July 28, 2022, 11:08 a.m. UTC | #4
Hi Phil!

On 2022-07-28T11:51:37+0100, Philip Herron <philip.herron@embecosm.com> wrote:
> I think you are right here. There are parts in
> libstd/liballoc/libpanic which start to look for what CPU features are
> available iirc.

Aha, good.  That -- once we get there ;-) -- shall then guide us on the
target options we implement, in addition to what we find generally
necessary for a conforming Rust programming language implementation (as
I'd mentioned).

> libcore [...] just
> cares about target pointer width and endienness which is more
> generally available as macros.

Right, and these are already implemented in
'gcc/rust/rust-session-manager.cc:Session::init'.  (..., but also should
get some test cases added; I'll have a look at some point.)

> It seems more clear now that maybe for this v1 set of patches,
> possibly this stuff doesn't really matter right now until we compile
> libstd which seems like a much better approach in order to review the
> front-end code. I think i will apply your patch and revert these
> changes for now since we have the git history for them we can look at
> this more closely when we need it.

Unless this issue is time-critical, let me offer that instead of my
"[HACK] Disable 'TARGET_RUST_CPU_INFO', 'TARGET_RUST_OS_INFO'",
I'll cook up a proper patch, removing the implementations of
'TARGET_RUST_CPU_INFO', 'TARGET_RUST_OS_INFO', etc., but keeping the
general infrastructure in place (if I find that makes sense)?


Grüße
 Thomas


> On Thu, 28 Jul 2022 at 11:38, Thomas Schwinge <thomas@codesourcery.com> wrote:
>>
>> Hi!
>>
>> On 2022-07-27T14:40:38+0100, "herron.philip--- via Gcc-patches" <gcc-patches@gcc.gnu.org> wrote:
>> > 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.
>>
>> I suppose the general approach may be fine, as is similarly implemented
>> by other languages' front ends in GCC.
>>
>> > We have received many patches here which gives us the target hook info for
>> > most platforms
>>
>> But this is all so much WIP and full of TODO notes, and has no test cases
>> at all!, that I still don't really see much value in keeping the current
>> implementations of 'TARGET_RUST_CPU_INFO', 'TARGET_RUST_OS_INFO', etc.
>> Applying "[HACK] Disable 'TARGET_RUST_CPU_INFO', 'TARGET_RUST_OS_INFO'"
>> that I've attached, we're not seeing any change in 'make check-rust'
>> results, for example.
>>
>> In my opinion, the current implementation should be backed out from the
>> main development branch (would also reduce pain in merges from GCC
>> upstream, as mentioned before), and then be developed (quite possibly
>> based on the current implementation) individually for all GCC
>> configurations that we'd like to support (with 'sorry' otherwise), in a
>> coherent way, instead of trying to guess all possible target options as
>> done by the current implementation.  And, with all relevant test cases
>> getting added, of course.  That is, at this time, restrict outselves to
>> GCC configurations that we're actually supporting and testing.
>>
>> Have we even figured out which of those target options are actually
>> mandated for a conforming Rust programming language implementation (that
>> is, users would potentially rely on these)?
>>
>> As far as I can tell, 'rustc' defines target options here:
>> <https://github.com/rust-lang/rust/tree/master/compiler/rustc_target/src/spec>,
>> and you may use 'rustc --print=cfg' to dump for the current
>> configuration?
>>
>> > but getting the normal x86 done correctly will define if
>> > the other patches are done correctly.
>>
>> Yes -- but I'm not sure this is it really, in its current WIPy,
>> un-tested, un-verified form:
>>
>> > gcc/config/ChangeLog:
>>
>> >         * 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
>>
>>
>> Grüße
>>  Thomas
>>
>>
>> -----------------
>> Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955
-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955
  
Philip Herron July 28, 2022, 11:41 a.m. UTC | #5
That would be brilliant if you could do that! I can spend my time
focused on splitting the front-end into patches. In the meantime,
while you work on that, I will use your patch here to disable the
target hook stuff so that the patches are buildable.

--Phil

On Thu, 28 Jul 2022 at 12:09, Thomas Schwinge <thomas@codesourcery.com> wrote:
>
> Hi Phil!
>
> On 2022-07-28T11:51:37+0100, Philip Herron <philip.herron@embecosm.com> wrote:
> > I think you are right here. There are parts in
> > libstd/liballoc/libpanic which start to look for what CPU features are
> > available iirc.
>
> Aha, good.  That -- once we get there ;-) -- shall then guide us on the
> target options we implement, in addition to what we find generally
> necessary for a conforming Rust programming language implementation (as
> I'd mentioned).
>
> > libcore [...] just
> > cares about target pointer width and endienness which is more
> > generally available as macros.
>
> Right, and these are already implemented in
> 'gcc/rust/rust-session-manager.cc:Session::init'.  (..., but also should
> get some test cases added; I'll have a look at some point.)
>
> > It seems more clear now that maybe for this v1 set of patches,
> > possibly this stuff doesn't really matter right now until we compile
> > libstd which seems like a much better approach in order to review the
> > front-end code. I think i will apply your patch and revert these
> > changes for now since we have the git history for them we can look at
> > this more closely when we need it.
>
> Unless this issue is time-critical, let me offer that instead of my
> "[HACK] Disable 'TARGET_RUST_CPU_INFO', 'TARGET_RUST_OS_INFO'",
> I'll cook up a proper patch, removing the implementations of
> 'TARGET_RUST_CPU_INFO', 'TARGET_RUST_OS_INFO', etc., but keeping the
> general infrastructure in place (if I find that makes sense)?
>
>
> Grüße
>  Thomas
>
>
> > On Thu, 28 Jul 2022 at 11:38, Thomas Schwinge <thomas@codesourcery.com> wrote:
> >>
> >> Hi!
> >>
> >> On 2022-07-27T14:40:38+0100, "herron.philip--- via Gcc-patches" <gcc-patches@gcc.gnu.org> wrote:
> >> > 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.
> >>
> >> I suppose the general approach may be fine, as is similarly implemented
> >> by other languages' front ends in GCC.
> >>
> >> > We have received many patches here which gives us the target hook info for
> >> > most platforms
> >>
> >> But this is all so much WIP and full of TODO notes, and has no test cases
> >> at all!, that I still don't really see much value in keeping the current
> >> implementations of 'TARGET_RUST_CPU_INFO', 'TARGET_RUST_OS_INFO', etc.
> >> Applying "[HACK] Disable 'TARGET_RUST_CPU_INFO', 'TARGET_RUST_OS_INFO'"
> >> that I've attached, we're not seeing any change in 'make check-rust'
> >> results, for example.
> >>
> >> In my opinion, the current implementation should be backed out from the
> >> main development branch (would also reduce pain in merges from GCC
> >> upstream, as mentioned before), and then be developed (quite possibly
> >> based on the current implementation) individually for all GCC
> >> configurations that we'd like to support (with 'sorry' otherwise), in a
> >> coherent way, instead of trying to guess all possible target options as
> >> done by the current implementation.  And, with all relevant test cases
> >> getting added, of course.  That is, at this time, restrict outselves to
> >> GCC configurations that we're actually supporting and testing.
> >>
> >> Have we even figured out which of those target options are actually
> >> mandated for a conforming Rust programming language implementation (that
> >> is, users would potentially rely on these)?
> >>
> >> As far as I can tell, 'rustc' defines target options here:
> >> <https://github.com/rust-lang/rust/tree/master/compiler/rustc_target/src/spec>,
> >> and you may use 'rustc --print=cfg' to dump for the current
> >> configuration?
> >>
> >> > but getting the normal x86 done correctly will define if
> >> > the other patches are done correctly.
> >>
> >> Yes -- but I'm not sure this is it really, in its current WIPy,
> >> un-tested, un-verified form:
> >>
> >> > gcc/config/ChangeLog:
> >>
> >> >         * 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
> >>
> >>
> >> Grüße
> >>  Thomas
> >>
> >>
> >> -----------------
> >> Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955
> -----------------
> Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955
  

Patch

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
+<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;
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 <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)
+
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
+<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");*/
+}
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
+   <http://www.gnu.org/licenses/>.  */
+
+#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
+   <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)
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
+   <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